sipaccount.cpp 38.3 KB
Newer Older
yanmorin's avatar
 
yanmorin committed
1
/*
2
 *  Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*
*  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*  Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21
22
23
24
25
26
27
28
29
30
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
31
*/
32

33
34
35
36
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

yanmorin's avatar
 
yanmorin committed
37
#include "sipaccount.h"
38
#include "sipvoiplink.h"
39
40
#include "config/yamlnode.h"
#include "config/yamlemitter.h"
41
#include "logger.h"
yanmorin's avatar
   
yanmorin committed
42
#include "manager.h"
43
#include <pwd.h>
44
#include <sstream>
45

46
const char * const SIPAccount::IP2IP_PROFILE = "IP2IP";
47
48
const char * const SIPAccount::OVERRTP_STR = "overrtp";
const char * const SIPAccount::SIPINFO_STR = "sipinfo";
49

50
51
52
53
namespace {
    const int MIN_REGISTRATION_TIME = 600;
}

54
55
56
SIPAccount::SIPAccount(const std::string& accountID)
    : Account(accountID, "SIP")
    , transport_(NULL)
57
    , credentials_()
58
59
    , regc_(NULL)
    , bRegister_(false)
60
    , registrationExpire_(MIN_REGISTRATION_TIME)
61
62
    , interface_("default")
    , publishedSameasLocal_(true)
63
    , publishedIpAddress_()
64
65
    , localPort_(DEFAULT_SIP_PORT)
    , publishedPort_(DEFAULT_SIP_PORT)
66
    , serviceRoute_()
67
68
    , tlsListenerPort_(DEFAULT_SIP_TLS_PORT)
    , transportType_(PJSIP_TRANSPORT_UNSPECIFIED)
69
    , cred_()
70
    , tlsSetting_()
71
    , contactHeader_()
72
    , contactUpdateEnabled_(false)
73
    , stunServerName_()
74
    , stunPort_(PJ_STUN_PORT)
75
    , dtmfType_(OVERRTP_STR)
76
    , tlsEnable_("false")
77
78
79
80
    , tlsCaListFile_()
    , tlsCertificateFile_()
    , tlsPrivateKeyFile_()
    , tlsPassword_()
81
    , tlsMethod_("TLSv1")
82
83
    , tlsCiphers_()
    , tlsServerName_(0, 0)
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    , tlsVerifyServer_(true)
    , tlsVerifyClient_(true)
    , tlsRequireClientCertificate_(true)
    , tlsNegotiationTimeoutSec_("2")
    , tlsNegotiationTimeoutMsec_("0")
    , stunServer_("stun.sflphone.org")
    , stunEnabled_(false)
    , srtpEnabled_(false)
    , srtpKeyExchange_("sdes")
    , srtpFallback_(false)
    , zrtpDisplaySas_(true)
    , zrtpDisplaySasOnce_(false)
    , zrtpHelloHash_(true)
    , zrtpNotSuppWarning_(true)
98
    , registrationStateDetailed_()
99
    , keepAliveTimer_()
100
    , link_(SIPVoIPLink::instance())
101
    , receivedParameter_()
102
{}
yanmorin's avatar
 
yanmorin committed
103

