opensips/modules/uac/uac.c

Mon, 16 Jan 2012 22:56:52 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 16 Jan 2012 22:56:52 +0100
changeset 21
6bb708a2265f
parent 16
c5c55937e44c
permissions
-rw-r--r--

Import original vendor code 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)
    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