/*
* 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"
* @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;
{
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);
eapol_set_bool(sm, EAPOL_eapResp, FALSE);
eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
sm->num_rounds = 0;
+ sm->prev_failure = 0;
}
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
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
"EAP authentication failed");
+
+ sm->prev_failure = 1;
}
}
+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
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 "
}
+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()
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;
+}