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