opensips/modules/uac/auth.c

changeset 18
8ec65b8f6e2c
parent 16
c5c55937e44c
     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) {

mercurial