void mschap_auth_response(u_int8_t *password, int passwordlen, u_int8_t *ntresponse, u_int8_t *auth_challenge, u_int8_t *peer_challenge, u_int8_t *username, int usernamelen, u_int8_t *auth_response) { EVP_MD_CTX ctx; u_int8_t password_hash[MSCHAP_HASH_SZ]; u_int8_t password_hash2[MSCHAP_HASH_SZ]; u_int8_t challenge[MSCHAP_CHALLENGE_SZ]; u_int8_t md[SHA_DIGEST_LENGTH], *ptr; u_int mdlen; int i; const u_int8_t hex[] = "0123456789ABCDEF"; static u_int8_t magic1[39] = { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; static u_int8_t magic2[41] = { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E }; mschap_ntpassword_hash(password, passwordlen, password_hash); mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2); EVP_DigestInit(&ctx, EVP_sha1()); EVP_DigestUpdate(&ctx, password_hash2, sizeof(password_hash2)); EVP_DigestUpdate(&ctx, ntresponse, 24); EVP_DigestUpdate(&ctx, magic1, 39); EVP_DigestFinal(&ctx, md, &mdlen); mschap_challenge_hash(peer_challenge, auth_challenge, username, usernamelen, challenge); EVP_DigestInit(&ctx, EVP_sha1()); EVP_DigestUpdate(&ctx, md, sizeof(md)); EVP_DigestUpdate(&ctx, challenge, sizeof(challenge)); EVP_DigestUpdate(&ctx, magic2, 41); EVP_DigestFinal(&ctx, md, &mdlen); /* * Encode the value of 'Digest' as "S=" followed by * 40 ASCII hexadecimal digits and return it in * AuthenticatorResponse. * For example, * "S=0123456789ABCDEF0123456789ABCDEF01234567" */ ptr = auth_response; *ptr++ = 'S'; *ptr++ = '='; for (i = 0; i < SHA_DIGEST_LENGTH; i++) { *ptr++ = hex[md[i] >> 4]; *ptr++ = hex[md[i] & 0x0f]; } }
void mschap_msk(u_int8_t *password, int passwordlen, u_int8_t *ntresponse, u_int8_t *msk) { u_int8_t password_hash[MSCHAP_HASH_SZ]; u_int8_t password_hash2[MSCHAP_HASH_SZ]; u_int8_t masterkey[MSCHAP_MASTERKEY_SZ]; u_int8_t sendkey[MSCHAP_MASTERKEY_SZ]; u_int8_t recvkey[MSCHAP_MASTERKEY_SZ]; mschap_ntpassword_hash(password, passwordlen, password_hash); mschap_ntpassword_hash(password_hash, MSCHAP_HASH_SZ, password_hash2); mschap_masterkey(password_hash2, ntresponse, masterkey); mschap_asymetric_startkey(masterkey, recvkey, sizeof(recvkey), 0, 1); mschap_asymetric_startkey(masterkey, sendkey, sizeof(sendkey), 1, 1); /* 16 bytes receive key + 16 bytes send key + 32 bytes 0 padding */ bzero(msk, MSCHAP_MSK_SZ); memcpy(msk, &recvkey, sizeof(recvkey)); memcpy(msk + sizeof(recvkey), &sendkey, sizeof(sendkey)); }
void mschap_nt_response(u_int8_t *auth_challenge, u_int8_t *peer_challenge, u_int8_t *username, int usernamelen, u_int8_t *password, int passwordlen, u_int8_t *response) { u_int8_t challenge[MSCHAP_CHALLENGE_SZ]; u_int8_t password_hash[MSCHAP_HASH_SZ]; mschap_challenge_hash(peer_challenge, auth_challenge, username, usernamelen, challenge); mschap_ntpassword_hash(password, passwordlen, password_hash); mschap_challenge_response(challenge, password_hash, response); }
static void mschapv2_authenticate(chap *_this, int id, char *username, u_char *challenge, int lchallenge, u_char *response) { int i, rval, passlen, lpkt; u_char *pkt; char password[MAX_PASSWORD_LENGTH * 2], ntresponse[24]; #ifdef USE_NPPPD_MPPE char pwdhash[16], pwdhashhash[16]; #endif CHAP_DBG((_this, LOG_DEBUG, "%s()", __func__)); pkt = ppp_packetbuf(_this->ppp, PPP_PROTO_CHAP) + HEADERLEN; lpkt = _this->ppp->mru - HEADERLEN; passlen = sizeof(password) / 2; rval = npppd_get_user_password(_this->ppp->pppd, _this->ppp, username, password, &passlen); if (rval != 0) { switch (rval) { case 1: chap_log(_this, LOG_INFO, "username=\"%s\" user unknown", username); break; default: chap_log(_this, LOG_ERR, "username=\"%s\" generic error", username); break; } goto auth_failed; } /* Convert the string charset from ASCII to UTF16-LE */ passlen = strlen(password); for (i = passlen - 1; i >= 0; i--) { password[i*2] = password[i]; password[i*2+1] = 0; } mschap_nt_response(challenge, response, username, strlen(username), password, passlen * 2, ntresponse); if (memcmp(ntresponse, response + 24, 24) != 0) { chap_log(_this, LOG_INFO, "username=\"%s\" password mismatch.", username); goto auth_failed; } /* * Authentication succeed */ CHAP_DBG((_this, LOG_DEBUG, "%s() OK", __func__)); mschap_auth_response(password, passlen * 2, ntresponse, challenge, response, username, strlen(username), pkt); lpkt = 42; #ifdef USE_NPPPD_MPPE if (_this->ppp->mppe.enabled != 0) { mschap_ntpassword_hash(password, passlen * 2, pwdhash); mschap_ntpassword_hash(pwdhash, sizeof(pwdhash), pwdhashhash); mschap_masterkey(pwdhashhash, ntresponse, _this->ppp->mppe.master_key); mschap_asymetric_startkey(_this->ppp->mppe.master_key, _this->ppp->mppe.recv.master_key, MPPE_KEYLEN, 0, 1); mschap_asymetric_startkey(_this->ppp->mppe.master_key, _this->ppp->mppe.send.master_key, MPPE_KEYLEN, 1, 1); } #endif chap_response(_this, 1, pkt, lpkt); return; auth_failed: /* No extra information */ mschapv2_send_error(_this, ERROR_AUTHENTICATION_FAILURE, 0); return; }