opensips/modules/uac/auth.c

changeset 18
8ec65b8f6e2c
parent 16
c5c55937e44c
equal deleted inserted replaced
0:f1a3a0c644fe 1:56ed910ccf3a
22 * 22 *
23 * History: 23 * History:
24 * --------- 24 * ---------
25 * 2005-01-31 first version (ramona) 25 * 2005-01-31 first version (ramona)
26 * 2006-03-02 UAC authentication looks first in AVPs for credential (bogdan) 26 * 2006-03-02 UAC authentication looks first in AVPs for credential (bogdan)
27 * 2010-01-18 UAC replaces proxy-auth entries with new credentials (msvb)
27 */ 28 */
28 29
29 30
30 #include <ctype.h> 31 #include <ctype.h>
31 #include <string.h> 32 #include <string.h>
373 struct cell *t; 374 struct cell *t;
374 struct hdr_field *hdr; 375 struct hdr_field *hdr;
375 HASHHEX response; 376 HASHHEX response;
376 str *new_hdr; 377 str *new_hdr;
377 378
379 /* pretransact */
380 int nret = 0;
381 pv_value_t pv_val;
382 str *newuri = 0;
383 struct uac_credential *tst = 0;
384 struct hdr_field *tmp_hdr = 0;
385 struct hdr_field *del_hdr = 0;
386
387
388 /* Goes something like this... */
389 /* HA1 = echo -n 'username:realm:password' | md5sum */
390 /* echo -n 'itsme:mydom.com:stupidpass' | md5sum */
391 /* HA2 = echo -n 'message:uri' | md5sum */
392 /* echo -n 'INVITE:sip:danc@ing.fool.es' | md5sum */
393 /* Response = echo -n 'HA1:nonce:HA2' | md5sum */
378 /* get transaction */ 394 /* get transaction */
379 t = uac_tmb.t_gett(); 395 t = uac_tmb.t_gett();
380 if (t==T_UNDEFINED || t==T_NULL_CELL) 396 if (t==T_UNDEFINED || t==T_NULL_CELL) {
381 { 397 /* begin without any transaction */
382 LM_CRIT("no current transaction found\n"); 398 /* set relevant structure variables */
383 goto error; 399 crd = 0;
384 } 400 crd = pkg_malloc(sizeof(struct uac_credential));
385 401 if (!crd) {
402 LM_ERR("no more pkg memory\n");
403 goto error;
404 }
405
406 /* set the realm from existing UAC message */
407 tmp_hdr = msg->proxy_auth;
408 del_hdr = 0;
409 while (tmp_hdr) {
410 crd->realm.s = strchr(strstr(tmp_hdr->body.s, "realm="), '"') + 1;
411 crd->realm.len = strchr(crd->realm.s, '"') - crd->realm.s;
412 if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
413 && pv_val.rs.len>0) /* ensure realm is the desired one */
414 if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0)
415 del_hdr = tmp_hdr;
416 tmp_hdr = tmp_hdr->sibling;
417 }
418 if (del_hdr)
419 crd->realm = pv_val.rs; /* success */
420 else
421 nret++; /* failure */
422
423 /* set username from new AVP proxy values */
424 if(pv_get_spec_value(msg, &auth_username_spec, &pv_val)!=0 \
425 || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
426 nret++; /* signal failure with nonzero value */
427 else
428 crd->user = pv_val.rs;
429
430 /* set password from new AVP proxy values */
431 if(pv_get_spec_value(msg, &auth_password_spec, &pv_val)!=0 \
432 || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
433 nret++; /* signal failure with nonzero value */
434 else
435 crd->passwd = pv_val.rs;
436
437 if (nret) { /* if not found, look into predefined credentials */
438 tst = lookup_realm(&crd->realm);
439
440 if (tst==0) { /* found? */
441 LM_DBG("no credential for realm \"%.*s\"\n", \
442 crd->realm.len, crd->realm.s);
443 pkg_free(crd);
444 goto error;
445 }
446
447 crd = tst; /* use predefined credentials */
448 /* set the realm from existing UAC message */
449 tmp_hdr = msg->proxy_auth;
450 del_hdr = 0;
451 while (tmp_hdr) {
452 if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
453 && pv_val.rs.len>0) /* ensure realm is the desired one */
454 if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0)
455 del_hdr = tmp_hdr;
456 tmp_hdr = tmp_hdr->sibling;
457 }
458 if (del_hdr == 0) { /* proxy-auth header matching realm not found */
459 LM_DBG("no credential for realm \"%.*s\"\n", \
460 crd->realm.len, crd->realm.s);
461 pkg_free(crd);
462 goto error;
463 }
464 }
465
466 /* set the uri from existing UAC message */
467 newuri = pkg_malloc(sizeof(str));
468 if (!newuri) {
469 LM_ERR("no more pkg memory\n");
470 goto error;
471 }
472 newuri->s = pkg_malloc(msg->new_uri.len);
473 if (!newuri->s) {
474 LM_ERR("no more pkg memory\n");
475 pkg_free(newuri);
476 goto error;
477 }
478 newuri->len = msg->new_uri.len;
479 strncpy(newuri->s, msg->new_uri.s, msg->new_uri.len);
480 if (!newuri->s) {
481 LM_DBG("failed to retrieve URI from UAC message\n");
482 pkg_free(newuri->s);
483 pkg_free(newuri);
484 goto error;
485 }
486
487 /* set the nonce from existing UAC message */
488 tmp_hdr = msg->proxy_auth;
489 auth.nonce.len = 0;
490 auth.nonce.s = 0;
491 while (tmp_hdr) {
492 if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
493 && pv_val.rs.len>0) /* ensure realm is the desired one */
494 if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) {
495 auth.nonce.s = strchr(strstr(tmp_hdr->body.s, "nonce="), '"') + 1;
496 auth.nonce.len = strchr(auth.nonce.s, '"') - auth.nonce.s;
497 }
498 tmp_hdr = tmp_hdr->sibling;
499 }
500 if (auth.nonce.s == 0) {
501 LM_DBG("failed to retrieve nonce from UAC message\n");
502 pkg_free(crd);
503 goto error;
504 }
505
506 /* do authentication */
507 do_uac_auth(msg, newuri, crd, &auth, response);
508 if (response==0) {
509 LM_ERR("failed to calculate challenge response\n");
510 pkg_free(crd);
511 goto error;
512 }
513
514 /* build the authorization header */
515 new_hdr = build_authorization_hdr(407, newuri, crd, &auth, response);
516 if (new_hdr==0) {
517 LM_ERR("failed to build authorization hdr\n");
518 pkg_free(crd);
519 goto error;
520 }
521
522 /* remove the old proxy-auth header and relink message index */
523 /* before updating the authorization credentials of the message */
524 if (del_hdr) { /* updated a record and must remove the old one */
525 if (del_lump(msg, del_hdr->name.s - msg->buf, del_hdr->len, 0)==0) {
526 LM_ERR("can't remove credentials\n");
527 pkg_free(crd);
528 goto error;
529 }
530 }
531
532 /* so far, so good -> add the header and set the proper RURI */
533 if (apply_urihdr_changes(msg, newuri, new_hdr)<0)
534 {
535 LM_ERR("failed to apply changes\n");
536 pkg_free(crd);
537 goto error;
538 }
539
540 pkg_free(crd); /* finished calculating new response string, success */
541 return 0;
542 } /* if (t==T_UNDEFINED || t==T_NULL_CELL) */
543
544 /* begin with transaction reply */
386 /* get the selected branch */ 545 /* get the selected branch */
387 branch = uac_tmb.t_get_picked(); 546 branch = uac_tmb.t_get_picked();
388 if (branch<0) { 547 if (branch<0) {
389 LM_CRIT("no picked branch (%d)\n",branch); 548 LM_CRIT("no picked branch (%d)\n",branch);
390 goto error; 549 goto error;

mercurial