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 +