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.

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

mercurial