int w_has_credentials(sip_msg_t *msg, char* realm, char* s2) { str srealm = {0, 0}; hdr_field_t *hdr = NULL; int ret; if (fixup_get_svalue(msg, (gparam_t*)realm, &srealm) < 0) { LM_ERR("failed to get realm value\n"); return -1; } ret = find_credentials(msg, &srealm, HDR_PROXYAUTH_T, &hdr); if(ret==0) { LM_DBG("found www credentials with realm [%.*s]\n", srealm.len, srealm.s); return 1; } ret = find_credentials(msg, &srealm, HDR_AUTHORIZATION_T, &hdr); if(ret==0) { LM_DBG("found proxy credentials with realm [%.*s]\n", srealm.len, srealm.s); return 1; } LM_DBG("no credentials with realm [%.*s]\n", srealm.len, srealm.s); return -1; }
/** * Returns the Private Identity extracted from the Authorization header. * If none found there takes the SIP URI in To without the "sip:" prefix * \todo - remove the fallback case to the To header * @param msg - the SIP message * @param realm - the realm to match in an Authorization header * @returns the str containing the private id, no mem dup */ str cscf_get_private_identity(struct sip_msg *msg, str realm) { str pi = {0, 0}; struct hdr_field* h = 0; int ret, i, res; if ((parse_headers(msg, HDR_AUTHORIZATION_F, 0) != 0) && (parse_headers(msg, HDR_PROXYAUTH_F, 0) != 0)) { return pi; } h = msg->authorization; if (!msg->authorization) { goto fallback; } if (realm.len && realm.s) { ret = find_credentials(msg, &realm, HDR_AUTHORIZATION_F, &h); if (ret < 0) { ret = find_credentials(msg, &realm, HDR_PROXYAUTH_F, &h); if (ret < 0) { goto fallback; } else { if (ret >0) { goto fallback; } h = msg->proxy_auth; } } else { if (ret > 0) { goto fallback; } } } if (!h) goto fallback; res = parse_credentials(h); if (res != 0) { LOG(L_ERR, "Error while parsing credentials\n"); return pi; } if (h) pi = ((auth_body_t*) h->parsed)->digest.username.whole; goto done; fallback: pi = cscf_get_public_identity(msg); if (pi.len > 4 && strncasecmp(pi.s, "sip:", 4) == 0) { pi.s += 4; pi.len -= 4; } for (i = 0; i < pi.len; i++) if (pi.s[i] == ';') { pi.len = i; break; } done: return pi; }
/** * Looks for the nonce parameter in the Authorization header and returns its value. * @param msg - the SIP message * @param realm - realm to match the right Authorization header * @returns the nonce or an empty string if none found */ str ims_get_nonce(struct sip_msg *msg, str realm) { struct hdr_field* h=0; int ret; str nonce={0,0}; if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) { LM_ERR("Error parsing until header Authorization: \n"); return nonce; } if (!msg->authorization){ LM_ERR("Message does not contain Authorization header.\n"); return nonce; } ret = find_credentials(msg, &realm, HDR_AUTHORIZATION_F, &h); if (ret < 0) { LM_ERR("Error while looking for credentials.\n"); return nonce; } else if (ret > 0) { LM_ERR("No credentials for this realm found.\n"); return nonce; } if (h&&h->parsed) { nonce = ((auth_body_t*)h->parsed)->digest.nonce; } return nonce; }
/* * Purpose of this function is to find credentials with given realm, * do sanity check, validate credential correctness and determine if * we should really authenticate (there must be no authentication for * ACK and CANCEL * @param hdr output param where the Authorize headerfield will be returned. * @param check_hdr pointer to the function checking Authorization header field */ auth_result_t pre_auth(struct sip_msg* msg, str* realm, hdr_types_t hftype, struct hdr_field** hdr, check_auth_hdr_t check_auth_hdr) { int ret; auth_body_t* c; check_auth_hdr_t check_hf; auth_result_t auth_rv; /* ACK and CANCEL must be always authenticated, there is * no way how to challenge ACK and CANCEL cannot be * challenged because it must have the same CSeq as * the request to be canceled. * PRACK is also not authenticated */ if (msg->REQ_METHOD & (METHOD_ACK|METHOD_CANCEL|METHOD_PRACK)) return AUTHENTICATED; /* Try to find credentials with corresponding realm * in the message, parse them and return pointer to * parsed structure */ strip_realm(realm); ret = find_credentials(msg, realm, hftype, hdr); if (ret < 0) { LOG(L_ERR, "auth:pre_auth: Error while looking for credentials\n"); return ERROR; } else if (ret > 0) { DBG("auth:pre_auth: Credentials with realm '%.*s' not found\n", realm->len, ZSW(realm->s)); return NO_CREDENTIALS; } /* Pointer to the parsed credentials */ c = (auth_body_t*)((*hdr)->parsed); /* digest headers are in c->digest */ DBG("auth: digest-algo: %.*s parsed value: %d\n", c->digest.alg.alg_str.len, c->digest.alg.alg_str.s, c->digest.alg.alg_parsed); if (mark_authorized_cred(msg, *hdr) < 0) { LOG(L_ERR, "auth:pre_auth: Error while marking parsed credentials\n"); return ERROR; } /* check authorization header field's validity */ if (check_auth_hdr == NULL) { check_hf = auth_check_hdr_md5; } else { /* use check function of external authentication module */ check_hf = check_auth_hdr; } /* use the right function */ if (!check_hf(msg, c, &auth_rv)) { return auth_rv; } return DO_AUTHENTICATION; }
int get_credentials(struct sip_msg* msg, select_t* s, struct hdr_field** hdr) { int ret; str realm; hdr_types_t hdr_type; *hdr = NULL; if (!msg) { /* fix-up call check domain for fparam conversion */ void * ptr; char chr; ptr=(void *)(s->params[1].v.s.s); chr=s->params[1].v.s.s[s->params[1].v.s.len]; s->params[1].v.s.s[s->params[1].v.s.len]=0; ret=fixup_var_str_12(&ptr,0); if (ret>=0) { s->params[1].v.s.s[s->params[1].v.s.len]=chr; s->params[1].v.p=ptr; s->params[1].type=SEL_PARAM_PTR; } return ret; } /* Try to find credentials with corresponding realm * in the message, parse them and return pointer to * parsed structure */ if (s->params[1].type==SEL_PARAM_PTR) { if (get_str_fparam(&realm, msg, s->params[1].v.p)<0) return -1; } else { realm = s->params[1].v.s; } switch (s->params[0].v.i) { case SEL_AUTH_WWW: hdr_type = HDR_AUTHORIZATION_T; break; case SEL_AUTH_PROXY: hdr_type = HDR_PROXYAUTH_T; break; default: BUG("Unexpected parameter value \"%d\"\n", s->params[0].v.i); return -1; } ret = find_credentials(msg, &realm, hdr_type, hdr); return ret; }
auth_diam_result_t diam_pre_auth(struct sip_msg* _m, str* _realm, int _hftype, struct hdr_field** _h) { int ret; struct sip_uri uri; str realm; if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) return AUTHORIZED; /* if no realm supplied, find out now */ if (_realm==0 || _realm->len == 0) { if (get_realm(_m, _hftype, &uri) < 0) { LM_ERR("failed to extract realm\n"); if (send_resp(_m, 400, &dia_400_err, 0, 0) == -1) { LM_ERR("failed to send 400 reply\n"); } return ERROR; } realm = uri.host; } else { realm = *_realm; } ret = find_credentials(_m, &realm, _hftype, _h); if (ret < 0) { LM_ERR("credentials not found\n"); if (send_resp(_m, (ret == -2) ? 500 : 400, (ret == -2) ? &dia_500_err : &dia_400_err, 0, 0) == -1) { LM_ERR("failed to send 400 reply\n"); } return ERROR; } else if (ret > 0) { LM_ERR("credentials with given realm not found\n"); return NO_CREDENTIALS; } return DO_AUTHORIZATION; }
auth_result_t pre_auth(struct sip_msg* _m, str* _realm, int _hftype, struct hdr_field** _h) { int ret; struct sip_uri uri; if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) return AUTHORIZED; /* if no realm supplied, find out now */ if (_realm==0 || _realm->len == 0) { if (get_realm(_m, _hftype, &uri) < 0) { LOG(L_ERR, M_NAME":pre_auth(): Error while extracting realm\n"); if (send_resp(_m, 400, MESSAGE_400, 0, 0) == -1) { LOG(L_ERR, M_NAME":pre_auth(): Error while sending 400 reply\n"); } return ERROR; } *_realm = uri.host; } ret = find_credentials(_m, _realm, _hftype, _h); if (ret < 0) { LOG(L_ERR, M_NAME":pre_auth(): Error while looking for credentials\n"); if (send_resp(_m, (ret == -2) ? 500 : 400, (ret == -2) ? MESSAGE_500 : MESSAGE_400, 0, 0) == -1) { LOG(L_ERR, M_NAME":pre_auth(): Error while sending 400 reply\n"); } return ERROR; } else if (ret > 0) { LOG(L_ERR, M_NAME":pre_auth(): Credentials with given realm not " "found\n"); return NO_CREDENTIALS; } return DO_AUTHORIZATION; }
/** * Looks for the auts parameter in the Authorization header and returns its value. * @param msg - the SIP message * @param realm - realm to match the right Authorization header * @returns the auts value or an empty string if not found */ str ims_get_auts(struct sip_msg *msg, str realm, int is_proxy_auth) { str name={"auts=\"",6}; struct hdr_field* h=0; int i,ret; str auts={0,0}; if (parse_headers(msg, is_proxy_auth ? HDR_PROXYAUTH_F : HDR_AUTHORIZATION_F,0)!=0) { LM_ERR("Error parsing until header Authorization: \n"); return auts; } if ((!is_proxy_auth && !msg->authorization) || (is_proxy_auth && !msg->proxy_auth)){ LM_ERR("Message does not contain Authorization nor Proxy-Authorization header.\n"); return auts; } ret = find_credentials(msg, &realm, is_proxy_auth ? HDR_PROXYAUTH_F : HDR_AUTHORIZATION_F, &h); if (ret < 0) { LM_ERR("Error while looking for credentials.\n"); return auts; } else if (ret > 0) { LM_ERR("No credentials for this realm found.\n"); return auts; } if (h) { for(i=0;i<h->body.len-name.len;i++) if (strncasecmp(h->body.s+i,name.s,name.len)==0){ auts.s = h->body.s+i+name.len; while(i+auts.len<h->body.len && auts.s[auts.len]!='\"') auts.len++; } } return auts; }
/** * Returns the Private Identity extracted from the Authorization header. * If none found there takes the SIP URI in To without the "sip:" prefix * \todo - remove the fallback case to the To header * @param msg - the SIP message * @param realm - the realm to match in an Authorization header * @param is_proxy_auth 0 if the header is Authorization, anything else for Proxy-Authorization * @returns the str containing the private id, no mem dup */ str get_private_identity(struct sip_msg *msg, str realm, int is_proxy_auth) { str pi={0,0}; struct hdr_field* h=0; int ret,i; if (parse_headers(msg, is_proxy_auth ? HDR_PROXYAUTH_F : HDR_AUTHORIZATION_F,0)!=0) { return pi; } if (!(is_proxy_auth ? msg->proxy_auth : msg->authorization)){ goto fallback; } ret = find_credentials(msg, &realm, is_proxy_auth ? HDR_PROXYAUTH_F : HDR_AUTHORIZATION_F, &h); if (ret < 0) { goto fallback; } else if (ret > 0) { goto fallback; } if (h) pi=((auth_body_t*)h->parsed)->digest.username.whole; goto done; fallback: pi = get_public_identity(msg); if (pi.len>4&&strncasecmp(pi.s,"sip:",4)==0) {pi.s+=4;pi.len-=4;} for(i=0;i<pi.len;i++) if (pi.s[i]==';') { pi.len=i; break; } done: return pi; }
static struct hdr_field* get_credentials(struct sip_msg* msg, select_t* s) { int ret; struct hdr_field* hdr; str realm; hdr_types_t hdr_type; /* Try to find credentials with corresponding realm * in the message, parse them and return pointer to * parsed structure */ realm = s->params[1].v.s; switch (s->params[0].v.i) { case SEL_AUTH_WWW: hdr_type = HDR_AUTHORIZATION_T; break; case SEL_AUTH_PROXY: hdr_type = HDR_PROXYAUTH_T; break; default: BUG("Unexpected parameter value \"%d\"\n", s->params[0].v.i); return 0; } ret = find_credentials(msg, &realm, hdr_type, &hdr); if (ret < 0) { ERR("Error while looking for credentials\n"); return 0; } else if (ret > 0) { return 0; } return hdr; }
/* * Purpose of this function is to find credentials with given realm, * do sanity check, validate credential correctness and determine if * we should really authenticate (there must be no authentication for * ACK and CANCEL */ auth_result_t pre_auth(struct sip_msg* _m, str* _realm, int _hftype, struct hdr_field** _h) { int ret; auth_body_t* c; struct sip_uri uri; /* ACK and CANCEL must be always authorized, there is * no way how to challenge ACK and CANCEL cannot be * challenged because it must have the same CSeq as * the request to be cancelled */ if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) return AUTHORIZED; if (_realm->len == 0) { if (get_realm(_m, _hftype, &uri) < 0) { LOG(L_ERR, "pre_auth(): Error while extracting realm\n"); if (send_resp(_m, 400, MESSAGE_400, 0, 0) == -1) { LOG(L_ERR, "pre_auth(): Error while sending 400 reply\n"); } return ERROR; } *_realm = uri.host; strip_realm(_realm); } /* Try to find credentials with corresponding realm * in the message, parse them and return pointer to * parsed structure */ ret = find_credentials(_m, _realm, _hftype, _h); if (ret < 0) { LOG(L_ERR, "pre_auth(): Error while looking for credentials\n"); if (send_resp(_m, (ret == -2) ? 500 : 400, (ret == -2) ? MESSAGE_500 : MESSAGE_400, 0, 0) == -1) { LOG(L_ERR, "pre_auth(): Error while sending 400 reply\n"); } return ERROR; } else if (ret > 0) { DBG("pre_auth(): Credentials with given realm not found\n"); return NOT_AUTHORIZED; } /* Pointer to the parsed credentials */ c = (auth_body_t*)((*_h)->parsed); /* Check credentials correctness here */ if (check_dig_cred(&(c->digest)) != E_DIG_OK) { LOG(L_ERR, "pre_auth(): Credentials received are not filled properly\n"); if (send_resp(_m, 400, MESSAGE_400, 0, 0) == -1) { LOG(L_ERR, "pre_auth(): Error while sending 400 reply\n"); } return ERROR; } if (check_nonce(&c->digest.nonce, &secret) != 0) { DBG("pre_auth(): Invalid nonce value received\n"); return NOT_AUTHORIZED; } return DO_AUTHORIZATION; }
/* * Purpose of this function is to find credentials with given realm, * do sanity check, validate credential correctness and determine if * we should really authenticate (there must be no authentication for * ACK and CANCEL */ auth_result_t pre_auth(struct sip_msg* _m, str* _realm, hdr_types_t _hftype, struct hdr_field** _h) { int ret; auth_body_t* c; struct sip_uri *uri; /* ACK and CANCEL must be always authorized, there is * no way how to challenge ACK and CANCEL cannot be * challenged because it must have the same CSeq as * the request to be canceled */ if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) return AUTHORIZED; if (_realm->len == 0) { if (get_realm(_m, _hftype, &uri) < 0) { LM_ERR("failed to extract realm\n"); if (send_resp(_m, 400, &auth_400_err, 0, 0) == -1) { LM_ERR("failed to send 400 reply\n"); } return ERROR; } *_realm = uri->host; strip_realm(_realm); } /* Try to find credentials with corresponding realm * in the message, parse them and return pointer to * parsed structure */ ret = find_credentials(_m, _realm, _hftype, _h); if (ret < 0) { LM_ERR("failed to find credentials\n"); if (send_resp(_m, (ret == -2) ? 500 : 400, (ret == -2) ? &auth_500_err : &auth_400_err, 0, 0) == -1) { LM_ERR("failed to send 400 reply\n"); } return ERROR; } else if (ret > 0) { LM_DBG("credentials with given realm not found\n"); return NO_CREDENTIALS; } /* Pointer to the parsed credentials */ c = (auth_body_t*)((*_h)->parsed); /* Check credentials correctness here */ if (check_dig_cred(&(c->digest)) != E_DIG_OK) { LM_DBG("received credentials are not filled properly\n"); if (send_resp(_m, 400, &auth_400_err, 0, 0) == -1) { LM_ERR("failed to send 400 reply\n"); } return ERROR; } if (mark_authorized_cred(_m, *_h) < 0) { LM_ERR("failed to mark parsed credentials\n"); if (send_resp(_m, 500, &auth_400_err, 0, 0) == -1) { LM_ERR("failed to send 400 reply\n"); } return ERROR; } if (is_nonce_stale(&c->digest.nonce)) { LM_DBG("stale nonce value received\n"); c->stale = 1; return STALE_NONCE; } if (check_nonce(&c->digest.nonce, &secret) != 0) { LM_DBG("invalid nonce value received\n"); c->stale = 1; return STALE_NONCE; } return DO_AUTHORIZATION; }