104
void SIPAccount::serialize(Conf::YamlEmitter &emitter)
Julien Bonjean's avatar
Julien Bonjean committed
105
{
106
107
108
109
110
111
112
113
114
115
116
117
    using namespace Conf;
    MappingNode accountmap(NULL);
    MappingNode srtpmap(NULL);
    MappingNode zrtpmap(NULL);
    MappingNode tlsmap(NULL);

    ScalarNode id(Account::accountID_);
    ScalarNode username(Account::username_);
    ScalarNode alias(Account::alias_);
    ScalarNode hostname(Account::hostname_);
    ScalarNode enable(enabled_);
    ScalarNode type(Account::type_);
118
119
    std::stringstream registrationExpireStr;
    registrationExpireStr << registrationExpire_;
120
    ScalarNode expire(registrationExpireStr.str());
121
    ScalarNode interface(interface_);
Julien Bonjean's avatar
Julien Bonjean committed
122
    std::stringstream portstr;
123
    portstr << localPort_;
124
125
    ScalarNode port(portstr.str());
    ScalarNode serviceRoute(serviceRoute_);
126
    ScalarNode contactUpdateEnabled(contactUpdateEnabled_);
Julien Bonjean's avatar
Julien Bonjean committed
127

128
129
    ScalarNode mailbox(mailBox_);
    ScalarNode publishAddr(publishedIpAddress_);
Julien Bonjean's avatar
Julien Bonjean committed
130
    std::stringstream publicportstr;
131
    publicportstr << publishedPort_;
132
133
134
135
136
137
138
139
140
    ScalarNode publishPort(publicportstr.str());
    ScalarNode sameasLocal(publishedSameasLocal_);
    ScalarNode codecs(codecStr_);
    ScalarNode ringtonePath(ringtonePath_);
    ScalarNode ringtoneEnabled(ringtoneEnabled_);
    ScalarNode stunServer(stunServer_);
    ScalarNode stunEnabled(stunEnabled_);
    ScalarNode displayName(displayName_);
    ScalarNode dtmfType(dtmfType_);
Julien Bonjean's avatar
Julien Bonjean committed
141
142
143

    std::stringstream countstr;
    countstr << 0;
144
    ScalarNode count(countstr.str());
Julien Bonjean's avatar
Julien Bonjean committed
145

146
147
148
    ScalarNode srtpenabled(srtpEnabled_);
    ScalarNode keyExchange(srtpKeyExchange_);
    ScalarNode rtpFallback(srtpFallback_);
Julien Bonjean's avatar
Julien Bonjean committed
149

150
151
152
153
    ScalarNode displaySas(zrtpDisplaySas_);
    ScalarNode displaySasOnce(zrtpDisplaySasOnce_);
    ScalarNode helloHashEnabled(zrtpHelloHash_);
    ScalarNode notSuppWarning(zrtpNotSuppWarning_);
Julien Bonjean's avatar
Julien Bonjean committed
154

Rafaël Carré's avatar
Rafaël Carré committed
155
    portstr.str("");
156
    portstr << tlsListenerPort_;
157
158
159
160
161
162
163
164
165
166
167
168
169
    ScalarNode tlsport(portstr.str());
    ScalarNode certificate(tlsCertificateFile_);
    ScalarNode calist(tlsCaListFile_);
    ScalarNode ciphers(tlsCiphers_);
    ScalarNode tlsenabled(tlsEnable_);
    ScalarNode tlsmethod(tlsMethod_);
    ScalarNode timeout(tlsNegotiationTimeoutSec_);
    ScalarNode tlspassword(tlsPassword_);
    ScalarNode privatekey(tlsPrivateKeyFile_);
    ScalarNode requirecertif(tlsRequireClientCertificate_);
    ScalarNode server(tlsServerName_);
    ScalarNode verifyclient(tlsVerifyServer_);
    ScalarNode verifyserver(tlsVerifyClient_);
170

171
172
173
174
175
176
177
    accountmap.setKeyValue(ALIAS_KEY, &alias);
    accountmap.setKeyValue(TYPE_KEY, &type);
    accountmap.setKeyValue(ID_KEY, &id);
    accountmap.setKeyValue(USERNAME_KEY, &username);
    accountmap.setKeyValue(HOSTNAME_KEY, &hostname);
    accountmap.setKeyValue(ACCOUNT_ENABLE_KEY, &enable);
    accountmap.setKeyValue(MAILBOX_KEY, &mailbox);
178
    accountmap.setKeyValue(Preferences::REGISTRATION_EXPIRE_KEY, &expire);
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    accountmap.setKeyValue(INTERFACE_KEY, &interface);
    accountmap.setKeyValue(PORT_KEY, &port);
    accountmap.setKeyValue(STUN_SERVER_KEY, &stunServer);
    accountmap.setKeyValue(STUN_ENABLED_KEY, &stunEnabled);
    accountmap.setKeyValue(PUBLISH_ADDR_KEY, &publishAddr);
    accountmap.setKeyValue(PUBLISH_PORT_KEY, &publishPort);
    accountmap.setKeyValue(SAME_AS_LOCAL_KEY, &sameasLocal);
    accountmap.setKeyValue(SERVICE_ROUTE_KEY, &serviceRoute);
    accountmap.setKeyValue(UPDATE_CONTACT_HEADER_KEY, &contactUpdateEnabled);
    accountmap.setKeyValue(DTMF_TYPE_KEY, &dtmfType);
    accountmap.setKeyValue(DISPLAY_NAME_KEY, &displayName);
    accountmap.setKeyValue(CODECS_KEY, &codecs);
    accountmap.setKeyValue(RINGTONE_PATH_KEY, &ringtonePath);
    accountmap.setKeyValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled);

    accountmap.setKeyValue(SRTP_KEY, &srtpmap);
    srtpmap.setKeyValue(SRTP_ENABLE_KEY, &srtpenabled);
    srtpmap.setKeyValue(KEY_EXCHANGE_KEY, &keyExchange);
    srtpmap.setKeyValue(RTP_FALLBACK_KEY, &rtpFallback);

    accountmap.setKeyValue(ZRTP_KEY, &zrtpmap);
    zrtpmap.setKeyValue(DISPLAY_SAS_KEY, &displaySas);
    zrtpmap.setKeyValue(DISPLAY_SAS_ONCE_KEY, &displaySasOnce);
    zrtpmap.setKeyValue(HELLO_HASH_ENABLED_KEY, &helloHashEnabled);
    zrtpmap.setKeyValue(NOT_SUPP_WARNING_KEY, &notSuppWarning);
204

205
    SequenceNode credentialseq(NULL);
206
    accountmap.setKeyValue(CRED_KEY, &credentialseq);
207
208
209
210
211

    std::vector<std::map<std::string, std::string> >::const_iterator it;

    for (it = credentials_.begin(); it != credentials_.end(); ++it) {
        std::map<std::string, std::string> cred = *it;
212
        MappingNode *map = new MappingNode(NULL);
213
214
215
        map->setKeyValue(CONFIG_ACCOUNT_USERNAME, new ScalarNode(cred[CONFIG_ACCOUNT_USERNAME]));
        map->setKeyValue(CONFIG_ACCOUNT_PASSWORD, new ScalarNode(cred[CONFIG_ACCOUNT_PASSWORD]));
        map->setKeyValue(CONFIG_ACCOUNT_REALM, new ScalarNode(cred[CONFIG_ACCOUNT_REALM]));
216
217
218
        credentialseq.addNode(map);
    }

