sipaccount.cpp 49.8 KB
Newer Older
yanmorin's avatar
 
yanmorin committed
1
/*
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
*
*  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
19
*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 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

37
#include "account_schema.h"
yanmorin's avatar
 
yanmorin committed
38
#include "sipaccount.h"
39
#include "sippresence.h"
40
#include "sip_utils.h"
41
#include "sipvoiplink.h"
42 43
#include "config/yamlnode.h"
#include "config/yamlemitter.h"
44
#include "logger.h"
yanmorin's avatar
 
yanmorin committed
45
#include "manager.h"
46
#include <unistd.h>
47
#include <pwd.h>
48
#include <sstream>
49 50
#include <algorithm>
#include <cstdlib>
51 52
#include <array>
#include <memory>
53

54

55 56 57 58
#ifdef SFL_VIDEO
#include "video/libav_utils.h"
#endif

59

60
const char * const SIPAccount::IP2IP_PROFILE = "IP2IP";
61 62
const char * const SIPAccount::OVERRTP_STR = "overrtp";
const char * const SIPAccount::SIPINFO_STR = "sipinfo";
63
const char * const SIPAccount::ACCOUNT_TYPE = "SIP";
64

65
namespace {
66 67 68 69
const int MIN_REGISTRATION_TIME = 60;
const int DEFAULT_REGISTRATION_TIME = 3600;
const char *const TRUE_STR = "true";
const char *const FALSE_STR = "false";
70 71
}

72 73
// we force RTP ports to be even, so we only need HALF_MAX_PORT booleans
bool SIPAccount::portsInUse_[HALF_MAX_PORT];
74

75
SIPAccount::SIPAccount(const std::string& accountID)
76
    : Account(accountID)
77
    , transport_(NULL)
78
    , credentials_()
79 80
    , regc_(NULL)
    , bRegister_(false)
81
    , registrationExpire_(MIN_REGISTRATION_TIME)
82 83
    , interface_("default")
    , publishedSameasLocal_(true)
84
    , publishedIpAddress_()
85 86
    , localPort_(DEFAULT_SIP_PORT)
    , publishedPort_(DEFAULT_SIP_PORT)
87
    , serviceRoute_()
88 89
    , tlsListenerPort_(DEFAULT_SIP_TLS_PORT)
    , transportType_(PJSIP_TRANSPORT_UNSPECIFIED)
90
    , cred_()
91
    , tlsSetting_()
Tristan Matthews's avatar
Tristan Matthews committed
92
    , ciphers_(100)
93
    , stunServerName_()
94
    , stunPort_(PJ_STUN_PORT)
95
    , dtmfType_(OVERRTP_STR)
96
    , tlsEnable_(FALSE_STR)
97 98 99 100
    , tlsCaListFile_()
    , tlsCertificateFile_()
    , tlsPrivateKeyFile_()
    , tlsPassword_()
101
    , tlsMethod_("TLSv1")
102 103
    , tlsCiphers_()
    , tlsServerName_(0, 0)
104 105 106 107 108 109 110 111 112 113 114 115 116 117
    , 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)
118
    , registrationStateDetailed_()
119
    , keepAliveEnabled_(false)
120
    , keepAliveTimer_()
121
    , keepAliveTimerActive_(false)
122
    , link_(SIPVoIPLink::instance())
123
    , receivedParameter_("")
124
    , rPort_(-1)
125
    , via_addr_()
126
    , presence_(new SIPPresence(this))
127
    , audioPortRange_({16384, 32766})
128
#ifdef SFL_VIDEO
129
    , videoPortRange_({49152, (MAX_PORT) - 2})
130
#endif
131
{
132 133 134 135
    via_addr_.host.ptr = 0;
    via_addr_.host.slen = 0;
    via_addr_.port = 0;

136 137 138
    if (isIP2IP())
        alias_ = IP2IP_PROFILE;
}
yanmorin's avatar
 
yanmorin committed
139

140

141 142 143 144 145
SIPAccount::~SIPAccount()
{
    delete presence_;
}

146

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
namespace {
std::array<std::unique_ptr<Conf::ScalarNode>, 2>
serializeRange(Conf::MappingNode &accountMap, const char *minKey, const char *maxKey, const std::pair<uint16_t, uint16_t> &range)
{
    using namespace Conf;
    std::array<std::unique_ptr<ScalarNode>, 2> result;

    std::ostringstream os;
    os << range.first;
    result[0].reset(new ScalarNode(os.str()));
    os.str("");
    accountMap.setKeyValue(minKey, result[0].get());

    os << range.second;
    ScalarNode portMax(os.str());
    result[1].reset(new ScalarNode(os.str()));
    accountMap.setKeyValue(maxKey, result[1].get());
    return result;
}

167 168 169 170 171 172 173 174 175

void updateRange(int min, int max, std::pair<uint16_t, uint16_t> &range)
{
    if (min > 0 and (max > min) and max <= MAX_PORT - 2) {
        range.first = min;
        range.second = max;
    }
}

176 177 178
void
unserializeRange(const Conf::YamlNode &mapNode, const char *minKey, const char *maxKey, std::pair<uint16_t, uint16_t> &range)
{
179 180 181 182 183
    int tmpMin = 0;
    int tmpMax = 0;
    mapNode.getValue(minKey, &tmpMin);
    mapNode.getValue(maxKey, &tmpMax);
    updateRange(tmpMin, tmpMax, range);
184 185 186 187
}
}


188

189
void SIPAccount::serialize(Conf::YamlEmitter &emitter)
Julien Bonjean's avatar
Julien Bonjean committed
190
{
191
    using namespace Conf;
Tristan Matthews's avatar
Tristan Matthews committed
192 193
    using std::vector;
    using std::string;
194
    using std::map;
195 196 197 198 199 200 201 202 203 204
    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_);
205
    ScalarNode autoAnswer(autoAnswerEnabled_);
206
    ScalarNode type(ACCOUNT_TYPE);
207 208
    std::stringstream registrationExpireStr;
    registrationExpireStr << registrationExpire_;
209
    ScalarNode expire(registrationExpireStr.str());
210
    ScalarNode interface(interface_);
Julien Bonjean's avatar
Julien Bonjean committed
211
    std::stringstream portstr;
212
    portstr << localPort_;
213 214
    ScalarNode port(portstr.str());
    ScalarNode serviceRoute(serviceRoute_);
215
    ScalarNode keepAliveEnabled(keepAliveEnabled_);
Julien Bonjean's avatar
Julien Bonjean committed
216

217 218
    ScalarNode mailbox(mailBox_);
    ScalarNode publishAddr(publishedIpAddress_);
Julien Bonjean's avatar
Julien Bonjean committed
219
    std::stringstream publicportstr;
220
    publicportstr << publishedPort_;
221

222
    ScalarNode publishPort(publicportstr.str());
223

224
    ScalarNode sameasLocal(publishedSameasLocal_);
225
    ScalarNode audioCodecs(audioCodecStr_);
226
#ifdef SFL_VIDEO
227 228
    SequenceNode videoCodecs(NULL);
    accountmap.setKeyValue(VIDEO_CODECS_KEY, &videoCodecs);
229

230
    for (auto &codec : videoCodecList_) {
231 232 233 234
        MappingNode *mapNode = new MappingNode(NULL);
        mapNode->setKeyValue(VIDEO_CODEC_NAME, new ScalarNode(codec[VIDEO_CODEC_NAME]));
        mapNode->setKeyValue(VIDEO_CODEC_BITRATE, new ScalarNode(codec[VIDEO_CODEC_BITRATE]));
        mapNode->setKeyValue(VIDEO_CODEC_ENABLED, new ScalarNode(codec[VIDEO_CODEC_ENABLED]));
235
        mapNode->setKeyValue(VIDEO_CODEC_PARAMETERS, new ScalarNode(codec[VIDEO_CODEC_PARAMETERS]));
236 237
        videoCodecs.addNode(mapNode);
    }
238

239
#endif
240

241 242 243 244 245 246
    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
247 248 249

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

252 253 254
    ScalarNode srtpenabled(srtpEnabled_);
    ScalarNode keyExchange(srtpKeyExchange_);
    ScalarNode rtpFallback(srtpFallback_);
Julien Bonjean's avatar
Julien Bonjean committed
255

256 257 258 259
    ScalarNode displaySas(zrtpDisplaySas_);
    ScalarNode displaySasOnce(zrtpDisplaySasOnce_);
    ScalarNode helloHashEnabled(zrtpHelloHash_);
    ScalarNode notSuppWarning(zrtpNotSuppWarning_);
Julien Bonjean's avatar
Julien Bonjean committed
260

Rafaël Carré's avatar
Rafaël Carré committed
261
    portstr.str("");
262
    portstr << tlsListenerPort_;
263 264 265
    ScalarNode tlsport(portstr.str());
    ScalarNode certificate(tlsCertificateFile_);
    ScalarNode calist(tlsCaListFile_);
266
    ScalarNode ciphersNode(tlsCiphers_);
267 268 269 270 271 272 273 274 275
    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_);
276

277 278 279 280 281 282
    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);
283
    accountmap.setKeyValue(ACCOUNT_AUTOANSWER_KEY, &autoAnswer);
284
    accountmap.setKeyValue(MAILBOX_KEY, &mailbox);
285
    accountmap.setKeyValue(Preferences::REGISTRATION_EXPIRE_KEY, &expire);
286 287 288 289 290 291 292 293 294 295
    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(DTMF_TYPE_KEY, &dtmfType);
    accountmap.setKeyValue(DISPLAY_NAME_KEY, &displayName);
296
    accountmap.setKeyValue(AUDIO_CODECS_KEY, &audioCodecs);
297 298
    accountmap.setKeyValue(RINGTONE_PATH_KEY, &ringtonePath);
    accountmap.setKeyValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled);
299
    accountmap.setKeyValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled);
300

301 302 303 304
    accountmap.setKeyValue(SRTP_KEY, &srtpmap);
    srtpmap.setKeyValue(SRTP_ENABLE_KEY, &srtpenabled);
    srtpmap.setKeyValue(KEY_EXCHANGE_KEY, &keyExchange);
    srtpmap.setKeyValue(RTP_FALLBACK_KEY, &rtpFallback);
305

306 307 308 309 310
    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);
311

312
    SequenceNode credentialseq(NULL);
313
    accountmap.setKeyValue(CRED_KEY, &credentialseq);
314

315 316
    for (const auto &it : credentials_) {
        std::map<std::string, std::string> cred = it;
317
        MappingNode *map = new MappingNode(NULL);
318 319 320
        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]));
321 322 323
        credentialseq.addNode(map);
    }

324 325 326 327
    accountmap.setKeyValue(TLS_KEY, &tlsmap);
    tlsmap.setKeyValue(TLS_PORT_KEY, &tlsport);
    tlsmap.setKeyValue(CERTIFICATE_KEY, &certificate);
    tlsmap.setKeyValue(CALIST_KEY, &calist);
328
    tlsmap.setKeyValue(CIPHERS_KEY, &ciphersNode);
329 330 331 332 333 334 335 336 337
    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
338

339 340 341
    ScalarNode userAgent(userAgent_);
    accountmap.setKeyValue(USER_AGENT_KEY, &userAgent);

342
    auto audioPortNodes(serializeRange(accountmap, AUDIO_PORT_MIN_KEY, AUDIO_PORT_MAX_KEY, audioPortRange_));
343
#ifdef SFL_VIDEO
344
    auto videoPortNodes(serializeRange(accountmap, VIDEO_PORT_MIN_KEY, VIDEO_PORT_MAX_KEY, videoPortRange_));
345 346
#endif

Julien Bonjean's avatar
Julien Bonjean committed
347
    try {
348
        emitter.serializeAccount(&accountmap);
349
    } catch (const YamlEmitterException &e) {
350
        ERROR("%s", e.what());
Julien Bonjean's avatar
Julien Bonjean committed
351
    }
352

353 354
    // Cleanup
    Sequence *credSeq = credentialseq.getSequence();
355

356 357
    for (const auto &seqit : *credSeq) {
        MappingNode *node = static_cast<MappingNode*>(seqit);
358 359 360
        delete node->getValue(CONFIG_ACCOUNT_USERNAME);
        delete node->getValue(CONFIG_ACCOUNT_PASSWORD);
        delete node->getValue(CONFIG_ACCOUNT_REALM);
361
        delete node;
362
    }
363 364 365

#ifdef SFL_VIDEO
    Sequence *videoCodecSeq = videoCodecs.getSequence();
366

367 368
    for (auto &i : *videoCodecSeq) {
        MappingNode *node = static_cast<MappingNode*>(i);
369 370 371
        delete node->getValue(VIDEO_CODEC_NAME);
        delete node->getValue(VIDEO_CODEC_BITRATE);
        delete node->getValue(VIDEO_CODEC_ENABLED);
372
        delete node->getValue(VIDEO_CODEC_PARAMETERS);
373 374
        delete node;
    }
375

376
#endif
377
}
378

379 380 381 382 383 384 385
void SIPAccount::usePublishedAddressPortInVIA()
{
    via_addr_.host.ptr = (char *) publishedIpAddress_.c_str();
    via_addr_.host.slen = publishedIpAddress_.size();
    via_addr_.port = publishedPort_;
}

386
void SIPAccount::unserialize(const Conf::YamlNode &mapNode)
387
{
388
    using namespace Conf;
389 390 391
    using std::vector;
    using std::map;
    using std::string;
Julien Bonjean's avatar
Julien Bonjean committed
392

393 394
    mapNode.getValue(ALIAS_KEY, &alias_);
    mapNode.getValue(USERNAME_KEY, &username_);
395

396
    if (not isIP2IP()) mapNode.getValue(HOSTNAME_KEY, &hostname_);
397

398
    mapNode.getValue(ACCOUNT_ENABLE_KEY, &enabled_);
399
    mapNode.getValue(ACCOUNT_AUTOANSWER_KEY, &autoAnswerEnabled_);
400

401
    if (not isIP2IP()) mapNode.getValue(MAILBOX_KEY, &mailBox_);
402

403
    mapNode.getValue(AUDIO_CODECS_KEY, &audioCodecStr_);
404
    // Update codec list which one is used for SDP offer
405
    setActiveAudioCodecs(split_string(audioCodecStr_));
406
#ifdef SFL_VIDEO
407 408
    YamlNode *videoCodecsNode(mapNode.getValue(VIDEO_CODECS_KEY));

409
    if (videoCodecsNode and videoCodecsNode->getType() == SEQUENCE) {
410 411
        SequenceNode *videoCodecs = static_cast<SequenceNode *>(videoCodecsNode);
        Sequence *seq = videoCodecs->getSequence();
412

413
        if (seq->empty()) {
414
            // Video codecs are an empty list
415
            WARN("Loading default video codecs");
416
            videoCodecList_ = libav_utils::getDefaultCodecs();
417
        } else {
418
            vector<map<string, string> > videoCodecDetails;
419

420 421
            for (auto it : *seq) {
                MappingNode *codec = static_cast<MappingNode *>(it);
422 423 424 425
                map<string, string> codecMap;
                codec->getValue(VIDEO_CODEC_NAME, &codecMap[VIDEO_CODEC_NAME]);
                codec->getValue(VIDEO_CODEC_BITRATE, &codecMap[VIDEO_CODEC_BITRATE]);
                codec->getValue(VIDEO_CODEC_ENABLED, &codecMap[VIDEO_CODEC_ENABLED]);
426
                codec->getValue(VIDEO_CODEC_PARAMETERS, &codecMap[VIDEO_CODEC_PARAMETERS]);
427 428
                videoCodecDetails.push_back(codecMap);
            }
429

430
            // these must be validated
431
            setVideoCodecs(videoCodecDetails);
432
        }
433 434 435 436
    } else {
        // either this is an older config file which had videoCodecs as a scalar node,
        // or it had no video codecs at all
        WARN("Loading default video codecs");
437
        videoCodecList_ = libav_utils::getDefaultCodecs();
438
    }
439

440
#endif
441

442 443
    mapNode.getValue(RINGTONE_PATH_KEY, &ringtonePath_);
    mapNode.getValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled_);
444

445
    if (not isIP2IP()) mapNode.getValue(Preferences::REGISTRATION_EXPIRE_KEY, &registrationExpire_);
446

447
    mapNode.getValue(INTERFACE_KEY, &interface_);
448
    int port = DEFAULT_SIP_PORT;
449
    mapNode.getValue(PORT_KEY, &port);
450
    localPort_ = port;
451 452
    mapNode.getValue(PUBLISH_ADDR_KEY, &publishedIpAddress_);
    mapNode.getValue(PUBLISH_PORT_KEY, &port);
453
    publishedPort_ = port;
454
    mapNode.getValue(SAME_AS_LOCAL_KEY, &publishedSameasLocal_);
455

456 457 458
    if (not publishedSameasLocal_)
        usePublishedAddressPortInVIA();

459
    if (not isIP2IP()) mapNode.getValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled_);
460 461

    std::string dtmfType;
462
    mapNode.getValue(DTMF_TYPE_KEY, &dtmfType);
463
    dtmfType_ = dtmfType;
464

465
    if (not isIP2IP()) mapNode.getValue(SERVICE_ROUTE_KEY, &serviceRoute_);
466

Julien Bonjean's avatar
Julien Bonjean committed
467
    // stun enabled
468
    if (not isIP2IP()) mapNode.getValue(STUN_ENABLED_KEY, &stunEnabled_);
469

470
    if (not isIP2IP()) mapNode.getValue(STUN_SERVER_KEY, &stunServer_);
Julien Bonjean's avatar
Julien Bonjean committed
471

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

475
    mapNode.getValue(DISPLAY_NAME_KEY, &displayName_);
476

477 478
    std::vector<std::map<std::string, std::string> > creds;

479
    YamlNode *credNode = mapNode.getValue(CRED_KEY);
480 481 482 483 484

    /* We check if the credential key is a sequence
     * because it was a mapping in a previous version of
     * the configuration file.
     */
