automake build system
[mech_eap.orig] / src / eap_peer / eap.c
index e518ec3..482934a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * EAP peer state machines (RFC 4137)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include "includes.h"
 
 #include "common.h"
-#include "eap_i.h"
-#include "eap_config.h"
-#include "tls.h"
-#include "crypto.h"
 #include "pcsc_funcs.h"
-#include "wpa_ctrl.h"
 #include "state_machine.h"
+#include "crypto/crypto.h"
+#include "crypto/tls.h"
+#include "common/wpa_ctrl.h"
+#include "eap_common/eap_wsc_common.h"
+#include "eap_i.h"
+#include "eap_config.h"
 
 #define STATE_MACHINE_DATA struct eap_sm
 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
@@ -105,7 +106,7 @@ static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
  * @method: EAP type
  * Returns: 1 = allowed EAP method, 0 = not allowed
  */
-static int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
+int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
 {
        struct eap_peer_config *config = eap_get_config(sm);
        int i;
@@ -133,7 +134,8 @@ SM_STATE(EAP, INITIALIZE)
 {
        SM_ENTRY(EAP, INITIALIZE);
        if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
-           sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
+           sm->m->has_reauth_data(sm, sm->eap_method_priv) &&
+           !sm->prev_failure) {
                wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
                           "fast reauthentication");
                sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
@@ -164,6 +166,7 @@ SM_STATE(EAP, INITIALIZE)
        eapol_set_bool(sm, EAPOL_eapResp, FALSE);
        eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
        sm->num_rounds = 0;
+       sm->prev_failure = 0;
 }
 
 
@@ -225,9 +228,15 @@ SM_STATE(EAP, GET_METHOD)
        if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
                wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
                           sm->reqVendor, method);
+               wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+                       "vendor=%u method=%u -> NAK",
+                       sm->reqVendor, method);
                goto nak;
        }
 
+       wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+               "vendor=%u method=%u", sm->reqVendor, method);
+
        /*
         * RFC 4137 does not define specific operation for fast
         * re-authentication (session resumption). The design here is to allow
@@ -504,6 +513,8 @@ SM_STATE(EAP, FAILURE)
 
        wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
                "EAP authentication failed");
+
+       sm->prev_failure = 1;
 }
 
 
@@ -1149,6 +1160,60 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
 }
 
 
+static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
+                                 union tls_event_data *data)
+{
+       struct eap_sm *sm = ctx;
+       char *hash_hex = NULL;
+       char *cert_hex = NULL;
+
+       switch (ev) {
+       case TLS_CERT_CHAIN_FAILURE:
+               wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
+                       "reason=%d depth=%d subject='%s' err='%s'",
+                       data->cert_fail.reason,
+                       data->cert_fail.depth,
+                       data->cert_fail.subject,
+                       data->cert_fail.reason_txt);
+               break;
+       case TLS_PEER_CERTIFICATE:
+               if (data->peer_cert.hash) {
+                       size_t len = data->peer_cert.hash_len * 2 + 1;
+                       hash_hex = os_malloc(len);
+                       if (hash_hex) {
+                               wpa_snprintf_hex(hash_hex, len,
+                                                data->peer_cert.hash,
+                                                data->peer_cert.hash_len);
+                       }
+               }
+               wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
+                       "depth=%d subject='%s'%s%s",
+                       data->peer_cert.depth, data->peer_cert.subject,
+                       hash_hex ? " hash=" : "", hash_hex ? hash_hex : "");
+
+               if (data->peer_cert.cert) {
+                       size_t len = wpabuf_len(data->peer_cert.cert) * 2 + 1;
+                       cert_hex = os_malloc(len);
+                       if (cert_hex == NULL)
+                               break;
+                       wpa_snprintf_hex(cert_hex, len,
+                                        wpabuf_head(data->peer_cert.cert),
+                                        wpabuf_len(data->peer_cert.cert));
+                       wpa_msg_ctrl(sm->msg_ctx, MSG_INFO,
+                                    WPA_EVENT_EAP_PEER_CERT
+                                    "depth=%d subject='%s' cert=%s",
+                                    data->peer_cert.depth,
+                                    data->peer_cert.subject,
+                                    cert_hex);
+               }
+               break;
+       }
+
+       os_free(hash_hex);
+       os_free(cert_hex);
+}
+
+
 /**
  * eap_peer_sm_init - Allocate and initialize EAP peer state machine
  * @eapol_ctx: Context data to be used with eapol_cb calls
@@ -1177,13 +1242,17 @@ struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
        sm->eapol_cb = eapol_cb;
        sm->msg_ctx = msg_ctx;
        sm->ClientTimeout = 60;
-       if (conf->mac_addr)
-               os_memcpy(sm->mac_addr, conf->mac_addr, ETH_ALEN);
+       sm->wps = conf->wps;
 
        os_memset(&tlsconf, 0, sizeof(tlsconf));
        tlsconf.opensc_engine_path = conf->opensc_engine_path;
        tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
        tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
+#ifdef CONFIG_FIPS
+       tlsconf.fips_mode = 1;
+#endif /* CONFIG_FIPS */
+       tlsconf.event_cb = eap_peer_sm_tls_event;
+       tlsconf.cb_ctx = sm;
        sm->ssl_ctx = tls_init(&tlsconf);
        if (sm->ssl_ctx == NULL) {
                wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
@@ -1854,6 +1923,15 @@ const char * eap_get_config_phase2(struct eap_sm *sm)
 }
 
 
+int eap_get_config_fragment_size(struct eap_sm *sm)
+{
+       struct eap_peer_config *config = eap_get_config(sm);
+       if (config == NULL)
+               return -1;
+       return config->fragment_size;
+}
+
+
 /**
  * eap_key_available - Get key availability (eapKeyAvailable variable)
  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
@@ -2043,3 +2121,29 @@ void eap_invalidate_cached_session(struct eap_sm *sm)
        if (sm)
                eap_deinit_prev_method(sm, "invalidate");
 }
+
+
+int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf)
+{
+       if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
+           os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
+               return 0; /* Not a WPS Enrollee */
+
+       if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL)
+               return 0; /* Not using PBC */
+
+       return 1;
+}
+
+
+int eap_is_wps_pin_enrollee(struct eap_peer_config *conf)
+{
+       if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
+           os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
+               return 0; /* Not a WPS Enrollee */
+
+       if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL)
+               return 0; /* Not using PIN */
+
+       return 1;
+}