219
220
221
222
223
224
225
226
227
228
229
230
231
232
    accountmap.setKeyValue(TLS_KEY, &tlsmap);
    tlsmap.setKeyValue(TLS_PORT_KEY, &tlsport);
    tlsmap.setKeyValue(CERTIFICATE_KEY, &certificate);
    tlsmap.setKeyValue(CALIST_KEY, &calist);
    tlsmap.setKeyValue(CIPHERS_KEY, &ciphers);
    tlsmap.setKeyValue(TLS_ENABLE_KEY, &tlsenabled);
    tlsmap.setKeyValue(METHOD_KEY, &tlsmethod);
    tlsmap.setKeyValue(TIMEOUT_KEY, &timeout);
    tlsmap.setKeyValue(TLS_PASSWORD_KEY, &tlspassword);
    tlsmap.setKeyValue(PRIVATE_KEY_KEY, &privatekey);
    tlsmap.setKeyValue(REQUIRE_CERTIF_KEY, &requirecertif);
    tlsmap.setKeyValue(SERVER_KEY, &server);
    tlsmap.setKeyValue(VERIFY_CLIENT_KEY, &verifyclient);
    tlsmap.setKeyValue(VERIFY_SERVER_KEY, &verifyserver);
Julien Bonjean's avatar
Julien Bonjean committed
233
234

    try {
235
        emitter.serializeAccount(&accountmap);
236
    } catch (const YamlEmitterException &e) {
237
        ERROR("ConfigTree: %s", e.what());
Julien Bonjean's avatar
Julien Bonjean committed
238
    }
239

240
241
    Sequence *seq = credentialseq.getSequence();
    Sequence::iterator seqit;
242

243
    for (seqit = seq->begin(); seqit != seq->end(); ++seqit) {
244
        MappingNode *node = static_cast<MappingNode*>(*seqit);
245
246
247
        delete node->getValue(CONFIG_ACCOUNT_USERNAME);
        delete node->getValue(CONFIG_ACCOUNT_PASSWORD);
        delete node->getValue(CONFIG_ACCOUNT_REALM);
248
        delete node;
249
    }
250
}
251

252
void SIPAccount::unserialize(const Conf::MappingNode &map)
253
{
254
    using namespace Conf;
Julien Bonjean's avatar
Julien Bonjean committed
255

256
257
258
259
260
261
262
    map.getValue(ALIAS_KEY, &alias_);
    map.getValue(TYPE_KEY, &type_);
    map.getValue(USERNAME_KEY, &username_);
    map.getValue(HOSTNAME_KEY, &hostname_);
    map.getValue(ACCOUNT_ENABLE_KEY, &enabled_);
    map.getValue(MAILBOX_KEY, &mailBox_);
    map.getValue(CODECS_KEY, &codecStr_);
263
    // Update codec list which one is used for SDP offer
264
    setActiveCodecs(ManagerImpl::unserialize(codecStr_));
265

266
267
268
269
    map.getValue(RINGTONE_PATH_KEY, &ringtonePath_);
    map.getValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled_);
    map.getValue(Preferences::REGISTRATION_EXPIRE_KEY, &registrationExpire_);
    map.getValue(INTERFACE_KEY, &interface_);
270
    int port = DEFAULT_SIP_PORT;
271
    map.getValue(PORT_KEY, &port);
272
    localPort_ = port;
273
274
    map.getValue(PUBLISH_ADDR_KEY, &publishedIpAddress_);
    map.getValue(PUBLISH_PORT_KEY, &port);
275
    publishedPort_ = port;
276
    map.getValue(SAME_AS_LOCAL_KEY, &publishedSameasLocal_);
277
278

    std::string dtmfType;
279
    map.getValue(DTMF_TYPE_KEY, &dtmfType);
280
    dtmfType_ = dtmfType;
281

282
283
    map.getValue(SERVICE_ROUTE_KEY, &serviceRoute_);
    map.getValue(UPDATE_CONTACT_HEADER_KEY, &contactUpdateEnabled_);
284

Julien Bonjean's avatar
Julien Bonjean committed
285
    // stun enabled
286
287
    map.getValue(STUN_ENABLED_KEY, &stunEnabled_);
    map.getValue(STUN_SERVER_KEY, &stunServer_);
Julien Bonjean's avatar
Julien Bonjean committed
288

289
    // Init stun server name with default server name
290
    stunServerName_ = pj_str((char*) stunServer_.data());
Julien Bonjean's avatar
Julien Bonjean committed
291

292
    map.getValue(DISPLAY_NAME_KEY, &displayName_);
293

294
295
    std::vector<std::map<std::string, std::string> > creds;

296
    YamlNode *credNode = map.getValue(CRED_KEY);
297
298
299
300
301

    /* We check if the credential key is a sequence
     * because it was a mapping in a previous version of
     * the configuration file.
     */
