コード例 #1
0
ファイル: rlm_chap.c プロジェクト: AirspeedTelecom/freeradius
/*
 *	Find the named user in this modules database.  Create the set
 *	of attribute-value pairs to check and reply with for this user
 *	from the database. The authentication code only needs to check
 *	the password, the rest is done here.
 */
static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(UNUSED void *instance,
				     REQUEST *request)
{
	VALUE_PAIR *passwd_item, *chap;
	uint8_t pass_str[MAX_STRING_LEN];

	if (!request->username) {
		RWDEBUG("Attribute 'User-Name' is required for authentication.\n");
		return RLM_MODULE_INVALID;
	}

	chap = pairfind(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY);
	if (!chap) {
		REDEBUG("You set 'Auth-Type = CHAP' for a request that does not contain a CHAP-Password attribute!");
		return RLM_MODULE_INVALID;
	}

	if (chap->length == 0) {
		REDEBUG("CHAP-Password is empty");
		return RLM_MODULE_INVALID;
	}

	if (chap->length != CHAP_VALUE_LENGTH + 1) {
		REDEBUG("CHAP-Password has invalid length");
		return RLM_MODULE_INVALID;
	}

	/*
	 *	Don't print out the CHAP password here.  It's binary crap.
	 */
	RDEBUG("Login attempt by \"%s\" with CHAP password",
		request->username->vp_strvalue);

	if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL){
		if (pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) != NULL){
			REDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			REDEBUG("!!! Please update your configuration so that the \"known !!!");
			REDEBUG("!!! good\" cleartext password is in Cleartext-Password,  !!!");
			REDEBUG("!!! and NOT in User-Password.                            !!!");
			REDEBUG("!!!						          !!!");
			REDEBUG("!!! Authentication will fail because of this.	          !!!");
			REDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		}

		REDEBUG("Cleartext password is required for authentication");
		return RLM_MODULE_INVALID;
	}

	rad_chap_encode(request->packet, pass_str,
			chap->vp_octets[0], passwd_item);

	if (RDEBUG_ENABLED3) {
		uint8_t const *p;
		size_t length;
		VALUE_PAIR *vp;
		char buffer[CHAP_VALUE_LENGTH * 2 + 1];

		RDEBUG3("Comparing with \"known good\" Cleartext-Password \"%s\"", passwd_item->vp_strvalue);

		vp = pairfind(request->packet->vps, PW_CHAP_CHALLENGE, 0, TAG_ANY);
		if (vp) {
			p = vp->vp_octets;
			length = vp->length;
		} else {
			p = request->packet->vector;
			length = sizeof(request->packet->vector);
		}

		fr_bin2hex(buffer, p, length);
		RINDENT();
		RDEBUG3("CHAP challenge :  %s", buffer);

		fr_bin2hex(buffer, chap->vp_octets + 1, CHAP_VALUE_LENGTH);
		RDEBUG3("Client sent    : %s", buffer);

		fr_bin2hex(buffer, pass_str + 1, CHAP_VALUE_LENGTH);
		RDEBUG3("We calculated  : %s", buffer);
		REXDENT();
	} else {
		RDEBUG2("Comparing with \"known good\" Cleartext-Password");
	}

	if (rad_digest_cmp(pass_str + 1, chap->vp_octets + 1,
			   CHAP_VALUE_LENGTH) != 0) {
		REDEBUG("Password is comparison failed: password is incorrect");
		return RLM_MODULE_REJECT;
	}

	RDEBUG("CHAP user \"%s\" authenticated successfully",
	      request->username->vp_strvalue);

	return RLM_MODULE_OK;
}
コード例 #2
0
ファイル: rlm_chap.c プロジェクト: janetuk/freeradius
/*
 *	Find the named user in this modules database.  Create the set
 *	of attribute-value pairs to check and reply with for this user
 *	from the database. The authentication code only needs to check
 *	the password, the rest is done here.
 */
