1.1 --- a/opensips/modules/uac/auth.c Wed Feb 10 21:21:24 2010 +0100 1.2 +++ b/opensips/modules/uac/auth.c Wed Feb 10 21:25:01 2010 +0100 1.3 @@ -24,6 +24,7 @@ 1.4 * --------- 1.5 * 2005-01-31 first version (ramona) 1.6 * 2006-03-02 UAC authentication looks first in AVPs for credential (bogdan) 1.7 + * 2010-01-18 UAC replaces proxy-auth entries with new credentials (msvb) 1.8 */ 1.9 1.10 1.11 @@ -375,14 +376,172 @@ 1.12 HASHHEX response; 1.13 str *new_hdr; 1.14 1.15 + /* pretransact */ 1.16 + int nret = 0; 1.17 + pv_value_t pv_val; 1.18 + str *newuri = 0; 1.19 + struct uac_credential *tst = 0; 1.20 + struct hdr_field *tmp_hdr = 0; 1.21 + struct hdr_field *del_hdr = 0; 1.22 + 1.23 + 1.24 + /* Goes something like this... */ 1.25 + /* HA1 = echo -n 'username:realm:password' | md5sum */ 1.26 + /* echo -n 'itsme:mydom.com:stupidpass' | md5sum */ 1.27 + /* HA2 = echo -n 'message:uri' | md5sum */ 1.28 + /* echo -n 'INVITE:sip:danc@ing.fool.es' | md5sum */ 1.29 + /* Response = echo -n 'HA1:nonce:HA2' | md5sum */ 1.30 /* get transaction */ 1.31 t = uac_tmb.t_gett(); 1.32 - if (t==T_UNDEFINED || t==T_NULL_CELL) 1.33 - { 1.34 - LM_CRIT("no current transaction found\n"); 1.35 - goto error; 1.36 - } 1.37 + if (t==T_UNDEFINED || t==T_NULL_CELL) { 1.38 + /* begin without any transaction */ 1.39 + /* set relevant structure variables */ 1.40 + crd = 0; 1.41 + crd = pkg_malloc(sizeof(struct uac_credential)); 1.42 + if (!crd) { 1.43 + LM_ERR("no more pkg memory\n"); 1.44 + goto error; 1.45 + } 1.46 1.47 + /* set the realm from existing UAC message */ 1.48 + tmp_hdr = msg->proxy_auth; 1.49 + del_hdr = 0; 1.50 + while (tmp_hdr) { 1.51 + crd->realm.s = strchr(strstr(tmp_hdr->body.s, "realm="), '"') + 1; 1.52 + crd->realm.len = strchr(crd->realm.s, '"') - crd->realm.s; 1.53 + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ 1.54 + && pv_val.rs.len>0) /* ensure realm is the desired one */ 1.55 + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) 1.56 + del_hdr = tmp_hdr; 1.57 + tmp_hdr = tmp_hdr->sibling; 1.58 + } 1.59 + if (del_hdr) 1.60 + crd->realm = pv_val.rs; /* success */ 1.61 + else 1.62 + nret++; /* failure */ 1.63 + 1.64 + /* set username from new AVP proxy values */ 1.65 + if(pv_get_spec_value(msg, &auth_username_spec, &pv_val)!=0 \ 1.66 + || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0) 1.67 + nret++; /* signal failure with nonzero value */ 1.68 + else 1.69 + crd->user = pv_val.rs; 1.70 + 1.71 + /* set password from new AVP proxy values */ 1.72 + if(pv_get_spec_value(msg, &auth_password_spec, &pv_val)!=0 \ 1.73 + || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0) 1.74 + nret++; /* signal failure with nonzero value */ 1.75 + else 1.76 + crd->passwd = pv_val.rs; 1.77 + 1.78 + if (nret) { /* if not found, look into predefined credentials */ 1.79 + tst = lookup_realm(&crd->realm); 1.80 + 1.81 + if (tst==0) { /* found? */ 1.82 + LM_DBG("no credential for realm \"%.*s\"\n", \ 1.83 + crd->realm.len, crd->realm.s); 1.84 + pkg_free(crd); 1.85 + goto error; 1.86 + } 1.87 + 1.88 + crd = tst; /* use predefined credentials */ 1.89 + /* set the realm from existing UAC message */ 1.90 + tmp_hdr = msg->proxy_auth; 1.91 + del_hdr = 0; 1.92 + while (tmp_hdr) { 1.93 + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ 1.94 + && pv_val.rs.len>0) /* ensure realm is the desired one */ 1.95 + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) 1.96 + del_hdr = tmp_hdr; 1.97 + tmp_hdr = tmp_hdr->sibling; 1.98 + } 1.99 + if (del_hdr == 0) { /* proxy-auth header matching realm not found */ 1.100 + LM_DBG("no credential for realm \"%.*s\"\n", \ 1.101 + crd->realm.len, crd->realm.s); 1.102 + pkg_free(crd); 1.103 + goto error; 1.104 + } 1.105 + } 1.106 + 1.107 + /* set the uri from existing UAC message */ 1.108 + newuri = pkg_malloc(sizeof(str)); 1.109 + if (!newuri) { 1.110 + LM_ERR("no more pkg memory\n"); 1.111 + goto error; 1.112 + } 1.113 + newuri->s = pkg_malloc(msg->new_uri.len); 1.114 + if (!newuri->s) { 1.115 + LM_ERR("no more pkg memory\n"); 1.116 + pkg_free(newuri); 1.117 + goto error; 1.118 + } 1.119 + newuri->len = msg->new_uri.len; 1.120 + strncpy(newuri->s, msg->new_uri.s, msg->new_uri.len); 1.121 + if (!newuri->s) { 1.122 + LM_DBG("failed to retrieve URI from UAC message\n"); 1.123 + pkg_free(newuri->s); 1.124 + pkg_free(newuri); 1.125 + goto error; 1.126 + } 1.127 + 1.128 + /* set the nonce from existing UAC message */ 1.129 + tmp_hdr = msg->proxy_auth; 1.130 + auth.nonce.len = 0; 1.131 + auth.nonce.s = 0; 1.132 + while (tmp_hdr) { 1.133 + if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \ 1.134 + && pv_val.rs.len>0) /* ensure realm is the desired one */ 1.135 + if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) { 1.136 + auth.nonce.s = strchr(strstr(tmp_hdr->body.s, "nonce="), '"') + 1; 1.137 + auth.nonce.len = strchr(auth.nonce.s, '"') - auth.nonce.s; 1.138 + } 1.139 + tmp_hdr = tmp_hdr->sibling; 1.140 + } 1.141 + if (auth.nonce.s == 0) { 1.142 + LM_DBG("failed to retrieve nonce from UAC message\n"); 1.143 + pkg_free(crd); 1.144 + goto error; 1.145 + } 1.146 + 1.147 + /* do authentication */ 1.148 + do_uac_auth(msg, newuri, crd, &auth, response); 1.149 + if (response==0) { 1.150 + LM_ERR("failed to calculate challenge response\n"); 1.151 + pkg_free(crd); 1.152 + goto error; 1.153 + } 1.154 + 1.155 + /* build the authorization header */ 1.156 + new_hdr = build_authorization_hdr(407, newuri, crd, &auth, response); 1.157 + if (new_hdr==0) { 1.158 + LM_ERR("failed to build authorization hdr\n"); 1.159 + pkg_free(crd); 1.160 + goto error; 1.161 + } 1.162 + 1.163 + /* remove the old proxy-auth header and relink message index */ 1.164 + /* before updating the authorization credentials of the message */ 1.165 + if (del_hdr) { /* updated a record and must remove the old one */ 1.166 + if (del_lump(msg, del_hdr->name.s - msg->buf, del_hdr->len, 0)==0) { 1.167 + LM_ERR("can't remove credentials\n"); 1.168 + pkg_free(crd); 1.169 + goto error; 1.170 + } 1.171 + } 1.172 + 1.173 + /* so far, so good -> add the header and set the proper RURI */ 1.174 + if (apply_urihdr_changes(msg, newuri, new_hdr)<0) 1.175 + { 1.176 + LM_ERR("failed to apply changes\n"); 1.177 + pkg_free(crd); 1.178 + goto error; 1.179 + } 1.180 + 1.181 + pkg_free(crd); /* finished calculating new response string, success */ 1.182 + return 0; 1.183 + } /* if (t==T_UNDEFINED || t==T_NULL_CELL) */ 1.184 + 1.185 + /* begin with transaction reply */ 1.186 /* get the selected branch */ 1.187 branch = uac_tmb.t_get_picked(); 1.188 if (branch<0) {