EXT PW: Add support for password parameter from external storage

This allows the password parameter for EAP methods to be fetched
from an external storage.

Following example can be used for developer testing:

ext_password_backend=test:pw1=password|pw2=testing

network={
    key_mgmt=WPA-EAP
    eap=TTLS
    identity="user"
    password=ext:pw1
    ca_cert="ca.pem"
    phase2="auth=PAP"
}

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-08-03 21:47:31 +03:00
parent 9173b16fd1
commit 0ebb23e340
9 changed files with 107 additions and 4 deletions

View file

@ -20,6 +20,7 @@
#include "common.h" #include "common.h"
#include "pcsc_funcs.h" #include "pcsc_funcs.h"
#include "state_machine.h" #include "state_machine.h"
#include "ext_password.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/tls.h" #include "crypto/tls.h"
#include "common/wpa_ctrl.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) 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) if (sm->m == NULL || sm->eap_method_priv == NULL)
return; 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 * eap_get_config_password - Get password from the network configuration
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @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); struct eap_peer_config *config = eap_get_config(sm);
if (config == NULL) if (config == NULL)
return 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; *len = config->password_len;
return config->password; 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); struct eap_peer_config *config = eap_get_config(sm);
if (config == NULL) if (config == NULL)
return 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; *len = config->password_len;
if (hash) if (hash)
*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH); *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; 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;
}

View file

@ -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_pbc_enrollee(struct eap_peer_config *conf);
int eap_is_wps_pin_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 /* IEEE8021X_EAPOL */
#endif /* EAP_H */ #endif /* EAP_H */

View file

@ -619,6 +619,7 @@ struct eap_peer_config {
int fragment_size; int fragment_size;
#define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0) #define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0)
#define EAP_CONFIG_FLAGS_EXT_PASSWORD BIT(1)
/** /**
* flags - Network configuration flags (bitfield) * flags - Network configuration flags (bitfield)
* *
@ -626,6 +627,8 @@ struct eap_peer_config {
* for the network parameters. * for the network parameters.
* bit 0 = password is represented as a 16-byte NtPasswordHash value * bit 0 = password is represented as a 16-byte NtPasswordHash value
* instead of plaintext password * 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; u32 flags;
}; };

View file

@ -330,6 +330,9 @@ struct eap_sm {
struct wps_context *wps; struct wps_context *wps;
int prev_failure; 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); const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len);

View file

@ -304,7 +304,9 @@ static void eap_mschapv2_password_changed(struct eap_sm *sm,
"EAP-MSCHAPV2: Password changed successfully"); "EAP-MSCHAPV2: Password changed successfully");
data->prev_error = 0; data->prev_error = 0;
os_free(config->password); 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 = os_malloc(16);
config->password_len = 16; config->password_len = 16;
if (config->password) { if (config->password) {

View file

@ -1,6 +1,6 @@
/* /*
* EAPOL supplicant state machines * EAPOL supplicant state machines
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -1946,3 +1946,11 @@ void eapol_sm_deinit(struct eapol_sm *sm)
os_free(sm->ctx); os_free(sm->ctx);
os_free(sm); 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);
}

View file

@ -1,6 +1,6 @@
/* /*
* EAPOL supplicant state machines * EAPOL supplicant state machines
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -243,6 +243,7 @@ struct eapol_ctx {
struct eap_peer_config; struct eap_peer_config;
struct ext_password_data;
#ifdef IEEE8021X_EAPOL #ifdef IEEE8021X_EAPOL
struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx); 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_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm);
void eapol_sm_invalidate_cached_session(struct eapol_sm *sm); void eapol_sm_invalidate_cached_session(struct eapol_sm *sm);
const char * eapol_sm_get_method_name(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 */ #else /* IEEE8021X_EAPOL */
static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) 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; return NULL;
} }
static inline void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
struct ext_password_data *ext)
{
}
#endif /* IEEE8021X_EAPOL */ #endif /* IEEE8021X_EAPOL */
#endif /* EAPOL_SUPP_SM_H */ #endif /* EAPOL_SUPP_SM_H */

View file

@ -1192,6 +1192,20 @@ static int wpa_config_parse_password(const struct parse_data *data,
return 0; 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) { if (os_strncmp(value, "hash:", 5) != 0) {
char *tmp; char *tmp;
size_t res_len; 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 = (u8 *) tmp;
ssid->eap.password_len = res_len; ssid->eap.password_len = res_len;
ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
return 0; return 0;
} }
@ -1237,6 +1252,7 @@ static int wpa_config_parse_password(const struct parse_data *data,
ssid->eap.password = hash; ssid->eap.password = hash;
ssid->eap.password_len = 16; ssid->eap.password_len = 16;
ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH; ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
return 0; return 0;
} }
@ -1250,6 +1266,17 @@ static char * wpa_config_write_password(const struct parse_data *data,
if (ssid->eap.password == NULL) if (ssid->eap.password == NULL)
return 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)) { if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
return wpa_config_write_string( return wpa_config_write_string(
ssid->eap.password, ssid->eap.password_len); ssid->eap.password, ssid->eap.password_len);

View file

@ -578,7 +578,8 @@ fast_reauth=1
# MSCHAP (EAP-MSCHAPv2, EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP). # 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 # 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 # PSK) is also configured using this field. For EAP-GPSK, this is a
# variable length PSK. # variable length PSK. ext:<name of external password field> 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 # 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 # or more trusted CA certificates. If ca_cert and ca_path are not
# included, server certificate will not be verified. This is insecure and # included, server certificate will not be verified. This is insecure and