a5b3f48e928e328043c248b5af66ca2bc38326c9
[sip-router] / src / modules / auth_ephemeral / authorize.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2013 Crocodile RCS Ltd
5  * Copyright (C) 2017 ng-voice GmbH
6  *
7  * This file is part of Kamailio, a free SIP server.
8  *
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
13  *
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.
18  *
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
22  *
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.
27  *
28  */
29 #include <openssl/hmac.h>
30 #include <openssl/sha.h>
31
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"
40
41 #include "auth_ephemeral_mod.h"
42 #include "authorize.h"
43
44 static inline int get_pass(str *_username, str *_secret, str *_password)
45 {
46         unsigned int hmac_len = SHA_DIGEST_LENGTH;
47         unsigned char hmac_sha1[512];
48
49         switch(autheph_sha_alg) {
50                 case AUTHEPH_SHA1:
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)
55                         {
56                                 LM_ERR("HMAC-SHA1 failed\n");
57                                 return -1;
58                         }
59                         break;
60                 case AUTHEPH_SHA256:
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)
65                         {
66                                 LM_ERR("HMAC-SHA256 failed\n");
67                                 return -1;
68                         }
69                         break;
70                 case AUTHEPH_SHA384:
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)
75                         {
76                                 LM_ERR("HMAC-SHA256 failed\n");
77                                 return -1;
78                         }
79                         break;
80                 case AUTHEPH_SHA512:
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)
85                         {
86                                 LM_ERR("HMAC-SHA512 failed\n");
87                                 return -1;
88                         }
89                         break;
90                 default:
91                         LM_ERR("Inavlid SHA Algorithm\n");
92                         return -1;
93
94         }
95
96         LM_DBG("HMAC-Len (%i)\n", hmac_len);
97
98
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);
103
104         return 0;
105 }
106
107 static inline int get_ha1(struct username *_username, str *_domain,
108                                 str *_secret, char *_ha1)
109 {
110         char password[base64_enc_len(SHA512_DIGEST_LENGTH)];
111         str spassword;
112
113         spassword.s = (char *) password;
114         spassword.len = 0;
115
116         if (get_pass(&_username->whole, _secret, &spassword) < 0)
117         {
118                 LM_ERR("calculating password\n");
119                 return -1;
120         }
121
122         eph_auth_api.calc_HA1(HA_MD5, &_username->whole, _domain, &spassword,
123                                 0, 0, _ha1);
124         LM_DBG("calculated HA1: %s\n", _ha1);
125
126         return 0;
127 }
128
129 static inline int do_auth(struct sip_msg *_m, struct hdr_field *_h, str *_realm,
130                         str *_method, str *_secret)
131 {
132         int ret;
133         char ha1[512];
134         auth_body_t *cred = (auth_body_t*) _h->parsed;
135
136         LM_DBG("secret: %.*s (%i)\n", _secret->len, _secret->s, _secret->len);
137
138         if (get_ha1(&cred->digest.username, _realm, _secret, ha1) < 0)
139         {
140                 LM_ERR("calculating HA1\n");
141                 return AUTH_ERROR;
142         }
143
144         LM_DBG("HA1: %i\n", (int)strlen(ha1));
145         
146         ret = eph_auth_api.check_response(&cred->digest, _method, ha1);
147         if (ret == AUTHENTICATED)
148         {
149                 if (eph_auth_api.post_auth(_m, _h, ha1) != AUTHENTICATED)
150                 {
151                         return AUTH_ERROR;
152                 }
153         }
154         else if (ret == NOT_AUTHENTICATED)
155         {
156                 return AUTH_INVALID_PASSWORD;
157         }
158         else
159         {
160                 ret = AUTH_ERROR;
161         }
162
163         return AUTH_OK;
164 }
165
166 int autheph_verify_timestamp(str *_username)
167 {
168         int pos = 0, cur_time = (int) time(NULL);
169         unsigned int expires;
170         str time_str = {0, 0};
171
172         while (pos < _username->len && _username->s[pos] != ':')
173                 pos++;
174
175         if (autheph_username_format == AUTHEPH_USERNAME_NON_IETF)
176         {
177                 if (pos < _username->len - 1)
178                 {
179                         time_str.s = _username->s + pos + 1;
180                         time_str.len = _username->len - pos - 1;
181                 }
182                 else
183                 {
184                         time_str.s = _username->s;
185                         time_str.len = _username->len;
186                 }
187         }
188         else
189         {
190                 time_str.s = _username->s;
191                 if (pos < _username->len - 1)
192                 {
193                         time_str.len = pos;
194                 }
195                 else
196                 {
197                         time_str.len = _username->len;
198                 }
199         }
200
201         LM_DBG("username timestamp: %.*s\n", time_str.len, time_str.s);
202         if (str2int(&time_str, &expires) < 0)
203         {
204                 LM_ERR("unable to convert timestamp to int\n");
205                 return -1;
206         }
207
208         LM_DBG("current time: %d\n", cur_time);
209         if (cur_time > expires)
210         {
211                 LM_WARN("username has expired\n");
212                 return -1;
213         }
214
215         return 0;
216 }
217
218 static inline int digest_authenticate(struct sip_msg *_m, str *_realm,
219                                 hdr_types_t _hftype, str *_method)
220 {
221         struct hdr_field* h;
222         int ret;
223         struct secret *secret_struct;
224         str username;
225
226         LM_DBG("realm: %.*s\n", _realm->len, _realm->s);
227         LM_DBG("method: %.*s\n", _method->len, _method->s);
228
229         ret = eph_auth_api.pre_auth(_m, _realm, _hftype, &h, NULL);
230         switch(ret)
231         {
232         case NONCE_REUSED:
233                 LM_DBG("nonce reused\n");
234                 return AUTH_NONCE_REUSED;
235         case STALE_NONCE:
236                 LM_DBG("stale nonce\n");
237                 return AUTH_STALE_NONCE;
238         case NO_CREDENTIALS:
239                 LM_DBG("no credentials\n");
240                 return AUTH_NO_CREDENTIALS;
241         case ERROR:
242         case BAD_CREDENTIALS:
243                 LM_DBG("error or bad credentials\n");
244                 return AUTH_ERROR;
245         case CREATE_CHALLENGE:
246                 LM_ERR("CREATE_CHALLENGE is not a valid state\n");
247                 return AUTH_ERROR;
248         case DO_RESYNCHRONIZATION:
249                 LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n");
250                 return AUTH_ERROR;
251         case NOT_AUTHENTICATED:
252                 LM_DBG("not authenticated\n");
253                 return AUTH_ERROR;
254         case DO_AUTHENTICATION:
255                 break;
256         case AUTHENTICATED:
257                 return AUTH_OK;
258         }
259
260         username = ((auth_body_t *) h->parsed)->digest.username.whole;
261         LM_DBG("username: %.*s\n", username.len, username.s);
262
263         if (autheph_verify_timestamp(&username) < 0)
264         {
265                 LM_ERR("invalid timestamp in username\n");
266                 return AUTH_ERROR;
267         }
268
269         SECRET_LOCK;
270         secret_struct = secret_list;
271         while (secret_struct != NULL)
272         {
273                 ret = do_auth(_m, h, _realm, _method,
274                                 &secret_struct->secret_key);
275                 if (ret == AUTH_OK)
276                 {
277                         break;
278                 }
279                 secret_struct = secret_struct->next;
280         }
281         SECRET_UNLOCK;
282
283         return ret;
284 }
285
286 int autheph_check(struct sip_msg *_m, char *_realm)
287 {
288         str srealm;
289
290         if (eph_auth_api.pre_auth == NULL)
291         {
292                 LM_ERR("autheph_check() cannot be used without the auth "
293                         "module\n");
294                 return AUTH_ERROR;
295         }
296
297         if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
298         {
299                 return AUTH_OK;
300         }
301
302         if(_m == NULL || _realm == NULL)
303         {
304                 LM_ERR("invalid parameters\n");
305                 return AUTH_ERROR;
306         }
307
308         if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
309         {
310                 LM_ERR("failed to get realm value\n");
311                 return AUTH_ERROR;
312         }
313
314         if (srealm.len == 0)
315         {
316                 LM_ERR("invalid realm parameter - empty value\n");
317                 return AUTH_ERROR;
318         }
319
320         if (_m->REQ_METHOD == METHOD_REGISTER)
321         {
322                 return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T,
323                                         &_m->first_line.u.request.method);
324         }
325         else
326         {
327                 return digest_authenticate(_m, &srealm, HDR_PROXYAUTH_T,
328                                         &_m->first_line.u.request.method);
329         }
330 }
331
332 int autheph_www(struct sip_msg *_m, char *_realm)
333 {
334         str srealm;
335
336         if (eph_auth_api.pre_auth == NULL)
337         {
338                 LM_ERR("autheph_www() cannot be used without the auth "
339                         "module\n");
340                 return AUTH_ERROR;
341         }
342
343         if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
344         {
345                 return AUTH_OK;
346         }
347
348         if(_m == NULL || _realm == NULL)
349         {
350                 LM_ERR("invalid parameters\n");
351                 return AUTH_ERROR;
352         }
353
354         if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
355         {
356                 LM_ERR("failed to get realm value\n");
357                 return AUTH_ERROR;
358         }
359
360         if (srealm.len == 0)
361         {
362                 LM_ERR("invalid realm parameter - empty value\n");
363                 return AUTH_ERROR;
364         }
365
366         return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T,
367                                         &_m->first_line.u.request.method);
368 }
369
370 int autheph_www2(struct sip_msg *_m, char *_realm, char *_method)
371 {
372         str srealm;
373         str smethod;
374
375         if (eph_auth_api.pre_auth == NULL)
376         {
377                 LM_ERR("autheph_www() cannot be used without the auth "
378                         "module\n");
379                 return AUTH_ERROR;
380         }
381
382         if(_m == NULL || _realm == NULL)
383         {
384                 LM_ERR("invalid parameters\n");
385                 return AUTH_ERROR;
386         }
387
388         if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
389         {
390                 return AUTH_OK;
391         }
392
393         if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
394         {
395                 LM_ERR("failed to get realm value\n");
396                 return AUTH_ERROR;
397         }
398
399         if (srealm.len == 0)
400         {
401                 LM_ERR("invalid realm parameter - empty value\n");
402                 return AUTH_ERROR;
403         }
404
405         if (get_str_fparam(&smethod, _m, (fparam_t*)_method) < 0)
406         {
407                 LM_ERR("failed to get method value\n");
408                 return AUTH_ERROR;
409         }
410
411         if (smethod.len == 0)
412         {
413                 LM_ERR("invalid method value - empty value\n");
414                 return AUTH_ERROR;
415         }
416
417         return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T, &smethod);
418 }
419
420 int autheph_proxy(struct sip_msg *_m, char *_realm)
421 {
422         str srealm;
423
424         if (eph_auth_api.pre_auth == NULL)
425         {
426                 LM_ERR("autheph_proxy() cannot be used without the auth "
427                         "module\n");
428                 return AUTH_ERROR;
429         }
430
431         if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL)
432         {
433                 return AUTH_OK;
434         }
435
436         if(_m == NULL || _realm == NULL)
437         {
438                 LM_ERR("invalid parameters\n");
439                 return AUTH_ERROR;
440         }
441
442         if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0)
443         {
444                 LM_ERR("failed to get realm value\n");
445                 return AUTH_ERROR;
446         }
447
448         if (srealm.len == 0)
449         {
450                 LM_ERR("invalid realm parameter - empty value\n");
451                 return AUTH_ERROR;
452         }
453
454         return digest_authenticate(_m, &srealm, HDR_PROXYAUTH_T,
455                                         &_m->first_line.u.request.method);
456 }
457
458 int autheph_authenticate(struct sip_msg *_m, char *_username, char *_password)
459 {
460         str susername, spassword;
461         char generated_password[base64_enc_len(SHA_DIGEST_LENGTH)];
462         str sgenerated_password;
463         struct secret *secret_struct;
464
465         if (_m == NULL || _username == NULL || _password == NULL)
466         {
467                 LM_ERR("invalid parameters\n");
468                 return AUTH_ERROR;
469         }
470
471         if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0)
472         {
473                 LM_ERR("failed to get username value\n");
474                 return AUTH_ERROR;
475         }
476
477         if (susername.len == 0)
478         {
479                 LM_ERR("invalid username parameter - empty value\n");
480                 return AUTH_ERROR;
481         }
482
483         if (get_str_fparam(&spassword, _m, (fparam_t*)_password) < 0)
484         {
485                 LM_ERR("failed to get password value\n");
486                 return AUTH_ERROR;
487         }
488
489         if (spassword.len == 0)
490         {
491                 LM_ERR("invalid password parameter - empty value\n");
492                 return AUTH_ERROR;
493         }
494
495         if (autheph_verify_timestamp(&susername) < 0)
496         {
497                 LM_ERR("invalid timestamp in username\n");
498                 return AUTH_ERROR;
499         }
500
501         LM_DBG("username: %.*s\n", susername.len, susername.s);
502         LM_DBG("password: %.*s\n", spassword.len, spassword.s);
503
504         sgenerated_password.s = generated_password;
505         SECRET_LOCK;
506         secret_struct = secret_list;
507         while (secret_struct != NULL)
508         {
509                 LM_DBG("trying secret: %.*s\n",
510                         secret_struct->secret_key.len,
511                         secret_struct->secret_key.s);
512                 if (get_pass(&susername, &secret_struct->secret_key,
513                                 &sgenerated_password) == 0)
514                 {
515                         LM_DBG("generated password: %.*s\n",
516                                 sgenerated_password.len, sgenerated_password.s);
517                         if (strncmp(spassword.s, sgenerated_password.s,
518                                         spassword.len) == 0)
519                         {
520                                 SECRET_UNLOCK;
521                                 return AUTH_OK;
522                         }
523                 }
524                 secret_struct = secret_struct->next;
525         }
526         SECRET_UNLOCK;
527
528         return AUTH_ERROR;
529 }