Browse Source

Add UNAUTH-TLS vendor specific EAP type

This EAP type uses a vendor specific expanded EAP header to encapsulate
EAP-TLS with a configuration where the EAP server does not authenticate
the EAP peer. In other words, this method includes only server
authentication. The peer is configured with only the ca_cert parameter
(similarly to other TLS-based EAP methods). This method can be used for
cases where the network provides free access to anyone, but use of RSN
with a securely derived unique PMK for each station is desired.

The expanded EAP header uses the hostapd/wpa_supplicant vendor
code 39068 and vendor type 1 to identify the UNAUTH-TLS method.

Signed-hostap: Jouni Malinen <j@w1.fi>
Jouni Malinen 12 years ago
parent
commit
065d2895b4

+ 8 - 0
hostapd/Makefile

@@ -223,6 +223,14 @@ OBJS += ../src/eap_server/eap_server_tls.o
 TLS_FUNCS=y
 endif
 
+ifdef CONFIG_EAP_UNAUTH_TLS
+CFLAGS += -DEAP_SERVER_UNAUTH_TLS
+ifndef CONFIG_EAP_TLS
+OBJS += ../src/eap_server/eap_server_tls.o
+TLS_FUNCS=y
+endif
+endif
+
 ifdef CONFIG_EAP_PEAP
 CFLAGS += -DEAP_SERVER_PEAP
 OBJS += ../src/eap_server/eap_server_peap.o

+ 5 - 0
hostapd/eap_register.c

@@ -39,6 +39,11 @@ int eap_server_register_methods(void)
 		ret = eap_server_tls_register();
 #endif /* EAP_SERVER_TLS */
 
+#ifdef EAP_SERVER_UNAUTH_TLS
+	if (ret == 0)
+		ret = eap_server_unauth_tls_register();
+#endif /* EAP_SERVER_TLS */
+
 #ifdef EAP_SERVER_MSCHAPV2
 	if (ret == 0)
 		ret = eap_server_mschapv2_register();

+ 3 - 0
src/eap_common/eap_defs.h

@@ -75,6 +75,9 @@ enum {
 	EAP_VENDOR_HOSTAP = 39068 /* hostapd/wpa_supplicant project */
 };
 
+#define EAP_VENDOR_UNAUTH_TLS EAP_VENDOR_HOSTAP
+#define EAP_VENDOR_TYPE_UNAUTH_TLS 1
+
 #define EAP_MSK_LEN 64
 #define EAP_EMSK_LEN 64
 

+ 1 - 0
src/eap_peer/eap_methods.h

@@ -85,6 +85,7 @@ static inline int eap_peer_method_unload(struct eap_method *method)
 /* EAP peer method registration calls for statically linked in methods */
 int eap_peer_md5_register(void);
 int eap_peer_tls_register(void);
+int eap_peer_unauth_tls_register(void);
 int eap_peer_mschapv2_register(void);
 int eap_peer_peap_register(void);
 int eap_peer_ttls_register(void);

+ 66 - 5
src/eap_peer/eap_tls.c

@@ -22,6 +22,7 @@ struct eap_tls_data {
 	struct eap_ssl_data ssl;
 	u8 *key_data;
 	void *ssl_ctx;
+	u8 eap_type;
 };
 
 
@@ -62,8 +63,37 @@ static void * eap_tls_init(struct eap_sm *sm)
 		return NULL;
 	}
 
+	data->eap_type = EAP_TYPE_TLS;
+
+	return data;
+}
+
+
+#ifdef EAP_UNAUTH_TLS
+static void * eap_unauth_tls_init(struct eap_sm *sm)
+{
+	struct eap_tls_data *data;
+	struct eap_peer_config *config = eap_get_config(sm);
+
+	data = os_zalloc(sizeof(*data));
+	if (data == NULL)
+		return NULL;
+
+	data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
+		sm->ssl_ctx;
+
+	if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
+				  EAP_UNAUTH_TLS_TYPE)) {
+		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
+		eap_tls_deinit(sm, data);
+		return NULL;
+	}
+
+	data->eap_type = EAP_UNAUTH_TLS_TYPE;
+
 	return data;
 }
