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; }
int mresponse_main(int argc, char **argv) { uint8_t chap_ident = 0; uint8_t challenge[32]; char buffer[512]; MD5_CTX context; int idx = 0; int usent = 0; int usepap = 0; if (argc < 2) return usage(argv[0]); if (!strcmp(argv[1],"-nt")) { usent = 1; argc--; idx++; } if (!strcmp(argv[1],"-pap")) { usepap = 1; argc--; idx++; } if (usent && usepap) return usage(argv[0]); if (argc < 4) return usage(argv[0]); if (argc == 5) chap_ident = atoi(argv[idx+4]); /* challenge - argv 1 */ memset(buffer, 0, sizeof(buffer)); strcpy(buffer, argv[idx+1]); hextochar(buffer, challenge, MD5LEN); /* uamsecret - argv 2 */ MD5Init(&context); MD5Update(&context, challenge, MD5LEN); MD5Update(&context, (uint8_t*)argv[idx+2], strlen(argv[idx+2])); MD5Final(challenge, &context); if (usepap) { uint8_t user_password[RADIUS_PWSIZE + 1]; uint8_t p[RADIUS_PWSIZE + 1]; int m, n, plen = strlen(argv[idx+3]); memset(p, 0, sizeof(p)); safe_strncpy((char *)p, argv[idx+3], RADIUS_PWSIZE); for (m=0; m < plen;) { for (n=0; n < REDIR_MD5LEN; m++, n++) { user_password[m] = p[m] ^ challenge[n]; } } chartohex(user_password, buffer, plen); printf("%s\n", buffer); } else if (usent) { #ifdef HAVE_OPENSSL uint8_t ntresponse[24]; if (argc < 5) return usage(argv[0]); GenerateNTResponse(challenge, challenge, (uint8_t*)argv[idx+3], strlen(argv[idx+3]), (uint8_t*)argv[idx+4], strlen(argv[idx+4]), ntresponse); chartohex(ntresponse, buffer, 24); printf("%s\n", buffer); #else printf("Requires OpenSSL Support\n"); #endif } else { uint8_t response[32]; /* password - argv 3 */ MD5Init(&context); MD5Update(&context, (uint8_t*)&chap_ident, 1); MD5Update(&context, (uint8_t*)argv[idx+3], strlen(argv[idx+3])); MD5Update(&context, challenge, MD5LEN); MD5Final(response, &context); chartohex(response, buffer, MD5LEN); printf("%s\n", buffer); } return 0; }