LCOV - code coverage report
Current view: top level - eap_server - eap_server_mschapv2.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1401872338 Lines: 174 274 63.5 %
Date: 2014-06-04 Functions: 13 15 86.7 %

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

Generated by: LCOV version 1.10