void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) { char *uuid; str suuid; reg_uac_t *ri = NULL; contact_t* c; int expires; struct sip_uri puri; struct hdr_field *hdr; HASHHEX response; str *new_auth_hdr = NULL; static struct authenticate_body auth; struct uac_credential cred; char b_ruri[MAX_URI_SIZE]; str s_ruri; #ifdef UAC_OLD_AUTH char b_turi[MAX_URI_SIZE]; str s_turi; #endif char b_hdrs[MAX_UACH_SIZE]; str s_hdrs; uac_req_t uac_r; str method = {"REGISTER", 8}; int ret; dlg_t tmdlg; if(ps->param==NULL || *ps->param==0) { LM_DBG("uuid not received\n"); return; } uuid = *((char**)ps->param); LM_DBG("completed with status %d [uuid: %s]\n", ps->code, uuid); suuid.s = uuid; suuid.len = strlen(suuid.s); ri = reg_ht_get_byuuid(&suuid); if(ri==NULL) { LM_DBG("no user with uuid %s\n", uuid); goto done; } if(ps->code == 200) { if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto error; } if (ps->rpl->contact==NULL) { LM_ERR("no Contact found\n"); goto error; } if (parse_contact(ps->rpl->contact) < 0) { LM_ERR("failed to parse Contact HF\n"); goto error; } if (((contact_body_t*)ps->rpl->contact->parsed)->star) { LM_DBG("* Contact found\n"); goto done; } if (contact_iterator(&c, ps->rpl, 0) < 0) goto done; while(c) { if(parse_uri(c->uri.s, c->uri.len, &puri)!=0) { LM_ERR("failed to parse c-uri\n"); goto error; } if(suuid.len==puri.user.len && (strncmp(puri.user.s, suuid.s, suuid.len)==0)) { /* calculate expires */ expires=0; if(c->expires==NULL || c->expires->body.len<=0) { if(ps->rpl->expires!=NULL && ps->rpl->expires->body.len>0) expires = atoi(ps->rpl->expires->body.s); } else { str2int(&c->expires->body, (unsigned int*)(&expires)); } ri->timer_expires = ri->timer_expires + expires; ri->flags |= UAC_REG_ONLINE; goto done; } if (contact_iterator(&c, ps->rpl, c) < 0) { LM_DBG("local contact not found\n"); goto done; } } } if(ps->code == 401 || ps->code == 407) { if(ri->flags & UAC_REG_AUTHSENT) { LM_ERR("authentication failed for <%.*s>\n", ri->l_uuid.len, ri->l_uuid.s); goto error; } hdr = get_autenticate_hdr(ps->rpl, ps->code); if (hdr==0) { LM_ERR("failed to extract authenticate hdr\n"); goto error; } LM_DBG("auth header body [%.*s]\n", hdr->body.len, hdr->body.s); if (parse_authenticate_body(&hdr->body, &auth)<0) { LM_ERR("failed to parse auth hdr body\n"); goto error; } if (ri->realm.len>0) { /* only check if realms match if it is non-empty */ if(auth.realm.len!=ri->realm.len || strncmp(auth.realm.s, ri->realm.s, ri->realm.len)!=0) { LM_ERR("realms do not match. requested realm: [%.*s]\n", auth.realm.len, auth.realm.s); goto error; } } cred.realm = auth.realm; cred.user = ri->auth_username; cred.passwd = ri->auth_password; cred.next = NULL; snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s", ri->r_domain.len, ri->r_domain.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); do_uac_auth(&method, &s_ruri, &cred, &auth, response); new_auth_hdr=build_authorization_hdr(ps->code, &s_ruri, &cred, &auth, response); if (new_auth_hdr==0) { LM_ERR("failed to build authorization hdr\n"); goto error; } #ifdef UAC_OLD_AUTH snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s", ri->r_username.len, ri->r_username.s, ri->r_domain.len, ri->r_domain.s); s_turi.s = b_turi; s_turi.len = strlen(s_turi.s); #endif snprintf(b_hdrs, MAX_UACH_SIZE, "Contact: <sip:%.*s@%.*s>\r\n" "Expires: %d\r\n" "%.*s", ri->l_uuid.len, ri->l_uuid.s, reg_contact_addr.len, reg_contact_addr.s, ri->expires, new_auth_hdr->len, new_auth_hdr->s); s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s); pkg_free(new_auth_hdr->s); memset(&uac_r, 0, sizeof(uac_r)); if(uac_reg_tmdlg(&tmdlg, ps->rpl)<0) { LM_ERR("failed to build tm dialog\n"); goto error; } tmdlg.rem_target = s_ruri; if(ri->auth_proxy.len) tmdlg.dst_uri = ri->auth_proxy; uac_r.method = &method; uac_r.headers = &s_hdrs; uac_r.dialog = &tmdlg; uac_r.cb_flags = TMCB_LOCAL_COMPLETED; /* Callback function */ uac_r.cb = uac_reg_tm_callback; /* Callback parameter */ uac_r.cbp = (void*)uuid; #ifdef UAC_OLD_AUTH ret = uac_tmb.t_request(&uac_r, /* UAC Req */ &s_ruri, /* Request-URI */ &s_turi, /* To */ &s_turi, /* From */ (ri->auth_proxy.len)?&ri->auth_proxy:NULL /* outbound uri */ ); #endif ret = uac_tmb.t_request_within(&uac_r); if(ret<0) { LM_ERR("failed to send request with authentication for [%.*s]", ri->l_uuid.len, ri->l_uuid.s); goto error; } ri->flags |= UAC_REG_AUTHSENT; return; } else { LM_ERR("got sip response %d while registering [%.*s]\n", ps->code, ri->l_uuid.len, ri->l_uuid.s); goto error; } error: ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT); if(reg_retry_interval) { ri->timer_expires = time(NULL) + reg_retry_interval; } else { ri->flags |= UAC_REG_DISABLED; counter_inc(regdisabled); } done: if(ri) ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT); shm_free(uuid); counter_inc(regactive); }
int uac_auth(sip_msg_t *msg) { static struct authenticate_body auth; struct uac_credential *crd; int code, branch; struct sip_msg *rpl; struct cell *t; struct hdr_field *hdr; HASHHEX response; str *new_hdr; sr_cfgenv_t *cenv = NULL; /* get transaction */ t = uac_tmb.t_gett(); if (t==T_UNDEFINED || t==T_NULL_CELL) { LM_CRIT("no current transaction found\n"); goto error; } /* get the selected branch */ branch = uac_tmb.t_get_picked_branch(); if (branch<0) { LM_CRIT("no picked branch (%d)\n",branch); goto error; } rpl = t->uac[branch].reply; code = t->uac[branch].last_received; LM_DBG("picked reply is %p, code %d\n",rpl,code); if (rpl==0) { LM_CRIT("empty reply on picked branch\n"); goto error; } if (rpl==FAKED_REPLY) { LM_ERR("cannot process a FAKED reply\n"); goto error; } hdr = get_autenticate_hdr( rpl, code); if (hdr==0) { LM_ERR("failed to extract authenticate hdr\n"); goto error; } LM_DBG("header found; body=<%.*s>\n", hdr->body.len, hdr->body.s); if (parse_authenticate_body( &hdr->body, &auth)<0) { LM_ERR("failed to parse auth hdr body\n"); goto error; } /* can we authenticate this realm? */ crd = 0; /* first look into AVP, if set */ if ( auth_realm_spec.type!=PVT_NONE ) crd = get_avp_credential( msg, &auth.realm ); /* if not found, look into predefined credentials */ if (crd==0) crd = lookup_realm( &auth.realm ); /* found? */ if (crd==0) { LM_DBG("no credential for realm \"%.*s\"\n", auth.realm.len, auth.realm.s); goto error; } /* do authentication */ do_uac_auth( &msg->first_line.u.request.method, &t->uac[branch].uri, crd, &auth, response); /* build the authorization header */ new_hdr = build_authorization_hdr( code, &t->uac[branch].uri, crd, &auth, response); if (new_hdr==0) { LM_ERR("failed to build authorization hdr\n"); goto error; } /* so far, so good -> add the header and set the proper RURI */ if ( apply_urihdr_changes( msg, &t->uac[branch].uri, new_hdr)<0 ) { LM_ERR("failed to apply changes\n"); goto error; } /* mark request in T with uac auth for increase of cseq via dialog * - this function is executed in failure route, msg_flags will be * reset afterwards by tm fake env */ if(t->uas.request) { t->uas.request->msg_flags |= FL_UAC_AUTH; cenv = sr_cfgenv_get(); if(cenv->cb_cseq_update != NULL) { if(cenv->cb_cseq_update(msg)<0) { goto error; } } } return 0; error: return -1; }
int uac_auth( struct sip_msg *msg) { static struct authenticate_body auth; struct uac_credential *crd; int picked_code, picked_br, b; struct sip_msg *rpl; struct cell *t; struct hdr_field *hdr; HASHHEX response; str *new_hdr; /* get transaction */ t = uac_tmb.t_gett(); if (t==T_UNDEFINED || t==T_NULL_CELL) { LOG(LOG_CRIT,"BUG:uac:uac_auth: no current transaction found\n"); goto error; } /* pick the selected reply */ picked_br = -1; picked_code = 999; for ( b=t->first_branch; b<t->nr_of_outgoings ; b++ ) { /* skip 'empty branches' */ if (!t->uac[b].request.buffer) continue; /* there is still an unfinished UAC transaction? */ if ( t->uac[b].last_received<200 ) { LOG(L_CRIT,"BUG:uac:uac_auth: incomplet transaction in failure " "route\n"); goto error; } if ( t->uac[b].last_received<picked_code ) { picked_br = b; picked_code = t->uac[b].last_received; } } if (picked_br<0) { LOG(L_CRIT,"BUG:uac:uac_auth: empty transaction in failure " "route\n"); goto error; } rpl = t->uac[picked_br].reply; DBG("DEBUG:uac:uac_auth: picked reply is %p, code %d\n",rpl,picked_code); if (rpl==0) { LOG(L_CRIT,"BUG:uac:uac_auth: empty reply on picked branch\n"); goto error; } if (rpl==FAKED_REPLY) { LOG(L_ERR,"ERROR:uac:uac_auth: cannot process a FAKED reply\n"); goto error; } hdr = get_autenticate_hdr( rpl, picked_code); if (hdr==0) { LOG( L_ERR,"ERROR:uac:uac_auth: failed to extract authenticate hdr\n"); goto error; } DBG("DEBUG:uac:uac_auth: header found; body=<%.*s>\n", hdr->body.len, hdr->body.s); if (parse_authenticate_body( &hdr->body, &auth)<0) { LOG(L_ERR,"ERROR:uac:uac_auth: failed to parse auth hdr body\n"); goto error; } /* can we authenticate this realm? */ crd = lookup_realm( &auth.realm ); if (crd==0) { LOG(L_ERR,"ERROR:uac:uac_auth: no credential for realm \"%.*s\"\n", auth.realm.len, auth.realm.s); goto error; } /* do authentication */ do_uac_auth( msg, &t->uac[picked_br].uri, crd, &auth, response); /* build the authorization header */ new_hdr = build_authorization_hdr( picked_code, &t->uac[picked_br].uri, crd, &auth, response); if (new_hdr==0) { LOG(L_ERR,"ERROR:uac:uac_auth: failed to build authorization hdr\n"); goto error; } /* so far, so good -> add the header and set the proper RURI */ if ( apply_urihdr_changes( msg, &t->uac[picked_br].uri, new_hdr)<0 ) { LOG(L_ERR,"ERROR:uac:uac_auth: failed to apply changes\n"); goto error; } /* increas the Cseq nr */ return 0; error: return -1; }
/** * TM callback function */ void uac_send_tm_callback(struct cell *t, int type, struct tmcb_params *ps) { int ret; struct hdr_field *hdr; HASHHEX response; str *new_auth_hdr = NULL; static struct authenticate_body auth; struct uac_credential cred; char b_hdrs[MAX_UACH_SIZE]; str s_hdrs; uac_req_t uac_r; dlg_t tmdlg; uac_send_info_t *tp = NULL; LM_DBG("tm callback with status %d\n", ps->code); if(ps->param==NULL || *ps->param==0) { LM_DBG("callback param with message id not received\n"); goto done; } tp = (uac_send_info_t*)(*ps->param); if(tp->evroute!=0) { uac_req_run_event_route((ps->rpl==FAKED_REPLY)?NULL:ps->rpl, tp, ps->code); } if((ps->code != 401 && ps->code != 407) || tp->s_apasswd.len<=0) { LM_DBG("completed with status %d\n", ps->code); goto done; } LM_DBG("completed with status %d\n", ps->code); hdr = get_autenticate_hdr(ps->rpl, ps->code); if (hdr==0) { LM_ERR("failed to extract authenticate hdr\n"); goto error; } LM_DBG("auth header body [%.*s]\n", hdr->body.len, hdr->body.s); if (parse_authenticate_body(&hdr->body, &auth)<0) { LM_ERR("failed to parse auth hdr body\n"); goto error; } cred.realm = auth.realm; cred.user = tp->s_auser; cred.passwd = tp->s_apasswd; cred.next = NULL; do_uac_auth(&tp->s_method, &tp->s_ruri, &cred, &auth, response); new_auth_hdr=build_authorization_hdr(ps->code, &tp->s_ruri, &cred, &auth, response); if (new_auth_hdr==0) { LM_ERR("failed to build authorization hdr\n"); goto error; } if(tp->s_hdrs.len <= 0) { snprintf(b_hdrs, MAX_UACH_SIZE, "%.*s", new_auth_hdr->len, new_auth_hdr->s); } else { snprintf(b_hdrs, MAX_UACH_SIZE, "%.*s%.*s", tp->s_hdrs.len, tp->s_hdrs.s, new_auth_hdr->len, new_auth_hdr->s); } s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s); pkg_free(new_auth_hdr->s); memset(&uac_r, 0, sizeof(uac_r)); if(uac_send_tmdlg(&tmdlg, ps->rpl)<0) { LM_ERR("failed to build tm dialog\n"); goto error; } tmdlg.rem_target = tp->s_ruri; if(tp->s_ouri.len>0) tmdlg.dst_uri = tp->s_ouri; uac_r.method = &tp->s_method; uac_r.headers = &s_hdrs; uac_r.body = (tp->s_body.len <= 0) ? NULL : &tp->s_body; uac_r.ssock = (tp->s_sock.len <= 0) ? NULL : &tp->s_sock; uac_r.dialog = &tmdlg; uac_r.cb_flags = TMCB_LOCAL_COMPLETED; ret = tmb.t_request_within(&uac_r); if(ret<0) { LM_ERR("failed to send request with authentication\n"); goto error; } done: error: if(tp!=NULL) shm_free(tp); return; }