EXT PW: Add support for password parameter from external storage
authorJouni Malinen <j@w1.fi>
Fri, 3 Aug 2012 18:47:31 +0000 (21:47 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 3 Aug 2012 19:15:42 +0000 (22:15 +0300)
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>

src/eap_peer/eap.c
src/eap_peer/eap.h
src/eap_peer/eap_config.h
src/eap_peer/eap_i.h
src/eap_peer/eap_mschapv2.c
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h
wpa_supplicant/config.c
wpa_supplicant/wpa_supplicant.conf

index 8b43be4..b672494 100644 (file)
@@ -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;
+}
index 6e87475..cf58608 100644 (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_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 */
index a6f6f4c..a08543e 100644 (file)
@@ -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;
 };
index 3318b81..dd94317 100644 (file)
@@ -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);
index 3b0a116..fb6c282 100644 (file)
@@ -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) {
index f0cae70..2a8ef1a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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.
  * 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);
+}
index 1a20e4b..b69dd97 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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.
  * 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 */
index 70c28fe..6573ba8 100644 (file)
@@ -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);
index 9f1cd00..1154aba 100644 (file)
@@ -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:<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
 #      or more trusted CA certificates. If ca_cert and ca_path are not
 #      included, server certificate will not be verified. This is insecure and