Exemple #1
0
static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
{
	struct eap_leap_data *data = priv;
	u8 *key, pw_hash_hash[16], pw_hash[16];
	const u8 *addr[5], *password;
	size_t elen[5], password_len;
	int pwhash;

	if (data->state != LEAP_DONE)
		return NULL;

	password = eap_get_config_password2(sm, &password_len, &pwhash);
	if (password == NULL)
		return NULL;

	key = os_malloc(LEAP_KEY_LEN);
	if (key == NULL)
		return NULL;

	if (pwhash) {
		if (hash_nt_password_hash(password, pw_hash_hash)) {
			os_free(key);
			return NULL;
		}
	} else {
		if (nt_password_hash(password, password_len, pw_hash) ||
		    hash_nt_password_hash(pw_hash, pw_hash_hash)) {
			os_free(key);
			return NULL;
		}
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash",
			pw_hash_hash, 16);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge",
		    data->peer_challenge, LEAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response",
		    data->peer_response, LEAP_RESPONSE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge",
		    data->ap_challenge, LEAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response",
		    data->ap_response, LEAP_RESPONSE_LEN);

	addr[0] = pw_hash_hash;
	elen[0] = 16;
	addr[1] = data->ap_challenge;
	elen[1] = LEAP_CHALLENGE_LEN;
	addr[2] = data->ap_response;
	elen[2] = LEAP_RESPONSE_LEN;
	addr[3] = data->peer_challenge;
	elen[3] = LEAP_CHALLENGE_LEN;
	addr[4] = data->peer_response;
	elen[4] = LEAP_RESPONSE_LEN;
	md5_vector(5, addr, elen, key);
	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
	*len = LEAP_KEY_LEN;

	return key;
}
Exemple #2
0
static void * eap_pwd_init(struct eap_sm *sm)
{
	struct eap_pwd_data *data;
	const u8 *identity, *password;
	size_t identity_len, password_len;
	int fragment_size;
	int pwhash;

	password = eap_get_config_password2(sm, &password_len, &pwhash);
	if (password == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: No password configured!");
		return NULL;
	}

	identity = eap_get_config_identity(sm, &identity_len);
	if (identity == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: No identity configured!");
		return NULL;
	}

	if ((data = os_zalloc(sizeof(*data))) == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: memory allocation data fail");
		return NULL;
	}

	if ((data->bnctx = BN_CTX_new()) == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
		os_free(data);
		return NULL;
	}

	if ((data->id_peer = os_malloc(identity_len)) == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
		BN_CTX_free(data->bnctx);
		os_free(data);
		return NULL;
	}

	os_memcpy(data->id_peer, identity, identity_len);
	data->id_peer_len = identity_len;

	if ((data->password = os_malloc(password_len)) == NULL) {
		wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail");
		BN_CTX_free(data->bnctx);
		bin_clear_free(data->id_peer, data->id_peer_len);
		os_free(data);
		return NULL;
	}
	os_memcpy(data->password, password, password_len);
	data->password_len = password_len;
	data->password_hash = pwhash;

	data->out_frag_pos = data->in_frag_pos = 0;
	data->inbuf = data->outbuf = NULL;
	fragment_size = eap_get_config_fragment_size(sm);
	if (fragment_size <= 0)
		data->mtu = 1020; /* default from RFC 5931 */
	else
		data->mtu = fragment_size;

	data->state = PWD_ID_Req;

	return data;
}
Exemple #3
0
static struct wpabuf * 
eap_mschapv2_change_password(
	struct eap_sm *sm, struct eap_mschapv2_data *data,
	struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id)
{
	struct wpabuf *resp;
	int ms_len;
	const u8 *username, *password, *new_password;
	size_t username_len, password_len, new_password_len;
	struct eap_mschapv2_hdr *ms;
	struct ms_change_password *cp;
	u8 password_hash[16], password_hash_hash[16];
	int pwhash;

	username = eap_get_config_identity(sm, &username_len);
	password = eap_get_config_password2(sm, &password_len, &pwhash);
	new_password = eap_get_config_new_password(sm, &new_password_len);
	if (username == NULL || password == NULL || new_password == NULL)
		return NULL;

	username = mschapv2_remove_domain(username, &username_len);

	ret->ignore = false;
	ret->methodState = METHOD_MAY_CONT;
	ret->decision = DECISION_COND_SUCC;
	ret->allowNotifications = TRUE;

	ms_len = sizeof(*ms) + sizeof(*cp);
	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
			     EAP_CODE_RESPONSE, id);
	if (resp == NULL)
		return NULL;
	ms = wpabuf_put(resp, sizeof(*ms));
	ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD;
	ms->mschapv2_id = req->mschapv2_id + 1;
	WPA_PUT_BE16(ms->ms_length, ms_len);
	cp = wpabuf_put(resp, sizeof(*cp));

	if (pwhash) {
		if (encrypt_pw_block_with_password_hash(
			new_password, new_password_len,
			password, cp->encr_password))
			goto fail;
	} else {
		if (new_password_encrypted_with_old_nt_password_hash(
			new_password, new_password_len,
			password, password_len, cp->encr_password))
			goto fail;
	}

	if (pwhash) {
		u8 new_password_hash[16];
		nt_password_hash(new_password, new_password_len,
				 new_password_hash);
		nt_password_hash_encrypted_with_block(password,
						      new_password_hash,
						      cp->encr_hash);
	} else {
		old_nt_password_hash_encrypted_with_new_nt_password_hash(
				new_password, new_password_len,
				password, password_len, cp->encr_hash);
	}

	if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN))
		goto fail;

	os_memset(cp->reserved, 0, 8);

	generate_nt_response(data->passwd_change_challenge, cp->peer_challenge,
			     username, username_len, new_password,
			     new_password_len, cp->nt_response);

	generate_authenticator_response(new_password, new_password_len,
					cp->peer_challenge,
					data->passwd_change_challenge,
					username, username_len,
					cp->nt_response, data->auth_response);
	data->auth_response_valid = 1;

	nt_password_hash(new_password, new_password_len, password_hash);
	hash_nt_password_hash(password_hash, password_hash_hash);
	get_master_key(password_hash_hash, cp->nt_response, data->master_key);
	data->master_key_valid = 1;

	os_memset(cp->flags, 0, 2);

	return resp;