302
    if (credNode && credNode->getType() == SEQUENCE) {
303
        SequenceNode *credSeq = static_cast<SequenceNode *>(credNode);
304
305
        Sequence::iterator it;
        Sequence *seq = credSeq->getSequence();
306
307

        for (it = seq->begin(); it != seq->end(); ++it) {
308
            MappingNode *cred = static_cast<MappingNode *>(*it);
309
310
311
            std::string user;
            std::string pass;
            std::string realm;
312
313
314
            cred->getValue(CONFIG_ACCOUNT_USERNAME, &user);
            cred->getValue(CONFIG_ACCOUNT_PASSWORD, &pass);
            cred->getValue(CONFIG_ACCOUNT_REALM, &realm);
315
            std::map<std::string, std::string> credentialMap;
316
317
318
            credentialMap[CONFIG_ACCOUNT_USERNAME] = user;
            credentialMap[CONFIG_ACCOUNT_PASSWORD] = pass;
            credentialMap[CONFIG_ACCOUNT_REALM] = realm;
319
320
321
322
            creds.push_back(credentialMap);
        }
    }

323
    if (creds.empty()) {
324
325
326
        // migration from old file format
        std::map<std::string, std::string> credmap;
        std::string password;
327
        map.getValue(PASSWORD_KEY, &password);
328

329
330
331
        credmap[CONFIG_ACCOUNT_USERNAME] = username_;
        credmap[CONFIG_ACCOUNT_PASSWORD] = password;
        credmap[CONFIG_ACCOUNT_REALM] = "*";
332
        creds.push_back(credmap);
333
    }
334
335

    setCredentials(creds);
Julien Bonjean's avatar
Julien Bonjean committed
336
337

    // get srtp submap
338
    MappingNode *srtpMap = static_cast<MappingNode *>(map.getValue(SRTP_KEY));
339

340
    if (srtpMap) {
341
342
343
        srtpMap->getValue(SRTP_ENABLE_KEY, &srtpEnabled_);
        srtpMap->getValue(KEY_EXCHANGE_KEY, &srtpKeyExchange_);
        srtpMap->getValue(RTP_FALLBACK_KEY, &srtpFallback_);
344
    }
Julien Bonjean's avatar
Julien Bonjean committed
345
346

    // get zrtp submap
347
    MappingNode *zrtpMap = static_cast<MappingNode *>(map.getValue(ZRTP_KEY));
348

349
    if (zrtpMap) {
350
351
352
353
        zrtpMap->getValue(DISPLAY_SAS_KEY, &zrtpDisplaySas_);
        zrtpMap->getValue(DISPLAY_SAS_ONCE_KEY, &zrtpDisplaySasOnce_);
        zrtpMap->getValue(HELLO_HASH_ENABLED_KEY, &zrtpHelloHash_);
        zrtpMap->getValue(NOT_SUPP_WARNING_KEY, &zrtpNotSuppWarning_);
354
    }
Julien Bonjean's avatar
Julien Bonjean committed
355
356

    // get tls submap
357
    MappingNode *tlsMap = static_cast<MappingNode *>(map.getValue(TLS_KEY));
358

359
    if (tlsMap) {
360
        tlsMap->getValue(TLS_ENABLE_KEY, &tlsEnable_);
361
362
363
        std::string tlsPort;
        tlsMap->getValue(TLS_PORT_KEY, &tlsPort);
        tlsListenerPort_ = atoi(tlsPort.c_str());
364
365
366
367
368
369
370
371
372
373
        tlsMap->getValue(CERTIFICATE_KEY, &tlsCertificateFile_);
        tlsMap->getValue(CALIST_KEY, &tlsCaListFile_);
        tlsMap->getValue(CIPHERS_KEY, &tlsCiphers_);
        tlsMap->getValue(METHOD_KEY, &tlsMethod_);
        tlsMap->getValue(TLS_PASSWORD_KEY, &tlsPassword_);
        tlsMap->getValue(PRIVATE_KEY_KEY, &tlsPrivateKeyFile_);
        tlsMap->getValue(REQUIRE_CERTIF_KEY, &tlsRequireClientCertificate_);
        tlsMap->getValue(SERVER_KEY, &tlsServerName_);
        tlsMap->getValue(VERIFY_CLIENT_KEY, &tlsVerifyServer_);
        tlsMap->getValue(VERIFY_SERVER_KEY, &tlsVerifyClient_);
374
        // FIXME
375
376
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutSec_);
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutMsec_);
377
    }
378
379
}

380

