diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index 8b43be438..b67249445 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -20,6 +20,7 @@ #include "common.h" #include "pcsc_funcs.h" #include "state_machine.h" +#include "ext_password.h" #include "crypto/crypto.h" #include "crypto/tls.h" #include "common/wpa_ctrl.h" @@ -93,6 +94,9 @@ static void eap_notify_status(struct eap_sm *sm, const char *status, static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) { + ext_password_free(sm->ext_pw_buf); + sm->ext_pw_buf = NULL; + if (sm->m == NULL || sm->eap_method_priv == NULL) return; @@ -1915,6 +1919,27 @@ const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) } +static int eap_get_ext_password(struct eap_sm *sm, + struct eap_peer_config *config) +{ + char *name; + + if (config->password == NULL) + return -1; + + name = os_zalloc(config->password_len + 1); + if (name == NULL) + return -1; + os_memcpy(name, config->password, config->password_len); + + ext_password_free(sm->ext_pw_buf); + sm->ext_pw_buf = ext_password_get(sm->ext_pw, name); + os_free(name); + + return sm->ext_pw_buf == NULL ? -1 : 0; +} + + /** * eap_get_config_password - Get password from the network configuration * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() @@ -1926,6 +1951,14 @@ const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len) struct eap_peer_config *config = eap_get_config(sm); if (config == NULL) return NULL; + + if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) { + if (eap_get_ext_password(sm, config) < 0) + return NULL; + *len = wpabuf_len(sm->ext_pw_buf); + return wpabuf_head(sm->ext_pw_buf); + } + *len = config->password_len; return config->password; } @@ -1945,6 +1978,14 @@ const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash) struct eap_peer_config *config = eap_get_config(sm); if (config == NULL) return NULL; + + if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) { + if (eap_get_ext_password(sm, config) < 0) + return NULL; + *len = wpabuf_len(sm->ext_pw_buf); + return wpabuf_head(sm->ext_pw_buf); + } + *len = config->password_len; if (hash) *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH); @@ -2256,3 +2297,11 @@ int eap_is_wps_pin_enrollee(struct eap_peer_config *conf) return 1; } + + +void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext) +{ + ext_password_free(sm->ext_pw_buf); + sm->ext_pw_buf = NULL; + sm->ext_pw = ext; +} diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h index 6e87475d3..cf58608c7 100644 --- a/src/eap_peer/eap.h +++ b/src/eap_peer/eap.h @@ -306,6 +306,9 @@ void eap_invalidate_cached_session(struct eap_sm *sm); int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf); int eap_is_wps_pin_enrollee(struct eap_peer_config *conf); +struct ext_password_data; +void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext); + #endif /* IEEE8021X_EAPOL */ #endif /* EAP_H */ diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h index a6f6f4cfc..a08543e11 100644 --- a/src/eap_peer/eap_config.h +++ b/src/eap_peer/eap_config.h @@ -619,6 +619,7 @@ struct eap_peer_config { int fragment_size; #define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0) +#define EAP_CONFIG_FLAGS_EXT_PASSWORD BIT(1) /** * flags - Network configuration flags (bitfield) * @@ -626,6 +627,8 @@ struct eap_peer_config { * for the network parameters. * bit 0 = password is represented as a 16-byte NtPasswordHash value * instead of plaintext password + * bit 1 = password is stored in external storage; the value in the + * password field is the name of that external entry */ u32 flags; }; diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h index 3318b8115..dd943174e 100644 --- a/src/eap_peer/eap_i.h +++ b/src/eap_peer/eap_i.h @@ -330,6 +330,9 @@ struct eap_sm { struct wps_context *wps; int prev_failure; + + struct ext_password_data *ext_pw; + struct wpabuf *ext_pw_buf; }; const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len); diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index 3b0a116bb..fb6c282a1 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -304,7 +304,9 @@ static void eap_mschapv2_password_changed(struct eap_sm *sm, "EAP-MSCHAPV2: Password changed successfully"); data->prev_error = 0; os_free(config->password); - if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { + if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) { + /* TODO: update external storage */ + } else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { config->password = os_malloc(16); config->password_len = 16; if (config->password) { diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index f0cae700d..2a8ef1a68 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -1,6 +1,6 @@ /* * EAPOL supplicant state machines - * Copyright (c) 2004-2008, Jouni Malinen + * Copyright (c) 2004-2012, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -1946,3 +1946,11 @@ void eapol_sm_deinit(struct eapol_sm *sm) os_free(sm->ctx); os_free(sm); } + + +void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, + struct ext_password_data *ext) +{ + if (sm && sm->eap) + eap_sm_set_ext_pw_ctx(sm->eap, ext); +} diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h index 1a20e4b98..b69dd9790 100644 --- a/src/eapol_supp/eapol_supp_sm.h +++ b/src/eapol_supp/eapol_supp_sm.h @@ -1,6 +1,6 @@ /* * EAPOL supplicant state machines - * Copyright (c) 2004-2008, Jouni Malinen + * Copyright (c) 2004-2012, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -243,6 +243,7 @@ struct eapol_ctx { struct eap_peer_config; +struct ext_password_data; #ifdef IEEE8021X_EAPOL struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx); @@ -275,6 +276,8 @@ void eapol_sm_request_reauth(struct eapol_sm *sm); void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm); void eapol_sm_invalidate_cached_session(struct eapol_sm *sm); const char * eapol_sm_get_method_name(struct eapol_sm *sm); +void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, + struct ext_password_data *ext); #else /* IEEE8021X_EAPOL */ static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) { @@ -366,6 +369,10 @@ static inline const char * eapol_sm_get_method_name(struct eapol_sm *sm) { return NULL; } +static inline void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, + struct ext_password_data *ext) +{ +} #endif /* IEEE8021X_EAPOL */ #endif /* EAPOL_SUPP_SM_H */ diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 70c28fe85..6573ba82c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1192,6 +1192,20 @@ static int wpa_config_parse_password(const struct parse_data *data, return 0; } +#ifdef CONFIG_EXT_PASSWORD + if (os_strncmp(value, "ext:", 4) == 0) { + char *name = os_strdup(value + 4); + if (name == NULL) + return -1; + os_free(ssid->eap.password); + ssid->eap.password = (u8 *) name; + ssid->eap.password_len = os_strlen(name); + ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; + ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD; + return 0; + } +#endif /* CONFIG_EXT_PASSWORD */ + if (os_strncmp(value, "hash:", 5) != 0) { char *tmp; size_t res_len; @@ -1209,6 +1223,7 @@ static int wpa_config_parse_password(const struct parse_data *data, ssid->eap.password = (u8 *) tmp; ssid->eap.password_len = res_len; ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; + ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD; return 0; } @@ -1237,6 +1252,7 @@ static int wpa_config_parse_password(const struct parse_data *data, ssid->eap.password = hash; ssid->eap.password_len = 16; ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH; + ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD; return 0; } @@ -1250,6 +1266,17 @@ static char * wpa_config_write_password(const struct parse_data *data, if (ssid->eap.password == NULL) return NULL; +#ifdef CONFIG_EXT_PASSWORD + if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) { + buf = os_zalloc(4 + ssid->eap.password_len + 1); + if (buf == NULL) + return NULL; + os_memcpy(buf, "ext:", 4); + os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len); + return buf; + } +#endif /* CONFIG_EXT_PASSWORD */ + if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) { return wpa_config_write_string( ssid->eap.password, ssid->eap.password_len); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 9f1cd00fb..1154aba3a 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -578,7 +578,8 @@ fast_reauth=1 # MSCHAP (EAP-MSCHAPv2, EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP). # EAP-PSK (128-bit PSK), EAP-PAX (128-bit PSK), and EAP-SAKE (256-bit # PSK) is also configured using this field. For EAP-GPSK, this is a -# variable length PSK. +# variable length PSK. ext: format can +# be used to indicate that the password is stored in external storage. # ca_cert: File path to CA certificate file (PEM/DER). This file can have one # or more trusted CA certificates. If ca_cert and ca_path are not # included, server certificate will not be verified. This is insecure and