Пример #1
0
/*
 * 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;
}
Пример #2
0
/*
 * 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;
}
Пример #3
0
/*
 * 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;
}
Пример #4
0
/* 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;
}
Пример #5
0
/* 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;
}
Пример #6
0
/*
 * 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;
}