opensips/modules/uac/uac.c

changeset 16
c5c55937e44c
child 18
8ec65b8f6e2c
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/opensips/modules/uac/uac.c	Wed Feb 10 21:14:04 2010 +0100
     1.3 @@ -0,0 +1,420 @@
     1.4 +/*
     1.5 + * $Id: uac.c 6481 2009-12-29 13:49:37Z bogdan_iancu $
     1.6 + *
     1.7 + * Copyright (C) 2005-2009 Voice Sistem SRL
     1.8 + *
     1.9 + * This file is part of opensips, a free SIP server.
    1.10 + *
    1.11 + * UAC OpenSIPS-module is free software; you can redistribute it and/or
    1.12 + * modify it under the terms of the GNU General Public License
    1.13 + * as published by the Free Software Foundation; either version 2
    1.14 + * of the License, or (at your option) any later version.
    1.15 + *
    1.16 + * UAC OpenSIPS-module is distributed in the hope that it will be useful,
    1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.19 + * GNU General Public License for more details.
    1.20 + *
    1.21 + * You should have received a copy of the GNU General Public License
    1.22 + * along with this program; if not, write to the Free Software
    1.23 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    1.24 + *
    1.25 + *
    1.26 + * History:
    1.27 + * ---------
    1.28 + *  2005-01-31  first version (ramona)
    1.29 + *  2005-08-12  some TM callbacks replaced with RR callback - more efficient;
    1.30 + *              (bogdan)
    1.31 + *  2006-03-02  UAC authentication looks first in AVPs for credential (bogdan)
    1.32 + *  2006-03-03  the RR parameter is encrypted via XOR with a password
    1.33 + *              (bogdan)
    1.34 + *  2009-08-22  TO header replacement added (bogdan)
    1.35 +
    1.36 + */
    1.37 +
    1.38 +
    1.39 +#include <stdio.h>
    1.40 +#include <string.h>
    1.41 +#include <stdlib.h>
    1.42 +
    1.43 +#include "../../sr_module.h"
    1.44 +#include "../../dprint.h"
    1.45 +#include "../../error.h"
    1.46 +#include "../../pvar.h"
    1.47 +#include "../../mem/mem.h"
    1.48 +#include "../../parser/parse_from.h"
    1.49 +#include "../tm/tm_load.h"
    1.50 +#include "../tm/t_hooks.h"
    1.51 +#include "../rr/api.h"
    1.52 +
    1.53 +#include "replace.h"
    1.54 +#include "auth.h"
    1.55 +
    1.56 +
    1.57 +
    1.58 +
    1.59 +
    1.60 +/* local variable used for init */
    1.61 +static char* restore_mode_str = NULL;
    1.62 +static char* auth_username_avp = NULL;
    1.63 +static char* auth_realm_avp = NULL;
    1.64 +static char* auth_password_avp = NULL;
    1.65 +
    1.66 +/* global param variables */
    1.67 +str rr_from_param = str_init("vsf");
    1.68 +str rr_to_param = str_init("vst");
    1.69 +str uac_passwd = str_init("");
    1.70 +int restore_mode = UAC_AUTO_RESTORE;
    1.71 +struct tm_binds uac_tmb;
    1.72 +struct rr_binds uac_rrb;
    1.73 +pv_spec_t auth_username_spec;
    1.74 +pv_spec_t auth_realm_spec;
    1.75 +pv_spec_t auth_password_spec;
    1.76 +
    1.77 +static int w_replace_from(struct sip_msg* msg, char* p1, char* p2);
    1.78 +static int w_restore_from(struct sip_msg* msg);
    1.79 +
    1.80 +static int w_replace_to(struct sip_msg* msg, char* p1, char* p2);
    1.81 +static int w_restore_to(struct sip_msg* msg);
    1.82 +
    1.83 +static int w_uac_auth(struct sip_msg* msg, char* str, char* str2);
    1.84 +static int fixup_replace_uri(void** param, int param_no);
    1.85 +static int fixup_replace_disp_uri(void** param, int param_no);
    1.86 +static int mod_init(void);
    1.87 +static void mod_destroy(void);
    1.88 +
    1.89 +
    1.90 +/* Exported functions */
    1.91 +static cmd_export_t cmds[]={
    1.92 +	{"uac_replace_from",  (cmd_function)w_replace_from,  2,
    1.93 +			fixup_replace_disp_uri, 0,
    1.94 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    1.95 +	{"uac_replace_from",  (cmd_function)w_replace_from,  1,
    1.96 +			fixup_replace_uri, 0,
    1.97 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
    1.98 +	{"uac_restore_from",  (cmd_function)w_restore_from,   0,
    1.99 +			0, 0,
   1.100 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   1.101 +	{"uac_replace_to",  (cmd_function)w_replace_to,  2,
   1.102 +			fixup_replace_disp_uri, 0,
   1.103 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   1.104 +	{"uac_replace_to",  (cmd_function)w_replace_to,  1,
   1.105 +			fixup_replace_uri, 0,
   1.106 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   1.107 +	{"uac_restore_to",  (cmd_function)w_restore_to,   0,
   1.108 +			0, 0,
   1.109 +			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE },
   1.110 +	{"uac_auth",          (cmd_function)w_uac_auth,       0,
   1.111 +			0, 0,
   1.112 +			FAILURE_ROUTE },
   1.113 +	{0,0,0,0,0,0}
   1.114 +};
   1.115 +
   1.116 +
   1.117 +
   1.118 +/* Exported parameters */
   1.119 +static param_export_t params[] = {
   1.120 +	{"rr_from_store_param", STR_PARAM,                &rr_from_param.s       },
   1.121 +	{"rr_to_store_param",   STR_PARAM,                &rr_to_param.s         },
   1.122 +	{"restore_mode",        STR_PARAM,                &restore_mode_str      },
   1.123 +	{"restore_passwd",      STR_PARAM,                &uac_passwd.s          },
   1.124 +	{"credential",          STR_PARAM|USE_FUNC_PARAM, (void*)&add_credential },
   1.125 +	{"auth_username_avp",   STR_PARAM,                &auth_username_avp     },
   1.126 +	{"auth_realm_avp",      STR_PARAM,                &auth_realm_avp        },
   1.127 +	{"auth_password_avp",   STR_PARAM,                &auth_password_avp     },
   1.128 +	{0, 0, 0}
   1.129 +};
   1.130 +
   1.131 +
   1.132 +
   1.133 +struct module_exports exports= {
   1.134 +	"uac",
   1.135 +	MODULE_VERSION,
   1.136 +	DEFAULT_DLFLAGS, /* dlopen flags */
   1.137 +	cmds,       /* exported functions */
   1.138 +	params,     /* param exports */
   1.139 +	0,          /* exported statistics */
   1.140 +	0,          /* exported MI functions */
   1.141 +	0,          /* exported pseudo-variables */
   1.142 +	0,          /* extra processes */
   1.143 +	mod_init,   /* module initialization function */
   1.144 +	(response_function) 0,
   1.145 +	mod_destroy,
   1.146 +	0  /* per-child init function */
   1.147 +};
   1.148 +
   1.149 +
   1.150 +inline static int parse_auth_avp( char *avp_spec, pv_spec_t *avp, char *txt)
   1.151 +{
   1.152 +	str s;
   1.153 +	s.s = avp_spec; s.len = strlen(s.s);
   1.154 +	if (pv_parse_spec(&s, avp)==NULL) {
   1.155 +		LM_ERR("malformed or non AVP %s AVP definition\n",txt);
   1.156 +		return -1;
   1.157 +	}
   1.158 +	return 0;
   1.159 +}
   1.160 +
   1.161 +
   1.162 +static int mod_init(void)
   1.163 +{
   1.164 +	LM_INFO("initializing...\n");
   1.165 +
   1.166 +	if (restore_mode_str && *restore_mode_str) {
   1.167 +		if (strcasecmp(restore_mode_str,"none")==0) {
   1.168 +			restore_mode = UAC_NO_RESTORE;
   1.169 +		} else if (strcasecmp(restore_mode_str,"manual")==0) {
   1.170 +			restore_mode = UAC_MANUAL_RESTORE;
   1.171 +		} else if (strcasecmp(restore_mode_str,"auto")==0) {
   1.172 +			restore_mode = UAC_AUTO_RESTORE;
   1.173 +		} else {
   1.174 +			LM_ERR("unsupported value '%s' for restore_mode\n",
   1.175 +				restore_mode_str);
   1.176 +			goto error;
   1.177 +		}
   1.178 +	}
   1.179 +
   1.180 +	rr_from_param.len = strlen(rr_from_param.s);
   1.181 +	rr_to_param.len = strlen(rr_to_param.s);
   1.182 +	if ( (rr_from_param.len==0 || rr_to_param.len==0) &&
   1.183 +	restore_mode!=UAC_NO_RESTORE)
   1.184 +	{
   1.185 +		LM_ERR("rr_store_param cannot be empty if FROM is restoreable\n");
   1.186 +		goto error;
   1.187 +	}
   1.188 +
   1.189 +	uac_passwd.len = strlen(uac_passwd.s);
   1.190 +
   1.191 +	/* parse the auth AVP spesc, if any */
   1.192 +	if ( auth_username_avp || auth_password_avp || auth_realm_avp) {
   1.193 +		if (!auth_username_avp || !auth_password_avp || !auth_realm_avp) {
   1.194 +			LM_ERR("partial definition of auth AVP!");
   1.195 +			goto error;
   1.196 +		}
   1.197 +		if ( parse_auth_avp(auth_realm_avp, &auth_realm_spec, "realm")<0
   1.198 +		|| parse_auth_avp(auth_username_avp, &auth_username_spec, "username")<0
   1.199 +		|| parse_auth_avp(auth_password_avp, &auth_password_spec, "password")<0
   1.200 +		) {
   1.201 +			goto error;
   1.202 +		}
   1.203 +	} else {
   1.204 +		memset( &auth_realm_spec, 0, sizeof(pv_spec_t));
   1.205 +		memset( &auth_password_spec, 0, sizeof(pv_spec_t));
   1.206 +		memset( &auth_username_spec, 0, sizeof(pv_spec_t));
   1.207 +	}
   1.208 +
   1.209 +	/* load the TM API - FIXME it should be loaded only
   1.210 +	 * if NO_RESTORE and AUTH */
   1.211 +	if (load_tm_api(&uac_tmb)!=0) {
   1.212 +		LM_ERR("can't load TM API\n");
   1.213 +		goto error;
   1.214 +	}
   1.215 +
   1.216 +	if (restore_mode!=UAC_NO_RESTORE) {
   1.217 +		/* load the RR API */
   1.218 +		if (load_rr_api(&uac_rrb)!=0) {
   1.219 +			LM_ERR("can't load RR API\n");
   1.220 +			goto error;
   1.221 +		}
   1.222 +
   1.223 +		if (restore_mode==UAC_AUTO_RESTORE) {
   1.224 +			/* we need the append_fromtag on in RR */
   1.225 +			if (!uac_rrb.append_fromtag) {
   1.226 +				LM_ERR("'append_fromtag' RR param is not enabled!"
   1.227 +					" - required by AUTO restore mode\n");
   1.228 +				goto error;
   1.229 +			}
   1.230 +			/* get all requests doing loose route */
   1.231 +			if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
   1.232 +				LM_ERR("failed to install RR callback\n");
   1.233 +				goto error;
   1.234 +			}
   1.235 +		}
   1.236 +	}
   1.237 +
   1.238 +	init_from_replacer();
   1.239 +
   1.240 +	return 0;
   1.241 +error:
   1.242 +	return -1;
   1.243 +}
   1.244 +
   1.245 +
   1.246 +static void mod_destroy(void)
   1.247 +{
   1.248 +	destroy_credentials();
   1.249 +}
   1.250 +
   1.251 +
   1.252 +
   1.253 +/************************** fixup functions ******************************/
   1.254 +
   1.255 +static int fixup_replace_uri(void** param, int param_no)
   1.256 +{
   1.257 +	pv_elem_t *model;
   1.258 +	str s;
   1.259 +
   1.260 +	model=NULL;
   1.261 +	s.s = (char*)(*param); s.len = strlen(s.s);
   1.262 +	if(pv_parse_format(&s, &model)<0)
   1.263 +	{
   1.264 +		LM_ERR("wrong format[%s]!\n",(char*)(*param));
   1.265 +		return E_UNSPEC;
   1.266 +	}
   1.267 +	if (model==NULL)
   1.268 +	{
   1.269 +		LM_ERR("empty parameter!\n");
   1.270 +		return E_UNSPEC;
   1.271 +	}
   1.272 +	*param = (void*)model;
   1.273 +
   1.274 +	return 0;
   1.275 +}
   1.276 +
   1.277 +
   1.278 +static int fixup_replace_disp_uri(void** param, int param_no)
   1.279 +{
   1.280 +	pv_elem_t *model;
   1.281 +	char *p;
   1.282 +	str s;
   1.283 +
   1.284 +	/* convert to str */
   1.285 +	s.s = (char*)*param;
   1.286 +	s.len = strlen(s.s);
   1.287 +
   1.288 +	model=NULL;
   1.289 +	if (param_no==1 && s.len) {
   1.290 +		/* put " around display name */
   1.291 +		p = (char*)pkg_malloc(s.len+3);
   1.292 +		if (p==0) {
   1.293 +			LM_CRIT("no more pkg mem\n");
   1.294 +			return E_OUT_OF_MEM;
   1.295 +		}
   1.296 +		p[0] = '\"';
   1.297 +		memcpy(p+1, s.s, s.len);
   1.298 +		p[s.len+1] = '\"';
   1.299 +		p[s.len+2] = '\0';
   1.300 +		pkg_free(s.s);
   1.301 +		s.s = p;
   1.302 +		s.len += 2;
   1.303 +	}
   1.304 +	if(pv_parse_format(&s ,&model)<0) {
   1.305 +		LM_ERR("wrong format [%s] for param no %d!\n", s.s, param_no);
   1.306 +		pkg_free(s.s);
   1.307 +		return E_UNSPEC;
   1.308 +	}
   1.309 +	*param = (void*)model;
   1.310 +
   1.311 +	return 0;
   1.312 +}
   1.313 +
   1.314 +
   1.315 +
   1.316 +/************************** wrapper functions ******************************/
   1.317 +
   1.318 +static int w_restore_from(struct sip_msg *msg)
   1.319 +{
   1.320 +	/* safety checks - must be a request */
   1.321 +	if (msg->first_line.type!=SIP_REQUEST) {
   1.322 +		LM_ERR("called for something not request\n");
   1.323 +		return -1;
   1.324 +	}
   1.325 +
   1.326 +	return (restore_uri(msg,&rr_from_param,1)==0)?1:-1;
   1.327 +}
   1.328 +
   1.329 +
   1.330 +static int w_replace_from(struct sip_msg* msg, char* p1, char* p2)
   1.331 +{
   1.332 +	str uri_s;
   1.333 +	str dsp_s;
   1.334 +	str *uri;
   1.335 +	str *dsp;
   1.336 +
   1.337 +	if (p2==NULL) {
   1.338 +		p2 = p1;
   1.339 +		p1 = NULL;
   1.340 +		dsp = NULL;
   1.341 +	}
   1.342 +
   1.343 +	/* p1 dispaly , p2 uri */
   1.344 +
   1.345 +	if ( p1!=NULL ) {
   1.346 +		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   1.347 +			return -1;
   1.348 +		dsp = &dsp_s;
   1.349 +	}
   1.350 +
   1.351 +	/* compute the URI string; if empty string -> make it NULL */
   1.352 +	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   1.353 +		return -1;
   1.354 +	uri = uri_s.len?&uri_s:NULL;
   1.355 +
   1.356 +	if (parse_from_header(msg)<0 ) {
   1.357 +		LM_ERR("failed to find/parse FROM hdr\n");
   1.358 +		return -1;
   1.359 +	}
   1.360 +
   1.361 +	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n",
   1.362 +		dsp,dsp?dsp->len:0,uri,uri?uri->len:0);
   1.363 +
   1.364 +	return (replace_uri(msg, dsp, uri, msg->from, &rr_from_param)==0)?1:-1;
   1.365 +}
   1.366 +
   1.367 +
   1.368 +static int w_restore_to(struct sip_msg *msg)
   1.369 +{
   1.370 +	/* safety checks - must be a request */
   1.371 +	if (msg->first_line.type!=SIP_REQUEST) {
   1.372 +		LM_ERR("called for something not request\n");
   1.373 +		return -1;
   1.374 +	}
   1.375 +
   1.376 +	return (restore_uri(msg,&rr_to_param,0)==0)?1:-1;
   1.377 +}
   1.378 +
   1.379 +
   1.380 +static int w_replace_to(struct sip_msg* msg, char* p1, char* p2)
   1.381 +{
   1.382 +	str uri_s;
   1.383 +	str dsp_s;
   1.384 +	str *uri;
   1.385 +	str *dsp;
   1.386 +
   1.387 +	if (p2==NULL) {
   1.388 +		p2 = p1;
   1.389 +		p1 = NULL;
   1.390 +		dsp = NULL;
   1.391 +	}
   1.392 +
   1.393 +	/* p1 dispaly , p2 uri */
   1.394 +
   1.395 +	if ( p1!=NULL ) {
   1.396 +		if(pv_printf_s( msg, (pv_elem_p)p1, &dsp_s)!=0)
   1.397 +			return -1;
   1.398 +		dsp = &dsp_s;
   1.399 +	}
   1.400 +
   1.401 +	/* compute the URI string; if empty string -> make it NULL */
   1.402 +	if (pv_printf_s( msg, (pv_elem_p)p2, &uri_s)!=0)
   1.403 +		return -1;
   1.404 +	uri = uri_s.len?&uri_s:NULL;
   1.405 +
   1.406 +	/* parse TO hdr */
   1.407 +	if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
   1.408 +		LM_ERR("failed to parse TO hdr\n");
   1.409 +		return -1;
   1.410 +	}
   1.411 +
   1.412 +	return (replace_uri(msg, dsp, uri, msg->to, &rr_to_param)==0)?1:-1;
   1.413 +}
   1.414 +
   1.415 +
   1.416 +
   1.417 +
   1.418 +static int w_uac_auth(struct sip_msg* msg, char* str, char* str2)
   1.419 +{
   1.420 +	return (uac_auth(msg)==0)?1:-1;
   1.421 +}
   1.422 +
   1.423 +

mercurial