485
    if (credNode && credNode->getType() == SEQUENCE) {
486
        SequenceNode *credSeq = static_cast<SequenceNode *>(credNode);
487
        Sequence *seq = credSeq->getSequence();
488

489 490
        for (auto it : *seq) {
            MappingNode *cred = static_cast<MappingNode *>(it);
491 492 493
            std::string user;
            std::string pass;
            std::string realm;
494 495 496
            cred->getValue(CONFIG_ACCOUNT_USERNAME, &user);
            cred->getValue(CONFIG_ACCOUNT_PASSWORD, &pass);
            cred->getValue(CONFIG_ACCOUNT_REALM, &realm);
497
            std::map<std::string, std::string> credentialMap;
498 499 500
            credentialMap[CONFIG_ACCOUNT_USERNAME] = user;
            credentialMap[CONFIG_ACCOUNT_PASSWORD] = pass;
            credentialMap[CONFIG_ACCOUNT_REALM] = realm;
501 502 503 504
            creds.push_back(credentialMap);
        }
    }

505
    if (creds.empty()) {
506 507 508
        // migration from old file format
        std::map<std::string, std::string> credmap;
        std::string password;
509

510
        if (not isIP2IP()) mapNode.getValue(PASSWORD_KEY, &password);
511

512 513 514
        credmap[CONFIG_ACCOUNT_USERNAME] = username_;
        credmap[CONFIG_ACCOUNT_PASSWORD] = password;
        credmap[CONFIG_ACCOUNT_REALM] = "*";
515
        creds.push_back(credmap);
516
    }
