Browse Source

Share EAP-TLS/PEAP/TTLS/FAST core process() functionality

Move the basic processing of received frames into eap_tls_common.c and use
callback functions to handle EAP type specific processing of the version
field and payload.
Jouni Malinen 17 years ago
parent
commit
cda97d11bb

+ 14 - 34
src/eap_server/eap_fast.c

@@ -1334,16 +1334,17 @@ static void eap_fast_process_phase2(struct eap_sm *sm,
 }
 
 
-static int eap_fast_process_version(struct eap_fast_data *data,
+static int eap_fast_process_version(struct eap_sm *sm, void *priv,
 				    int peer_version)
 {
+	struct eap_fast_data *data = priv;
+
 	data->peer_version = peer_version;
 
 	if (data->force_version >= 0 && peer_version != data->force_version) {
 		wpa_printf(MSG_INFO, "EAP-FAST: peer did not select the forced"
 			   " version (forced=%d peer=%d) - reject",
 			   data->force_version, peer_version);
-		eap_fast_state(data, FAILURE);
 		return -1;
 	}
 
@@ -1416,34 +1417,10 @@ static void eap_fast_process_phase2_start(struct eap_sm *sm,
 }
 
 
-static void eap_fast_process(struct eap_sm *sm, void *priv,
-			     struct wpabuf *respData)
+static void eap_fast_process_msg(struct eap_sm *sm, void *priv,
+				 const struct wpabuf *respData)
 {
 	struct eap_fast_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	int ret;
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData,
-			       &left);
-	if (pos == NULL || left < 1)
-		return;
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-FAST: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-
-	if (eap_fast_process_version(data, flags & EAP_TLS_VERSION_MASK))
-		return;
-
-	ret = eap_server_tls_reassemble(&data->ssl, flags, &pos, &left);
-	if (ret < 0) {
-		eap_fast_state(data, FAILURE);
-		return;
-	} else if (ret == 1)
-		return;
 
 	switch (data->state) {
 	case PHASE1:
@@ -1465,14 +1442,17 @@ static void eap_fast_process(struct eap_sm *sm, void *priv,
 			   data->state, __func__);
 		break;
 	}
+}
 
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-FAST: Locally detected fatal error "
-			   "in TLS processing");
-		eap_fast_state(data, FAILURE);
-	}
 
-	eap_server_tls_free_in_buf(&data->ssl);
+static void eap_fast_process(struct eap_sm *sm, void *priv,
+			     struct wpabuf *respData)
+{
+	struct eap_fast_data *data = priv;
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_FAST, eap_fast_process_version,
+				   eap_fast_process_msg) < 0)
+		eap_fast_state(data, FAILURE);
 }
 
 

+ 28 - 33
src/eap_server/eap_peap.c

@@ -1110,12 +1110,17 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
 static void eap_peap_process_phase2(struct eap_sm *sm,
 				    struct eap_peap_data *data,
 				    const struct wpabuf *respData,
-				    const u8 *in_data, size_t in_len)
+				    struct wpabuf *in_buf)
 {
 	struct wpabuf *in_decrypted;
 	int len_decrypted;
 	const struct eap_hdr *hdr;
 	size_t buf_len, len;
+	u8 *in_data;
+	size_t in_len;
+
+	in_data = wpabuf_mhead(in_buf);
+	in_len = wpabuf_len(in_buf);
 
 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
 		   " Phase 2", (unsigned long) in_len);
@@ -1332,32 +1337,17 @@ static int eap_peapv2_start_phase2(struct eap_sm *sm,
 }
 
 
-static void eap_peap_process(struct eap_sm *sm, void *priv,
-			     struct wpabuf *respData)
+static int eap_peap_process_version(struct eap_sm *sm, void *priv,
+				    int peer_version)
 {
 	struct eap_peap_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	int peer_version;
-	int ret;
 
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData,
-			       &left);
-	if (pos == NULL || left < 1)
-		return;
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-	data->recv_version = peer_version = flags & EAP_TLS_VERSION_MASK;
+	data->recv_version = peer_version;
 	if (data->force_version >= 0 && peer_version != data->force_version) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
 			   " version (forced=%d peer=%d) - reject",
 			   data->force_version, peer_version);
-		eap_peap_state(data, FAILURE);
-		return;
+		return -1;
 	}
 	if (peer_version < data->peap_version) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
