sipaccount.cpp 38.1 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"
yanmorin's avatar
 
yanmorin committed
41
#include "manager.h"
42
#include <pwd.h>
43
#include <sstream>
44
#include <cassert>
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 77
    , tlsEnable_("false")
    , tlsPort_(DEFAULT_SIP_TLS_PORT)
78 79 80 81
    , tlsCaListFile_()
    , tlsCertificateFile_()
    , tlsPrivateKeyFile_()
    , tlsPassword_()
82
    , tlsMethod_("TLSv1")
83 84
    , tlsCiphers_()
    , tlsServerName_(0, 0)
85 86 87 88 89 90 91 92 93 94 95 96 97 98
    , 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)
99
    , registrationStateDetailed_()
100
    , keepAliveTimer_()
101 102
    , link_(SIPVoIPLink::instance())
{}
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 << tlsPort_;
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(aliasKey, &alias);
    accountmap.setKeyValue(typeKey, &type);
    accountmap.setKeyValue(idKey, &id);
    accountmap.setKeyValue(usernameKey, &username);
    accountmap.setKeyValue(hostnameKey, &hostname);
    accountmap.setKeyValue(accountEnableKey, &enable);
    accountmap.setKeyValue(mailboxKey, &mailbox);
178
    accountmap.setKeyValue(registrationExpireKey, &expire);
179 180 181 182 183 184 185 186
    accountmap.setKeyValue(interfaceKey, &interface);
    accountmap.setKeyValue(portKey, &port);
    accountmap.setKeyValue(stunServerKey, &stunServer);
    accountmap.setKeyValue(stunEnabledKey, &stunEnabled);
    accountmap.setKeyValue(publishAddrKey, &publishAddr);
    accountmap.setKeyValue(publishPortKey, &publishPort);
    accountmap.setKeyValue(sameasLocalKey, &sameasLocal);
    accountmap.setKeyValue(serviceRouteKey, &serviceRoute);
