Esempio n. 1
0
/**
 * eap_tls_process_output - Process outgoing TLS message
 * @data: Data for TLS processing
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
 * @peap_version: Version number for EAP-PEAP/TTLS
 * @id: EAP identifier for the response
 * @ret: Return value to use on success
 * @out_data: Buffer for returning the allocated output buffer
 * Returns: ret (0 or 1) on success, -1 on failure
 */
static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
				  int peap_version, u8 id, int ret,
				  struct wpabuf **out_data)
{
	size_t len;
	u8 *flags;
	int more_fragments, length_included;

	if (data->tls_out == NULL)
		return -1;
	len = wpabuf_len(data->tls_out) - data->tls_out_pos;
	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
		   "%lu bytes)",
		   (unsigned long) len,
		   (unsigned long) wpabuf_len(data->tls_out));

	/*
	 * Limit outgoing message to the configured maximum size. Fragment
	 * message if needed.
	 */
	if (len > data->tls_out_limit) {
		more_fragments = 1;
		len = data->tls_out_limit;
		wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
			   "will follow", (unsigned long) len);
	} else
		more_fragments = 0;

	length_included = data->tls_out_pos == 0 &&
		(wpabuf_len(data->tls_out) > data->tls_out_limit ||
		 data->include_tls_length);
	if (!length_included &&
	    eap_type == EAP_TYPE_PEAP && peap_version == 0 &&
	    !tls_connection_established(data->eap->ssl_ctx, data->conn)) {
		/*
		 * Windows Server 2008 NPS really wants to have the TLS Message
		 * length included in phase 0 even for unfragmented frames or
		 * it will get very confused with Compound MAC calculation and
		 * Outer TLVs.
		 */
		length_included = 1;
	}

	*out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type,
				  1 + length_included * 4 + len,
				  EAP_CODE_RESPONSE, id);
	if (*out_data == NULL)
		return -1;

	flags = wpabuf_put(*out_data, 1);
	*flags = peap_version;
	if (more_fragments)
		*flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
	if (length_included) {
		*flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
		wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out));
	}

	wpabuf_put_data(*out_data,
			wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
			len);
	data->tls_out_pos += len;

	if (!more_fragments)
		eap_peer_tls_reset_output(data);

	return ret;
}
Esempio n. 2
0
static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id)
{
	struct wpabuf *req;
	u8 flags;
	size_t send_len, plen, icv_len = 0;

	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request");

	flags = 0;
	send_len = wpabuf_len(data->out_buf) - data->out_used;
	if (1 + send_len > data->fragment_size) {
		send_len = data->fragment_size - 1;
		flags |= IKEV2_FLAGS_MORE_FRAGMENTS;
		if (data->out_used == 0) {
			flags |= IKEV2_FLAGS_LENGTH_INCLUDED;
			send_len -= 4;
		}
	}

	plen = 1 + send_len;
	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
		plen += 4;
	if (data->keys_ready) {
		const struct ikev2_integ_alg *integ;
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum "
			   "Data");
		flags |= IKEV2_FLAGS_ICV_INCLUDED;
		integ = ikev2_get_integ(data->ikev2.proposal.integ);
		if (integ == NULL) {
			wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
				   "transform / cannot generate ICV");
			return NULL;
		}
		icv_len = integ->hash_len;

		plen += icv_len;
	}
	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen,
			    EAP_CODE_REQUEST, id);
	if (req == NULL)
		return NULL;

	wpabuf_put_u8(req, flags); /* Flags */
	if (flags & IKEV2_FLAGS_LENGTH_INCLUDED)
		wpabuf_put_be32(req, wpabuf_len(data->out_buf));

	wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
			send_len);
	data->out_used += send_len;

	if (flags & IKEV2_FLAGS_ICV_INCLUDED) {
		const u8 *msg = wpabuf_head(req);
		size_t len = wpabuf_len(req);
		ikev2_integ_hash(data->ikev2.proposal.integ,
				 data->ikev2.keys.SK_ai,
				 data->ikev2.keys.SK_integ_len,
				 msg, len, wpabuf_put(req, icv_len));
	}

	if (data->out_used == wpabuf_len(data->out_buf)) {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
			   "(message sent completely)",
			   (unsigned long) send_len);
		wpabuf_free(data->out_buf);
		data->out_buf = NULL;
		data->out_used = 0;
	} else {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes "
			   "(%lu more to send)", (unsigned long) send_len,
			   (unsigned long) wpabuf_len(data->out_buf) -
			   data->out_used);
		eap_ikev2_state(data, WAIT_FRAG_ACK);
	}

	return req;
}
Esempio n. 3
0
static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv,
				       struct eap_method_ret *ret,
				       const struct wpabuf *reqData)
{
	struct eap_gtc_data *data = priv;
	struct wpabuf *resp;
	const u8 *pos, *password, *identity;
	size_t password_len, identity_len, len, plen;
	int otp;
	u8 id;

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len);
	if (pos == NULL) {
		ret->ignore = TRUE;
		return NULL;
	}
	id = eap_get_id(reqData);

	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
	if (data->prefix &&
	    (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) {
		wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
			   "expected prefix");

		/* Send an empty response in order to allow tunneled
		 * acknowledgement of the failure. This will also cover the
		 * error case which seems to use EAP-MSCHAPv2 like error
		 * reporting with EAP-GTC inside EAP-FAST tunnel. */
		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC,
				     0, EAP_CODE_RESPONSE, id);
		return resp;
	}

	password = eap_get_config_otp(sm, &password_len);
	if (password)
		otp = 1;
	else {
		password = eap_get_config_password(sm, &password_len);
		otp = 0;
	}

	if (password == NULL) {
		wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
		eap_sm_request_otp(sm, (const char *) pos, len);
		ret->ignore = TRUE;
		return NULL;
	}

	ret->ignore = FALSE;

	ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE;
	ret->decision = DECISION_COND_SUCC;
	ret->allowNotifications = FALSE;

	plen = password_len;
	identity = eap_get_config_identity(sm, &identity_len);
	if (identity == NULL)
		return NULL;
	if (data->prefix)
		plen += 9 + identity_len + 1;
	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen,
			     EAP_CODE_RESPONSE, id);
	if (resp == NULL)
		return NULL;
	if (data->prefix) {
		wpabuf_put_data(resp, "RESPONSE=", 9);
		wpabuf_put_data(resp, identity, identity_len);
		wpabuf_put_u8(resp, '\0');
	}
	wpabuf_put_data(resp, password, password_len);
	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
			      wpabuf_head_u8(resp) + sizeof(struct eap_hdr) +
			      1, plen);

	if (otp) {
		wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password");
		eap_clear_config_otp(sm);
	}

	return resp;
}
Esempio n. 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: 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;
}
Esempio n. 5
0
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_probe_req_ie
Routine Description: set probe request ie for WSC mode change
Arguments:
   priv - pointer to private data structure
   ies - probe_req_ie data
   ies_len - ie data length
