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