Line data Source code
1 : /*
2 : * Copyright (C) 2004-2026 Savoir-faire Linux Inc.
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 : #include "sipaccount_config.h"
18 : #include "account_const.h"
19 : #include "account_schema.h"
20 : #include "config/yamlparser.h"
21 :
22 : extern "C" {
23 : #include <pjlib-util/md5.h>
24 : }
25 :
26 : namespace jami {
27 :
28 : namespace Conf {
29 : constexpr const char* ID_KEY = "id";
30 : constexpr const char* USERNAME_KEY = "username";
31 : constexpr const char* BIND_ADDRESS_KEY = "bindAddress";
32 : constexpr const char* INTERFACE_KEY = "interface";
33 : constexpr const char* PORT_KEY = "port";
34 : constexpr const char* PUBLISH_ADDR_KEY = "publishAddr";
35 : constexpr const char* PUBLISH_PORT_KEY = "publishPort";
36 : constexpr const char* SAME_AS_LOCAL_KEY = "sameasLocal";
37 : constexpr const char* DTMF_TYPE_KEY = "dtmfType";
38 : constexpr const char* SERVICE_ROUTE_KEY = "serviceRoute";
39 : constexpr const char* ALLOW_IP_AUTO_REWRITE = "allowIPAutoRewrite";
40 : constexpr const char* PRESENCE_PUBLISH_SUPPORTED_KEY = "presencePublishSupported";
41 : constexpr const char* PRESENCE_SUBSCRIBE_SUPPORTED_KEY = "presenceSubscribeSupported";
42 : constexpr const char* PRESENCE_STATUS_KEY = "presenceStatus";
43 : constexpr const char* PRESENCE_NOTE_KEY = "presenceNote";
44 : constexpr const char* PRESENCE_MODULE_ENABLED_KEY = "presenceModuleEnabled";
45 : constexpr const char* KEEP_ALIVE_ENABLED = "keepAliveEnabled";
46 :
47 : constexpr const char* const TLS_KEY = "tls";
48 : constexpr const char* CERTIFICATE_KEY = "certificate";
49 : constexpr const char* CALIST_KEY = "calist";
50 : constexpr const char* TLS_PORT_KEY = "tlsPort";
51 : constexpr const char* CIPHERS_KEY = "ciphers";
52 : constexpr const char* TLS_ENABLE_KEY = "enable";
53 : constexpr const char* METHOD_KEY = "method";
54 : constexpr const char* TIMEOUT_KEY = "timeout";
55 : constexpr const char* TLS_PASSWORD_KEY = "password";
56 : constexpr const char* PRIVATE_KEY_KEY = "privateKey";
57 : constexpr const char* REQUIRE_CERTIF_KEY = "requireCertif";
58 : constexpr const char* SERVER_KEY = "server";
59 : constexpr const char* VERIFY_CLIENT_KEY = "verifyClient";
60 : constexpr const char* VERIFY_SERVER_KEY = "verifyServer";
61 : constexpr const char* DISABLE_SECURE_DLG_CHECK = "disableSecureDlgCheck";
62 :
63 : constexpr const char* STUN_ENABLED_KEY = "stunEnabled";
64 : constexpr const char* STUN_SERVER_KEY = "stunServer";
65 : constexpr const char* CRED_KEY = "credential";
66 : constexpr const char* SRTP_KEY = "srtp";
67 : constexpr const char* KEY_EXCHANGE_KEY = "keyExchange";
68 : constexpr const char* RTP_FALLBACK_KEY = "rtpFallback";
69 : } // namespace Conf
70 :
71 : static const SipAccountConfig DEFAULT_CONFIG {};
72 : static constexpr unsigned MIN_REGISTRATION_TIME = 60; // seconds
73 :
74 : using yaml_utils::parseValueOptional;
75 : using yaml_utils::parseVectorMap;
76 :
77 : void
78 59 : SipAccountConfig::serialize(YAML::Emitter& out) const
79 : {
80 59 : out << YAML::BeginMap;
81 59 : out << YAML::Key << Conf::ID_KEY << YAML::Value << id;
82 59 : SipAccountBaseConfig::serializeDiff(out, DEFAULT_CONFIG);
83 :
84 59 : out << YAML::Key << Conf::BIND_ADDRESS_KEY << YAML::Value << bindAddress;
85 59 : out << YAML::Key << Conf::PORT_KEY << YAML::Value << localPort;
86 59 : out << YAML::Key << Conf::PUBLISH_PORT_KEY << YAML::Value << publishedPort;
87 :
88 59 : out << YAML::Key << Conf::USERNAME_KEY << YAML::Value << username;
89 :
90 : // each credential is a map, and we can have multiple credentials
91 59 : out << YAML::Key << Conf::CRED_KEY << YAML::Value << getCredentials();
92 :
93 59 : out << YAML::Key << Conf::KEEP_ALIVE_ENABLED << YAML::Value << registrationRefreshEnabled;
94 :
95 : // out << YAML::Key << PRESENCE_MODULE_ENABLED_KEY << YAML::Value
96 : // << (presence_ and presence_->isEnabled());
97 :
98 59 : out << YAML::Key << Conf::CONFIG_ACCOUNT_REGISTRATION_EXPIRE << YAML::Value << registrationExpire;
99 59 : out << YAML::Key << Conf::SERVICE_ROUTE_KEY << YAML::Value << serviceRoute;
100 59 : out << YAML::Key << Conf::ALLOW_IP_AUTO_REWRITE << YAML::Value << allowIPAutoRewrite;
101 59 : out << YAML::Key << Conf::STUN_ENABLED_KEY << YAML::Value << stunEnabled;
102 59 : out << YAML::Key << Conf::STUN_SERVER_KEY << YAML::Value << stunServer;
103 :
104 : // tls submap
105 59 : out << YAML::Key << Conf::TLS_KEY << YAML::Value << YAML::BeginMap;
106 59 : out << YAML::Key << Conf::CALIST_KEY << YAML::Value << tlsCaListFile;
107 59 : out << YAML::Key << Conf::CERTIFICATE_KEY << YAML::Value << tlsCertificateFile;
108 59 : out << YAML::Key << Conf::TLS_PASSWORD_KEY << YAML::Value << tlsPassword;
109 59 : out << YAML::Key << Conf::PRIVATE_KEY_KEY << YAML::Value << tlsPrivateKeyFile;
110 59 : out << YAML::Key << Conf::TLS_ENABLE_KEY << YAML::Value << tlsEnable;
111 59 : out << YAML::Key << Conf::TLS_PORT_KEY << YAML::Value << tlsListenerPort;
112 59 : out << YAML::Key << Conf::VERIFY_CLIENT_KEY << YAML::Value << tlsVerifyClient;
113 59 : out << YAML::Key << Conf::VERIFY_SERVER_KEY << YAML::Value << tlsVerifyServer;
114 59 : out << YAML::Key << Conf::REQUIRE_CERTIF_KEY << YAML::Value << tlsRequireClientCertificate;
115 59 : out << YAML::Key << Conf::DISABLE_SECURE_DLG_CHECK << YAML::Value << tlsDisableSecureDlgCheck;
116 59 : out << YAML::Key << Conf::TIMEOUT_KEY << YAML::Value << tlsNegotiationTimeout;
117 59 : out << YAML::Key << Conf::CIPHERS_KEY << YAML::Value << tlsCiphers;
118 59 : out << YAML::Key << Conf::METHOD_KEY << YAML::Value << tlsMethod;
119 59 : out << YAML::Key << Conf::SERVER_KEY << YAML::Value << tlsServerName;
120 59 : out << YAML::EndMap;
121 :
122 : // srtp submap
123 59 : out << YAML::Key << Conf::SRTP_KEY << YAML::Value << YAML::BeginMap;
124 59 : out << YAML::Key << Conf::KEY_EXCHANGE_KEY << YAML::Value << sip_utils::getKeyExchangeName(srtpKeyExchange);
125 59 : out << YAML::EndMap;
126 :
127 59 : out << YAML::EndMap;
128 59 : }
129 :
130 : void
131 0 : SipAccountConfig::unserialize(const YAML::Node& node)
132 : {
133 0 : SipAccountBaseConfig::unserialize(node);
134 0 : parseValueOptional(node, Conf::USERNAME_KEY, username);
135 0 : parseValueOptional(node, Conf::BIND_ADDRESS_KEY, bindAddress);
136 0 : parseValueOptional(node, Conf::PORT_KEY, localPort);
137 0 : parseValueOptional(node, Conf::PUBLISH_PORT_KEY, publishedPort);
138 0 : parseValueOptional(node, Conf::CONFIG_ACCOUNT_REGISTRATION_EXPIRE, registrationExpire);
139 0 : registrationExpire = std::max(MIN_REGISTRATION_TIME, registrationExpire);
140 0 : parseValueOptional(node, Conf::KEEP_ALIVE_ENABLED, registrationRefreshEnabled);
141 0 : parseValueOptional(node, Conf::SERVICE_ROUTE_KEY, serviceRoute);
142 0 : parseValueOptional(node, Conf::ALLOW_IP_AUTO_REWRITE, allowIPAutoRewrite);
143 :
144 0 : parseValueOptional(node, Conf::PRESENCE_MODULE_ENABLED_KEY, presenceEnabled);
145 0 : parseValueOptional(node, Conf::PRESENCE_PUBLISH_SUPPORTED_KEY, publishSupported);
146 0 : parseValueOptional(node, Conf::PRESENCE_SUBSCRIBE_SUPPORTED_KEY, subscribeSupported);
147 :
148 : // ICE - STUN/TURN
149 0 : parseValueOptional(node, Conf::STUN_ENABLED_KEY, stunEnabled);
150 0 : parseValueOptional(node, Conf::STUN_SERVER_KEY, stunServer);
151 :
152 0 : const auto& credsNode = node[Conf::CRED_KEY];
153 0 : setCredentials(
154 0 : parseVectorMap(credsNode,
155 : {Conf::CONFIG_ACCOUNT_REALM, Conf::CONFIG_ACCOUNT_USERNAME, Conf::CONFIG_ACCOUNT_PASSWORD}));
156 :
157 : // get tls submap
158 : try {
159 0 : const auto& tlsMap = node[Conf::TLS_KEY];
160 0 : parseValueOptional(tlsMap, Conf::CERTIFICATE_KEY, tlsCertificateFile);
161 0 : parseValueOptional(tlsMap, Conf::CALIST_KEY, tlsCaListFile);
162 0 : parseValueOptional(tlsMap, Conf::TLS_PASSWORD_KEY, tlsPassword);
163 0 : parseValueOptional(tlsMap, Conf::PRIVATE_KEY_KEY, tlsPrivateKeyFile);
164 0 : parseValueOptional(tlsMap, Conf::TLS_ENABLE_KEY, tlsEnable);
165 0 : parseValueOptional(tlsMap, Conf::TLS_PORT_KEY, tlsListenerPort);
166 0 : parseValueOptional(tlsMap, Conf::CIPHERS_KEY, tlsCiphers);
167 0 : parseValueOptional(tlsMap, Conf::METHOD_KEY, tlsMethod);
168 0 : parseValueOptional(tlsMap, Conf::SERVER_KEY, tlsServerName);
169 0 : parseValueOptional(tlsMap, Conf::REQUIRE_CERTIF_KEY, tlsRequireClientCertificate);
170 0 : parseValueOptional(tlsMap, Conf::VERIFY_CLIENT_KEY, tlsVerifyClient);
171 0 : parseValueOptional(tlsMap, Conf::VERIFY_SERVER_KEY, tlsVerifyServer);
172 0 : parseValueOptional(tlsMap, Conf::DISABLE_SECURE_DLG_CHECK, tlsDisableSecureDlgCheck);
173 0 : parseValueOptional(tlsMap, Conf::TIMEOUT_KEY, tlsNegotiationTimeout);
174 0 : } catch (...) {
175 0 : }
176 :
177 : // get srtp submap
178 0 : const auto& srtpMap = node[Conf::SRTP_KEY];
179 0 : std::string tmpKey;
180 0 : parseValueOptional(srtpMap, Conf::KEY_EXCHANGE_KEY, tmpKey);
181 0 : srtpKeyExchange = sip_utils::getKeyExchangeProtocol(tmpKey);
182 0 : }
183 :
184 : std::map<std::string, std::string>
185 62 : SipAccountConfig::toMap() const
186 : {
187 62 : auto a = SipAccountBaseConfig::toMap();
188 : // general sip settings
189 62 : a.emplace(Conf::CONFIG_ACCOUNT_USERNAME, username);
190 62 : a.emplace(Conf::CONFIG_LOCAL_PORT, std::to_string(localPort));
191 62 : a.emplace(Conf::CONFIG_ACCOUNT_DTMF_TYPE, dtmfType);
192 62 : a.emplace(Conf::CONFIG_LOCAL_INTERFACE, interface);
193 62 : a.emplace(Conf::CONFIG_PUBLISHED_PORT, std::to_string(publishedPort));
194 62 : a.emplace(Conf::CONFIG_PUBLISHED_SAMEAS_LOCAL, publishedSameasLocal ? TRUE_STR : FALSE_STR);
195 62 : a.emplace(Conf::CONFIG_PUBLISHED_ADDRESS, publishedIp);
196 62 : a.emplace(Conf::CONFIG_STUN_ENABLE, stunEnabled ? TRUE_STR : FALSE_STR);
197 62 : a.emplace(Conf::CONFIG_STUN_SERVER, stunServer);
198 62 : a.emplace(Conf::CONFIG_BIND_ADDRESS, bindAddress);
199 62 : a.emplace(Conf::CONFIG_ACCOUNT_ROUTESET, serviceRoute);
200 62 : a.emplace(Conf::CONFIG_ACCOUNT_IP_AUTO_REWRITE, allowIPAutoRewrite ? TRUE_STR : FALSE_STR);
201 62 : a.emplace(Conf::CONFIG_PRESENCE_ENABLED, presenceEnabled ? TRUE_STR : FALSE_STR);
202 62 : a.emplace(Conf::CONFIG_KEEP_ALIVE_ENABLED, registrationRefreshEnabled ? TRUE_STR : FALSE_STR);
203 62 : a.emplace(Conf::CONFIG_ACCOUNT_REGISTRATION_EXPIRE, std::to_string(registrationExpire));
204 :
205 62 : std::string password {};
206 62 : if (not credentials.empty()) {
207 54 : for (const auto& cred : credentials)
208 54 : if (cred.username == username) {
209 54 : password = cred.password;
210 54 : break;
211 : }
212 : }
213 62 : a.emplace(Conf::CONFIG_ACCOUNT_PASSWORD, std::move(password));
214 :
215 : // srtp settings
216 62 : a.emplace(Conf::CONFIG_SRTP_KEY_EXCHANGE, sip_utils::getKeyExchangeName(srtpKeyExchange));
217 62 : a.emplace(Conf::CONFIG_TLS_ENABLE, tlsEnable ? TRUE_STR : FALSE_STR);
218 62 : a.emplace(Conf::CONFIG_TLS_LISTENER_PORT, std::to_string(tlsListenerPort));
219 62 : a.emplace(Conf::CONFIG_TLS_CA_LIST_FILE, tlsCaListFile);
220 62 : a.emplace(Conf::CONFIG_TLS_CERTIFICATE_FILE, tlsCertificateFile);
221 62 : a.emplace(Conf::CONFIG_TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile);
222 62 : a.emplace(Conf::CONFIG_TLS_PASSWORD, tlsPassword);
223 62 : a.emplace(Conf::CONFIG_TLS_METHOD, tlsMethod);
224 62 : a.emplace(Conf::CONFIG_TLS_CIPHERS, tlsCiphers);
225 62 : a.emplace(Conf::CONFIG_TLS_SERVER_NAME, tlsServerName);
226 62 : a.emplace(Conf::CONFIG_TLS_VERIFY_SERVER, tlsVerifyServer ? TRUE_STR : FALSE_STR);
227 62 : a.emplace(Conf::CONFIG_TLS_VERIFY_CLIENT, tlsVerifyClient ? TRUE_STR : FALSE_STR);
228 62 : a.emplace(Conf::CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE, tlsRequireClientCertificate ? TRUE_STR : FALSE_STR);
229 62 : a.emplace(Conf::CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC, std::to_string(tlsNegotiationTimeout));
230 62 : a.emplace(Conf::CONFIG_TLS_DISABLE_SECURE_DLG_CHECK, tlsDisableSecureDlgCheck ? TRUE_STR : FALSE_STR);
231 124 : return a;
232 62 : }
233 :
234 : void
235 9 : SipAccountConfig::fromMap(const std::map<std::string, std::string>& details)
236 : {
237 9 : SipAccountBaseConfig::fromMap(details);
238 :
239 : // general sip settings
240 9 : parseString(details, Conf::CONFIG_ACCOUNT_USERNAME, username);
241 9 : parseInt(details, Conf::CONFIG_LOCAL_PORT, localPort);
242 9 : parseString(details, Conf::CONFIG_BIND_ADDRESS, bindAddress);
243 9 : parseString(details, Conf::CONFIG_ACCOUNT_ROUTESET, serviceRoute);
244 9 : parseBool(details, Conf::CONFIG_ACCOUNT_IP_AUTO_REWRITE, allowIPAutoRewrite);
245 9 : parseString(details, Conf::CONFIG_LOCAL_INTERFACE, interface);
246 9 : parseBool(details, Conf::CONFIG_PUBLISHED_SAMEAS_LOCAL, publishedSameasLocal);
247 9 : parseString(details, Conf::CONFIG_PUBLISHED_ADDRESS, publishedIp);
248 9 : parseInt(details, Conf::CONFIG_PUBLISHED_PORT, publishedPort);
249 9 : parseBool(details, Conf::CONFIG_PRESENCE_ENABLED, presenceEnabled);
250 9 : parseString(details, Conf::CONFIG_ACCOUNT_DTMF_TYPE, dtmfType);
251 9 : parseBool(details, Conf::CONFIG_KEEP_ALIVE_ENABLED, registrationRefreshEnabled);
252 9 : parseInt(details, Conf::CONFIG_ACCOUNT_REGISTRATION_EXPIRE, registrationExpire);
253 :
254 : // srtp settings
255 9 : auto iter = details.find(Conf::CONFIG_SRTP_KEY_EXCHANGE);
256 9 : if (iter != details.end())
257 9 : srtpKeyExchange = sip_utils::getKeyExchangeProtocol(iter->second);
258 :
259 9 : if (credentials.empty()) { // credentials not set, construct 1 entry
260 9 : JAMI_WARN("No credentials set, inferring them...");
261 9 : std::map<std::string, std::string> map;
262 9 : map[Conf::CONFIG_ACCOUNT_USERNAME] = username;
263 9 : parseString(details, Conf::CONFIG_ACCOUNT_PASSWORD, map[Conf::CONFIG_ACCOUNT_PASSWORD]);
264 9 : map[Conf::CONFIG_ACCOUNT_REALM] = "*";
265 18 : setCredentials({map});
266 9 : }
267 :
268 : // ICE - STUN
269 9 : parseBool(details, Conf::CONFIG_STUN_ENABLE, stunEnabled);
270 9 : parseString(details, Conf::CONFIG_STUN_SERVER, stunServer);
271 :
272 : // TLS
273 9 : parseBool(details, Conf::CONFIG_TLS_ENABLE, tlsEnable);
274 9 : parseInt(details, Conf::CONFIG_TLS_LISTENER_PORT, tlsListenerPort);
275 9 : parsePath(details, Conf::CONFIG_TLS_CA_LIST_FILE, tlsCaListFile, path);
276 9 : parsePath(details, Conf::CONFIG_TLS_CERTIFICATE_FILE, tlsCertificateFile, path);
277 9 : parsePath(details, Conf::CONFIG_TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile, path);
278 9 : parseString(details, Conf::CONFIG_TLS_PASSWORD, tlsPassword);
279 9 : parseString(details, Conf::CONFIG_TLS_METHOD, tlsMethod);
280 9 : parseString(details, Conf::CONFIG_TLS_CIPHERS, tlsCiphers);
281 9 : parseString(details, Conf::CONFIG_TLS_SERVER_NAME, tlsServerName);
282 9 : parseBool(details, Conf::CONFIG_TLS_VERIFY_SERVER, tlsVerifyServer);
283 9 : parseBool(details, Conf::CONFIG_TLS_VERIFY_CLIENT, tlsVerifyClient);
284 9 : parseBool(details, Conf::CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE, tlsRequireClientCertificate);
285 9 : parseBool(details, Conf::CONFIG_TLS_DISABLE_SECURE_DLG_CHECK, tlsDisableSecureDlgCheck);
286 9 : parseInt(details, Conf::CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC, tlsNegotiationTimeout);
287 9 : }
288 :
289 9 : SipAccountConfig::Credentials::Credentials(const std::map<std::string, std::string>& cred)
290 : {
291 9 : auto itrealm = cred.find(Conf::CONFIG_ACCOUNT_REALM);
292 9 : auto user = cred.find(Conf::CONFIG_ACCOUNT_USERNAME);
293 9 : auto passw = cred.find(Conf::CONFIG_ACCOUNT_PASSWORD);
294 9 : realm = itrealm != cred.end() ? itrealm->second : "";
295 9 : username = user != cred.end() ? user->second : "";
296 9 : password = passw != cred.end() ? passw->second : "";
297 9 : computePasswordHash();
298 9 : }
299 :
300 : std::map<std::string, std::string>
301 59 : SipAccountConfig::Credentials::toMap() const
302 : {
303 59 : return {{Conf::CONFIG_ACCOUNT_REALM, realm},
304 59 : {Conf::CONFIG_ACCOUNT_USERNAME, username},
305 236 : {Conf::CONFIG_ACCOUNT_PASSWORD, password}};
306 : }
307 :
308 : void
309 9 : SipAccountConfig::Credentials::computePasswordHash()
310 : {
311 : pj_md5_context pms;
312 :
313 : /* Compute md5 hash = MD5(username ":" realm ":" password) */
314 9 : pj_md5_init(&pms);
315 9 : pj_md5_update(&pms, (const uint8_t*) username.data(), username.length());
316 9 : pj_md5_update(&pms, (const uint8_t*) ":", 1);
317 9 : pj_md5_update(&pms, (const uint8_t*) realm.data(), realm.length());
318 9 : pj_md5_update(&pms, (const uint8_t*) ":", 1);
319 9 : pj_md5_update(&pms, (const uint8_t*) password.data(), password.length());
320 :
321 : unsigned char digest[16];
322 9 : pj_md5_final(&pms, digest);
323 :
324 : char hash[32];
325 :
326 153 : for (int i = 0; i < 16; ++i)
327 144 : pj_val_to_hex_digit(digest[i], &hash[2 * i]);
328 :
329 9 : password_h = {hash, 32};
330 9 : }
331 :
332 : std::vector<std::map<std::string, std::string>>
333 59 : SipAccountConfig::getCredentials() const
334 : {
335 59 : std::vector<std::map<std::string, std::string>> ret;
336 59 : ret.reserve(credentials.size());
337 118 : for (const auto& c : credentials) {
338 59 : ret.emplace_back(c.toMap());
339 : }
340 59 : return ret;
341 0 : }
342 :
343 : void
344 9 : SipAccountConfig::setCredentials(const std::vector<std::map<std::string, std::string>>& creds)
345 : {
346 9 : credentials.clear();
347 9 : credentials.reserve(creds.size());
348 18 : for (const auto& cred : creds)
349 9 : credentials.emplace_back(cred);
350 9 : }
351 :
352 : } // namespace jami
|