+#endif /* EAP_UNAUTH_TLS */
 
 
 static void eap_tls_deinit(struct eap_sm *sm, void *priv)
@@ -109,7 +139,7 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
 		return resp;
 	}
 
-	return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0);
+	return eap_peer_tls_build_ack(id, data->eap_type, 0);
 }
 
 
@@ -149,7 +179,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
 	const u8 *pos;
 	struct eap_tls_data *data = priv;
 
-	pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret,
+	pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
 					reqData, &left, &flags);
 	if (pos == NULL)
 		return NULL;
@@ -162,8 +192,8 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
 	}
 
 	resp = NULL;
-	res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id,
-					  pos, left, &resp);
+	res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0,
+					  id, pos, left, &resp);
 
 	if (res < 0) {
 		return eap_tls_failure(sm, data, ret, res, resp, id);
@@ -174,7 +204,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
 
 	if (res == 1) {
 		wpabuf_free(resp);
-		return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0);
+		return eap_peer_tls_build_ack(id, data->eap_type, 0);
 	}
 
 	return resp;
@@ -285,3 +315,34 @@ int eap_peer_tls_register(void)
 		eap_peer_method_free(eap);
 	return ret;
 }
+
+
+#ifdef EAP_UNAUTH_TLS
+int eap_peer_unauth_tls_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_UNAUTH_TLS,
+				    EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_unauth_tls_init;
+	eap->deinit = eap_tls_deinit;
+	eap->process = eap_tls_process;
+	eap->isKeyAvailable = eap_tls_isKeyAvailable;
+	eap->getKey = eap_tls_getKey;
+	eap->get_status = eap_tls_get_status;
+	eap->has_reauth_data = eap_tls_has_reauth_data;
+	eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
+	eap->init_for_reauth = eap_tls_init_for_reauth;
+	eap->get_emsk = eap_tls_get_emsk;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
+#endif /* EAP_UNAUTH_TLS */

+ 22 - 6
src/eap_peer/eap_tls_common.c

@@ -16,6 +16,18 @@
 #include "eap_config.h"
 
 
+static struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
+					 u8 code, u8 identifier)
+{
+	if (type == EAP_UNAUTH_TLS_TYPE)
+		return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
+				     EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
+				     code, identifier);
+	return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
+			     identifier);
+}
+
+
 static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
 			      const u8 **data, size_t *data_len)
 {
@@ -538,9 +550,8 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
 		length_included = 1;
 	}
 
-	*out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type,
-				  1 + length_included * 4 + len,
-				  EAP_CODE_RESPONSE, id);
+	*out_data = eap_tls_msg_alloc(eap_type, 1 + length_included * 4 + len,
+				      EAP_CODE_RESPONSE, id);
 	if (*out_data == NULL)
 		return -1;
 
@@ -678,8 +689,7 @@ struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type,
 {
 	struct wpabuf *resp;
 
-	resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_RESPONSE,
-			     id);
+	resp = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_RESPONSE, id);
 	if (resp == NULL)
 		return NULL;
 	wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)",