517 518

    setCredentials(creds);
Julien Bonjean's avatar
Julien Bonjean committed
519 520

    // get srtp submap
521
    MappingNode *srtpMap = static_cast<MappingNode *>(mapNode.getValue(SRTP_KEY));
522

523
    if (srtpMap) {
524 525 526
        srtpMap->getValue(SRTP_ENABLE_KEY, &srtpEnabled_);
        srtpMap->getValue(KEY_EXCHANGE_KEY, &srtpKeyExchange_);
        srtpMap->getValue(RTP_FALLBACK_KEY, &srtpFallback_);
527
    }
Julien Bonjean's avatar
Julien Bonjean committed
528 529

    // get zrtp submap
530
    MappingNode *zrtpMap = static_cast<MappingNode *>(mapNode.getValue(ZRTP_KEY));
531

532
    if (zrtpMap) {
533 534 535 536
        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_);
537
    }
Julien Bonjean's avatar
Julien Bonjean committed
538 539

    // get tls submap
540
    MappingNode *tlsMap = static_cast<MappingNode *>(mapNode.getValue(TLS_KEY));
541

542
    if (tlsMap) {
543
        tlsMap->getValue(TLS_ENABLE_KEY, &tlsEnable_);
544 545 546
        std::string tlsPort;
        tlsMap->getValue(TLS_PORT_KEY, &tlsPort);
        tlsListenerPort_ = atoi(tlsPort.c_str());
547 548 549 550 551 552 553 554 555 556
        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_);
