Project 'savoirfairelinux/ring-daemon' was moved to 'savoirfairelinux/jami-daemon'. Please update any links and bookmarks that may still have the old path.
Select Git revision
account.cpp
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
sipaccount.cpp 40.84 KiB
/*
* Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
*
* 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.
*
* 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.
*/
#include "sipaccount.h"
#include "manager.h"
#include <pwd.h>
#include <sstream>
#include <cassert>
namespace {
const char * const DFT_STUN_SERVER = "stun.sflphone.org"; /** Default STUN server address */
const char *DFT_EXPIRE_VALUE = "600"; /** Default expire value for registration */
} // end anonymous namespace
Credentials::Credentials() : credentialCount (0) {}
Credentials::~Credentials() {}
void Credentials::setNewCredential (const std::string &username,
const std::string &password,
const std::string &realm)
{
credentialArray[credentialCount].username = username;
credentialArray[credentialCount].password = password;
credentialArray[credentialCount].realm = realm;
}
const CredentialItem *Credentials::getCredential (unsigned index) const
{
if (index >= credentialCount)
return NULL;
return &credentialArray[index];
}
void Credentials::serialize (Conf::YamlEmitter *emitter UNUSED)
{
}
void Credentials::unserialize (Conf::MappingNode *map)
{
Conf::ScalarNode *val;
val = (Conf::ScalarNode *) (map->getValue (credentialCountKey));
if (val)
credentialCount = atoi (val->getValue().data());
}
namespace {
static void free_cred(pjsip_cred_info *cred)
{
if (!cred)
return;
unsigned i;
unsigned max = 1; /* getCredentialCount() see #6408 */
for (i = 0 ; i < max ; i++) {
free(cred[i].username.ptr);
free(cred[i].data.ptr);
free(cred[i].realm.ptr);
}
free (cred);
}
} // end anonymous namespace
SIPAccount::SIPAccount (const AccountID& accountID)
: Account (accountID, "SIP")
, _routeSet ("")
, _pool (NULL)
, _regc (NULL)
, _bRegister (false)
, _registrationExpire ("")
, _interface ("default")
, _publishedSameasLocal (true)
, _publishedIpAddress ("")
, _localPort (atoi (DEFAULT_SIP_PORT))
, _publishedPort (atoi (DEFAULT_SIP_PORT))
, _serviceRoute ("")
, _tlsListenerPort (atoi (DEFAULT_SIP_TLS_PORT))
, _transportType (PJSIP_TRANSPORT_UNSPECIFIED)
, _transport (NULL)
, _resolveOnce (false)
, _cred (NULL)
, _realm (DEFAULT_REALM)
, _authenticationUsername ("")
, _tlsSetting (NULL)
, _dtmfType (OVERRTP)
, _tlsEnable ("false")
, _tlsPortStr (DEFAULT_SIP_TLS_PORT)
, _tlsCaListFile ("")
, _tlsCertificateFile ("")
, _tlsPrivateKeyFile ("")
, _tlsPassword ("")
, _tlsMethod ("TLSv1")
, _tlsCiphers ("")
, _tlsServerName ("")
, _tlsVerifyServer (true)
, _tlsVerifyClient (true)
, _tlsRequireClientCertificate (true)
, _tlsNegotiationTimeoutSec ("2")
, _tlsNegotiationTimeoutMsec ("0")
, _stunServer (DFT_STUN_SERVER)
, _stunEnabled (false)
, _srtpEnabled (false)
, _srtpKeyExchange ("sdes")
, _srtpFallback (false)
, _zrtpDisplaySas (true)
, _zrtpDisplaySasOnce (false)
, _zrtpHelloHash (true)
, _zrtpNotSuppWarning (true)
{
_stunServerName.ptr = NULL;
_stunServerName.slen = 0;
_stunPort = 0;
}
SIPAccount::~SIPAccount()
{
/* One SIP account less connected to the sip voiplink */
if (_accountID != "default")
dynamic_cast<SIPVoIPLink*> (_link)->decrementClients();
/* Delete accounts-related information */
_regc = NULL;
free_cred(_cred);
free (_tlsSetting);
}
void SIPAccount::serialize (Conf::YamlEmitter *emitter)
{
if(emitter == NULL) {
_error("SIPAccount: Error: emitter is NULL in serialize");
return;
}
Conf::MappingNode accountmap (NULL);
Conf::MappingNode credentialmap (NULL);
Conf::MappingNode srtpmap (NULL);
Conf::MappingNode zrtpmap (NULL);
Conf::MappingNode tlsmap (NULL);
Conf::ScalarNode id (Account::_accountID);
Conf::ScalarNode username (Account::_username);
Conf::ScalarNode password (Account::_password);
Conf::ScalarNode alias (Account::_alias);
Conf::ScalarNode hostname (Account::_hostname);
Conf::ScalarNode enable (_enabled ? "true" : "false");
Conf::ScalarNode type (Account::_type);
Conf::ScalarNode expire (_registrationExpire);
Conf::ScalarNode interface (_interface);
std::stringstream portstr;
portstr << _localPort;
Conf::ScalarNode port (portstr.str());
Conf::ScalarNode serviceRoute (_serviceRoute);
Conf::ScalarNode mailbox (_mailBox);
Conf::ScalarNode publishAddr (_publishedIpAddress);
std::stringstream publicportstr;
publicportstr << _publishedPort;
Conf::ScalarNode publishPort (publicportstr.str());
Conf::ScalarNode sameasLocal (_publishedSameasLocal ? "true" : "false");
Conf::ScalarNode resolveOnce (_resolveOnce ? "true" : "false");
Conf::ScalarNode codecs (_codecStr);
Conf::ScalarNode ringtonePath (_ringtonePath);
Conf::ScalarNode ringtoneEnabled (_ringtoneEnabled ? "true" : "false");
Conf::ScalarNode stunServer (_stunServer);
Conf::ScalarNode stunEnabled (_stunEnabled ? "true" : "false");
Conf::ScalarNode displayName (_displayName);
Conf::ScalarNode dtmfType (_dtmfType==OVERRTP ? "overrtp" : "sipinfo");
std::stringstream countstr;
countstr << 0;
Conf::ScalarNode count (countstr.str());
Conf::ScalarNode srtpenabled (_srtpEnabled ? "true" : "false");
Conf::ScalarNode keyExchange (_srtpKeyExchange);
Conf::ScalarNode rtpFallback (_srtpFallback ? "true" : "false");
Conf::ScalarNode displaySas (_zrtpDisplaySas ? "true" : "false");
Conf::ScalarNode displaySasOnce (_zrtpDisplaySasOnce ? "true" : "false");
Conf::ScalarNode helloHashEnabled (_zrtpHelloHash ? "true" : "false");
Conf::ScalarNode notSuppWarning (_zrtpNotSuppWarning ? "true" : "false");
Conf::ScalarNode tlsport (_tlsPortStr);
Conf::ScalarNode certificate (_tlsCertificateFile);
Conf::ScalarNode calist (_tlsCaListFile);
Conf::ScalarNode ciphers (_tlsCiphers);
Conf::ScalarNode tlsenabled (_tlsEnable);
Conf::ScalarNode tlsmethod (_tlsMethod);
Conf::ScalarNode timeout (_tlsNegotiationTimeoutSec);
Conf::ScalarNode tlspassword (_tlsPassword);
Conf::ScalarNode privatekey (_tlsPrivateKeyFile);
Conf::ScalarNode requirecertif (_tlsRequireClientCertificate ? "true" : "false");
Conf::ScalarNode server (_tlsServerName);
Conf::ScalarNode verifyclient (_tlsVerifyServer ? "true" : "false");
Conf::ScalarNode verifyserver (_tlsVerifyClient ? "true" : "false");
accountmap.setKeyValue (aliasKey, &alias);
accountmap.setKeyValue (typeKey, &type);
accountmap.setKeyValue (idKey, &id);
accountmap.setKeyValue (usernameKey, &username);
accountmap.setKeyValue (passwordKey, &password);
accountmap.setKeyValue (hostnameKey, &hostname);
accountmap.setKeyValue (accountEnableKey, &enable);
accountmap.setKeyValue (mailboxKey, &mailbox);
accountmap.setKeyValue (expireKey, &expire);
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 (resolveOnceKey, &resolveOnce);
accountmap.setKeyValue (serviceRouteKey, &serviceRoute);
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, ¬SuppWarning);
accountmap.setKeyValue (credKey, &credentialmap);
credentialmap.setKeyValue (credentialCountKey, &count);
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);
try {
emitter->serializeAccount (&accountmap);
} catch (Conf::YamlEmitterException &e) {
_error ("ConfigTree: %s", e.what());
}
}
void SIPAccount::unserialize (Conf::MappingNode *map)
{
Conf::ScalarNode *val;
Conf::MappingNode *srtpMap;
Conf::MappingNode *tlsMap;
Conf::MappingNode *zrtpMap;
Conf::MappingNode *credMap;
assert(map);
val = (Conf::ScalarNode *) (map->getValue (aliasKey));
if (val)
_alias = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (typeKey));
if (val)
_type = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (idKey));
if (val)
_accountID = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (usernameKey));
if (val)
_username = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (passwordKey));
if (val)
_password = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (hostnameKey));
if (val)
_hostname = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (accountEnableKey));
if (val)
_enabled = (val->getValue() != "false");
val = (Conf::ScalarNode *) (map->getValue (mailboxKey));
if (val)
_mailBox = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (codecsKey));
if (val)
_codecStr = val->getValue();
// Update codec list which one is used for SDP offer
setActiveCodecs (Manager::instance ().unserialize (_codecStr));
val = (Conf::ScalarNode *) (map->getValue (ringtonePathKey));
if (val)
_ringtonePath = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (ringtoneEnabledKey));
if (val)
_ringtoneEnabled = (val->getValue() == "true");
val = (Conf::ScalarNode *) (map->getValue (expireKey));
if (val)
_registrationExpire = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (interfaceKey));
if (val)
_interface = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (portKey));
if (val)
_localPort = atoi (val->getValue().data());
val = (Conf::ScalarNode *) (map->getValue (publishAddrKey));
if (val)
_publishedIpAddress = val->getValue();
val = (Conf::ScalarNode *) (map->getValue (publishPortKey));
if (val)
_publishedPort = atoi (val->getValue().data());
val = (Conf::ScalarNode *) (map->getValue (sameasLocalKey));
if (val)
_publishedSameasLocal = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (map->getValue (resolveOnceKey));
if (val)
_resolveOnce = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (map->getValue (dtmfTypeKey));
if (val)
_dtmfType = (val->getValue() == "overrtp") ? OVERRTP : SIPINFO;
// _dtmfType = atoi(val->getValue();
val = (Conf::ScalarNode *) (map->getValue (serviceRouteKey));
if (val)
_serviceRoute = val->getValue();
// stun enabled
val = (Conf::ScalarNode *) (map->getValue (stunEnabledKey));
if (val)
_stunEnabled = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (map->getValue (stunServerKey));
if (val)
_stunServer = val->getValue();
// Init stun server name with default server name
_stunServerName = pj_str ( (char*) _stunServer.data());
credMap = (Conf::MappingNode *) (map->getValue (credKey));
if (credMap)
credentials.unserialize (credMap);
val = (Conf::ScalarNode *) (map->getValue (displayNameKey));
if (val)
_displayName = val->getValue();
// get srtp submap
srtpMap = (Conf::MappingNode *) (map->getValue (srtpKey));
if (!srtpMap)
throw SipAccountException (" did not found srtp map");
val = (Conf::ScalarNode *) (srtpMap->getValue (srtpEnableKey));
if (val)
_srtpEnabled = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (srtpMap->getValue (keyExchangeKey));
if (val)
_srtpKeyExchange = val->getValue();
val = (Conf::ScalarNode *) (srtpMap->getValue (rtpFallbackKey));
if (val)
_srtpFallback = (val->getValue().compare ("true") == 0);
// get zrtp submap
zrtpMap = (Conf::MappingNode *) (map->getValue (zrtpKey));
if (!zrtpMap)
throw SipAccountException (" did not found zrtp map");
val = (Conf::ScalarNode *) (zrtpMap->getValue (displaySasKey));
if (val)
_zrtpDisplaySas = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (zrtpMap->getValue (displaySasOnceKey));
if (val)
_zrtpDisplaySasOnce = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (zrtpMap->getValue (helloHashEnabledKey));
if (val)
_zrtpHelloHash = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (zrtpMap->getValue (notSuppWarningKey));
if (val)
_zrtpNotSuppWarning = (val->getValue().compare ("true") == 0);
// get tls submap
tlsMap = (Conf::MappingNode *) (map->getValue (tlsKey));
if (!tlsMap)
throw SipAccountException (" did not found tls map");
val = (Conf::ScalarNode *) (tlsMap->getValue (tlsEnableKey));
if (val)
_tlsEnable = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (tlsPortKey));
if (val)
_tlsPortStr = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (certificateKey));
if (val)
_tlsCertificateFile = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (calistKey));
if (val)
_tlsCaListFile = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (ciphersKey));
if (val)
_tlsCiphers = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (methodKey));
if (val)
_tlsMethod = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (timeoutKey));
if (val) {
// FIXME
_tlsNegotiationTimeoutSec = val->getValue();
_tlsNegotiationTimeoutMsec = val->getValue();
}
val = (Conf::ScalarNode *) (tlsMap->getValue (tlsPasswordKey));
if (val)
_tlsPassword = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (privateKeyKey));
if (val)
_tlsPrivateKeyFile = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (requireCertifKey));
if (val)
_tlsRequireClientCertificate = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (tlsMap->getValue (serverKey));
if (val)
_tlsServerName = val->getValue();
val = (Conf::ScalarNode *) (tlsMap->getValue (verifyClientKey));
if (val)
_tlsVerifyServer = (val->getValue().compare ("true") == 0);
val = (Conf::ScalarNode *) (tlsMap->getValue (verifyServerKey));
if (val)
_tlsVerifyClient = (val->getValue().compare ("true") == 0);
}
void SIPAccount::setAccountDetails (const std::map<std::string, std::string>& details)
{
std::map<std::string, std::string> map_cpy;
std::map<std::string, std::string>::iterator iter;
// Work on a copy
map_cpy = details;
std::string alias;
std::string type;
std::string hostname;
std::string username;
std::string password;
std::string mailbox;
std::string accountEnable;
std::string ringtonePath;
std::string ringtoneEnabled;
// Account setting common to SIP and IAX
find_in_map (CONFIG_ACCOUNT_ALIAS, alias)
find_in_map (CONFIG_ACCOUNT_TYPE, type)
find_in_map (HOSTNAME, hostname)
find_in_map (USERNAME, username)
find_in_map (PASSWORD, password)
find_in_map (CONFIG_ACCOUNT_MAILBOX, mailbox);
find_in_map (CONFIG_ACCOUNT_ENABLE, accountEnable);
find_in_map (CONFIG_RINGTONE_PATH, ringtonePath);
find_in_map (CONFIG_RINGTONE_ENABLED, ringtoneEnabled);
setAlias (alias);
setType (type);
setUsername (username);
setHostname (hostname);
setPassword (password);
setEnabled ( (accountEnable == "true"));
setRingtonePath (ringtonePath);
setRingtoneEnabled ( (ringtoneEnabled == "true"));
setMailBox (mailbox);
// SIP specific account settings
std::string ua_name;
std::string realm;
std::string routeset;
std::string authenticationName;
std::string resolveOnce;
std::string registrationExpire;
std::string displayName;
std::string localInterface;
std::string publishedSameasLocal;
std::string localAddress;
std::string publishedAddress;
std::string localPort;
std::string publishedPort;
std::string stunEnable;
std::string stunServer;
std::string dtmfType;
std::string srtpEnable;
std::string srtpRtpFallback;
std::string zrtpDisplaySas;
std::string zrtpDisplaySasOnce;
std::string zrtpNotSuppWarning;
std::string zrtpHelloHash;
std::string srtpKeyExchange;
std::string tlsListenerPort;
std::string tlsEnable;
std::string tlsCaListFile;
std::string tlsCertificateFile;
std::string tlsPrivateKeyFile;
std::string tlsPassword;
std::string tlsMethod;
std::string tlsCiphers;
std::string tlsServerName;
std::string tlsVerifyServer;
std::string tlsVerifyClient;
std::string tlsRequireClientCertificate;
std::string tlsNegotiationTimeoutSec;
std::string tlsNegotiationTimeoutMsec;
// general sip settings
find_in_map (DISPLAY_NAME, displayName)
find_in_map (ROUTESET, routeset)
find_in_map (LOCAL_INTERFACE, localInterface)
find_in_map (PUBLISHED_SAMEAS_LOCAL, publishedSameasLocal)
find_in_map (PUBLISHED_ADDRESS, publishedAddress)
find_in_map (LOCAL_PORT, localPort)
find_in_map (PUBLISHED_PORT, publishedPort)
find_in_map (STUN_ENABLE, stunEnable)
find_in_map (STUN_SERVER, stunServer)
find_in_map (ACCOUNT_DTMF_TYPE, dtmfType)
find_in_map (CONFIG_ACCOUNT_RESOLVE_ONCE, resolveOnce)
find_in_map (CONFIG_ACCOUNT_REGISTRATION_EXPIRE, registrationExpire)
setDisplayName (displayName);
setServiceRoute (routeset);
setLocalInterface (localInterface);
setPublishedSameasLocal (publishedSameasLocal == "true");
setPublishedAddress (publishedAddress);
setLocalPort (atoi (localPort.data()));
setPublishedPort (atoi (publishedPort.data()));
setStunServer (stunServer);
setStunEnabled (stunEnable == "true");
setDtmfType ( (dtmfType == "overrtp") ? OVERRTP : SIPINFO);
setResolveOnce (resolveOnce == "true");
setRegistrationExpire (registrationExpire);
// sip credential
find_in_map (REALM, realm)
find_in_map (AUTHENTICATION_USERNAME, authenticationName)
find_in_map (USERAGENT, ua_name)
setUseragent (ua_name);
// srtp settings
find_in_map (SRTP_ENABLE, srtpEnable)
find_in_map (SRTP_RTP_FALLBACK, srtpRtpFallback)
find_in_map (ZRTP_DISPLAY_SAS, zrtpDisplaySas)
find_in_map (ZRTP_DISPLAY_SAS_ONCE, zrtpDisplaySasOnce)
find_in_map (ZRTP_NOT_SUPP_WARNING, zrtpNotSuppWarning)
find_in_map (ZRTP_HELLO_HASH, zrtpHelloHash)
find_in_map (SRTP_KEY_EXCHANGE, srtpKeyExchange)
setSrtpEnable (srtpEnable == "true");
setSrtpFallback (srtpRtpFallback == "true");
setZrtpDisplaySas (zrtpDisplaySas == "true");
setZrtpDiaplaySasOnce (zrtpDisplaySasOnce == "true");
setZrtpNotSuppWarning (zrtpNotSuppWarning == "true");
setZrtpHelloHash (zrtpHelloHash == "true");
setSrtpKeyExchange (srtpKeyExchange);
// TLS settings
// The TLS listener is unique and globally defined through IP2IP_PROFILE
if (_accountID == IP2IP_PROFILE) {
find_in_map (TLS_LISTENER_PORT, tlsListenerPort)
}
find_in_map (TLS_ENABLE, tlsEnable)
find_in_map (TLS_CA_LIST_FILE, tlsCaListFile)
find_in_map (TLS_CERTIFICATE_FILE, tlsCertificateFile)
find_in_map (TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile)
find_in_map (TLS_PASSWORD, tlsPassword)
find_in_map (TLS_METHOD, tlsMethod)
find_in_map (TLS_CIPHERS, tlsCiphers)
find_in_map (TLS_SERVER_NAME, tlsServerName)
find_in_map (TLS_VERIFY_SERVER, tlsVerifyServer)
find_in_map (TLS_VERIFY_CLIENT, tlsVerifyClient)
find_in_map (TLS_REQUIRE_CLIENT_CERTIFICATE, tlsRequireClientCertificate)
find_in_map (TLS_NEGOTIATION_TIMEOUT_SEC, tlsNegotiationTimeoutSec)
find_in_map (TLS_NEGOTIATION_TIMEOUT_MSEC, tlsNegotiationTimeoutMsec)
if (_accountID == IP2IP_PROFILE) {
setTlsListenerPort (atoi (tlsListenerPort.data()));
}
setTlsEnable (tlsEnable);
setTlsCaListFile (tlsCaListFile);
setTlsCertificateFile (tlsCertificateFile);
setTlsPrivateKeyFile (tlsPrivateKeyFile);
setTlsPassword (tlsPassword);
setTlsMethod (tlsMethod);
setTlsCiphers (tlsCiphers);
setTlsServerName (tlsServerName);
setTlsVerifyServer (tlsVerifyServer == "true");
setTlsVerifyClient (tlsVerifyServer == "true");
setTlsRequireClientCertificate (tlsRequireClientCertificate == "true");
setTlsNegotiationTimeoutSec (tlsNegotiationTimeoutSec);
setTlsNegotiationTimeoutMsec (tlsNegotiationTimeoutMsec);
if (!Manager::instance().preferences.getMd5Hash()) {
setPassword (password);
} else {
// Make sure not to re-hash the password field if
// it is already saved as a MD5 Hash.
// TODO: This test is weak. Fix this.
if ( (password.compare (getPassword()) != 0)) {
_debug ("SipAccount: Password sent and password from config are different. Re-hashing");
std::string hash;
if (authenticationName.empty()) {
hash = Manager::instance().computeMd5HashFromCredential (username, password, realm);
} else {
hash = Manager::instance().computeMd5HashFromCredential (authenticationName, password, realm);
}
setPassword (hash);
}
}
}
std::map<std::string, std::string> SIPAccount::getAccountDetails() const
{
std::map<std::string, std::string> a;
a.insert (std::pair<std::string, std::string> (ACCOUNT_ID, _accountID));
// The IP profile does not allow to set an alias
(_accountID == IP2IP_PROFILE) ?
a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_ALIAS, IP2IP_PROFILE)) :
a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_ALIAS, getAlias()));
a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_ENABLE, isEnabled() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_TYPE, getType()));
a.insert (std::pair<std::string, std::string> (HOSTNAME, getHostname()));
a.insert (std::pair<std::string, std::string> (USERNAME, getUsername()));
a.insert (std::pair<std::string, std::string> (PASSWORD, getPassword()));
a.insert (std::pair<std::string, std::string> (CONFIG_RINGTONE_PATH, getRingtonePath()));
a.insert (std::pair<std::string, std::string> (CONFIG_RINGTONE_ENABLED, getRingtoneEnabled() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_MAILBOX, getMailBox()));
RegistrationState state = Unregistered;
std::string registrationStateCode;
std::string registrationStateDescription;
if (_accountID == IP2IP_PROFILE) {
registrationStateCode = ""; // emtpy field
registrationStateDescription = "Direct IP call";
} else {
state = getRegistrationState();
int code = getRegistrationStateDetailed().first;
std::stringstream out;
out << code;
registrationStateCode = out.str();
registrationStateDescription = getRegistrationStateDetailed().second;
}
(_accountID == IP2IP_PROFILE) ?
a.insert (std::pair<std::string, std::string> (REGISTRATION_STATUS, "READY")) :
a.insert (std::pair<std::string, std::string> (REGISTRATION_STATUS, Manager::instance().mapStateNumberToString (state)));
a.insert (std::pair<std::string, std::string> (REGISTRATION_STATE_CODE, registrationStateCode));
a.insert (std::pair<std::string, std::string> (REGISTRATION_STATE_DESCRIPTION, registrationStateDescription));
// Add sip specific details
a.insert (std::pair<std::string, std::string> (ROUTESET, getServiceRoute()));
a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_RESOLVE_ONCE, isResolveOnce() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (REALM, _realm));
a.insert (std::pair<std::string, std::string> (USERAGENT, getUseragent()));
a.insert (std::pair<std::string, std::string> (CONFIG_ACCOUNT_REGISTRATION_EXPIRE, getRegistrationExpire()));
a.insert (std::pair<std::string, std::string> (LOCAL_INTERFACE, getLocalInterface()));
a.insert (std::pair<std::string, std::string> (PUBLISHED_SAMEAS_LOCAL, getPublishedSameasLocal() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (PUBLISHED_ADDRESS, getPublishedAddress()));
std::stringstream localport;
localport << getLocalPort();
a.insert (std::pair<std::string, std::string> (LOCAL_PORT, localport.str()));
std::stringstream publishedport;
publishedport << getPublishedPort();
a.insert (std::pair<std::string, std::string> (PUBLISHED_PORT, publishedport.str()));
a.insert (std::pair<std::string, std::string> (STUN_ENABLE, isStunEnabled() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (STUN_SERVER, getStunServer()));
a.insert (std::pair<std::string, std::string> (ACCOUNT_DTMF_TYPE, (getDtmfType() == OVERRTP) ? "overrtp" : "sipinfo"));
a.insert (std::pair<std::string, std::string> (SRTP_KEY_EXCHANGE, getSrtpKeyExchange()));
a.insert (std::pair<std::string, std::string> (SRTP_ENABLE, getSrtpEnable() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (SRTP_RTP_FALLBACK, getSrtpFallback() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (ZRTP_DISPLAY_SAS, getZrtpDisplaySas() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (ZRTP_DISPLAY_SAS_ONCE, getZrtpDiaplaySasOnce() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (ZRTP_HELLO_HASH, getZrtpHelloHash() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (ZRTP_NOT_SUPP_WARNING, getZrtpNotSuppWarning() ? "true" : "false"));
// TLS listener is unique and parameters are modified through IP2IP_PROFILE
std::stringstream tlslistenerport;
tlslistenerport << getTlsListenerPort();
a.insert (std::pair<std::string, std::string> (TLS_LISTENER_PORT, tlslistenerport.str()));
a.insert (std::pair<std::string, std::string> (TLS_ENABLE, getTlsEnable()));
a.insert (std::pair<std::string, std::string> (TLS_CA_LIST_FILE, getTlsCaListFile()));
a.insert (std::pair<std::string, std::string> (TLS_CERTIFICATE_FILE, getTlsCertificateFile()));
a.insert (std::pair<std::string, std::string> (TLS_PRIVATE_KEY_FILE, getTlsPrivateKeyFile()));
a.insert (std::pair<std::string, std::string> (TLS_PASSWORD, getTlsPassword()));
a.insert (std::pair<std::string, std::string> (TLS_METHOD, getTlsMethod()));
a.insert (std::pair<std::string, std::string> (TLS_CIPHERS, getTlsCiphers()));
a.insert (std::pair<std::string, std::string> (TLS_SERVER_NAME, getTlsServerName()));
a.insert (std::pair<std::string, std::string> (TLS_VERIFY_SERVER, getTlsVerifyServer() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (TLS_VERIFY_CLIENT, getTlsVerifyClient() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (TLS_REQUIRE_CLIENT_CERTIFICATE, getTlsRequireClientCertificate() ? "true" : "false"));
a.insert (std::pair<std::string, std::string> (TLS_NEGOTIATION_TIMEOUT_SEC, getTlsNegotiationTimeoutSec()));
a.insert (std::pair<std::string, std::string> (TLS_NEGOTIATION_TIMEOUT_MSEC, getTlsNegotiationTimeoutMsec()));
return a;
}
// void SIPAccount::setVoIPLink(VoIPLink *link) {
void SIPAccount::setVoIPLink()
{
_link = SIPVoIPLink::instance ("");
dynamic_cast<SIPVoIPLink*> (_link)->incrementClients();
}
void SIPAccount::initCredential (void)
{
// We want to make sure that the password is really
// 32 characters long. Otherwise, pjsip will fail
// on an assertion.
bool md5HashingEnabled = Manager::instance().preferences.getMd5Hash()
&& _password.length() == 32;
int dataType = md5HashingEnabled ? PJSIP_CRED_DATA_DIGEST
: PJSIP_CRED_DATA_PLAIN_PASSWD;
std::string digest;
// Create the credential array
free_cred(_cred);
_cred = (pjsip_cred_info *) calloc(getCredentialCount(), sizeof (pjsip_cred_info));
if (!_cred) {
_error ("SipAccount: Error: Failed to set _cred for account %s", _accountID.c_str());
return;
}
if (md5HashingEnabled )
_debug ("Setting digest ");
// Use authentication username if provided
if (!_authenticationUsername.empty())
_cred[0].username = pj_str (strdup (_authenticationUsername.c_str()));
else
_cred[0].username = pj_str (strdup (_username.c_str()));
// Set password
_cred[0].data = pj_str (strdup (_password.c_str()));
// Set realm for that credential. * by default.
_cred[0].realm = pj_str (strdup (_realm.c_str()));
_cred[0].data_type = dataType;
_cred[0].scheme = pj_str ( (char*) "digest");
#if 0 // FIXME, unused. see https://projects.savoirfairelinux.com/issues/6408
unsigned i;
// Default credential already initialized, use credentials.getCredentialCount()
for (i = 0; i < credentials.getCredentialCount(); i++) {
_cred[i].username = pj_str (strdup (_username.c_str()));
_cred[i].data = pj_str (strdup (_password.c_str()));
_cred[i].realm = pj_str (strdup (_realm.c_str()));
_cred[i].data_type = dataType;
_cred[i].scheme = pj_str ( (char*) "digest");
_debug ("Setting credential %u realm = %s passwd = %s username = %s data_type = %d", i, _realm.c_str(), _password.c_str(), _username.c_str(), _cred[i].data_type);
}
#endif
}
int SIPAccount::registerVoIPLink()
{
if (_hostname.length() >= PJ_MAX_HOSTNAME) {
return 1;
}
// Init set of additional credentials, if supplied by the user
initCredential();
// Init TLS settings if the user wants to use TLS
if (_tlsEnable == "true") {
_debug ("SIPAccount: TLS is enabled for account %s", getAccountID().c_str());
_transportType = PJSIP_TRANSPORT_TLS;
initTlsConfiguration();
}
// Init STUN settings for this account if the user selected it
if (_stunEnabled) {
_transportType = PJSIP_TRANSPORT_START_OTHER;
initStunConfiguration ();
} else {
_stunServerName = pj_str ( (char*) _stunServer.data());
}
try {
// In our definition of the ip2ip profile (aka Direct IP Calls),
// no registration should be performed
if (_accountID != IP2IP_PROFILE) {
_link->sendRegister (_accountID);
}
}
catch(VoipLinkException &e) {
_error("SIPAccount: %s", e.what());
}
return 0;
}
int SIPAccount::unregisterVoIPLink()
{
if (_accountID == IP2IP_PROFILE) {
return true;
}
try {
_link->sendUnregister (_accountID);
setRegistrationInfo (NULL);
}
catch(VoipLinkException &e) {
_error("SIPAccount: %s", e.what());
return false;
}
return true;
}
pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum (const std::string& method)
{
if (method == "Default")
return PJSIP_SSL_UNSPECIFIED_METHOD;
if (method == "TLSv1")
return PJSIP_TLSV1_METHOD;
if (method == "SSLv2")
return PJSIP_SSLV2_METHOD;
if (method == "SSLv3")
return PJSIP_SSLV3_METHOD;
if (method == "SSLv23")
return PJSIP_SSLV23_METHOD;
return PJSIP_SSL_UNSPECIFIED_METHOD;
}
void SIPAccount::initTlsConfiguration (void)
{
// TLS listener is unique and should be only modified through IP2IP_PROFILE
// setTlsListenerPort(atoi(tlsPortStr.c_str()));
setTlsListenerPort (atoi (_tlsPortStr.c_str()));
free (_tlsSetting);
_tlsSetting = (pjsip_tls_setting *) malloc (sizeof (pjsip_tls_setting));
assert (_tlsSetting);
pjsip_tls_setting_default (_tlsSetting);
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());
_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;
_tlsSetting->timeout.sec = atol (_tlsNegotiationTimeoutSec.c_str());
_tlsSetting->timeout.msec = atol (_tlsNegotiationTimeoutMsec.c_str());
}
void SIPAccount::initStunConfiguration (void)
{
size_t pos;
std::string stunServer, serverName, serverPort;
stunServer = _stunServer;
// Init STUN socket
pos = stunServer.find (':');
if (pos == std::string::npos) {
_stunServerName = pj_str ( (char*) stunServer.data());
_stunPort = PJ_STUN_PORT;
//stun_status = pj_sockaddr_in_init (&stun_srv.ipv4, &stun_adr, (pj_uint16_t) 3478);
} else {
serverName = stunServer.substr (0, pos);
serverPort = stunServer.substr (pos + 1);
_stunPort = atoi (serverPort.data());
_stunServerName = pj_str ( (char*) serverName.data());
//stun_status = pj_sockaddr_in_init (&stun_srv.ipv4, &stun_adr, (pj_uint16_t) nPort);
}
}
void SIPAccount::loadConfig()
{
if (_registrationExpire.empty())
_registrationExpire = DFT_EXPIRE_VALUE;
if (_tlsEnable == "true") {
initTlsConfiguration();
_transportType = PJSIP_TRANSPORT_TLS;
} else {
_transportType = PJSIP_TRANSPORT_UDP;
}
// Account generic
Account::loadConfig();
}
bool SIPAccount::fullMatch (const std::string& username, const std::string& hostname) const
{
return (userMatch (username) && hostnameMatch (hostname));
}
bool SIPAccount::userMatch (const std::string& username) const
{
if (username.empty()) {
return false;
}
return (username == getUsername());
}
bool SIPAccount::hostnameMatch (const std::string& hostname) const
{
return (hostname == getHostname());
}
std::string SIPAccount::getMachineName (void) const
{
std::string hostname;
hostname = std::string (pj_gethostname()->ptr, pj_gethostname()->slen);
return hostname;
}
std::string SIPAccount::getLoginName (void) const
{
std::string username;
uid_t uid = getuid();
struct passwd * user_info = NULL;
user_info = getpwuid (uid);
if (user_info != NULL) {
username = user_info->pw_name;
}
return username;
}
std::string SIPAccount::getTransportMapKey (void) const
{
std::stringstream out;
out << getLocalPort();
std::string localPort = out.str();
return localPort;
}
std::string SIPAccount::getFromUri (void) const
{
char uri[PJSIP_MAX_URL_SIZE];
std::string scheme;
std::string transport;
std::string username = _username;
std::string hostname = _hostname;
// UDP does not require the transport specification
if (_transportType == PJSIP_TRANSPORT_TLS) {
scheme = "sips:";
transport = ";transport=" + std::string (pjsip_transport_get_type_name (_transportType));
} else {
scheme = "sip:";
transport = "";
}
// Get login name if username is not specified
if (_username.empty()) {
username = getLoginName();
}
// Get machine hostname if not provided
if (_hostname.empty()) {
hostname = getMachineName();
}
int len = pj_ansi_snprintf (uri, PJSIP_MAX_URL_SIZE,
"<%s%s@%s%s>",
scheme.c_str(),
username.c_str(),
hostname.c_str(),
transport.c_str());
return std::string (uri, len);
}
std::string SIPAccount::getToUri (const std::string& username) const
{
char uri[PJSIP_MAX_URL_SIZE];
std::string scheme;
std::string transport;
std::string hostname = "";
// UDP does not require the transport specification
if (_transportType == PJSIP_TRANSPORT_TLS) {
scheme = "sips:";
transport = ";transport=" + std::string (pjsip_transport_get_type_name (_transportType));
} else {
scheme = "sip:";
transport = "";
}
// Check if scheme is already specified
if (username.find ("sip") == 0) {
scheme = "";
}
// Check if hostname is already specified
if (username.find ("@") == std::string::npos) {
// hostname not specified
hostname = _hostname;
}
int len = pj_ansi_snprintf (uri, PJSIP_MAX_URL_SIZE,
"<%s%s%s%s%s>",
scheme.c_str(),
username.c_str(),
(hostname.empty()) ? "" : "@",
hostname.c_str(),
transport.c_str());
return std::string (uri, len);
}
std::string SIPAccount::getServerUri (void) const
{
char uri[PJSIP_MAX_URL_SIZE];
std::string scheme;
std::string transport;
std::string hostname = _hostname;
// UDP does not require the transport specification
if (_transportType == PJSIP_TRANSPORT_TLS) {
scheme = "sips:";
transport = ";transport=" + std::string (pjsip_transport_get_type_name (_transportType));
} else {
scheme = "sip:";
transport = "";
}
int len = pj_ansi_snprintf (uri, PJSIP_MAX_URL_SIZE,
"<%s%s%s>",
scheme.c_str(),
hostname.c_str(),
transport.c_str());
return std::string (uri, len);
}
std::string SIPAccount::getContactHeader (const std::string& address, const std::string& port) const
{
char contact[PJSIP_MAX_URL_SIZE];
const char * beginquote, * endquote;
std::string scheme;
std::string transport;
// if IPV6, should be set to []
beginquote = endquote = "";
// UDP does not require the transport specification
if (_transportType == PJSIP_TRANSPORT_TLS) {
scheme = "sips:";
transport = ";transport=" + std::string (pjsip_transport_get_type_name (_transportType));
} else {
scheme = "sip:";
transport = "";
}
_debug ("Display Name: %s", _displayName.c_str());
int len = pj_ansi_snprintf (contact, PJSIP_MAX_URL_SIZE,
"%s%s<%s%s%s%s%s%s:%d%s>",
_displayName.c_str(),
(_displayName.empty() ? "" : " "),
scheme.c_str(),
_username.c_str(),
(_username.empty() ? "":"@"),
beginquote,
address.c_str(),
endquote,
atoi (port.c_str()),
transport.c_str());
return std::string (contact, len);
}