381
void SIPAccount::setAccountDetails(std::map<std::string, std::string> details)
382
{
Julien Bonjean's avatar
Julien Bonjean committed
383
    // Account setting common to SIP and IAX
384
385
    alias_ = details[CONFIG_ACCOUNT_ALIAS];
    type_ = details[CONFIG_ACCOUNT_TYPE];
386
387
    username_ = details[CONFIG_ACCOUNT_USERNAME];
    hostname_ = details[CONFIG_ACCOUNT_HOSTNAME];
388
389
390
391
    enabled_ = details[CONFIG_ACCOUNT_ENABLE] == "true";
    ringtonePath_ = details[CONFIG_RINGTONE_PATH];
    ringtoneEnabled_ = details[CONFIG_RINGTONE_ENABLED] == "true";
    mailBox_ = details[CONFIG_ACCOUNT_MAILBOX];
Julien Bonjean's avatar
Julien Bonjean committed
392
393

    // SIP specific account settings
394
395

    // general sip settings
396
397
398
399
400
401
402
    displayName_ = details[CONFIG_DISPLAY_NAME];
    serviceRoute_ = details[CONFIG_ACCOUNT_ROUTESET];
    interface_ = details[CONFIG_LOCAL_INTERFACE];
    publishedSameasLocal_ = details[CONFIG_PUBLISHED_SAMEAS_LOCAL] == "true";
    publishedIpAddress_ = details[CONFIG_PUBLISHED_ADDRESS];
    localPort_ = atoi(details[CONFIG_LOCAL_PORT].c_str());
    publishedPort_ = atoi(details[CONFIG_PUBLISHED_PORT].c_str());
403
404
    if(stunServer_ != details[CONFIG_STUN_SERVER]) {
        DEBUG("Stun server changed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
405
        link_->sipTransport.destroyStunResolver(stunServer_);
406
407
        // pj_stun_sock_destroy(pj_stun_sock *stun_sock);
    }
408
409
410
    stunServer_ = details[CONFIG_STUN_SERVER];
    stunEnabled_ = details[CONFIG_STUN_ENABLE] == "true";
    dtmfType_ = details[CONFIG_ACCOUNT_DTMF_TYPE];
Rafaël Carré's avatar
Rafaël Carré committed
411
    registrationExpire_ = atoi(details[CONFIG_ACCOUNT_REGISTRATION_EXPIRE].c_str());
412

413
    userAgent_ = details[CONFIG_ACCOUNT_USERAGENT];
414
415

    // srtp settings
416
417
418
419
420
421
422
    srtpEnabled_ = details[CONFIG_SRTP_ENABLE] == "true";
    srtpFallback_ = details[CONFIG_SRTP_RTP_FALLBACK] == "true";
    zrtpDisplaySas_ = details[CONFIG_ZRTP_DISPLAY_SAS] == "true";
    zrtpDisplaySasOnce_ = details[CONFIG_ZRTP_DISPLAY_SAS_ONCE] == "true";
    zrtpNotSuppWarning_ = details[CONFIG_ZRTP_NOT_SUPP_WARNING] == "true";
    zrtpHelloHash_ = details[CONFIG_ZRTP_HELLO_HASH] == "true";
    srtpKeyExchange_ = details[CONFIG_SRTP_KEY_EXCHANGE];
423
424

    // TLS settings
425
    tlsListenerPort_ = atoi(details[CONFIG_TLS_LISTENER_PORT].c_str());
426
427
428
429
430
431
432
433
434
435
436
437
438
    tlsEnable_ = details[CONFIG_TLS_ENABLE];
    tlsCaListFile_ = details[CONFIG_TLS_CA_LIST_FILE];
    tlsCertificateFile_ = details[CONFIG_TLS_CERTIFICATE_FILE];
    tlsPrivateKeyFile_ = details[CONFIG_TLS_PRIVATE_KEY_FILE];
    tlsPassword_ = details[CONFIG_TLS_PASSWORD];
    tlsMethod_ = details[CONFIG_TLS_METHOD];
    tlsCiphers_ = details[CONFIG_TLS_CIPHERS];
    tlsServerName_ = details[CONFIG_TLS_SERVER_NAME];
    tlsVerifyServer_ = details[CONFIG_TLS_VERIFY_SERVER] == "true";
    tlsVerifyClient_ = details[CONFIG_TLS_VERIFY_CLIENT] == "true";
    tlsRequireClientCertificate_ = details[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] == "true";
    tlsNegotiationTimeoutSec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC];
    tlsNegotiationTimeoutMsec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC];
439

440
    if (credentials_.empty()) { // credentials not set, construct 1 entry
441
442
        std::vector<std::map<std::string, std::string> > v;
        std::map<std::string, std::string> map;
443
444
445
        map[CONFIG_ACCOUNT_USERNAME] = username_;
        map[CONFIG_ACCOUNT_PASSWORD] = details[CONFIG_ACCOUNT_PASSWORD];
        map[CONFIG_ACCOUNT_REALM]    = "*";
446
447
448
        v.push_back(map);
        setCredentials(v);
    }
449
450
}

