Extend uac_auth() of the UAC module to workaround CSEQ problems.

Wed, 10 Feb 2010 21:25:01 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 10 Feb 2010 21:25:01 +0100
changeset 18
8ec65b8f6e2c
parent 17
733187d496d0
child 19
3374f578f080

Extend uac_auth() of the UAC module to workaround CSEQ problems.
This logic is meant to complement that of changeset 17, which
added rich authentication credentials to the gw table and its
associated logic in the LCR module.

opensips/modules/uac/auth.c file | annotate | diff | comparison | revisions
opensips/modules/uac/uac.c file | annotate | diff | comparison | revisions
opensips/uac-reauth.diff file | annotate | diff | comparison | revisions
opensips/uac-reauth.txt file | annotate | diff | comparison | revisions
     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) {
     2.1 --- a/opensips/modules/uac/uac.c	Wed Feb 10 21:21:24 2010 +0100
     2.2 +++ b/opensips/modules/uac/uac.c	Wed Feb 10 21:25:01 2010 +0100
     2.3 @@ -29,6 +29,7 @@
     2.4   *  2006-03-03  the RR parameter is encrypted via XOR with a password
     2.5   *              (bogdan)
     2.6   *  2009-08-22  TO header replacement added (bogdan)
     2.7 + *  2010-01-18  UAC is able to construct credentials from request (msvb)
     2.8  
     2.9   */
    2.10  
    2.11 @@ -106,7 +107,7 @@
    2.12  			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    2.13  	{"uac_auth",          (cmd_function)w_uac_auth,       0,
    2.14  			0, 0,
    2.15 -			FAILURE_ROUTE },
    2.16 +			REQUEST_ROUTE|FAILURE_ROUTE },
    2.17  	{0,0,0,0,0,0}
    2.18  };
    2.19  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/opensips/uac-reauth.diff	Wed Feb 10 21:25:01 2010 +0100
     3.3 @@ -0,0 +1,211 @@
     3.4 +Index: modules/uac/auth.c
     3.5 +diff -Nau modules/uac/auth.c.orig modules/uac/auth.c
     3.6 +--- modules/uac/auth.c.orig	2010-01-18 12:32:26.152280000 +0100
     3.7 ++++ modules/uac/auth.c	2010-02-10 20:25:06.204228079 +0100
     3.8 +@@ -24,6 +24,7 @@
     3.9 +  * ---------
    3.10 +  *  2005-01-31  first version (ramona)
    3.11 +  *  2006-03-02  UAC authentication looks first in AVPs for credential (bogdan)
    3.12 ++ *  2010-01-18  UAC replaces proxy-auth entries with new credentials (msvb)
    3.13 +  */
    3.14 + 
    3.15 + 
    3.16 +@@ -375,14 +376,172 @@
    3.17 + 	HASHHEX response;
    3.18 + 	str *new_hdr;
    3.19 + 
    3.20 ++	/* pretransact */
    3.21 ++	int nret = 0;
    3.22 ++	pv_value_t pv_val;
    3.23 ++	str *newuri = 0;
    3.24 ++	struct uac_credential *tst = 0;
    3.25 ++	struct hdr_field *tmp_hdr = 0;
    3.26 ++	struct hdr_field *del_hdr = 0;
    3.27 ++
    3.28 ++
    3.29 ++	/* Goes something like this...                          */
    3.30 ++	/* HA1 = echo -n 'username:realm:password' | md5sum     */
    3.31 ++	/*       echo -n 'itsme:mydom.com:stupidpass' | md5sum  */
    3.32 ++	/* HA2 = echo -n 'message:uri' | md5sum                 */
    3.33 ++	/*       echo -n 'INVITE:sip:danc@ing.fool.es' | md5sum */
    3.34 ++	/* Response = echo -n 'HA1:nonce:HA2' | md5sum          */
    3.35 + 	/* get transaction */
    3.36 + 	t = uac_tmb.t_gett();
    3.37 +-	if (t==T_UNDEFINED || t==T_NULL_CELL)
    3.38 +-	{
    3.39 +-		LM_CRIT("no current transaction found\n");
    3.40 +-		goto error;
    3.41 +-	}
    3.42 ++	if (t==T_UNDEFINED || t==T_NULL_CELL) {
    3.43 ++		/* begin without any transaction */
    3.44 ++		/* set relevant structure variables */
    3.45 ++		crd = 0;
    3.46 ++		crd = pkg_malloc(sizeof(struct uac_credential));
    3.47 ++		if (!crd) {
    3.48 ++			LM_ERR("no more pkg memory\n");
    3.49 ++			goto error;
    3.50 ++		}
    3.51 ++
    3.52 ++		/* set the realm from existing UAC message */
    3.53 ++		tmp_hdr = msg->proxy_auth;
    3.54 ++		del_hdr = 0;
    3.55 ++		while (tmp_hdr) {
    3.56 ++			crd->realm.s = strchr(strstr(tmp_hdr->body.s, "realm="), '"') + 1;
    3.57 ++			crd->realm.len = strchr(crd->realm.s, '"') - crd->realm.s;
    3.58 ++			if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
    3.59 ++				&& pv_val.rs.len>0) /* ensure realm is the desired one */
    3.60 ++				if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0)
    3.61 ++					del_hdr = tmp_hdr;
    3.62 ++			tmp_hdr = tmp_hdr->sibling;
    3.63 ++		}
    3.64 ++		if (del_hdr)
    3.65 ++			crd->realm = pv_val.rs;	/* success */
    3.66 ++		else
    3.67 ++			nret++;					/* failure */
    3.68 ++
    3.69 ++		/* set username from new AVP proxy values */
    3.70 ++		if(pv_get_spec_value(msg, &auth_username_spec, &pv_val)!=0 \
    3.71 ++			|| pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
    3.72 ++			nret++; /* signal failure with nonzero value */
    3.73 ++		else
    3.74 ++			crd->user = pv_val.rs;
    3.75 ++
    3.76 ++		/* set password from new AVP proxy values */
    3.77 ++		if(pv_get_spec_value(msg, &auth_password_spec, &pv_val)!=0 \
    3.78 ++			|| pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
    3.79 ++			nret++; /* signal failure with nonzero value */
    3.80 ++		else
    3.81 ++			crd->passwd = pv_val.rs;
    3.82 ++
    3.83 ++		if (nret) { /* if not found, look into predefined credentials */
    3.84 ++			tst = lookup_realm(&crd->realm);
    3.85 ++
    3.86 ++			if (tst==0) { /* found? */
    3.87 ++				LM_DBG("no credential for realm \"%.*s\"\n", \
    3.88 ++					crd->realm.len, crd->realm.s);
    3.89 ++				pkg_free(crd);
    3.90 ++				goto error;
    3.91 ++			}
    3.92 ++
    3.93 ++			crd = tst; /* use predefined credentials */
    3.94 ++			/* set the realm from existing UAC message */
    3.95 ++			tmp_hdr = msg->proxy_auth;
    3.96 ++			del_hdr = 0;
    3.97 ++			while (tmp_hdr) {
    3.98 ++				if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
    3.99 ++					&& pv_val.rs.len>0) /* ensure realm is the desired one */
   3.100 ++					if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0)
   3.101 ++						del_hdr = tmp_hdr;
   3.102 ++				tmp_hdr = tmp_hdr->sibling;
   3.103 ++			}
   3.104 ++			if (del_hdr == 0) { /* proxy-auth header matching realm not found */
   3.105 ++				LM_DBG("no credential for realm \"%.*s\"\n", \
   3.106 ++					crd->realm.len, crd->realm.s);
   3.107 ++				pkg_free(crd);
   3.108 ++				goto error;
   3.109 ++			}
   3.110 ++		}
   3.111 ++
   3.112 ++		/* set the uri from existing UAC message */
   3.113 ++		newuri = pkg_malloc(sizeof(str));
   3.114 ++		if (!newuri) {
   3.115 ++			LM_ERR("no more pkg memory\n");
   3.116 ++			goto error;
   3.117 ++		}
   3.118 ++		newuri->s = pkg_malloc(msg->new_uri.len);
   3.119 ++		if (!newuri->s) {
   3.120 ++			LM_ERR("no more pkg memory\n");
   3.121 ++			pkg_free(newuri);
   3.122 ++			goto error;
   3.123 ++		}
   3.124 ++		newuri->len = msg->new_uri.len;
   3.125 ++		strncpy(newuri->s, msg->new_uri.s, msg->new_uri.len);
   3.126 ++		if (!newuri->s) {
   3.127 ++			LM_DBG("failed to retrieve URI from UAC message\n");
   3.128 ++			pkg_free(newuri->s);
   3.129 ++			pkg_free(newuri);
   3.130 ++			goto error;
   3.131 ++		}
   3.132 ++
   3.133 ++		/* set the nonce from existing UAC message */
   3.134 ++		tmp_hdr = msg->proxy_auth;
   3.135 ++		auth.nonce.len = 0;
   3.136 ++		auth.nonce.s = 0;
   3.137 ++		while (tmp_hdr) {
   3.138 ++			if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
   3.139 ++				&& pv_val.rs.len>0) /* ensure realm is the desired one */
   3.140 ++				if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) {
   3.141 ++					auth.nonce.s = strchr(strstr(tmp_hdr->body.s, "nonce="), '"') + 1;
   3.142 ++					auth.nonce.len = strchr(auth.nonce.s, '"') - auth.nonce.s;
   3.143 ++				}
   3.144 ++			tmp_hdr = tmp_hdr->sibling;
   3.145 ++		}
   3.146 ++		if (auth.nonce.s == 0) {
   3.147 ++			LM_DBG("failed to retrieve nonce from UAC message\n");
   3.148 ++			pkg_free(crd);
   3.149 ++			goto error;
   3.150 ++		}
   3.151 ++
   3.152 ++		/* do authentication */
   3.153 ++		do_uac_auth(msg, newuri, crd, &auth, response);
   3.154 ++		if (response==0) {
   3.155 ++			LM_ERR("failed to calculate challenge response\n");
   3.156 ++			pkg_free(crd);
   3.157 ++			goto error;
   3.158 ++		}
   3.159 ++
   3.160 ++		/* build the authorization header */
   3.161 ++		new_hdr = build_authorization_hdr(407, newuri, crd, &auth, response);
   3.162 ++		if (new_hdr==0) {
   3.163 ++			LM_ERR("failed to build authorization hdr\n");
   3.164 ++			pkg_free(crd);
   3.165 ++			goto error;
   3.166 ++		}
   3.167 ++
   3.168 ++		/* remove the old proxy-auth header and relink message index    */
   3.169 ++		/* before updating the authorization credentials of the message */
   3.170 ++		if (del_hdr) { /* updated a record and must remove the old one  */
   3.171 ++			if (del_lump(msg, del_hdr->name.s - msg->buf, del_hdr->len, 0)==0) {
   3.172 ++				LM_ERR("can't remove credentials\n");
   3.173 ++				pkg_free(crd);
   3.174 ++				goto error;
   3.175 ++			}
   3.176 ++		}
   3.177 ++
   3.178 ++		/* so far, so good -> add the header and set the proper RURI */
   3.179 ++		if (apply_urihdr_changes(msg, newuri, new_hdr)<0)
   3.180 ++		{
   3.181 ++			LM_ERR("failed to apply changes\n");
   3.182 ++			pkg_free(crd);
   3.183 ++			goto error;
   3.184 ++		}
   3.185 ++
   3.186 ++		pkg_free(crd); /* finished calculating new response string, success */
   3.187 ++		return 0;
   3.188 ++	} /* if (t==T_UNDEFINED || t==T_NULL_CELL) */
   3.189 + 
   3.190 ++	/* begin with transaction reply */
   3.191 + 	/* get the selected branch */
   3.192 + 	branch = uac_tmb.t_get_picked();
   3.193 + 	if (branch<0) {
   3.194 +Index: modules/uac/uac.c
   3.195 +diff -Nau modules/uac/uac.c.orig modules/uac/uac.c
   3.196 +--- modules/uac/uac.c.orig	2010-01-18 12:32:26.159078000 +0100
   3.197 ++++ modules/uac/uac.c	2010-02-10 20:25:06.206731656 +0100
   3.198 +@@ -29,6 +29,7 @@
   3.199 +  *  2006-03-03  the RR parameter is encrypted via XOR with a password
   3.200 +  *              (bogdan)
   3.201 +  *  2009-08-22  TO header replacement added (bogdan)
   3.202 ++ *  2010-01-18  UAC is able to construct credentials from request (msvb)
   3.203 + 
   3.204 +  */
   3.205 + 
   3.206 +@@ -106,7 +107,7 @@
   3.207 + 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   3.208 + 	{"uac_auth",          (cmd_function)w_uac_auth,       0,
   3.209 + 			0, 0,
   3.210 +-			FAILURE_ROUTE },
   3.211 ++			REQUEST_ROUTE|FAILURE_ROUTE },
   3.212 + 	{0,0,0,0,0,0}
   3.213 + };
   3.214 + 
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/opensips/uac-reauth.txt	Wed Feb 10 21:25:01 2010 +0100
     4.3 @@ -0,0 +1,82 @@
     4.4 +UAC module authentication extention (contribution)
     4.5 +
     4.6 +Problem
     4.7 +
     4.8 +A problem involving SIP authentication has plagued OpenSIPS for years.
     4.9 +Because OpenSIPS is a proxy it may not manipulate the CSEQ of incoming
    4.10 +requests or responses. When a UAC sends a SIP message which triggers
    4.11 +an authentication challenge from another proxy or external UAS, OpenSIPS
    4.12 +may receive a SIP response message with a 401 or 407 code.
    4.13 +
    4.14 +The UAC module provides a function uac_auth() to allow OpenSIPS to
    4.15 +authenticate, however it is of limited utility because any SIP compliant
    4.16 +proxy, PBX, or UAS sending such authentication challenges expects the
    4.17 +CSEQ of the succeeding request to be different than the preceding one.
    4.18 +
    4.19 +Solution
    4.20 +
    4.21 +While somewhat of a hack, one solution to this problem is to forward
    4.22 +code 401 and 407 responses to the UAC which will formulate an
    4.23 +authorization header, insert it into the original request, and
    4.24 +send the message again after incrementing the CSEQ. OpenSIPS
    4.25 +receives the new request and passes it with success this time.
    4.26 +
    4.27 +This solution requires new hack logic to allow OpenSIPS to provide
    4.28 +the uac_auth() function inside of request routing blocks, whereas
    4.29 +the unmodified versions of OpenSIPS allow usage of uac_auth() only
    4.30 +in failure routes.
    4.31 +
    4.32 +Usage
    4.33 +
    4.34 +To use the new logic simply follow the instructions of uac_auth() usage
    4.35 +on incoming SIP requests (for example INVITE) inside a main or secondary
    4.36 +routing block like so:
    4.37 +
    4.38 +  if (!load_gws()) {
    4.39 +      send_reply("500", "Server Internal Error");
    4.40 +      exit;
    4.41 +  }
    4.42 +  if (!next_gw()) {
    4.43 +      send_reply("503", "Service Unavailable");
    4.44 +      exit;
    4.45 +  }
    4.46 +  if ($avp(s:authuser) == "") {  # this is in case no user exists
    4.47 +      $avp(s:authuser) = $fU;    # in the gw database table row
    4.48 +  }
    4.49 +  if ($hdr(P-hint) != "lcr applied") {
    4.50 +      append_hf("P-hint: lcr applied\r\n");
    4.51 +  }
    4.52 +
    4.53 +  # the following uac_auth avp parameters are filled in
    4.54 +  # by the lcr itself, through a patch to its datatables
    4.55 +  uac_auth();   # patched for use in request route as well
    4.56 +  route(1);     # forward to gateway provider
    4.57 +
    4.58 +Location
    4.59 +
    4.60 +http://scm.europalab.com/contrib/opensips/
    4.61 +http://scm.europalab.com/contrib/file/tip/opensips/
    4.62 +http://scm.europalab.com/contrib/file/tip/opensips/uac-reauth.txt
    4.63 +http://scm.europalab.com/contrib/file/tip/opensips/uac-reauth.diff
    4.64 +
    4.65 +Instructions
    4.66 +
    4.67 +To integrate this contributed logic into the source code tree of
    4.68 +a OpenSIPS distribution, download the unified diff and use the
    4.69 +patch(1) command:
    4.70 +
    4.71 +  $ cd /tmp && mkdir uac-patch && cd uac-patch
    4.72 +  $ wget http://scm.europalab.com/contrib/raw-file/tip/opensips/uac-reauth.diff
    4.73 +  $ tar zxf /tmp/opensips-<version>-tls.tar.gz
    4.74 +  $ cd opensips-<version>-tls
    4.75 +  $ patch -p0 <../uac-reauth.diff
    4.76 +
    4.77 +Disclaimer
    4.78 +
    4.79 +This software contribution is based on source code from OpenSIPS SVN
    4.80 +revision 6590. The author makes no guarantees as to this contribution.
    4.81 +A user who downloads and executes it does so at his own risk.
    4.82 +
    4.83 +Michael Schloh von Bennewitz
    4.84 +http://michael.schloh.com/
    4.85 +Wednsday, 10. February 2010

mercurial