opensips/modules/uac/auth.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: auth.c 5901 2009-07-21 07:45:05Z bogdan_iancu $
michael@16 3 *
michael@16 4 * Copyright (C) 2005 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 * 2006-03-02 UAC authentication looks first in AVPs for credential (bogdan)
michael@18 27 * 2010-01-18 UAC replaces proxy-auth entries with new credentials (msvb)
michael@16 28 */
michael@16 29
michael@16 30
michael@16 31 #include <ctype.h>
michael@16 32 #include <string.h>
michael@16 33
michael@16 34 #include "../../str.h"
michael@16 35 #include "../../dprint.h"
michael@16 36 #include "../../pvar.h"
michael@16 37 #include "../../data_lump.h"
michael@16 38 #include "../../mem/mem.h"
michael@16 39 #include "../tm/tm_load.h"
michael@16 40
michael@16 41 #include "auth.h"
michael@16 42 #include "auth_alg.h"
michael@16 43 #include "auth_hdr.h"
michael@16 44
michael@16 45
michael@16 46 extern struct tm_binds uac_tmb;
michael@16 47 extern pv_spec_t auth_username_spec;
michael@16 48 extern pv_spec_t auth_realm_spec;
michael@16 49 extern pv_spec_t auth_password_spec;
michael@16 50
michael@16 51
michael@16 52 static struct uac_credential *crd_list = 0;
michael@16 53
michael@16 54
michael@16 55 #define duplicate_str(_strd, _strs, _error) \
michael@16 56 do { \
michael@16 57 _strd.s = (char*)pkg_malloc(_strs.len); \
michael@16 58 if (_strd.s==0) \
michael@16 59 { \
michael@16 60 LM_ERR("no more pkg memory\n");\
michael@16 61 goto _error; \
michael@16 62 } \
michael@16 63 memcpy( _strd.s, _strs.s, _strs.len); \
michael@16 64 _strd.len = _strs.len; \
michael@16 65 }while(0)
michael@16 66
michael@16 67
michael@16 68 #define WWW_AUTH_CODE 401
michael@16 69 #define WWW_AUTH_HDR "WWW-Authenticate"
michael@16 70 #define WWW_AUTH_HDR_LEN (sizeof(WWW_AUTH_HDR)-1)
michael@16 71 #define PROXY_AUTH_CODE 407
michael@16 72 #define PROXY_AUTH_HDR "Proxy-Authenticate"
michael@16 73 #define PROXY_AUTH_HDR_LEN (sizeof(PROXY_AUTH_HDR)-1)
michael@16 74
michael@16 75 static str nc = {"00000001", 8};
michael@16 76 static str cnonce = {"o", 1};
michael@16 77
michael@16 78 int has_credentials(void)
michael@16 79 {
michael@16 80 return (crd_list!=0)?1:0;
michael@16 81 }
michael@16 82
michael@16 83 void free_credential(struct uac_credential *crd)
michael@16 84 {
michael@16 85 if (crd)
michael@16 86 {
michael@16 87 if (crd->realm.s)
michael@16 88 pkg_free(crd->realm.s);
michael@16 89 if (crd->user.s)
michael@16 90 pkg_free(crd->user.s);
michael@16 91 if (crd->passwd.s)
michael@16 92 pkg_free(crd->passwd.s);
michael@16 93 pkg_free(crd);
michael@16 94 }
michael@16 95 }
michael@16 96
michael@16 97
michael@16 98 int add_credential( unsigned int type, void *val)
michael@16 99 {
michael@16 100 struct uac_credential *crd;
michael@16 101 char *p;
michael@16 102 str foo;
michael@16 103
michael@16 104 p = (char*)val;
michael@16 105 crd = 0;
michael@16 106
michael@16 107 if (p==0 || *p==0)
michael@16 108 goto error;
michael@16 109
michael@16 110 crd = (struct uac_credential*)pkg_malloc(sizeof(struct uac_credential));
michael@16 111 if (crd==0)
michael@16 112 {
michael@16 113 LM_ERR("no more pkg mem\n");
michael@16 114 goto error;
michael@16 115 }
michael@16 116 memset( crd, 0, sizeof(struct uac_credential));
michael@16 117
michael@16 118 /*parse the user */
michael@16 119 while (*p && isspace((int)*p)) p++;
michael@16 120 foo.s = p;
michael@16 121 while (*p && *p!=':' && !isspace((int)*p)) p++;
michael@16 122 if (foo.s==p || *p==0)
michael@16 123 /* missing or empty user */
michael@16 124 goto parse_error;
michael@16 125 foo.len = p - foo.s;
michael@16 126 /* dulicate it */
michael@16 127 duplicate_str( crd->user, foo, error);
michael@16 128
michael@16 129 /* parse the ':' separator */
michael@16 130 while (*p && isspace((int)*p)) p++;
michael@16 131 if (*p!=':')
michael@16 132 goto parse_error;
michael@16 133 p++;
michael@16 134 while (*p && isspace((int)*p)) p++;
michael@16 135 if (*p==0)
michael@16 136 goto parse_error;
michael@16 137
michael@16 138 /*parse the realm */
michael@16 139 while (*p && isspace((int)*p)) p++;
michael@16 140 foo.s = p;
michael@16 141 while (*p && *p!=':' && !isspace((int)*p)) p++;
michael@16 142 if (foo.s==p || *p==0)
michael@16 143 /* missing or empty realm */
michael@16 144 goto parse_error;
michael@16 145 foo.len = p - foo.s;
michael@16 146 /* dulicate it */
michael@16 147 duplicate_str( crd->realm, foo, error);
michael@16 148
michael@16 149 /* parse the ':' separator */
michael@16 150 while (*p && isspace((int)*p)) p++;
michael@16 151 if (*p!=':')
michael@16 152 goto parse_error;
michael@16 153 p++;
michael@16 154 while (*p && isspace((int)*p)) p++;
michael@16 155 if (*p==0)
michael@16 156 goto parse_error;
michael@16 157
michael@16 158 /*parse the passwd */
michael@16 159 while (*p && isspace((int)*p)) p++;
michael@16 160 foo.s = p;
michael@16 161 while (*p && !isspace((int)*p)) p++;
michael@16 162 if (foo.s==p)
michael@16 163 /* missing or empty passwd */
michael@16 164 goto parse_error;
michael@16 165 foo.len = p - foo.s;
michael@16 166 /* dulicate it */
michael@16 167 duplicate_str( crd->passwd, foo, error);
michael@16 168
michael@16 169 /* end of string */
michael@16 170 while (*p && isspace((int)*p)) p++;
michael@16 171 if (*p!=0)
michael@16 172 goto parse_error;
michael@16 173
michael@16 174 /* link the new cred struct */
michael@16 175 crd->next = crd_list;
michael@16 176 crd_list = crd;
michael@16 177
michael@16 178 pkg_free(val);
michael@16 179 return 0;
michael@16 180 parse_error:
michael@16 181 LM_ERR("parse error in <%s> "
michael@16 182 "around %ld\n", (char*)val, (long)(p-(char*)val));
michael@16 183 error:
michael@16 184 if (crd)
michael@16 185 free_credential(crd);
michael@16 186 return -1;
michael@16 187 }
michael@16 188
michael@16 189
michael@16 190 void destroy_credentials(void)
michael@16 191 {
michael@16 192 struct uac_credential *foo;
michael@16 193
michael@16 194 while (crd_list)
michael@16 195 {
michael@16 196 foo = crd_list;
michael@16 197 crd_list = crd_list->next;
michael@16 198 free_credential(foo);
michael@16 199 }
michael@16 200 crd_list = 0;
michael@16 201 }
michael@16 202
michael@16 203
michael@16 204 static inline struct hdr_field *get_autenticate_hdr(struct sip_msg *rpl,
michael@16 205 int rpl_code)
michael@16 206 {
michael@16 207 struct hdr_field *hdr;
michael@16 208 str hdr_name;
michael@16 209
michael@16 210 /* what hdr should we look for */
michael@16 211 if (rpl_code==WWW_AUTH_CODE)
michael@16 212 {
michael@16 213 hdr_name.s = WWW_AUTH_HDR;
michael@16 214 hdr_name.len = WWW_AUTH_HDR_LEN;
michael@16 215 } else if (rpl_code==PROXY_AUTH_CODE) {
michael@16 216 hdr_name.s = PROXY_AUTH_HDR;
michael@16 217 hdr_name.len = PROXY_AUTH_HDR_LEN;
michael@16 218 } else {
michael@16 219 LM_ERR("reply is not an "
michael@16 220 "auth request\n");
michael@16 221 goto error;
michael@16 222 }
michael@16 223
michael@16 224 LM_DBG("looking for header \"%.*s\"\n",
michael@16 225 hdr_name.len, hdr_name.s);
michael@16 226
michael@16 227 /* search the auth hdr, but first parse them all */
michael@16 228 if (parse_headers( rpl, HDR_EOH_F, 0)<0)
michael@16 229 {
michael@16 230 LM_ERR("failed to parse reply\n");
michael@16 231 goto error;
michael@16 232 }
michael@16 233 hdr = get_header_by_name( rpl , hdr_name.s, hdr_name.len);
michael@16 234 if (hdr)
michael@16 235 return hdr;
michael@16 236
michael@16 237 LM_ERR("reply has no "
michael@16 238 "auth hdr (%.*s)\n", hdr_name.len, hdr_name.s);
michael@16 239 error:
michael@16 240 return 0;
michael@16 241 }
michael@16 242
michael@16 243
michael@16 244 static inline struct uac_credential *lookup_realm( str *realm)
michael@16 245 {
michael@16 246 struct uac_credential *crd;
michael@16 247
michael@16 248 for( crd=crd_list ; crd ; crd=crd->next )
michael@16 249 if (realm->len==crd->realm.len &&
michael@16 250 strncmp( realm->s, crd->realm.s, realm->len)==0 )
michael@16 251 return crd;
michael@16 252 return 0;
michael@16 253 }
michael@16 254
michael@16 255
michael@16 256 static inline struct uac_credential *get_avp_credential(struct sip_msg *msg,
michael@16 257 str *realm)
michael@16 258 {
michael@16 259 static struct uac_credential crd;
michael@16 260 pv_value_t pv_val;
michael@16 261
michael@16 262 if(pv_get_spec_value( msg, &auth_realm_spec, &pv_val)!=0
michael@16 263 || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
michael@16 264 return 0;
michael@16 265
michael@16 266 crd.realm = pv_val.rs;
michael@16 267 /* is it the domain we are looking for? */
michael@16 268 if (realm->len!=crd.realm.len ||
michael@16 269 strncmp( realm->s, crd.realm.s, realm->len)!=0 )
michael@16 270 return 0;
michael@16 271
michael@16 272 /* get username and password */
michael@16 273 if(pv_get_spec_value( msg, &auth_username_spec, &pv_val)!=0
michael@16 274 || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
michael@16 275 return 0;
michael@16 276 crd.user = pv_val.rs;
michael@16 277
michael@16 278 if(pv_get_spec_value( msg, &auth_password_spec, &pv_val)!=0
michael@16 279 || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
michael@16 280 return 0;
michael@16 281 crd.passwd = pv_val.rs;
michael@16 282
michael@16 283 return &crd;
michael@16 284 }
michael@16 285
michael@16 286
michael@16 287 static inline void do_uac_auth(struct sip_msg *req, str *uri,
michael@16 288 struct uac_credential *crd, struct authenticate_body *auth,
michael@16 289 HASHHEX response)
michael@16 290 {
michael@16 291 HASHHEX ha1;
michael@16 292 HASHHEX ha2;
michael@16 293
michael@16 294 if((auth->flags&QOP_AUTH) || (auth->flags&QOP_AUTH_INT))
michael@16 295 {
michael@16 296 /* if qop generate nonce-count and cnonce */
michael@16 297 cnonce.s = int2str(core_hash(&auth->nonce, 0, 0),&cnonce.len);
michael@16 298
michael@16 299 /* do authentication */
michael@16 300 uac_calc_HA1( crd, auth, &cnonce, ha1);
michael@16 301 uac_calc_HA2( &req->first_line.u.request.method, uri,
michael@16 302 auth, 0/*hentity*/, ha2 );
michael@16 303
michael@16 304 uac_calc_response( ha1, ha2, auth, &nc, &cnonce, response);
michael@16 305 auth->nc = &nc;
michael@16 306 auth->cnonce = &cnonce;
michael@16 307 } else {
michael@16 308 /* do authentication */
michael@16 309 uac_calc_HA1( crd, auth, 0/*cnonce*/, ha1);
michael@16 310 uac_calc_HA2( &req->first_line.u.request.method, uri,
michael@16 311 auth, 0/*hentity*/, ha2 );
michael@16 312
michael@16 313 uac_calc_response( ha1, ha2, auth, 0/*nc*/, 0/*cnonce*/, response);
michael@16 314 }
michael@16 315 }
michael@16 316
michael@16 317
michael@16 318 static inline int apply_urihdr_changes( struct sip_msg *req,
michael@16 319 str *uri, str *hdr)
michael@16 320 {
michael@16 321 struct lump* anchor;
michael@16 322
michael@16 323 /* add the uri - move it to branch directly FIXME (bogdan)*/
michael@16 324 if (req->new_uri.s)
michael@16 325 {
michael@16 326 pkg_free(req->new_uri.s);
michael@16 327 req->new_uri.len=0;
michael@16 328 }
michael@16 329 req->parsed_uri_ok=0;
michael@16 330 req->new_uri.s = (char*)pkg_malloc(uri->len+1);
michael@16 331 if (req->new_uri.s==0)
michael@16 332 {
michael@16 333 LM_ERR("no more pkg\n");
michael@16 334 goto error;
michael@16 335 }
michael@16 336 memcpy( req->new_uri.s, uri->s, uri->len);
michael@16 337 req->new_uri.s[uri->len]=0;
michael@16 338 req->new_uri.len=uri->len;
michael@16 339
michael@16 340 /* add the header */
michael@16 341 if (parse_headers(req, HDR_EOH_F, 0) == -1)
michael@16 342 {
michael@16 343 LM_ERR("failed to parse message\n");
michael@16 344 goto error;
michael@16 345 }
michael@16 346
michael@16 347 anchor = anchor_lump(req, req->unparsed - req->buf, 0, 0);
michael@16 348 if (anchor==0)
michael@16 349 {
michael@16 350 LM_ERR("failed to get anchor\n");
michael@16 351 goto error;
michael@16 352 }
michael@16 353
michael@16 354 if (insert_new_lump_before(anchor, hdr->s, hdr->len, 0) == 0)
michael@16 355 {
michael@16 356 LM_ERR("faield to insert lump\n");
michael@16 357 goto error;
michael@16 358 }
michael@16 359
michael@16 360 return 0;
michael@16 361 error:
michael@16 362 pkg_free( hdr->s );
michael@16 363 return -1;
michael@16 364 }
michael@16 365
michael@16 366
michael@16 367
michael@16 368 int uac_auth( struct sip_msg *msg)
michael@16 369 {
michael@16 370 static struct authenticate_body auth;
michael@16 371 struct uac_credential *crd;
michael@16 372 int code, branch;
michael@16 373 struct sip_msg *rpl;
michael@16 374 struct cell *t;
michael@16 375 struct hdr_field *hdr;
michael@16 376 HASHHEX response;
michael@16 377 str *new_hdr;
michael@16 378
michael@18 379 /* pretransact */
michael@18 380 int nret = 0;
michael@18 381 pv_value_t pv_val;
michael@18 382 str *newuri = 0;
michael@18 383 struct uac_credential *tst = 0;
michael@18 384 struct hdr_field *tmp_hdr = 0;
michael@18 385 struct hdr_field *del_hdr = 0;
michael@18 386
michael@18 387
michael@18 388 /* Goes something like this... */
michael@18 389 /* HA1 = echo -n 'username:realm:password' | md5sum */
michael@18 390 /* echo -n 'itsme:mydom.com:stupidpass' | md5sum */
michael@18 391 /* HA2 = echo -n 'message:uri' | md5sum */
michael@18 392 /* echo -n 'INVITE:sip:danc@ing.fool.es' | md5sum */
michael@18 393 /* Response = echo -n 'HA1:nonce:HA2' | md5sum */
michael@16 394 /* get transaction */
michael@16 395 t = uac_tmb.t_gett();
michael@18 396 if (t==T_UNDEFINED || t==T_NULL_CELL) {
michael@18 397 /* begin without any transaction */
michael@18 398 /* set relevant structure variables */
michael@18 399 crd = 0;
michael@18 400 crd = pkg_malloc(sizeof(struct uac_credential));
michael@18 401 if (!crd) {
michael@18 402 LM_ERR("no more pkg memory\n");
michael@18 403 goto error;
michael@18 404 }
michael@16 405
michael@18 406 /* set the realm from existing UAC message */
michael@18 407 tmp_hdr = msg->proxy_auth;
michael@18 408 del_hdr = 0;
michael@18 409 while (tmp_hdr) {
michael@18 410 crd->realm.s = strchr(strstr(tmp_hdr->body.s, "realm="), '"') + 1;
michael@18 411 crd->realm.len = strchr(crd->realm.s, '"') - crd->realm.s;
michael@18 412 if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
michael@18 413 && pv_val.rs.len>0) /* ensure realm is the desired one */
michael@18 414 if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0)
michael@18 415 del_hdr = tmp_hdr;
michael@18 416 tmp_hdr = tmp_hdr->sibling;
michael@18 417 }
michael@18 418 if (del_hdr)
michael@18 419 crd->realm = pv_val.rs; /* success */
michael@18 420 else
michael@18 421 nret++; /* failure */
michael@18 422
michael@18 423 /* set username from new AVP proxy values */
michael@18 424 if(pv_get_spec_value(msg, &auth_username_spec, &pv_val)!=0 \
michael@18 425 || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
michael@18 426 nret++; /* signal failure with nonzero value */
michael@18 427 else
michael@18 428 crd->user = pv_val.rs;
michael@18 429
michael@18 430 /* set password from new AVP proxy values */
michael@18 431 if(pv_get_spec_value(msg, &auth_password_spec, &pv_val)!=0 \
michael@18 432 || pv_val.flags&PV_VAL_NULL || pv_val.rs.len<=0)
michael@18 433 nret++; /* signal failure with nonzero value */
michael@18 434 else
michael@18 435 crd->passwd = pv_val.rs;
michael@18 436
michael@18 437 if (nret) { /* if not found, look into predefined credentials */
michael@18 438 tst = lookup_realm(&crd->realm);
michael@18 439
michael@18 440 if (tst==0) { /* found? */
michael@18 441 LM_DBG("no credential for realm \"%.*s\"\n", \
michael@18 442 crd->realm.len, crd->realm.s);
michael@18 443 pkg_free(crd);
michael@18 444 goto error;
michael@18 445 }
michael@18 446
michael@18 447 crd = tst; /* use predefined credentials */
michael@18 448 /* set the realm from existing UAC message */
michael@18 449 tmp_hdr = msg->proxy_auth;
michael@18 450 del_hdr = 0;
michael@18 451 while (tmp_hdr) {
michael@18 452 if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
michael@18 453 && pv_val.rs.len>0) /* ensure realm is the desired one */
michael@18 454 if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0)
michael@18 455 del_hdr = tmp_hdr;
michael@18 456 tmp_hdr = tmp_hdr->sibling;
michael@18 457 }
michael@18 458 if (del_hdr == 0) { /* proxy-auth header matching realm not found */
michael@18 459 LM_DBG("no credential for realm \"%.*s\"\n", \
michael@18 460 crd->realm.len, crd->realm.s);
michael@18 461 pkg_free(crd);
michael@18 462 goto error;
michael@18 463 }
michael@18 464 }
michael@18 465
michael@18 466 /* set the uri from existing UAC message */
michael@18 467 newuri = pkg_malloc(sizeof(str));
michael@18 468 if (!newuri) {
michael@18 469 LM_ERR("no more pkg memory\n");
michael@18 470 goto error;
michael@18 471 }
michael@18 472 newuri->s = pkg_malloc(msg->new_uri.len);
michael@18 473 if (!newuri->s) {
michael@18 474 LM_ERR("no more pkg memory\n");
michael@18 475 pkg_free(newuri);
michael@18 476 goto error;
michael@18 477 }
michael@18 478 newuri->len = msg->new_uri.len;
michael@18 479 strncpy(newuri->s, msg->new_uri.s, msg->new_uri.len);
michael@18 480 if (!newuri->s) {
michael@18 481 LM_DBG("failed to retrieve URI from UAC message\n");
michael@18 482 pkg_free(newuri->s);
michael@18 483 pkg_free(newuri);
michael@18 484 goto error;
michael@18 485 }
michael@18 486
michael@18 487 /* set the nonce from existing UAC message */
michael@18 488 tmp_hdr = msg->proxy_auth;
michael@18 489 auth.nonce.len = 0;
michael@18 490 auth.nonce.s = 0;
michael@18 491 while (tmp_hdr) {
michael@18 492 if(pv_get_spec_value(msg, &auth_realm_spec, &pv_val)==0 \
michael@18 493 && pv_val.rs.len>0) /* ensure realm is the desired one */
michael@18 494 if (strncmp(crd->realm.s, pv_val.rs.s, crd->realm.len)==0) {
michael@18 495 auth.nonce.s = strchr(strstr(tmp_hdr->body.s, "nonce="), '"') + 1;
michael@18 496 auth.nonce.len = strchr(auth.nonce.s, '"') - auth.nonce.s;
michael@18 497 }
michael@18 498 tmp_hdr = tmp_hdr->sibling;
michael@18 499 }
michael@18 500 if (auth.nonce.s == 0) {
michael@18 501 LM_DBG("failed to retrieve nonce from UAC message\n");
michael@18 502 pkg_free(crd);
michael@18 503 goto error;
michael@18 504 }
michael@18 505
michael@18 506 /* do authentication */
michael@18 507 do_uac_auth(msg, newuri, crd, &auth, response);
michael@18 508 if (response==0) {
michael@18 509 LM_ERR("failed to calculate challenge response\n");
michael@18 510 pkg_free(crd);
michael@18 511 goto error;
michael@18 512 }
michael@18 513
michael@18 514 /* build the authorization header */
michael@18 515 new_hdr = build_authorization_hdr(407, newuri, crd, &auth, response);
michael@18 516 if (new_hdr==0) {
michael@18 517 LM_ERR("failed to build authorization hdr\n");
michael@18 518 pkg_free(crd);
michael@18 519 goto error;
michael@18 520 }
michael@18 521
michael@18 522 /* remove the old proxy-auth header and relink message index */
michael@18 523 /* before updating the authorization credentials of the message */
michael@18 524 if (del_hdr) { /* updated a record and must remove the old one */
michael@18 525 if (del_lump(msg, del_hdr->name.s - msg->buf, del_hdr->len, 0)==0) {
michael@18 526 LM_ERR("can't remove credentials\n");
michael@18 527 pkg_free(crd);
michael@18 528 goto error;
michael@18 529 }
michael@18 530 }
michael@18 531
michael@18 532 /* so far, so good -> add the header and set the proper RURI */
michael@18 533 if (apply_urihdr_changes(msg, newuri, new_hdr)<0)
michael@18 534 {
michael@18 535 LM_ERR("failed to apply changes\n");
michael@18 536 pkg_free(crd);
michael@18 537 goto error;
michael@18 538 }
michael@18 539
michael@18 540 pkg_free(crd); /* finished calculating new response string, success */
michael@18 541 return 0;
michael@18 542 } /* if (t==T_UNDEFINED || t==T_NULL_CELL) */
michael@18 543
michael@18 544 /* begin with transaction reply */
michael@16 545 /* get the selected branch */
michael@16 546 branch = uac_tmb.t_get_picked();
michael@16 547 if (branch<0) {
michael@16 548 LM_CRIT("no picked branch (%d)\n",branch);
michael@16 549 goto error;
michael@16 550 }
michael@16 551
michael@16 552 rpl = t->uac[branch].reply;
michael@16 553 code = t->uac[branch].last_received;
michael@16 554 LM_DBG("picked reply is %p, code %d\n",rpl,code);
michael@16 555
michael@16 556 if (rpl==0)
michael@16 557 {
michael@16 558 LM_CRIT("empty reply on picked branch\n");
michael@16 559 goto error;
michael@16 560 }
michael@16 561 if (rpl==FAKED_REPLY)
michael@16 562 {
michael@16 563 LM_ERR("cannot process a FAKED reply\n");
michael@16 564 goto error;
michael@16 565 }
michael@16 566
michael@16 567 hdr = get_autenticate_hdr( rpl, code);
michael@16 568 if (hdr==0)
michael@16 569 {
michael@16 570 LM_ERR("failed to extract authenticate hdr\n");
michael@16 571 goto error;
michael@16 572 }
michael@16 573
michael@16 574 LM_DBG("header found; body=<%.*s>\n",
michael@16 575 hdr->body.len, hdr->body.s);
michael@16 576
michael@16 577 if (parse_authenticate_body( &hdr->body, &auth)<0)
michael@16 578 {
michael@16 579 LM_ERR("failed to parse auth hdr body\n");
michael@16 580 goto error;
michael@16 581 }
michael@16 582
michael@16 583 /* can we authenticate this realm? */
michael@16 584 crd = 0;
michael@16 585 /* first look into AVP, if set */
michael@16 586 if ( auth_realm_spec.type==PVT_AVP )
michael@16 587 crd = get_avp_credential( msg, &auth.realm );
michael@16 588 /* if not found, look into predefined credentials */
michael@16 589 if (crd==0)
michael@16 590 crd = lookup_realm( &auth.realm );
michael@16 591 /* found? */
michael@16 592 if (crd==0)
michael@16 593 {
michael@16 594 LM_DBG("no credential for realm \"%.*s\"\n",
michael@16 595 auth.realm.len, auth.realm.s);
michael@16 596 goto error;
michael@16 597 }
michael@16 598
michael@16 599 /* do authentication */
michael@16 600 do_uac_auth( msg, &t->uac[branch].uri, crd, &auth, response);
michael@16 601
michael@16 602 /* build the authorization header */
michael@16 603 new_hdr = build_authorization_hdr( code, &t->uac[branch].uri,
michael@16 604 crd, &auth, response);
michael@16 605 if (new_hdr==0)
michael@16 606 {
michael@16 607 LM_ERR("failed to build authorization hdr\n");
michael@16 608 goto error;
michael@16 609 }
michael@16 610
michael@16 611 /* so far, so good -> add the header and set the proper RURI */
michael@16 612 if ( apply_urihdr_changes( msg, &t->uac[branch].uri, new_hdr)<0 )
michael@16 613 {
michael@16 614 LM_ERR("failed to apply changes\n");
michael@16 615 goto error;
michael@16 616 }
michael@16 617
michael@16 618 /* increas the Cseq nr */
michael@16 619
michael@16 620
michael@16 621 return 0;
michael@16 622 error:
michael@16 623 return -1;
michael@16 624 }
michael@16 625
michael@16 626
michael@16 627

mercurial