sipaccount.cpp 45.7 KB
Newer Older
yanmorin's avatar
 
yanmorin committed
1
/*
2
 *  Copyright (C) 2004-2012 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 "sip_utils.h"
40
#include "sipvoiplink.h"
41
42
#include "config/yamlnode.h"
#include "config/yamlemitter.h"
43
#include "logger.h"
yanmorin's avatar
   
yanmorin committed
44
#include "manager.h"
45
#include <unistd.h>
46
#include <pwd.h>
47
#include <sstream>
48
49
#include <algorithm>
#include <cstdlib>
50

51
52
53
54
#ifdef SFL_VIDEO
#include "video/libav_utils.h"
#endif

55
const char * const SIPAccount::IP2IP_PROFILE = "IP2IP";
56
57
const char * const SIPAccount::OVERRTP_STR = "overrtp";
const char * const SIPAccount::SIPINFO_STR = "sipinfo";
58
const char * const SIPAccount::ACCOUNT_TYPE = "SIP";
59

60
namespace {
61
62
63
64
const int MIN_REGISTRATION_TIME = 60;
const int DEFAULT_REGISTRATION_TIME = 3600;
const char *const TRUE_STR = "true";
const char *const FALSE_STR = "false";
65
66
}

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

127
128
129
    if (isIP2IP())
        alias_ = IP2IP_PROFILE;
}
yanmorin's avatar
 
yanmorin committed
130

131
void SIPAccount::serialize(Conf::YamlEmitter &emitter)
Julien Bonjean's avatar
Julien Bonjean committed
132
{
133
    using namespace Conf;
Tristan Matthews's avatar
Tristan Matthews committed
134
135
    using std::vector;
    using std::string;
136
    using std::map;
137
138
139
140
141
142
143
144
145
146
    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_);
147
    ScalarNode autoAnswer(autoAnswerEnabled_);
148
    ScalarNode type(ACCOUNT_TYPE);
149
150
    std::stringstream registrationExpireStr;
    registrationExpireStr << registrationExpire_;
151
    ScalarNode expire(registrationExpireStr.str());
152
    ScalarNode interface(interface_);
Julien Bonjean's avatar
Julien Bonjean committed
153
    std::stringstream portstr;
154
    portstr << localPort_;
155
156
    ScalarNode port(portstr.str());
    ScalarNode serviceRoute(serviceRoute_);
157
    ScalarNode keepAliveEnabled(keepAliveEnabled_);
Julien Bonjean's avatar
Julien Bonjean committed
158

159
160
    ScalarNode mailbox(mailBox_);
    ScalarNode publishAddr(publishedIpAddress_);
Julien Bonjean's avatar
Julien Bonjean committed
161
    std::stringstream publicportstr;
162
    publicportstr << publishedPort_;
163

164
    ScalarNode publishPort(publicportstr.str());
165

166
    ScalarNode sameasLocal(publishedSameasLocal_);
167
    ScalarNode audioCodecs(audioCodecStr_);
168
#ifdef SFL_VIDEO
169
170
    SequenceNode videoCodecs(NULL);
    accountmap.setKeyValue(VIDEO_CODECS_KEY, &videoCodecs);
171

172
    for (auto &codec : videoCodecList_) {
173
174
175
176
        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]));
177
        mapNode->setKeyValue(VIDEO_CODEC_PARAMETERS, new ScalarNode(codec[VIDEO_CODEC_PARAMETERS]));
178
179
        videoCodecs.addNode(mapNode);
    }
180

181
#endif
182

183
184
185
186
187
188
    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
189
190
191

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

194
195
196
    ScalarNode srtpenabled(srtpEnabled_);
    ScalarNode keyExchange(srtpKeyExchange_);
    ScalarNode rtpFallback(srtpFallback_);
Julien Bonjean's avatar
Julien Bonjean committed
197

198
199
200
201
    ScalarNode displaySas(zrtpDisplaySas_);
    ScalarNode displaySasOnce(zrtpDisplaySasOnce_);
    ScalarNode helloHashEnabled(zrtpHelloHash_);
    ScalarNode notSuppWarning(zrtpNotSuppWarning_);
Julien Bonjean's avatar
Julien Bonjean committed
202

Rafaël Carré's avatar
Rafaël Carré committed
203
    portstr.str("");
204
    portstr << tlsListenerPort_;
205
206
207
    ScalarNode tlsport(portstr.str());
    ScalarNode certificate(tlsCertificateFile_);
    ScalarNode calist(tlsCaListFile_);
208
    ScalarNode ciphersNode(tlsCiphers_);
209
210
211
212
213
214
215
216
217
    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_);
218

219
220
221
222
223
224
    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);
225
    accountmap.setKeyValue(ACCOUNT_AUTOANSWER_KEY, &autoAnswer);
226
    accountmap.setKeyValue(MAILBOX_KEY, &mailbox);
227
    accountmap.setKeyValue(Preferences::REGISTRATION_EXPIRE_KEY, &expire);
228
229
230
231
232
233
234
235
236
237
    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);
238
    accountmap.setKeyValue(AUDIO_CODECS_KEY, &audioCodecs);
239
240
    accountmap.setKeyValue(RINGTONE_PATH_KEY, &ringtonePath);
    accountmap.setKeyValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled);
241
    accountmap.setKeyValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled);
242

243
244
245
246
    accountmap.setKeyValue(SRTP_KEY, &srtpmap);
    srtpmap.setKeyValue(SRTP_ENABLE_KEY, &srtpenabled);
    srtpmap.setKeyValue(KEY_EXCHANGE_KEY, &keyExchange);
    srtpmap.setKeyValue(RTP_FALLBACK_KEY, &rtpFallback);
247

248
249
250
251
252
    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);
253

254
    SequenceNode credentialseq(NULL);
255
    accountmap.setKeyValue(CRED_KEY, &credentialseq);
256

257
258
    for (const auto &it : credentials_) {
        std::map<std::string, std::string> cred = it;
259
        MappingNode *map = new MappingNode(NULL);
260
261
262
        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]));
263
264
265
        credentialseq.addNode(map);
    }

266
267
268
269
    accountmap.setKeyValue(TLS_KEY, &tlsmap);
    tlsmap.setKeyValue(TLS_PORT_KEY, &tlsport);
    tlsmap.setKeyValue(CERTIFICATE_KEY, &certificate);
    tlsmap.setKeyValue(CALIST_KEY, &calist);
270
    tlsmap.setKeyValue(CIPHERS_KEY, &ciphersNode);
271
272
273
274
275
276
277
278
279
    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
280

281
282
283
    ScalarNode userAgent(userAgent_);
    accountmap.setKeyValue(USER_AGENT_KEY, &userAgent);

Julien Bonjean's avatar
Julien Bonjean committed
284
    try {
285
        emitter.serializeAccount(&accountmap);
286
    } catch (const YamlEmitterException &e) {
287
        ERROR("%s", e.what());
Julien Bonjean's avatar
Julien Bonjean committed
288
    }
289

290
291
    // Cleanup
    Sequence *credSeq = credentialseq.getSequence();
292

293
294
    for (const auto &seqit : *credSeq) {
        MappingNode *node = static_cast<MappingNode*>(seqit);
295
296
297
        delete node->getValue(CONFIG_ACCOUNT_USERNAME);
        delete node->getValue(CONFIG_ACCOUNT_PASSWORD);
        delete node->getValue(CONFIG_ACCOUNT_REALM);
298
        delete node;
299
    }
300
301
302

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

304
305
    for (auto &i : *videoCodecSeq) {
        MappingNode *node = static_cast<MappingNode*>(i);
306
307
308
        delete node->getValue(VIDEO_CODEC_NAME);
        delete node->getValue(VIDEO_CODEC_BITRATE);
        delete node->getValue(VIDEO_CODEC_ENABLED);
309
        delete node->getValue(VIDEO_CODEC_PARAMETERS);
310
311
        delete node;
    }
312

313
#endif
314
}
315

316
void SIPAccount::unserialize(const Conf::YamlNode &mapNode)
317
{
318
    using namespace Conf;
319
320
321
    using std::vector;
    using std::map;
    using std::string;
Julien Bonjean's avatar
Julien Bonjean committed
322

323
324
    mapNode.getValue(ALIAS_KEY, &alias_);
    mapNode.getValue(USERNAME_KEY, &username_);
325

326
    if (not isIP2IP()) mapNode.getValue(HOSTNAME_KEY, &hostname_);
327

328
    mapNode.getValue(ACCOUNT_ENABLE_KEY, &enabled_);
329
    mapNode.getValue(ACCOUNT_AUTOANSWER_KEY, &autoAnswerEnabled_);
330

331
    if (not isIP2IP()) mapNode.getValue(MAILBOX_KEY, &mailBox_);
332

333
    mapNode.getValue(AUDIO_CODECS_KEY, &audioCodecStr_);
334
    // Update codec list which one is used for SDP offer
335
    setActiveAudioCodecs(split_string(audioCodecStr_));
336
#ifdef SFL_VIDEO
337
338
    YamlNode *videoCodecsNode(mapNode.getValue(VIDEO_CODECS_KEY));

339
    if (videoCodecsNode and videoCodecsNode->getType() == SEQUENCE) {
340
341
        SequenceNode *videoCodecs = static_cast<SequenceNode *>(videoCodecsNode);
        Sequence *seq = videoCodecs->getSequence();
342

343
        if (seq->empty()) {
344
            // Video codecs are an empty list
345
            WARN("Loading default video codecs");
346
            videoCodecList_ = libav_utils::getDefaultCodecs();
347
        } else {
348
            vector<map<string, string> > videoCodecDetails;
349

350
351
            for (auto it : *seq) {
                MappingNode *codec = static_cast<MappingNode *>(it);
352
353
354
355
                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]);
356
                codec->getValue(VIDEO_CODEC_PARAMETERS, &codecMap[VIDEO_CODEC_PARAMETERS]);
357
358
                videoCodecDetails.push_back(codecMap);
            }
359

360
            // these must be validated
361
            setVideoCodecs(videoCodecDetails);
362
        }
363
364
365
366
    } 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");
367
        videoCodecList_ = libav_utils::getDefaultCodecs();
368
    }
369

370
#endif
371

372
373
    mapNode.getValue(RINGTONE_PATH_KEY, &ringtonePath_);
    mapNode.getValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled_);
374

375
    if (not isIP2IP()) mapNode.getValue(Preferences::REGISTRATION_EXPIRE_KEY, &registrationExpire_);
376

377
    mapNode.getValue(INTERFACE_KEY, &interface_);
378
    int port = DEFAULT_SIP_PORT;
379
    mapNode.getValue(PORT_KEY, &port);
380
    localPort_ = port;
381
382
    mapNode.getValue(PUBLISH_ADDR_KEY, &publishedIpAddress_);
    mapNode.getValue(PUBLISH_PORT_KEY, &port);
383
    publishedPort_ = port;
384
    mapNode.getValue(SAME_AS_LOCAL_KEY, &publishedSameasLocal_);
385

386
    if (not isIP2IP()) mapNode.getValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled_);
387
388

    std::string dtmfType;
389
    mapNode.getValue(DTMF_TYPE_KEY, &dtmfType);
390
    dtmfType_ = dtmfType;
391

392
    if (not isIP2IP()) mapNode.getValue(SERVICE_ROUTE_KEY, &serviceRoute_);
393

Julien Bonjean's avatar
Julien Bonjean committed
394
    // stun enabled
395
    if (not isIP2IP()) mapNode.getValue(STUN_ENABLED_KEY, &stunEnabled_);
396

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

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

402
    mapNode.getValue(DISPLAY_NAME_KEY, &displayName_);
403

404
405
    std::vector<std::map<std::string, std::string> > creds;

406
    YamlNode *credNode = mapNode.getValue(CRED_KEY);
407
408
409
410
411

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

416
417
        for (auto it : *seq) {
            MappingNode *cred = static_cast<MappingNode *>(it);
418
419
420
            std::string user;
            std::string pass;
            std::string realm;
421
422
423
            cred->getValue(CONFIG_ACCOUNT_USERNAME, &user);
            cred->getValue(CONFIG_ACCOUNT_PASSWORD, &pass);
            cred->getValue(CONFIG_ACCOUNT_REALM, &realm);
424
            std::map<std::string, std::string> credentialMap;
425
426
427
            credentialMap[CONFIG_ACCOUNT_USERNAME] = user;
            credentialMap[CONFIG_ACCOUNT_PASSWORD] = pass;
            credentialMap[CONFIG_ACCOUNT_REALM] = realm;
428
429
430
431
            creds.push_back(credentialMap);
        }
    }

432
    if (creds.empty()) {
433
434
435
        // migration from old file format
        std::map<std::string, std::string> credmap;
        std::string password;
436

437
        if (not isIP2IP()) mapNode.getValue(PASSWORD_KEY, &password);
438

439
440
441
        credmap[CONFIG_ACCOUNT_USERNAME] = username_;
        credmap[CONFIG_ACCOUNT_PASSWORD] = password;
        credmap[CONFIG_ACCOUNT_REALM] = "*";
442
        creds.push_back(credmap);
443
    }
444
445

    setCredentials(creds);
Julien Bonjean's avatar
Julien Bonjean committed
446
447

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

450
    if (srtpMap) {
451
452
453
        srtpMap->getValue(SRTP_ENABLE_KEY, &srtpEnabled_);
        srtpMap->getValue(KEY_EXCHANGE_KEY, &srtpKeyExchange_);
        srtpMap->getValue(RTP_FALLBACK_KEY, &srtpFallback_);
454
    }
Julien Bonjean's avatar
Julien Bonjean committed
455
456

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

459
    if (zrtpMap) {
460
461
462
463
        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_);
464
    }
Julien Bonjean's avatar
Julien Bonjean committed
465
466

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

469
    if (tlsMap) {
470
        tlsMap->getValue(TLS_ENABLE_KEY, &tlsEnable_);
471
472
473
        std::string tlsPort;
        tlsMap->getValue(TLS_PORT_KEY, &tlsPort);
        tlsListenerPort_ = atoi(tlsPort.c_str());
474
475
476
477
478
479
480
481
482
483
        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_);
484
        // FIXME
485
486
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutSec_);
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutMsec_);
487
    }
488
    mapNode.getValue(USER_AGENT_KEY, &userAgent_);
489
490
}

491
void SIPAccount::setAccountDetails(std::map<std::string, std::string> details)
492
{
Julien Bonjean's avatar
Julien Bonjean committed
493
    // Account setting common to SIP and IAX
494
    alias_ = details[CONFIG_ACCOUNT_ALIAS];
495
496
    username_ = details[CONFIG_ACCOUNT_USERNAME];
    hostname_ = details[CONFIG_ACCOUNT_HOSTNAME];
497
498
    enabled_ = details[CONFIG_ACCOUNT_ENABLE] == TRUE_STR;
    autoAnswerEnabled_ = details[CONFIG_ACCOUNT_AUTOANSWER] == TRUE_STR;
499
    ringtonePath_ = details[CONFIG_RINGTONE_PATH];
500
    ringtoneEnabled_ = details[CONFIG_RINGTONE_ENABLED] == TRUE_STR;
501
    mailBox_ = details[CONFIG_ACCOUNT_MAILBOX];
Julien Bonjean's avatar
Julien Bonjean committed
502
503

    // SIP specific account settings
504
505

    // general sip settings
506
507
508
    displayName_ = details[CONFIG_DISPLAY_NAME];
    serviceRoute_ = details[CONFIG_ACCOUNT_ROUTESET];
    interface_ = details[CONFIG_LOCAL_INTERFACE];
509
    publishedSameasLocal_ = details[CONFIG_PUBLISHED_SAMEAS_LOCAL] == TRUE_STR;
510
511
512
    publishedIpAddress_ = details[CONFIG_PUBLISHED_ADDRESS];
    localPort_ = atoi(details[CONFIG_LOCAL_PORT].c_str());
    publishedPort_ = atoi(details[CONFIG_PUBLISHED_PORT].c_str());
513

Tristan Matthews's avatar
Tristan Matthews committed
514
    if (stunServer_ != details[CONFIG_STUN_SERVER]) {
515
        link_->sipTransport.destroyStunResolver(stunServer_);
516
517
        // pj_stun_sock_destroy(pj_stun_sock *stun_sock);
    }
518

519
    stunServer_ = details[CONFIG_STUN_SERVER];
520
    stunEnabled_ = details[CONFIG_STUN_ENABLE] == TRUE_STR;
521
    dtmfType_ = details[CONFIG_ACCOUNT_DTMF_TYPE];
Rafaël Carré's avatar
Rafaël Carré committed
522
    registrationExpire_ = atoi(details[CONFIG_ACCOUNT_REGISTRATION_EXPIRE].c_str());
523
524

    if (registrationExpire_ < MIN_REGISTRATION_TIME)
525
        registrationExpire_ = MIN_REGISTRATION_TIME;
526

527
    userAgent_ = details[CONFIG_ACCOUNT_USERAGENT];
528
    keepAliveEnabled_ = details[CONFIG_KEEP_ALIVE_ENABLED] == TRUE_STR;
529
530

    // srtp settings
531
532
533
534
535
536
    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;
537
    srtpKeyExchange_ = details[CONFIG_SRTP_KEY_EXCHANGE];
538
539

    // TLS settings
540
    tlsListenerPort_ = atoi(details[CONFIG_TLS_LISTENER_PORT].c_str());
541
542
543
544
545
546
547
548
    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];
549
550
551
    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;
552
553
    tlsNegotiationTimeoutSec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC];
    tlsNegotiationTimeoutMsec_ = details[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC];
554

555
    if (credentials_.empty()) { // credentials not set, construct 1 entry
556
557
        std::vector<std::map<std::string, std::string> > v;
        std::map<std::string, std::string> map;
558
559
560
        map[CONFIG_ACCOUNT_USERNAME] = username_;
        map[CONFIG_ACCOUNT_PASSWORD] = details[CONFIG_ACCOUNT_PASSWORD];
        map[CONFIG_ACCOUNT_REALM]    = "*";
561
562
563
        v.push_back(map);
        setCredentials(v);
    }
564
565
}

566
567
568
569
570
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);
571
572
573

    if (map_iter_username != map.end()) {
        if (map_iter_username->second == username) {
574
            map_iter_password = map.find(CONFIG_ACCOUNT_PASSWORD);
575
576

            if (map_iter_password != map.end()) {
577
578
579
580
581
582
583
584
                return map_iter_password->second;
            }
        }
    }

    return "";
}

585
std::map<std::string, std::string> SIPAccount::getAccountDetails() const
586
{
Julien Bonjean's avatar
Julien Bonjean committed
587
588
    std::map<std::string, std::string> a;

589
    a[CONFIG_ACCOUNT_ID] = accountID_;
590
591
    // note: The IP2IP profile will always have IP2IP as an alias
    a[CONFIG_ACCOUNT_ALIAS] = alias_;
Julien Bonjean's avatar
Julien Bonjean committed
592

593
    a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? TRUE_STR : FALSE_STR;
594
    a[CONFIG_ACCOUNT_AUTOANSWER] = autoAnswerEnabled_ ? TRUE_STR : FALSE_STR;
595
    a[CONFIG_ACCOUNT_TYPE] = ACCOUNT_TYPE;
596
597
    a[CONFIG_ACCOUNT_HOSTNAME] = hostname_;
    a[CONFIG_ACCOUNT_USERNAME] = username_;
598
599
    // get password for this username
    a[CONFIG_ACCOUNT_PASSWORD] = "";
600
601
602

    if (hasCredentials()) {

603
604
        for (const auto &vect_item : credentials_) {
            const std::string password = retrievePassword(vect_item, username_);
605
606
607

            if (not password.empty())
                a[CONFIG_ACCOUNT_PASSWORD] = password;
608
609
        }
    }
610

611
    a[CONFIG_RINGTONE_PATH] = ringtonePath_;
612
    a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? TRUE_STR : FALSE_STR;
613
    a[CONFIG_ACCOUNT_MAILBOX] = mailBox_;
614

615
    RegistrationState state = UNREGISTERED;
Julien Bonjean's avatar
Julien Bonjean committed
616
617
618
    std::string registrationStateCode;
    std::string registrationStateDescription;

619
    if (isIP2IP())
Julien Bonjean's avatar
Julien Bonjean committed
620
        registrationStateDescription = "Direct IP call";
621
622
    else {
        state = registrationState_;
623
        int code = registrationStateDetailed_.first;
Julien Bonjean's avatar
Julien Bonjean committed
624
625
626
        std::stringstream out;
        out << code;
        registrationStateCode = out.str();
627
        registrationStateDescription = registrationStateDetailed_.second;
Julien Bonjean's avatar
Julien Bonjean committed
628
629
    }

630
    a[CONFIG_ACCOUNT_REGISTRATION_STATUS] = isIP2IP() ? "READY" : mapStateNumberToString(state);
631
632
    a[CONFIG_ACCOUNT_REGISTRATION_STATE_CODE] = registrationStateCode;
    a[CONFIG_ACCOUNT_REGISTRATION_STATE_DESC] = registrationStateDescription;
Julien Bonjean's avatar
Julien Bonjean committed
633
634

    // Add sip specific details
635
636
    a[CONFIG_ACCOUNT_ROUTESET] = serviceRoute_;
    a[CONFIG_ACCOUNT_USERAGENT] = userAgent_;
637

638
639
640
    std::stringstream registrationExpireStr;
    registrationExpireStr << registrationExpire_;
    a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = registrationExpireStr.str();
641
    a[CONFIG_LOCAL_INTERFACE] = interface_;
642
    a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? TRUE_STR : FALSE_STR;
643
    a[CONFIG_PUBLISHED_ADDRESS] = publishedIpAddress_;
644
645

    std::stringstream localport;
646
    localport << localPort_;
647
    a[CONFIG_LOCAL_PORT] = localport.str();
648
    std::stringstream publishedport;
649
    publishedport << publishedPort_;
650
    a[CONFIG_PUBLISHED_PORT] = publishedport.str();
651
    a[CONFIG_STUN_ENABLE] = stunEnabled_ ? TRUE_STR : FALSE_STR;
652
653
    a[CONFIG_STUN_SERVER] = stunServer_;
    a[CONFIG_ACCOUNT_DTMF_TYPE] = dtmfType_;
654
    a[CONFIG_KEEP_ALIVE_ENABLED] = keepAliveEnabled_ ? TRUE_STR : FALSE_STR;
655

656
    a[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_;
657
658
    a[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? TRUE_STR : FALSE_STR;
    a[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? TRUE_STR : FALSE_STR;
659

660
661
662
663
    a[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? TRUE_STR : FALSE_STR;
    a[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? TRUE_STR : FALSE_STR;
    a[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? TRUE_STR : FALSE_STR;
    a[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? TRUE_STR : FALSE_STR;
664
665
666

    // TLS listener is unique and parameters are modified through IP2IP_PROFILE
    std::stringstream tlslistenerport;
667
    tlslistenerport << tlsListenerPort_;
668
669
670
671
672
673
674
675
676
    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_;
677
678
679
    a[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? TRUE_STR : FALSE_STR;
    a[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? TRUE_STR : FALSE_STR;
    a[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? TRUE_STR : FALSE_STR;
680
681
    a[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_;
    a[CONFIG_TLS_NEGOTIATION_TIMEOUT_MSEC] = tlsNegotiationTimeoutMsec_;
Julien Bonjean's avatar
Julien Bonjean committed
682
683

    return a;
684
685
}

686
void SIPAccount::registerVoIPLink()
Julien Bonjean's avatar
Julien Bonjean committed
687
{
688
689
    if (hostname_.length() >= PJ_MAX_HOSTNAME)
        return;
690

691
#if HAVE_TLS
692

693
    // Init TLS settings if the user wants to use TLS
694
    if (tlsEnable_ == TRUE_STR) {
695
        DEBUG("TLS is enabled for account %s", accountID_.c_str());
696
        transportType_ = PJSIP_TRANSPORT_TLS;
Emmanuel Milou's avatar
Emmanuel Milou committed
697
        initTlsConfiguration();
698
    }
699

700
#endif
701

702
    // Init STUN settings for this account if the user selected it
703
704
    if (stunEnabled_) {
        transportType_ = PJSIP_TRANSPORT_START_OTHER;
705
        initStunConfiguration();
Julien Bonjean's avatar
Julien Bonjean committed
706
    } else {
707
        stunServerName_ = pj_str((char*) stunServer_.c_str());
708
    }
709

710
711
    // In our definition of the ip2ip profile (aka Direct IP Calls),
    // no registration should be performed
712
    if (isIP2IP())
713
        return;
714

715
    try {
716
        link_->sendRegister(this);
717
    } catch (const VoipLinkException &e) {
718
        ERROR("%s", e.what());
719
    }
yanmorin's avatar
 
yanmorin committed
720
721
}

722
void SIPAccount::unregisterVoIPLink()
yanmorin's avatar
 
yanmorin committed
723
{
724
    if (isIP2IP())
725
        return;
Emmanuel Milou's avatar
Emmanuel Milou committed
726

727
    try {
728
729
        link_->sendUnregister(this);
    } catch (const VoipLinkException &e) {
730
        ERROR("%s", e.what());
731
    }
yanmorin's avatar
 
yanmorin committed
732
733
}

734
735
void SIPAccount::startKeepAliveTimer()
{
736
737
738
739

    if (isTlsEnabled())
        return;

740
741
742
    if (isIP2IP())
        return;

743
    if (keepAliveTimerActive_)
744
745
746
        return;

    DEBUG("Start keep alive timer for account %s", getAccountID().c_str());
747

748
749
750
    // make sure here we have an entirely new timer
    memset(&keepAliveTimer_, 0, sizeof(pj_timer_entry));

751
    pj_time_val keepAliveDelay_;
752
    keepAliveTimer_.cb = &SIPAccount::keepAliveRegistrationCb;
753
    keepAliveTimer_.user_data = this;
754
    keepAliveTimer_.id = rand();
755

756
    // expiration may be undetermined during the first registration request
757
    if (registrationExpire_ == 0) {
758
759
        DEBUG("Registration Expire: 0, taking 60 instead");
        keepAliveDelay_.sec = 3600;
760
    } else {
761
762
        DEBUG("Registration Expire: %d", registrationExpire_);
        keepAliveDelay_.sec = registrationExpire_ + MIN_REGISTRATION_TIME;
763
764
    }

765
    keepAliveDelay_.msec = 0;
766

Tristan Matthews's avatar