Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / src / eap_server / eap_server_mschapv2.c
index 39d1c6e..98d74e0 100644 (file)
@@ -2,20 +2,15 @@
  * hostapd / EAP-MSCHAPv2 (draft-kamath-pppext-eap-mschapv2-00.txt) server
  * Copyright (c) 2004-2007, 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
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "includes.h"
 
 #include "common.h"
 #include "crypto/ms_funcs.h"
+#include "crypto/random.h"
 #include "eap_i.h"
 
 
@@ -96,7 +91,7 @@ static void eap_mschapv2_reset(struct eap_sm *sm, void *priv)
                return;
 
        os_free(data->peer_challenge);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -105,18 +100,17 @@ static struct wpabuf * eap_mschapv2_build_challenge(
 {
        struct wpabuf *req;
        struct eap_mschapv2_hdr *ms;
-       char *name = "hostapd"; /* TODO: make this configurable */
        size_t ms_len;
 
        if (!data->auth_challenge_from_tls &&
-           os_get_random(data->auth_challenge, CHALLENGE_LEN)) {
+           random_get_bytes(data->auth_challenge, CHALLENGE_LEN)) {
                wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to get random "
                           "data");
                data->state = FAILURE;
                return NULL;
        }
 
-       ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + os_strlen(name);
+       ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
        req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
                            EAP_CODE_REQUEST, id);
        if (req == NULL) {
@@ -138,7 +132,7 @@ static struct wpabuf * eap_mschapv2_build_challenge(
                wpabuf_put(req, CHALLENGE_LEN);
        wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
                    data->auth_challenge, CHALLENGE_LEN);
-       wpabuf_put_data(req, name, os_strlen(name));
+       wpabuf_put_data(req, sm->server_id, sm->server_id_len);
 
        return req;
 }
@@ -296,6 +290,7 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
        const u8 *username, *user;
        size_t username_len, user_len;
        int res;
+       char *buf;
 
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
                               &len);
@@ -335,6 +330,13 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
        wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags);
        wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len);
 
+       buf = os_malloc(name_len * 4 + 1);
+       if (buf) {
+               printf_encode(buf, name_len * 4 + 1, name, name_len);
+               eap_log_msg(sm, "EAP-MSCHAPV2 Name '%s'", buf);
+               os_free(buf);
+       }
+
        /* MSCHAPv2 does not include optional domain name in the
         * challenge-response calculation, so remove domain prefix
         * (if present). */
@@ -358,6 +360,19 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
                }
        }
 
+#ifdef CONFIG_TESTING_OPTIONS
+       {
+               u8 challenge[8];
+
+               if (challenge_hash(peer_challenge, data->auth_challenge,
+                                  username, username_len, challenge) == 0) {
+                       eap_server_mschap_rx_callback(sm, "EAP-MSCHAPV2",
+                                                     username, username_len,
+                                                     challenge, nt_response);
+               }
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
+
        if (username_len != user_len ||
            os_memcmp(username, user, username_len) != 0) {
                wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names");
@@ -391,7 +406,7 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
                return;
        }
 
-       if (os_memcmp(nt_response, expected, 24) == 0) {
+       if (os_memcmp_const(nt_response, expected, 24) == 0) {
                const u8 *pw_hash;
                u8 pw_hash_buf[16], pw_hash_hash[16];
 
@@ -404,18 +419,24 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
                if (sm->user->password_hash) {
                        pw_hash = sm->user->password;
                } else {
-                       nt_password_hash(sm->user->password,
-                                        sm->user->password_len,
-                                        pw_hash_buf);
+                       if (nt_password_hash(sm->user->password,
+                                            sm->user->password_len,
+                                            pw_hash_buf) < 0) {
+                               data->state = FAILURE;
+                               return;
+                       }
                        pw_hash = pw_hash_buf;
                }
-               generate_authenticator_response_pwhash(
-                       pw_hash, peer_challenge, data->auth_challenge,
-                       username, username_len, nt_response,
-                       data->auth_response);
-
-               hash_nt_password_hash(pw_hash, pw_hash_hash);
-               get_master_key(pw_hash_hash, nt_response, data->master_key);
+               if (generate_authenticator_response_pwhash(
+                           pw_hash, peer_challenge, data->auth_challenge,
+                           username, username_len, nt_response,
+                           data->auth_response) < 0 ||
+                   hash_nt_password_hash(pw_hash, pw_hash_hash) < 0 ||
+                   get_master_key(pw_hash_hash, nt_response,
+                                  data->master_key)) {
+                       data->state = FAILURE;
+                       return;
+               }
                data->master_key_valid = 1;
                wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key",
                                data->master_key, MSCHAPV2_KEY_LEN);