@@ -772,7 +782,13 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
 		return NULL;
 	}
 
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left);
+	if (eap_type == EAP_UNAUTH_TLS_TYPE)
+		pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
+				       EAP_VENDOR_TYPE_UNAUTH_TLS, reqData,
+				       &left);
+	else
+		pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData,
+				       &left);
 	if (pos == NULL) {
 		ret->ignore = TRUE;
 		return NULL;

+ 3 - 0
src/eap_peer/eap_tls_common.h

@@ -85,6 +85,9 @@ struct eap_ssl_data {
  /* could be up to 128 bytes, but only the first 64 bytes are used */
 #define EAP_TLS_KEY_LEN 64
 
+/* dummy type used as a flag for UNAUTH-TLS */
+#define EAP_UNAUTH_TLS_TYPE 255
+
 
 int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 			  struct eap_peer_config *config, u8 eap_type);

+ 1 - 0
src/eap_server/eap_methods.h

@@ -26,6 +26,7 @@ const char * eap_server_get_name(int vendor, EapType type);
 int eap_server_identity_register(void);
 int eap_server_md5_register(void);
 int eap_server_tls_register(void);
+int eap_server_unauth_tls_register(void);
 int eap_server_mschapv2_register(void);
 int eap_server_peap_register(void);
 int eap_server_tlv_register(void);

+ 69 - 7
src/eap_server/eap_server_tls.c

@@ -21,6 +21,7 @@ struct eap_tls_data {
 	struct eap_ssl_data ssl;
 	enum { START, CONTINUE, SUCCESS, FAILURE } state;
 	int established;
+	u8 eap_type;
 };
 
 
@@ -65,8 +66,32 @@ static void * eap_tls_init(struct eap_sm *sm)
 		return NULL;
 	}
 
+	data->eap_type = EAP_TYPE_TLS;
+
+	return data;
+}
+
+
+#ifdef EAP_SERVER_UNAUTH_TLS
+static void * eap_unauth_tls_init(struct eap_sm *sm)
+{
+	struct eap_tls_data *data;
+
+	data = os_zalloc(sizeof(*data));
+	if (data == NULL)
+		return NULL;
+	data->state = START;
+
+	if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
+		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
+		eap_tls_reset(sm, data);
+		return NULL;
+	}
+
+	data->eap_type = EAP_UNAUTH_TLS_TYPE;
 	return data;
 }
+#endif /* EAP_SERVER_UNAUTH_TLS */
 
 
 static void eap_tls_reset(struct eap_sm *sm, void *priv)
@@ -84,8 +109,7 @@ static struct wpabuf * eap_tls_build_start(struct eap_sm *sm,
 {
 	struct wpabuf *req;
 
-	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, 1, EAP_CODE_REQUEST,
-			    id);
+	req = eap_tls_msg_alloc(data->eap_type, 1, EAP_CODE_REQUEST, id);
 	if (req == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
 			   "request");
@@ -107,11 +131,11 @@ static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
 	struct wpabuf *res;
 
 	if (data->ssl.state == FRAG_ACK) {
-		return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0);
+		return eap_server_tls_build_ack(id, data->eap_type, 0);
 	}
 
 	if (data->ssl.state == WAIT_FRAG_ACK) {
-		res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0,
+		res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0,
 					       id);
 		goto check_established;
 	}
@@ -129,7 +153,7 @@ static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
 		return NULL;
 	}
 
-	res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id);
+	res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0, id);
 
 check_established:
 	if (data->established && data->ssl.state != WAIT_FRAG_ACK) {
@@ -146,10 +170,17 @@ check_established:
 static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
 			     struct wpabuf *respData)
 {
+	struct eap_tls_data *data = priv;
 	const u8 *pos;
 	size_t len;
 
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &len);
+	if (data->eap_type == EAP_UNAUTH_TLS_TYPE)
+		pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
+				       EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
+				       &len);
+	else
+		pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_type,
+				       respData, &len);
 	if (pos == NULL || len < 1) {
 		wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
 		return TRUE;
@@ -178,7 +209,7 @@ static void eap_tls_process(struct eap_sm *sm, void *priv,
 {
 	struct eap_tls_data *data = priv;
 	if (eap_server_tls_process(sm, &data->ssl, respData, data,
-				   EAP_TYPE_TLS, NULL, eap_tls_process_msg) <
+				   data->eap_type, NULL, eap_tls_process_msg) <
 	    0)
 		eap_tls_state(data, FAILURE);
 }
@@ -278,3 +309,34 @@ int eap_server_tls_register(void)
 		eap_server_method_free(eap);
 	return ret;
 }
