static void GenerateAuthenticatorResponsePlain( const char *secret, int secret_len, u_char NTResponse[24], const u_char PeerChallenge[16], const u_char *rchallenge, const char *username, u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { u_char unicodePassword[MAX_NT_PASSWORD * 2]; u_char PasswordHash[MD4_SIGNATURE_SIZE]; u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, rchallenge, username, authResponse); }
/* * If PeerChallenge is NULL, one is generated and response->PeerChallenge * is filled in. Call this way when generating a response. * If PeerChallenge is supplied, it is copied into response->PeerChallenge. * Call this way when verifying a response (or debugging). * Do not call with PeerChallenge = response->PeerChallenge. * * response->PeerChallenge is then used for calculation of the * Authenticator Response. */ void ChapMS2(chap_state *cstate, u_char *rchallenge, u_char *PeerChallenge, char *user, char *secret, int secret_len, MS_Chap2Response *response, u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1], int authenticator) { /* ARGSUSED */ u_char *p = response->PeerChallenge; int i; BZERO(response, sizeof(*response)); /* Generate the Peer-Challenge if requested, or copy it if supplied. */ if (!PeerChallenge) { for (i = 0; i < sizeof(response->PeerChallenge); i++) { *p++ = (u_char) (lrand48() & 0xff); } } else { BCOPY(PeerChallenge, response->PeerChallenge, sizeof(response->PeerChallenge)); } /* Generate the NT-Response */ ChapMS2_NT(rchallenge, response->PeerChallenge, user, secret, secret_len, response->NTResp); /* Generate the Authenticator Response. */ GenerateAuthenticatorResponse(secret, secret_len, response->NTResp, response->PeerChallenge, rchallenge, user, authResponse); cstate->resp_length = MS_CHAP2_RESPONSE_LEN; #ifdef MPPE SetMasterKeys(secret, secret_len, response->NTResp, authenticator); mppe_keys_set = 1; #endif }
static char * chap_BuildAnswer(char *name, char *key, u_char id, char *challenge #ifndef NODES , u_char type, char *peerchallenge, char *authresponse, int lanman #endif ) { char *result, *digest; size_t nlen, klen; nlen = strlen(name); klen = strlen(key); #ifndef NODES if (type == 0x80) { char expkey[AUTHLEN << 2]; MD4_CTX MD4context; size_t f; if ((result = malloc(1 + nlen + MS_CHAP_RESPONSE_LEN)) == NULL) return result; digest = result; /* the response */ *digest++ = MS_CHAP_RESPONSE_LEN; /* 49 */ memcpy(digest + MS_CHAP_RESPONSE_LEN, name, nlen); if (lanman) { memset(digest + 24, '\0', 25); mschap_LANMan(digest, challenge + 1, key); /* LANMan response */ } else { memset(digest, '\0', 25); digest += 24; for (f = 0; f < klen; f++) { expkey[2*f] = key[f]; expkey[2*f+1] = '\0'; } /* * ----------- * expkey = | k\0e\0y\0 | * ----------- */ MD4Init(&MD4context); MD4Update(&MD4context, expkey, klen << 1); MD4Final(digest, &MD4context); /* * ---- -------- ---------------- ------- ------ * result = | 49 | LANMan | 16 byte digest | 9 * ? | name | * ---- -------- ---------------- ------- ------ */ mschap_NT(digest, challenge + 1); } /* * ---- -------- ------------- ----- ------ * | | struct MS_ChapResponse24 | | * result = | 49 | LANMan | NT digest | 0/1 | name | * ---- -------- ------------- ----- ------ * where only one of LANMan & NT digest are set. */ } else if (type == 0x81) { char expkey[AUTHLEN << 2]; char pwdhash[CHAP81_HASH_LEN]; char pwdhashhash[CHAP81_HASH_LEN]; char *ntresponse; size_t f; if ((result = malloc(1 + nlen + CHAP81_RESPONSE_LEN)) == NULL) return result; memset(result, 0, 1 + nlen + CHAP81_RESPONSE_LEN); digest = result; *digest++ = CHAP81_RESPONSE_LEN; /* value size */ /* Copy our challenge */ memcpy(digest, peerchallenge + 1, CHAP81_CHALLENGE_LEN); /* Expand password to Unicode XXX */ for (f = 0; f < klen; f++) { expkey[2*f] = key[f]; expkey[2*f+1] = '\0'; } ntresponse = digest + CHAP81_NTRESPONSE_OFF; /* Get some needed hashes */ NtPasswordHash(expkey, klen * 2, pwdhash); HashNtPasswordHash(pwdhash, pwdhashhash); /* Generate NTRESPONSE to respond on challenge call */ GenerateNTResponse(challenge + 1, peerchallenge + 1, name, expkey, klen * 2, ntresponse); /* Generate MPPE MASTERKEY */ GetMasterKey(pwdhashhash, ntresponse, MPPE_MasterKey); /* XXX Global ! */ /* Generate AUTHRESPONSE to verify on auth success */ GenerateAuthenticatorResponse(expkey, klen * 2, ntresponse, peerchallenge + 1, challenge + 1, name, authresponse); authresponse[CHAP81_AUTHRESPONSE_LEN] = 0; memcpy(digest + CHAP81_RESPONSE_LEN, name, nlen); } else #endif if ((result = malloc(nlen + 17)) != NULL) { /* Normal MD5 stuff */ MD5_CTX MD5context; digest = result; *digest++ = 16; /* value size */ MD5Init(&MD5context); MD5Update(&MD5context, &id, 1); MD5Update(&MD5context, key, klen); MD5Update(&MD5context, challenge + 1, *challenge); MD5Final(digest, &MD5context); memcpy(digest + 16, name, nlen); /* * ---- -------- ------ * result = | 16 | digest | name | * ---- -------- ------ */ } return result; }