fail:
	wpabuf_free(resp);
	return NULL;
}
Exemple #4
0
static struct wpabuf * 
eap_mschapv2_challenge_reply(
	struct eap_sm *sm, struct eap_mschapv2_data *data,
	u8 id, u8 mschapv2_id, const u8 *auth_challenge)
{
	struct wpabuf *resp;
	struct eap_mschapv2_hdr *ms;
	u8 *peer_challenge;
	int ms_len;
	struct ms_response *r;
	size_t identity_len, password_len;
	const u8 *identity, *password;
	int pwhash;

	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generate Challenge Response\n");

	identity = eap_get_config_identity(sm, &identity_len);
	password = eap_get_config_password2(sm, &password_len, &pwhash);
	if (identity == NULL || password == NULL)
		return NULL;

	ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len;
	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
			     ms_len, EAP_CODE_RESPONSE, id);
	if (resp == NULL)
		return NULL;

	ms = wpabuf_put(resp, sizeof(*ms));
	ms->op_code = MSCHAPV2_OP_RESPONSE;
	ms->mschapv2_id = mschapv2_id;
	if (data->prev_error)
		ms->mschapv2_id++;
	WPA_PUT_BE16(ms->ms_length, ms_len);
	wpabuf_put_u8(resp, sizeof(*r));

	/* Response */
	r = wpabuf_put(resp, sizeof(*r));
	peer_challenge = r->peer_challenge;
	if (data->peer_challenge) {
		peer_challenge = data->peer_challenge;
	os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN);
	} else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) {
		wpabuf_free(resp);
		return NULL;
	}
	os_memset(r->reserved, 0, 8);
	if (data->auth_challenge)
		auth_challenge = data->auth_challenge;
	if (mschapv2_derive_response(identity, identity_len, password,
				     password_len, pwhash, auth_challenge,
				     peer_challenge, r->nt_response,
				     data->auth_response, data->master_key)) {
		wpabuf_free(resp);
		return NULL;
	}
	data->auth_response_valid = 1;
	data->master_key_valid = 1;

	r->flags = 0;

	wpabuf_put_data(resp, identity, identity_len);
	return resp;
}
Exemple #5
0
static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv,
						struct eap_method_ret *ret,
						const struct wpabuf *reqData)
{
	struct eap_leap_data *data = priv;
	struct wpabuf *resp;
	const u8 *pos, *challenge, *identity, *password;
	u8 challenge_len, *rpos;
	size_t identity_len, password_len, len;
	int pwhash;

	wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request");

	identity = eap_get_config_identity(sm, &identity_len);
	password = eap_get_config_password2(sm, &password_len, &pwhash);
	if (identity == NULL || password == NULL)
		return NULL;

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len);
	if (pos == NULL || len < 3) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame");
		ret->ignore = TRUE;
		return NULL;
	}

	if (*pos != LEAP_VERSION) {
		wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version "
			   "%d", *pos);
		ret->ignore = TRUE;
		return NULL;
	}
	pos++;

	pos++; /* skip unused byte */

	challenge_len = *pos++;
	if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > len - 3) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge "
			   "(challenge_len=%d reqDataLen=%lu)",
			   challenge_len, (unsigned long) wpabuf_len(reqData));
		ret->ignore = TRUE;
		return NULL;
	}
	challenge = pos;
	os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP",
		    challenge, LEAP_CHALLENGE_LEN);

	wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response");

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP,
			     3 + LEAP_RESPONSE_LEN + identity_len,
			     EAP_CODE_RESPONSE, eap_get_id(reqData));
	if (resp == NULL)
		return NULL;
	wpabuf_put_u8(resp, LEAP_VERSION);
	wpabuf_put_u8(resp, 0); /* unused */
	wpabuf_put_u8(resp, LEAP_RESPONSE_LEN);
	rpos = wpabuf_put(resp, LEAP_RESPONSE_LEN);
	if (pwhash)
		challenge_response(challenge, password, rpos);
	else
		nt_challenge_response(challenge, password, password_len, rpos);
	os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN);
	wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response",
		    rpos, LEAP_RESPONSE_LEN);
	wpabuf_put_data(resp, identity, identity_len);

	data->state = LEAP_WAIT_SUCCESS;

	return resp;
}
Exemple #6
0
static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv,
						 struct eap_method_ret *ret,
						 const struct wpabuf *reqData)
{
	struct eap_leap_data *data = priv;
	const u8 *pos, *password;
	u8 response_len, pw_hash[16], pw_hash_hash[16],
		expected[LEAP_RESPONSE_LEN];
	size_t password_len, len;
	int pwhash;

	wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response");

	password = eap_get_config_password2(sm, &password_len, &pwhash);
	if (password == NULL)
		return NULL;

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len);
	if (pos == NULL || len < 3) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame");
		ret->ignore = TRUE;
		return NULL;
	}

	if (*pos != LEAP_VERSION) {
		wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version "
			   "%d", *pos);
		ret->ignore = TRUE;
		return NULL;
	}
	pos++;

	pos++; /* skip unused byte */

	response_len = *pos++;
	if (response_len != LEAP_RESPONSE_LEN || response_len > len - 3) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response "
			   "(response_len=%d reqDataLen=%lu)",
			   response_len, (unsigned long) wpabuf_len(reqData));
		ret->ignore = TRUE;
		return NULL;
	}

	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Response from AP",
		    pos, LEAP_RESPONSE_LEN);
	os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN);

	if (pwhash) {
		if (hash_nt_password_hash(password, pw_hash_hash)) {
			ret->ignore = TRUE;
			return NULL;
		}
	} else {
		if (nt_password_hash(password, password_len, pw_hash) ||
		    hash_nt_password_hash(pw_hash, pw_hash_hash)) {
			ret->ignore = TRUE;
			return NULL;
		}
	}
	challenge_response(data->ap_challenge, pw_hash_hash, expected);

	ret->methodState = METHOD_DONE;
	ret->allowNotifications = FALSE;

	if (os_memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) {
		wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid "
			   "response - authentication failed");
		wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP",
			    expected, LEAP_RESPONSE_LEN);
		ret->decision = DECISION_FAIL;
		return NULL;
	}

	ret->decision = DECISION_UNCOND_SUCC;

	/* LEAP is somewhat odd method since it sends EAP-Success in the middle
	 * of the authentication. Use special variable to transit EAP state
	 * machine to SUCCESS state. */
	sm->leap_done = TRUE;
	data->state = LEAP_DONE;

	/* No more authentication messages expected; AP will send EAPOL-Key
	 * frames if encryption is enabled. */
	return NULL;
}
Exemple #7
0
static struct wpabuf * eap_mschapv2_change_password(
	struct eap_sm *sm, struct eap_mschapv2_data *data,
	struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id)
{
	struct wpabuf *resp;
	int ms_len;
	const u8 *username, *password, *new_password;
	size_t username_len, password_len, new_password_len;
	struct eap_mschapv2_hdr *ms;
	struct ms_change_password *cp;
	u8 password_hash[16], password_hash_hash[16];
	int pwhash;

	username = eap_get_config_identity(sm, &username_len);
	password = eap_get_config_password2(sm, &password_len, &pwhash);
	new_password = eap_get_config_new_password(sm, &new_password_len);
	if (username == NULL || password == NULL || new_password == NULL)
		return NULL;

	username = mschapv2_remove_domain(username, &username_len);

	ret->ignore = FALSE;
	ret->methodState = METHOD_MAY_CONT;
	ret->decision = DECISION_COND_SUCC;
	ret->allowNotifications = TRUE;

	ms_len = sizeof(*ms) + sizeof(*cp);
	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
			     EAP_CODE_RESPONSE, id);
	if (resp == NULL)
		return NULL;

	ms = wpabuf_put(resp, sizeof(*ms));
	ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD;
	ms->mschapv2_id = req->mschapv2_id + 1;
	WPA_PUT_BE16(ms->ms_length, ms_len);
	cp = wpabuf_put(resp, sizeof(*cp));

	/* Encrypted-Password */
	if (pwhash) {
		if (encrypt_pw_block_with_password_hash(
			    new_password, new_password_len,
			    password, cp->encr_password))
			goto fail;
	} else {
		if (new_password_encrypted_with_old_nt_password_hash(
			    new_password, new_password_len,
			    password, password_len, cp->encr_password))
			goto fail;
	}

	/* Encrypted-Hash */
	if (pwhash) {
		u8 new_password_hash[16];
		nt_password_hash(new_password, new_password_len,
				 new_password_hash);
		nt_password_hash_encrypted_with_block(password,
						      new_password_hash,
						      cp->encr_hash);
	} else {
		old_nt_password_hash_encrypted_with_new_nt_password_hash(
			new_password, new_password_len,
			password, password_len, cp->encr_hash);
	}

	/* Peer-Challenge */
	if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN))
		goto fail;

	/* Reserved, must be zero */
	os_memset(cp->reserved, 0, 8);

	/* NT-Response */
	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge",
		    data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge",
		    cp->peer_challenge, MSCHAPV2_CHAL_LEN);
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username",
			  username, username_len);
	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password",
			      new_password, new_password_len);
	generate_nt_response(data->passwd_change_challenge, cp->peer_challenge,
			     username, username_len,
			     new_password, new_password_len,
			     cp->nt_response);
	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response",
		    cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN);

	/* Authenticator response is not really needed yet, but calculate it
	 * here so that challenges need not be saved. */
	generate_authenticator_response(new_password, new_password_len,
					cp->peer_challenge,
					data->passwd_change_challenge,
					username, username_len,
					cp->nt_response, data->auth_response);
	data->auth_response_valid = 1;

	/* Likewise, generate master_key here since we have the needed data
	 * available. */
	nt_password_hash(new_password, new_password_len, password_hash);
	hash_nt_password_hash(password_hash, password_hash_hash);
	get_master_key(password_hash_hash, cp->nt_response, data->master_key);
	data->master_key_valid = 1;

	/* Flags */
	os_memset(cp->flags, 0, 2);

	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d "
		   "(change pw)", id, ms->mschapv2_id);

	return resp;

