LCOV - code coverage report
Current view: top level - src/eap_server - eap_server_mschapv2.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 229 276 83.0 %
Date: 2016-10-02 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / EAP-MSCHAPv2 (draft-kamath-pppext-eap-mschapv2-00.txt) server
       3             :  * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "crypto/ms_funcs.h"
      13             : #include "crypto/random.h"
      14             : #include "eap_i.h"
      15             : 
      16             : 
      17             : struct eap_mschapv2_hdr {
      18             :         u8 op_code; /* MSCHAPV2_OP_* */
      19             :         u8 mschapv2_id; /* must be changed for challenges, but not for
      20             :                          * success/failure */
      21             :         u8 ms_length[2]; /* Note: misaligned; length - 5 */
      22             :         /* followed by data */
      23             : } STRUCT_PACKED;
      24             : 
      25             : #define MSCHAPV2_OP_CHALLENGE 1
      26             : #define MSCHAPV2_OP_RESPONSE 2
      27             : #define MSCHAPV2_OP_SUCCESS 3
      28             : #define MSCHAPV2_OP_FAILURE 4
      29             : #define MSCHAPV2_OP_CHANGE_PASSWORD 7
      30             : 
      31             : #define MSCHAPV2_RESP_LEN 49
      32             : 
      33             : #define ERROR_RESTRICTED_LOGON_HOURS 646
      34             : #define ERROR_ACCT_DISABLED 647
      35             : #define ERROR_PASSWD_EXPIRED 648
      36             : #define ERROR_NO_DIALIN_PERMISSION 649
      37             : #define ERROR_AUTHENTICATION_FAILURE 691
      38             : #define ERROR_CHANGING_PASSWORD 709
      39             : 
      40             : #define PASSWD_CHANGE_CHAL_LEN 16
      41             : #define MSCHAPV2_KEY_LEN 16
      42             : 
      43             : 
      44             : #define CHALLENGE_LEN 16
      45             : 
      46             : struct eap_mschapv2_data {
      47             :         u8 auth_challenge[CHALLENGE_LEN];
      48             :         int auth_challenge_from_tls;
      49             :         u8 *peer_challenge;
      50             :         u8 auth_response[20];
      51             :         enum { CHALLENGE, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE } state;
      52             :         u8 resp_mschapv2_id;
      53             :         u8 master_key[16];
      54             :         int master_key_valid;
      55             : };
      56             : 
      57             : 
      58         212 : static void * eap_mschapv2_init(struct eap_sm *sm)
      59             : {
      60             :         struct eap_mschapv2_data *data;
      61             : 
      62         212 :         data = os_zalloc(sizeof(*data));
      63         212 :         if (data == NULL)
      64           1 :                 return NULL;
      65         211 :         data->state = CHALLENGE;
      66             : 
      67         211 :         if (sm->auth_challenge) {
      68          40 :                 os_memcpy(data->auth_challenge, sm->auth_challenge,
      69             :                           CHALLENGE_LEN);
      70          40 :                 data->auth_challenge_from_tls = 1;
      71             :         }
      72             : 
      73         211 :         if (sm->peer_challenge) {
      74          40 :                 data->peer_challenge = os_malloc(CHALLENGE_LEN);
      75          40 :                 if (data->peer_challenge == NULL) {
      76           0 :                         os_free(data);
      77           0 :                         return NULL;
      78             :                 }
      79          40 :                 os_memcpy(data->peer_challenge, sm->peer_challenge,
      80             :                           CHALLENGE_LEN);
      81             :         }
      82             : 
      83         211 :         return data;
      84             : }
      85             : 
      86             : 
      87         211 : static void eap_mschapv2_reset(struct eap_sm *sm, void *priv)
      88             : {
      89         211 :         struct eap_mschapv2_data *data = priv;
      90         211 :         if (data == NULL)
      91         211 :                 return;
      92             : 
      93         211 :         os_free(data->peer_challenge);
      94         211 :         bin_clear_free(data, sizeof(*data));
      95             : }
      96             : 
      97             : 
      98         211 : static struct wpabuf * eap_mschapv2_build_challenge(
      99             :         struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
     100             : {
     101             :         struct wpabuf *req;
     102             :         struct eap_mschapv2_hdr *ms;
     103             :         size_t ms_len;
     104             : 
     105         382 :         if (!data->auth_challenge_from_tls &&
     106         171 :             random_get_bytes(data->auth_challenge, CHALLENGE_LEN)) {
     107           0 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to get random "
     108             :                            "data");
     109           0 :                 data->state = FAILURE;
     110           0 :                 return NULL;
     111             :         }
     112             : 
     113         211 :         ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
     114         211 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     115             :                             EAP_CODE_REQUEST, id);
     116         211 :         if (req == NULL) {
     117           1 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     118             :                            " for request");
     119           1 :                 data->state = FAILURE;
     120           1 :                 return NULL;
     121             :         }
     122             : 
     123         210 :         ms = wpabuf_put(req, sizeof(*ms));
     124         210 :         ms->op_code = MSCHAPV2_OP_CHALLENGE;
     125         210 :         ms->mschapv2_id = id;
     126         210 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     127             : 
     128         210 :         wpabuf_put_u8(req, CHALLENGE_LEN);
     129         210 :         if (!data->auth_challenge_from_tls)
     130         170 :                 wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN);
     131             :         else
     132          40 :                 wpabuf_put(req, CHALLENGE_LEN);
     133         210 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
     134         210 :                     data->auth_challenge, CHALLENGE_LEN);
     135         210 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     136             : 
     137         210 :         return req;
     138             : }
     139             : 
     140             : 
     141         133 : static struct wpabuf * eap_mschapv2_build_success_req(
     142             :         struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
     143             : {
     144             :         struct wpabuf *req;
     145             :         struct eap_mschapv2_hdr *ms;
     146             :         u8 *msg;
     147         133 :         char *message = "OK";
     148             :         size_t ms_len;
     149             : 
     150         133 :         ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 +
     151         133 :                 os_strlen(message);
     152         133 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     153             :                             EAP_CODE_REQUEST, id);
     154         133 :         if (req == NULL) {
     155           1 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     156             :                            " for request");
     157           1 :                 data->state = FAILURE;
     158           1 :                 return NULL;
     159             :         }
     160             : 
     161         132 :         ms = wpabuf_put(req, sizeof(*ms));
     162         132 :         ms->op_code = MSCHAPV2_OP_SUCCESS;
     163         132 :         ms->mschapv2_id = data->resp_mschapv2_id;
     164         132 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     165         132 :         msg = (u8 *) (ms + 1);
     166             : 
     167         132 :         wpabuf_put_u8(req, 'S');
     168         132 :         wpabuf_put_u8(req, '=');
     169         132 :         wpa_snprintf_hex_uppercase(
     170         132 :                 wpabuf_put(req, sizeof(data->auth_response) * 2),
     171             :                 sizeof(data->auth_response) * 2 + 1,
     172         132 :                 data->auth_response, sizeof(data->auth_response));
     173         132 :         wpabuf_put_u8(req, ' ');
     174         132 :         wpabuf_put_u8(req, 'M');
     175         132 :         wpabuf_put_u8(req, '=');
     176         132 :         wpabuf_put_data(req, message, os_strlen(message));
     177             : 
     178         132 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message",
     179             :                           msg, ms_len - sizeof(*ms));
     180             : 
     181         132 :         return req;
     182             : }
     183             : 
     184             : 
     185           6 : static struct wpabuf * eap_mschapv2_build_failure_req(
     186             :         struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
     187             : {
     188             :         struct wpabuf *req;
     189             :         struct eap_mschapv2_hdr *ms;
     190           6 :         char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 "
     191             :                 "M=FAILED";
     192             :         size_t ms_len;
     193             : 
     194           6 :         ms_len = sizeof(*ms) + os_strlen(message);
     195           6 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     196             :                             EAP_CODE_REQUEST, id);
     197           6 :         if (req == NULL) {
     198           1 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     199             :                            " for request");
     200           1 :                 data->state = FAILURE;
     201           1 :                 return NULL;
     202             :         }
     203             : 
     204           5 :         ms = wpabuf_put(req, sizeof(*ms));
     205           5 :         ms->op_code = MSCHAPV2_OP_FAILURE;
     206           5 :         ms->mschapv2_id = data->resp_mschapv2_id;
     207           5 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     208             : 
     209           5 :         wpabuf_put_data(req, message, os_strlen(message));
     210             : 
     211           5 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message",
     212             :                           (u8 *) message, os_strlen(message));
     213             : 
     214           5 :         return req;
     215             : }
     216             : 
     217             : 
     218         350 : static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv,
     219             :                                              u8 id)
     220             : {
     221         350 :         struct eap_mschapv2_data *data = priv;
     222             : 
     223         350 :         switch (data->state) {
     224             :         case CHALLENGE:
     225         211 :                 return eap_mschapv2_build_challenge(sm, data, id);
     226             :         case SUCCESS_REQ:
     227         133 :                 return eap_mschapv2_build_success_req(sm, data, id);
     228             :         case FAILURE_REQ:
     229           6 :                 return eap_mschapv2_build_failure_req(sm, data, id);
     230             :         default:
     231           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in "
     232           0 :                            "buildReq", data->state);
     233           0 :                 break;
     234             :         }
     235           0 :         return NULL;
     236             : }
     237             : 
     238             : 
     239         274 : static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv,
     240             :                                   struct wpabuf *respData)
     241             : {
     242         274 :         struct eap_mschapv2_data *data = priv;
     243             :         struct eap_mschapv2_hdr *resp;
     244             :         const u8 *pos;
     245             :         size_t len;
     246             : 
     247         274 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     248             :                                &len);
     249         274 :         if (pos == NULL || len < 1) {
     250           0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame");
     251           0 :                 return TRUE;
     252             :         }
     253             : 
     254         274 :         resp = (struct eap_mschapv2_hdr *) pos;
     255         414 :         if (data->state == CHALLENGE &&
     256         140 :             resp->op_code != MSCHAPV2_OP_RESPONSE) {
     257           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Response - "
     258           0 :                            "ignore op %d", resp->op_code);
     259           0 :                 return TRUE;
     260             :         }
     261             : 
     262         404 :         if (data->state == SUCCESS_REQ &&
     263         130 :             resp->op_code != MSCHAPV2_OP_SUCCESS &&
     264           0 :             resp->op_code != MSCHAPV2_OP_FAILURE) {
     265           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Success or "
     266           0 :                            "Failure - ignore op %d", resp->op_code);
     267           0 :                 return TRUE;
     268             :         }
     269             : 
     270         278 :         if (data->state == FAILURE_REQ &&
     271           4 :             resp->op_code != MSCHAPV2_OP_FAILURE) {
     272           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Failure "
     273           0 :                            "- ignore op %d", resp->op_code);
     274           0 :                 return TRUE;
     275             :         }
     276             : 
     277         274 :         return FALSE;
     278             : }
     279             : 
     280             : 
     281         139 : static void eap_mschapv2_process_response(struct eap_sm *sm,
     282             :                                           struct eap_mschapv2_data *data,
     283             :                                           struct wpabuf *respData)
     284             : {
     285             :         struct eap_mschapv2_hdr *resp;
     286             :         const u8 *pos, *end, *peer_challenge, *nt_response, *name;
     287             :         u8 flags;
     288             :         size_t len, name_len, i;
     289             :         u8 expected[24];
     290             :         const u8 *username, *user;
     291             :         size_t username_len, user_len;
     292             :         int res;
     293             :         char *buf;
     294             : 
     295         139 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     296             :                                &len);
     297         139 :         if (pos == NULL || len < 1)
     298           0 :                 return; /* Should not happen - frame already validated */
     299             : 
     300         139 :         end = pos + len;
     301         139 :         resp = (struct eap_mschapv2_hdr *) pos;
     302         139 :         pos = (u8 *) (resp + 1);
     303             : 
     304         278 :         if (len < sizeof(*resp) + 1 + 49 ||
     305         278 :             resp->op_code != MSCHAPV2_OP_RESPONSE ||
     306         139 :             pos[0] != 49) {
     307           0 :                 wpa_hexdump_buf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid response",
     308             :                                 respData);
     309           0 :                 data->state = FAILURE;
     310           0 :                 return;
     311             :         }
     312         139 :         data->resp_mschapv2_id = resp->mschapv2_id;
     313         139 :         pos++;
     314         139 :         peer_challenge = pos;
     315         139 :         pos += 16 + 8;
     316         139 :         nt_response = pos;
     317         139 :         pos += 24;
     318         139 :         flags = *pos++;
     319         139 :         name = pos;
     320         139 :         name_len = end - name;
     321             : 
     322         139 :         if (data->peer_challenge) {
     323          37 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured "
     324             :                            "Peer-Challenge");
     325          37 :                 peer_challenge = data->peer_challenge;
     326             :         }
     327         139 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge",
     328             :                     peer_challenge, 16);
     329         139 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24);
     330         139 :         wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags);
     331         139 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len);
     332             : 
     333         139 :         buf = os_malloc(name_len * 4 + 1);
     334         139 :         if (buf) {
     335         139 :                 printf_encode(buf, name_len * 4 + 1, name, name_len);
     336         139 :                 eap_log_msg(sm, "EAP-MSCHAPV2 Name '%s'", buf);
     337         139 :                 os_free(buf);
     338             :         }
     339             : 
     340             :         /* MSCHAPv2 does not include optional domain name in the
     341             :          * challenge-response calculation, so remove domain prefix
     342             :          * (if present). */
     343         139 :         username = sm->identity;
     344         139 :         username_len = sm->identity_len;
     345         787 :         for (i = 0; i < username_len; i++) {
     346         650 :                 if (username[i] == '\\') {
     347           2 :                         username_len -= i + 1;
     348           2 :                         username += i + 1;
     349           2 :                         break;
     350             :                 }
     351             :         }
     352             : 
     353         139 :         user = name;
     354         139 :         user_len = name_len;
     355         787 :         for (i = 0; i < user_len; i++) {
     356         650 :                 if (user[i] == '\\') {
     357           2 :                         user_len -= i + 1;
     358           2 :                         user += i + 1;
     359           2 :                         break;
     360             :                 }
     361             :         }
     362             : 
     363             : #ifdef CONFIG_TESTING_OPTIONS
     364             :         {
     365             :                 u8 challenge[8];
     366             : 
     367         139 :                 if (challenge_hash(peer_challenge, data->auth_challenge,
     368             :                                    username, username_len, challenge) == 0) {
     369         139 :                         eap_server_mschap_rx_callback(sm, "EAP-MSCHAPV2",
     370             :                                                       username, username_len,
     371             :                                                       challenge, nt_response);
     372             :                 }
     373             :         }
     374             : #endif /* CONFIG_TESTING_OPTIONS */
     375             : 
     376         278 :         if (username_len != user_len ||
     377         139 :             os_memcmp(username, user, username_len) != 0) {
     378           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names");
     379           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Expected user "
     380             :                                   "name", username, username_len);
     381           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Received user "
     382             :                                   "name", user, user_len);
     383           0 :                 data->state = FAILURE;
     384           0 :                 return;
     385             :         }
     386             : 
     387         139 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: User name",
     388             :                           username, username_len);
     389             : 
     390         139 :         if (sm->user->password_hash) {
     391           0 :                 res = generate_nt_response_pwhash(data->auth_challenge,
     392             :                                                   peer_challenge,
     393             :                                                   username, username_len,
     394           0 :                                                   sm->user->password,
     395             :                                                   expected);
     396             :         } else {
     397         278 :                 res = generate_nt_response(data->auth_challenge,
     398             :                                            peer_challenge,
     399             :                                            username, username_len,
     400         139 :                                            sm->user->password,
     401         139 :                                            sm->user->password_len,
     402             :                                            expected);
     403             :         }
     404         139 :         if (res) {
     405           0 :                 data->state = FAILURE;
     406           0 :                 return;
     407             :         }
     408             : 
     409         139 :         if (os_memcmp_const(nt_response, expected, 24) == 0) {
     410             :                 const u8 *pw_hash;
     411             :                 u8 pw_hash_buf[16], pw_hash_hash[16];
     412             : 
     413         133 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Correct NT-Response");
     414         133 :                 data->state = SUCCESS_REQ;
     415             : 
     416             :                 /* Authenticator response is not really needed yet, but
     417             :                  * calculate it here so that peer_challenge and username need
     418             :                  * not be saved. */
     419         133 :                 if (sm->user->password_hash) {
     420           0 :                         pw_hash = sm->user->password;
     421             :                 } else {
     422         133 :                         if (nt_password_hash(sm->user->password,
     423         133 :                                              sm->user->password_len,
     424             :                                              pw_hash_buf) < 0) {
     425           0 :                                 data->state = FAILURE;
     426           0 :                                 return;
     427             :                         }
     428         133 :                         pw_hash = pw_hash_buf;
     429             :                 }
     430         133 :                 if (generate_authenticator_response_pwhash(
     431         133 :                             pw_hash, peer_challenge, data->auth_challenge,
     432             :                             username, username_len, nt_response,
     433         266 :                             data->auth_response) < 0 ||
     434         266 :                     hash_nt_password_hash(pw_hash, pw_hash_hash) < 0 ||
     435         133 :                     get_master_key(pw_hash_hash, nt_response,
     436         133 :                                    data->master_key)) {
     437           0 :                         data->state = FAILURE;
     438           0 :                         return;
     439             :                 }
     440         133 :                 data->master_key_valid = 1;
     441         133 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key",
     442         133 :                                 data->master_key, MSCHAPV2_KEY_LEN);
     443             :         } else {
     444           6 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Expected NT-Response",
     445             :                             expected, 24);
     446           6 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response");
     447           6 :                 data->state = FAILURE_REQ;
     448             :         }
     449             : }
     450             : 
     451             : 
     452         130 : static void eap_mschapv2_process_success_resp(struct eap_sm *sm,
     453             :                                               struct eap_mschapv2_data *data,
     454             :                                               struct wpabuf *respData)
     455             : {
     456             :         struct eap_mschapv2_hdr *resp;
     457             :         const u8 *pos;
     458             :         size_t len;
     459             : 
     460         130 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     461             :                                &len);
     462         130 :         if (pos == NULL || len < 1)
     463         130 :                 return; /* Should not happen - frame already validated */
     464             : 
     465         130 :         resp = (struct eap_mschapv2_hdr *) pos;
     466             : 
     467         130 :         if (resp->op_code == MSCHAPV2_OP_SUCCESS) {
     468         130 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Success Response"
     469             :                            " - authentication completed successfully");
     470         130 :                 data->state = SUCCESS;
     471             :         } else {
     472           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Success "
     473             :                            "Response - peer rejected authentication");
     474           0 :                 data->state = FAILURE;
     475             :         }
     476             : }
     477             : 
     478             : 
     479           4 : static void eap_mschapv2_process_failure_resp(struct eap_sm *sm,
     480             :                                               struct eap_mschapv2_data *data,
     481             :                                               struct wpabuf *respData)
     482             : {
     483             :         struct eap_mschapv2_hdr *resp;
     484             :         const u8 *pos;
     485             :         size_t len;
     486             : 
     487           4 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     488             :                                &len);
     489           4 :         if (pos == NULL || len < 1)
     490           4 :                 return; /* Should not happen - frame already validated */
     491             : 
     492           4 :         resp = (struct eap_mschapv2_hdr *) pos;
     493             : 
     494           4 :         if (resp->op_code == MSCHAPV2_OP_FAILURE) {
     495           4 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Failure Response"
     496             :                            " - authentication failed");
     497             :         } else {
     498           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Failure "
     499             :                            "Response - authentication failed");
     500             :         }
     501             : 
     502           4 :         data->state = FAILURE;
     503             : }
     504             : 
     505             : 
     506         274 : static void eap_mschapv2_process(struct eap_sm *sm, void *priv,
     507             :                                  struct wpabuf *respData)
     508             : {
     509         274 :         struct eap_mschapv2_data *data = priv;
     510             : 
     511         274 :         if (sm->user == NULL || sm->user->password == NULL) {
     512           1 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
     513           1 :                 data->state = FAILURE;
     514         275 :                 return;
     515             :         }
     516             : 
     517         273 :         switch (data->state) {
     518             :         case CHALLENGE:
     519         139 :                 eap_mschapv2_process_response(sm, data, respData);
     520         139 :                 break;
     521             :         case SUCCESS_REQ:
     522         130 :                 eap_mschapv2_process_success_resp(sm, data, respData);
     523         130 :                 break;
     524             :         case FAILURE_REQ:
     525           4 :                 eap_mschapv2_process_failure_resp(sm, data, respData);
     526           4 :                 break;
     527             :         default:
     528           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in "
     529           0 :                            "process", data->state);
     530           0 :                 break;
     531             :         }
     532             : }
     533             : 
     534             : 
     535         274 : static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv)
     536             : {
     537         274 :         struct eap_mschapv2_data *data = priv;
     538         274 :         return data->state == SUCCESS || data->state == FAILURE;
     539             : }
     540             : 
     541             : 
     542         121 : static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
     543             : {
     544         121 :         struct eap_mschapv2_data *data = priv;
     545             :         u8 *key;
     546             : 
     547         121 :         if (data->state != SUCCESS || !data->master_key_valid)
     548           0 :                 return NULL;
     549             : 
     550         121 :         *len = 2 * MSCHAPV2_KEY_LEN;
     551         121 :         key = os_malloc(*len);
     552         121 :         if (key == NULL)
     553           1 :                 return NULL;
     554             :         /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */
     555         120 :         get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1);
     556         120 :         get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
     557             :                                 MSCHAPV2_KEY_LEN, 1, 1);
     558         120 :         wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len);
     559             : 
     560         120 :         return key;
     561             : }
     562             : 
     563             : 
     564         135 : static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv)
     565             : {
     566         135 :         struct eap_mschapv2_data *data = priv;
     567         135 :         return data->state == SUCCESS;
     568             : }
     569             : 
     570             : 
     571          25 : int eap_server_mschapv2_register(void)
     572             : {
     573             :         struct eap_method *eap;
     574             : 
     575          25 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     576             :                                       EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
     577             :                                       "MSCHAPV2");
     578          25 :         if (eap == NULL)
     579           0 :                 return -1;
     580             : 
     581          25 :         eap->init = eap_mschapv2_init;
     582          25 :         eap->reset = eap_mschapv2_reset;
     583          25 :         eap->buildReq = eap_mschapv2_buildReq;
     584          25 :         eap->check = eap_mschapv2_check;
     585          25 :         eap->process = eap_mschapv2_process;
     586          25 :         eap->isDone = eap_mschapv2_isDone;
     587          25 :         eap->getKey = eap_mschapv2_getKey;
     588          25 :         eap->isSuccess = eap_mschapv2_isSuccess;
     589             : 
     590          25 :         return eap_server_method_register(eap);
     591             : }

Generated by: LCOV version 1.10