@@ -1366,12 +1356,14 @@ static void eap_peap_process(struct eap_sm *sm, void *priv,
 		data->peap_version = peer_version;
 	}
 
-	ret = eap_server_tls_reassemble(&data->ssl, flags, &pos, &left);
-	if (ret < 0) {
-		eap_peap_state(data, FAILURE);
-		return;
-	} else if (ret == 1)
-		return;
+	return 0;
+}
+
+
+static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
+				 const struct wpabuf *respData)
+{
+	struct eap_peap_data *data = priv;
 
 	switch (data->state) {
 	case PHASE1:
@@ -1397,7 +1389,7 @@ static void eap_peap_process(struct eap_sm *sm, void *priv,
 	case PHASE2_METHOD:
 	case PHASE2_SOH:
 	case PHASE2_TLV:
-		eap_peap_process_phase2(sm, data, respData, pos, left);
+		eap_peap_process_phase2(sm, data, respData, data->ssl.in_buf);
 		break;
 	case SUCCESS_REQ:
 		eap_peap_state(data, SUCCESS);
@@ -1410,14 +1402,17 @@ static void eap_peap_process(struct eap_sm *sm, void *priv,
 			   data->state, __func__);
 		break;
 	}
+}
 
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error "
-			   "in TLS processing");
-		eap_peap_state(data, FAILURE);
-	}
 
-	eap_server_tls_free_in_buf(&data->ssl);
+static void eap_peap_process(struct eap_sm *sm, void *priv,
+			     struct wpabuf *respData)
+{
+	struct eap_peap_data *data = priv;
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_PEAP, eap_peap_process_version,
+				   eap_peap_process_msg) < 0)
+		eap_peap_state(data, FAILURE);
 }
 
 

+ 11 - 29
src/eap_server/eap_tls.c

@@ -129,41 +129,23 @@ static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
 }
 
 
-static void eap_tls_process(struct eap_sm *sm, void *priv,
-			    struct wpabuf *respData)
+static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
+				const struct wpabuf *respData)
 {
 	struct eap_tls_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	int ret;
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &left);
-	if (pos == NULL || left < 1)
-		return; /* Should not happen - frame already validated */
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-TLS: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-
-	ret = eap_server_tls_reassemble(&data->ssl, flags, &pos, &left);
-	if (ret < 0) {
-		data->state = FAILURE;
-		return;
-	} else if (ret == 1)
-		return;
-
 	if (eap_server_tls_phase1(sm, &data->ssl) < 0)
 		data->state = FAILURE;
+}
 
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-TLS: Locally detected fatal error "
-			   "in TLS processing");
-		data->state = FAILURE;
-	}
 
-	eap_server_tls_free_in_buf(&data->ssl);
+static void eap_tls_process(struct eap_sm *sm, void *priv,
+			    struct wpabuf *respData)
+{
+	struct eap_tls_data *data = priv;
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_TLS, NULL, eap_tls_process_msg) <
+	    0)
+		data->state = FAILURE;
 }
 
 

+ 50 - 3
src/eap_server/eap_tls_common.c

@@ -263,8 +263,8 @@ int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
 }
 
 
-int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
-			      const u8 **pos, size_t *left)
+static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
+				     const u8 **pos, size_t *left)
 {
 	unsigned int tls_msg_len = 0;
 	const u8 *end = *pos + *left;
@@ -323,7 +323,7 @@ int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
 }
 
 
-void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
+static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
 {
 	if (data->in_buf != &data->tmpbuf)
 		wpabuf_free(data->in_buf);
@@ -355,3 +355,50 @@ struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
 
 	return buf;
 }
+
+
+int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
+			   struct wpabuf *respData, void *priv, int eap_type,
+			   int (*proc_version)(struct eap_sm *sm, void *priv,
+					       int peer_version),
+			   void (*proc_msg)(struct eap_sm *sm, void *priv,
+					    const struct wpabuf *respData))
+{
+	const u8 *pos;
+	u8 flags;
+	size_t left;
+	int ret, res = 0;
+
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left);
+	if (pos == NULL || left < 1)
+		return 0; /* Should not happen - frame already validated */
+	flags = *pos++;
+	left--;
+	wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
+		   (unsigned long) wpabuf_len(respData), flags);
+
+	if (proc_version &&
+	    proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
+		return -1;
+
+	ret = eap_server_tls_reassemble(data, flags, &pos, &left);
+	if (ret < 0) {
+		res = -1;
+		goto done;
+	} else if (ret == 1)
+		return 0;
+
+	if (proc_msg)
+		proc_msg(sm, priv, respData);
+
+	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) {
+		wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
+			   "TLS processing");
+		res = -1;
+	}
+
+done:
+	eap_server_tls_free_in_buf(data);
+
+	return res;
+}

