michael@377: Index: modules/uac/auth.c michael@377: diff -Nau modules/uac/auth.c.orig modules/uac/auth.c michael@377: --- modules/uac/auth.c.orig 2008-08-03 15:53:40.000000000 +0200 michael@377: +++ modules/uac/auth.c 2009-03-24 21:48:53.478867420 +0100 michael@397: @@ -143,14 +143,172 @@ michael@377: HASHHEX response; michael@377: str *new_hdr; michael@377: michael@377: + /* pretransact */ michael@377: + int nret = 0; michael@377: + pv_value_t pv_val; michael@377: + str *newuri = 0; michael@377: + struct uac_credential *tst = 0; michael@377: + struct hdr_field *tmp_hdr = 0; michael@377: + struct hdr_field *del_hdr = 0; michael@377: + michael@377: + michael@377: + /* Goes something like this... */ michael@377: + /* HA1 = echo -n 'username:realm:password' | md5sum */ michael@377: + /* echo -n 'itsme:mydom.com:stupidpass' | md5sum */ michael@377: + /* HA2 = echo -n 'message:uri' | md5sum */ michael@377: + /* echo -n 'INVITE:sip:danc@ing.fool.es' | md5sum */ michael@377: + /* Response = echo -n 'HA1:nonce:HA2' | md5sum */ michael@377: /* get transaction */ michael@377: t = uac_tmb.t_gett(); michael@377: - if (t==T_UNDEFINED || t==T_NULL_CELL) michael@377: - { michael@377: - LM_CRIT("no current transaction found\n"); michael@377: - goto error; michael@377: - } michael@377: + if (t==T_UNDEFINED || t==T_NULL_CELL) { michael@377: + /* begin without any transaction */ michael@377: + /* set relevant structure variables */ michael@377: + crd = 0; michael@377: + crd = pkg_malloc(sizeof(struct uac_credential)); michael@377: + if (!crd) { michael@377: + LM_ERR("no more pkg memory\n"); michael@377: + goto error; michael@377: + } michael@377: + michael@377: + /* set the realm from existing UAC message */ michael@377: + tmp_hdr = msg->proxy_auth; michael@377: + del_hdr = 0; michael@377: + while (tmp_hdr) { michael@377: + crd->realm.s = strchr(strstr(tmp_hdr->body.s, "realm="), '"') + 1; michael@377: + crd->realm.len = strchr(crd->realm.s, '"') - crd->realm.s; michael@377: + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ michael@377: + && pv_val.rs.len>0) /* ensure realm is the desired one */ michael@377: + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) michael@377: + del_hdr = tmp_hdr; michael@377: + tmp_hdr = tmp_hdr->sibling; michael@377: + } michael@377: + if (del_hdr) michael@377: + crd->realm = pv_val.rs; /* success */ michael@377: + else michael@377: + nret++; /* failure */ michael@377: + michael@377: + /* set username from new AVP proxy values */ michael@377: + if(pv_get_spec_value(msg, &auth_username_spec, &pv_val)!=0 \ michael@377: + || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0) michael@377: + nret++; /* signal failure with nonzero value */ michael@377: + else michael@377: + crd->user = pv_val.rs; michael@377: + michael@377: + /* set password from new AVP proxy values */ michael@377: + if(pv_get_spec_value(msg, &auth_password_spec, &pv_val)!=0 \ michael@377: + || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0) michael@377: + nret++; /* signal failure with nonzero value */ michael@377: + else michael@377: + crd->passwd = pv_val.rs; michael@377: + michael@377: + if (nret) { /* if not found, look into predefined credentials */ michael@397: + tst = uac_auth_api._lookup_realm(&crd->realm); michael@377: + michael@377: + if (tst==0) { /* found? */ michael@377: + LM_DBG("no credential for realm \"%.*s\"\n", \ michael@377: + crd->realm.len, crd->realm.s); michael@377: + pkg_free(crd); michael@377: + goto error; michael@377: + } michael@377: + michael@377: + crd = tst; /* use predefined credentials */ michael@377: + /* set the realm from existing UAC message */ michael@377: + tmp_hdr = msg->proxy_auth; michael@377: + del_hdr = 0; michael@377: + while (tmp_hdr) { michael@377: + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ michael@377: + && pv_val.rs.len>0) /* ensure realm is the desired one */ michael@377: + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) michael@377: + del_hdr = tmp_hdr; michael@377: + tmp_hdr = tmp_hdr->sibling; michael@377: + } michael@377: + if (del_hdr == 0) { /* proxy-auth header matching realm not found */ michael@377: + LM_DBG("no credential for realm \"%.*s\"\n", \ michael@377: + crd->realm.len, crd->realm.s); michael@377: + pkg_free(crd); michael@377: + goto error; michael@377: + } michael@377: + } michael@377: + michael@377: + /* set the uri from existing UAC message */ michael@377: + newuri = pkg_malloc(sizeof(str)); michael@377: + if (!newuri) { michael@377: + LM_ERR("no more pkg memory\n"); michael@377: + goto error; michael@377: + } michael@377: + newuri->s = pkg_malloc(msg->new_uri.len); michael@377: + if (!newuri->s) { michael@377: + LM_ERR("no more pkg memory\n"); michael@377: + pkg_free(newuri); michael@377: + goto error; michael@377: + } michael@377: + newuri->len = msg->new_uri.len; michael@377: + strncpy(newuri->s, msg->new_uri.s, msg->new_uri.len); michael@377: + if (!newuri->s) { michael@377: + LM_DBG("failed to retrieve URI from UAC message\n"); michael@377: + pkg_free(newuri->s); michael@377: + pkg_free(newuri); michael@377: + goto error; michael@377: + } michael@377: + michael@377: + /* set the nonce from existing UAC message */ michael@377: + tmp_hdr = msg->proxy_auth; michael@397: + auth->nonce.len = 0; michael@397: + auth->nonce.s = 0; michael@377: + while (tmp_hdr) { michael@377: + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ michael@377: + && pv_val.rs.len>0) /* ensure realm is the desired one */ michael@377: + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) { michael@397: + auth->nonce.s = strchr(strstr(tmp_hdr->body.s, "nonce="), '"') + 1; michael@397: + auth->nonce.len = strchr(auth->nonce.s, '"') - auth->nonce.s; michael@377: + } michael@377: + tmp_hdr = tmp_hdr->sibling; michael@377: + } michael@397: + if (auth->nonce.s == 0) { michael@377: + LM_DBG("failed to retrieve nonce from UAC message\n"); michael@377: + pkg_free(crd); michael@377: + goto error; michael@377: + } michael@377: + michael@377: + /* do authentication */ michael@397: + uac_auth_api._do_uac_auth(msg, newuri, crd, auth, &auth_nc_cnonce, response); michael@377: + if (response==0) { michael@377: + LM_ERR("failed to calculate challenge response\n"); michael@377: + pkg_free(crd); michael@377: + goto error; michael@377: + } michael@377: + michael@377: + /* build the authorization header */ michael@397: + new_hdr = uac_auth_api._build_authorization_hdr(407, newuri, crd, auth, &auth_nc_cnonce, response); michael@377: + if (new_hdr==0) { michael@377: + LM_ERR("failed to build authorization hdr\n"); michael@377: + pkg_free(crd); michael@377: + goto error; michael@377: + } michael@377: + michael@377: + /* remove the old proxy-auth header and relink message index */ michael@377: + /* before updating the authorization credentials of the message */ michael@377: + if (del_hdr) { /* updated a record and must remove the old one */ michael@377: + if (del_lump(msg, del_hdr->name.s - msg->buf, del_hdr->len, 0)==0) { michael@377: + LM_ERR("can't remove credentials\n"); michael@377: + pkg_free(crd); michael@377: + goto error; michael@377: + } michael@377: + } michael@377: + michael@377: + /* so far, so good -> add the header and set the proper RURI */ michael@377: + if (apply_urihdr_changes(msg, newuri, new_hdr)<0) michael@377: + { michael@377: + LM_ERR("failed to apply changes\n"); michael@377: + pkg_free(crd); michael@377: + goto error; michael@377: + } michael@377: + michael@377: + pkg_free(crd); /* finished calculating new response string, success */ michael@377: + return 0; michael@377: + } /* if (t==T_UNDEFINED || t==T_NULL_CELL) */ michael@377: michael@377: + /* begin with transaction reply */ michael@377: /* get the selected branch */ michael@377: branch = uac_tmb.t_get_picked(); michael@377: if (branch<0) { michael@377: Index: modules/uac/uac.c michael@377: diff -Nau modules/uac/uac.c.orig modules/uac/uac.c michael@377: --- modules/uac/uac.c.orig 2008-08-03 15:53:40.000000000 +0200 michael@377: +++ modules/uac/uac.c 2009-03-24 21:49:48.922890737 +0100 michael@397: @@ -117,7 +117,7 @@ michael@377: REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE }, michael@377: {"uac_auth", (cmd_function)w_uac_auth, 0, michael@377: 0, 0, michael@377: - FAILURE_ROUTE }, michael@377: + REQUEST_ROUTE|FAILURE_ROUTE }, michael@377: {0,0,0,0,0,0} michael@377: }; michael@377: