Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2009-2015 Tobias Brunner
                      3:  * Copyright (C) 2010 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "eap_mschapv2.h"
                     18: 
                     19: #include <ctype.h>
                     20: #include <unistd.h>
                     21: 
                     22: #include <daemon.h>
                     23: #include <library.h>
                     24: #include <collections/enumerator.h>
                     25: #include <crypto/crypters/crypter.h>
                     26: #include <crypto/hashers/hasher.h>
                     27: 
                     28: typedef struct private_eap_mschapv2_t private_eap_mschapv2_t;
                     29: 
                     30: /**
                     31:  * Private data of an eap_mschapv2_t object.
                     32:  */
                     33: struct private_eap_mschapv2_t
                     34: {
                     35:        /**
                     36:         * Public authenticator_t interface.
                     37:         */
                     38:        eap_mschapv2_t public;
                     39: 
                     40:        /**
                     41:         * ID of the server
                     42:         */
                     43:        identification_t *server;
                     44: 
                     45:        /**
                     46:         * ID of the peer
                     47:         */
                     48:        identification_t *peer;
                     49: 
                     50:        /**
                     51:         * challenge sent by the server
                     52:         */
                     53:        chunk_t challenge;
                     54: 
                     55:        /**
                     56:         * generated NT-Response
                     57:         */
                     58:        chunk_t nt_response;
                     59: 
                     60:        /**
                     61:         * generated Authenticator Response
                     62:         */
                     63:        chunk_t auth_response;
                     64: 
                     65:        /**
                     66:         * generated MSK
                     67:         */
                     68:        chunk_t msk;
                     69: 
                     70:        /**
                     71:         * EAP message identifier
                     72:         */
                     73:        uint8_t identifier;
                     74: 
                     75:        /**
                     76:         * MS-CHAPv2-ID (session ID, increases with each retry)
                     77:         */
                     78:        uint8_t mschapv2id;
                     79: 
                     80:        /**
                     81:         * Number of retries
                     82:         */
                     83:        int retries;
                     84: 
                     85:        /**
                     86:         * Provide EAP-Identity
                     87:         */
                     88:        auth_cfg_t *auth;
                     89: 
                     90:        /**
                     91:         * Current state
                     92:         */
                     93:        enum {
                     94:                S_EXPECT_CHALLENGE,
                     95:                S_EXPECT_RESPONSE,
                     96:                S_EXPECT_SUCCESS,
                     97:                S_DONE,
                     98:        } state;
                     99: };
                    100: 
                    101: /**
                    102:  * OpCodes
                    103:  */
                    104: enum mschapv2_opcode_t
                    105: {
                    106:        MSCHAPV2_CHALLENGE = 1,
                    107:        MSCHAPV2_RESPONSE = 2,
                    108:        MSCHAPV2_SUCCESS = 3,
                    109:        MSCHAPV2_FAILURE = 4,
                    110:        MSCHAPV2_CHANGE_PASSWORD = 7,
                    111: };
                    112: 
                    113: /**
                    114:  * Names for OpCodes
                    115:  */
                    116: ENUM_BEGIN(mschapv2_opcode_names, MSCHAPV2_CHALLENGE, MSCHAPV2_FAILURE,
                    117:                "CHALLENGE",
                    118:                "RESPONSE",
                    119:                "SUCCESS",
                    120:                "FAILURE");
                    121: ENUM_NEXT(mschapv2_opcode_names, MSCHAPV2_CHANGE_PASSWORD, MSCHAPV2_CHANGE_PASSWORD, MSCHAPV2_FAILURE,
                    122:                "CHANGE_PASSWORD");
                    123: ENUM_END(mschapv2_opcode_names, MSCHAPV2_CHANGE_PASSWORD);
                    124: 
                    125: /**
                    126:  * Error codes
                    127:  */
                    128: enum mschapv2_error_t
                    129: {
                    130:        ERROR_RESTRICTED_LOGON_HOURS    = 646,
                    131:        ERROR_ACCT_DISABLED                             = 647,
                    132:        ERROR_PASSWD_EXPIRED                    = 648,
                    133:        ERROR_NO_DIALIN_PERMISSION              = 649,
                    134:        ERROR_AUTHENTICATION_FAILURE    = 691,
                    135:        ERROR_CHANGING_PASSWORD                 = 709,
                    136: };
                    137: 
                    138: /**
                    139:  * Names for error codes
                    140:  */
                    141: ENUM_BEGIN(mschapv2_error_names, ERROR_RESTRICTED_LOGON_HOURS, ERROR_NO_DIALIN_PERMISSION,
                    142:                "ERROR_RESTRICTED_LOGON_HOURS",
                    143:                "ERROR_ACCT_DISABLED",
                    144:                "ERROR_PASSWD_EXPIRED",
                    145:                "ERROR_NO_DIALIN_PERMISSION");
                    146: ENUM_NEXT(mschapv2_error_names, ERROR_AUTHENTICATION_FAILURE, ERROR_AUTHENTICATION_FAILURE, ERROR_NO_DIALIN_PERMISSION,
                    147:                "ERROR_AUTHENTICATION_FAILURE");
                    148: ENUM_NEXT(mschapv2_error_names, ERROR_CHANGING_PASSWORD, ERROR_CHANGING_PASSWORD, ERROR_AUTHENTICATION_FAILURE,
                    149:                "ERROR_CHANGING_PASSWORD");
                    150: ENUM_END(mschapv2_error_names, ERROR_CHANGING_PASSWORD);
                    151: 
                    152: /* Length of the challenge */
                    153: #define CHALLENGE_LEN 16
                    154: /* Length of the response (see eap_mschapv2_response_t) */
                    155: #define RESPONSE_LEN 49
                    156: /* Length of the authenticator response string ("S=<...>") */
                    157: #define AUTH_RESPONSE_LEN 42
                    158: /* Name we send as authenticator */
                    159: #define MSCHAPV2_HOST_NAME "strongSwan"
                    160: /* Message sent on success */
                    161: #define SUCCESS_MESSAGE " M=Welcome2strongSwan"
                    162: /* Message sent on failure */
                    163: #define FAILURE_MESSAGE "E=691 R=1 C="
                    164: /* Length of the complete failure message */
                    165: #define FAILURE_MESSAGE_LEN (sizeof(FAILURE_MESSAGE) + CHALLENGE_LEN * 2)
                    166: 
                    167: /* Number of seconds to delay retries */
                    168: #define RETRY_DELAY 2
                    169: /* Maximum number of retries */
                    170: #define MAX_RETRIES 2
                    171: 
                    172: typedef struct eap_mschapv2_header_t eap_mschapv2_header_t;
                    173: typedef struct eap_mschapv2_challenge_t eap_mschapv2_challenge_t;
                    174: typedef struct eap_mschapv2_response_t eap_mschapv2_response_t;
                    175: 
                    176: /**
                    177:  * packed EAP-MS-CHAPv2 header struct
                    178:  */
                    179: struct eap_mschapv2_header_t
                    180: {
                    181:        /** EAP code (REQUEST/RESPONSE) */
                    182:        uint8_t code;
                    183:        /** unique message identifier */
                    184:        uint8_t identifier;
                    185:        /** length of whole message */
                    186:        uint16_t length;
                    187:        /** EAP type */
                    188:        uint8_t type;
                    189:        /** MS-CHAPv2 OpCode */
                    190:        uint8_t opcode;
                    191:        /** MS-CHAPv2-ID (equals identifier) */
                    192:        uint8_t ms_chapv2_id;
                    193:        /** MS-Length (defined as length - 5) */
                    194:        uint16_t ms_length;
                    195:        /** packet data (determined by OpCode) */
                    196:        uint8_t data[];
                    197: }__attribute__((__packed__));
                    198: 
                    199: /**
                    200:  * packed data for a MS-CHAPv2 Challenge packet
                    201:  */
                    202: struct eap_mschapv2_challenge_t
                    203: {
                    204:        /** Value-Size */
                    205:        uint8_t value_size;
                    206:        /** Challenge */
                    207:        uint8_t challenge[CHALLENGE_LEN];
                    208:        /** Name */
                    209:        uint8_t name[];
                    210: }__attribute__((__packed__));
                    211: 
                    212: /**
                    213:  * packed data for a MS-CHAPv2 Response packet
                    214:  */
                    215: struct eap_mschapv2_response_t
                    216: {
                    217:        /** Value-Size */
                    218:        uint8_t value_size;
                    219:        /** Response */
                    220:        struct
                    221:        {
                    222:                /* Peer-Challenge*/
                    223:                uint8_t peer_challenge[CHALLENGE_LEN];
                    224:                /* Reserved (=zero) */
                    225:                uint8_t peer_reserved[8];
                    226:                /* NT-Response */
                    227:                uint8_t nt_response[24];
                    228:                /* Flags (=zero) */
                    229:                uint8_t flags;
                    230:        } response;
                    231:        /** Name */
                    232:        uint8_t name[];
                    233: }__attribute__((__packed__));
                    234: 
                    235: /**
                    236:  * Length of the MS-CHAPv2 header
                    237:  */
                    238: #define HEADER_LEN (sizeof(eap_mschapv2_header_t))
                    239: 
                    240: /**
                    241:  * Length of the header for MS-CHAPv2 success/failure packets (does not include
                    242:  * MS-CHAPv2-ID and MS-Length, i.e. 3 octets)
                    243:  */
                    244: #define SHORT_HEADER_LEN (HEADER_LEN - 3)
                    245: 
                    246: /**
                    247:  * The minimum length of an MS-CHAPv2 Challenge packet (the name MUST be
                    248:  * at least one octet)
                    249:  */
                    250: #define CHALLENGE_PAYLOAD_LEN (HEADER_LEN + sizeof(eap_mschapv2_challenge_t))
                    251: 
                    252: /**
                    253:  * The minimum length of an MS-CHAPv2 Response packet
                    254:  */
                    255: #define RESPONSE_PAYLOAD_LEN (HEADER_LEN + sizeof(eap_mschapv2_response_t))
                    256: 
                    257: 
                    258: /**
                    259:  * Expand a 56-bit key to a 64-bit DES key by adding parity bits (odd parity)
                    260:  */
                    261: static chunk_t ExpandDESKey(chunk_t key)
                    262: {
                    263:        static const u_char bitmask[] = { 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
                    264:        int i;
                    265:        u_char carry = 0;
                    266:        chunk_t expanded;
                    267: 
                    268:        /* expand the 7 octets to 8 octets */
                    269:        expanded = chunk_alloc(8);
                    270:        for (i = 0; i < 7; i++)
                    271:        {
                    272:                expanded.ptr[i] = ((key.ptr[i] & bitmask[i]) >> i) | (carry << (8 - i));
                    273:                carry = key.ptr[i] & ~bitmask[i];
                    274:        }
                    275:        expanded.ptr[7] = carry << 1;
                    276: 
                    277:        /* add parity bits to each octet */
                    278:        for (i = 0; i < 8; i++)
                    279:        {
                    280:                u_char val = expanded.ptr[i];
                    281:                val = (val ^ (val >> 4)) & 0x0f;
                    282:                expanded.ptr[i] |= (0x9669 >> val) & 1;
                    283:        }
                    284:        return expanded;
                    285: }
                    286: 
                    287: /**
                    288:  * Calculate the NT password hash (i.e. hash the (unicode) password with MD4)
                    289:  */
                    290: static status_t NtPasswordHash(chunk_t password, chunk_t *password_hash)
                    291: {
                    292:        hasher_t *hasher;
                    293:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD4);
                    294:        if (hasher == NULL)
                    295:        {
                    296:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no MD4 hasher available");
                    297:                return FAILED;
                    298:        }
                    299:        if (!hasher->allocate_hash(hasher, password, password_hash))
                    300:        {
                    301:                hasher->destroy(hasher);
                    302:                return FAILED;
                    303:        }
                    304:        hasher->destroy(hasher);
                    305:        return SUCCESS;
                    306: }
                    307: 
                    308: /**
                    309:  * Calculate the challenge hash (i.e. hash [peer_challenge | server_challenge |
                    310:  * username (without domain part)] with SHA1)
                    311:  */
                    312: static status_t ChallengeHash(chunk_t peer_challenge, chunk_t server_challenge,
                    313:                                                          chunk_t username, chunk_t *challenge_hash)
                    314: {
                    315:        chunk_t concat;
                    316:        hasher_t *hasher;
                    317:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                    318:        if (hasher == NULL)
                    319:        {
                    320:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, SHA1 not supported");
                    321:                return FAILED;
                    322:        }
                    323:        concat = chunk_cata("ccc", peer_challenge, server_challenge, username);
                    324:        if (!hasher->allocate_hash(hasher, concat, challenge_hash))
                    325:        {
                    326:                hasher->destroy(hasher);
                    327:                return FAILED;
                    328:        }
                    329:        hasher->destroy(hasher);
                    330:        /* we need only the first 8 octets */
                    331:        challenge_hash->len = 8;
                    332:        return SUCCESS;
                    333: }
                    334: 
                    335: /**
                    336:  * Calculate the challenge response (i.e. expand password_hash to three DES keys
                    337:  * and then encrypt the 8-octet challenge_hash with these keys and concatenate
                    338:  * the results).
                    339:  */
                    340: static status_t ChallengeResponse(chunk_t challenge_hash, chunk_t password_hash,
                    341:                                                                  chunk_t *response)
                    342: {
                    343:        int i;
                    344:        crypter_t *crypter;
                    345:        chunk_t keys[3], z_password_hash;
                    346:        crypter = lib->crypto->create_crypter(lib->crypto, ENCR_DES_ECB, 8);
                    347:        if (crypter == NULL)
                    348:        {
                    349:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, DES-ECB not supported");
                    350:                return FAILED;
                    351:        }
                    352:        /* prepare keys: first pad password_hash to 21 octets, these get then split
                    353:         * into 7-octet chunks, which then get expanded into 8-octet DES keys */
                    354:        z_password_hash = chunk_alloca(21);
                    355:        memset(z_password_hash.ptr, 0, z_password_hash.len);
                    356:        memcpy(z_password_hash.ptr, password_hash.ptr, password_hash.len);
                    357:        chunk_split(z_password_hash, "mmm", 7, &keys[0], 7, &keys[1], 7, &keys[2]);
                    358: 
                    359:        *response = chunk_alloc(24);
                    360:        for (i = 0; i < 3; i++)
                    361:        {
                    362:                chunk_t expanded, encrypted;
                    363: 
                    364:                expanded = ExpandDESKey(keys[i]);
                    365:                if (!crypter->set_key(crypter, expanded) ||
                    366:                        !crypter->encrypt(crypter, challenge_hash, chunk_empty, &encrypted))
                    367:                {
                    368:                        chunk_clear(&expanded);
                    369:                        crypter->destroy(crypter);
                    370:                        return FAILED;
                    371:                }
                    372:                memcpy(&response->ptr[i * 8], encrypted.ptr, encrypted.len);
                    373:                chunk_clear(&encrypted);
                    374:                chunk_clear(&expanded);
                    375:        }
                    376:        crypter->destroy(crypter);
                    377:        return SUCCESS;
                    378: }
                    379: 
                    380: /**
                    381:  * Computes the authenticator response
                    382:  */
                    383: static status_t AuthenticatorResponse(chunk_t password_hash_hash,
                    384:                chunk_t challenge_hash, chunk_t nt_response, chunk_t *response)
                    385: {
                    386:        chunk_t magic1 = chunk_from_chars(
                    387:                0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
                    388:                0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
                    389:                0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
                    390:                0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74);
                    391:        chunk_t magic2 = chunk_from_chars(
                    392:                0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
                    393:                0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
                    394:                0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
                    395:                0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
                    396:                0x6E);
                    397:        chunk_t digest = chunk_empty, concat;
                    398:        hasher_t *hasher;
                    399: 
                    400:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                    401:        if (hasher == NULL)
                    402:        {
                    403:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, SHA1 not supported");
                    404:                return FAILED;
                    405:        }
                    406: 
                    407:        concat = chunk_cata("ccc", password_hash_hash, nt_response, magic1);
                    408:        if (!hasher->allocate_hash(hasher, concat, &digest))
                    409:        {
                    410:                hasher->destroy(hasher);
                    411:                return FAILED;
                    412:        }
                    413:        concat = chunk_cata("ccc", digest, challenge_hash, magic2);
                    414:        if (!hasher->allocate_hash(hasher, concat, response))
                    415:        {
                    416:                hasher->destroy(hasher);
                    417:                return FAILED;
                    418:        }
                    419:        hasher->destroy(hasher);
                    420:        chunk_free(&digest);
                    421:        return SUCCESS;
                    422: }
                    423: 
                    424: /**
                    425:  * Generate the master session key according to RFC3079
                    426:  */
                    427: static status_t GenerateMSK(chunk_t password_hash_hash,
                    428:                                                        chunk_t nt_response, chunk_t *msk)
                    429: {
                    430:        chunk_t magic1 = chunk_from_chars(
                    431:                0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
                    432:                0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
                    433:                0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79);
                    434:        chunk_t magic2 = chunk_from_chars(
                    435:                0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
                    436:                0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
                    437:                0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
                    438:                0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
                    439:                0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
                    440:                0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
                    441:                0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
                    442:                0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
                    443:                0x6b, 0x65, 0x79, 0x2e);
                    444:        chunk_t magic3 = chunk_from_chars(
                    445:                0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
                    446:                0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
                    447:                0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
                    448:                0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
                    449:                0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
                    450:                0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
                    451:                0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
                    452:                0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
                    453:                0x6b, 0x65, 0x79, 0x2e);
                    454:        chunk_t shapad1 = chunk_from_chars(
                    455:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    456:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    457:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    458:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                    459:        chunk_t shapad2 = chunk_from_chars(
                    460:                0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
                    461:                0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
                    462:                0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
                    463:                0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2);
                    464:        chunk_t keypad = chunk_from_chars(
                    465:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    466:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                    467:        char master_key[HASH_SIZE_SHA1];
                    468:        char master_receive_key[HASH_SIZE_SHA1], master_send_key[HASH_SIZE_SHA1];
                    469:        chunk_t concat, master;
                    470:        hasher_t *hasher;
                    471: 
                    472:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                    473:        if (hasher == NULL)
                    474:        {
                    475:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, SHA1 not supported");
                    476:                return FAILED;
                    477:        }
                    478: 
                    479:        concat = chunk_cata("ccc", password_hash_hash, nt_response, magic1);
                    480:        if (!hasher->get_hash(hasher, concat, master_key))
                    481:        {
                    482:                hasher->destroy(hasher);
                    483:                return FAILED;
                    484:        }
                    485:        master = chunk_create(master_key, 16);
                    486:        concat = chunk_cata("cccc", master, shapad1, magic2, shapad2);
                    487:        if (!hasher->get_hash(hasher, concat, master_receive_key))
                    488:        {
                    489:                hasher->destroy(hasher);
                    490:                return FAILED;
                    491:        }
                    492:        concat = chunk_cata("cccc", master, shapad1, magic3, shapad2);
                    493:        if (!hasher->get_hash(hasher, concat, master_send_key))
                    494:        {
                    495:                hasher->destroy(hasher);
                    496:                return FAILED;
                    497:        }
                    498: 
                    499:        *msk = chunk_cat("cccc", chunk_create(master_receive_key, 16),
                    500:                                         chunk_create(master_send_key, 16), keypad, keypad);
                    501: 
                    502:        hasher->destroy(hasher);
                    503:        return SUCCESS;
                    504: }
                    505: 
                    506: static status_t GenerateStuff(private_eap_mschapv2_t *this,
                    507:                                                          chunk_t server_challenge, chunk_t peer_challenge,
                    508:                                                          chunk_t username, chunk_t nt_hash)
                    509: {
                    510:        status_t status = FAILED;
                    511:        chunk_t nt_hash_hash = chunk_empty, challenge_hash = chunk_empty;
                    512: 
                    513:        if (NtPasswordHash(nt_hash, &nt_hash_hash) != SUCCESS)
                    514:        {
                    515:                goto error;
                    516:        }
                    517:        if (ChallengeHash(peer_challenge, server_challenge, username,
                    518:                                                &challenge_hash) != SUCCESS)
                    519:        {
                    520:                goto error;
                    521:        }
                    522:        if (ChallengeResponse(challenge_hash, nt_hash,
                    523:                                                &this->nt_response) != SUCCESS)
                    524:        {
                    525:                goto error;
                    526:        }
                    527:        if (AuthenticatorResponse(nt_hash_hash, challenge_hash,
                    528:                                                this->nt_response, &this->auth_response) != SUCCESS)
                    529:        {
                    530:                goto error;
                    531:        }
                    532:        if (GenerateMSK(nt_hash_hash, this->nt_response, &this->msk) != SUCCESS)
                    533:        {
                    534:                goto error;
                    535:        }
                    536: 
                    537:        status = SUCCESS;
                    538: 
                    539: error:
                    540:        chunk_free(&nt_hash_hash);
                    541:        chunk_free(&challenge_hash);
                    542:        return status;
                    543: }
                    544: 
                    545: /**
                    546:  * Try to decode the UTF-8 byte sequence utf8 points to and advance the
                    547:  * position.  Returns FALSE if the byte sequence is incomplete (the actual
                    548:  * values are not validated).
                    549:  */
                    550: static inline bool decode_utf8(chunk_t *utf8, uint32_t *c)
                    551: {
                    552:        uint8_t b1, b2, b3, b4;
                    553:        int i = 0;
                    554: 
                    555:        if (!utf8->len)
                    556:        {
                    557:                return FALSE;
                    558:        }
                    559: 
                    560:        b1 = utf8->ptr[i++];
                    561:        if (b1 & 0x80)
                    562:        {
                    563:                if (i == utf8->len)
                    564:                {
                    565:                        return FALSE;
                    566:                }
                    567:                b2 = utf8->ptr[i++];
                    568:                if (b1 < 0xe0)
                    569:                {       /* two-byte encoding */
                    570:                        *c = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
                    571:                        goto done;
                    572:                }
                    573:                if (i == utf8->len)
                    574:                {
                    575:                        return FALSE;
                    576:                }
                    577:                b3 = utf8->ptr[i++];
                    578:                if (b1 < 0xf0)
                    579:                {       /* three-byte encoding */
                    580:                        *c = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
                    581:                        goto done;
                    582:                }
                    583:                if (i == utf8->len)
                    584:                {
                    585:                        return FALSE;
                    586:                }
                    587:                b4 = utf8->ptr[i++];
                    588:                /* four-byte encoding */
                    589:                *c =  ((b1 & 0x07) << 18) | ((b2 & 0x3f) << 12) |
                    590:                          ((b3 & 0x3f) << 6) | (b4 & 0x3f);
                    591:        }
                    592:        else
                    593:        {       /* single-byte ASCII */
                    594:                *c = b1;
                    595:        }
                    596: 
                    597: done:
                    598:        *utf8 = chunk_skip(*utf8, i);
                    599:        return TRUE;
                    600: }
                    601: 
                    602: /**
                    603:  * Encode the given code point (or surrogate) as UTF-16LE where utf16 points
                    604:  * to and advance the position.
                    605:  */
                    606: static inline void encode_utf16le_single(chunk_t *utf16, uint16_t c)
                    607: {
                    608:        if (utf16->len >= 2)
                    609:        {
                    610:                utf16->ptr[0] = c & 0xff;
                    611:                utf16->ptr[1] = c >> 8;
                    612:                *utf16 = chunk_skip(*utf16, 2);
                    613:        }
                    614: }
                    615: 
                    616: /**
                    617:  * Encode the given code point as UTF-16LE where utf16 points to and advance
                    618:  * the position.  Invalid code points are ignored.
                    619:  */
                    620: static inline void encode_utf16le(chunk_t *utf16, uint32_t c)
                    621: {
                    622: 
                    623:        if (c >= 0xd800 && (c <= 0xdfff || c > 0x10ffff ||
                    624:                (0xfdd0 <= c && (c <= 0xfdef || (c & 0xfffe) == 0xfffe))))
                    625:        {       /* ignore code points that are not characters: single surrogates
                    626:                 * 0xd800..0xdfff, any value > 0x10ffff, 0xfdd0..0xfdef as per
                    627:                 * Unicode 3.1, the last two in each plane 0x__fffe and 0x__ffff. */
                    628:                return;
                    629:        }
                    630:        if (c < 0x10000)
                    631:        {       /* BMP code points */
                    632:                encode_utf16le_single(utf16, c);
                    633:        }
                    634:        else
                    635:        {       /* supplementary code points are split into two 16-bit surrogates */
                    636:                encode_utf16le_single(utf16, 0xd7c0 + (c >> 10));
                    637:                encode_utf16le_single(utf16, 0xdc00 | (c & 0x3ff));
                    638:        }
                    639: }
                    640: 
                    641: /**
                    642:  * Converts an (assumed) UTF-8 string into a UTF-16 (little-endian) string
                    643:  */
                    644: static chunk_t utf8_to_utf16le(chunk_t utf8)
                    645: {
                    646:        chunk_t utf16, buf;
                    647:        uint32_t c;
                    648: 
                    649:        /* unless the input is ASCII-only this will generally be too much, but
                    650:         * doesn't really matter for the length of strings processed here */
                    651:        utf16 = buf = chunk_alloc(utf8.len * 2);
                    652: 
                    653:        while (decode_utf8(&utf8, &c))
                    654:        {
                    655:                encode_utf16le(&buf, c);
                    656:        }
                    657: 
                    658:        utf16.len = utf16.len - buf.len;
                    659: 
                    660:        return utf16;
                    661: }
                    662: 
                    663: /**
                    664:  * sanitize a string for printing
                    665:  */
                    666: static char* sanitize(char *str)
                    667: {
                    668:        char *pos = str;
                    669: 
                    670:        while (pos && *pos)
                    671:        {
                    672:                if (!isprint(*pos))
                    673:                {
                    674:                        *pos = '?';
                    675:                }
                    676:                pos++;
                    677:        }
                    678:        return str;
                    679: }
                    680: 
                    681: /**
                    682:  * Returns a chunk of just the username part of the given user identity.
                    683:  * Note: the chunk points to internal data of the given chunk
                    684:  */
                    685: static chunk_t extract_username(chunk_t id)
                    686: {
                    687:        char *has_domain;
                    688: 
                    689:        has_domain = (char*)memchr(id.ptr, '\\', id.len);
                    690:        if (has_domain)
                    691:        {
                    692:                int len;
                    693:                has_domain++; /* skip the backslash */
                    694:                len = id.len - ((u_char*)has_domain - id.ptr);
                    695:                return len > 0 ? chunk_create(has_domain, len) : chunk_empty;
                    696:        }
                    697:        return id;
                    698: }
                    699: 
                    700: /**
                    701:  * Set the ms_length field using aligned write
                    702:  */
                    703: static void set_ms_length(eap_mschapv2_header_t *eap, uint16_t len)
                    704: {
                    705:        len = htons(len - 5);
                    706:        memcpy(&eap->ms_length, &len, sizeof(uint16_t));
                    707: }
                    708: 
                    709: METHOD(eap_method_t, initiate_peer, status_t,
                    710:        private_eap_mschapv2_t *this, eap_payload_t **out)
                    711: {
                    712:        /* peer never initiates */
                    713:        return FAILED;
                    714: }
                    715: 
                    716: METHOD(eap_method_t, initiate_server, status_t,
                    717:        private_eap_mschapv2_t *this, eap_payload_t **out)
                    718: {
                    719:        rng_t *rng;
                    720:        eap_mschapv2_header_t *eap;
                    721:        eap_mschapv2_challenge_t *cha;
                    722:        const char *name = MSCHAPV2_HOST_NAME;
                    723:        uint16_t len = CHALLENGE_PAYLOAD_LEN + sizeof(MSCHAPV2_HOST_NAME) - 1;
                    724: 
                    725:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                    726:        if (!rng || !rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge))
                    727:        {
                    728:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, no challenge");
                    729:                DESTROY_IF(rng);
                    730:                return FAILED;
                    731:        }
                    732:        rng->destroy(rng);
                    733: 
                    734:        eap = alloca(len);
                    735:        eap->code = EAP_REQUEST;
                    736:        eap->identifier = this->identifier;
                    737:        eap->length = htons(len);
                    738:        eap->type = EAP_MSCHAPV2;
                    739:        eap->opcode = MSCHAPV2_CHALLENGE;
                    740:        eap->ms_chapv2_id = this->mschapv2id;
                    741:        set_ms_length(eap, len);
                    742: 
                    743:        cha = (eap_mschapv2_challenge_t*)eap->data;
                    744:        cha->value_size = CHALLENGE_LEN;
                    745:        memcpy(cha->challenge, this->challenge.ptr, this->challenge.len);
                    746:        memcpy(cha->name, name, sizeof(MSCHAPV2_HOST_NAME) - 1);
                    747: 
                    748:        *out = eap_payload_create_data(chunk_create((void*) eap, len));
                    749:        this->state = S_EXPECT_RESPONSE;
                    750:        return NEED_MORE;
                    751: }
                    752: 
                    753: static bool get_nt_hash(private_eap_mschapv2_t *this, identification_t *me,
                    754:                                           identification_t *other, chunk_t *nt_hash)
                    755: {
                    756:        shared_key_t *shared;
                    757:        chunk_t password;
                    758: 
                    759:        /* try to find a stored NT_HASH first */
                    760:        shared = lib->credmgr->get_shared(lib->credmgr, SHARED_NT_HASH, me, other);
                    761:        if (shared )
                    762:        {
                    763:                *nt_hash = chunk_clone(shared->get_key(shared));
                    764:                shared->destroy(shared);
                    765:                return TRUE;
                    766:        }
                    767: 
                    768:        /* fallback to plaintext password */
                    769:        shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, me, other);
                    770:        if (shared)
                    771:        {
                    772:                password = utf8_to_utf16le(shared->get_key(shared));
                    773:                shared->destroy(shared);
                    774: 
                    775:                if (NtPasswordHash(password, nt_hash) == SUCCESS)
                    776:                {
                    777:                        chunk_clear(&password);
                    778:                        return TRUE;
                    779:                }
                    780:                chunk_clear(&password);
                    781:        }
                    782:        return FALSE;
                    783: }
                    784: 
                    785: /**
                    786:  * Process MS-CHAPv2 Challenge Requests
                    787:  */
                    788: static status_t process_peer_challenge(private_eap_mschapv2_t *this,
                    789:                                                                           eap_payload_t *in, eap_payload_t **out)
                    790: {
                    791:        rng_t *rng;
                    792:        eap_mschapv2_header_t *eap;
                    793:        eap_mschapv2_challenge_t *cha;
                    794:        eap_mschapv2_response_t *res;
                    795:        chunk_t data, peer_challenge, userid, username, nt_hash;
                    796:        uint16_t len = RESPONSE_PAYLOAD_LEN;
                    797: 
                    798:        data = in->get_data(in);
                    799:        eap = (eap_mschapv2_header_t*)data.ptr;
                    800: 
                    801:        /* the name MUST be at least one octet long */
                    802:        if (data.len < CHALLENGE_PAYLOAD_LEN + 1)
                    803:        {
                    804:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
                    805:                return FAILED;
                    806:        }
                    807: 
                    808:        cha = (eap_mschapv2_challenge_t*)eap->data;
                    809: 
                    810:        if (cha->value_size != CHALLENGE_LEN)
                    811:        {
                    812:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
                    813:                         "invalid challenge size");
                    814:                return FAILED;
                    815:        }
                    816: 
                    817:        this->mschapv2id = eap->ms_chapv2_id;
                    818:        this->challenge = chunk_clone(chunk_create(cha->challenge, CHALLENGE_LEN));
                    819: 
                    820:        peer_challenge = chunk_alloca(CHALLENGE_LEN);
                    821:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                    822:        if (!rng || !rng->get_bytes(rng, CHALLENGE_LEN, peer_challenge.ptr))
                    823:        {
                    824:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, allocating challenge failed");
                    825:                DESTROY_IF(rng);
                    826:                return FAILED;
                    827:        }
                    828:        rng->destroy(rng);
                    829: 
                    830:        if (!get_nt_hash(this, this->peer, this->server, &nt_hash))
                    831:        {
                    832:                DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'",
                    833:                         this->server, this->peer);
                    834:                return NOT_FOUND;
                    835:        }
                    836: 
                    837:        /* we transmit the whole user identity (including the domain part) but
                    838:         * only use the user part when calculating the challenge hash */
                    839:        userid = this->peer->get_encoding(this->peer);
                    840:        len += userid.len;
                    841:        username = extract_username(userid);
                    842: 
                    843:        if (GenerateStuff(this, this->challenge, peer_challenge,
                    844:                                          username, nt_hash) != SUCCESS)
                    845:        {
                    846:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 generating NT-Response failed");
                    847:                chunk_clear(&nt_hash);
                    848:                return FAILED;
                    849:        }
                    850:        chunk_clear(&nt_hash);
                    851: 
                    852:        eap = alloca(len);
                    853:        eap->code = EAP_RESPONSE;
                    854:        eap->identifier = this->identifier;
                    855:        eap->length = htons(len);
                    856:        eap->type = EAP_MSCHAPV2;
                    857:        eap->opcode = MSCHAPV2_RESPONSE;
                    858:        eap->ms_chapv2_id = this->mschapv2id;
                    859:        set_ms_length(eap, len);
                    860: 
                    861:        res = (eap_mschapv2_response_t*)eap->data;
                    862:        res->value_size = RESPONSE_LEN;
                    863:        memset(&res->response, 0, RESPONSE_LEN);
                    864:        memcpy(res->response.peer_challenge, peer_challenge.ptr, peer_challenge.len);
                    865:        memcpy(res->response.nt_response, this->nt_response.ptr, this->nt_response.len);
                    866:        memcpy(res->name, userid.ptr, userid.len);
                    867: 
                    868:        *out = eap_payload_create_data(chunk_create((void*) eap, len));
                    869:        this->state = S_EXPECT_SUCCESS;
                    870:        return NEED_MORE;
                    871: }
                    872: 
                    873: /**
                    874:  * Process MS-CHAPv2 Success Requests
                    875:  */
                    876: static status_t process_peer_success(private_eap_mschapv2_t *this,
                    877:                                                                          eap_payload_t *in, eap_payload_t **out)
                    878: {
                    879:        status_t status = FAILED;
                    880:        enumerator_t *enumerator;
                    881:        eap_mschapv2_header_t *eap;
                    882:        chunk_t data, auth_string = chunk_empty;
                    883:        char *message, *token, *msg = NULL;
                    884:        int message_len;
                    885:        uint16_t len = SHORT_HEADER_LEN;
                    886: 
                    887:        data = in->get_data(in);
                    888:        eap = (eap_mschapv2_header_t*)data.ptr;
                    889: 
                    890:        if (data.len < AUTH_RESPONSE_LEN)
                    891:        {
                    892:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
                    893:                return FAILED;
                    894:        }
                    895: 
                    896:        message_len = data.len - HEADER_LEN;
                    897:        message = malloc(message_len + 1);
                    898:        memcpy(message, eap->data, message_len);
                    899:        message[message_len] = '\0';
                    900: 
                    901:        /* S=<auth_string> M=<msg> */
                    902:        enumerator = enumerator_create_token(message, " ", " ");
                    903:        while (enumerator->enumerate(enumerator, &token))
                    904:        {
                    905:                if (strpfx(token, "S="))
                    906:                {
                    907:                        chunk_t hex;
                    908:                        token += 2;
                    909:                        if (strlen(token) != AUTH_RESPONSE_LEN - 2)
                    910:                        {
                    911:                                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
                    912:                                         "invalid auth string");
                    913:                                goto error;
                    914:                        }
                    915:                        chunk_free(&auth_string);
                    916:                        hex = chunk_create(token, AUTH_RESPONSE_LEN - 2);
                    917:                        auth_string = chunk_from_hex(hex, NULL);
                    918:                }
                    919:                else if (strpfx(token, "M="))
                    920:                {
                    921:                        token += 2;
                    922:                        free(msg);
                    923:                        msg = strdup(token);
                    924:                }
                    925:        }
                    926:        enumerator->destroy(enumerator);
                    927: 
                    928:        if (auth_string.ptr == NULL)
                    929:        {
                    930:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
                    931:                         "auth string missing");
                    932:                goto error;
                    933:        }
                    934: 
                    935:        if (!chunk_equals_const(this->auth_response, auth_string))
                    936:        {
                    937:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
                    938:                goto error;
                    939:        }
                    940: 
                    941:        DBG1(DBG_IKE, "EAP-MS-CHAPv2 succeeded: '%s'", sanitize(msg));
                    942: 
                    943:        eap = alloca(len);
                    944:        eap->code = EAP_RESPONSE;
                    945:        eap->identifier = this->identifier;
                    946:        eap->length = htons(len);
                    947:        eap->type = EAP_MSCHAPV2;
                    948:        eap->opcode = MSCHAPV2_SUCCESS;
                    949: 
                    950:        *out = eap_payload_create_data(chunk_create((void*) eap, len));
                    951:        status = NEED_MORE;
                    952:        this->state = S_DONE;
                    953: 
                    954: error:
                    955:        chunk_free(&auth_string);
                    956:        free(message);
                    957:        free(msg);
                    958:        return status;
                    959: }
                    960: 
                    961: static status_t process_peer_failure(private_eap_mschapv2_t *this,
                    962:                                                                         eap_payload_t *in, eap_payload_t **out)
                    963: {
                    964:        status_t status = FAILED;
                    965:        enumerator_t *enumerator;
                    966:        eap_mschapv2_header_t *eap;
                    967:        chunk_t data;
                    968:        char *message, *token, *msg = NULL;
                    969:        int message_len, error = 0;
                    970:        chunk_t challenge = chunk_empty;
                    971: 
                    972:        data = in->get_data(in);
                    973:        eap = (eap_mschapv2_header_t*)data.ptr;
                    974: 
                    975:        if (data.len < 3) /* we want at least an error code: E=e */
                    976:        {
                    977:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
                    978:                return FAILED;
                    979:        }
                    980: 
                    981:        message_len = data.len - HEADER_LEN;
                    982:        message = malloc(message_len + 1);
                    983:        memcpy(message, eap->data, message_len);
                    984:        message[message_len] = '\0';
                    985: 
                    986:        /* E=eeeeeeeeee R=r C=cccccccccccccccccccccccccccccccc V=vvvvvvvvvv M=<msg> */
                    987:        enumerator = enumerator_create_token(message, " ", " ");
                    988:        while (enumerator->enumerate(enumerator, &token))
                    989:        {
                    990:                if (strpfx(token, "E="))
                    991:                {
                    992:                        token += 2;
                    993:                        error = atoi(token);
                    994:                }
                    995:                else if (strpfx(token, "R="))
                    996:                {
                    997:                        /* ignore retriable */
                    998:                }
                    999:                else if (strpfx(token, "C="))
                   1000:                {
                   1001:                        chunk_t hex;
                   1002:                        token += 2;
                   1003:                        if (strlen(token) != 2 * CHALLENGE_LEN)
                   1004:                        {
                   1005:                                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message:"
                   1006:                                         "invalid challenge");
                   1007:                                goto error;
                   1008:                        }
                   1009:                        chunk_free(&challenge);
                   1010:                        hex = chunk_create(token, 2 * CHALLENGE_LEN);
                   1011:                        challenge = chunk_from_hex(hex, NULL);
                   1012:                }
                   1013:                else if (strpfx(token, "V="))
                   1014:                {
                   1015:                        /* ignore version */
                   1016:                }
                   1017:                else if (strpfx(token, "M="))
                   1018:                {
                   1019:                        token += 2;
                   1020:                        free(msg);
                   1021:                        msg = strdup(token);
                   1022:                }
                   1023:        }
                   1024:        enumerator->destroy(enumerator);
                   1025: 
                   1026:        DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed with error %N: '%s'",
                   1027:                 mschapv2_error_names, error, sanitize(msg));
                   1028: 
                   1029:        /**
                   1030:         * at this point, if the error is retriable, we MAY retry the authentication
                   1031:         * or MAY send a Change Password packet.
                   1032:         *
                   1033:         * if the error is not retriable (or if we do neither of the above), we
                   1034:         * SHOULD send a Failure Response packet.
                   1035:         * windows clients don't do that, and since windows server 2008 r2 behaves
                   1036:         * pretty odd if we do send a Failure Response, we just don't send one
                   1037:         * either. windows 7 actually sends a delete notify (which, according to the
                   1038:         * logs, results in an error on windows server 2008 r2).
                   1039:         *
                   1040:         * btw, windows server 2008 r2 does not send non-retriable errors for e.g.
                   1041:         * a disabled account but returns the windows error code in a notify payload
                   1042:         * of type 12345.
                   1043:         */
                   1044: 
                   1045:        status = FAILED;
                   1046:        this->state = S_DONE;
                   1047: 
                   1048: error:
                   1049:        chunk_free(&challenge);
                   1050:        free(message);
                   1051:        free(msg);
                   1052:        return status;
                   1053: }
                   1054: 
                   1055: METHOD(eap_method_t, process_peer, status_t,
                   1056:        private_eap_mschapv2_t *this, eap_payload_t *in, eap_payload_t **out)
                   1057: {
                   1058:        chunk_t data;
                   1059:        eap_mschapv2_header_t *eap;
                   1060: 
                   1061:        this->identifier = in->get_identifier(in);
                   1062:        data = in->get_data(in);
                   1063:        if (data.len < SHORT_HEADER_LEN)
                   1064:        {
                   1065:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message");
                   1066:                return FAILED;
                   1067:        }
                   1068: 
                   1069:        eap = (eap_mschapv2_header_t*)data.ptr;
                   1070: 
                   1071:        switch (this->state)
                   1072:        {
                   1073:                case S_EXPECT_CHALLENGE:
                   1074:                        if (eap->opcode == MSCHAPV2_CHALLENGE)
                   1075:                        {
                   1076:                                return process_peer_challenge(this, in, out);
                   1077:                        }
                   1078:                        break;
                   1079:                case S_EXPECT_SUCCESS:
                   1080:                        switch (eap->opcode)
                   1081:                        {
                   1082:                                case MSCHAPV2_SUCCESS:
                   1083:                                        return process_peer_success(this, in, out);
                   1084:                                case MSCHAPV2_FAILURE:
                   1085:                                        return process_peer_failure(this, in, out);
                   1086:                        }
                   1087:                        break;
                   1088:                default:
                   1089:                        break;
                   1090:        }
                   1091:        switch (eap->opcode)
                   1092:        {
                   1093:                case MSCHAPV2_CHALLENGE:
                   1094:                case MSCHAPV2_SUCCESS:
                   1095:                case MSCHAPV2_FAILURE:
                   1096:                        DBG1(DBG_IKE, "received unexpected EAP-MS-CHAPv2 message with "
                   1097:                                 "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
                   1098:                        break;
                   1099:                default:
                   1100:                        DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
                   1101:                                 "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
                   1102:                        break;
                   1103:        }
                   1104:        return FAILED;
                   1105: }
                   1106: 
                   1107: /**
                   1108:  * Handles retries on the server
                   1109:  */
                   1110: static status_t process_server_retry(private_eap_mschapv2_t *this,
                   1111:                                                                         eap_payload_t **out)
                   1112: {
                   1113:        eap_mschapv2_header_t *eap;
                   1114:        rng_t *rng;
                   1115:        chunk_t hex;
                   1116:        char msg[FAILURE_MESSAGE_LEN];
                   1117:        uint16_t len = HEADER_LEN + FAILURE_MESSAGE_LEN - 1; /* no null byte */
                   1118: 
                   1119:        if (++this->retries > MAX_RETRIES)
                   1120:        {
                   1121:                /* we MAY send a Failure Request with R=0, but windows 7 does not
                   1122:                 * really like that and does not respond with a Failure Response.
                   1123:                 * so, to clean up our state we just fail with an EAP-Failure.
                   1124:                 * this gives an unknown error on the windows side, but is also fine
                   1125:                 * with the standard. */
                   1126:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed: "
                   1127:                         "maximum number of retries reached");
                   1128:                return FAILED;
                   1129:        }
                   1130: 
                   1131:        DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed, retry (%d)", this->retries);
                   1132: 
                   1133:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                   1134:        if (!rng || !rng->get_bytes(rng, CHALLENGE_LEN, this->challenge.ptr))
                   1135:        {
                   1136:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed, allocating challenge failed");
                   1137:                DESTROY_IF(rng);
                   1138:                return FAILED;
                   1139:        }
                   1140:        rng->destroy(rng);
                   1141: 
                   1142:        chunk_free(&this->nt_response);
                   1143:        chunk_free(&this->auth_response);
                   1144:        chunk_free(&this->msk);
                   1145: 
                   1146:        eap = alloca(len);
                   1147:        eap->code = EAP_REQUEST;
                   1148:        eap->identifier = ++this->identifier;
                   1149:        eap->length = htons(len);
                   1150:        eap->type = EAP_MSCHAPV2;
                   1151:        eap->opcode = MSCHAPV2_FAILURE;
                   1152:        eap->ms_chapv2_id = this->mschapv2id++; /* increase for each retry */
                   1153:        set_ms_length(eap, len);
                   1154: 
                   1155:        hex = chunk_to_hex(this->challenge, NULL, TRUE);
                   1156:        snprintf(msg, FAILURE_MESSAGE_LEN, "%s%s", FAILURE_MESSAGE, hex.ptr);
                   1157:        chunk_free(&hex);
                   1158:        memcpy(eap->data, msg, FAILURE_MESSAGE_LEN - 1); /* no null byte */
                   1159:        *out = eap_payload_create_data(chunk_create((void*) eap, len));
                   1160: 
                   1161:        /* delay the response for some time to make brute-force attacks harder */
                   1162:        sleep(RETRY_DELAY);
                   1163: 
                   1164:        /* since the error is retriable the state does not change, we still
                   1165:         * expect an MSCHAPV2_RESPONSE from the peer */
                   1166:        return NEED_MORE;
                   1167: }
                   1168: 
                   1169: /**
                   1170:  * Process MS-CHAPv2 Response response packets
                   1171:  */
                   1172: static status_t process_server_response(private_eap_mschapv2_t *this,
                   1173:                                                                                eap_payload_t *in, eap_payload_t **out)
                   1174: {
                   1175:        eap_mschapv2_header_t *eap;
                   1176:        eap_mschapv2_response_t *res;
                   1177:        chunk_t data, peer_challenge, username, nt_hash;
                   1178:        identification_t *userid;
                   1179:        int name_len;
                   1180:        char buf[256];
                   1181: 
                   1182:        data = in->get_data(in);
                   1183:        eap = (eap_mschapv2_header_t*)data.ptr;
                   1184: 
                   1185:        if (data.len < RESPONSE_PAYLOAD_LEN)
                   1186:        {
                   1187:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
                   1188:                return FAILED;
                   1189:        }
                   1190: 
                   1191:        res = (eap_mschapv2_response_t*)eap->data;
                   1192:        peer_challenge = chunk_create(res->response.peer_challenge, CHALLENGE_LEN);
                   1193: 
                   1194:        name_len = min(data.len - RESPONSE_PAYLOAD_LEN, 255);
                   1195:        snprintf(buf, sizeof(buf), "%.*s", name_len, res->name);
                   1196:        userid = identification_create_from_string(buf);
                   1197:        if (!userid->equals(userid, this->peer))
                   1198:        {
                   1199:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 username: '%Y'", userid);
                   1200:        }
                   1201:        /* userid can only be destroyed after the last use of username */
                   1202:        username = extract_username(userid->get_encoding(userid));
                   1203: 
                   1204:        if (!get_nt_hash(this, this->server, userid, &nt_hash))
                   1205:        {
                   1206:                DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'",
                   1207:                                          this->server, userid);
                   1208:                /* FIXME: windows 7 always sends the username that is first entered in
                   1209:                 * the username box, even, if the user changes it during retries (probably
                   1210:                 * to keep consistent with the EAP-Identity).
                   1211:                 * thus, we could actually fail here, because retries do not make much
                   1212:                 * sense. on the other hand, an attacker could guess usernames, if the
                   1213:                 * error messages were different. */
                   1214:                userid->destroy(userid);
                   1215:                return process_server_retry(this, out);
                   1216:        }
                   1217: 
                   1218:        if (GenerateStuff(this, this->challenge, peer_challenge,
                   1219:                                          username, nt_hash) != SUCCESS)
                   1220:        {
                   1221:                DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
                   1222:                userid->destroy(userid);
                   1223:                chunk_clear(&nt_hash);
                   1224:                return FAILED;
                   1225:        }
                   1226:        chunk_clear(&nt_hash);
                   1227: 
                   1228:        if (memeq_const(res->response.nt_response, this->nt_response.ptr,
                   1229:                                        this->nt_response.len))
                   1230:        {
                   1231:                chunk_t hex;
                   1232:                char msg[AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE)];
                   1233:                uint16_t len = HEADER_LEN + AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE);
                   1234: 
                   1235:                eap = alloca(len);
                   1236:                eap->code = EAP_REQUEST;
                   1237:                eap->identifier = ++this->identifier;
                   1238:                eap->length = htons(len);
                   1239:                eap->type = EAP_MSCHAPV2;
                   1240:                eap->opcode = MSCHAPV2_SUCCESS;
                   1241:                eap->ms_chapv2_id = this->mschapv2id;
                   1242:                set_ms_length(eap, len);
                   1243: 
                   1244:                hex = chunk_to_hex(this->auth_response, NULL, TRUE);
                   1245:                snprintf(msg, AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE),
                   1246:                                          "S=%s%s", hex.ptr, SUCCESS_MESSAGE);
                   1247:                chunk_free(&hex);
                   1248:                memcpy(eap->data, msg, AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE));
                   1249:                *out = eap_payload_create_data(chunk_create((void*) eap, len));
                   1250: 
                   1251:                this->auth->add(this->auth, AUTH_RULE_EAP_IDENTITY, userid);
                   1252:                this->state = S_EXPECT_SUCCESS;
                   1253:                return NEED_MORE;
                   1254:        }
                   1255:        userid->destroy(userid);
                   1256:        return process_server_retry(this, out);
                   1257: }
                   1258: 
                   1259: METHOD(eap_method_t, process_server, status_t,
                   1260:        private_eap_mschapv2_t *this, eap_payload_t *in, eap_payload_t **out)
                   1261: {
                   1262:        eap_mschapv2_header_t *eap;
                   1263:        chunk_t data;
                   1264: 
                   1265:        if (this->identifier != in->get_identifier(in))
                   1266:        {
                   1267:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
                   1268:                         "unexpected identifier");
                   1269:                return FAILED;
                   1270:        }
                   1271: 
                   1272:        data = in->get_data(in);
                   1273:        if (data.len < SHORT_HEADER_LEN)
                   1274:        {
                   1275:                DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
                   1276:                return FAILED;
                   1277:        }
                   1278: 
                   1279:        eap = (eap_mschapv2_header_t*)data.ptr;
                   1280: 
                   1281:        switch (this->state)
                   1282:        {
                   1283:                case S_EXPECT_RESPONSE:
                   1284:                        if (eap->opcode == MSCHAPV2_RESPONSE)
                   1285:                        {
                   1286:                                return process_server_response(this, in, out);
                   1287:                        }
                   1288:                        break;
                   1289:                case S_EXPECT_SUCCESS:
                   1290:                        if (eap->opcode == MSCHAPV2_SUCCESS &&
                   1291:                                this->msk.ptr)
                   1292:                        {
                   1293:                                return SUCCESS;
                   1294:                        }
                   1295:                        break;
                   1296:                default:
                   1297:                        break;
                   1298:        }
                   1299:        switch (eap->opcode)
                   1300:        {
                   1301:                case MSCHAPV2_FAILURE:
                   1302:                        /* the client may abort the authentication by sending us a failure
                   1303:                         * in any state */
                   1304:                        return FAILED;
                   1305:                case MSCHAPV2_RESPONSE:
                   1306:                case MSCHAPV2_SUCCESS:
                   1307:                        DBG1(DBG_IKE, "received unexpected EAP-MS-CHAPv2 message with "
                   1308:                                 "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
                   1309:                        break;
                   1310:                default:
                   1311:                        DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
                   1312:                                 "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
                   1313:                        break;
                   1314:        }
                   1315:        return FAILED;
                   1316: }
                   1317: 
                   1318: METHOD(eap_method_t, get_type, eap_type_t,
                   1319:        private_eap_mschapv2_t *this, uint32_t *vendor)
                   1320: {
                   1321:        *vendor = 0;
                   1322:        return EAP_MSCHAPV2;
                   1323: }
                   1324: 
                   1325: METHOD(eap_method_t, get_msk, status_t,
                   1326:        private_eap_mschapv2_t *this, chunk_t *msk)
                   1327: {
                   1328:        if (this->msk.ptr)
                   1329:        {
                   1330:                *msk = this->msk;
                   1331:                return SUCCESS;
                   1332:        }
                   1333:        return FAILED;
                   1334: }
                   1335: 
                   1336: METHOD(eap_method_t, get_identifier, uint8_t,
                   1337:        private_eap_mschapv2_t *this)
                   1338: {
                   1339:        return this->identifier;
                   1340: }
                   1341: 
                   1342: METHOD(eap_method_t, set_identifier, void,
                   1343:        private_eap_mschapv2_t *this, uint8_t identifier)
                   1344: {
                   1345:        this->identifier = identifier;
                   1346: }
                   1347: 
                   1348: METHOD(eap_method_t, is_mutual, bool,
                   1349:        private_eap_mschapv2_t *this)
                   1350: {
                   1351:        return FALSE;
                   1352: }
                   1353: 
                   1354: METHOD(eap_method_t, get_auth, auth_cfg_t*,
                   1355:        private_eap_mschapv2_t *this)
                   1356: {
                   1357:        return this->auth;
                   1358: }
                   1359: 
                   1360: METHOD(eap_method_t, destroy, void,
                   1361:         private_eap_mschapv2_t *this)
                   1362: {
                   1363:        this->peer->destroy(this->peer);
                   1364:        this->server->destroy(this->server);
                   1365:        this->auth->destroy(this->auth);
                   1366:        chunk_free(&this->challenge);
                   1367:        chunk_free(&this->nt_response);
                   1368:        chunk_free(&this->auth_response);
                   1369:        chunk_free(&this->msk);
                   1370:        free(this);
                   1371: }
                   1372: 
                   1373: /**
                   1374:  * Generic constructor
                   1375:  */
                   1376: static private_eap_mschapv2_t *eap_mschapv2_create_generic(identification_t *server, identification_t *peer)
                   1377: {
                   1378:        private_eap_mschapv2_t *this;
                   1379: 
                   1380:        INIT(this,
                   1381:                .public = {
                   1382:                        .eap_method_interface = {
                   1383:                                .get_type = _get_type,
                   1384:                                .is_mutual = _is_mutual,
                   1385:                                .get_msk = _get_msk,
                   1386:                                .get_identifier = _get_identifier,
                   1387:                                .set_identifier = _set_identifier,
                   1388:                                .get_auth = _get_auth,
                   1389:                                .destroy = _destroy,
                   1390:                        },
                   1391:                },
                   1392:                .peer = peer->clone(peer),
                   1393:                .server = server->clone(server),
                   1394:                .auth = auth_cfg_create(),
                   1395:                .state = S_EXPECT_CHALLENGE,
                   1396:        );
                   1397: 
                   1398:        return this;
                   1399: }
                   1400: 
                   1401: /*
                   1402:  * see header
                   1403:  */
                   1404: eap_mschapv2_t *eap_mschapv2_create_server(identification_t *server, identification_t *peer)
                   1405: {
                   1406:        private_eap_mschapv2_t *this = eap_mschapv2_create_generic(server, peer);
                   1407: 
                   1408:        this->public.eap_method_interface.initiate = _initiate_server;
                   1409:        this->public.eap_method_interface.process = _process_server;
                   1410: 
                   1411:        /* generate a non-zero identifier */
                   1412:        do
                   1413:        {
                   1414:                this->identifier = random();
                   1415:        } while (!this->identifier);
                   1416: 
                   1417:        this->mschapv2id = this->identifier;
                   1418: 
                   1419:        return &this->public;
                   1420: }
                   1421: 
                   1422: /*
                   1423:  * see header
                   1424:  */
                   1425: eap_mschapv2_t *eap_mschapv2_create_peer(identification_t *server, identification_t *peer)
                   1426: {
                   1427:        private_eap_mschapv2_t *this = eap_mschapv2_create_generic(server, peer);
                   1428: 
                   1429:        this->public.eap_method_interface.initiate = _initiate_peer;
                   1430:        this->public.eap_method_interface.process = _process_peer;
                   1431: 
                   1432:        return &this->public;
                   1433: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>