static inline int pv_authorize(struct sip_msg* msg, gparam_p realm, hdr_types_t hftype) { static char ha1[256]; int res; struct hdr_field* h; auth_body_t* cred; auth_result_t ret; str domain; if(fixup_get_svalue(msg, realm, &domain)!=0) { LM_ERR("invalid realm parameter\n"); return -1; } if (domain.len==0) domain.s = 0; ret = pre_auth(msg, &domain, hftype, &h); if (ret != DO_AUTHORIZATION) return ret; cred = (auth_body_t*)h->parsed; res = auth_get_ha1(msg, &cred->digest.username, &domain, ha1); if (res < 0) { /* Error */ if (sigb.reply(msg, 500, &auth_500_err, NULL) == -1) { LM_ERR("failed to send 500 reply\n"); } return ERROR; } if (res > 0) { /* Username not found */ return USER_UNKNOWN; } /* Recalculate response, it must be same to authorize successfully */ if (!check_response(&(cred->digest),&msg->first_line.u.request.method,ha1)) { return post_auth(msg, h); } return INVALID_PASSWORD; }
/** * @brief do WWW-Digest authentication with password taken from cfg var */ static int pv_authenticate(struct sip_msg *msg, char *p1, char *p2, char *p3, int hftype) { int flags = 0; str realm = {0, 0}; str passwd = {0, 0}; struct hdr_field* h; auth_body_t* cred; int ret; str hf = {0, 0}; avp_value_t val; static char ha1[256]; struct qp *qop = NULL; cred = 0; ret = AUTH_ERROR; if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(realm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_str_fparam(&passwd, msg, (fparam_t*)p2) < 0) { LM_ERR("failed to get passwd value\n"); goto error; } if(passwd.len==0) { LM_ERR("invalid password value - empty content\n"); goto error; } if (get_int_fparam(&flags, msg, (fparam_t*)p3) < 0) { LM_ERR("invalid flags value\n"); goto error; } switch(pre_auth(msg, &realm, hftype, &h, NULL)) { case ERROR: case BAD_CREDENTIALS: LM_DBG("error or bad credentials\n"); ret = AUTH_ERROR; goto end; case CREATE_CHALLENGE: LM_ERR("CREATE_CHALLENGE is not a valid state\n"); ret = AUTH_ERROR; goto end; case DO_RESYNCHRONIZATION: LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n"); ret = AUTH_ERROR; goto end; case NOT_AUTHENTICATED: LM_DBG("not authenticated\n"); ret = AUTH_ERROR; goto end; case DO_AUTHENTICATION: break; case AUTHENTICATED: ret = AUTH_OK; goto end; } cred = (auth_body_t*)h->parsed; /* compute HA1 if needed */ if ((flags&1)==0) { /* Plaintext password is stored in PV, calculate HA1 */ calc_HA1(HA_MD5, &cred->digest.username.whole, &realm, &passwd, 0, 0, ha1); LM_DBG("HA1 string calculated: %s\n", ha1); } else { memcpy(ha1, passwd.s, passwd.len); ha1[passwd.len] = '\0'; } /* Recalculate response, it must be same to authorize successfully */ ret = auth_check_response(&(cred->digest), &msg->first_line.u.request.method, ha1); if(ret==AUTHENTICATED) { ret = AUTH_OK; switch(post_auth(msg, h)) { case AUTHENTICATED: break; default: ret = AUTH_ERROR; break; } } else { if(ret==NOT_AUTHENTICATED) ret = AUTH_INVALID_PASSWORD; else ret = AUTH_ERROR; } end: if (ret < 0) { /* check if required to add challenge header as avp */ if(!(flags&14)) return ret; if(flags&8) { qop = &auth_qauthint; } else if(flags&4) { qop = &auth_qauth; } if (get_challenge_hf(msg, (cred ? cred->stale : 0), &realm, NULL, NULL, qop, hftype, &hf) < 0) { ERR("Error while creating challenge\n"); ret = AUTH_ERROR; } else { val.s = hf; if(add_avp(challenge_avpid.flags | AVP_VAL_STR, challenge_avpid.name, val) < 0) { LM_ERR("Error while creating attribute with challenge\n"); ret = AUTH_ERROR; } pkg_free(hf.s); } } error: return ret; }
/* 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; }
/** * @brief do WWW-Digest authentication with password taken from cfg var */ int pv_authenticate(struct sip_msg *msg, str *realm, str *passwd, int flags, int hftype, str *method) { struct hdr_field* h; auth_body_t* cred; int ret; str hf = {0, 0}; avp_value_t val; static char ha1[256]; struct qp *qop = NULL; cred = 0; ret = AUTH_ERROR; switch(pre_auth(msg, realm, hftype, &h, NULL)) { case NONCE_REUSED: LM_DBG("nonce reused"); ret = AUTH_NONCE_REUSED; goto end; case STALE_NONCE: LM_DBG("stale nonce\n"); ret = AUTH_STALE_NONCE; goto end; case NO_CREDENTIALS: LM_DBG("no credentials\n"); ret = AUTH_NO_CREDENTIALS; goto end; case ERROR: case BAD_CREDENTIALS: LM_DBG("error or bad credentials\n"); ret = AUTH_ERROR; goto end; case CREATE_CHALLENGE: LM_ERR("CREATE_CHALLENGE is not a valid state\n"); ret = AUTH_ERROR; goto end; case DO_RESYNCHRONIZATION: LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n"); ret = AUTH_ERROR; goto end; case NOT_AUTHENTICATED: LM_DBG("not authenticated\n"); ret = AUTH_ERROR; goto end; case DO_AUTHENTICATION: break; case AUTHENTICATED: ret = AUTH_OK; goto end; } cred = (auth_body_t*)h->parsed; /* compute HA1 if needed */ if ((flags&1)==0) { /* Plaintext password is stored in PV, calculate HA1 */ calc_HA1(HA_MD5, &cred->digest.username.whole, realm, passwd, 0, 0, ha1); LM_DBG("HA1 string calculated: %s\n", ha1); } else { memcpy(ha1, passwd->s, passwd->len); ha1[passwd->len] = '\0'; } /* Recalculate response, it must be same to authorize successfully */ ret = auth_check_response(&(cred->digest), method, ha1); if(ret==AUTHENTICATED) { ret = AUTH_OK; switch(post_auth(msg, h)) { case AUTHENTICATED: break; default: ret = AUTH_ERROR; break; } } else { if(ret==NOT_AUTHENTICATED) ret = AUTH_INVALID_PASSWORD; else ret = AUTH_ERROR; } end: if (ret < 0) { /* check if required to add challenge header as avp */ if(!(flags&14)) return ret; if(flags&8) { qop = &auth_qauthint; } else if(flags&4) { qop = &auth_qauth; } if (get_challenge_hf(msg, (cred ? cred->stale : 0), realm, NULL, NULL, qop, hftype, &hf) < 0) { ERR("Error while creating challenge\n"); ret = AUTH_ERROR; } else { val.s = hf; if(add_avp(challenge_avpid.flags | AVP_VAL_STR, challenge_avpid.name, val) < 0) { LM_ERR("Error while creating attribute with challenge\n"); ret = AUTH_ERROR; } pkg_free(hf.s); } } return ret; }