/* * Purpose of this function is to do post authentication steps like * marking authorized credentials and so on. */ auth_result_t post_auth(struct sip_msg* _m, struct hdr_field* _h, str* _rpid) { int res = AUTHORIZED; auth_body_t* c; c = (auth_body_t*)((_h)->parsed); if (is_nonce_stale(&c->digest.nonce)) { if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) { /* Method is ACK or CANCEL, we must accept stale * nonces because there is no way how to challenge * with new nonce (ACK has no response associated * and CANCEL must have the same CSeq as the request * to be cancelled) */ } else { DBG("post_auth(): Response is OK, but nonce is stale\n"); c->stale = 1; res = NOT_AUTHORIZED; } } if (mark_authorized_cred(_m, _h) < 0) { LOG(L_ERR, "post_auth(): Error while marking parsed credentials\n"); if (send_resp(_m, 500, MESSAGE_500, 0, 0) == -1) { LOG(L_ERR, "post_auth(): Error while sending 500 reply\n"); } res = ERROR; } save_rpid(_rpid); return res; }
/* * 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; }
/* * Purpose of this function is to do post authentication steps like * marking authorized credentials and so on. */ auth_result_t post_auth(struct sip_msg* _m, struct hdr_field* _h) { int res = AUTHORIZED; auth_body_t* c; c = (auth_body_t*)((_h)->parsed); if (is_nonce_stale(&c->digest.nonce)) { if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) { /* Method is ACK or CANCEL, we must accept stale * nonces because there is no way how to challenge * with new nonce (ACK has no response associated * and CANCEL must have the same CSeq as the request * to be canceled) */ } else { LM_DBG("response is OK, but nonce is stale\n"); c->stale = 1; res = STALE_NONCE; } } 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 500 reply\n"); } res = ERROR; } return res; }
/* Authorize digest credentials */ int authorize(struct sip_msg* msg, str* realm, int hftype) { auth_result_t ret; struct hdr_field* h; auth_body_t* cred = NULL; str* uri; struct sip_uri puri; str domain; domain = *realm; /* see what is to do after a first look at the message */ ret = pre_auth(msg, &domain, hftype, &h); switch(ret) { case ERROR: return 0; case AUTHORIZED: return 1; case NO_CREDENTIALS: cred = NULL; break; case DO_AUTHORIZATION: cred = (auth_body_t*)h->parsed; break; } if (get_uri(msg, &uri) < 0) { LOG(L_ERR, M_NAME":authorize(): From/To URI not found\n"); return -1; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, M_NAME":authorize(): Error while parsing From/To URI\n"); return -1; } // user.s = (char *)pkg_malloc(puri.user.len); // un_escape(&(puri.user), &user); /* parse the ruri, if not yet */ if(msg->parsed_uri_ok==0 && parse_sip_msg_uri(msg)<0) { LOG(L_ERR,M_NAME":authorize(): ERROR while parsing the Request-URI\n"); return -1; } /* preliminary check */ if(cred) { if (puri.host.len != cred->digest.realm.len) { DBG(M_NAME":authorize(): Credentials realm and URI host do not " "match\n"); return -1; } if (strncasecmp(puri.host.s, cred->digest.realm.s, puri.host.len) != 0) { DBG(M_NAME":authorize(): Credentials realm and URI host do not " "match\n"); return -1; } } if( diameter_authorize(cred?h:NULL, &msg->first_line.u.request.method, puri, msg->parsed_uri, msg->id, rb) != 1) { send_resp(msg, 500, "Internal Server Error", NULL, 0); return -1; } if( srv_response(msg, rb, hftype) != 1 ) return -1; mark_authorized_cred(msg, h); return 1; }
/* Authorize digest credentials */ int authorize(struct sip_msg* msg, pv_elem_t* realm, int hftype) { auth_result_t ret; struct hdr_field* h; auth_body_t* cred = NULL; str* uri; struct sip_uri puri; str domain; if (realm) { if (pv_printf_s(msg, realm, &domain)!=0) { LM_ERR("pv_printf_s failed\n"); return AUTH_ERROR; } } else { domain.len = 0; domain.s = 0; } /* see what is to do after a first look at the message */ ret = diam_pre_auth(msg, &domain, hftype, &h); switch(ret) { case NO_CREDENTIALS: cred = NULL; break; case DO_AUTHORIZATION: cred = (auth_body_t*)h->parsed; break; default: return ret; } if (get_uri(msg, &uri) < 0) { LM_ERR("From/To URI not found\n"); return AUTH_ERROR; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_ERR("failed to parse From/To URI\n"); return AUTH_ERROR; } // user.s = (char *)pkg_malloc(puri.user.len); // un_escape(&(puri.user), &user); /* parse the ruri, if not yet */ if(msg->parsed_uri_ok==0 && parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse the Request-URI\n"); return AUTH_ERROR; } /* preliminary check */ if(cred) { if (puri.host.len != cred->digest.realm.len) { LM_DBG("credentials realm and URI host do not match\n"); return AUTH_ERROR; } if (strncasecmp(puri.host.s, cred->digest.realm.s, puri.host.len) != 0) { LM_DBG("credentials realm and URI host do not match\n"); return AUTH_ERROR; } } if( diameter_authorize(cred?h:NULL, &msg->first_line.u.request.method, puri, msg->parsed_uri, msg->id, rb) != 1) { send_resp(msg, 500, &dia_500_err, NULL, 0); return AUTH_ERROR; } if( srv_response(msg, rb, hftype) != 1 ) return AUTH_ERROR; mark_authorized_cred(msg, h); return AUTHORIZED; }
/* * 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; }