557
        // FIXME
558 559
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutSec_);
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutMsec_);
560
    }
561
    mapNode.getValue(USER_AGENT_KEY, &userAgent_);
562 563 564 565 566

    unserializeRange(mapNode, AUDIO_PORT_MIN_KEY, AUDIO_PORT_MAX_KEY, audioPortRange_);
#ifdef SFL_VIDEO
    unserializeRange(mapNode, VIDEO_PORT_MIN_KEY, VIDEO_PORT_MAX_KEY, videoPortRange_);
#endif
567 568
}

569
void SIPAccount::setAccountDetails(std::map<std::string, std::string> details)
570
{
Julien Bonjean's avatar
Julien Bonjean committed
571
    // Account setting common to SIP and IAX
572
    alias_ = details[CONFIG_ACCOUNT_ALIAS];
573 574
    username_ = details[CONFIG_ACCOUNT_USERNAME];
    hostname_ = details[CONFIG_ACCOUNT_HOSTNAME];
575 576
    enabled_ = details[CONFIG_ACCOUNT_ENABLE] == TRUE_STR;
    autoAnswerEnabled_ = details[CONFIG_ACCOUNT_AUTOANSWER] == TRUE_STR;
577
    ringtonePath_ = details[CONFIG_RINGTONE_PATH];
578
    ringtoneEnabled_ = details[CONFIG_RINGTONE_ENABLED] == TRUE_STR;
579
    mailBox_ = details[CONFIG_ACCOUNT_MAILBOX];
Julien Bonjean's avatar
Julien Bonjean committed
580 581

    // SIP specific account settings
582 583

    // general sip settings
584 585 586
    displayName_ = details[CONFIG_DISPLAY_NAME];
    serviceRoute_ = details[CONFIG_ACCOUNT_ROUTESET];
    interface_ = details[CONFIG_LOCAL_INTERFACE];
587
    publishedSameasLocal_ = details[CONFIG_PUBLISHED_SAMEAS_LOCAL] == TRUE_STR;
588 589 590
    publishedIpAddress_ = details[CONFIG_PUBLISHED_ADDRESS];
    localPort_ = atoi(details[CONFIG_LOCAL_PORT].c_str());
    publishedPort_ = atoi(details[CONFIG_PUBLISHED_PORT].c_str());
591

592 593 594
    if (not publishedSameasLocal_)
        usePublishedAddressPortInVIA();

Tristan Matthews's avatar
Tristan Matthews committed
595
    if (stunServer_ != details[CONFIG_STUN_SERVER]) {
596
        link_->sipTransport.destroyStunResolver(stunServer_);
597 598
        // pj_stun_sock_destroy(pj_stun_sock *stun_sock);
    }
599

600
    stunServer_ = details[CONFIG_STUN_SERVER];
601
    stunEnabled_ = details[CONFIG_STUN_ENABLE] == TRUE_STR;
602
    dtmfType_ = details[CONFIG_ACCOUNT_DTMF_TYPE];
Rafaël Carré's avatar
Rafaël Carré committed
603
    registrationExpire_ = atoi(details[CONFIG_ACCOUNT_REGISTRATION_EXPIRE].c_str());
604 605

    if (registrationExpire_ < MIN_REGISTRATION_TIME)
606
        registrationExpire_ = MIN_REGISTRATION_TIME;
607

608
    userAgent_ = details[CONFIG_ACCOUNT_USERAGENT];
609
    keepAliveEnabled_ = details[CONFIG_KEEP_ALIVE_ENABLED] == TRUE_STR;
610

611 612 613
    int tmpMin = atoi(details[CONFIG_ACCOUNT_AUDIO_PORT_MIN].c_str());
    int tmpMax = atoi(details[CONFIG_ACCOUNT_AUDIO_PORT_MAX].c_str());
    updateRange(tmpMin, tmpMax, audioPortRange_);
614
#ifdef SFL_VIDEO
615 616 617
    tmpMin = atoi(details[CONFIG_ACCOUNT_VIDEO_PORT_MIN].c_str());
    tmpMax = atoi(details[CONFIG_ACCOUNT_VIDEO_PORT_MAX].c_str());
    updateRange(tmpMin, tmpMax, videoPortRange_);
618 619
#endif

620 621
    enablePresence(details[CONFIG_PRESENCE_ENABLED] == TRUE_STR);

622
    // srtp settings
623 624 625 626 627 628
    srtpEnabled_ = details[CONFIG_SRTP_ENABLE] == TRUE_STR;
    srtpFallback_ = details[CONFIG_SRTP_RTP_FALLBACK] == TRUE_STR;
    zrtpDisplaySas_ = details[CONFIG_ZRTP_DISPLAY_SAS] == TRUE_STR;
    zrtpDisplaySasOnce_ = details[CONFIG_ZRTP_DISPLAY_SAS_ONCE] == TRUE_STR;
    zrtpNotSuppWarning_ = details[CONFIG_ZRTP_NOT_SUPP_WARNING] == TRUE_STR;
    zrtpHelloHash_ = details[CONFIG_ZRTP_HELLO_HASH] == TRUE_STR;
629
    srtpKeyExchange_ = details[CONFIG_SRTP_KEY_EXCHANGE];
630 631

    // TLS settings
632
    tlsListenerPort_ = atoi(details[CONFIG_TLS_LISTENER_PORT].c_str());
633 634 635 636 637 638 639 640
    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];
