opensips/modules/uac/uac.c

Wed, 10 Feb 2010 21:14:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 10 Feb 2010 21:14:04 +0100
changeset 16
c5c55937e44c
child 18
8ec65b8f6e2c
permissions
-rw-r--r--

Import unmodified vendor sources for correction and improvement.

     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)
    33  */
    36 #include <stdio.h>
    37 #include <string.h>
    38 #include <stdlib.h>
    40 #include "../../sr_module.h"
    41 #include "../../dprint.h"
    42 #include "../../error.h"
    43 #include "../../pvar.h"
    44 #include "../../mem/mem.h"
    45 #include "../../parser/parse_from.h"
    46 #include "../tm/tm_load.h"
    47 #include "../tm/t_hooks.h"
    48 #include "../rr/api.h"
    50 #include "replace.h"
    51 #include "auth.h"
    57 /* local variable used for init */
    58 static char* restore_mode_str = NULL;
    59 static char* auth_username_avp = NULL;
    60 static char* auth_realm_avp = NULL;
    61 static char* auth_password_avp = NULL;
    63 /* global param variables */
    64 str rr_from_param = str_init("vsf");
    65 str rr_to_param = str_init("vst");
    66 str uac_passwd = str_init("");
    67 int restore_mode = UAC_AUTO_RESTORE;
    68 struct tm_binds uac_tmb;
    69 struct rr_binds uac_rrb;
    70 pv_spec_t auth_username_spec;
    71 pv_spec_t auth_realm_spec;
    72 pv_spec_t auth_password_spec;
    74 static int w_replace_from(struct sip_msg* msg, char* p1, char* p2);
    75 static int w_restore_from(struct sip_msg* msg);
    77 static int w_replace_to(struct sip_msg* msg, char* p1, char* p2);
    78 static int w_restore_to(struct sip_msg* msg);
    80 static int w_uac_auth(struct sip_msg* msg, char* str, char* str2);
    81 static int fixup_replace_uri(void** param, int param_no);
    82 static int fixup_replace_disp_uri(void** param, int param_no);
    83 static int mod_init(void);
    84 static void mod_destroy(void);
    87 /* Exported functions */
    88 static cmd_export_t cmds[]={
    89 	{"uac_replace_from",  (cmd_function)w_replace_from,  2,
    90 			fixup_replace_disp_uri, 0,
    91 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    92 	{"uac_replace_from",  (cmd_function)w_replace_from,  1,
    93 			fixup_replace_uri, 0,
    94 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    95 	{"uac_restore_from",  (cmd_function)w_restore_from,   0,
    96 			0, 0,
    97 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    98 	{"uac_replace_to",  (cmd_function)w_replace_to,  2,
    99 			fixup_replace_disp_uri, 0,
   100 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   101 	{"uac_replace_to",  (cmd_function)w_replace_to,  1,
   102 			fixup_replace_uri, 0,
   103 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   104 	{"uac_restore_to",  (cmd_function)w_restore_to,   0,
   105 			0, 0,
   106 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   107 	{"uac_auth",          (cmd_function)w_uac_auth,       0,
   108 			0, 0,
   109 			FAILURE_ROUTE },
   110 	{0,0,0,0,0,0}
   111 };
   115 /* Exported parameters */
   116 static param_export_t params[] = {
   117 	{"rr_from_store_param", STR_PARAM,                &rr_from_param.s       },
   118 	{"rr_to_store_param",   STR_PARAM,                &rr_to_param.s         },
   119 	{"restore_mode",        STR_PARAM,                &restore_mode_str      },
   120 	{"restore_passwd",      STR_PARAM,                &uac_passwd.s          },
   121 	{"credential",          STR_PARAM|USE_FUNC_PARAM, (void*)&add_credential },
   122 	{"auth_username_avp",   STR_PARAM,                &auth_username_avp     },
   123 	{"auth_realm_avp",      STR_PARAM,                &auth_realm_avp        },
   124 	{"auth_password_avp",   STR_PARAM,                &auth_password_avp     },
   125 	{0, 0, 0}
   126 };
   130 struct module_exports exports= {
   131 	"uac",
   132 	MODULE_VERSION,
   133 	DEFAULT_DLFLAGS, /* dlopen flags */
   134 	cmds,       /* exported functions */
   135 	params,     /* param exports */
   136 	0,          /* exported statistics */
   137 	0,          /* exported MI functions */
   138 	0,          /* exported pseudo-variables */
   139 	0,          /* extra processes */
   140 	mod_init,   /* module initialization function */
   141 	(response_function) 0,
   142 	mod_destroy,
   143 	0  /* per-child init function */
   144 };
   147 inline static int parse_auth_avp( char *avp_spec, pv_spec_t *avp, char *txt)
   148 {
   149 	str s;
   150 	s.s = avp_spec; s.len = strlen(s.s);
   151 	if (pv_parse_spec(&s, avp)==NULL) {
   152 		LM_ERR("malformed or non AVP %s AVP definition\n",txt);
   153 		return -1;
   154 	}
   155 	return 0;
   156 }
   159 static int mod_init(void)
   160 {
   161 	LM_INFO("initializing...\n");
   163 	if (restore_mode_str && *restore_mode_str) {
   164 		if (strcasecmp(restore_mode_str,"none")==0) {
   165 			restore_mode = UAC_NO_RESTORE;
   166 		} else if (strcasecmp(restore_mode_str,"manual")==0) {
   167 			restore_mode = UAC_MANUAL_RESTORE;
   168 		} else if (strcasecmp(restore_mode_str,"auto")==0) {
   169 			restore_mode = UAC_AUTO_RESTORE;
   170 		} else {
   171 			LM_ERR("unsupported value '%s' for restore_mode\n",
   172 				restore_mode_str);
   173 			goto error;
   174 		}
   175 	}
   177 	rr_from_param.len = strlen(rr_from_param.s);
   178 	rr_to_param.len = strlen(rr_to_param.s);
   179 	if ( (rr_from_param.len==0 || rr_to_param.len==0) &&
   180 	restore_mode!=UAC_NO_RESTORE)
   181 	{
   182 		LM_ERR("rr_store_param cannot be empty if FROM is restoreable\n");
   183 		goto error;
   184 	}
   186 	uac_passwd.len = strlen(uac_passwd.s);
   188 	/* parse the auth AVP spesc, if any */
   189 	if ( auth_username_avp || auth_password_avp || auth_realm_avp) {
   190 		if (!auth_username_avp || !auth_password_avp || !auth_realm_avp) {
   191 			LM_ERR("partial definition of auth AVP!");
   192 			goto error;
   193 		}
   194 		if ( parse_auth_avp(auth_realm_avp, &auth_realm_spec, "realm")<0
   195 		|| parse_auth_avp(auth_username_avp, &auth_username_spec, "username")<0
   196 		|| parse_auth_avp(auth_password_avp, &auth_password_spec, "password")<0
   197 		) {
   198 			goto error;
   199 		}
   200 	} else {
   201 		memset( &auth_realm_spec, 0, sizeof(pv_spec_t));
   202 		memset( &auth_password_spec, 0, sizeof(pv_spec_t));
   203 		memset( &auth_username_spec, 0, sizeof(pv_spec_t));
   204 	}
   206 	/* load the TM API - FIXME it should be loaded only
   207 	 * if NO_RESTORE and AUTH */
   208 	if (load_tm_api(&uac_tmb)!=0) {
   209 		LM_ERR("can't load TM API\n");
   210 		goto error;
   211 	}
   213 	if (restore_mode!=UAC_NO_RESTORE) {
   214 		/* load the RR API */
   215 		if (load_rr_api(&uac_rrb)!=0) {
   216 			LM_ERR("can't load RR API\n");
   217 			goto error;
   218 		}
   220 		if (restore_mode==UAC_AUTO_RESTORE) {
   221 			/* we need the append_fromtag on in RR */
   222 			if (!uac_rrb.append_fromtag) {
   223 				LM_ERR("'append_fromtag' RR param is not enabled!"
   224 					" - required by AUTO restore mode\n");
   225 				goto error;
   226 			}
   227 			/* get all requests doing loose route */
   228 			if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
   229 				LM_ERR("failed to install RR callback\n");
   230 				goto error;
   231 			}
   232 		}
   233 	}
   235 	init_from_replacer();
   237 	return 0;
   238 error:
   239 	return -1;
   240 }
   243 static void mod_destroy(void)
   244 {
   245 	destroy_credentials();
   246 }
   250 /************************** fixup functions ******************************/
   252 static int fixup_replace_uri(void** param, int param_no)
   253 {
   254 	pv_elem_t *model;
   255 	str s;
   257 	model=NULL;
   258 	s.s = (char*)(*param); s.len = strlen(s.s);
   259 	if(pv_parse_format(&s, &model)<0)
   260 	{
   261 		LM_ERR("wrong format[%s]!\n",(char*)(*param));
   262 		return E_UNSPEC;
   263 	}
   264 	if (model==NULL)
   265 	{
   266 		LM_ERR("empty parameter!\n");
   267 		return E_UNSPEC;
   268 	}
   269 	*param = (void*)model;
   271 	return 0;
   272 }
   275 static int fixup_replace_disp_uri(void** param, int param_no)
   276 {
   277 	pv_elem_t *model;
   278 	char *p;
   279 	str s;
   281 	/* convert to str */
   282 	s.s = (char*)*param;
   283 	s.len = strlen(s.s);
   285 	model=NULL;
   286 	if (param_no==1 && s.len) {
   287 		/* put " around display name */
   288 		p = (char*)pkg_malloc(s.len+3);
   289 		if (p==0) {
   290 			LM_CRIT("no more pkg mem\n");
   291 			return E_OUT_OF_MEM;
   292 		}
   293 		p[0] = '\"';
   294 		memcpy(p+1, s.s, s.len);
   295 		p[s.len+1] = '\"';
   296 		p[s.len+2] = '\0';
   297 		pkg_free(s.s);
   298 		s.s = p;
   299 		s.len += 2;
   300 	}
   301 	if(pv_parse_format(&s ,&model)<0) {
   302 		LM_ERR("wrong format [%s] for param no %d!\n", s.s, param_no);
   303 		pkg_free(s.s);
   304 		return E_UNSPEC;
   305 	}
   306 	*param = (void*)model;
   308 	return 0;
   309 }
   313 /************************** wrapper functions ******************************/
   315 static int w_restore_from(struct sip_msg *msg)
   316 {
   317 	/* safety checks - must be a request */
   318 	if (msg->first_line.type!=SIP_REQUEST) {
   319 		LM_ERR("called for something not request\n");
   320 		return -1;
   321 	}
   323 	return (restore_uri(msg,&rr_from_param,1)==0)?1:-1;
   324 }
   327 static int w_replace_from(struct sip_msg* msg, char* p1, char* p2)
   328 {
   329 	str uri_s;
   330 	str dsp_s;
   331 	str *uri;
   332 	str *dsp;
   334 	if (p2==NULL) {
   335 		p2 = p1;
   336 		p1 = NULL;
   337 		dsp = NULL;
   338 	}
   340 	/* p1 dispaly , p2 uri */
   342 	if ( p1!=NULL ) {
   343 		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   344 			return -1;
   345 		dsp = &dsp_s;
   346 	}
   348 	/* compute the URI string; if empty string -> make it NULL */
   349 	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   350 		return -1;
   351 	uri = uri_s.len?&uri_s:NULL;
   353 	if (parse_from_header(msg)<0 ) {
   354 		LM_ERR("failed to find/parse FROM hdr\n");
   355 		return -1;
   356 	}
   358 	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n",
   359 		dsp,dsp?dsp->len:0,uri,uri?uri->len:0);
   361 	return (replace_uri(msg, dsp, uri, msg->from, &rr_from_param)==0)?1:-1;
   362 }
   365 static int w_restore_to(struct sip_msg *msg)
   366 {
   367 	/* safety checks - must be a request */
   368 	if (msg->first_line.type!=SIP_REQUEST) {
   369 		LM_ERR("called for something not request\n");
   370 		return -1;
   371 	}
   373 	return (restore_uri(msg,&rr_to_param,0)==0)?1:-1;
   374 }
   377 static int w_replace_to(struct sip_msg* msg, char* p1, char* p2)
   378 {
   379 	str uri_s;
   380 	str dsp_s;
   381 	str *uri;
   382 	str *dsp;
   384 	if (p2==NULL) {
   385 		p2 = p1;
   386 		p1 = NULL;
   387 		dsp = NULL;
   388 	}
   390 	/* p1 dispaly , p2 uri */
   392 	if ( p1!=NULL ) {
   393 		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   394 			return -1;
   395 		dsp = &dsp_s;
   396 	}
   398 	/* compute the URI string; if empty string -> make it NULL */
   399 	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   400 		return -1;
   401 	uri = uri_s.len?&uri_s:NULL;
   403 	/* parse TO hdr */
   404 	if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
   405 		LM_ERR("failed to parse TO hdr\n");
   406 		return -1;
   407 	}
   409 	return (replace_uri(msg, dsp, uri, msg->to, &rr_to_param)==0)?1:-1;
   410 }
   415 static int w_uac_auth(struct sip_msg* msg, char* str, char* str2)
   416 {
   417 	return (uac_auth(msg)==0)?1:-1;
   418 }

mercurial