4 * Copyright (C) 2013 Crocodile RCS Ltd
5 * Copyright (C) 2017 ng-voice GmbH
7 * This file is part of Kamailio, a free SIP server.
9 * Kamailio is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version
14 * Kamailio is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * Exception: permission to copy, modify, propagate, and distribute a work
24 * formed by combining OpenSSL toolkit software and the code in this file,
25 * such as linking with software components and libraries released under
26 * OpenSSL project license.
29 #include <openssl/hmac.h>
30 #include <openssl/sha.h>
32 #include "../../core/basex.h"
33 #include "../../core/dprint.h"
34 #include "../../core/mod_fix.h"
35 #include "../../core/str.h"
36 #include "../../core/ut.h"
37 #include "../../core/parser/digest/digest.h"
38 #include "../../core/parser/hf.h"
39 #include "../../core/mod_fix.h"
41 #include "auth_ephemeral_mod.h"
42 #include "authorize.h"
44 static inline int get_pass(str *_username, str *_secret, str *_password)
46 unsigned int hmac_len = SHA_DIGEST_LENGTH;
47 unsigned char hmac_sha1[512];
49 switch(autheph_sha_alg) {
51 hmac_len = SHA_DIGEST_LENGTH;
52 if (HMAC(EVP_sha1(), _secret->s, _secret->len,
53 (unsigned char *) _username->s,
54 _username->len, hmac_sha1, &hmac_len) == NULL)
56 LM_ERR("HMAC-SHA1 failed\n");
61 hmac_len = SHA256_DIGEST_LENGTH;
62 if (HMAC(EVP_sha256(), _secret->s, _secret->len,
63 (unsigned char *) _username->s,
64 _username->len, hmac_sha1, &hmac_len) == NULL)
66 LM_ERR("HMAC-SHA256 failed\n");
71 hmac_len = SHA384_DIGEST_LENGTH;
72 if (HMAC(EVP_sha256(), _secret->s, _secret->len,
73 (unsigned char *) _username->s,
74 _username->len, hmac_sha1, &hmac_len) == NULL)
76 LM_ERR("HMAC-SHA256 failed\n");
81 hmac_len = SHA512_DIGEST_LENGTH;
82 if (HMAC(EVP_sha512(), _secret->s, _secret->len,
83 (unsigned char *) _username->s,
84 _username->len, hmac_sha1, &hmac_len) == NULL)
86 LM_ERR("HMAC-SHA512 failed\n");
91 LM_ERR("Inavlid SHA Algorithm\n");
96 LM_DBG("HMAC-Len (%i)\n", hmac_len);
99 _password->len = base64_enc(hmac_sha1, hmac_len,
100 (unsigned char *) _password->s,
101 base64_enc_len(hmac_len));
102 LM_DBG("calculated password: %.*s (%i)\n", _password->len, _password->s, _password->len);
107 static inline int get_ha1(struct username *_username, str *_domain,
108 str *_secret, char *_ha1)
110 char password[base64_enc_len(SHA512_DIGEST_LENGTH)];
113 spassword.s = (char *) password;
116 if (get_pass(&_username->whole, _secret, &spassword) < 0)
118 LM_ERR("calculating password\n");
122 eph_auth_api.calc_HA1(HA_MD5, &_username->whole, _domain, &spassword,
124 LM_DBG("calculated HA1: %s\n", _ha1);
129 static inline int do_auth(struct sip_msg *_m, struct hdr_field *_h, str *_realm,
130 str *_method, str *_secret)
134 auth_body_t *cred = (auth_body_t*) _h->parsed;
136 LM_DBG("secret: %.*s (%i)\n", _secret->len, _secret->s, _secret->len);
138 if (get_ha1(&cred->digest.username, _realm, _secret, ha1) < 0)
140 LM_ERR("calculating HA1\n");
144 LM_DBG("HA1: %i\n", (int)strlen(ha1));
146 ret = eph_auth_api.check_response(&cred->digest, _method, ha1);
147 if (ret == AUTHENTICATED)
149 if (eph_auth_api.post_auth(_m, _h, ha1) != AUTHENTICATED) {
153 } else if (ret == NOT_AUTHENTICATED) {
154 return AUTH_INVALID_PASSWORD;
160 int autheph_verify_timestamp(str *_username)
162 int pos = 0, cur_time = (int) time(NULL);
163 unsigned int expires;
164 str time_str = {0, 0};
166 while (pos < _username->len && _username->s[pos] != ':')
169 if (autheph_username_format == AUTHEPH_USERNAME_NON_IETF)
171 if (pos < _username->len - 1)
173 time_str.s = _username->s + pos + 1;
174 time_str.len = _username->len - pos - 1;
178 time_str.s = _username->s;
179 time_str.len = _username->len;
184 time_str.s = _username->s;
185 if (pos < _username->len - 1)
191 time_str.len = _username->len;
195 LM_DBG("username timestamp: %.*s\n", time_str.len, time_str.s);
196 if (str2int(&time_str, &expires) < 0)
198 LM_ERR("unable to convert timestamp to int\n");
202 LM_DBG("current time: %d\n", cur_time);
203 if (cur_time > expires)
205 LM_WARN("username has expired\n");
212 static inline int digest_authenticate(struct sip_msg *_m, str *_realm,
213 hdr_types_t _hftype, str *_method)
216 auth_cfg_result_t ret;
218 struct secret *secret_struct;
221 LM_DBG("realm: %.*s\n", _realm->len, _realm->s);
222 LM_DBG("method: %.*s\n", _method->len, _method->s);
224 rauth = eph_auth_api.pre_auth(_m, _realm, _hftype, &h, NULL);
228 LM_DBG("nonce reused\n");
229 return AUTH_NONCE_REUSED;
231 LM_DBG("stale nonce\n");
232 return AUTH_STALE_NONCE;
234 LM_DBG("no credentials\n");
235 return AUTH_NO_CREDENTIALS;
237 case BAD_CREDENTIALS:
238 LM_DBG("error or bad credentials\n");
240 case CREATE_CHALLENGE:
241 LM_ERR("CREATE_CHALLENGE is not a valid state\n");
243 case DO_RESYNCHRONIZATION:
244 LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n");
246 case NOT_AUTHENTICATED:
247 LM_DBG("not authenticated\n");
249 case DO_AUTHENTICATION:
255 username = ((auth_body_t *) h->parsed)->digest.username.whole;
256 LM_DBG("username: %.*s\n", username.len, username.s);
258 if (autheph_verify_timestamp(&username) < 0)
260 LM_ERR("invalid timestamp in username\n");
265 secret_struct = secret_list;
266 while (secret_struct != NULL)
268 ret = do_auth(_m, h, _realm, _method,
269 &secret_struct->secret_key);
274 secret_struct = secret_struct->next;
281 int autheph_check(struct sip_msg *_m, char *_realm)
285 if (eph_auth_api.pre_auth == NULL)
287 LM_ERR("autheph_check() cannot be used without the auth "
292 if(_m == NULL || _realm == NULL)
294 LM_ERR("invalid parameters\n");
298 if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
303 if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
305 LM_ERR("failed to get realm value\n");
311 LM_ERR("invalid realm parameter - empty value\n");
315 if (_m->REQ_METHOD == METHOD_REGISTER)
317 return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T,
318 &_m->first_line.u.request.method);
322 return digest_authenticate(_m, &srealm, HDR_PROXYAUTH_T,
323 &_m->first_line.u.request.method);
327 int autheph_www(struct sip_msg *_m, char *_realm)
331 if (eph_auth_api.pre_auth == NULL)
333 LM_ERR("autheph_www() cannot be used without the auth "
338 if(_m == NULL || _realm == NULL)
340 LM_ERR("invalid parameters\n");
344 if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
349 if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
351 LM_ERR("failed to get realm value\n");
357 LM_ERR("invalid realm parameter - empty value\n");
361 return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T,
362 &_m->first_line.u.request.method);
365 int autheph_www2(struct sip_msg *_m, char *_realm, char *_method)
370 if (eph_auth_api.pre_auth == NULL)
372 LM_ERR("autheph_www() cannot be used without the auth "
377 if(_m == NULL || _realm == NULL)
379 LM_ERR("invalid parameters\n");
383 if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
388 if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
390 LM_ERR("failed to get realm value\n");
396 LM_ERR("invalid realm parameter - empty value\n");
400 if (get_str_fparam(&smethod, _m, (fparam_t*)_method) < 0)
402 LM_ERR("failed to get method value\n");
406 if (smethod.len == 0)
408 LM_ERR("invalid method value - empty value\n");
412 return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T, &smethod);
415 int autheph_proxy(struct sip_msg *_m, char *_realm)
419 if (eph_auth_api.pre_auth == NULL)
421 LM_ERR("autheph_proxy() cannot be used without the auth "
426 if(_m == NULL || _realm == NULL)
428 LM_ERR("invalid parameters\n");
432 if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
437 if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
439 LM_ERR("failed to get realm value\n");
445 LM_ERR("invalid realm parameter - empty value\n");
449 return digest_authenticate(_m, &srealm, HDR_PROXYAUTH_T,
450 &_m->first_line.u.request.method);
453 int autheph_authenticate(struct sip_msg *_m, char *_username, char *_password)
455 str susername, spassword;
456 char generated_password[base64_enc_len(SHA_DIGEST_LENGTH)];
457 str sgenerated_password;
458 struct secret *secret_struct;
460 if (_m == NULL || _username == NULL || _password == NULL)
462 LM_ERR("invalid parameters\n");
466 if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0)
468 LM_ERR("failed to get username value\n");
472 if (susername.len == 0)
474 LM_ERR("invalid username parameter - empty value\n");
478 if (get_str_fparam(&spassword, _m, (fparam_t*)_password) < 0)
480 LM_ERR("failed to get password value\n");
484 if (spassword.len == 0)
486 LM_ERR("invalid password parameter - empty value\n");
490 if (autheph_verify_timestamp(&susername) < 0)
492 LM_ERR("invalid timestamp in username\n");
496 LM_DBG("username: %.*s\n", susername.len, susername.s);
497 LM_DBG("password: %.*s\n", spassword.len, spassword.s);
499 sgenerated_password.s = generated_password;
501 secret_struct = secret_list;
502 while (secret_struct != NULL)
504 LM_DBG("trying secret: %.*s\n",
505 secret_struct->secret_key.len,
506 secret_struct->secret_key.s);
507 if (get_pass(&susername, &secret_struct->secret_key,
508 &sgenerated_password) == 0)
510 LM_DBG("generated password: %.*s\n",
511 sgenerated_password.len, sgenerated_password.s);
512 if (strncmp(spassword.s, sgenerated_password.s,
519 secret_struct = secret_struct->next;