1 /*
2 * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
3 * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
4 *
5 * The initial version of this code was written by Dragos Vingarzan
6 * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
7 * Fruanhofer Institute. It was and still is maintained in a separate
8 * branch of the original SER. We are therefore migrating it to
9 * Kamailio/SR and look forward to maintaining it from here on out.
10 * 2011/2012 Smile Communications, Pty. Ltd.
11 * ported/maintained/improved by
12 * Jason Penton (jason(dot)penton(at)smilecoms.com and
13 * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
14 * effort to add full IMS support to Kamailio/SR using a new and
15 * improved architecture
16 *
17 * NB: Alot of this code was originally part of OpenIMSCore,
18 * FhG Fokus.
19 * Copyright (C) 2004-2006 FhG Fokus
20 * Thanks for great work! This is an effort to
21 * break apart the various CSCF functions into logically separate
22 * components. We hope this will drive wider use. We also feel
23 * that in this way the architecture is more complete and thereby easier
24 * to manage in the Kamailio/SR environment
25 *
26 * This file is part of Kamailio, a free SIP server.
27 *
28 * Kamailio is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 2 of the License, or
31 * (at your option) any later version
32 *
33 * Kamailio is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
41 *
42 */
43
44 #include <string.h>
45 #include "../../core/ut.h"
46 #include "../../core/str.h"
47 #include "../../core/basex.h"
48 #include "../../core/hashes.h"
49 #include "../../lib/srdb1/db.h"
50 #include "../../lib/srdb1/db_ut.h"
51 #include "../../core/dprint.h"
52 #include "../../core/parser/digest/digest.h"
53 #include "../../core/parser/hf.h"
54 #include "../../core/parser/parser_f.h"
55 #include "../../core/usr_avp.h"
56 #include "../../core/mod_fix.h"
57 #include "../../core/mem/mem.h"
58 #include "../../core/rand/kam_rand.h"
59 #include "../cdp/diameter.h"
60 #include "../cdp/diameter_ims_code_result.h"
61
62 #include "cxdx_mar.h"
63 #include "cxdx_avp.h"
64
65
66 #include "../../lib/ims/ims_getters.h"
67 #include "../tm/tm_load.h"
68 #include "api.h"
69 #include "ims_auth_mod.h"
70 #include "authorize.h"
71 #include "utils.h"
72 #include "../../core/action.h" /* run_actions */
73
74 extern unsigned char registration_default_algorithm_type; /**< fixed default algorithm for registration (if none present) */
75 extern struct tm_binds tmb;
76 extern struct cdp_binds cdpb;
77
78 extern str registration_qop_str; /**< the qop options to put in the authorization challenges */
79 extern str invite_qop_str; /**< the qop options to put in the authorization challenges for INVITE*/
80 extern int av_request_at_sync; /**< how many auth vectors to request in a sync MAR */
81 extern int av_request_at_once; /**< how many auth vectors to request in a MAR */
82 extern int auth_vector_timeout;
83 extern int auth_data_timeout; /**< timeout for a hash entry to expire when empty in sec */
84 extern int auth_used_vector_timeout;
85 extern int add_authinfo_hdr;
86 extern int max_nonce_reuse;
87 extern str scscf_name_str;
88 extern int ignore_failed_auth;
89 extern int av_check_only_impu;
90
91 auth_hash_slot_t *auth_data; /**< Authentication vector hash table */
92 static int act_auth_data_hash_size = 0; /**< authentication vector hash table size */
93
94 static str empty_s = {0, 0};
95
96 str S_WWW = {"WWW", 3};
97 str S_Proxy = {"Proxy", 5};
98 str S_Authorization_AKA = {"%.*s-Authenticate: Digest realm=\"%.*s\","
99 " nonce=\"%.*s\", algorithm=%.*s, ck=\"%.*s\", ik=\"%.*s\"%.*s\r\n", 107};
100 str S_Authorization_MD5 = {"%.*s-Authenticate: Digest realm=\"%.*s\","
101 " nonce=\"%.*s\", algorithm=%.*s%.*s\r\n", 102};
102
103 str algorithm_types[] = {
104 {"unknown", 7},
105 {"AKAv1-MD5", 9},
106 {"AKAv2-MD5", 9},
107 {"Early-IMS", 9},
108 {"MD5", 3},
109 {"CableLabs-Digest", 16},
110 {"3GPP-Digest", 11},
111 {"TISPAN-HTTP_DIGEST_MD5", 22},
112 {"NASS-Bundled", 12},
113 {0, 0}
114 };
115
116 str auth_scheme_types[] = {
117 {"unknown", 7},
118 {"Digest-AKAv1-MD5", 16},
119 {"Digest-AKAv2-MD5", 16},
120 {"Early-IMS-Security", 18},
121 {"Digest-MD5", 10},
122 {"Digest", 6},
123 {"SIP Digest", 10},
124 {"HTTP_DIGEST_MD5", 15},
125 {"NASS-Bundled", 12},
126 {0, 0}
127 };
128
129 /**
130 * Convert the SIP Algorithm to its type
131 * @param algorithm - the SIP Algorithm
132 * @returns the algorithm type
133 */
get_algorithm_type(str algorithm)134 unsigned char get_algorithm_type(str algorithm) {
135 int i;
136 for (i = 0; algorithm_types[i].len > 0; i++)
137 if (algorithm_types[i].len == algorithm.len
138 && strncasecmp(algorithm_types[i].s, algorithm.s, algorithm.len)
139 == 0)
140 return i;
141 return AUTH_UNKNOWN;
142 }
143
144 /**
145 * Convert the Diameter Authorization Scheme to its type
146 * @param scheme - the Diameter Authorization Scheme
147 * @returns the SIP Algorithm
148 */
get_auth_scheme_type(str scheme)149 unsigned char get_auth_scheme_type(str scheme) {
150 int i;
151 for (i = 0; auth_scheme_types[i].len > 0; i++)
152 if (auth_scheme_types[i].len == scheme.len &&
153 strncasecmp(auth_scheme_types[i].s, scheme.s, scheme.len) == 0)
154 return i;
155 return AUTH_UNKNOWN;
156 }
157
158 /*
159 * Authorize digest credentials
160 */
digest_authenticate(struct sip_msg * msg,str * realm,str * table,hdr_types_t hftype)161 static int digest_authenticate(struct sip_msg* msg, str *realm,
162 str *table, hdr_types_t hftype) {
163 return 0;
164 }
165
166 /**
167 * Starts the reg_await_timer for an authentication vector.
168 * @param av - the authentication vector
169 */
start_reg_await_timer(auth_vector * av)170 void start_reg_await_timer(auth_vector *av) {
171 av->expires = get_ticks() + auth_vector_timeout;
172 av->status = AUTH_VECTOR_SENT;
173 }
174
175 /**
176 * Timer callback for reg await timers.
177 * Drops the auth vectors that have been sent and are expired
178 * Also drops the useless auth vectors - used and no longer needed
179 * @param ticks - what's the time
180 * @param param - a given parameter to be called with
181 */
reg_await_timer(unsigned int ticks,void * param)182 void reg_await_timer(unsigned int ticks, void* param) {
183 auth_userdata *aud, *aud_next;
184 auth_vector *av, *av_next;
185 int i;
186
187 LM_DBG("Looking for expired/useless at %d\n", ticks);
188 for (i = 0; i < act_auth_data_hash_size; i++) {
189 auth_data_lock(i);
190 aud = auth_data[i].head;
191 while (aud) {
192 LM_DBG("Slot %4d <%.*s>\n",
193 aud->hash, aud->private_identity.len, aud->private_identity.s);
194 aud_next = aud->next;
195 av = aud->head;
196 while (av) {
197 LM_DBG(".. AV %4d - %d Exp %3d %p\n",
198 av->item_number, av->status, (int) av->expires, av);
199 av_next = av->next;
200 if (av->status == AUTH_VECTOR_USELESS ||
201 ((av->status == AUTH_VECTOR_USED || av->status == AUTH_VECTOR_SENT) && av->expires < ticks)
202 ) {
203 LM_DBG("... dropping av %d - %d\n",
204 av->item_number, av->status);
205 if (av->prev) av->prev->next = av->next;
206 else aud->head = av->next;
207 if (av->next) av->next->prev = av->prev;
208 else aud->tail = av->prev;
209 free_auth_vector(av);
210 }
211 av = av_next;
212 }
213 if (!aud->head) {
214 if (aud->expires == 0) {
215 LM_DBG("... started empty aud drop timer\n");
216 aud->expires = ticks + auth_data_timeout;
217 } else
218 if (aud->expires < ticks) {
219 LM_DBG("... dropping aud \n");
220 if (aud->prev) aud->prev->next = aud->next;
221 else auth_data[i].head = aud->next;
222 if (aud->next) aud->next->prev = aud->prev;
223 else auth_data[i].tail = aud->prev;
224 free_auth_userdata(aud);
225 }
226 } else aud->expires = 0;
227
228 aud = aud_next;
229 }
230 auth_data_unlock(i);
231 }
232 LM_DBG("[DONE] Looking for expired/useless at %d\n", ticks);
233 }
234
235 /*
236 * Authenticate using Proxy-Authorize header field
237 */
238
239 /*
240 int proxy_authenticate(struct sip_msg* _m, char* _realm, char* _table) {
241 str srealm;
242 str stable;
243
244 if (_table == NULL) {
245 LM_ERR("invalid table parameter\n");
246 return -1;
247 }
248
249 stable.s = _table;
250 stable.len = strlen(stable.s);
251
252 if (get_str_fparam(&srealm, _m, (fparam_t*) _realm) < 0) {
253 LM_ERR("failed to get realm value\n");
254 return -1; //AUTH_ERROR;
255 }
256
257 if (srealm.len == 0) {
258 LM_ERR("invalid realm parameter - empty value\n");
259 return -1; //AUTH_ERROR;
260 }
261 LM_DBG("realm value [%.*s]\n", srealm.len, srealm.s);
262
263 return digest_authenticate(_m, &srealm, &stable, HDR_PROXYAUTH_T);
264 }
265 */
challenge(struct sip_msg * msg,char * str1,char * alg,int is_proxy_auth,char * route)266 int challenge(struct sip_msg* msg, char* str1, char* alg, int is_proxy_auth, char *route) {
267
268 str realm = {0, 0}, algo = {0,0};
269 unsigned int aud_hash;
270 str private_identity, public_identity, auts = {0, 0}, nonce = {0, 0};
271 auth_vector *av = 0;
272 int algo_type = 0;
273 str route_name;
274
275 saved_transaction_t* saved_t;
276 tm_cell_t *t = 0;
277 cfg_action_t* cfg_action;
278
279 if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
280 LM_ERR("no async route block for assign_server_unreg\n");
281 return -1;
282 }
283
284 if (!alg) {
285 LM_DBG("no algorithm specified in cfg... using default\n");
286 } else {
287 if (get_str_fparam(&algo, msg, (fparam_t*) alg) < 0) {
288 LM_ERR("failed to get auth algorithm\n");
289 return -1;
290 }
291 }
292
293 LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
294 int ri = route_get(&main_rt, route_name.s);
295 if (ri < 0) {
296 LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
297 return -1;
298 }
299 cfg_action = main_rt.rlist[ri];
300 if (cfg_action == NULL) {
301 LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
302 return -1;
303 }
304
305 if (get_str_fparam(&realm, msg, (fparam_t*) str1) < 0) {
306 LM_ERR("failed to get realm value\n");
307 return CSCF_RETURN_ERROR;
308 }
309
310 if (realm.len == 0) {
311 LM_ERR("invalid realm value - empty content\n");
312 return CSCF_RETURN_ERROR;
313 }
314
315 create_return_code(CSCF_RETURN_ERROR);
316
317 LM_DBG("Need to challenge for realm [%.*s]\n", realm.len, realm.s);
318
319 if (msg->first_line.type != SIP_REQUEST) {
320 LM_ERR("This message is not a request\n");
321 return CSCF_RETURN_ERROR;
322 }
323 if (!is_proxy_auth) {
324 LM_DBG("Checking if REGISTER is authorized for realm [%.*s]...\n", realm.len, realm.s);
325
326 /* First check the parameters */
327 if (msg->first_line.u.request.method.len != 8 ||
328 memcmp(msg->first_line.u.request.method.s, "REGISTER", 8) != 0) {
329 LM_ERR("This message is not a REGISTER request\n");
330 return CSCF_RETURN_ERROR;
331 }
332 }
333
334 /* get the private_identity */
335 if (is_proxy_auth)
336 private_identity = cscf_get_private_identity_from(msg, realm);
337 else
338 private_identity = cscf_get_private_identity(msg, realm);
339 if (!private_identity.len) {
340 LM_ERR("No private identity specified (Authorization: username)\n");
341 stateful_request_reply(msg, 403, MSG_403_NO_PRIVATE);
342 return CSCF_RETURN_BREAK;
343 }
344 /* get the public_identity */
345 if (is_proxy_auth)
346 public_identity = cscf_get_public_identity_from(msg);
347 else
348 public_identity = cscf_get_public_identity(msg);
349
350 if (!public_identity.len) {
351 LM_ERR("No public identity specified (To:)\n");
352 stateful_request_reply(msg, 403, MSG_403_NO_PUBLIC);
353 return CSCF_RETURN_BREAK;
354 }
355
356 if (algo.len > 0) {
357 algo_type = get_algorithm_type(algo);
358 } else {
359 algo_type = registration_default_algorithm_type;
360 }
361
362 // /* check if it is a synchronization request */
363 // //TODO this is MAR syncing - have removed it currently - TOD maybe put back in
364 // auts = ims_get_auts(msg, realm, is_proxy_auth);
365 // if (auts.len) {
366 // LM_DBG("IMS Auth Synchronization requested <%.*s>\n", auts.len, auts.s);
367 //
368 // nonce = ims_get_nonce(msg, realm);
369 // if (nonce.len == 0) {
370 // LM_DBG("Nonce not found (Authorization: nonce)\n");
371 // stateful_request_reply(msg, 403, MSG_403_NO_NONCE);
372 // return CSCF_RETURN_BREAK;
373 // }
374 // av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_USED, &nonce, &aud_hash);
375 // if (!av)
376 // av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_SENT, &nonce, &aud_hash);
377 //
378 // if (!av) {
379 // LM_ERR("nonce not recognized as sent, no sync!\n");
380 // auts.len = 0;
381 // auts.s = 0;
382 // } else {
383 // av->status = AUTH_VECTOR_USELESS;
384 // auth_data_unlock(aud_hash);
385 // av = 0;
386 // resync = 1;
387 // }
388 // }
389
390 //RICHARD changed this
391 //Previous approach sent MAR, got MAA then put auth vectors into queue
392 //Then we try and get that auth vector out the queue (it might be used by someone else so we loop)
393 //new approach
394 //we do MAR get MAA (asynchronously) get auth vector use it to pack the vector etc.
395 //set it to sent and set an expires on it
396 //then add it to the queue!
397
398 /* loop because some other process might steal the auth_vector that we just retrieved */
399 //while (!(av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_UNUSED, 0, &aud_hash))) {
400
401 if ((av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_UNUSED, 0, &aud_hash))) {
402 if (!av) {
403 LM_ERR("Error retrieving an auth vector\n");
404 return CSCF_RETURN_ERROR;
405 }
406
407 if (!pack_challenge(msg, realm, av, is_proxy_auth)) {
408 stateful_request_reply(msg, 500, MSG_500_PACK_AV);
409 auth_data_unlock(aud_hash);
410 return CSCF_RETURN_ERROR;
411 }
412
413 start_reg_await_timer(av); //start the timer to remove stale or unused Auth Vectors
414 if (is_proxy_auth) {
415 stateful_request_reply(msg, 407, MSG_407_CHALLENGE);
416 } else {
417 stateful_request_reply(msg, 401, MSG_401_CHALLENGE);
418 }
419 auth_data_unlock(aud_hash);
420
421 } else {
422
423 //before we send lets suspend the transaction
424 t = tmb.t_gett();
425 if (t == NULL || t == T_UNDEFINED) {
426 if (tmb.t_newtran(msg) < 0) {
427 LM_ERR("cannot create the transaction for MAR async\n");
428 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
429 return CSCF_RETURN_BREAK;
430 }
431 t = tmb.t_gett();
432 if (t == NULL || t == T_UNDEFINED) {
433 LM_ERR("cannot lookup the transaction\n");
434 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
435 return CSCF_RETURN_BREAK;
436 }
437 }
438
439 saved_t = shm_malloc(sizeof (saved_transaction_t));
440 if (!saved_t) {
441 LM_ERR("no more memory trying to save transaction state\n");
442 return CSCF_RETURN_ERROR;
443
444 }
445 memset(saved_t, 0, sizeof (saved_transaction_t));
446 saved_t->act = cfg_action;
447
448 saved_t->realm.s = (char*) shm_malloc(realm.len + 1);
449 if (!saved_t->realm.s) {
450 LM_ERR("no more memory trying to save transaction state : callid\n");
451 shm_free(saved_t);
452 return CSCF_RETURN_ERROR;
453 }
454 memset(saved_t->realm.s, 0, realm.len + 1);
455 memcpy(saved_t->realm.s, realm.s, realm.len);
456 saved_t->realm.len = realm.len;
457
458 saved_t->is_proxy_auth = is_proxy_auth;
459
460 LM_DBG("Suspending SIP TM transaction\n");
461 if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) != 0) {
462 LM_ERR("failed to suspend the TM processing\n");
463 free_saved_transaction_data(saved_t);
464 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
465 return CSCF_RETURN_BREAK;
466 }
467
468 if (multimedia_auth_request(msg, public_identity, private_identity, av_request_at_once,
469 auth_scheme_types[algo_type], nonce, auts, scscf_name_str, saved_t)!=0) {
470 LM_ERR("ERR:I_MAR: Error sending MAR or MAR time-out\n");
471 tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel);
472 free_saved_transaction_data(saved_t);
473 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
474 return CSCF_RETURN_BREAK;
475 }
476 }
477 return CSCF_RETURN_BREAK;
478 }
www_challenge2(struct sip_msg * msg,char * _route,char * str1,char * str2)479 int www_challenge2(struct sip_msg* msg, char* _route, char* str1, char* str2) {
480 return challenge(msg, str1, 0, 0, _route);
481 }
482
www_challenge3(struct sip_msg * msg,char * _route,char * str1,char * str2)483 int www_challenge3(struct sip_msg* msg, char* _route, char* str1, char* str2) {
484 return challenge(msg, str1, str2, 0, _route);
485 }
486
www_resync_auth(struct sip_msg * msg,char * _route,char * str1,char * str2)487 int www_resync_auth(struct sip_msg* msg, char* _route, char* str1, char* str2) {
488
489 str realm = {0, 0};
490 unsigned int aud_hash;
491 str private_identity, public_identity, auts = {0, 0}, nonce = {0, 0};
492 auth_vector *av = 0;
493 int algo_type;
494 int is_proxy_auth=0;
495 str route_name;
496
497 saved_transaction_t* saved_t;
498 tm_cell_t *t = 0;
499 cfg_action_t* cfg_action;
500
501 if (fixup_get_svalue(msg, (gparam_t*) _route, &route_name) != 0) {
502 LM_ERR("no async route block for assign_server_unreg\n");
503 return -1;
504 }
505
506 LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
507 int ri = route_get(&main_rt, route_name.s);
508 if (ri < 0) {
509 LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
510 return -1;
511 }
512 cfg_action = main_rt.rlist[ri];
513 if (cfg_action == NULL) {
514 LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
515 return -1;
516 }
517
518 if (get_str_fparam(&realm, msg, (fparam_t*) str1) < 0) {
519 LM_ERR("failed to get realm value\n");
520 return CSCF_RETURN_ERROR;
521 }
522
523 if (realm.len == 0) {
524 LM_ERR("invalid realm value - empty content\n");
525 return CSCF_RETURN_ERROR;
526 }
527
528 create_return_code(CSCF_RETURN_ERROR);
529
530 if (msg->first_line.type != SIP_REQUEST) {
531 LM_ERR("This message is not a request\n");
532 return CSCF_RETURN_ERROR;
533 }
534
535 /* get the private_identity */
536 private_identity = cscf_get_private_identity(msg, realm);
537 if (!private_identity.len) {
538 LM_ERR("No private identity specified (Authorization: username)\n");
539 stateful_request_reply(msg, 403, MSG_403_NO_PRIVATE);
540 return CSCF_RETURN_BREAK;
541 }
542 /* get the public_identity */
543 public_identity = cscf_get_public_identity(msg);
544 if (!public_identity.len) {
545 LM_ERR("No public identity specified (To:)\n");
546 stateful_request_reply(msg, 403, MSG_403_NO_PUBLIC);
547 return CSCF_RETURN_BREAK;
548 }
549
550 algo_type = registration_default_algorithm_type;
551
552 /* check if it is a synchronization request */
553 //TODO this is MAR syncing - have removed it currently - TOD maybe put back in
554 auts = ims_get_auts(msg, realm, is_proxy_auth);
555 if (auts.len) {
556 LM_DBG("IMS Auth Synchronization requested <%.*s>\n", auts.len, auts.s);
557
558 nonce = ims_get_nonce(msg, realm);
559 if (nonce.len == 0) {
560 LM_DBG("Nonce not found (Authorization: nonce)\n");
561 stateful_request_reply(msg, 403, MSG_403_NO_NONCE);
562 return CSCF_RETURN_BREAK;
563 }
564 av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_USED, &nonce, &aud_hash);
565 if (!av)
566 av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_SENT, &nonce, &aud_hash);
567
568 if (!av) {
569 LM_ERR("nonce not recognized as sent, no sync!\n");
570 auts.len = 0;
571 auts.s = 0;
572 } else {
573 av->status = AUTH_VECTOR_USELESS;
574 auth_data_unlock(aud_hash);
575 av = 0;
576 }
577 }
578
579 //before we send lets suspend the transaction
580 t = tmb.t_gett();
581 if (t == NULL || t == T_UNDEFINED) {
582 if (tmb.t_newtran(msg) < 0) {
583 LM_ERR("cannot create the transaction for MAR async\n");
584 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
585 return CSCF_RETURN_BREAK;
586 }
587 t = tmb.t_gett();
588 if (t == NULL || t == T_UNDEFINED) {
589 LM_ERR("cannot lookup the transaction\n");
590 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
591 return CSCF_RETURN_BREAK;
592 }
593 }
594
595 saved_t = shm_malloc(sizeof(saved_transaction_t));
596 if (!saved_t) {
597 LM_ERR("no more memory trying to save transaction state\n");
598 return CSCF_RETURN_ERROR;
599
600 }
601 memset(saved_t, 0, sizeof(saved_transaction_t));
602 saved_t->act = cfg_action;
603
604 saved_t->realm.s = (char*) shm_malloc(realm.len + 1);
605 if (!saved_t->realm.s) {
606 LM_ERR("no more memory trying to save transaction state : callid\n");
607 shm_free(saved_t);
608 return CSCF_RETURN_ERROR;
609 }
610 memset(saved_t->realm.s, 0, realm.len + 1);
611 memcpy(saved_t->realm.s, realm.s, realm.len);
612 saved_t->realm.len = realm.len;
613
614 saved_t->is_proxy_auth = is_proxy_auth;
615 saved_t->is_resync = 1;
616
617 LM_DBG("Suspending SIP TM transaction\n");
618 if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) < 0) {
619 LM_ERR("failed to suspend the TM processing\n");
620 free_saved_transaction_data(saved_t);
621
622 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
623 return CSCF_RETURN_BREAK;
624 }
625
626 if (multimedia_auth_request(msg, public_identity, private_identity,
627 av_request_at_sync, auth_scheme_types[algo_type], nonce, auts,
628 scscf_name_str, saved_t) != 0) {
629 LM_ERR("ERR:I_MAR: Error sending MAR or MAR time-out\n");
630 tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel);
631 free_saved_transaction_data(saved_t);
632 stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
633 return CSCF_RETURN_BREAK;
634 }
635
636 return CSCF_RETURN_BREAK;
637 }
638
proxy_challenge(struct sip_msg * msg,char * _route,char * str1,char * str2)639 int proxy_challenge(struct sip_msg* msg, char* _route, char* str1, char* str2) {
640 return challenge(msg, str1, str2, 1, _route);
641 }
642
643 /**
644 * Replies to a REGISTER and also adds the need headers
645 * Path and Service-Route are added.
646 * @param msg - the SIP message to operator on
647 * @param code - Reason Code for the response
648 * @param text - Reason Phrase for the response
649 * @returns #CSCF_RETURN_TRUE on success or #CSCF_RETURN_FALSE if not added
650 */
stateful_request_reply(struct sip_msg * msg,int code,char * text)651 int stateful_request_reply(struct sip_msg *msg, int code, char *text) {
652 unsigned int hash, label;
653 struct hdr_field *h;
654 str t = {0, 0};
655 if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
656 LM_ERR("Error parsing headers\n");
657 return -1;
658 }
659 h = msg->headers;
660 while (h) {
661 if (h->name.len == 4 &&
662 strncasecmp(h->name.s, "Path", 4) == 0) {
663 t.s = h->name.s;
664 t.len = h->len;
665 ims_add_header_rpl(msg, &(t));
666 }
667 h = h->next;
668 }
669
670 /*if (code==200){
671 ims_add_header_rpl(msg,&scscf_service_route);
672 }*/ //TODO: need to get the service route from somewhere - registrar?
673
674
675 if (tmb.t_get_trans_ident(msg, &hash, &label) < 0) {
676 if (tmb.t_newtran(msg) < 0)
677 LM_INFO("Failed creating SIP transaction\n");
678 }
679 return tmb.t_reply(msg, code, text);
680
681 }
682
683 /**
684 * Replies to a REGISTER and also adds the need headers
685 * Path and Service-Route are added.
686 * @param msg - the SIP message to operator on
687 * @param code - Reason Code for the response
688 * @param text - Reason Phrase for the response
689 * @returns #CSCF_RETURN_TRUE on success or #CSCF_RETURN_FALSE if not added
690 */
691
stateful_request_reply_async(struct cell * t_cell,struct sip_msg * msg,int code,char * text)692 int stateful_request_reply_async(struct cell* t_cell, struct sip_msg *msg, int code, char *text) {
693 struct hdr_field *h;
694 str t = {0, 0};
695 if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
696 LM_ERR("Error parsing headers\n");
697 return -1;
698 }
699 h = msg->headers;
700 while (h) {
701 if (h->name.len == 4 &&
702 strncasecmp(h->name.s, "Path", 4) == 0) {
703 t.s = h->name.s;
704 t.len = h->len;
705 ims_add_header_rpl(msg, &(t));
706 }
707 h = h->next;
708 }
709
710 return tmb.t_reply_trans(t_cell, msg, code, text);
711
712 }
713
authenticate(struct sip_msg * msg,char * _realm,char * str2,int is_proxy_auth)714 int authenticate(struct sip_msg* msg, char* _realm, char* str2, int is_proxy_auth) {
715 int ret = -1; //CSCF_RETURN_FALSE;
716 unsigned int aud_hash = 0;
717 str realm;
718 str private_identity, public_identity, username;
719 str nonce, response16, nc, cnonce, qop_str = {0, 0}, auts = {0, 0}, body, *next_nonce = &empty_s;
720 enum qop_type qop = QOP_UNSPEC;
721 str uri = {0, 0};
722 HASHHEX expected, ha1, hbody = {0}, rspauth;
723 int expected_len = 32;
724 int expires = 0;
725 auth_vector *av = 0;
726 uint32_t nc_parsed = 0; /* the numerical representation of nc */
727
728 LM_DBG("Running authenticate, is_proxy_auth=%d\n", is_proxy_auth);
729
730 ret = AUTH_ERROR;
731
732 if (get_str_fparam(&realm, msg, (fparam_t*) _realm) < 0) {
733 LM_ERR("failed to get realm value\n");
734 return AUTH_NO_CREDENTIALS;
735 }
736
737 if (realm.len == 0) {
738 LM_ERR("invalid realm value - empty content\n");
739 return AUTH_NO_CREDENTIALS;
740 }
741
742 if (msg->first_line.type != SIP_REQUEST) {
743 LM_ERR("This message is not a request\n");
744 ret = AUTH_ERROR;
745 goto end;
746 }
747 if (!is_proxy_auth) {
748 LM_DBG("Checking if REGISTER is authorized for realm [%.*s]...\n", realm.len, realm.s);
749
750 /* First check the parameters */
751 if (msg->first_line.u.request.method.len != 8 ||
752 memcmp(msg->first_line.u.request.method.s, "REGISTER", 8) != 0) {
753 LM_ERR("This message is not a REGISTER request\n");
754 ret = AUTH_ERROR;
755 goto end;
756 }
757 }
758
759 if (!realm.len) {
760 LM_ERR("No realm found\n");
761 return 0; //CSCF_RETURN_BREAK;
762 }
763
764 if (is_proxy_auth) {
765 private_identity = cscf_get_private_identity_from(msg, realm);
766 } else {
767 private_identity = cscf_get_private_identity(msg, realm);
768 }
769 if (!private_identity.len) {
770 LM_ERR("private identity missing\n");
771 return AUTH_NO_CREDENTIALS;
772 }
773
774 if (is_proxy_auth)
775 public_identity = cscf_get_public_identity_from(msg);
776 else
777 public_identity = cscf_get_public_identity(msg);
778
779 if (!public_identity.len) {
780 LM_ERR("public identity missing\n");
781 return AUTH_NO_CREDENTIALS;
782 }
783
784 if (!get_nonce_response(msg, &username, realm, &nonce, &response16, &qop, &qop_str, &nc, &cnonce, &uri, is_proxy_auth) ||
785 !nonce.len || !response16.len) {
786 LM_DBG("Nonce or response missing: nonce len [%i], response16 len[%i]\n", nonce.len, response16.len);
787 return AUTH_ERROR;
788 }
789
790 if (qop == QOP_AUTHINT) {
791 body = ims_get_body(msg);
792 calc_H(&body, hbody);
793 }
794
795 /* first, look for an already used vector (if nonce reuse is enabled) */
796 if (max_nonce_reuse > 0) {
797 LM_DBG("look for an already used vector for %.*s\n",
798 private_identity.len, private_identity.s);
799 av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_USED, &nonce, &aud_hash);
800 }
801
802 if (!av) {
803 /* if none found, or nonce reuse is disabled, look for a fresh vector
804 * We should also drop every other used vector at this point
805 * (there souldn't be more than one) */
806 LM_DBG("Looking for auth vector based on IMPI: [%.*s] and IMPU: [%.*s]\n", private_identity.len, private_identity.s, public_identity.len, public_identity.s);
807 auth_userdata *aud;
808 auth_vector *av_it;
809 aud = get_auth_userdata(private_identity, public_identity);
810 if (aud) {
811 av_it = aud->head;
812 while (av_it) {
813 if (av_it->status == AUTH_VECTOR_USED) {
814 LM_DBG("vector %p is marked for deletion\n", av_it);
815 av_it->status = AUTH_VECTOR_USELESS;
816 }
817 av_it = av_it->next;
818 }
819 auth_data_unlock(aud->hash);
820 }
821
822 LM_DBG("look for a fresh vector for %.*s\n",
823 private_identity.len, private_identity.s);
824 av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_SENT, &nonce, &aud_hash);
825 }
826
827 LM_INFO("uri=%.*s nonce=%.*s response=%.*s qop=%.*s nc=%.*s cnonce=%.*s hbody=%.*s\n",
828 uri.len, uri.s,
829 nonce.len, nonce.s,
830 response16.len, response16.s,
831 qop_str.len, qop_str.s,
832 nc.len, nc.s,
833 cnonce.len, cnonce.s,
834 32, hbody);
835
836 if (!av) {
837 LM_DBG("no matching auth vector found - maybe timer expired\n");
838
839 if (ignore_failed_auth) {
840 LM_WARN("NB: Ignoring all failed auth - check your config if you don't expect this\n");
841 ret = AUTH_OK;
842 }
843
844 goto end;
845 }
846
847 if (qop != QOP_UNSPEC) {
848 /* if QOP is sent, nc must be specified */
849 /* the expected nc is the last used one plus 1 */
850 int p;
851 if (!nc.s || nc.len < 8 ) {
852 LM_ERR("qop specified with no nonce count... failing\n");
853 goto cleanup;
854 }
855 for (p = 0; p < 8; ++p) { /* nc is 8LHEX (RFC 2617 §3.2.2) */
856 nc_parsed = (nc_parsed << 4) | UNHEX((int) nc.s[p]);
857 }
858 LM_DBG("nc is %08x, expected: %08x\n",
859 nc_parsed, av->use_nb + 1);
860 if (nc_parsed <= av->use_nb) { /* nc is lower than expected */
861 ret = AUTH_NONCE_REUSED;
862 av->status = AUTH_VECTOR_USELESS; /* invalidate this vector if any mistake/error occurs */
863 goto cleanup;
864 } else if (nc_parsed > av->use_nb + 1) { /* nc is bigger than expected */
865 ret = AUTH_ERROR;
866 av->status = AUTH_VECTOR_USELESS;
867 goto cleanup;
868 }
869 }
870
871 switch (av->type) {
872 case AUTH_AKAV1_MD5:
873 case AUTH_AKAV2_MD5:
874 case AUTH_MD5:
875 calc_HA1(HA_MD5, &username/*&private_identity*/, &realm, &(av->authorization), &(av->authenticate), &cnonce, ha1);
876 calc_response(ha1, &(av->authenticate),
877 &nc,
878 &cnonce,
879 &qop_str,
880 qop == QOP_AUTHINT,
881 &msg->first_line.u.request.method, &uri, hbody, expected);
882 LM_INFO("UE said: %.*s and we expect %.*s ha1 %.*s (%.*s)\n",
883 response16.len, response16.s,
884 /*av->authorization.len,av->authorization.s,*/32, expected,
885 32, ha1,
886 msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
887 break;
888 case AUTH_SIP_DIGEST:
889 case AUTH_DIGEST:
890 // memcpy of received HA1
891 memcpy(ha1, av->authorization.s, HASHHEXLEN);
892 calc_response(ha1, &(av->authenticate),
893 &nc,
894 &cnonce,
895 &qop_str,
896 qop == QOP_AUTHINT,
897 &msg->first_line.u.request.method, &uri, hbody, expected);
898 LM_INFO("UE said: %.*s and we expect %.*s ha1 %.*s (%.*s)\n",
899 response16.len, response16.s,
900 32,expected,
901 32,ha1,
902 msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
903 break;
904 default:
905 LM_ERR("algorithm %.*s is not handled.\n",
906 algorithm_types[av->type].len, algorithm_types[av->type].s);
907 ret = AUTH_ERROR;
908 goto cleanup; /* release aud before returning */
909 }
910
911 expires = cscf_get_max_expires(msg, 0);
912
913 if (response16.len == expected_len && strncasecmp(response16.s, expected, response16.len) == 0) {
914 if (max_nonce_reuse > 0 && av->status == AUTH_VECTOR_SENT) {
915 /* first use of a reusable vector */
916 /* set the vector's new timeout */
917 LM_DBG("vector %p now expires in %d seconds\n", av, auth_used_vector_timeout);
918 av->expires = get_ticks() + auth_used_vector_timeout;
919 }
920 av->use_nb++;
921 LM_DBG("vector %p successfully used %d time(s)\n", av, av->use_nb);
922
923 if (av->use_nb == max_nonce_reuse + 1) {
924 LM_DBG("vector %p isn't fresh anymore, recycle it with a new nonce\n", av);
925
926 int i;
927 char y[NONCE_LEN];
928 for (i = 0; i < NONCE_LEN; i++)
929 y[i] = (unsigned char) ((int) (256.0 * kam_rand() / (KAM_RAND_MAX + 1.0)));
930
931 if (unlikely((av->authenticate.len < 2 * NONCE_LEN))) {
932 if (av->authenticate.s) {
933 shm_free(av->authenticate.s);
934 }
935 av->authenticate.len = 2 * NONCE_LEN;
936 av->authenticate.s = shm_malloc(av->authenticate.len);
937 }
938
939 if (!av->authenticate.s) {
940 LM_ERR("new_auth_vector: failed allocating %d bytes!\n", av->authenticate.len);
941 av->authenticate.len = 0;
942 goto cleanup;
943 }
944
945 av->authenticate.len = bin_to_base16(y, NONCE_LEN, av->authenticate.s);
946
947 next_nonce = &(av->authenticate);
948 av->status = AUTH_VECTOR_USED;
949 av->use_nb = 0;
950 av->expires = get_ticks() + auth_used_vector_timeout; /* reset the timer */
951
952 } else if (expires == 0) { /* de-registration */
953 LM_DBG("de-registration, vector %p isn't needed anymore\n", av);
954 av->status = AUTH_VECTOR_USELESS;
955 } else {
956 av->status = AUTH_VECTOR_USED;
957 /* nextnonce is the current nonce */
958 next_nonce = &nonce;
959 }
960 ret = AUTH_OK;
961
962 if (add_authinfo_hdr && expires != 0 /* don't add auth. info if de-registation */) {
963 /* calculate rspauth */
964 calc_response(ha1, &nonce,
965 &nc,
966 &cnonce,
967 &qop_str,
968 qop == QOP_AUTHINT,
969 0, &uri, hbody, rspauth);
970
971 add_authinfo_resp_hdr(msg, *next_nonce, qop_str, rspauth, cnonce, nc);
972 }
973
974
975 } else {
976 char authorise[200];
977 char authenticate_bin[200];
978 char authenticate_hex[200];
979 memset(authorise, 0, 200);
980 memset(authenticate_bin, 0, 200);
981 memset(authenticate_hex, 0, 200);
982
983 int authorise_len = bin_to_base16(av->authorization.s, av->authorization.len, authorise);
984 int authenticate_len = base64_to_bin(av->authenticate.s, av->authenticate.len, authenticate_bin);
985 int authenticate_hex_len = bin_to_base16(authenticate_bin, authenticate_len, authenticate_hex);
986 av->status = AUTH_VECTOR_USELESS; /* first mistake, you're out! (but maybe it's synchronization) */
987 LM_DBG("UE said: %.*s, but we expect %.*s : authenticate(b64) is [%.*s], authenticate(hex) is [%.*s], authorise is [%d] [%.*s]\n",
988 response16.len, response16.s,
989 32, expected,
990 av->authenticate.len, av->authenticate.s,
991 authenticate_hex_len,authenticate_hex,
992 authorise_len,
993 authorise_len, authorise);
994 // /* check for auts in authorization header - if it is then we need to resync */
995 auts = ims_get_auts(msg, realm, is_proxy_auth);
996 if (auts.len) {
997 LM_DBG("IMS Auth Synchronization requested <%.*s>\n", auts.len, auts.s);
998 ret = AUTH_RESYNC_REQUESTED;
999 av->status = AUTH_VECTOR_SENT;
1000 } else {
1001 ret = AUTH_INVALID_PASSWORD;
1002 }
1003 }
1004
1005 if (ignore_failed_auth) {
1006 LM_WARN("NB: Ignoring all failed auth - check your config if you don't expect this\n");
1007 ret = AUTH_OK;
1008 }
1009
1010 cleanup:
1011 auth_data_unlock(aud_hash);
1012 end:
1013 return ret;
1014 }
1015
1016 /*
1017 * Authenticate using WWW-Authorize header field
1018 */
www_authenticate(struct sip_msg * msg,char * _realm,char * str2)1019 int www_authenticate(struct sip_msg* msg, char* _realm, char* str2) {
1020 return authenticate(msg, _realm, str2, 0);
1021 }
1022
1023 /*
1024 * Authenticate using WWW-Authorize header field
1025 */
proxy_authenticate(struct sip_msg * msg,char * _realm,char * str2)1026 int proxy_authenticate(struct sip_msg* msg, char* _realm, char* str2) {
1027 return authenticate(msg, _realm, str2, 1);
1028 }
1029
1030 /**
1031 * @brief bind functions to IMS AUTH API structure
1032 */
bind_ims_auth(ims_auth_api_t * api)1033 int bind_ims_auth(ims_auth_api_t * api) {
1034 if (!api) {
1035 ERR("Invalid parameter value\n");
1036 return -1;
1037 }
1038 api->digest_authenticate = digest_authenticate;
1039
1040 return 0;
1041 }
1042
1043 /**
1044 * Retrieve an authentication vector.
1045 * \note returns with a lock, so unlock it when done
1046 * @param private_identity - the private identity
1047 * @param public_identity - the public identity
1048 * @param status - the status of the authentication vector
1049 * @param nonce - the nonce in the auth vector
1050 * @param hash - the hash to unlock when done
1051 * @returns the auth_vector* if found or NULL if not
1052 */
get_auth_vector(str private_identity,str public_identity,int status,str * nonce,unsigned int * hash)1053 auth_vector * get_auth_vector(str private_identity, str public_identity, int status, str *nonce, unsigned int *hash) {
1054 auth_userdata *aud;
1055 auth_vector *av;
1056 aud = get_auth_userdata(private_identity, public_identity);
1057 if (!aud) {
1058 LM_ERR("no auth userdata\n");
1059 goto error;
1060 }
1061
1062 av = aud->head;
1063 while (av) {
1064 LM_DBG("looping through AV status is %d and were looking for %d\n", av->status, status);
1065 if (av->status == status && (nonce == 0 || (nonce->len == av->authenticate.len && memcmp(nonce->s, av->authenticate.s, nonce->len) == 0))) {
1066 LM_DBG("Found result\n");
1067 *hash = aud->hash;
1068 return av;
1069 }
1070 av = av->next;
1071 }
1072
1073 error:
1074 if (aud) auth_data_unlock(aud->hash);
1075 return 0;
1076 }
1077
1078 /**
1079 * Locks the required slot of the auth_data.
1080 * @param hash - the index of the slot
1081 */
auth_data_lock(unsigned int hash)1082 void auth_data_lock(unsigned int hash) {
1083 lock_get(auth_data[(hash)].lock);
1084 }
1085
1086 /**
1087 * UnLocks the required slot of the auth_data
1088 * @param hash - the index of the slot
1089 */
auth_data_unlock(unsigned int hash)1090 void auth_data_unlock(unsigned int hash) {
1091 lock_release(auth_data[(hash)].lock);
1092 }
1093
1094 /**
1095 * Initializes the Authorization Data structures.
1096 * @param size - size of the hash table
1097 * @returns 1 on success or 0 on error
1098 */
auth_data_init(int size)1099 int auth_data_init(int size) {
1100 int i;
1101 auth_data = shm_malloc(sizeof (auth_hash_slot_t) * size);
1102 if (!auth_data) {
1103 LM_ERR("error allocating mem\n");
1104 return 0;
1105 }
1106 memset(auth_data, 0, sizeof (auth_hash_slot_t) * size);
1107 for (i = 0; i < size; i++) {
1108 auth_data[i].lock = lock_alloc();
1109 lock_init(auth_data[i].lock);
1110 }
1111 act_auth_data_hash_size = size;
1112 return 1;
1113 }
1114
1115 /**
1116 * Destroy the Authorization Data structures */
auth_data_destroy()1117 void auth_data_destroy() {
1118 int i;
1119 auth_userdata *aud, *next;
1120 for (i = 0; i < act_auth_data_hash_size; i++) {
1121 auth_data_lock(i);
1122 lock_destroy(auth_data[i].lock);
1123 lock_dealloc(auth_data[i].lock);
1124 aud = auth_data[i].head;
1125 while (aud) {
1126 next = aud->next;
1127 free_auth_userdata(aud);
1128 aud = next;
1129 }
1130 }
1131 if (auth_data) shm_free(auth_data);
1132 }
1133
1134 /**
1135 * Create new authorization vector
1136 * @param item_number - number to index it in the vectors list
1137 * @param auth_scheme - Diameter Authorization Scheme
1138 * @param authenticate - the challenge
1139 * @param authorization - the expected response
1140 * @param ck - the cypher key
1141 * @param ik - the integrity key
1142 * @returns the new auth_vector* or NULL on error
1143 */
new_auth_vector(int item_number,str auth_scheme,str authenticate,str authorization,str ck,str ik)1144 auth_vector * new_auth_vector(int item_number, str auth_scheme, str authenticate,
1145 str authorization, str ck, str ik) {
1146 auth_vector *x = 0;
1147 char base16_ck[32+1] = {0};
1148 int base16_ck_len = 0;
1149 x = shm_malloc(sizeof (auth_vector));
1150 if (!x) {
1151 LM_ERR("error allocating mem\n");
1152 goto done;
1153 }
1154 memset(x, 0, sizeof (auth_vector));
1155 x->item_number = item_number;
1156 x->type = get_auth_scheme_type(auth_scheme);
1157 switch (x->type) {
1158 case AUTH_AKAV1_MD5:
1159 case AUTH_AKAV2_MD5:
1160 /* AKA */
1161 x->authenticate.len = authenticate.len * 4 / 3 + 4;
1162 x->authenticate.s = shm_malloc(x->authenticate.len);
1163 if (!x->authenticate.s) {
1164 LM_ERR("error allocating mem\n");
1165 goto done;
1166 }
1167 x->authenticate.len = bin_to_base64(authenticate.s, authenticate.len,
1168 x->authenticate.s);
1169
1170 x->authorization.len = authorization.len;
1171 x->authorization.s = shm_malloc(x->authorization.len);
1172 if (!x->authorization.s) {
1173 LM_ERR("error allocating mem\n");
1174 goto done;
1175 }
1176 memcpy(x->authorization.s, authorization.s, authorization.len);
1177 x->ck.len = ck.len;
1178 x->ck.s = shm_malloc(ck.len);
1179 if (!x->ck.s) {
1180 LM_ERR("error allocating mem\n");
1181 goto done;
1182 }
1183 memcpy(x->ck.s, ck.s, ck.len);
1184
1185 x->ik.len = ik.len;
1186 x->ik.s = shm_malloc(ik.len);
1187 if (!x->ik.s) {
1188 LM_ERR("error allocating mem\n");
1189 goto done;
1190 }
1191 memcpy(x->ik.s, ik.s, ik.len);
1192 break;
1193
1194 case AUTH_MD5:
1195 /* MD5 */
1196 x->authenticate.len = authenticate.len * 2;
1197 x->authenticate.s = shm_malloc(x->authenticate.len);
1198 if (!x->authenticate.s) {
1199 LM_ERR("new_auth_vector: error allocating mem\n");
1200 goto done;
1201 }
1202 x->authenticate.len = bin_to_base16(authenticate.s, authenticate.len,
1203 x->authenticate.s);
1204
1205 x->authorization.len = authorization.len;
1206 x->authorization.s = shm_malloc(x->authorization.len);
1207 if (!x->authorization.s) {
1208 LM_ERR("new_auth_vector: error allocating mem\n");
1209 goto done;
1210 }
1211 memcpy(x->authorization.s, authorization.s, authorization.len);
1212 x->authorization.len = authorization.len;
1213 break;
1214 case AUTH_DIGEST:
1215 case AUTH_SIP_DIGEST:
1216 {
1217 int i;
1218 char y[NONCE_LEN];
1219 for (i = 0; i < NONCE_LEN; i++)
1220 y[i] = (unsigned char) ((int) (256.0 * kam_rand() / (KAM_RAND_MAX + 1.0)));
1221 x->authenticate.len = 2 * NONCE_LEN;
1222 x->authenticate.s = shm_malloc(x->authenticate.len);
1223 if (!x->authenticate.s) {
1224 LM_ERR("new_auth_vector: failed allocating %d bytes!\n", x->authenticate.len);
1225 x->authenticate.len = 0;
1226 goto done;
1227 }
1228 x->authenticate.len = bin_to_base16(y, NONCE_LEN, x->authenticate.s);
1229 }
1230
1231 x->authorization.len = authorization.len;
1232 x->authorization.s = shm_malloc(x->authorization.len);
1233 if (!x->authorization.s) {
1234 LM_ERR("new_auth_vector: error allocating mem\n");
1235 x->authorization.len = 0;
1236 goto done;
1237 }
1238 memcpy(x->authorization.s, authorization.s, authorization.len);
1239 x->authorization.len = authorization.len;
1240
1241 break;
1242 case AUTH_HTTP_DIGEST_MD5:
1243 x->authenticate.len = authenticate.len;
1244 x->authenticate.s = shm_malloc(x->authenticate.len);
1245 if (!x->authenticate.s) {
1246 LM_ERR("new_auth_vector: error allocating mem\n");
1247 x->authenticate.len = 0;
1248 goto done;
1249 }
1250 memcpy(x->authenticate.s, authenticate.s, authenticate.len);
1251
1252 x->authorization.len = authorization.len;
1253 x->authorization.s = shm_malloc(x->authorization.len);
1254 if (!x->authorization.s) {
1255 LM_ERR("new_auth_vector: error allocating mem\n");
1256 x->authorization.len = 0;
1257 goto done;
1258 }
1259 memcpy(x->authorization.s, authorization.s, authorization.len);
1260 break;
1261 case AUTH_EARLY_IMS:
1262 /* early IMS */
1263 x->authenticate.len = 0;
1264 x->authenticate.s = 0;
1265 x->authorization.len = authorization.len;
1266 x->authorization.s = shm_malloc(x->authorization.len);
1267 if (!x->authorization.s) {
1268 LM_ERR("new_auth_vector: error allocating mem\n");
1269 goto done;
1270 }
1271 memcpy(x->authorization.s, authorization.s, authorization.len);
1272 x->authorization.len = authorization.len;
1273 break;
1274 case AUTH_NASS_BUNDLED:
1275 /* NASS-Bundled */
1276 x->authenticate.len = 0;
1277 x->authenticate.s = 0;
1278 x->authorization.len = authorization.len;
1279 x->authorization.s = shm_malloc(x->authorization.len);
1280 if (!x->authorization.s) {
1281 LM_ERR("new_auth_vector: error allocating mem\n");
1282 goto done;
1283 }
1284 memcpy(x->authorization.s, authorization.s, authorization.len);
1285 x->authorization.len = authorization.len;
1286 break;
1287
1288 default:
1289 /* all else */
1290 x->authenticate.len = 0;
1291 x->authenticate.s = 0;
1292
1293 }
1294
1295 x->use_nb = 0;
1296
1297 x->next = 0;
1298 x->prev = 0;
1299 x->status = AUTH_VECTOR_UNUSED;
1300 x->expires = 0;
1301
1302 if (x->ck.len > 0 && x->ck.s) {
1303 base16_ck_len = bin_to_base16(x->ck.s, 16, base16_ck);
1304 if (base16_ck_len)
1305 LM_DBG("new auth-vector with ck [%s] with status %d\n", base16_ck, x->status);
1306 }
1307
1308 done:
1309 return x;
1310 }
1311
1312 /**
1313 * Frees the memory taken by a authentication vector
1314 * @param av - the vector to be freed
1315 */
free_auth_vector(auth_vector * av)1316 void free_auth_vector(auth_vector * av) {
1317 if (av) {
1318 if (av->authenticate.s) shm_free(av->authenticate.s);
1319 if (av->authorization.s) shm_free(av->authorization.s);
1320 if (av->ck.s) shm_free(av->ck.s);
1321 if (av->ik.s) shm_free(av->ik.s);
1322 shm_free(av);
1323 }
1324 }
1325
1326 /**
1327 * Creates a new Authorization Userdata structure.
1328 * @param private_identity - the private identity to attach to
1329 * @param public_identity - the public identity to attach to
1330 * @returns the new auth_userdata* on success or NULL on error
1331 */
new_auth_userdata(str private_identity,str public_identity)1332 auth_userdata * new_auth_userdata(str private_identity, str public_identity) {
1333 auth_userdata *x = 0;
1334
1335 x = shm_malloc(sizeof (auth_userdata));
1336 if (!x) {
1337 LM_ERR("error allocating mem\n");
1338 goto done;
1339 }
1340
1341 x->private_identity.len = private_identity.len;
1342 x->private_identity.s = shm_malloc(private_identity.len);
1343 if (!x) {
1344 LM_ERR("error allocating mem\n");
1345 goto done;
1346 }
1347 memcpy(x->private_identity.s, private_identity.s, private_identity.len);
1348
1349 x->public_identity.len = public_identity.len;
1350 x->public_identity.s = shm_malloc(public_identity.len);
1351 if (!x) {
1352 LM_ERR("error allocating mem\n");
1353 goto done;
1354 }
1355 memcpy(x->public_identity.s, public_identity.s, public_identity.len);
1356
1357 x->head = 0;
1358 x->tail = 0;
1359
1360 x->next = 0;
1361 x->prev = 0;
1362
1363 done:
1364 return x;
1365 }
1366
1367 /**
1368 * Deallocates the auth_userdata.
1369 * @param aud - the auth_userdata to be deallocated
1370 */
free_auth_userdata(auth_userdata * aud)1371 void free_auth_userdata(auth_userdata * aud) {
1372 auth_vector *av, *next;
1373 if (aud) {
1374 if (aud->private_identity.s) shm_free(aud->private_identity.s);
1375 if (aud->public_identity.s) shm_free(aud->public_identity.s);
1376 av = aud->head;
1377 while (av) {
1378 next = av->next;
1379 free_auth_vector(av);
1380 av = next;
1381 }
1382 shm_free(aud);
1383 }
1384 }
1385
1386 /**
1387 * Computes a hash based on the private and public identities
1388 * @param private_identity - the private identity
1389 * @param public_identity - the public identity
1390 * @returns the hash % Auth_data->size
1391 */
get_hash_auth(str private_identity,str public_identity)1392 unsigned int get_hash_auth(str private_identity, str public_identity) {
1393 if (av_check_only_impu)
1394 return core_hash(&public_identity, 0, act_auth_data_hash_size);
1395 else
1396 return core_hash(&public_identity, 0, act_auth_data_hash_size);
1397 /*
1398
1399
1400 #define h_inc h+=v^(v>>3)
1401 char* p;
1402 register unsigned v;
1403 register unsigned h;
1404
1405 h = 0;
1406 for (p = private_identity.s; p <= (private_identity.s + private_identity.len - 4); p += 4) {
1407 v = (*p << 24)+(p[1] << 16)+(p[2] << 8) + p[3];
1408 h_inc;
1409 }
1410 v = 0;
1411 for (; p < (private_identity.s + private_identity.len); p++) {
1412 v <<= 8;
1413 v += *p;
1414 }
1415 h_inc;
1416 for (p = public_identity.s; p <= (public_identity.s + public_identity.len - 4); p += 4) {
1417 v = (*p << 24)+(p[1] << 16)+(p[2] << 8) + p[3];
1418 h_inc;
1419 }
1420 v = 0;
1421 for (; p < (public_identity.s + public_identity.len); p++) {
1422 v <<= 8;
1423 v += *p;
1424 }
1425
1426 h = ((h)+(h >> 11))+((h >> 13)+(h >> 23));
1427 return (h) % auth_data_hash_size;
1428 #undef h_inc
1429 */
1430 }
1431
1432 /**
1433 * Retrieve the auth_userdata for a user.
1434 * \note you will return with lock on the hash slot, so release it!
1435 * @param private_identity - the private identity
1436 * @param public_identity - the public identity
1437 * @returns the auth_userdata* found or newly created on success, NULL on error
1438 */
get_auth_userdata(str private_identity,str public_identity)1439 auth_userdata * get_auth_userdata(str private_identity, str public_identity) {
1440
1441 unsigned int hash = 0;
1442 auth_userdata *aud = 0;
1443
1444 hash = get_hash_auth(private_identity, public_identity);
1445 auth_data_lock(hash);
1446 aud = auth_data[hash].head;
1447 if (av_check_only_impu)
1448 LM_DBG("Searching auth_userdata for IMPU %.*s (Hash %d)\n", public_identity.len, public_identity.s, hash);
1449 else
1450 LM_DBG("Searching auth_userdata for IMPU %.*s / IMPI %.*s (Hash %d)\n", public_identity.len, public_identity.s,
1451 private_identity.len, private_identity.s, hash);
1452
1453 while (aud) {
1454 if (av_check_only_impu) {
1455 if (aud->public_identity.len == public_identity.len &&
1456 memcmp(aud->public_identity.s, public_identity.s, public_identity.len) == 0) {
1457 LM_DBG("Found auth_userdata\n");
1458 return aud;
1459 }
1460 } else {
1461 if (aud->private_identity.len == private_identity.len &&
1462 aud->public_identity.len == public_identity.len &&
1463 memcmp(aud->private_identity.s, private_identity.s, private_identity.len) == 0 &&
1464 memcmp(aud->public_identity.s, public_identity.s, public_identity.len) == 0) {
1465 LM_DBG("Found auth_userdata\n");
1466 return aud;
1467 }
1468 }
1469
1470 aud = aud->next;
1471 }
1472 /* if we get here, there is no auth_userdata for this user */
1473 aud = new_auth_userdata(private_identity, public_identity);
1474 if (!aud) {
1475 auth_data_unlock(hash);
1476 return 0;
1477 }
1478
1479 aud->prev = auth_data[hash].tail;
1480 aud->next = 0;
1481 aud->hash = hash;
1482
1483 if (!auth_data[hash].head) auth_data[hash].head = aud;
1484 if (auth_data[hash].tail) auth_data[hash].tail->next = aud;
1485 auth_data[hash].tail = aud;
1486
1487 return aud;
1488 }
1489
1490 /**
1491 * Sends a Multimedia-Authentication-Response to retrieve some authentication vectors and maybe synchronize.
1492 * Must respond with a SIP reply every time it returns 0
1493 * @param msg - the SIP REGISTER message
1494 * @param public_identity - the public identity
1495 * @param private_identity - the private identity
1496 * @param count - how many vectors to request
1497 * @param algorithm - which algorithm to request
1498 * @param nonce - the challenge that will be sent
1499 * @param auts - the AKA synchronization or empty string if not a synchronization
1500 * @param server_name - the S-CSCF name to be saved on the HSS
1501 * @returns 1 on success, 0 on failure
1502 */
multimedia_auth_request(struct sip_msg * msg,str public_identity,str private_identity,int count,str auth_scheme,str nonce,str auts,str servername,saved_transaction_t * transaction_data)1503 int multimedia_auth_request(struct sip_msg *msg, str public_identity, str private_identity,
1504 int count, str auth_scheme, str nonce, str auts, str servername, saved_transaction_t* transaction_data) {
1505
1506
1507 str authorization = {0, 0};
1508 int result = -1;
1509
1510 int is_sync = 0;
1511 if (auts.len) {
1512 authorization.s = pkg_malloc(nonce.len * 3 / 4 + auts.len * 3 / 4 + 8);
1513 if (!authorization.s) {
1514 LM_ERR("no more pkg mem\n");
1515 return result;
1516 }
1517 authorization.len = base64_to_bin(nonce.s, nonce.len, authorization.s);
1518 authorization.len = RAND_LEN;
1519 authorization.len += base64_to_bin(auts.s, auts.len, authorization.s + authorization.len);
1520 is_sync = 1;
1521 }
1522
1523 if (is_sync) {
1524 drop_auth_userdata(private_identity, public_identity);
1525 }
1526
1527
1528 LM_DBG("Sending MAR\n");
1529 result = cxdx_send_mar(msg, public_identity, private_identity, count, auth_scheme, authorization, servername, transaction_data);
1530 if (authorization.s) pkg_free(authorization.s);
1531
1532 return result;
1533 }
1534
1535 /**
1536 * Adds the WWW-Authenticate header for challenge, based on the authentication vector.
1537 * @param msg - SIP message to add the header to
1538 * @param realm - the realm
1539 * @param av - the authentication vector
1540 * @returns 1 on success, 0 on error
1541 */
pack_challenge(struct sip_msg * msg,str realm,auth_vector * av,int is_proxy_auth)1542 int pack_challenge(struct sip_msg *msg, str realm, auth_vector *av, int is_proxy_auth) {
1543 str x = {0, 0};
1544 char ck[32], ik[32];
1545 int ck_len, ik_len;
1546 str *auth_prefix = is_proxy_auth ? &S_Proxy : &S_WWW;
1547 str qop;
1548 int is_invite;
1549
1550 is_invite = (msg->first_line.u.request.method_value == METHOD_INVITE) ? 1:0;
1551 if (is_invite) {
1552 qop.s = invite_qop_str.s;
1553 qop.len = invite_qop_str.len;
1554 LM_DBG("setting QOP str used is [%.*s]\n", invite_qop_str.len, invite_qop_str.s);
1555 // av->type = AUTH_MD5;
1556 } else {
1557 qop.s = registration_qop_str.s;
1558 qop.len = registration_qop_str.len;
1559 LM_DBG("setting QOP str used is [%.*s]\n", registration_qop_str.len, registration_qop_str.s);
1560 }
1561 LM_DBG("QOP str used is [%.*s]\n", qop.len, qop.s);
1562
1563
1564 switch (av->type) {
1565 case AUTH_AKAV1_MD5:
1566 case AUTH_AKAV2_MD5:
1567 /* AKA */
1568 ck_len = bin_to_base16(av->ck.s, 16, ck);
1569 ik_len = bin_to_base16(av->ik.s, 16, ik);
1570 x.len = S_Authorization_AKA.len + auth_prefix->len + realm.len + av->authenticate.len
1571 + algorithm_types[av->type].len + ck_len + ik_len
1572 + qop.len;
1573 x.s = pkg_malloc(x.len);
1574 if (!x.s) {
1575 LM_ERR("Error allocating %d bytes\n",
1576 x.len);
1577 goto error;
1578 }
1579 sprintf(x.s, S_Authorization_AKA.s, auth_prefix->len, auth_prefix->s, realm.len, realm.s,
1580 av->authenticate.len, av->authenticate.s,
1581 algorithm_types[av->type].len, algorithm_types[av->type].s,
1582 ck_len, ck, ik_len, ik, qop.len,
1583 qop.s);
1584 x.len = strlen(x.s);
1585 break;
1586 case AUTH_HTTP_DIGEST_MD5:
1587 /* ETSI HTTP_DIGEST MD5 */
1588 /* this one continues into the next one */
1589 case AUTH_DIGEST:
1590 /* Cable-Labs MD5 */
1591 /* this one continues into the next one */
1592 case AUTH_SIP_DIGEST:
1593 /* 3GPP MD5 */
1594 /* this one continues into the next one */
1595 case AUTH_MD5:
1596 /* FOKUS MD5 */
1597 x.len = S_Authorization_MD5.len + auth_prefix->len + realm.len + av->authenticate.len
1598 + algorithm_types[av->type].len + qop.len;
1599 x.s = pkg_malloc(x.len);
1600 if (!x.s) {
1601 LM_ERR("pack_challenge: Error allocating %d bytes\n", x.len);
1602 goto error;
1603 }
1604 sprintf(x.s, S_Authorization_MD5.s, auth_prefix->len, auth_prefix->s, realm.len, realm.s,
1605 av->authenticate.len, av->authenticate.s,
1606 algorithm_types[AUTH_MD5].len, algorithm_types[AUTH_MD5].s,
1607 qop.len, qop.s);
1608 x.len = strlen(x.s);
1609 break;
1610
1611 default:
1612 LM_CRIT("not implemented for algorithm %.*s\n",
1613 algorithm_types[av->type].len, algorithm_types[av->type].s);
1614 goto error;
1615 }
1616
1617 if (ims_add_header_rpl(msg, &x)) {
1618 pkg_free(x.s);
1619 return 1;
1620 }
1621
1622 error:
1623 if (x.s)
1624 pkg_free(x.s);
1625
1626 return 0;
1627 }
1628
1629 /**
1630 * Adds the Authentication-Info header for, based on the credentials sent by a successful REGISTER.
1631 * @param msg - SIP message to add the header to
1632 * @returns 1 on success, 0 on error
1633 */
add_authinfo_resp_hdr(struct sip_msg * msg,str nextnonce,str qop,HASHHEX rspauth,str cnonce,str nc)1634 int add_authinfo_resp_hdr(struct sip_msg *msg, str nextnonce, str qop, HASHHEX rspauth, str cnonce, str nc) {
1635
1636 str authinfo_hdr;
1637 static const char authinfo_fmt[] = "Authentication-Info: "
1638 "nextnonce=\"%.*s\","
1639 "qop=%.*s,"
1640 "rspauth=\"%.*s\","
1641 "cnonce=\"%.*s\","
1642 "nc=%.*s\r\n";
1643
1644 authinfo_hdr.len = sizeof (authinfo_fmt) + nextnonce.len + qop.len + HASHHEXLEN + cnonce.len + nc.len - 20 /* format string parameters */ - 1 /* trailing \0 */;
1645 authinfo_hdr.s = pkg_malloc(authinfo_hdr.len + 1);
1646
1647 if (!authinfo_hdr.s) {
1648 LM_ERR("add_authinfo_resp_hdr: Error allocating %d bytes\n", authinfo_hdr.len);
1649 goto error;
1650 }
1651 snprintf(authinfo_hdr.s, authinfo_hdr.len + 1, authinfo_fmt,
1652 nextnonce.len, nextnonce.s,
1653 qop.len, qop.s,
1654 HASHHEXLEN, rspauth,
1655 cnonce.len, cnonce.s,
1656 nc.len, nc.s);
1657 LM_DBG("authinfo hdr built: %.*s", authinfo_hdr.len, authinfo_hdr.s);
1658 if (ims_add_header_rpl(msg, &authinfo_hdr)) {
1659 LM_DBG("authinfo hdr added");
1660 pkg_free(authinfo_hdr.s);
1661 return 1;
1662 }
1663 error:
1664 if (authinfo_hdr.s) pkg_free(authinfo_hdr.s);
1665
1666 return 0;
1667 }
1668
1669 /**
1670 * Add an authentication vector to the authentication userdata storage.
1671 * @param private_identity - the private identity
1672 * @param public_identity - the public identity
1673 * @param av - the authentication vector
1674 * @returns 1 on success or 0 on error
1675 */
add_auth_vector(str private_identity,str public_identity,auth_vector * av)1676 int add_auth_vector(str private_identity, str public_identity, auth_vector * av) {
1677 auth_userdata *aud;
1678 aud = get_auth_userdata(private_identity, public_identity);
1679 if (!aud) goto error;
1680
1681 LM_DBG("Adding auth_vector (status %d) for IMPU %.*s / IMPI %.*s (Hash %d)\n", av->status,
1682 public_identity.len, public_identity.s,
1683 private_identity.len, private_identity.s, aud->hash);
1684
1685
1686 av->prev = 0;
1687 if (aud->head) {
1688 av->next = aud->head;
1689 aud->head->prev = av;
1690 }
1691
1692 aud->head = av;
1693
1694 auth_data_unlock(aud->hash);
1695 return 1;
1696 error:
1697
1698 return 0;
1699 }
1700
1701 /**
1702 * Declares all auth vectors as useless when we do a synchronization
1703 * @param private_identity - the private identity
1704 * @param public_identity - the public identity
1705 * @returns 1 on success, 0 on error
1706 */
drop_auth_userdata(str private_identity,str public_identity)1707 int drop_auth_userdata(str private_identity, str public_identity) {
1708 auth_userdata *aud;
1709 auth_vector *av;
1710 aud = get_auth_userdata(private_identity, public_identity);
1711 if (!aud) goto error;
1712
1713 av = aud->head;
1714 while (av) {
1715 LM_DBG("dropping auth vector that was in status %d\n", av->status);
1716 av->status = AUTH_VECTOR_USELESS;
1717 av = av->next;
1718 }
1719 auth_data_unlock(aud->hash);
1720 return 1;
1721 error:
1722 LM_DBG("no authdata to drop any auth vectors\n");
1723 if (aud) auth_data_unlock(aud->hash);
1724 return 0;
1725 }
1726