Example #1
0
static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv,
					struct eap_method_ret *ret,
					const struct wpabuf *reqData)
{
	const struct eap_hdr *eap;
	size_t password_len;
	const u8 *password;

	password = eap_get_config_password(sm, &password_len);
	if (password == NULL) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured");
		eap_sm_request_password(sm);
		ret->ignore = TRUE;
		return NULL;
	}

	/*
	 * LEAP needs to be able to handle EAP-Success frame which does not
	 * include Type field. Consequently, eap_hdr_validate() cannot be used
	 * here. This validation will be done separately for EAP-Request and
	 * EAP-Response frames.
	 */
	eap = wpabuf_head(reqData);
	if (wpabuf_len(reqData) < sizeof(*eap) ||
	    be_to_host16(eap->length) > wpabuf_len(reqData)) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame");
		ret->ignore = TRUE;
		return NULL;
	}

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

	sm->leap_done = FALSE;

	switch (eap->code) {
	case EAP_CODE_REQUEST:
		return eap_leap_process_request(sm, priv, ret, reqData);
	case EAP_CODE_SUCCESS:
		return eap_leap_process_success(sm, priv, ret, reqData);
	case EAP_CODE_RESPONSE:
		return eap_leap_process_response(sm, priv, ret, reqData);
	default:
		wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - "
			   "ignored", eap->code);
		ret->ignore = TRUE;
		return NULL;
	}
}
static u8 * eap_leap_process(struct eap_sm *sm, void *priv,
			     struct eap_method_ret *ret,
			     const u8 *reqData, size_t reqDataLen,
			     size_t *respDataLen)
{
	const struct eap_hdr *eap;
	size_t len, password_len;
	const u8 *password;

	password = eap_get_config_password(sm, &password_len);
	if (password == NULL) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured");
		eap_sm_request_password(sm);
		ret->ignore = TRUE;
		return NULL;
	}

	eap = (const struct eap_hdr *) reqData;

	if (reqDataLen < sizeof(*eap) ||
	    (len = be_to_host16(eap->length)) > reqDataLen) {
		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame");
		ret->ignore = TRUE;
		return NULL;
	}

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

	sm->leap_done = FALSE;

	switch (eap->code) {
	case EAP_CODE_REQUEST:
		return eap_leap_process_request(sm, priv, ret, reqData, len,
						respDataLen);
	case EAP_CODE_SUCCESS:
		return eap_leap_process_success(sm, priv, ret, reqData,
						respDataLen);
	case EAP_CODE_RESPONSE:
		return eap_leap_process_response(sm, priv, ret, reqData, len);
	default:
		wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - "
			   "ignored", eap->code);
		ret->ignore = TRUE;
		return NULL;
	}
}
Example #3
0
static int eap_mschapv2_check_config(struct eap_sm *sm)
{
	size_t len;

	if (eap_get_config_identity(sm, &len) == NULL) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured");
		eap_sm_request_identity(sm);
		return -1;
	}

	if (eap_get_config_password(sm, &len) == NULL) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
		eap_sm_request_password(sm);
		return -1;
	}

	return 0;
}
Example #4
0
void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
{
	struct wpa_ssid *config = eap_get_config(sm);

	if (config == NULL)
		return;

	/* Re-send any pending requests for user data since a new control
	 * interface was added. This handles cases where the EAP authentication
	 * starts immediately after system startup when the user interface is
	 * not yet running. */
	if (config->pending_req_identity)
		eap_sm_request_identity(sm, config);
	if (config->pending_req_password)
		eap_sm_request_password(sm, config);
	if (config->pending_req_otp)
		eap_sm_request_otp(sm, config, NULL, 0);
	if (config->pending_req_pin)
		eap_sm_request_pin(sm, config);
}
Example #5
0
static u8 * eap_md5_process(struct eap_sm *sm, void *priv,
			    struct eap_method_ret *ret,
			    const u8 *reqData, size_t reqDataLen,
			    size_t *respDataLen)
{
	struct wpa_ssid *config = eap_get_config(sm);
	const struct eap_hdr *req;
	struct eap_hdr *resp;
	const u8 *pos, *challenge;
	u8 *rpos;
	size_t len, challenge_len;
	const u8 *addr[3];
	size_t elen[3];

	if (config == NULL || config->password == NULL) {
		wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
		eap_sm_request_password(sm, config);
		ret->ignore = TRUE;
		return NULL;
	}

	pos = eap_hdr_validate(EAP_TYPE_MD5, reqData, reqDataLen, &len);
	if (pos == NULL) {
		ret->ignore = TRUE;
		return NULL;
	}
	req = (const struct eap_hdr *) reqData;
	challenge_len = *pos++;
	if (challenge_len == 0 ||
	    challenge_len > len - 1) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
			   "(challenge_len=%lu len=%lu",
			   (unsigned long) challenge_len, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}
	ret->ignore = FALSE;
	challenge = pos;
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
		    challenge, challenge_len);

	wpa_printf(MSG_DEBUG, "EAP-MD5: generating Challenge Response");
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_UNCOND_SUCC;
	ret->allowNotifications = TRUE;

	*respDataLen = sizeof(struct eap_hdr) + 1 + 1 + MD5_MAC_LEN;
	resp = malloc(*respDataLen);
	if (resp == NULL)
		return NULL;
	resp->code = EAP_CODE_RESPONSE;
	resp->identifier = req->identifier;
	resp->length = host_to_be16(*respDataLen);
	rpos = (u8 *) (resp + 1);
	*rpos++ = EAP_TYPE_MD5;
	*rpos++ = MD5_MAC_LEN; /* Value-Size */

	addr[0] = &resp->identifier;
	elen[0] = 1;
	addr[1] = config->password;
	elen[1] = config->password_len;
	addr[2] = challenge;
	elen[2] = challenge_len;
	md5_vector(3, addr, elen, rpos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, MD5_MAC_LEN);

	return (u8 *) resp;
}
Example #6
0
static u8 * eap_md5_process(struct eap_sm *sm, void *priv,
			    struct eap_method_ret *ret,
			    const u8 *reqData, size_t reqDataLen,
			    size_t *respDataLen)
{
	const struct eap_hdr *req;
	struct eap_hdr *resp;
	const u8 *pos, *challenge, *password;
	u8 *rpos;
	size_t len, challenge_len, password_len;
	const u8 *addr[3];
	size_t elen[3];

	password = eap_get_config_password(sm, &password_len);
	if (password == NULL) {
		wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
		eap_sm_request_password(sm);
		ret->ignore = TRUE;
		return NULL;
	}

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5,
			       reqData, reqDataLen, &len);
	if (pos == NULL || len == 0) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)",
			   pos, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}

	/*
	 * CHAP Challenge:
	 * Value-Size (1 octet) | Value(Challenge) | Name(optional)
	 */
	req = (const struct eap_hdr *) reqData;
	challenge_len = *pos++;
	if (challenge_len == 0 || challenge_len > len - 1) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
			   "(challenge_len=%lu len=%lu)",
			   (unsigned long) challenge_len, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}
	ret->ignore = FALSE;
	challenge = pos;
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
		    challenge, challenge_len);

	wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_UNCOND_SUCC;
	ret->allowNotifications = TRUE;

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, respDataLen,
			     1 + MD5_MAC_LEN, EAP_CODE_RESPONSE,
			     req->identifier, &rpos);
	if (resp == NULL)
		return NULL;

	/*
	 * CHAP Response:
	 * Value-Size (1 octet) | Value(Response) | Name(optional)
	 */
	*rpos++ = MD5_MAC_LEN;

	addr[0] = &resp->identifier;
	elen[0] = 1;
	addr[1] = password;
	elen[1] = password_len;
	addr[2] = challenge;
	elen[2] = challenge_len;
	md5_vector(3, addr, elen, rpos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, MD5_MAC_LEN);

	return (u8 *) resp;
}
Example #7
0
static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
				       struct eap_method_ret *ret,
				       const struct wpabuf *reqData)
{
	struct wpabuf *resp;
	const u8 *pos, *challenge, *password;
	u8 *rpos, id;
	size_t len, challenge_len, password_len;

	password = eap_get_config_password(sm, &password_len);
	if (password == NULL) {
		wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
		eap_sm_request_password(sm);
		ret->ignore = TRUE;
		return NULL;
	}

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len);
	if (pos == NULL || len == 0) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)",
			   pos, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}

	/*
	 * CHAP Challenge:
	 * Value-Size (1 octet) | Value(Challenge) | Name(optional)
	 */
	challenge_len = *pos++;
	if (challenge_len == 0 || challenge_len > len - 1) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
			   "(challenge_len=%lu len=%lu)",
			   (unsigned long) challenge_len, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}
	ret->ignore = FALSE;
	challenge = pos;
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
		    challenge, challenge_len);

	wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_COND_SUCC;
	ret->allowNotifications = TRUE;

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN,
			     EAP_CODE_RESPONSE, eap_get_id(reqData));
	if (resp == NULL)
		return NULL;

	/*
	 * CHAP Response:
	 * Value-Size (1 octet) | Value(Response) | Name(optional)
	 */
	wpabuf_put_u8(resp, CHAP_MD5_LEN);

	id = eap_get_id(resp);
	rpos = wpabuf_put(resp, CHAP_MD5_LEN);
	chap_md5(id, password, password_len, challenge, challenge_len, rpos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN);

	return resp;
}
static u8 * eap_mschapv2_process(struct eap_sm *sm, void *priv,
				 struct eap_method_ret *ret,
				 const u8 *reqData, size_t reqDataLen,
				 size_t *respDataLen)
{
	struct eap_mschapv2_data *data = priv;
	struct wpa_ssid *config = eap_get_config(sm);
	const struct eap_mschapv2_hdr *req;
	int using_prev_challenge = 0;
	const u8 *pos;
	size_t ms_len, len;

	if (eap_get_config_identity(sm, &len) == NULL) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured");
		eap_sm_request_identity(sm);
		ret->ignore = TRUE;
		return NULL;
	}

	if (eap_get_config_password(sm, &len) == NULL) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
		eap_sm_request_password(sm);
		ret->ignore = TRUE;
		return NULL;
	}

	if (config->mschapv2_retry && data->prev_challenge &&
	    data->prev_error == ERROR_AUTHENTICATION_FAILURE) {
		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Replacing pending packet "
			   "with the previous challenge");

		reqData = data->prev_challenge;
		reqDataLen = data->prev_challenge_len;
		using_prev_challenge = 1;
		config->mschapv2_retry = 0;
	}

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
			       reqData, reqDataLen, &len);
	if (pos == NULL || len < 5) {
		ret->ignore = TRUE;
		return NULL;
	}
	req = (const struct eap_mschapv2_hdr *) reqData;
	len = be_to_host16(req->length);
	ms_len = WPA_GET_BE16(req->ms_length);
	if (ms_len != len - 5) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu "
			   "ms_len=%lu", (unsigned long) len,
			   (unsigned long) ms_len);
		if (sm->workaround) {
			/* Some authentication servers use invalid ms_len,
			 * ignore it for interoperability. */
			wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore"
				   " invalid ms_len");
		} else {
			ret->ignore = TRUE;
			return NULL;
		}
	}

	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d",
		   req->identifier, req->mschapv2_id);

	switch (req->op_code) {
	case MSCHAPV2_OP_CHALLENGE:
		if (!using_prev_challenge) {
			free(data->prev_challenge);
			data->prev_challenge = malloc(len);
			if (data->prev_challenge) {
				data->prev_challenge_len = len;
				memcpy(data->prev_challenge, reqData, len);
			}
		}
		return eap_mschapv2_challenge(sm, data, ret, req, respDataLen);
	case MSCHAPV2_OP_SUCCESS:
		return eap_mschapv2_success(sm, data, ret, req, respDataLen);
	case MSCHAPV2_OP_FAILURE:
		return eap_mschapv2_failure(sm, data, ret, req, respDataLen);
	default:
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored",
			   req->op_code);
		ret->ignore = TRUE;
		return NULL;
	}
}
static int eap_mschapv2_failure_txt(struct eap_sm *sm,
				    struct eap_mschapv2_data *data, char *txt)
{
	char *pos, *msg = "";
	int retry = 1;
	struct wpa_ssid *config = eap_get_config(sm);