static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(UNUSED void *instance, REQUEST *request)
{
	VALUE_PAIR *password, *chap;
	uint8_t pass_str[MAX_STRING_LEN];

	if (!request->username) {
		REDEBUG("&request:User-Name attribute is required for authentication");
		return RLM_MODULE_INVALID;
	}

	chap = fr_pair_find_by_num(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY);
	if (!chap) {
		REDEBUG("You set '&control:Auth-Type = CHAP' for a request that "
			"does not contain a CHAP-Password attribute!");
		return RLM_MODULE_INVALID;
	}

	if (chap->vp_length == 0) {
		REDEBUG("&request:CHAP-Password is empty");
		return RLM_MODULE_INVALID;
	}

	if (chap->vp_length != CHAP_VALUE_LENGTH + 1) {
		REDEBUG("&request:CHAP-Password has invalid length");
		return RLM_MODULE_INVALID;
	}

	password = fr_pair_find_by_num(request->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
	if (password == NULL) {
		if (fr_pair_find_by_num(request->config, PW_USER_PASSWORD, 0, TAG_ANY) != NULL){
			REDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			REDEBUG("!!! Please update your configuration so that the \"known !!!");
			REDEBUG("!!! good\" cleartext password is in Cleartext-Password,  !!!");
			REDEBUG("!!! and NOT in User-Password.                            !!!");
			REDEBUG("!!!						          !!!");
			REDEBUG("!!! Authentication will fail because of this.	          !!!");
			REDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		}

		REDEBUG("&control:Cleartext-Password is required for authentication");
		return RLM_MODULE_FAIL;
	}

	rad_chap_encode(request->packet, pass_str, chap->vp_octets[0], password);

	if (RDEBUG_ENABLED3) {
		uint8_t const *p;
		size_t length;
		VALUE_PAIR *vp;
		char buffer[MAX_STRING_LEN * 2 + 1];

		RDEBUG3("Comparing with \"known good\" &control:Cleartext-Password value \"%s\"",
			password->vp_strvalue);

		vp = fr_pair_find_by_num(request->packet->vps, PW_CHAP_CHALLENGE, 0, TAG_ANY);
		if (vp) {
			RDEBUG2("Using challenge from &request:CHAP-Challenge");
			p = vp->vp_octets;
			length = vp->vp_length;
		} else {
			RDEBUG2("Using challenge from authenticator field");
			p = request->packet->vector;
			length = sizeof(request->packet->vector);
		}

		fr_bin2hex(buffer, p, length);
		RINDENT();
		RDEBUG3("CHAP challenge : %s", buffer);

		fr_bin2hex(buffer, chap->vp_octets + 1, CHAP_VALUE_LENGTH);
		RDEBUG3("Client sent    : %s", buffer);

		fr_bin2hex(buffer, pass_str + 1, CHAP_VALUE_LENGTH);
		RDEBUG3("We calculated  : %s", buffer);
		REXDENT();
	} else {
		RDEBUG2("Comparing with \"known good\" Cleartext-Password");
	}

	if (rad_digest_cmp(pass_str + 1, chap->vp_octets + 1, CHAP_VALUE_LENGTH) != 0) {
		REDEBUG("Password comparison failed: password is incorrect");
		return RLM_MODULE_REJECT;
	}

	RDEBUG("CHAP user \"%s\" authenticated successfully", request->username->vp_strvalue);

	return RLM_MODULE_OK;
}
コード例 #3
0
/*
 *	Find the named user in this modules database.  Create the set
 *	of attribute-value pairs to check and reply with for this user
 *	from the database. The authentication code only needs to check
 *	the password, the rest is done here.
 */
static rlm_rcode_t mod_authenticate(UNUSED void *instance,
				     UNUSED REQUEST *request)
{
	VALUE_PAIR *passwd_item, *chap;
	uint8_t pass_str[MAX_STRING_LEN];

	if (!request->username) {
		RWDEBUG("Attribute 'User-Name' is required for authentication.\n");
		return RLM_MODULE_INVALID;
	}

	chap = pairfind(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY);
	if (!chap) {
		REDEBUG("You set 'Auth-Type = CHAP' for a request that does not contain a CHAP-Password attribute!");
		return RLM_MODULE_INVALID;
	}

	if (chap->length == 0) {
		REDEBUG("CHAP-Password is empty");
		return RLM_MODULE_INVALID;
	}

	if (chap->length != CHAP_VALUE_LENGTH + 1) {
		REDEBUG("CHAP-Password has invalid length");
		return RLM_MODULE_INVALID;
	}

	/*
	 *	Don't print out the CHAP password here.  It's binary crap.
	 */
	RDEBUG("Login attempt by \"%s\" with CHAP password",
		request->username->vp_strvalue);

	if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL){
		if (pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) != NULL){
			REDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
			REDEBUG("!!! Please update your configuration so that the \"known !!!");
			REDEBUG("!!! good\" clear text password is in Cleartext-Password, !!!");
			REDEBUG("!!! and NOT in User-Password.                            !!!");
			REDEBUG("!!!						          !!!");
			REDEBUG("!!! Authentication will fail because of this.	          !!!");
			REDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		}

		REDEBUG("Clear-Text password is required for authentication");
		return RLM_MODULE_INVALID;
	}

	RDEBUG("Using Clear-Text password \"%s\" for user %s authentication.",
	      passwd_item->vp_strvalue, request->username->vp_strvalue);

	rad_chap_encode(request->packet,pass_str,
			chap->vp_octets[0],passwd_item);

	if (rad_digest_cmp(pass_str + 1, chap->vp_octets + 1,
			   CHAP_VALUE_LENGTH) != 0) {
		REDEBUG("Password is comparison failed: password is incorrect");
		return RLM_MODULE_REJECT;
	}

	RDEBUG("CHAP user \"%s\" authenticated successfully",
	      request->username->vp_strvalue);

	return RLM_MODULE_OK;
}
コード例 #4
0
/*
 *	Do the MS-CHAP stuff.
 *
 *	This function is here so that all of the MS-CHAP related
 *	authentication is in one place, and we can perhaps later replace
 *	it with code to call winbindd, or something similar.
 */