641 642 643
    tlsVerifyServer_ = details[CONFIG_TLS_VERIFY_SERVER] == TRUE_STR;
    tlsVerifyClient_ = details[CONFIG_TLS_VERIFY_CLIENT] == TRUE_STR;
    tlsRequireClientCertificate_ = details[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] == TRUE_STR;
644 645
    tlsNegotiationTimeoutSec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC];
    tlsNegotiationTimeoutMsec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC];
646

647
    if (credentials_.empty()) { // credentials not set, construct 1 entry
648 649
        std::vector<std::map<std::string, std::string> > v;
        std::map<std::string, std::string> map;
650 651 652
        map[CONFIG_ACCOUNT_USERNAME] = username_;
        map[CONFIG_ACCOUNT_PASSWORD] = details[CONFIG_ACCOUNT_PASSWORD];
        map[CONFIG_ACCOUNT_REALM]    = "*";
653 654 655
        v.push_back(map);
        setCredentials(v);
    }
656 657
}

658 659 660 661 662
static std::string retrievePassword(const std::map<std::string, std::string>& map, const std::string &username)
{
    std::map<std::string, std::string>::const_iterator map_iter_username;
    std::map<std::string, std::string>::const_iterator map_iter_password;
    map_iter_username = map.find(CONFIG_ACCOUNT_USERNAME);
663 664 665

    if (map_iter_username != map.end()) {
        if (map_iter_username->second == username) {
666
            map_iter_password = map.find(CONFIG_ACCOUNT_PASSWORD);
667 668

            if (map_iter_password != map.end()) {
669 670 671 672 673 674 675 676
                return map_iter_password->second;
            }
        }
    }

    return "";
}