	/* For example:
	 * E=691 R=1 C=<32 octets hex challenge> V=3 M=Authentication Failure
	 */

	pos = txt;

	if (pos && strncmp(pos, "E=", 2) == 0) {
		pos += 2;
		data->prev_error = atoi(pos);
		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d",
			   data->prev_error);
		pos = strchr(pos, ' ');
		if (pos)
			pos++;
	}

	if (pos && strncmp(pos, "R=", 2) == 0) {
		pos += 2;
		retry = atoi(pos);
		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed",
			   retry == 1 ? "" : "not ");
		pos = strchr(pos, ' ');
		if (pos)
			pos++;
	}

	if (pos && strncmp(pos, "C=", 2) == 0) {
		int hex_len;
		pos += 2;
		hex_len = strchr(pos, ' ') - (char *) pos;
		if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) {
			if (hexstr2bin(pos, data->passwd_change_challenge,
				       PASSWD_CHANGE_CHAL_LEN)) {
				wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid "
					   "failure challenge");
			} else {
				wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: failure "
					    "challenge",
					    data->passwd_change_challenge,
					    PASSWD_CHANGE_CHAL_LEN);
				data->passwd_change_challenge_valid = 1;
			}
		} else {
			wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure "
				   "challenge len %d", hex_len);
		}
		pos = strchr(pos, ' ');
		if (pos)
			pos++;
	} else {
		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: required challenge field "
			   "was not present in failure message");
	}

	if (pos && strncmp(pos, "V=", 2) == 0) {
		pos += 2;
		data->passwd_change_version = atoi(pos);
		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing "
			   "protocol version %d", data->passwd_change_version);
		pos = strchr(pos, ' ');
		if (pos)
			pos++;
	}

	if (pos && strncmp(pos, "M=", 2) == 0) {
		pos += 2;
		msg = pos;
	}
	wpa_msg(sm->msg_ctx, MSG_WARNING,
		"EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error "
		"%d)",
		msg, retry == 1 ? "" : "not ", data->prev_error);
	if (data->prev_error == ERROR_PASSWD_EXPIRED &&
	    data->passwd_change_version == 3 && config) {
		if (config->new_password == NULL) {
			wpa_msg(sm->msg_ctx, MSG_INFO,
				"EAP-MSCHAPV2: Password expired - password "
				"change required");
			eap_sm_request_new_password(sm);
		}
	} else if (retry == 1 && config) {
		/* TODO: could prevent the current password from being used
		 * again at least for some period of time */
		if (!config->mschapv2_retry)
			eap_sm_request_identity(sm);
		eap_sm_request_password(sm);
		config->mschapv2_retry = 1;
	} else if (config) {
		/* TODO: prevent retries using same username/password */
		config->mschapv2_retry = 0;
	}

	return retry == 1;
}
Example #10
0
static u8 * eap_mschapv2_process(struct eap_sm *sm, void *priv,
				 struct eap_method_ret *ret,
				 u8 *reqData, size_t reqDataLen,
				 size_t *respDataLen)
{
	struct eap_mschapv2_data *data = priv;
	struct wpa_ssid *config = eap_get_config(sm);
	struct eap_mschapv2_hdr *req;
	int ms_len, len;

	if (config == NULL || config->identity == NULL) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured");
		eap_sm_request_identity(sm, config);
		ret->ignore = TRUE;
		return NULL;
	}

	if (config->password == NULL) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
		eap_sm_request_password(sm, config);
		ret->ignore = TRUE;
		return NULL;
	}

	req = (struct eap_mschapv2_hdr *) reqData;
	len = be_to_host16(req->length);
	if (len < sizeof(*req) + 2 || req->type != EAP_TYPE_MSCHAPV2) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame");
		ret->ignore = TRUE;
		return NULL;
	}

	ms_len = ((int) req->ms_length[0] << 8) | req->ms_length[1];
	if (ms_len != len - 5) {
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%d "
			   "ms_len=%d", len, ms_len);
		if (sm->workaround) {
			/* Some authentication servers use invalid ms_len,
			 * ignore it for interoperability. */
			wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore"
				   " invalid ms_len");
		} else {
			ret->ignore = TRUE;
			return NULL;
		}
	}

	switch (req->op_code) {
	case MSCHAPV2_OP_CHALLENGE:
		return eap_mschapv2_challenge(sm, data, ret, req, respDataLen);
	case MSCHAPV2_OP_SUCCESS:
		return eap_mschapv2_success(sm, data, ret, req, respDataLen);
	case MSCHAPV2_OP_FAILURE:
		return eap_mschapv2_failure(sm, data, ret, req, respDataLen);
	default:
		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored",
			   req->op_code);
		ret->ignore = TRUE;
		return NULL;
	}
}
static int eap_ttls_phase2_request(struct eap_sm *sm,
				   struct eap_ttls_data *data,
				   struct eap_method_ret *ret,
				   const struct eap_hdr *req,
				   struct eap_hdr *hdr,
				   u8 **resp, size_t *resp_len)
{
	int res = 0;
	size_t len;

	if (data->phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||
	    data->phase2_type == EAP_TTLS_PHASE2_MSCHAP ||
	    data->phase2_type == EAP_TTLS_PHASE2_PAP ||
	    data->phase2_type == EAP_TTLS_PHASE2_CHAP) {
		if (eap_get_config_identity(sm, &len) == NULL) {
			wpa_printf(MSG_INFO,
				   "EAP-TTLS: Identity not configured");
			eap_sm_request_identity(sm);
			if (eap_get_config_password(sm, &len) == NULL)
				eap_sm_request_password(sm);
			return 0;
		}

		if (eap_get_config_password(sm, &len) == NULL) {
			wpa_printf(MSG_INFO,
				   "EAP-TTLS: Password not configured");
			eap_sm_request_password(sm);
			return 0;
		}
	}

	switch (data->phase2_type) {
	case EAP_TTLS_PHASE2_EAP:
		res = eap_ttls_phase2_request_eap(sm, data, ret, hdr,
						  resp, resp_len);
		break;
	case EAP_TTLS_PHASE2_MSCHAPV2:
		res = eap_ttls_phase2_request_mschapv2(sm, data, ret,
						       resp, resp_len);
		break;
	case EAP_TTLS_PHASE2_MSCHAP:
		res = eap_ttls_phase2_request_mschap(sm, data, ret,
						     resp, resp_len);
		break;
	case EAP_TTLS_PHASE2_PAP:
		res = eap_ttls_phase2_request_pap(sm, data, ret,
						  resp, resp_len);
		break;
	case EAP_TTLS_PHASE2_CHAP:
		res = eap_ttls_phase2_request_chap(sm, data, ret,
						   resp, resp_len);
		break;
	default:
		wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown");
		res = -1;
		break;
	}

	if (res < 0) {
		ret->methodState = METHOD_DONE;
		ret->decision = DECISION_FAIL;
	}

	return res;
}