187
    accountmap.setKeyValue(updateContactHeaderKey, &contactUpdateEnabled);
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
    accountmap.setKeyValue(dtmfTypeKey, &dtmfType);
    accountmap.setKeyValue(displayNameKey, &displayName);
    accountmap.setKeyValue(codecsKey, &codecs);
    accountmap.setKeyValue(ringtonePathKey, &ringtonePath);
    accountmap.setKeyValue(ringtoneEnabledKey, &ringtoneEnabled);

    accountmap.setKeyValue(srtpKey, &srtpmap);
    srtpmap.setKeyValue(srtpEnableKey, &srtpenabled);
    srtpmap.setKeyValue(keyExchangeKey, &keyExchange);
    srtpmap.setKeyValue(rtpFallbackKey, &rtpFallback);

    accountmap.setKeyValue(zrtpKey, &zrtpmap);
    zrtpmap.setKeyValue(displaySasKey, &displaySas);
    zrtpmap.setKeyValue(displaySasOnceKey, &displaySasOnce);
    zrtpmap.setKeyValue(helloHashEnabledKey, &helloHashEnabled);
    zrtpmap.setKeyValue(notSuppWarningKey, &notSuppWarning);

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

    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 219 220 221 222 223 224 225 226 227 228 229 230 231 232
        credentialseq.addNode(map);
    }

    accountmap.setKeyValue(tlsKey, &tlsmap);
    tlsmap.setKeyValue(tlsPortKey, &tlsport);
    tlsmap.setKeyValue(certificateKey, &certificate);
    tlsmap.setKeyValue(calistKey, &calist);
    tlsmap.setKeyValue(ciphersKey, &ciphers);
    tlsmap.setKeyValue(tlsEnableKey, &tlsenabled);
    tlsmap.setKeyValue(methodKey, &tlsmethod);
    tlsmap.setKeyValue(timeoutKey, &timeout);
    tlsmap.setKeyValue(tlsPasswordKey, &tlspassword);
    tlsmap.setKeyValue(privateKeyKey, &privatekey);
    tlsmap.setKeyValue(requireCertifKey, &requirecertif);
    tlsmap.setKeyValue(serverKey, &server);
    tlsmap.setKeyValue(verifyClientKey, &verifyclient);
    tlsmap.setKeyValue(verifyServerKey, &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 = (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
}
253

254
void SIPAccount::unserialize(const Conf::MappingNode *map)
255
{
256 257 258 259
    using namespace Conf;
    MappingNode *srtpMap;
    MappingNode *tlsMap;
    MappingNode *zrtpMap;
Julien Bonjean's avatar
Julien Bonjean committed
260

261
    assert(map);
Julien Bonjean's avatar
Julien Bonjean committed
262

Tristan Matthews's avatar
Tristan Matthews committed
263 264 265 266 267 268 269
    map->getValue(aliasKey, &alias_);
    map->getValue(typeKey, &type_);
    map->getValue(usernameKey, &username_);
    map->getValue(hostnameKey, &hostname_);
    map->getValue(accountEnableKey, &enabled_);
    map->getValue(mailboxKey, &mailBox_);
    map->getValue(codecsKey, &codecStr_);
270
    // Update codec list which one is used for SDP offer
271
    setActiveCodecs(ManagerImpl::unserialize(codecStr_));
272

Tristan Matthews's avatar
Tristan Matthews committed
273 274
    map->getValue(ringtonePathKey, &ringtonePath_);
    map->getValue(ringtoneEnabledKey, &ringtoneEnabled_);
275
    map->getValue(registrationExpireKey, &registrationExpire_);
276
    map->getValue(interfaceKey, &interface_);
277 278
    int port;
    map->getValue(portKey, &port);
279 280
    localPort_ = port;
    map->getValue(publishAddrKey, &publishedIpAddress_);
281
    map->getValue(publishPortKey, &port);
282 283
    publishedPort_ = port;
    map->getValue(sameasLocalKey, &publishedSameasLocal_);
284 285 286

    std::string dtmfType;
    map->getValue(dtmfTypeKey, &dtmfType);
287
    dtmfType_ = dtmfType;
288

289
    map->getValue(serviceRouteKey, &serviceRoute_);
290 291
    map->getValue(updateContactHeaderKey, &contactUpdateEnabled_);

Julien Bonjean's avatar
Julien Bonjean committed
292
    // stun enabled
293 294
    map->getValue(stunEnabledKey, &stunEnabled_);
    map->getValue(stunServerKey, &stunServer_);
Julien Bonjean's avatar
Julien Bonjean committed
295

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

Tristan Matthews's avatar
Tristan Matthews committed
299
    map->getValue(displayNameKey, &displayName_);
300

301 302
    std::vector<std::map<std::string, std::string> > creds;

303
    YamlNode *credNode = map->getValue(credKey);
304 305 306 307 308

    /* We check if the credential key is a sequence
     * because it was a mapping in a previous version of
     * the configuration file.
     */
309 310 311 312
    if (credNode && credNode->getType() == SEQUENCE) {
        SequenceNode *credSeq = (SequenceNode *) credNode;
        Sequence::iterator it;
        Sequence *seq = credSeq->getSequence();
313 314

        for (it = seq->begin(); it != seq->end(); ++it) {
315
            MappingNode *cred = (MappingNode *)(*it);
316 317 318
            std::string user;
            std::string pass;
            std::string realm;
319 320 321
            cred->getValue(CONFIG_ACCOUNT_USERNAME, &user);
            cred->getValue(CONFIG_ACCOUNT_PASSWORD, &pass);
            cred->getValue(CONFIG_ACCOUNT_REALM, &realm);
322
            std::map<std::string, std::string> credentialMap;
323 324 325
            credentialMap[CONFIG_ACCOUNT_USERNAME] = user;
            credentialMap[CONFIG_ACCOUNT_PASSWORD] = pass;
            credentialMap[CONFIG_ACCOUNT_REALM] = realm;
326 327 328 329
            creds.push_back(credentialMap);
        }
    }

330
    if (creds.empty()) {
331 332 333 334 335
        // migration from old file format
        std::map<std::string, std::string> credmap;
        std::string password;
        map->getValue(passwordKey, &password);

336 337 338
        credmap[CONFIG_ACCOUNT_USERNAME] = username_;
        credmap[CONFIG_ACCOUNT_PASSWORD] = password;
        credmap[CONFIG_ACCOUNT_REALM] = "*";
339
        creds.push_back(credmap);
340
    }
341 342

    setCredentials(creds);
Julien Bonjean's avatar
Julien Bonjean committed
343 344

    // get srtp submap
345
    srtpMap = (MappingNode *)(map->getValue(srtpKey));
346

347
    if (srtpMap) {
348 349 350
        srtpMap->getValue(srtpEnableKey, &srtpEnabled_);
        srtpMap->getValue(keyExchangeKey, &srtpKeyExchange_);
        srtpMap->getValue(rtpFallbackKey, &srtpFallback_);
351
    }
Julien Bonjean's avatar
Julien Bonjean committed
352 353

    // get zrtp submap
354
    zrtpMap = (MappingNode *)(map->getValue(zrtpKey));
355

356
    if (zrtpMap) {
357 358 359 360
        zrtpMap->getValue(displaySasKey, &zrtpDisplaySas_);
        zrtpMap->getValue(displaySasOnceKey, &zrtpDisplaySasOnce_);
        zrtpMap->getValue(helloHashEnabledKey, &zrtpHelloHash_);
        zrtpMap->getValue(notSuppWarningKey, &zrtpNotSuppWarning_);
361
    }
Julien Bonjean's avatar
Julien Bonjean committed
362 363

    // get tls submap
364
    tlsMap = (MappingNode *)(map->getValue(tlsKey));
365

366
    if (tlsMap) {
367 368 369 370 371 372 373 374 375 376 377 378
        tlsMap->getValue(tlsEnableKey, &tlsEnable_);
        tlsMap->getValue(tlsPortKey, &tlsPort_);
        tlsMap->getValue(certificateKey, &tlsCertificateFile_);
        tlsMap->getValue(calistKey, &tlsCaListFile_);
        tlsMap->getValue(ciphersKey, &tlsCiphers_);
        tlsMap->getValue(methodKey, &tlsMethod_);
        tlsMap->getValue(tlsPasswordKey, &tlsPassword_);
        tlsMap->getValue(privateKeyKey, &tlsPrivateKeyFile_);
        tlsMap->getValue(requireCertifKey, &tlsRequireClientCertificate_);
        tlsMap->getValue(serverKey, &tlsServerName_);
        tlsMap->getValue(verifyClientKey, &tlsVerifyServer_);
        tlsMap->getValue(verifyServerKey, &tlsVerifyClient_);
379
        // FIXME
380 381
        tlsMap->getValue(timeoutKey, &tlsNegotiationTimeoutSec_);
        tlsMap->getValue(timeoutKey, &tlsNegotiationTimeoutMsec_);
382
    }
383 384
}

385

386
void SIPAccount::setAccountDetails(std::map<std::string, std::string> details)
387
{
Julien Bonjean's avatar
Julien Bonjean committed
388
    // Account setting common to SIP and IAX
389 390
    alias_ = details[CONFIG_ACCOUNT_ALIAS];
    type_ = details[CONFIG_ACCOUNT_TYPE];
391 392
    username_ = details[CONFIG_ACCOUNT_USERNAME];
    hostname_ = details[CONFIG_ACCOUNT_HOSTNAME];
393 394 395 396
    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
397 398

    // SIP specific account settings
399 400

    // general sip settings
401 402 403 404 405 406 407
    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());
408 409 410 411 412
    if(stunServer_ != details[CONFIG_STUN_SERVER]) {
        DEBUG("Stun server changed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        link_->destroyStunResolver(stunServer_);
        // pj_stun_sock_destroy(pj_stun_sock *stun_sock);
    }
413 414 415
    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
416
    registrationExpire_ = atoi(details[CONFIG_ACCOUNT_REGISTRATION_EXPIRE].c_str());
417

418
    userAgent_ = details[CONFIG_ACCOUNT_USERAGENT];
419 420

    // srtp settings
421 422 423 424 425 426 427
    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];
428 429 430

    // TLS settings
    // The TLS listener is unique and globally defined through IP2IP_PROFILE
431
    if (isIP2IP())
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
        tlsListenerPort_ = atoi(details[CONFIG_TLS_LISTENER_PORT].c_str());

    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];
