Updated to hostap_2_6
[mech_eap.git] / libeap / src / eap_peer / eap_tls.c
index 66a027a..ca2354f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * EAP peer method: EAP-TLS (RFC 2716)
- * Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -25,6 +25,7 @@ struct eap_tls_data {
        size_t id_len;
        void *ssl_ctx;
        u8 eap_type;
+       struct wpabuf *pending_resp;
 };
 
 
@@ -142,6 +143,7 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv)
        eap_peer_tls_ssl_deinit(sm, &data->ssl);
        eap_tls_free_key(data);
        os_free(data->session_id);
+       wpabuf_free(data->pending_resp);
        os_free(data);
 }
 
@@ -216,6 +218,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
        struct eap_tls_data *data = priv;
        struct wpabuf msg;
 
+       if (sm->waiting_ext_cert_check && data->pending_resp) {
+               struct eap_peer_config *config = eap_get_config(sm);
+
+               if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
+                       wpa_printf(MSG_DEBUG,
+                                  "EAP-TLS: External certificate check succeeded - continue handshake");
+                       resp = data->pending_resp;
+                       data->pending_resp = NULL;
+                       sm->waiting_ext_cert_check = 0;
+                       return resp;
+               }
+
+               if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
+                       wpa_printf(MSG_DEBUG,
+                                  "EAP-TLS: External certificate check failed - force authentication failure");
+                       ret->methodState = METHOD_DONE;
+                       ret->decision = DECISION_FAIL;
+                       sm->waiting_ext_cert_check = 0;
+                       return NULL;
+               }
+
+               wpa_printf(MSG_DEBUG,
+                          "EAP-TLS: Continuing to wait external server certificate validation");
+               return NULL;
+       }
+
        pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
                                        reqData, &left, &flags);
        if (pos == NULL)
@@ -237,6 +265,14 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
                return eap_tls_failure(sm, data, ret, res, resp, id);
        }
 
+       if (sm->waiting_ext_cert_check) {
+               wpa_printf(MSG_DEBUG,
+                          "EAP-TLS: Waiting external server certificate validation");
+               wpabuf_free(data->pending_resp);
+               data->pending_resp = resp;
+               return NULL;
+       }
+
        if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
                eap_tls_success(sm, data, ret);
 
@@ -258,6 +294,10 @@ static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
 
 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
 {
+       struct eap_tls_data *data = priv;
+
+       wpabuf_free(data->pending_resp);
+       data->pending_resp = NULL;
 }
 
 
@@ -350,7 +390,6 @@ static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
 int eap_peer_tls_register(void)
 {
        struct eap_method *eap;
-       int ret;
 
        eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
                                    EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
@@ -369,10 +408,7 @@ int eap_peer_tls_register(void)
        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;
+       return eap_peer_method_register(eap);
 }
 
 
@@ -380,7 +416,6 @@ int eap_peer_tls_register(void)
 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,
@@ -399,10 +434,7 @@ int eap_peer_unauth_tls_register(void)
        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;
+       return eap_peer_method_register(eap);
 }
 #endif /* EAP_UNAUTH_TLS */
 
@@ -411,7 +443,6 @@ int eap_peer_unauth_tls_register(void)
 int eap_peer_wfa_unauth_tls_register(void)
 {
        struct eap_method *eap;
-       int ret;
 
        eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
                                    EAP_VENDOR_WFA_NEW,
@@ -431,9 +462,6 @@ int eap_peer_wfa_unauth_tls_register(void)
        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;
+       return eap_peer_method_register(eap);
 }
 #endif /* CONFIG_HS20 */