michael@18: Index: modules/uac/auth.c michael@18: diff -Nau modules/uac/auth.c.orig modules/uac/auth.c michael@18: --- modules/uac/auth.c.orig 2010-01-18 12:32:26.152280000 +0100 michael@18: +++ modules/uac/auth.c 2010-02-10 20:25:06.204228079 +0100 michael@18: @@ -24,6 +24,7 @@ michael@18: * --------- michael@18: * 2005-01-31 first version (ramona) michael@18: * 2006-03-02 UAC authentication looks first in AVPs for credential (bogdan) michael@18: + * 2010-01-18 UAC replaces proxy-auth entries with new credentials (msvb) michael@18: */ michael@18: michael@18: michael@18: @@ -375,14 +376,172 @@ michael@18: HASHHEX response; michael@18: str *new_hdr; michael@18: michael@18: + /* pretransact */ michael@18: + int nret = 0; michael@18: + pv_value_t pv_val; michael@18: + str *newuri = 0; michael@18: + struct uac_credential *tst = 0; michael@18: + struct hdr_field *tmp_hdr = 0; michael@18: + struct hdr_field *del_hdr = 0; michael@18: + michael@18: + michael@18: + /* Goes something like this... */ michael@18: + /* HA1 = echo -n 'username:realm:password' | md5sum */ michael@18: + /* echo -n 'itsme:mydom.com:stupidpass' | md5sum */ michael@18: + /* HA2 = echo -n 'message:uri' | md5sum */ michael@18: + /* echo -n 'INVITE:sip:danc@ing.fool.es' | md5sum */ michael@18: + /* Response = echo -n 'HA1:nonce:HA2' | md5sum */ michael@18: /* get transaction */ michael@18: t = uac_tmb.t_gett(); michael@18: - if (t==T_UNDEFINED || t==T_NULL_CELL) michael@18: - { michael@18: - LM_CRIT("no current transaction found\n"); michael@18: - goto error; michael@18: - } michael@18: + if (t==T_UNDEFINED || t==T_NULL_CELL) { michael@18: + /* begin without any transaction */ michael@18: + /* set relevant structure variables */ michael@18: + crd = 0; michael@18: + crd = pkg_malloc(sizeof(struct uac_credential)); michael@18: + if (!crd) { michael@18: + LM_ERR("no more pkg memory\n"); michael@18: + goto error; michael@18: + } michael@18: + michael@18: + /* set the realm from existing UAC message */ michael@18: + tmp_hdr = msg->proxy_auth; michael@18: + del_hdr = 0; michael@18: + while (tmp_hdr) { michael@18: + crd->realm.s = strchr(strstr(tmp_hdr->body.s, "realm="), '"') + 1; michael@18: + crd->realm.len = strchr(crd->realm.s, '"') - crd->realm.s; michael@18: + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ michael@18: + && pv_val.rs.len>0) /* ensure realm is the desired one */ michael@18: + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) michael@18: + del_hdr = tmp_hdr; michael@18: + tmp_hdr = tmp_hdr->sibling; michael@18: + } michael@18: + if (del_hdr) michael@18: + crd->realm = pv_val.rs; /* success */ michael@18: + else michael@18: + nret++; /* failure */ michael@18: + michael@18: + /* set username from new AVP proxy values */ michael@18: + if(pv_get_spec_value(msg, &auth_username_spec, &pv_val)!=0 \ michael@18: + || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0) michael@18: + nret++; /* signal failure with nonzero value */ michael@18: + else michael@18: + crd->user = pv_val.rs; michael@18: + michael@18: + /* set password from new AVP proxy values */ michael@18: + if(pv_get_spec_value(msg, &auth_password_spec, &pv_val)!=0 \ michael@18: + || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0) michael@18: + nret++; /* signal failure with nonzero value */ michael@18: + else michael@18: + crd->passwd = pv_val.rs; michael@18: + michael@18: + if (nret) { /* if not found, look into predefined credentials */ michael@18: + tst = lookup_realm(&crd->realm); michael@18: + michael@18: + if (tst==0) { /* found? */ michael@18: + LM_DBG("no credential for realm \"%.*s\"\n", \ michael@18: + crd->realm.len, crd->realm.s); michael@18: + pkg_free(crd); michael@18: + goto error; michael@18: + } michael@18: + michael@18: + crd = tst; /* use predefined credentials */ michael@18: + /* set the realm from existing UAC message */ michael@18: + tmp_hdr = msg->proxy_auth; michael@18: + del_hdr = 0; michael@18: + while (tmp_hdr) { michael@18: + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ michael@18: + && pv_val.rs.len>0) /* ensure realm is the desired one */ michael@18: + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) michael@18: + del_hdr = tmp_hdr; michael@18: + tmp_hdr = tmp_hdr->sibling; michael@18: + } michael@18: + if (del_hdr == 0) { /* proxy-auth header matching realm not found */ michael@18: + LM_DBG("no credential for realm \"%.*s\"\n", \ michael@18: + crd->realm.len, crd->realm.s); michael@18: + pkg_free(crd); michael@18: + goto error; michael@18: + } michael@18: + } michael@18: + michael@18: + /* set the uri from existing UAC message */ michael@18: + newuri = pkg_malloc(sizeof(str)); michael@18: + if (!newuri) { michael@18: + LM_ERR("no more pkg memory\n"); michael@18: + goto error; michael@18: + } michael@18: + newuri->s = pkg_malloc(msg->new_uri.len); michael@18: + if (!newuri->s) { michael@18: + LM_ERR("no more pkg memory\n"); michael@18: + pkg_free(newuri); michael@18: + goto error; michael@18: + } michael@18: + newuri->len = msg->new_uri.len; michael@18: + strncpy(newuri->s, msg->new_uri.s, msg->new_uri.len); michael@18: + if (!newuri->s) { michael@18: + LM_DBG("failed to retrieve URI from UAC message\n"); michael@18: + pkg_free(newuri->s); michael@18: + pkg_free(newuri); michael@18: + goto error; michael@18: + } michael@18: + michael@18: + /* set the nonce from existing UAC message */ michael@18: + tmp_hdr = msg->proxy_auth; michael@18: + auth.nonce.len = 0; michael@18: + auth.nonce.s = 0; michael@18: + while (tmp_hdr) { michael@18: + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ michael@18: + && pv_val.rs.len>0) /* ensure realm is the desired one */ michael@18: + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) { michael@18: + auth.nonce.s = strchr(strstr(tmp_hdr->body.s, "nonce="), '"') + 1; michael@18: + auth.nonce.len = strchr(auth.nonce.s, '"') - auth.nonce.s; michael@18: + } michael@18: + tmp_hdr = tmp_hdr->sibling; michael@18: + } michael@18: + if (auth.nonce.s == 0) { michael@18: + LM_DBG("failed to retrieve nonce from UAC message\n"); michael@18: + pkg_free(crd); michael@18: + goto error; michael@18: + } michael@18: + michael@18: + /* do authentication */ michael@18: + do_uac_auth(msg, newuri, crd, &auth, response); michael@18: + if (response==0) { michael@18: + LM_ERR("failed to calculate challenge response\n"); michael@18: + pkg_free(crd); michael@18: + goto error; michael@18: + } michael@18: + michael@18: + /* build the authorization header */ michael@18: + new_hdr = build_authorization_hdr(407, newuri, crd, &auth, response); michael@18: + if (new_hdr==0) { michael@18: + LM_ERR("failed to build authorization hdr\n"); michael@18: + pkg_free(crd); michael@18: + goto error; michael@18: + } michael@18: + michael@18: + /* remove the old proxy-auth header and relink message index */ michael@18: + /* before updating the authorization credentials of the message */ michael@18: + if (del_hdr) { /* updated a record and must remove the old one */ michael@18: + if (del_lump(msg, del_hdr->name.s - msg->buf, del_hdr->len, 0)==0) { michael@18: + LM_ERR("can't remove credentials\n"); michael@18: + pkg_free(crd); michael@18: + goto error; michael@18: + } michael@18: + } michael@18: + michael@18: + /* so far, so good -> add the header and set the proper RURI */ michael@18: + if (apply_urihdr_changes(msg, newuri, new_hdr)<0) michael@18: + { michael@18: + LM_ERR("failed to apply changes\n"); michael@18: + pkg_free(crd); michael@18: + goto error; michael@18: + } michael@18: + michael@18: + pkg_free(crd); /* finished calculating new response string, success */ michael@18: + return 0; michael@18: + } /* if (t==T_UNDEFINED || t==T_NULL_CELL) */ michael@18: michael@18: + /* begin with transaction reply */ michael@18: /* get the selected branch */ michael@18: branch = uac_tmb.t_get_picked(); michael@18: if (branch<0) { michael@18: Index: modules/uac/uac.c michael@18: diff -Nau modules/uac/uac.c.orig modules/uac/uac.c michael@18: --- modules/uac/uac.c.orig 2010-01-18 12:32:26.159078000 +0100 michael@18: +++ modules/uac/uac.c 2010-02-10 20:25:06.206731656 +0100 michael@18: @@ -29,6 +29,7 @@ michael@18: * 2006-03-03 the RR parameter is encrypted via XOR with a password michael@18: * (bogdan) michael@18: * 2009-08-22 TO header replacement added (bogdan) michael@18: + * 2010-01-18 UAC is able to construct credentials from request (msvb) michael@18: michael@18: */ michael@18: michael@18: @@ -106,7 +107,7 @@ michael@18: REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE }, michael@18: {"uac_auth", (cmd_function)w_uac_auth, 0, michael@18: 0, 0, michael@18: - FAILURE_ROUTE }, michael@18: + REQUEST_ROUTE|FAILURE_ROUTE }, michael@18: {0,0,0,0,0,0} michael@18: }; michael@18: