opensips/modules/uac/uac.c

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 16
c5c55937e44c
permissions
-rw-r--r--

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.

     1 /*
     2  * $Id: uac.c 6481 2009-12-29 13:49:37Z bogdan_iancu $
     3  *
     4  * Copyright (C) 2005-2009 Voice Sistem SRL
     5  *
     6  * This file is part of opensips, a free SIP server.
     7  *
     8  * UAC OpenSIPS-module is free software; you can redistribute it and/or
     9  * modify it under the terms of the GNU General Public License
    10  * as published by the Free Software Foundation; either version 2
    11  * of the License, or (at your option) any later version.
    12  *
    13  * UAC OpenSIPS-module is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  *
    18  * You should have received a copy of the GNU General Public License
    19  * along with this program; if not, write to the Free Software
    20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    21  *
    22  *
    23  * History:
    24  * ---------
    25  *  2005-01-31  first version (ramona)
    26  *  2005-08-12  some TM callbacks replaced with RR callback - more efficient;
    27  *              (bogdan)
    28  *  2006-03-02  UAC authentication looks first in AVPs for credential (bogdan)
    29  *  2006-03-03  the RR parameter is encrypted via XOR with a password
    30  *              (bogdan)
    31  *  2009-08-22  TO header replacement added (bogdan)
    32  *  2010-01-18  UAC is able to construct credentials from request (msvb)
    34  */
    37 #include <stdio.h>
    38 #include <string.h>
    39 #include <stdlib.h>
    41 #include "../../sr_module.h"
    42 #include "../../dprint.h"
    43 #include "../../error.h"
    44 #include "../../pvar.h"
    45 #include "../../mem/mem.h"
    46 #include "../../parser/parse_from.h"
    47 #include "../tm/tm_load.h"
    48 #include "../tm/t_hooks.h"
    49 #include "../rr/api.h"
    51 #include "replace.h"
    52 #include "auth.h"
    58 /* local variable used for init */
    59 static char* restore_mode_str = NULL;
    60 static char* auth_username_avp = NULL;
    61 static char* auth_realm_avp = NULL;
    62 static char* auth_password_avp = NULL;
    64 /* global param variables */
    65 str rr_from_param = str_init("vsf");
    66 str rr_to_param = str_init("vst");
    67 str uac_passwd = str_init("");
    68 int restore_mode = UAC_AUTO_RESTORE;
    69 struct tm_binds uac_tmb;
    70 struct rr_binds uac_rrb;
    71 pv_spec_t auth_username_spec;
    72 pv_spec_t auth_realm_spec;
    73 pv_spec_t auth_password_spec;
    75 static int w_replace_from(struct sip_msg* msg, char* p1, char* p2);
    76 static int w_restore_from(struct sip_msg* msg);
    78 static int w_replace_to(struct sip_msg* msg, char* p1, char* p2);
    79 static int w_restore_to(struct sip_msg* msg);
    81 static int w_uac_auth(struct sip_msg* msg, char* str, char* str2);
    82 static int fixup_replace_uri(void** param, int param_no);
    83 static int fixup_replace_disp_uri(void** param, int param_no);
    84 static int mod_init(void);
    85 static void mod_destroy(void);
    88 /* Exported functions */
    89 static cmd_export_t cmds[]={
    90 	{"uac_replace_from",  (cmd_function)w_replace_from,  2,
    91 			fixup_replace_disp_uri, 0,
    92 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    93 	{"uac_replace_from",  (cmd_function)w_replace_from,  1,
    94 			fixup_replace_uri, 0,
    95 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    96 	{"uac_restore_from",  (cmd_function)w_restore_from,   0,
    97 			0, 0,
    98 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    99 	{"uac_replace_to",  (cmd_function)w_replace_to,  2,
   100 			fixup_replace_disp_uri, 0,
   101 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   102 	{"uac_replace_to",  (cmd_function)w_replace_to,  1,
   103 			fixup_replace_uri, 0,
   104 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   105 	{"uac_restore_to",  (cmd_function)w_restore_to,   0,
   106 			0, 0,
   107 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   108 	{"uac_auth",          (cmd_function)w_uac_auth,       0,
   109 			0, 0,
   110 			REQUEST_ROUTE|FAILURE_ROUTE },
   111 	{0,0,0,0,0,0}
   112 };
   116 /* Exported parameters */
   117 static param_export_t params[] = {
   118 	{"rr_from_store_param", STR_PARAM,                &rr_from_param.s       },
   119 	{"rr_to_store_param",   STR_PARAM,                &rr_to_param.s         },
   120 	{"restore_mode",        STR_PARAM,                &restore_mode_str      },
   121 	{"restore_passwd",      STR_PARAM,                &uac_passwd.s          },
   122 	{"credential",          STR_PARAM|USE_FUNC_PARAM, (void*)&add_credential },
   123 	{"auth_username_avp",   STR_PARAM,                &auth_username_avp     },
   124 	{"auth_realm_avp",      STR_PARAM,                &auth_realm_avp        },
   125 	{"auth_password_avp",   STR_PARAM,                &auth_password_avp     },
   126 	{0, 0, 0}
   127 };
   131 struct module_exports exports= {
   132 	"uac",
   133 	MODULE_VERSION,
   134 	DEFAULT_DLFLAGS, /* dlopen flags */
   135 	cmds,       /* exported functions */
   136 	params,     /* param exports */
   137 	0,          /* exported statistics */
   138 	0,          /* exported MI functions */
   139 	0,          /* exported pseudo-variables */
   140 	0,          /* extra processes */
   141 	mod_init,   /* module initialization function */
   142 	(response_function) 0,
   143 	mod_destroy,
   144 	0  /* per-child init function */
   145 };
   148 inline static int parse_auth_avp( char *avp_spec, pv_spec_t *avp, char *txt)
   149 {
   150 	str s;
   151 	s.s = avp_spec; s.len = strlen(s.s);
   152 	if (pv_parse_spec(&s, avp)==NULL) {
   153 		LM_ERR("malformed or non AVP %s AVP definition\n",txt);
   154 		return -1;
   155 	}
   156 	return 0;
   157 }
   160 static int mod_init(void)
   161 {
   162 	LM_INFO("initializing...\n");
   164 	if (restore_mode_str && *restore_mode_str) {
   165 		if (strcasecmp(restore_mode_str,"none")==0) {
   166 			restore_mode = UAC_NO_RESTORE;
   167 		} else if (strcasecmp(restore_mode_str,"manual")==0) {
   168 			restore_mode = UAC_MANUAL_RESTORE;
   169 		} else if (strcasecmp(restore_mode_str,"auto")==0) {
   170 			restore_mode = UAC_AUTO_RESTORE;
   171 		} else {
   172 			LM_ERR("unsupported value '%s' for restore_mode\n",
   173 				restore_mode_str);
   174 			goto error;
   175 		}
   176 	}
   178 	rr_from_param.len = strlen(rr_from_param.s);
   179 	rr_to_param.len = strlen(rr_to_param.s);
   180 	if ( (rr_from_param.len==0 || rr_to_param.len==0) &&
   181 	restore_mode!=UAC_NO_RESTORE)
   182 	{
   183 		LM_ERR("rr_store_param cannot be empty if FROM is restoreable\n");
   184 		goto error;
   185 	}
   187 	uac_passwd.len = strlen(uac_passwd.s);
   189 	/* parse the auth AVP spesc, if any */
   190 	if ( auth_username_avp || auth_password_avp || auth_realm_avp) {
   191 		if (!auth_username_avp || !auth_password_avp || !auth_realm_avp) {
   192 			LM_ERR("partial definition of auth AVP!");
   193 			goto error;
   194 		}
   195 		if ( parse_auth_avp(auth_realm_avp, &auth_realm_spec, "realm")<0
   196 		|| parse_auth_avp(auth_username_avp, &auth_username_spec, "username")<0
   197 		|| parse_auth_avp(auth_password_avp, &auth_password_spec, "password")<0
   198 		) {
   199 			goto error;
   200 		}
   201 	} else {
   202 		memset( &auth_realm_spec, 0, sizeof(pv_spec_t));
   203 		memset( &auth_password_spec, 0, sizeof(pv_spec_t));
   204 		memset( &auth_username_spec, 0, sizeof(pv_spec_t));
   205 	}
   207 	/* load the TM API - FIXME it should be loaded only
   208 	 * if NO_RESTORE and AUTH */
   209 	if (load_tm_api(&uac_tmb)!=0) {
   210 		LM_ERR("can't load TM API\n");
   211 		goto error;
   212 	}
   214 	if (restore_mode!=UAC_NO_RESTORE) {
   215 		/* load the RR API */
   216 		if (load_rr_api(&uac_rrb)!=0) {
   217 			LM_ERR("can't load RR API\n");
   218 			goto error;
   219 		}
   221 		if (restore_mode==UAC_AUTO_RESTORE) {
   222 			/* we need the append_fromtag on in RR */
   223 			if (!uac_rrb.append_fromtag) {
   224 				LM_ERR("'append_fromtag' RR param is not enabled!"
   225 					" - required by AUTO restore mode\n");
   226 				goto error;
   227 			}
   228 			/* get all requests doing loose route */
   229 			if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
   230 				LM_ERR("failed to install RR callback\n");
   231 				goto error;
   232 			}
   233 		}
   234 	}
   236 	init_from_replacer();
   238 	return 0;
   239 error:
   240 	return -1;
   241 }
   244 static void mod_destroy(void)
   245 {
   246 	destroy_credentials();
   247 }
   251 /************************** fixup functions ******************************/
   253 static int fixup_replace_uri(void** param, int param_no)
   254 {
   255 	pv_elem_t *model;
   256 	str s;
   258 	model=NULL;
   259 	s.s = (char*)(*param); s.len = strlen(s.s);
   260 	if(pv_parse_format(&s, &model)<0)
   261 	{
   262 		LM_ERR("wrong format[%s]!\n",(char*)(*param));
   263 		return E_UNSPEC;
   264 	}
   265 	if (model==NULL)
   266 	{
   267 		LM_ERR("empty parameter!\n");
   268 		return E_UNSPEC;
   269 	}
   270 	*param = (void*)model;
   272 	return 0;
   273 }
   276 static int fixup_replace_disp_uri(void** param, int param_no)
   277 {
   278 	pv_elem_t *model;
   279 	char *p;
   280 	str s;
   282 	/* convert to str */
   283 	s.s = (char*)*param;
   284 	s.len = strlen(s.s);
   286 	model=NULL;
   287 	if (param_no==1 && s.len) {
   288 		/* put " around display name */
   289 		p = (char*)pkg_malloc(s.len+3);
   290 		if (p==0) {
   291 			LM_CRIT("no more pkg mem\n");
   292 			return E_OUT_OF_MEM;
   293 		}
   294 		p[0] = '\"';
   295 		memcpy(p+1, s.s, s.len);
   296 		p[s.len+1] = '\"';
   297 		p[s.len+2] = '\0';
   298 		pkg_free(s.s);
   299 		s.s = p;
   300 		s.len += 2;
   301 	}
   302 	if(pv_parse_format(&s ,&model)<0) {
   303 		LM_ERR("wrong format [%s] for param no %d!\n", s.s, param_no);
   304 		pkg_free(s.s);
   305 		return E_UNSPEC;
   306 	}
   307 	*param = (void*)model;
   309 	return 0;
   310 }
   314 /************************** wrapper functions ******************************/
   316 static int w_restore_from(struct sip_msg *msg)
   317 {
   318 	/* safety checks - must be a request */
   319 	if (msg->first_line.type!=SIP_REQUEST) {
   320 		LM_ERR("called for something not request\n");
   321 		return -1;
   322 	}
   324 	return (restore_uri(msg,&rr_from_param,1)==0)?1:-1;
   325 }
   328 static int w_replace_from(struct sip_msg* msg, char* p1, char* p2)
   329 {
   330 	str uri_s;
   331 	str dsp_s;
   332 	str *uri;
   333 	str *dsp;
   335 	if (p2==NULL) {
   336 		p2 = p1;
   337 		p1 = NULL;
   338 		dsp = NULL;
   339 	}
   341 	/* p1 dispaly , p2 uri */
   343 	if ( p1!=NULL ) {
   344 		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   345 			return -1;
   346 		dsp = &dsp_s;
   347 	}
   349 	/* compute the URI string; if empty string -> make it NULL */
   350 	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   351 		return -1;
   352 	uri = uri_s.len?&uri_s:NULL;
   354 	if (parse_from_header(msg)<0 ) {
   355 		LM_ERR("failed to find/parse FROM hdr\n");
   356 		return -1;
   357 	}
   359 	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n",
   360 		dsp,dsp?dsp->len:0,uri,uri?uri->len:0);
   362 	return (replace_uri(msg, dsp, uri, msg->from, &rr_from_param)==0)?1:-1;
   363 }
   366 static int w_restore_to(struct sip_msg *msg)
   367 {
   368 	/* safety checks - must be a request */
   369 	if (msg->first_line.type!=SIP_REQUEST) {
   370 		LM_ERR("called for something not request\n");
   371 		return -1;
   372 	}
   374 	return (restore_uri(msg,&rr_to_param,0)==0)?1:-1;
   375 }
   378 static int w_replace_to(struct sip_msg* msg, char* p1, char* p2)
   379 {
   380 	str uri_s;
   381 	str dsp_s;
   382 	str *uri;
   383 	str *dsp;
   385 	if (p2==NULL) {
   386 		p2 = p1;
   387 		p1 = NULL;
   388 		dsp = NULL;
   389 	}
   391 	/* p1 dispaly , p2 uri */
   393 	if ( p1!=NULL ) {
   394 		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   395 			return -1;
   396 		dsp = &dsp_s;
   397 	}
   399 	/* compute the URI string; if empty string -> make it NULL */
   400 	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   401 		return -1;
   402 	uri = uri_s.len?&uri_s:NULL;
   404 	/* parse TO hdr */
   405 	if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
   406 		LM_ERR("failed to parse TO hdr\n");
   407 		return -1;
   408 	}
   410 	return (replace_uri(msg, dsp, uri, msg->to, &rr_to_param)==0)?1:-1;
   411 }
   416 static int w_uac_auth(struct sip_msg* msg, char* str, char* str2)
   417 {
   418 	return (uac_auth(msg)==0)?1:-1;
   419 }

mercurial