Return Value: actual buffer length - success, -1 - failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_probe_req_ie(void *priv, const u8* ies, size_t ies_len)
{
	struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv;
#ifdef CONFIG_WPS
	TWscMode WscModeStruct;

        TI_CHECK_DRIVER( drv->driver_is_loaded, -1 );

	if ((!ies || (0 == ies_len)) && (NULL == drv->probe_req_ie)) {
		return 0;
	}

	if (ies && drv->probe_req_ie) {
		size_t len = wpabuf_len(drv->probe_req_ie);
		u8* data = (u8*)wpabuf_head(drv->probe_req_ie);
		if ((ies_len == len) && (0 == os_memcmp(ies, data, ies_len))) {
			return 0;
		}
	}

	os_memset(&WscModeStruct, 0, sizeof(TWscMode));

	if (!ies || (0 == ies_len)) {
		WscModeStruct.WSCMode = TIWLN_SIMPLE_CONFIG_OFF;
	} else {
		const size_t head_len = 6; /* probeReqIe head: dd xx 00 50 f2 04 */
		u8 *pos, *end;
		u16 password_id = 0;
		size_t min_len = 0;

		pos = (u8*)ies + head_len; /* Find the WSC mode in probe_req_ie by password_id */
		end = (u8*)ies + ies_len;
		while (pos < end) {
			if (ATTR_DEV_PASSWORD_ID == WPA_GET_BE16(pos)) {
				password_id = WPA_GET_BE16(pos+4);
				break;
			}
			pos += (4 + WPA_GET_BE16(pos+2));
		}
		WscModeStruct.WSCMode = (DEV_PW_PUSHBUTTON == password_id)?TIWLN_SIMPLE_CONFIG_PBC_METHOD:TIWLN_SIMPLE_CONFIG_PIN_METHOD;

		pos = (u8*)ies + head_len;
		min_len = ies_len - head_len;
		if (min_len > sizeof(WscModeStruct.probeReqWSCIE)) {
			min_len = sizeof(WscModeStruct.probeReqWSCIE);
		}
		os_memcpy(WscModeStruct.probeReqWSCIE, pos, min_len);
	}

	wpa_hexdump(MSG_DEBUG, "SetProbeReqIe:WscModeStruct", (u8*)&WscModeStruct, sizeof(TWscMode));
	if(0 == wpa_driver_tista_private_send(priv, SITE_MGR_SIMPLE_CONFIG_MODE, (void*)&WscModeStruct, sizeof(TWscMode), NULL, 0)) {
		/* Update the cached probe req ie */
		wpabuf_free(drv->probe_req_ie);
		drv->probe_req_ie = NULL;

		if (ies && ies_len) {
			drv->probe_req_ie = wpabuf_alloc(sizeof(WscModeStruct.probeReqWSCIE));
			if (drv->probe_req_ie) {
				wpabuf_put_data(drv->probe_req_ie, ies, ies_len);
			}
		}
	} else {
		wpa_printf(MSG_ERROR, "ERROR - Failed to set wsc mode!");
		return -1;
	}
#endif
	return 0;
}