static int do_mschap(rlm_mschap_t *inst,
		     REQUEST *request, VALUE_PAIR *password,
		     uint8_t *challenge, uint8_t *response,
		     uint8_t *nthashhash, int do_ntlm_auth)
{
	uint8_t		calculated[24];

	/*
	 *	Do normal authentication.
	 */
	if (!do_ntlm_auth) {
		/*
		 *	No password: can't do authentication.
		 */
		if (!password) {
			RDEBUG2("FAILED: No NT/LM-Password.  Cannot perform authentication.");
			return -1;
		}

		smbdes_mschap(password->vp_strvalue, challenge, calculated);
		if (rad_digest_cmp(response, calculated, 24) != 0) {
			return -1;
		}

		/*
		 *	If the password exists, and is an NT-Password,
		 *	then calculate the hash of the NT hash.  Doing this
		 *	here minimizes work for later.
		 */
		if (password && (password->attribute == PW_NT_PASSWORD)) {
			fr_md4_calc(nthashhash, password->vp_octets, 16);
		} else {
			memset(nthashhash, 0, 16);
		}
	} else {		/* run ntlm_auth */
		int	result;
		char	buffer[256];

		memset(nthashhash, 0, 16);

		/*
		 *	Run the program, and expect that we get 16
		 */
		result = radius_exec_program(inst->ntlm_auth, request,
					     TRUE, /* wait */
					     buffer, sizeof(buffer),
					     NULL, NULL, 1);
		if (result != 0) {
			char *p;
			VALUE_PAIR *vp = NULL;

			RDEBUG2("External script failed.");

			vp = pairmake("Module-Failure-Message", "", T_OP_EQ);
			if (!vp) {
				radlog_request(L_ERR, 0, request, "No memory to allocate Module-Failure-Message");
				return RLM_MODULE_FAIL;
			}

			p = strchr(buffer, '\n');
			if (p) *p = '\0';
			snprintf(vp->vp_strvalue, sizeof(vp->vp_strvalue),
				"%s: External script says %s",
				 inst->xlat_name, buffer);
			vp->length = strlen(vp->vp_strvalue);
			pairadd(&request->packet->vps, vp);
			return -1;
		}

		/*
		 *	Parse the answer as an nthashhash.
		 *
		 *	ntlm_auth currently returns:
		 *	NT_KEY: 000102030405060708090a0b0c0d0e0f
		 */
		if (memcmp(buffer, "NT_KEY: ", 8) != 0) {
			RDEBUG2("Invalid output from ntlm_auth: expecting NT_KEY");
			return -1;
		}

		/*
		 *	Check the length.  It should be at least 32,
		 *	with an LF at the end.
		 */
		if (strlen(buffer + 8) < 32) {
			RDEBUG2("Invalid output from ntlm_auth: NT_KEY has unexpected length");
			return -1;
		}

		/*
		 *	Update the NT hash hash, from the NT key.
		 */
		if (fr_hex2bin(buffer + 8, nthashhash, 16) != 16) {
			RDEBUG2("Invalid output from ntlm_auth: NT_KEY has non-hex values");
			return -1;
		}
	}

	return 0;
}
コード例 #5
0
/*
 *	Find the named user in this modules database.  Create the set
 *	of attribute-value pairs to check and reply with for this user
 *	from the database. The authentication code only needs to check
 *	the password, the rest is done here.
 */