677 678 679 680 681 682 683 684 685 686 687
void
addRangeToDetails(std::map<std::string, std::string> &a, const char *minKey, const char *maxKey, const std::pair<uint16_t, uint16_t> &range)
{
    std::ostringstream os;
    os << range.first;
    a[minKey] = os.str();
    os.str("");
    os << range.second;
    a[maxKey] = os.str();
}

688
std::map<std::string, std::string> SIPAccount::getAccountDetails() const
689
{
Julien Bonjean's avatar
Julien Bonjean committed
690 691
    std::map<std::string, std::string> a;

692
    a[CONFIG_ACCOUNT_ID] = accountID_;
693 694
    // note: The IP2IP profile will always have IP2IP as an alias
    a[CONFIG_ACCOUNT_ALIAS] = alias_;
Julien Bonjean's avatar
Julien Bonjean committed
695

696
    a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? TRUE_STR : FALSE_STR;
697
    a[CONFIG_ACCOUNT_AUTOANSWER] = autoAnswerEnabled_ ? TRUE_STR : FALSE_STR;
698
    a[CONFIG_ACCOUNT_TYPE] = ACCOUNT_TYPE;
699 700
    a[CONFIG_ACCOUNT_HOSTNAME] = hostname_;
    a[CONFIG_ACCOUNT_USERNAME] = username_;
701 702
    // get password for this username
    a[CONFIG_ACCOUNT_PASSWORD] = "";
703 704 705

    if (hasCredentials()) {

706 707
        for (const auto &vect_item : credentials_) {
            const std::string password = retrievePassword(vect_item, username_);
708 709 710

            if (not password.empty())
                a[CONFIG_ACCOUNT_PASSWORD] = password;
711 712
        }
    }
713

714
    a[CONFIG_RINGTONE_PATH] = ringtonePath_;
715
    a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? TRUE_STR : FALSE_STR;
716
    a[CONFIG_ACCOUNT_MAILBOX] = mailBox_;
717
    a[CONFIG_PRESENCE_ENABLED] = getPresence()->isEnabled()? TRUE_STR : FALSE_STR;
718

719
    RegistrationState state = UNREGISTERED;
Julien Bonjean's avatar
Julien Bonjean committed
720 721 722
    std::string registrationStateCode;
    std::string registrationStateDescription;

723
    if (isIP2IP())
Julien Bonjean's avatar
Julien Bonjean committed
724
        registrationStateDescription = "Direct IP call";
725 726
    else {
        state = registrationState_;
727
        int code = registrationStateDetailed_.first;
Julien Bonjean's avatar
Julien Bonjean committed
728 729 730
        std::stringstream out;
        out << code;
        registrationStateCode = out.str();
731
        registrationStateDescription = registrationStateDetailed_.second;
Julien Bonjean's avatar
Julien Bonjean committed
732 733
    }

734
    a[CONFIG_ACCOUNT_REGISTRATION_STATUS] = isIP2IP() ? "READY" : mapStateNumberToString(state);
735 736
    a[CONFIG_ACCOUNT_REGISTRATION_STATE_CODE] = registrationStateCode;
    a[CONFIG_ACCOUNT_REGISTRATION_STATE_DESC] = registrationStateDescription;
Julien Bonjean's avatar
Julien Bonjean committed
737 738

    // Add sip specific details
739 740
    a[CONFIG_ACCOUNT_ROUTESET] = serviceRoute_;
    a[CONFIG_ACCOUNT_USERAGENT] = userAgent_;
741

742 743 744 745 746
    addRangeToDetails(a, CONFIG_ACCOUNT_AUDIO_PORT_MIN, CONFIG_ACCOUNT_AUDIO_PORT_MAX, audioPortRange_);
#ifdef SFL_VIDEO
    addRangeToDetails(a, CONFIG_ACCOUNT_VIDEO_PORT_MIN, CONFIG_ACCOUNT_VIDEO_PORT_MAX, videoPortRange_);
#endif

747 748 749
    std::stringstream registrationExpireStr;
    registrationExpireStr << registrationExpire_;
    a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = registrationExpireStr.str();
750
    a[CONFIG_LOCAL_INTERFACE] = interface_;
751
    a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? TRUE_STR : FALSE_STR;
752
    a[CONFIG_PUBLISHED_ADDRESS] = publishedIpAddress_;
753 754

    std::stringstream localport;
755
    localport << localPort_;
756
    a[CONFIG_LOCAL_PORT] = localport.str();
757
    std::stringstream publishedport;
758
    publishedport << publishedPort_;
759
    a[CONFIG_PUBLISHED_PORT] = publishedport.str();