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 1401264779 Lines: 209 274 76.3 %
Date: 2014-05-28 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          57 : static void * eap_mschapv2_init(struct eap_sm *sm)
      59             : {
      60             :         struct eap_mschapv2_data *data;
      61             : 
      62          57 :         data = os_zalloc(sizeof(*data));
      63          57 :         if (data == NULL)
      64           0 :                 return NULL;
      65          57 :         data->state = CHALLENGE;
      66             : 
      67          57 :         if (sm->auth_challenge) {
      68           4 :                 os_memcpy(data->auth_challenge, sm->auth_challenge,
      69             :                           CHALLENGE_LEN);
      70           4 :                 data->auth_challenge_from_tls = 1;
      71             :         }
      72             : 
      73          57 :         if (sm->peer_challenge) {
      74           4 :                 data->peer_challenge = os_malloc(CHALLENGE_LEN);
      75           4 :                 if (data->peer_challenge == NULL) {
      76           0 :                         os_free(data);
      77           0 :                         return NULL;
      78             :                 }
      79           4 :                 os_memcpy(data->peer_challenge, sm->peer_challenge,
      80             :                           CHALLENGE_LEN);
      81             :         }
      82             : 
      83          57 :         return data;
      84             : }
      85             : 
      86             : 
      87          57 : static void eap_mschapv2_reset(struct eap_sm *sm, void *priv)
      88             : {
      89          57 :         struct eap_mschapv2_data *data = priv;
      90          57 :         if (data == NULL)
      91          57 :                 return;
      92             : 
      93          57 :         os_free(data->peer_challenge);
      94          57 :         os_free(data);
      95             : }
      96             : 
      97             : 
      98          57 : 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         110 :         if (!data->auth_challenge_from_tls &&
     106          53 :             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          57 :         ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
     114          57 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     115             :                             EAP_CODE_REQUEST, id);
     116          57 :         if (req == NULL) {
     117           0 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     118             :                            " for request");
     119           0 :                 data->state = FAILURE;
     120           0 :                 return NULL;
     121             :         }
     122             : 
     123          57 :         ms = wpabuf_put(req, sizeof(*ms));
     124          57 :         ms->op_code = MSCHAPV2_OP_CHALLENGE;
     125          57 :         ms->mschapv2_id = id;
     126          57 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     127             : 
     128          57 :         wpabuf_put_u8(req, CHALLENGE_LEN);
     129          57 :         if (!data->auth_challenge_from_tls)
     130          53 :                 wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN);
     131             :         else
     132           4 :                 wpabuf_put(req, CHALLENGE_LEN);
     133          57 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
     134          57 :                     data->auth_challenge, CHALLENGE_LEN);
     135          57 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     136             : 
     137          57 :         return req;
     138             : }
     139             : 
     140             : 
     141          44 : 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          44 :         char *message = "OK";
     148             :         size_t ms_len;
     149             : 
     150          44 :         ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 +
     151          44 :                 os_strlen(message);
     152          44 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     153             :                             EAP_CODE_REQUEST, id);
     154          44 :         if (req == NULL) {
     155           0 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     156             :                            " for request");
     157           0 :                 data->state = FAILURE;
     158           0 :                 return NULL;
     159             :         }
     160             : 
     161          44 :         ms = wpabuf_put(req, sizeof(*ms));
     162          44 :         ms->op_code = MSCHAPV2_OP_SUCCESS;
     163          44 :         ms->mschapv2_id = data->resp_mschapv2_id;
     164          44 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     165          44 :         msg = (u8 *) (ms + 1);
     166             : 
     167          44 :         wpabuf_put_u8(req, 'S');
     168          44 :         wpabuf_put_u8(req, '=');
     169          44 :         wpa_snprintf_hex_uppercase(
     170          44 :                 wpabuf_put(req, sizeof(data->auth_response) * 2),
     171             :                 sizeof(data->auth_response) * 2 + 1,
     172          44 :                 data->auth_response, sizeof(data->auth_response));
     173          44 :         wpabuf_put_u8(req, ' ');
     174          44 :         wpabuf_put_u8(req, 'M');
     175          44 :         wpabuf_put_u8(req, '=');
     176          44 :         wpabuf_put_data(req, message, os_strlen(message));
     177             : 
     178          44 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message",
     179             :                           msg, ms_len - sizeof(*ms));
     180             : 
     181          44 :         return req;
     182             : }
     183             : 
     184             : 
     185           2 : 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           2 :         char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 "
     191             :                 "M=FAILED";
     192             :         size_t ms_len;
     193             : 
     194           2 :         ms_len = sizeof(*ms) + os_strlen(message);
     195           2 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     196             :                             EAP_CODE_REQUEST, id);
     197           2 :         if (req == NULL) {
     198           0 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     199             :                            " for request");
     200           0 :                 data->state = FAILURE;
     201           0 :                 return NULL;
     202             :         }
     203             : 
     204           2 :         ms = wpabuf_put(req, sizeof(*ms));
     205           2 :         ms->op_code = MSCHAPV2_OP_FAILURE;
     206           2 :         ms->mschapv2_id = data->resp_mschapv2_id;
     207           2 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     208             : 
     209           2 :         wpabuf_put_data(req, message, os_strlen(message));
     210             : 
     211           2 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message",
     212             :                           (u8 *) message, os_strlen(message));
     213             : 
     214           2 :         return req;
     215             : }
     216             : 
     217             : 
     218         103 : static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv,
     219             :                                              u8 id)
     220             : {
     221         103 :         struct eap_mschapv2_data *data = priv;
     222             : 
     223         103 :         switch (data->state) {
     224             :         case CHALLENGE:
     225          57 :                 return eap_mschapv2_build_challenge(sm, data, id);
     226             :         case SUCCESS_REQ:
     227          44 :                 return eap_mschapv2_build_success_req(sm, data, id);
     228             :         case FAILURE_REQ:
     229           2 :                 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          92 : static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv,
     240             :                                   struct wpabuf *respData)
     241             : {
     242          92 :         struct eap_mschapv2_data *data = priv;
     243             :         struct eap_mschapv2_hdr *resp;
     244             :         const u8 *pos;
     245             :         size_t len;
     246             : 
     247          92 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     248             :                                &len);
     249          92 :         if (pos == NULL || len < 1) {
     250           0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame");
     251           0 :                 return TRUE;
     252             :         }
     253             : 
     254          92 :         resp = (struct eap_mschapv2_hdr *) pos;
     255         138 :         if (data->state == CHALLENGE &&
     256          46 :             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         136 :         if (data->state == SUCCESS_REQ &&
     263          44 :             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          94 :         if (data->state == FAILURE_REQ &&
     271           2 :             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          92 :         return FALSE;
     278             : }
     279             : 
     280             : 
     281          46 : 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          46 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     296             :                                &len);
     297          46 :         if (pos == NULL || len < 1)
     298           0 :                 return; /* Should not happen - frame already validated */
     299             : 
     300          46 :         end = pos + len;
     301          46 :         resp = (struct eap_mschapv2_hdr *) pos;
     302          46 :         pos = (u8 *) (resp + 1);
     303             : 
     304          92 :         if (len < sizeof(*resp) + 1 + 49 ||
     305          92 :             resp->op_code != MSCHAPV2_OP_RESPONSE ||
     306          46 :             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          46 :         data->resp_mschapv2_id = resp->mschapv2_id;
     313          46 :         pos++;
     314          46 :         peer_challenge = pos;
     315          46 :         pos += 16 + 8;
     316          46 :         nt_response = pos;
     317          46 :         pos += 24;
     318          46 :         flags = *pos++;
     319          46 :         name = pos;
     320          46 :         name_len = end - name;
     321             : 
     322          46 :         if (data->peer_challenge) {
     323           4 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured "
     324             :                            "Peer-Challenge");
     325           4 :                 peer_challenge = data->peer_challenge;
     326             :         }
     327          46 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge",
     328             :                     peer_challenge, 16);
     329          46 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24);
     330          46 :         wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags);
     331          46 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len);
     332             : 
     333          46 :         buf = os_malloc(name_len * 3 + 1);
     334          46 :         if (buf) {
     335          46 :                 printf_encode(buf, name_len * 3 + 1, name, name_len);
     336          46 :                 eap_log_msg(sm, "EAP-MSCHAPV2 Name '%s'", buf);
     337          46 :                 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          46 :         username = sm->identity;
     344          46 :         username_len = sm->identity_len;
     345         230 :         for (i = 0; i < username_len; i++) {
     346         184 :                 if (username[i] == '\\') {
     347           0 :                         username_len -= i + 1;
     348           0 :                         username += i + 1;
     349           0 :                         break;
     350             :                 }
     351             :         }
     352             : 
     353          46 :         user = name;
     354          46 :         user_len = name_len;
     355         230 :         for (i = 0; i < user_len; i++) {
     356         184 :                 if (user[i] == '\\') {
     357           0 :                         user_len -= i + 1;
     358           0 :                         user += i + 1;
     359           0 :                         break;
     360             :                 }
     361             :         }
     362             : 
     363          92 :         if (username_len != user_len ||
     364          46 :             os_memcmp(username, user, username_len) != 0) {
     365           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names");
     366           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Expected user "
     367             :                                   "name", username, username_len);
     368           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Received user "
     369             :                                   "name", user, user_len);
     370           0 :                 data->state = FAILURE;
     371           0 :                 return;
     372             :         }
     373             : 
     374          46 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: User name",
     375             :                           username, username_len);
     376             : 
     377          46 :         if (sm->user->password_hash) {
     378           0 :                 res = generate_nt_response_pwhash(data->auth_challenge,
     379             :                                                   peer_challenge,
     380             :                                                   username, username_len,
     381           0 :                                                   sm->user->password,
     382             :                                                   expected);
     383             :         } else {
     384          92 :                 res = generate_nt_response(data->auth_challenge,
     385             :                                            peer_challenge,
     386             :                                            username, username_len,
     387          46 :                                            sm->user->password,
     388          46 :                                            sm->user->password_len,
     389             :                                            expected);
     390             :         }
     391          46 :         if (res) {
     392           0 :                 data->state = FAILURE;
     393           0 :                 return;
     394             :         }
     395             : 
     396          46 :         if (os_memcmp(nt_response, expected, 24) == 0) {
     397             :                 const u8 *pw_hash;
     398             :                 u8 pw_hash_buf[16], pw_hash_hash[16];
     399             : 
     400          44 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Correct NT-Response");
     401          44 :                 data->state = SUCCESS_REQ;
     402             : 
     403             :                 /* Authenticator response is not really needed yet, but
     404             :                  * calculate it here so that peer_challenge and username need
     405             :                  * not be saved. */
     406          44 :                 if (sm->user->password_hash) {
     407           0 :                         pw_hash = sm->user->password;
     408             :                 } else {
     409          44 :                         if (nt_password_hash(sm->user->password,
     410          44 :                                              sm->user->password_len,
     411             :                                              pw_hash_buf) < 0) {
     412           0 :                                 data->state = FAILURE;
     413           0 :                                 return;
     414             :                         }
     415          44 :                         pw_hash = pw_hash_buf;
     416             :                 }
     417          44 :                 generate_authenticator_response_pwhash(
     418          44 :                         pw_hash, peer_challenge, data->auth_challenge,
     419             :                         username, username_len, nt_response,
     420          44 :                         data->auth_response);
     421             : 
     422          44 :                 hash_nt_password_hash(pw_hash, pw_hash_hash);
     423          44 :                 get_master_key(pw_hash_hash, nt_response, data->master_key);
     424          44 :                 data->master_key_valid = 1;
     425          44 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key",
     426          44 :                                 data->master_key, MSCHAPV2_KEY_LEN);
     427             :         } else {
     428           2 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Expected NT-Response",
     429             :                             expected, 24);
     430           2 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response");
     431           2 :                 data->state = FAILURE_REQ;
     432             :         }
     433             : }
     434             : 
     435             : 
     436          44 : static void eap_mschapv2_process_success_resp(struct eap_sm *sm,
     437             :                                               struct eap_mschapv2_data *data,
     438             :                                               struct wpabuf *respData)
     439             : {
     440             :         struct eap_mschapv2_hdr *resp;
     441             :         const u8 *pos;
     442             :         size_t len;
     443             : 
     444          44 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     445             :                                &len);
     446          44 :         if (pos == NULL || len < 1)
     447          44 :                 return; /* Should not happen - frame already validated */
     448             : 
     449          44 :         resp = (struct eap_mschapv2_hdr *) pos;
     450             : 
     451          44 :         if (resp->op_code == MSCHAPV2_OP_SUCCESS) {
     452          44 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Success Response"
     453             :                            " - authentication completed successfully");
     454          44 :                 data->state = SUCCESS;
     455             :         } else {
     456           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Success "
     457             :                            "Response - peer rejected authentication");
     458           0 :                 data->state = FAILURE;
     459             :         }
     460             : }
     461             : 
     462             : 
     463           2 : static void eap_mschapv2_process_failure_resp(struct eap_sm *sm,
     464             :                                               struct eap_mschapv2_data *data,
     465             :                                               struct wpabuf *respData)
     466             : {
     467             :         struct eap_mschapv2_hdr *resp;
     468             :         const u8 *pos;
     469             :         size_t len;
     470             : 
     471           2 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     472             :                                &len);
     473           2 :         if (pos == NULL || len < 1)
     474           2 :                 return; /* Should not happen - frame already validated */
     475             : 
     476           2 :         resp = (struct eap_mschapv2_hdr *) pos;
     477             : 
     478           2 :         if (resp->op_code == MSCHAPV2_OP_FAILURE) {
     479           2 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Failure Response"
     480             :                            " - authentication failed");
     481             :         } else {
     482           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Failure "
     483             :                            "Response - authentication failed");
     484             :         }
     485             : 
     486           2 :         data->state = FAILURE;
     487             : }
     488             : 
     489             : 
     490          92 : static void eap_mschapv2_process(struct eap_sm *sm, void *priv,
     491             :                                  struct wpabuf *respData)
     492             : {
     493          92 :         struct eap_mschapv2_data *data = priv;
     494             : 
     495          92 :         if (sm->user == NULL || sm->user->password == NULL) {
     496           0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
     497           0 :                 data->state = FAILURE;
     498          92 :                 return;
     499             :         }
     500             : 
     501          92 :         switch (data->state) {
     502             :         case CHALLENGE:
     503          46 :                 eap_mschapv2_process_response(sm, data, respData);
     504          46 :                 break;
     505             :         case SUCCESS_REQ:
     506          44 :                 eap_mschapv2_process_success_resp(sm, data, respData);
     507          44 :                 break;
     508             :         case FAILURE_REQ:
     509           2 :                 eap_mschapv2_process_failure_resp(sm, data, respData);
     510           2 :                 break;
     511             :         default:
     512           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in "
     513           0 :                            "process", data->state);
     514           0 :                 break;
     515             :         }
     516             : }
     517             : 
     518             : 
     519          92 : static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv)
     520             : {
     521          92 :         struct eap_mschapv2_data *data = priv;
     522          92 :         return data->state == SUCCESS || data->state == FAILURE;
     523             : }
     524             : 
     525             : 
     526          38 : static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
     527             : {
     528          38 :         struct eap_mschapv2_data *data = priv;
     529             :         u8 *key;
     530             : 
     531          38 :         if (data->state != SUCCESS || !data->master_key_valid)
     532           0 :                 return NULL;
     533             : 
     534          38 :         *len = 2 * MSCHAPV2_KEY_LEN;
     535          38 :         key = os_malloc(*len);
     536          38 :         if (key == NULL)
     537           0 :                 return NULL;
     538             :         /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */
     539          38 :         get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1);
     540          38 :         get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
     541             :                                 MSCHAPV2_KEY_LEN, 1, 1);
     542          38 :         wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len);
     543             : 
     544          38 :         return key;
     545             : }
     546             : 
     547             : 
     548          46 : static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv)
     549             : {
     550          46 :         struct eap_mschapv2_data *data = priv;
     551          46 :         return data->state == SUCCESS;
     552             : }
     553             : 
     554             : 
     555           2 : int eap_server_mschapv2_register(void)
     556             : {
     557             :         struct eap_method *eap;
     558             :         int ret;
     559             : 
     560           2 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     561             :                                       EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
     562             :                                       "MSCHAPV2");
     563           2 :         if (eap == NULL)
     564           0 :                 return -1;
     565             : 
     566           2 :         eap->init = eap_mschapv2_init;
     567           2 :         eap->reset = eap_mschapv2_reset;
     568           2 :         eap->buildReq = eap_mschapv2_buildReq;
     569           2 :         eap->check = eap_mschapv2_check;
     570           2 :         eap->process = eap_mschapv2_process;
     571           2 :         eap->isDone = eap_mschapv2_isDone;
     572           2 :         eap->getKey = eap_mschapv2_getKey;
     573           2 :         eap->isSuccess = eap_mschapv2_isSuccess;
     574             : 
     575           2 :         ret = eap_server_method_register(eap);
     576           2 :         if (ret)
     577           0 :                 eap_server_method_free(eap);
     578           2 :         return ret;
     579             : }

Generated by: LCOV version 1.10