451
std::map<std::string, std::string> SIPAccount::getAccountDetails() const
452
{
Julien Bonjean's avatar
Julien Bonjean committed
453
454
    std::map<std::string, std::string> a;

455
    a[CONFIG_ACCOUNT_ID] = accountID_;
Julien Bonjean's avatar
Julien Bonjean committed
456
    // The IP profile does not allow to set an alias
457
    a[CONFIG_ACCOUNT_ALIAS] = isIP2IP() ? IP2IP_PROFILE : alias_;
Julien Bonjean's avatar
Julien Bonjean committed
458

459
460
    a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? "true" : "false";
    a[CONFIG_ACCOUNT_TYPE] = type_;
461
462
    a[CONFIG_ACCOUNT_HOSTNAME] = hostname_;
    a[CONFIG_ACCOUNT_USERNAME] = username_;
463

464
465
466
    a[CONFIG_RINGTONE_PATH] = ringtonePath_;
    a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? "true" : "false";
    a[CONFIG_ACCOUNT_MAILBOX] = mailBox_;
467

Julien Bonjean's avatar
Julien Bonjean committed
468
469
470
471
    RegistrationState state = Unregistered;
    std::string registrationStateCode;
    std::string registrationStateDescription;

472
    if (isIP2IP())
Julien Bonjean's avatar
Julien Bonjean committed
473
        registrationStateDescription = "Direct IP call";
474
475
    else {
        state = registrationState_;
476
        int code = registrationStateDetailed_.first;
Julien Bonjean's avatar
Julien Bonjean committed
477
478
479
        std::stringstream out;
        out << code;
        registrationStateCode = out.str();
480
        registrationStateDescription = registrationStateDetailed_.second;
Julien Bonjean's avatar
Julien Bonjean committed
481
482
    }

483
    a[CONFIG_REGISTRATION_STATUS] = isIP2IP() ? "READY": mapStateNumberToString(state);
484
485
    a[CONFIG_REGISTRATION_STATE_CODE] = registrationStateCode;
    a[CONFIG_REGISTRATION_STATE_DESCRIPTION] = registrationStateDescription;
Julien Bonjean's avatar
Julien Bonjean committed
486
487

    // Add sip specific details
488
489
    a[CONFIG_ACCOUNT_ROUTESET] = serviceRoute_;
    a[CONFIG_ACCOUNT_USERAGENT] = userAgent_;
490

491
492
493
    std::stringstream registrationExpireStr;
    registrationExpireStr << registrationExpire_;
    a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = registrationExpireStr.str();
494
495
496
    a[CONFIG_LOCAL_INTERFACE] = interface_;
    a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? "true" : "false";
    a[CONFIG_PUBLISHED_ADDRESS] = publishedIpAddress_;
497
498

    std::stringstream localport;
499
    localport << localPort_;
500
    a[CONFIG_LOCAL_PORT] = localport.str();
501
    std::stringstream publishedport;
502
    publishedport << publishedPort_;
503
504
505
506
    a[CONFIG_PUBLISHED_PORT] = publishedport.str();
    a[CONFIG_STUN_ENABLE] = stunEnabled_ ? "true" : "false";
    a[CONFIG_STUN_SERVER] = stunServer_;
    a[CONFIG_ACCOUNT_DTMF_TYPE] = dtmfType_;
507

508
509
510
    a[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_;
    a[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? "true" : "false";
    a[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? "true" : "false";
511

512
513
514
515
    a[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? "true" : "false";
    a[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? "true" : "false";
    a[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? "true" : "false";
    a[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? "true" : "false";
516
517
518

    // TLS listener is unique and parameters are modified through IP2IP_PROFILE
    std::stringstream tlslistenerport;
519
    tlslistenerport << tlsListenerPort_;
520
521
522
523
524
525
526
527
528
529
530
531
532
533
    a[CONFIG_TLS_LISTENER_PORT] = tlslistenerport.str();
    a[CONFIG_TLS_ENABLE] = tlsEnable_;
    a[CONFIG_TLS_CA_LIST_FILE] = tlsCaListFile_;
    a[CONFIG_TLS_CERTIFICATE_FILE] = tlsCertificateFile_;
    a[CONFIG_TLS_PRIVATE_KEY_FILE] = tlsPrivateKeyFile_;
    a[CONFIG_TLS_PASSWORD] = tlsPassword_;
    a[CONFIG_TLS_METHOD] = tlsMethod_;
    a[CONFIG_TLS_CIPHERS] = tlsCiphers_;
    a[CONFIG_TLS_SERVER_NAME] = tlsServerName_;
    a[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? "true" : "false";
    a[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? "true" : "false";
    a[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? "true" : "false";
    a[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_;
    a[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC] = tlsNegotiationTimeoutMsec_;
Julien Bonjean's avatar
Julien Bonjean committed
534
535

    return a;
536
537
}

538
void SIPAccount::registerVoIPLink()
Julien Bonjean's avatar
Julien Bonjean committed
539
{
540
541
    if (hostname_.length() >= PJ_MAX_HOSTNAME)
        return;
542

543
    // Init TLS settings if the user wants to use TLS
544
    if (tlsEnable_ == "true") {
545
        DEBUG("SIPAccount: TLS is enabled for account %s", accountID_.c_str());
546
        transportType_ = PJSIP_TRANSPORT_TLS;
Emmanuel Milou's avatar
Emmanuel Milou committed
547
        initTlsConfiguration();
548
    }
549

550
    // Init STUN settings for this account if the user selected it
551
552
    if (stunEnabled_) {
        transportType_ = PJSIP_TRANSPORT_START_OTHER;
553
        initStunConfiguration();
Julien Bonjean's avatar
Julien Bonjean committed
554
    } else {
555
        stunServerName_ = pj_str((char*) stunServer_.c_str());
556
    }
557

558
559
    // In our definition of the ip2ip profile (aka Direct IP Calls),
    // no registration should be performed
560
    if (isIP2IP())
561
        return;
562

563
    try {
564
        link_->sendRegister(this);
565
    } catch (const VoipLinkException &e) {
566
        ERROR("SIPAccount: %s", e.what());
567
    }
yanmorin's avatar
 
yanmorin committed
568
569
}

570
void SIPAccount::unregisterVoIPLink()
yanmorin's avatar
 
yanmorin committed
571
{
572
    if (isIP2IP())
573
        return;
Emmanuel Milou's avatar
Emmanuel Milou committed
574

575
    try {
576
577
        link_->sendUnregister(this);
    } catch (const VoipLinkException &e) {
578
        ERROR("SIPAccount: %s", e.what());
579
    }
yanmorin's avatar
 
yanmorin committed
580
581
}

582
583
584
585
586
void SIPAccount::startKeepAliveTimer() {

    if (isTlsEnabled())
        return;

587
588
    DEBUG("SIP ACCOUNT: start keep alive timer");

589
590
591
    // make sure here we have an entirely new timer
    memset(&keepAliveTimer_, 0, sizeof(pj_timer_entry));

592
    pj_time_val keepAliveDelay_;
593
    keepAliveTimer_.cb = &SIPAccount::keepAliveRegistrationCb;
594
    keepAliveTimer_.user_data = this;
595

596
    // expiration may be undetermined during the first registration request
597
598
    if (registrationExpire_ == 0) {
        DEBUG("Registration Expire == 0, take 60");
599
        keepAliveDelay_.sec = 60;
600
601
    }
    else {
Tristan Matthews's avatar
Tristan Matthews committed
602
        DEBUG("Registration Expire == %d", registrationExpire_);
603
        keepAliveDelay_.sec = registrationExpire_;
604
605
    }

606

607
    keepAliveDelay_.msec = 0;
608

609
    link_->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
610
611
612
}

void SIPAccount::stopKeepAliveTimer() {
613
     link_->cancelKeepAliveTimer(keepAliveTimer_);
614
615
}

616
pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum(const std::string& method)
617
{
618
    if (method == "Default")
Emmanuel Milou's avatar
Emmanuel Milou committed
619
        return PJSIP_SSL_UNSPECIFIED_METHOD;
620

621
    if (method == "TLSv1")
Emmanuel Milou's avatar
Emmanuel Milou committed
622
        return PJSIP_TLSV1_METHOD;
623

624
    if (method == "SSLv3")
Emmanuel Milou's avatar
Emmanuel Milou committed
625
        return PJSIP_SSLV3_METHOD;
626

627
    if (method == "SSLv23")
Emmanuel Milou's avatar
Emmanuel Milou committed
628
        return PJSIP_SSLV23_METHOD;
629

Emmanuel Milou's avatar
Emmanuel Milou committed
630
    return PJSIP_SSL_UNSPECIFIED_METHOD;
631
632
}

633
void SIPAccount::initTlsConfiguration()
634
{
635
    // TLS listener is unique and should be only modified through IP2IP_PROFILE
636
    pjsip_tls_setting_default(&tlsSetting_);
637

638
639
640
641
642
643
644
    pj_cstr(&tlsSetting_.ca_list_file, tlsCaListFile_.c_str());
    pj_cstr(&tlsSetting_.cert_file, tlsCertificateFile_.c_str());
    pj_cstr(&tlsSetting_.privkey_file, tlsPrivateKeyFile_.c_str());
    pj_cstr(&tlsSetting_.password, tlsPassword_.c_str());
    tlsSetting_.method = sslMethodStringToPjEnum(tlsMethod_);
    pj_cstr(&tlsSetting_.ciphers, tlsCiphers_.c_str());
    pj_cstr(&tlsSetting_.server_name, tlsServerName_.c_str());
645

646
647
648
    tlsSetting_.verify_server = tlsVerifyServer_ ? PJ_TRUE: PJ_FALSE;
    tlsSetting_.verify_client = tlsVerifyClient_ ? PJ_TRUE: PJ_FALSE;
    tlsSetting_.require_client_cert = tlsRequireClientCertificate_ ? PJ_TRUE: PJ_FALSE;
649

650
651
    tlsSetting_.timeout.sec = atol(tlsNegotiationTimeoutSec_.c_str());
    tlsSetting_.timeout.msec = atol(tlsNegotiationTimeoutMsec_.c_str());
652
653
}

654
void SIPAccount::initStunConfiguration()
655
{
Emmanuel Milou's avatar
Emmanuel Milou committed
656
657
658
    size_t pos;
    std::string stunServer, serverName, serverPort;

659
    stunServer = stunServer_;
Emmanuel Milou's avatar
Emmanuel Milou committed
660
    // Init STUN socket
661
    pos = stunServer.find(':');
662
663

    if (pos == std::string::npos) {
664
        stunServerName_ = pj_str((char*) stunServer.data());
665
        stunPort_ = PJ_STUN_PORT;
666
667
        //stun_status = pj_sockaddr_in_init (&stun_srv.ipv4, &stun_adr, (pj_uint16_t) 3478);
    } else {
668
669
670
671
        serverName = stunServer.substr(0, pos);
        serverPort = stunServer.substr(pos + 1);
        stunPort_ = atoi(serverPort.data());
        stunServerName_ = pj_str((char*) serverName.data());
672
        //stun_status = pj_sockaddr_in_init (&stun_srv.ipv4, &stun_adr, (pj_uint16_t) nPort);
Emmanuel Milou's avatar
Emmanuel Milou committed
673
    }
674
675
}

676
void SIPAccount::loadConfig()
677
{
Rafaël Carré's avatar
Rafaël Carré committed
678
    if (registrationExpire_ == 0)
679
        registrationExpire_ = MIN_REGISTRATION_TIME; /** Default expire value for registration */
680

681
    if (tlsEnable_ == "true") {
Emmanuel Milou's avatar
Emmanuel Milou committed
682
        initTlsConfiguration();
683
        transportType_ = PJSIP_TRANSPORT_TLS;
684
    } else
685
        transportType_ = PJSIP_TRANSPORT_UDP;
yanmorin's avatar
   
yanmorin committed
686
}
687

688
bool SIPAccount::fullMatch(const std::string& username, const std::string& hostname) const
689
{
690
    return userMatch(username) and hostnameMatch(hostname);
691
692
}

693
bool SIPAccount::userMatch(const std::string& username) const
694
{
695
    return !username.empty() and username == username_;
696
697
}

698
bool SIPAccount::hostnameMatch(const std::string& hostname) const
699
{
700
    return hostname == hostname_;
701
702
}

703
std::string SIPAccount::getLoginName()
704
{
705
    struct passwd * user_info = getpwuid(getuid());
Rafaël Carré's avatar
Rafaël Carré committed
706
    return user_info ? user_info->pw_name : "";
707
708
}

709
std::string SIPAccount::getFromUri() const
710
{
711
712
713
714
    std::string scheme;
    std::string transport;
    std::string username(username_);
    std::string hostname(hostname_);
715

716
    // UDP does not require the transport specification
717
    if (transportType_ == PJSIP_TRANSPORT_TLS) {
718
        scheme = "sips:";
Rafaël Carré's avatar
Rafaël Carré committed
719
        transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
720
    } else
721
722
723
        scheme = "sip:";

    // Get login name if username is not specified
Tristan Matthews's avatar
Tristan Matthews committed
724
    if (username_.empty())
725
        username = getLoginName();
726
727

    // Get machine hostname if not provided
Tristan Matthews's avatar
Tristan Matthews committed
728
    if (hostname_.empty())
729
        hostname = std::string(pj_gethostname()->ptr, pj_gethostname()->slen);
730

Rafaël Carré's avatar
Rafaël Carré committed
731
    return "<" + scheme + username + "@" + hostname + transport + ">";
732
733
}

734
std::string SIPAccount::getToUri(const std::string& username) const
735
736
737
{
    std::string scheme;
    std::string transport;
Rafaël Carré's avatar
Rafaël Carré committed
738
    std::string hostname;
739

740
    // UDP does not require the transport specification
741
    if (transportType_ == PJSIP_TRANSPORT_TLS) {
742
        scheme = "sips:";
Rafaël Carré's avatar
Rafaël Carré committed
743
744
        transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
    } else
745
        scheme = "sip:";
746

747
    // Check if scheme is already specified
748
    if (username.find("sip") == 0)
749
        scheme = "";
750

751
    // Check if hostname is already specified
752
    if (username.find("@") == std::string::npos)
Tristan Matthews's avatar
Tristan Matthews committed
753
        hostname = hostname_;
754

Rafaël Carré's avatar
Rafaël Carré committed
755
    return "<" + scheme + username + (hostname.empty() ? "" : "@") + hostname + transport + ">";
756
757
}

758
std::string SIPAccount::getServerUri() const
759
760
761
{
    std::string scheme;
    std::string transport;
762

763
    // UDP does not require the transport specification
764
    if (transportType_ == PJSIP_TRANSPORT_TLS) {
765
        scheme = "sips:";
766
        transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
767
    } else {
768
769
        scheme = "sip:";
        transport = "";
770
    }
771

Rafaël Carré's avatar
Rafaël Carré committed
772
    return "<" + scheme + hostname_ + transport + ">";
773
774
}

775
776
777
778
779
780
781
782
783
784
785
void SIPAccount::setContactHeader(std::string address, std::string port)
{
    std::string scheme;
    std::string transport;

    // UDP does not require the transport specification
    if (transportType_ == PJSIP_TRANSPORT_TLS) {
        scheme = "sips:";
        transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
    } else
        scheme = "sip:";
786

787
788
789
790
    contactHeader_ = displayName_ + (displayName_.empty() ? "" : " ") + "<" +
                     scheme + username_ + (username_.empty() ? "":"@") +
                     address + ":" + port + transport + ">";
}
791

792

793
std::string SIPAccount::getContactHeader() const
794
{
Tristan Matthews's avatar
Tristan Matthews committed
795
    if (transport_ == NULL)
796
797
798
        ERROR("Transport not created yet");

    // The transport type must be specified, in our case START_OTHER refers to stun transport
Tristan Matthews's avatar
Tristan Matthews committed
799
800
    pjsip_transport_type_e transportType = transportType_;
    if (transportType == PJSIP_TRANSPORT_START_OTHER)
801
        transportType = PJSIP_TRANSPORT_UDP;
802

803
    // Use the CONTACT header provided by the registrar if any
Tristan Matthews's avatar
Tristan Matthews committed
804
    if (!contactHeader_.empty())
805
806
807
808
        return contactHeader_;

    // Else we determine this infor based on transport information
    std::string address, port;
Alexandre Savard's avatar