]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add UNAUTH-TLS vendor specific EAP type
authorJouni Malinen <j@w1.fi>
Wed, 22 Aug 2012 19:34:11 +0000 (22:34 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 22 Aug 2012 19:34:11 +0000 (22:34 +0300)
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>

13 files changed:
hostapd/Makefile
hostapd/eap_register.c
src/eap_common/eap_defs.h
src/eap_peer/eap_methods.h
src/eap_peer/eap_tls.c
src/eap_peer/eap_tls_common.c
src/eap_peer/eap_tls_common.h
src/eap_server/eap_methods.h
src/eap_server/eap_server_tls.c
src/eap_server/eap_server_tls_common.c
src/eap_server/eap_tls_common.h
wpa_supplicant/Makefile
wpa_supplicant/eap_register.c

index 420bc5b67e8add601a82c2ca2bea6be6a7b2c2e4..6809b0766a528f5234708100af74cea63191f5b5 100644 (file)
@@ -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
index 089c7b23a923ef1116f0dd308772ad5efe8f1af4..0a7ff918885d926858622a9a2c4a7a86e839e13e 100644 (file)
@@ -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();
index 4047e04c9ad4f8d3f8a763ee1b51a27229ce3dca..0d247c4d13a7256124f6a055d7837d3a74796ba9 100644 (file)
@@ -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
 
index ff9f50db30d4212261dd7e3736e49e57fac4ad4c..4994ff1cd9a0ce94f5b88bd6d1400f83b7378931 100644 (file)
@@ -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);
index 1dd0e94f2376a53e8db896e704d93651b5aae878..061a72b10a542d7971c7ab82581d458c4fbbb9bc 100644 (file)
@@ -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 */
index 33f2f27bed735a8efcb2b183e16f9956717c014e..7eefe8c93558867e7bf8adeb8e9dd4052c7bbddb 100644 (file)
 #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;
index 58c44ac2e32b30cc8fee4ced94f7dd99b33580b7..91d3a25a0ec97dbc8b59461bd98bfbd549972c08 100644 (file)
@@ -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);
index 9667cf472593f1d989767c5af74239941977751d..bc810a9b815c8a7c5df2a6ce7bcc2708bc9479f6 100644 (file)
@@ -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);
index d34ef41c5cc719053d22f20aa1c9333e079761e7..447f47cfa00a818ec6f214385ed0f27ceaf9713b 100644 (file)
@@ -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 */
index 88a410de7cfd947a989e37842cc51df28a405779..31be2ecb8976f024302fcfa06b6bbdfa3faf38a5 100644 (file)
 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++;
index 31fe503fc954a00371aa21e3fca8700d1f5528a2..11f5827513ab25fe65d793495972a28b536f8d53 100644 (file)
@@ -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);
index eb64725d97f7687958ee72873ae5b49b1cf7863f..4b399dfcd993cad1204c158882222ece05307570 100644 (file)
@@ -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)
index c220aec479dd2a595319e949b9f02d90fc43d19f..d1eb4ff3b0a6f50d5c56c340d3badc4210458408 100644 (file)
@@ -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();