static int chap_authenticate(void *instance, REQUEST *request)
{
	VALUE_PAIR *passwd_item, *chap;
	uint8_t pass_str[MAX_STRING_LEN];
	VALUE_PAIR *module_fmsg_vp;
	char module_fmsg[MAX_STRING_LEN];

	/* quiet the compiler */
	instance = instance;
	request = request;

	if (!request->username) {
		radlog_request(L_AUTH, 0, request, "rlm_chap: Attribute \"User-Name\" is required for authentication.\n");
		return RLM_MODULE_INVALID;
	}

	chap = pairfind(request->packet->vps, PW_CHAP_PASSWORD);
	if (!chap) {
		RDEBUG("ERROR: You set 'Auth-Type = CHAP' for a request that does not contain a CHAP-Password attribute!");
		return RLM_MODULE_INVALID;
	}

	if (chap->length == 0) {
		RDEBUG("ERROR: CHAP-Password is empty");
		return RLM_MODULE_INVALID;
	}

	if (chap->length != CHAP_VALUE_LENGTH + 1) {
		RDEBUG("ERROR: CHAP-Password has invalid length");
		return RLM_MODULE_INVALID;
	}

	/*
	 *	Don't print out the CHAP password here.  It's binary crap.
	 */
	RDEBUG("login attempt by \"%s\" with CHAP password",
		request->username->vp_strvalue);

	if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) == NULL){
	  RDEBUG("Cleartext-Password is required for authentication");
		snprintf(module_fmsg, sizeof(module_fmsg),
			 "rlm_chap: Clear text password not available");
		module_fmsg_vp = pairmake("Module-Failure-Message",
					  module_fmsg, T_OP_EQ);
		pairadd(&request->packet->vps, module_fmsg_vp);
		return RLM_MODULE_INVALID;
	}

	RDEBUG("Using clear text password \"%s\" for user %s authentication.",
	      passwd_item->vp_strvalue, request->username->vp_strvalue);

	rad_chap_encode(request->packet,pass_str,
			chap->vp_octets[0],passwd_item);

	if (rad_digest_cmp(pass_str + 1, chap->vp_octets + 1,
			   CHAP_VALUE_LENGTH) != 0) {
		RDEBUG("Password check failed");
		snprintf(module_fmsg, sizeof(module_fmsg),
			 "rlm_chap: Wrong user password");
		module_fmsg_vp = pairmake("Module-Failure-Message",
					  module_fmsg, T_OP_EQ);
		pairadd(&request->packet->vps, module_fmsg_vp);
		return RLM_MODULE_REJECT;
	}

	RDEBUG("chap user %s authenticated succesfully",
	      request->username->vp_strvalue);

	return RLM_MODULE_OK;
}