Beispiel #1
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;
}
Beispiel #2
0
/*
 * Create and send a challenge
 */
static inline int challenge(struct sip_msg* _msg, str* _realm, int _qop, 
			    int _code, char* _message, char* _challenge_msg)
{
	int auth_hf_len;
	struct hdr_field* h;
	auth_body_t* cred = 0;
	char *auth_hf;
	int ret, hftype = 0; /* Makes gcc happy */
	struct sip_uri uri;

	switch(_code) {
	case 401: 
		get_authorized_cred(_msg->authorization, &h); 
		hftype = HDR_AUTHORIZATION;
		break;
	case 407: 
		get_authorized_cred(_msg->proxy_auth, &h);
		hftype = HDR_PROXYAUTH;
		break;
	}

	if (h) cred = (auth_body_t*)(h->parsed);

	if (_realm->len == 0) {
		if (get_realm(_msg, hftype, &uri) < 0) {
			LOG(L_ERR, "challenge(): Error while extracting URI\n");
			if (send_resp(_msg, 400, MESSAGE_400, 0, 0) == -1) {
				LOG(L_ERR, "challenge(): Error while sending response\n");
				return -1;
			}
			return 0;
		}

		_realm = &uri.host;
		strip_realm(_realm);
	}

	auth_hf = build_auth_hf(0, (cred ? cred->stale : 0), _realm, &auth_hf_len, _qop, _challenge_msg);
	if (!auth_hf) {
		LOG(L_ERR, "ERROR: challenge: no mem w/cred\n");
		return -1;
	}
	
	ret = send_resp(_msg, _code, _message, auth_hf, auth_hf_len);
	if (auth_hf) pkg_free(auth_hf);
	if (ret == -1) {
		LOG(L_ERR, "challenge(): Error while sending response\n");
		return -1;
	}
	
	return 0;
}
Beispiel #3
0
/*
 * Create and send a challenge
 */
static inline int challenge(struct sip_msg* _msg, gparam_p _realm, int _qop,
						int _code, char* _message, char* _challenge_msg)
{
	int auth_hf_len;
	struct hdr_field* h;
	auth_body_t* cred = 0;
	char *auth_hf;
	int ret;
	hdr_types_t hftype = 0; /* Makes gcc happy */
	struct sip_uri *uri;
	str realm;
	str reason;

	switch(_code) {
	case 401:
		get_authorized_cred(_msg->authorization, &h); 
		hftype = HDR_AUTHORIZATION_T;
		break;
	case 407:
		get_authorized_cred(_msg->proxy_auth, &h);
		hftype = HDR_PROXYAUTH_T;
		break;
	}

	if (h) cred = (auth_body_t*)(h->parsed);

	if(fixup_get_svalue(_msg, _realm, &realm)!=0)
	{
		LM_ERR("invalid realm parameter");
		if (send_resp(_msg, 500, &auth_500_err, 0, 0)==-1)
			return -1;
		else
			return 0;
	}
	if (realm.len == 0) {
		if (get_realm(_msg, hftype, &uri) < 0) {
			LM_ERR("failed to extract URI\n");
			if (send_resp(_msg, 400, &auth_400_err, 0, 0) == -1) {
				LM_ERR("failed to send the response\n");
				return -1;
			}
			return 0;
		}

		realm = uri->host;
		strip_realm(&realm);
	}

	auth_hf = build_auth_hf(0, (cred ? cred->stale : 0), &realm, 
			&auth_hf_len, _qop, _challenge_msg);
	if (!auth_hf) {
		LM_ERR("failed to generate nonce\n");
		return -1;
	}

	reason.s = _message;
	reason.len = strlen(_message);
	ret = send_resp(_msg, _code, &reason, auth_hf, auth_hf_len);
	if (auth_hf) pkg_free(auth_hf);
	if (ret == -1) {
		LM_ERR("failed to send the response\n");
		return -1;
	}
	
	return 0;
}
Beispiel #4
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, 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;
}
Beispiel #5
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;
}