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 1443382998 Lines: 231 279 82.8 %
Date: 2015-09-27 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          87 : static void * eap_mschapv2_init(struct eap_sm *sm)
      59             : {
      60             :         struct eap_mschapv2_data *data;
      61             : 
      62          87 :         data = os_zalloc(sizeof(*data));
      63          87 :         if (data == NULL)
      64           1 :                 return NULL;
      65          86 :         data->state = CHALLENGE;
      66             : 
      67          86 :         if (sm->auth_challenge) {
      68           5 :                 os_memcpy(data->auth_challenge, sm->auth_challenge,
      69             :                           CHALLENGE_LEN);
      70           5 :                 data->auth_challenge_from_tls = 1;
      71             :         }
      72             : 
      73          86 :         if (sm->peer_challenge) {
      74           5 :                 data->peer_challenge = os_malloc(CHALLENGE_LEN);
      75           5 :                 if (data->peer_challenge == NULL) {
      76           0 :                         os_free(data);
      77           0 :                         return NULL;
      78             :                 }
      79           5 :                 os_memcpy(data->peer_challenge, sm->peer_challenge,
      80             :                           CHALLENGE_LEN);
      81             :         }
      82             : 
      83          86 :         return data;
      84             : }
      85             : 
      86             : 
      87          86 : static void eap_mschapv2_reset(struct eap_sm *sm, void *priv)
      88             : {
      89          86 :         struct eap_mschapv2_data *data = priv;
      90          86 :         if (data == NULL)
      91          86 :                 return;
      92             : 
      93          86 :         os_free(data->peer_challenge);
      94          86 :         bin_clear_free(data, sizeof(*data));
      95             : }
      96             : 
      97             : 
      98          86 : 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         167 :         if (!data->auth_challenge_from_tls &&
     106          81 :             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          86 :         ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
     114          86 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     115             :                             EAP_CODE_REQUEST, id);
     116          86 :         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          85 :         ms = wpabuf_put(req, sizeof(*ms));
     124          85 :         ms->op_code = MSCHAPV2_OP_CHALLENGE;
     125          85 :         ms->mschapv2_id = id;
     126          85 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     127             : 
     128          85 :         wpabuf_put_u8(req, CHALLENGE_LEN);
     129          85 :         if (!data->auth_challenge_from_tls)
     130          80 :                 wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN);
     131             :         else
     132           5 :                 wpabuf_put(req, CHALLENGE_LEN);
     133          85 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
     134          85 :                     data->auth_challenge, CHALLENGE_LEN);
     135          85 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     136             : 
     137          85 :         return req;
     138             : }
     139             : 
     140             : 
     141          58 : 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          58 :         char *message = "OK";
     148             :         size_t ms_len;
     149             : 
     150          58 :         ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 +
     151          58 :                 os_strlen(message);
     152          58 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     153             :                             EAP_CODE_REQUEST, id);
     154          58 :         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          57 :         ms = wpabuf_put(req, sizeof(*ms));
     162          57 :         ms->op_code = MSCHAPV2_OP_SUCCESS;
     163          57 :         ms->mschapv2_id = data->resp_mschapv2_id;
     164          57 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     165          57 :         msg = (u8 *) (ms + 1);
     166             : 
     167          57 :         wpabuf_put_u8(req, 'S');
     168          57 :         wpabuf_put_u8(req, '=');
     169          57 :         wpa_snprintf_hex_uppercase(
     170          57 :                 wpabuf_put(req, sizeof(data->auth_response) * 2),
     171             :                 sizeof(data->auth_response) * 2 + 1,
     172          57 :                 data->auth_response, sizeof(data->auth_response));
     173          57 :         wpabuf_put_u8(req, ' ');
     174          57 :         wpabuf_put_u8(req, 'M');
     175          57 :         wpabuf_put_u8(req, '=');
     176          57 :         wpabuf_put_data(req, message, os_strlen(message));
     177             : 
     178          57 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message",
     179             :                           msg, ms_len - sizeof(*ms));
     180             : 
     181          57 :         return req;
     182             : }
     183             : 
     184             : 
     185           4 : 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           4 :         char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 "
     191             :                 "M=FAILED";
     192             :         size_t ms_len;
     193             : 
     194           4 :         ms_len = sizeof(*ms) + os_strlen(message);
     195           4 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     196             :                             EAP_CODE_REQUEST, id);
     197           4 :         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           3 :         ms = wpabuf_put(req, sizeof(*ms));
     205           3 :         ms->op_code = MSCHAPV2_OP_FAILURE;
     206           3 :         ms->mschapv2_id = data->resp_mschapv2_id;
     207           3 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     208             : 
     209           3 :         wpabuf_put_data(req, message, os_strlen(message));
     210             : 
     211           3 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message",
     212             :                           (u8 *) message, os_strlen(message));
     213             : 
     214           3 :         return req;
     215             : }
     216             : 
     217             : 
     218         148 : static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv,
     219             :                                              u8 id)
     220             : {
     221         148 :         struct eap_mschapv2_data *data = priv;
     222             : 
     223         148 :         switch (data->state) {
     224             :         case CHALLENGE:
     225          86 :                 return eap_mschapv2_build_challenge(sm, data, id);
     226             :         case SUCCESS_REQ:
     227          58 :                 return eap_mschapv2_build_success_req(sm, data, id);
     228             :         case FAILURE_REQ:
     229           4 :                 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         123 : static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv,
     240             :                                   struct wpabuf *respData)
     241             : {
     242         123 :         struct eap_mschapv2_data *data = priv;
     243             :         struct eap_mschapv2_hdr *resp;
     244             :         const u8 *pos;
     245             :         size_t len;
     246             : 
     247         123 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     248             :                                &len);
     249         123 :         if (pos == NULL || len < 1) {
     250           0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame");
     251           0 :                 return TRUE;
     252             :         }
     253             : 
     254         123 :         resp = (struct eap_mschapv2_hdr *) pos;
     255         186 :         if (data->state == CHALLENGE &&
     256          63 :             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         180 :         if (data->state == SUCCESS_REQ &&
     263          57 :             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         126 :         if (data->state == FAILURE_REQ &&
     271           3 :             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         123 :         return FALSE;
     278             : }
     279             : 
     280             : 
     281          62 : 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          62 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     296             :                                &len);
     297          62 :         if (pos == NULL || len < 1)
     298           0 :                 return; /* Should not happen - frame already validated */
     299             : 
     300          62 :         end = pos + len;
     301          62 :         resp = (struct eap_mschapv2_hdr *) pos;
     302          62 :         pos = (u8 *) (resp + 1);
     303             : 
     304         124 :         if (len < sizeof(*resp) + 1 + 49 ||
     305         124 :             resp->op_code != MSCHAPV2_OP_RESPONSE ||
     306          62 :             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          62 :         data->resp_mschapv2_id = resp->mschapv2_id;
     313          62 :         pos++;
     314          62 :         peer_challenge = pos;
     315          62 :         pos += 16 + 8;
     316          62 :         nt_response = pos;
     317          62 :         pos += 24;
     318          62 :         flags = *pos++;
     319          62 :         name = pos;
     320          62 :         name_len = end - name;
     321             : 
     322          62 :         if (data->peer_challenge) {
     323           5 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured "
     324             :                            "Peer-Challenge");
     325           5 :                 peer_challenge = data->peer_challenge;
     326             :         }
     327          62 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge",
     328             :                     peer_challenge, 16);
     329          62 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24);
     330          62 :         wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags);
     331          62 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len);
     332             : 
     333          62 :         buf = os_malloc(name_len * 4 + 1);
     334          62 :         if (buf) {
     335          62 :                 printf_encode(buf, name_len * 4 + 1, name, name_len);
     336          62 :                 eap_log_msg(sm, "EAP-MSCHAPV2 Name '%s'", buf);
     337          62 :                 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          62 :         username = sm->identity;
     344          62 :         username_len = sm->identity_len;
     345         314 :         for (i = 0; i < username_len; i++) {
     346         254 :                 if (username[i] == '\\') {
     347           2 :                         username_len -= i + 1;
     348           2 :                         username += i + 1;
     349           2 :                         break;
     350             :                 }
     351             :         }
     352             : 
     353          62 :         user = name;
     354          62 :         user_len = name_len;
     355         314 :         for (i = 0; i < user_len; i++) {
     356         254 :                 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          62 :                 if (challenge_hash(peer_challenge, data->auth_challenge,
     368             :                                    username, username_len, challenge) == 0) {
     369          62 :                         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         124 :         if (username_len != user_len ||
     377          62 :             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          62 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: User name",
     388             :                           username, username_len);
     389             : 
     390          62 :         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         124 :                 res = generate_nt_response(data->auth_challenge,
     398             :                                            peer_challenge,
     399             :                                            username, username_len,
     400          62 :                                            sm->user->password,
     401          62 :                                            sm->user->password_len,
     402             :                                            expected);
     403             :         }
     404          62 :         if (res) {
     405           0 :                 data->state = FAILURE;
     406           0 :                 return;
     407             :         }
     408             : 
     409          62 :         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          58 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Correct NT-Response");
     414          58 :                 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          58 :                 if (sm->user->password_hash) {
     420           0 :                         pw_hash = sm->user->password;
     421             :                 } else {
     422          58 :                         if (nt_password_hash(sm->user->password,
     423          58 :                                              sm->user->password_len,
     424             :                                              pw_hash_buf) < 0) {
     425           0 :                                 data->state = FAILURE;
     426           0 :                                 return;
     427             :                         }
     428          58 :                         pw_hash = pw_hash_buf;
     429             :                 }
     430          58 :                 if (generate_authenticator_response_pwhash(
     431          58 :                             pw_hash, peer_challenge, data->auth_challenge,
     432             :                             username, username_len, nt_response,
     433         116 :                             data->auth_response) < 0 ||
     434         116 :                     hash_nt_password_hash(pw_hash, pw_hash_hash) < 0 ||
     435          58 :                     get_master_key(pw_hash_hash, nt_response,
     436          58 :                                    data->master_key)) {
     437           0 :                         data->state = FAILURE;
     438           0 :                         return;
     439             :                 }
     440          58 :                 data->master_key_valid = 1;
     441          58 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key",
     442          58 :                                 data->master_key, MSCHAPV2_KEY_LEN);
     443             :         } else {
     444           4 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Expected NT-Response",
     445             :                             expected, 24);
     446           4 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response");
     447           4 :                 data->state = FAILURE_REQ;
     448             :         }
     449             : }
     450             : 
     451             : 
     452          57 : 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          57 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     461             :                                &len);
     462          57 :         if (pos == NULL || len < 1)
     463          57 :                 return; /* Should not happen - frame already validated */
     464             : 
     465          57 :         resp = (struct eap_mschapv2_hdr *) pos;
     466             : 
     467          57 :         if (resp->op_code == MSCHAPV2_OP_SUCCESS) {
     468          57 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Success Response"
     469             :                            " - authentication completed successfully");
     470          57 :                 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           3 : 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           3 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     488             :                                &len);
     489           3 :         if (pos == NULL || len < 1)
     490           3 :                 return; /* Should not happen - frame already validated */
     491             : 
     492           3 :         resp = (struct eap_mschapv2_hdr *) pos;
     493             : 
     494           3 :         if (resp->op_code == MSCHAPV2_OP_FAILURE) {
     495           3 :                 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           3 :         data->state = FAILURE;
     503             : }
     504             : 
     505             : 
     506         123 : static void eap_mschapv2_process(struct eap_sm *sm, void *priv,
     507             :                                  struct wpabuf *respData)
     508             : {
     509         123 :         struct eap_mschapv2_data *data = priv;
     510             : 
     511         123 :         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         124 :                 return;
     515             :         }
     516             : 
     517         122 :         switch (data->state) {
     518             :         case CHALLENGE:
     519          62 :                 eap_mschapv2_process_response(sm, data, respData);
     520          62 :                 break;
     521             :         case SUCCESS_REQ:
     522          57 :                 eap_mschapv2_process_success_resp(sm, data, respData);
     523          57 :                 break;
     524             :         case FAILURE_REQ:
     525           3 :                 eap_mschapv2_process_failure_resp(sm, data, respData);
     526           3 :                 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         123 : static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv)
     536             : {
     537         123 :         struct eap_mschapv2_data *data = priv;
     538         123 :         return data->state == SUCCESS || data->state == FAILURE;
     539             : }
     540             : 
     541             : 
     542          50 : static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
     543             : {
     544          50 :         struct eap_mschapv2_data *data = priv;
     545             :         u8 *key;
     546             : 
     547          50 :         if (data->state != SUCCESS || !data->master_key_valid)
     548           0 :                 return NULL;
     549             : 
     550          50 :         *len = 2 * MSCHAPV2_KEY_LEN;
     551          50 :         key = os_malloc(*len);
     552          50 :         if (key == NULL)
     553           1 :                 return NULL;
     554             :         /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */
     555          49 :         get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1);
     556          49 :         get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
     557             :                                 MSCHAPV2_KEY_LEN, 1, 1);
     558          49 :         wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len);
     559             : 
     560          49 :         return key;
     561             : }
     562             : 
     563             : 
     564          61 : static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv)
     565             : {
     566          61 :         struct eap_mschapv2_data *data = priv;
     567          61 :         return data->state == SUCCESS;
     568             : }
     569             : 
     570             : 
     571          25 : int eap_server_mschapv2_register(void)
     572             : {
     573             :         struct eap_method *eap;
     574             :         int ret;
     575             : 
     576          25 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     577             :                                       EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
     578             :                                       "MSCHAPV2");
     579          25 :         if (eap == NULL)
     580           0 :                 return -1;
     581             : 
     582          25 :         eap->init = eap_mschapv2_init;
     583          25 :         eap->reset = eap_mschapv2_reset;
     584          25 :         eap->buildReq = eap_mschapv2_buildReq;
     585          25 :         eap->check = eap_mschapv2_check;
     586          25 :         eap->process = eap_mschapv2_process;
     587          25 :         eap->isDone = eap_mschapv2_isDone;
     588          25 :         eap->getKey = eap_mschapv2_getKey;
     589          25 :         eap->isSuccess = eap_mschapv2_isSuccess;
     590             : 
     591          25 :         ret = eap_server_method_register(eap);
     592          25 :         if (ret)
     593           0 :                 eap_server_method_free(eap);
     594          25 :         return ret;
     595             : }

Generated by: LCOV version 1.10