Select Git revision
sipaccount.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);
}