447

448
    if (credentials_.empty()) { // credentials not set, construct 1 entry
449 450
        std::vector<std::map<std::string, std::string> > v;
        std::map<std::string, std::string> map;
451 452 453
        map[CONFIG_ACCOUNT_USERNAME] = username_;
        map[CONFIG_ACCOUNT_PASSWORD] = details[CONFIG_ACCOUNT_PASSWORD];
        map[CONFIG_ACCOUNT_REALM]    = "*";
454 455 456
        v.push_back(map);
        setCredentials(v);
    }
457 458
}

459
std::map<std::string, std::string> SIPAccount::getAccountDetails() const
460
{
Julien Bonjean's avatar
Julien Bonjean committed
461 462
    std::map<std::string, std::string> a;

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

467 468
    a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? "true" : "false";
    a[CONFIG_ACCOUNT_TYPE] = type_;
469 470
    a[CONFIG_ACCOUNT_HOSTNAME] = hostname_;
    a[CONFIG_ACCOUNT_USERNAME] = username_;
471

472 473 474
    a[CONFIG_RINGTONE_PATH] = ringtonePath_;
    a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? "true" : "false";
    a[CONFIG_ACCOUNT_MAILBOX] = mailBox_;
475

Julien Bonjean's avatar
Julien Bonjean committed
476 477 478 479
    RegistrationState state = Unregistered;
    std::string registrationStateCode;
    std::string registrationStateDescription;

480
    if (isIP2IP())
Julien Bonjean's avatar
Julien Bonjean committed
481
        registrationStateDescription = "Direct IP call";
482 483
    else {
        state = registrationState_;
484
        int code = registrationStateDetailed_.first;
Julien Bonjean's avatar
Julien Bonjean committed
485 486 487
        std::stringstream out;
        out << code;
        registrationStateCode = out.str();
488
        registrationStateDescription = registrationStateDetailed_.second;
Julien Bonjean's avatar
Julien Bonjean committed
489 490
    }

491
    a[CONFIG_REGISTRATION_STATUS] = isIP2IP() ? "READY": mapStateNumberToString(state);
492 493
    a[CONFIG_REGISTRATION_STATE_CODE] = registrationStateCode;
    a[CONFIG_REGISTRATION_STATE_DESCRIPTION] = registrationStateDescription;
Julien Bonjean's avatar
Julien Bonjean committed
494 495

    // Add sip specific details
496 497
    a[CONFIG_ACCOUNT_ROUTESET] = serviceRoute_;
    a[CONFIG_ACCOUNT_USERAGENT] = userAgent_;
498

499 500 501
    std::stringstream registrationExpireStr;
    registrationExpireStr << registrationExpire_;
    a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = registrationExpireStr.str();
502 503 504
    a[CONFIG_LOCAL_INTERFACE] = interface_;
    a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? "true" : "false";
    a[CONFIG_PUBLISHED_ADDRESS] = publishedIpAddress_;
505 506

    std::stringstream localport;
507
    localport << localPort_;
508
    a[CONFIG_LOCAL_PORT] = localport.str();
509
    std::stringstream publishedport;
510
    publishedport << publishedPort_;
511 512 513 514
    a[CONFIG_PUBLISHED_PORT] = publishedport.str();
    a[CONFIG_STUN_ENABLE] = stunEnabled_ ? "true" : "false";
    a[CONFIG_STUN_SERVER] = stunServer_;
    a[CONFIG_ACCOUNT_DTMF_TYPE] = dtmfType_;
515

516 517 518
    a[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_;
    a[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? "true" : "false";
    a[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? "true" : "false";
519

520 521 522 523
    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";
524 525 526

    // TLS listener is unique and parameters are modified through IP2IP_PROFILE
    std::stringstream tlslistenerport;
527
    tlslistenerport << tlsListenerPort_;
528 529 530 531 532 533 534 535 536 537 538 539 540 541
    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
542 543

    return a;
544 545
}

546
void SIPAccount::registerVoIPLink()
Julien Bonjean's avatar
Julien Bonjean committed
547
{
548 549
    if (hostname_.length() >= PJ_MAX_HOSTNAME)
        return;
550

551
    // Init TLS settings if the user wants to use TLS
552
    if (tlsEnable_ == "true") {
553
        DEBUG("SIPAccount: TLS is enabled for account %s", accountID_.c_str());
554
        transportType_ = PJSIP_TRANSPORT_TLS;
Emmanuel Milou's avatar
Emmanuel Milou committed
555
        initTlsConfiguration();
556
    }
557

558
    // Init STUN settings for this account if the user selected it
559 560
    if (stunEnabled_) {
        transportType_ = PJSIP_TRANSPORT_START_OTHER;
561
        initStunConfiguration();
Julien Bonjean's avatar
Julien Bonjean committed
562
    } else {
563
        stunServerName_ = pj_str((char*) stunServer_.c_str());
564
    }
565

566 567
    // In our definition of the ip2ip profile (aka Direct IP Calls),
    // no registration should be performed
568
    if (isIP2IP())
569
        return;
570

571
    try {
572
        link_->sendRegister(this);
573
    } catch (const VoipLinkException &e) {
574
        ERROR("SIPAccount: %s", e.what());
575
    }
yanmorin's avatar
 
yanmorin committed
576 577
}

578
void SIPAccount::unregisterVoIPLink()
yanmorin's avatar
 
yanmorin committed
579
{
580
    if (isIP2IP())
581
        return;
Emmanuel Milou's avatar
Emmanuel Milou committed
582

583
    try {
584 585
        link_->sendUnregister(this);
    } catch (const VoipLinkException &e) {
586
        ERROR("SIPAccount: %s", e.what());
587
    }
yanmorin's avatar
 
yanmorin committed
588 589
}

590 591 592 593 594
void SIPAccount::startKeepAliveTimer() {

    if (isTlsEnabled())
        return;

595 596
    DEBUG("SIP ACCOUNT: start keep alive timer");

597 598 599
    // make sure here we have an entirely new timer
    memset(&keepAliveTimer_, 0, sizeof(pj_timer_entry));

600
    pj_time_val keepAliveDelay_;
601
    keepAliveTimer_.cb = &SIPAccount::keepAliveRegistrationCb;
602
    keepAliveTimer_.user_data = this;
603

604
    // expiration may be undetermined during the first registration request
605 606
    if (registrationExpire_ == 0) {
        DEBUG("Registration Expire == 0, take 60");
607
        keepAliveDelay_.sec = 60;
608 609 610
    }
    else {
        DEBUG("Regsitration Expire == %d", registrationExpire_);
611
        keepAliveDelay_.sec = registrationExpire_;
612 613
    }

614

615
    keepAliveDelay_.msec = 0;
616

617
    link_->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
618 619 620
}

void SIPAccount::stopKeepAliveTimer() {
621
     link_->cancelKeepAliveTimer(keepAliveTimer_);
622 623
}

624
pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum(const std::string& method)
625
{
626
    if (method == "Default")
Emmanuel Milou's avatar
Emmanuel Milou committed
627
        return PJSIP_SSL_UNSPECIFIED_METHOD;
628

629
    if (method == "TLSv1")
Emmanuel Milou's avatar
Emmanuel Milou committed
630
        return PJSIP_TLSV1_METHOD;
631

632
    if (method == "SSLv3")
Emmanuel Milou's avatar
Emmanuel Milou committed
633
        return PJSIP_SSLV3_METHOD;
634

635
    if (method == "SSLv23")
Emmanuel Milou's avatar
Emmanuel Milou committed
636
        return PJSIP_SSLV23_METHOD;
637

Emmanuel Milou's avatar
Emmanuel Milou committed
638
    return PJSIP_SSL_UNSPECIFIED_METHOD;
639 640
}

641
void SIPAccount::initTlsConfiguration()
642
{
643
    // TLS listener is unique and should be only modified through IP2IP_PROFILE
644
    tlsListenerPort_ = tlsPort_;
Julien Bonjean's avatar
Julien Bonjean committed
645

646
    pjsip_tls_setting_default(&tlsSetting_);
647

648 649 650 651 652 653 654
    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());
655

656 657 658
    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;
659

660 661
    tlsSetting_.timeout.sec = atol(tlsNegotiationTimeoutSec_.c_str());
    tlsSetting_.timeout.msec = atol(tlsNegotiationTimeoutMsec_.c_str());
662 663
}

664
void SIPAccount::initStunConfiguration()
665
{
Emmanuel Milou's avatar
Emmanuel Milou committed
666 667 668
    size_t pos;
    std::string stunServer, serverName, serverPort;

669
    stunServer = stunServer_;
Emmanuel Milou's avatar
Emmanuel Milou committed
670
    // Init STUN socket
671
    pos = stunServer.find(':');
672 673

    if (pos == std::string::npos) {
674
        stunServerName_ = pj_str((char*) stunServer.data());
675
        stunPort_ = PJ_STUN_PORT;
676 677
        //stun_status = pj_sockaddr_in_init (&stun_srv.ipv4, &stun_adr, (pj_uint16_t) 3478);
    } else {
678 679 680 681
        serverName = stunServer.substr(0, pos);
        serverPort = stunServer.substr(pos + 1);
        stunPort_ = atoi(serverPort.data());
        stunServerName_ = pj_str((char*) serverName.data());
682
        //stun_status = pj_sockaddr_in_init (&stun_srv.ipv4, &stun_adr, (pj_uint16_t) nPort);
Emmanuel Milou's avatar
Emmanuel Milou committed
683
    }
684 685
}

686
void SIPAccount::loadConfig()
687
{
Rafaël Carré's avatar
Rafaël Carré committed
688
    if (registrationExpire_ == 0)
689
        registrationExpire_ = MIN_REGISTRATION_TIME; /** Default expire value for registration */
690

691
    if (tlsEnable_ == "true") {
Emmanuel Milou's avatar
Emmanuel Milou committed
692
        initTlsConfiguration();
693
        transportType_ = PJSIP_TRANSPORT_TLS;
694
    } else
695
        transportType_ = PJSIP_TRANSPORT_UDP;
yanmorin's avatar
 
yanmorin committed
696
}
697

698
bool SIPAccount::fullMatch(const std::string& username, const std::string& hostname) const
699
{
700
    return userMatch(username) and hostnameMatch(hostname);
701 702
}

703
bool SIPAccount::userMatch(const std::string& username) const
704
{
705
    return !username.empty() and username == username_;
706 707
}

708
bool SIPAccount::hostnameMatch(const std::string& hostname) const
709
{
710
    return hostname == hostname_;
711 712
}

713
std::string SIPAccount::getLoginName()
714
{
715
    struct passwd * user_info = getpwuid(getuid());
Rafaël Carré's avatar
Rafaël Carré committed
716
    return user_info ? user_info->pw_name : "";
717 718
}

719
std::string SIPAccount::getFromUri() const
720
{
721 722 723 724
    std::string scheme;
    std::string transport;
    std::string username(username_);
    std::string hostname(hostname_);
725

726
    // UDP does not require the transport specification
727
    if (transportType_ == PJSIP_TRANSPORT_TLS) {
728
        scheme = "sips:";
Rafaël Carré's avatar
Rafaël Carré committed
729
        transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
730
    } else
731 732 733
        scheme = "sip:";

    // Get login name if username is not specified
Tristan Matthews's avatar
Tristan Matthews committed
734
    if (username_.empty())
735
        username = getLoginName();
736 737

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

Rafaël Carré's avatar
Rafaël Carré committed
741
    return "<" + scheme + username + "@" + hostname + transport + ">";
742 743
}

744
std::string SIPAccount::getToUri(const std::string& username) const
745 746 747
{
    std::string scheme;
    std::string transport;
Rafaël Carré's avatar
Rafaël Carré committed
748
    std::string hostname;
749

750
    // UDP does not require the transport specification
751
    if (transportType_ == PJSIP_TRANSPORT_TLS) {
752
        scheme = "sips:";
Rafaël Carré's avatar
Rafaël Carré committed
753 754
        transport = ";transport=" + std::string(pjsip_transport_get_type_name(transportType_));
    } else
755
        scheme = "sip:";
756

757
    // Check if scheme is already specified
758
    if (username.find("sip") == 0)
759
        scheme = "";
760

761
    // Check if hostname is already specified
762
    if (username.find("@") == std::string::npos)
Tristan Matthews's avatar
Tristan Matthews committed
763
        hostname = hostname_;
764

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

768
std::string SIPAccount::getServerUri() const
769 770 771
{
    std::string scheme;
    std::string transport;
772

773
    // UDP does not require the transport specification
774
    if (transportType_ == PJSIP_TRANSPORT_TLS) {
pierre-luc's avatar
<