+
+
+#ifdef EAP_SERVER_UNAUTH_TLS
+int eap_server_unauth_tls_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
+				      EAP_VENDOR_UNAUTH_TLS,
+				      EAP_VENDOR_TYPE_UNAUTH_TLS,
+				      "UNAUTH-TLS");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_unauth_tls_init;
+	eap->reset = eap_tls_reset;
+	eap->buildReq = eap_tls_buildReq;
+	eap->check = eap_tls_check;
+	eap->process = eap_tls_process;
+	eap->isDone = eap_tls_isDone;
+	eap->getKey = eap_tls_getKey;
+	eap->isSuccess = eap_tls_isSuccess;
+	eap->get_emsk = eap_tls_get_emsk;
+
+	ret = eap_server_method_register(eap);
+	if (ret)
+		eap_server_method_free(eap);
+	return ret;
+}
+#endif /* EAP_SERVER_UNAUTH_TLS */

+ 21 - 5
src/eap_server/eap_server_tls_common.c

@@ -18,6 +18,18 @@
 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data);
 
 
+struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
+				  u8 code, u8 identifier)
+{
+	if (type == EAP_UNAUTH_TLS_TYPE)
+		return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
+				     EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
+				     code, identifier);
+	return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
+			     identifier);
+}
+
+
 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 			    int verify_peer)
 {
@@ -131,8 +143,7 @@ struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
 		plen += 4;
 
-	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen,
-			    EAP_CODE_REQUEST, id);
+	req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id);
 	if (req == NULL)
 		return NULL;
 
@@ -168,8 +179,7 @@ struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
 {
 	struct wpabuf *req;
 
-	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST,
-			    id);
+	req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id);
 	if (req == NULL)
 		return NULL;
 	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
@@ -359,7 +369,13 @@ int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
 	size_t left;
 	int ret, res = 0;
 
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left);
+	if (eap_type == EAP_UNAUTH_TLS_TYPE)
+		pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
+				       EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
+				       &left);
+	else
+		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++;

+ 5 - 0
src/eap_server/eap_tls_common.h

@@ -62,7 +62,12 @@ struct eap_ssl_data {
  /* could be up to 128 bytes, but only the first 64 bytes are used */
 #define EAP_TLS_KEY_LEN 64
 
+/* dummy type used as a flag for UNAUTH-TLS */
+#define EAP_UNAUTH_TLS_TYPE 255
 
+
+struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
+				  u8 code, u8 identifier);
 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 			    int verify_peer);
 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);

+ 11 - 0
wpa_supplicant/Makefile

@@ -306,6 +306,17 @@ TLS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
+ifdef CONFIG_EAP_UNAUTH_TLS
+# EAP-UNAUTH-TLS
+CFLAGS += -DEAP_UNAUTH_TLS
+ifndef CONFIG_EAP_UNAUTH_TLS
+OBJS += ../src/eap_peer/eap_tls.o
+OBJS_h += ../src/eap_server/eap_server_tls.o
+TLS_FUNCS=y
+endif
+CONFIG_IEEE8021X_EAPOL=y
+endif
+
 ifdef CONFIG_EAP_PEAP
 # EAP-PEAP
 ifeq ($(CONFIG_EAP_PEAP), dyn)

+ 10 - 0
wpa_supplicant/eap_register.c

@@ -35,6 +35,11 @@ int eap_register_methods(void)
 		ret = eap_peer_tls_register();
 #endif /* EAP_TLS */
 
+#ifdef EAP_UNAUTH_TLS
+	if (ret == 0)
+		ret = eap_peer_unauth_tls_register();
+#endif /* EAP_UNAUTH_TLS */
+
 #ifdef EAP_MSCHAPv2
 	if (ret == 0)
 		ret = eap_peer_mschapv2_register();
@@ -145,6 +150,11 @@ int eap_register_methods(void)
 		ret = eap_server_tls_register();
 #endif /* EAP_SERVER_TLS */
 
+#ifdef EAP_SERVER_UNAUTH_TLS
+	if (ret == 0)
+		ret = eap_server_unauth_tls_register();
+#endif /* EAP_SERVER_UNAUTH_TLS */
+
 #ifdef EAP_SERVER_MSCHAPV2
 	if (ret == 0)
 		ret = eap_server_mschapv2_register();