fail:
	wpabuf_free(resp);
	return NULL;
}
Exemple #8
0
static struct wpabuf * eap_mschapv2_challenge_reply(
	struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id,
	u8 mschapv2_id, const u8 *auth_challenge)
{
	struct wpabuf *resp;
	struct eap_mschapv2_hdr *ms;
	u8 *peer_challenge;
	int ms_len;
	struct ms_response *r;
	size_t identity_len, password_len;
	const u8 *identity, *password;
	int pwhash;

	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response");

	identity = eap_get_config_identity(sm, &identity_len);
	password = eap_get_config_password2(sm, &password_len, &pwhash);
	if (identity == NULL || password == NULL)
		return NULL;

	ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len;
	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
			     EAP_CODE_RESPONSE, id);
	if (resp == NULL)
		return NULL;

	ms = wpabuf_put(resp, sizeof(*ms));
	ms->op_code = MSCHAPV2_OP_RESPONSE;
	ms->mschapv2_id = mschapv2_id;
	if (data->prev_error) {
		/*
		 * TODO: this does not seem to be enough when processing two
		 * or more failure messages. IAS did not increment mschapv2_id
		 * in its own packets, but it seemed to expect the peer to
		 * increment this for all packets(?).
		 */
		ms->mschapv2_id++;
	}
	WPA_PUT_BE16(ms->ms_length, ms_len);

	wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */

	/* Response */
	r = wpabuf_put(resp, sizeof(*r));
	peer_challenge = r->peer_challenge;
	if (data->peer_challenge) {
		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated "
			   "in Phase 1");
		peer_challenge = data->peer_challenge;
		os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN);
	} else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) {
		wpabuf_free(resp);
		return NULL;
	}
	os_memset(r->reserved, 0, 8);
	if (data->auth_challenge) {
		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated "
			   "in Phase 1");
		auth_challenge = data->auth_challenge;
	}

	if (mschapv2_derive_response(identity, identity_len, password,
				     password_len, pwhash, auth_challenge,
				     peer_challenge, r->nt_response,
				     data->auth_response, data->master_key)) {
		wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to derive "
			   "response");
		wpabuf_free(resp);
		return NULL;
	}
	data->auth_response_valid = 1;
	data->master_key_valid = 1;

	r->flags = 0; /* reserved, must be zero */

	wpabuf_put_data(resp, identity, identity_len);
	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d "
		   "(response)", id, ms->mschapv2_id);
	return resp;
}