opensips/modules/uac/uac.c

Mon, 16 Jan 2012 23:08:14 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 16 Jan 2012 23:08:14 +0100
changeset 23
d783b433388d
parent 16
c5c55937e44c
permissions
-rw-r--r--

Inconclusively complete possibly missing fields. This change introduces
inconsistencies difficult to correct given incomplete documentation of
IPKG and OPKG packaging standards.

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

mercurial