+ 6 - 3
src/eap_server/eap_tls_common.h

@@ -51,11 +51,14 @@ struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
 					 int eap_type, int version, u8 id);
 struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version);
 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data);
-int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
-			      const u8 **pos, size_t *left);
-void eap_server_tls_free_in_buf(struct eap_ssl_data *data);
 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
 				       struct eap_ssl_data *data,
 				       const u8 *plain, size_t plain_len);
+int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
+			   struct wpabuf *respData, void *priv, int eap_type,
+			   int (*proc_version)(struct eap_sm *sm, void *priv,
+					       int peer_version),
+			   void (*proc_msg)(struct eap_sm *sm, void *priv,
+					    const struct wpabuf *respData));
 
 #endif /* EAP_TLS_COMMON_H */

+ 21 - 38
src/eap_server/eap_ttls.c

@@ -1272,10 +1272,10 @@ static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
 }
 
 
-static void eap_ttls_process_version(struct eap_sm *sm,
-				     struct eap_ttls_data *data,
-				     int peer_version)
+static int eap_ttls_process_version(struct eap_sm *sm, void *priv,
+				    int peer_version)
 {
+	struct eap_ttls_data *data = priv;
 	if (peer_version < data->ttls_version) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
 			   "use version %d",
@@ -1287,41 +1287,19 @@ static void eap_ttls_process_version(struct eap_sm *sm,
 		if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) {
 			wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable "
 				   "TLS/IA");
-			eap_ttls_state(data, FAILURE);
-			return;
+			return -1;
 		}
 		data->tls_ia_configured = 1;
 	}
+
+	return 0;
 }
 
 
-static void eap_ttls_process(struct eap_sm *sm, void *priv,
-			     struct wpabuf *respData)
+static void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
+				 const struct wpabuf *respData)
 {
 	struct eap_ttls_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	int ret;
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData,
-			       &left);
-	if (pos == NULL || left < 1)
-		return;
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-
-	eap_ttls_process_version(sm, data, flags & EAP_TLS_VERSION_MASK);
-
-	ret = eap_server_tls_reassemble(&data->ssl, flags, &pos, &left);
-	if (ret < 0) {
-		eap_ttls_state(data, FAILURE);
-		return;
-	} else if (ret == 1)
-		return;
 
 	switch (data->state) {
 	case PHASE1:
@@ -1335,7 +1313,8 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv,
 		eap_ttls_start_tnc(sm, data);
 		break;
 	case PHASE2_MSCHAPV2_RESP:
-		if (data->mschapv2_resp_ok && left == 0) {
+		if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.in_buf) ==
+		    0) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
 				   "acknowledged response");
 			eap_ttls_state(data, data->ttls_version > 0 ?
@@ -1348,7 +1327,8 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv,
 			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "
 				   "frame from peer (payload len %lu, "
 				   "expected empty frame)",
-				   (unsigned long) left);
+				   (unsigned long)
+				   wpabuf_len(data->ssl.in_buf));
 			eap_ttls_state(data, FAILURE);
 		}
 		eap_ttls_start_tnc(sm, data);
@@ -1358,14 +1338,17 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv,
 			   data->state, __func__);
 		break;
 	}
+}
 
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-TTLS: Locally detected fatal error "
-			   "in TLS processing");
-		eap_ttls_state(data, FAILURE);
-	}
 
-	eap_server_tls_free_in_buf(&data->ssl);
+static void eap_ttls_process(struct eap_sm *sm, void *priv,
+			     struct wpabuf *respData)
+{
+	struct eap_ttls_data *data = priv;
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_TTLS, eap_ttls_process_version,
+				   eap_ttls_process_msg) < 0)
+		eap_ttls_state(data, FAILURE);
 }