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; |