int uac_auth( struct sip_msg *msg) { struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; struct uac_credential *crd; int code, branch; unsigned int new_cseq; struct sip_msg *rpl; struct cell *t; HASHHEX response; str *new_hdr; str param; char *p; struct dlg_cell *dlg; /* 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(); 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; } if (code==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(rpl)) auth = get_www_authenticate(rpl); } else if (code==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(rpl)) auth = get_proxy_authenticate(rpl); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto error; } /* can we authenticate this realm? */ /* look into existing credentials */ crd = uac_auth_api._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 */ uac_auth_api._do_uac_auth( &msg->first_line.u.request.method, &t->uac[branch].uri, crd, auth, &auth_nc_cnonce, response); /* build the authorization header */ new_hdr = uac_auth_api._build_authorization_hdr( code, &t->uac[branch].uri, crd, auth, &auth_nc_cnonce, 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"); pkg_free(new_hdr->s); new_hdr->s = NULL; new_hdr->len = 0; goto error; } if ( (new_cseq = apply_cseq_op(msg,1)) < 0) { LM_WARN("Failure to increment the CSEQ header - continue \n"); goto error; } /* only register the TMCB once per transaction */ if (!(msg->msg_flags & FL_USE_UAC_CSEQ || t->uas.request->msg_flags & FL_USE_UAC_CSEQ)) { if (uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_FWDED, apply_cseq_decrement,0,0)!=1) { LM_ERR("Failed to register TMCB response fwded - continue \n"); goto error; } } if (dlg_api.get_dlg && (dlg = dlg_api.get_dlg())) { /* dlg->legs[dlg->legs_no[DLG_LEGS_USED]-1].last_gen_cseq = new_cseq; */ dlg->flags |= DLG_FLAG_CSEQ_ENFORCE; } else { param.len=rr_uac_cseq_param.len+3; param.s=pkg_malloc(param.len); if (!param.s) { LM_ERR("No more pkg mem \n"); goto error; } p = param.s; *p++=';'; memcpy(p,rr_uac_cseq_param.s,rr_uac_cseq_param.len); p+=rr_uac_cseq_param.len; *p++='='; *p++='1'; if (uac_rrb.add_rr_param( msg, ¶m)!=0) { LM_ERR("add_RR_param failed\n"); pkg_free(param.s); goto error; } pkg_free(param.s); } msg->msg_flags |= FL_USE_UAC_CSEQ; t->uas.request->msg_flags |= FL_USE_UAC_CSEQ; return 0; error: return -1; }
int run_reg_tm_cback(void *e_data, void *data, void *r_data) { struct sip_msg *msg; int statuscode = 0; unsigned int exp = 0; reg_record_t *rec = (reg_record_t*)e_data; struct hdr_field *c_ptr, *head_contact; struct uac_credential crd; contact_t *contact; struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; HASHHEX response; str *new_hdr; struct reg_tm_cback_data *tm_cback_data = (struct reg_tm_cback_data*)data; struct cell *t; struct tmcb_params *ps; time_t now; reg_tm_cb_t *cb_param; cb_param = tm_cback_data->cb_param; if (rec!=cb_param->uac) { /* no action on current list elemnt */ return 0; /* continue list traversal */ } t = tm_cback_data->t; ps = tm_cback_data->ps; now = tm_cback_data->now; reg_print_record(rec); if (ps->rpl==FAKED_REPLY) memset(&rec->td.forced_to_su, 0, sizeof(union sockaddr_union)); else if (rec->td.forced_to_su.s.sa_family == AF_UNSPEC) rec->td.forced_to_su = t->uac[0].request.dst.to; statuscode = ps->code; switch(statuscode) { case 200: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto done; } if (msg->contact) { c_ptr = msg->contact; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) { LM_ERR("failed to parse Contact body\n"); goto done; } } c_ptr = c_ptr->next; } } else { LM_ERR("No contact header in received 200ok\n"); goto done; } head_contact = msg->contact; contact = ((contact_body_t*)msg->contact->parsed)->contacts; while (contact) { /* Check for binding */ if (contact->uri.len==rec->contact_uri.len && strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){ if (contact->expires && contact->expires->body.len) { if (str2int(&contact->expires->body, &exp)<0) { LM_ERR("Unable to extract expires from [%.*s]" " for binding [%.*s]\n", contact->expires->body.len, contact->expires->body.s, contact->uri.len, contact->uri.s); } } break; } /* get the next contact */ if (contact->next == NULL) { contact = NULL; c_ptr = head_contact->next; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { head_contact = c_ptr; contact = ((contact_body_t*)c_ptr->parsed)->contacts; break; } c_ptr = c_ptr->next; } } else { contact = contact->next; } } rec->state = REGISTERED_STATE; if (exp) rec->expires = exp; rec->registration_timeout = now + rec->expires - timer_interval; break; case WWW_AUTH_CODE: case PROXY_AUTH_CODE: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (rec->auth_user.s==NULL || rec->auth_user.len==0 || rec->auth_password.s==NULL || rec->auth_password.len==0) { LM_ERR("Credentials not provisioned\n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; /* action successfuly completed on current list element */ return 1; /* exit list traversal */ } if (statuscode==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(msg)) auth = get_www_authenticate(msg); } else if (statuscode==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(msg)) auth = get_proxy_authenticate(msg); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto done; } LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]" " opaque=[%.*s] qop=[%.*s]\n", auth->flags, auth->realm.len, auth->realm.s, auth->domain.len, auth->domain.s, auth->nonce.len, auth->nonce.s, auth->opaque.len, auth->opaque.s, auth->qop.len, auth->qop.s); switch(rec->state) { case REGISTERING_STATE: break; case AUTHENTICATING_STATE: /* We already sent an authenticated REGISTER and we are still challanged! */ LM_WARN("Wrong credentials for [%.*s]\n", rec->td.rem_uri.len, rec->td.rem_uri.s); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; /* action successfuly completed on current list element */ return 1; /* exit list traversal */ default: LM_ERR("Unexpected [%d] notification cb in state [%d]\n", statuscode, rec->state); goto done; } /* perform authentication */ if (auth->realm.s && auth->realm.len) { crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len; } else { LM_ERR("No realm found\n"); goto done; } crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len; crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len; memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce)); uac_auth_api._do_uac_auth(®ister_method, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); if (!new_hdr) { LM_ERR("failed to build authorization hdr\n"); goto done; } if(send_register(cb_param->hash_index, rec, new_hdr)==1) { rec->state = AUTHENTICATING_STATE; } else { rec->state = INTERNAL_ERROR_STATE; } pkg_free(new_hdr->s); new_hdr->s = NULL; new_hdr->len = 0; break; case 423: /* Interval Too Brief */ msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (0 == parse_min_expires(msg)) { rec->expires = (unsigned int)(long)msg->min_expires->parsed; if(send_register(cb_param->hash_index, rec, NULL)==1) rec->state = REGISTERING_STATE; else rec->state = INTERNAL_ERROR_STATE; } else { rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } break; case 408: /* Interval Too Brief */ rec->state = REGISTER_TIMEOUT_STATE; rec->registration_timeout = now + rec->expires - timer_interval; break; default: if(statuscode<400 && statuscode>=300) { LM_ERR("Redirection not implemented yet\n"); rec->state = INTERNAL_ERROR_STATE; } else { /* we got an error from the server */ rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } } /* action successfuly completed on current list element */ return 1; /* exit list traversal */ done: rec->state = INTERNAL_ERROR_STATE; rec->registration_timeout = now + rec->expires; return -1; /* exit list traversal */ }
void reg_tm_cback(struct cell *t, int type, struct tmcb_params *ps) { struct sip_msg *msg; reg_tm_cb_t *cb_param; int statuscode = 0; unsigned int exp = 0; reg_record_t *rec; struct hdr_field *c_ptr, *head_contact; struct uac_credential crd; contact_t *contact; struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; HASHHEX response; str *new_hdr; time_t now; if(ps==NULL || ps->rpl==NULL) { LM_ERR("wrong ps parameter\n"); return; } if(ps->param==NULL || *ps->param==NULL) { LM_ERR("null callback parameter\n"); return; } cb_param = (reg_tm_cb_t *)*ps->param; if(cb_param->uac == NULL) { LM_ERR("null record\n"); return; } statuscode = ps->code; now = time(0); LM_DBG("tm [%p] notification cb for %s [%d] reply at [%d]\n", t, (ps->rpl==FAKED_REPLY)?"FAKED_REPLY":"", statuscode, (unsigned int)now); if(statuscode<200) return; lock_get(®_htable[cb_param->hash_index].lock); rec = reg_htable[cb_param->hash_index].first; while(rec) { if (rec==cb_param->uac) { break; } rec = rec->next; } if(!rec) { LM_ERR("record [%p] not found on hash index [%d]\n", cb_param->uac, cb_param->hash_index); lock_release(®_htable[cb_param->hash_index].lock); return; } reg_print_record(rec); switch(statuscode) { case 200: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto done; } if (msg->contact) { c_ptr = msg->contact; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) { LM_ERR("failed to parse Contact body\n"); goto done; } } c_ptr = c_ptr->next; } } else { LM_ERR("No contact header in received 200ok\n"); goto done; } head_contact = msg->contact; contact = ((contact_body_t*)msg->contact->parsed)->contacts; while (contact) { /* Check for binding */ if (contact->uri.len==rec->contact_uri.len && strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){ if (contact->expires && contact->expires->body.len) { if (str2int(&contact->expires->body, &exp)<0) { LM_ERR("Unable to extract expires from [%.*s]" " for binding [%.*s]\n", contact->expires->body.len, contact->expires->body.s, contact->uri.len, contact->uri.s); } else { rec->expires = exp; } } break; } /* get the next contact */ if (contact->next == NULL) { contact = NULL; c_ptr = head_contact->next; while(c_ptr) { if (c_ptr->type == HDR_CONTACT_T) { head_contact = c_ptr; contact = ((contact_body_t*)c_ptr->parsed)->contacts; break; } c_ptr = c_ptr->next; } } else { contact = contact->next; } } rec->state = REGISTERED_STATE; rec->registration_timeout = now + rec->expires - timer_interval; break; case WWW_AUTH_CODE: case PROXY_AUTH_CODE: msg = ps->rpl; if(msg==FAKED_REPLY) { LM_ERR("FAKED_REPLY\n"); goto done; } if (rec->auth_user.s==NULL || rec->auth_user.len==0 || rec->auth_password.s==NULL || rec->auth_password.len==0) { LM_ERR("Credentials not provisioned\n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; lock_release(®_htable[cb_param->hash_index].lock); return; } if (statuscode==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(msg)) auth = get_www_authenticate(msg); } else if (statuscode==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(msg)) auth = get_proxy_authenticate(msg); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto done; } LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]" " opaque=[%.*s] qop=[%.*s]\n", auth->flags, auth->realm.len, auth->realm.s, auth->domain.len, auth->domain.s, auth->nonce.len, auth->nonce.s, auth->opaque.len, auth->opaque.s, auth->qop.len, auth->qop.s); switch(rec->state) { case REGISTERING_STATE: break; case AUTHENTICATING_STATE: /* We already sent an authenticated REGISTER and we are still challanged! */ LM_ERR("Wrong credentials for \n"); rec->state = WRONG_CREDENTIALS_STATE; rec->registration_timeout = 0; lock_release(®_htable[cb_param->hash_index].lock); return; default: LM_ERR("Unexpected [%d] notification cb in state [%d]\n", statuscode, rec->state); goto done; } /* perform authentication */ if (auth->realm.s && auth->realm.len) { crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len; } else { LM_ERR("No realm found\n"); goto done; } crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len; crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len; memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce)); uac_auth_api._do_uac_auth(®ister_method, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target, &crd, auth, &auth_nc_cnonce, response); if (!new_hdr) { LM_ERR("failed to build authorization hdr\n"); goto done; } if(send_register(cb_param->hash_index, rec, new_hdr)==1) { rec->state = AUTHENTICATING_STATE; } else { rec->state = INTERNAL_ERROR_STATE; } break; default: if(statuscode<400 && statuscode>=300) { LM_ERR("Redirection not implemented yet\n"); rec->state = INTERNAL_ERROR_STATE; } else { /* we got an error from the server */ rec->state = REGISTRAR_ERROR_STATE; rec->registration_timeout = now + rec->expires - timer_interval; } } lock_release(®_htable[cb_param->hash_index].lock); return; done: rec->state = INTERNAL_ERROR_STATE; rec->registration_timeout = now + rec->expires; lock_release(®_htable[cb_param->hash_index].lock); return; }
int uac_auth( struct sip_msg *msg) { struct authenticate_body *auth = NULL; static struct authenticate_nc_cnonce auth_nc_cnonce; struct uac_credential *crd; int code, branch; struct sip_msg *rpl; struct cell *t; HASHHEX response; str *new_hdr; /* 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(); 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; } if (code==WWW_AUTH_CODE) { if (0 == parse_www_authenticate_header(rpl)) auth = get_www_authenticate(rpl); } else if (code==PROXY_AUTH_CODE) { if (0 == parse_proxy_authenticate_header(rpl)) auth = get_proxy_authenticate(rpl); } if (auth == NULL) { LM_ERR("Unable to extract authentication info\n"); goto error; } /* can we authenticate this realm? */ crd = 0; /* first look into AVP, if set */ if ( auth_realm_spec.type==PVT_AVP ) crd = get_avp_credential( msg, &auth->realm ); /* if not found, look into predefined credentials */ if (crd==0) crd = uac_auth_api._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 */ uac_auth_api._do_uac_auth( &msg->first_line.u.request.method, &t->uac[branch].uri, crd, auth, &auth_nc_cnonce, response); /* build the authorization header */ new_hdr = uac_auth_api._build_authorization_hdr( code, &t->uac[branch].uri, crd, auth, &auth_nc_cnonce, 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; } /* increas the Cseq nr */ return 0; error: return -1; }