/*++ Copyright (c) 1989 Microsoft Corporation Module Name: response.c Abstract: Contains functions that calculate the correct response to return to the server when logging on. CalculateLmResponse Author: David Chalmers (Davidc) 10-21-91 David Arnold (DavidAr) 12-15-93 (Adapted for RPC SSP) Revision History: --*/ #ifdef BLDR_KERNEL_RUNTIME #include #endif #include #include #include #include // // Define the user session key that represents an error. // This value will be generated by other parts of the system on failure. // We will check for it in our query code and return an error if it's found. // USER_SESSION_KEY ErrorSessionKey = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; BOOL CalculateLmResponse( IN PLM_CHALLENGE LmChallenge, IN PLM_OWF_PASSWORD LmOwfPassword, OUT PLM_RESPONSE LmResponse ) /*++ Routine Description: Takes the challenge sent by the server and the OwfPassword generated from the password the user entered and calculates the response to return to the server. Arguments: LmChallenge - The challenge sent by the server LmOwfPassword - The hashed password. LmResponse - The response is returned here. Return Values: TRUE - The function completed successfully. The response is in LmResponse. FALSE - Something failed. The LmResponse is undefined. --*/ { BLOCK_KEY Key; PCHAR pKey, pData; // The first 2 keys we can get at by type-casting if (DES_ECB_LM(ENCR_KEY, (unsigned char *)&(((PBLOCK_KEY)(LmOwfPassword->data))[0]), (unsigned char *)LmChallenge, (unsigned char *)&(LmResponse->data[0]) ) != CRYPT_OK) { return (FALSE); } if (DES_ECB_LM(ENCR_KEY, (unsigned char *)&(((PBLOCK_KEY)(LmOwfPassword->data))[1]), (unsigned char *)LmChallenge, (unsigned char *)&(LmResponse->data[1]) ) != CRYPT_OK) { return (FALSE); } // To get the last key we must copy the remainder of the OwfPassword // and fill the rest of the key with 0s pKey = &(Key.data[0]); pData = (PCHAR)&(((PBLOCK_KEY)(LmOwfPassword->data))[2]); while (pData < (PCHAR)&(LmOwfPassword->data[2])) { *pKey++ = *pData++; } // Zero extend while (pKey < (PCHAR)&((&Key)[1])) { *pKey++ = 0; } // Use the 3rd key if (DES_ECB_LM(ENCR_KEY, (const char *)&Key, (unsigned char *)LmChallenge, (unsigned char *)&(LmResponse->data[2]) ) != CRYPT_OK) { return (FALSE); } return(TRUE); } BOOL CalculateNtResponse( IN PNT_CHALLENGE NtChallenge, IN PNT_OWF_PASSWORD NtOwfPassword, OUT PNT_RESPONSE NtResponse ) /*++ Routine Description: Calculates the NT challenge response. Currently just calls the LM function. --*/ { return CalculateLmResponse( (PLM_CHALLENGE)NtChallenge, (PLM_OWF_PASSWORD)NtOwfPassword, (PLM_RESPONSE)NtResponse); } BOOL CalculateUserSessionKeyLm( IN PLM_RESPONSE LmResponse, IN PLM_OWF_PASSWORD LmOwfPassword, OUT PUSER_SESSION_KEY UserSessionKey) /*++ Routine Description: Takes the passed Response and OwfPassword and generates a UserSessionKey. The current implementation takes the one-way-function of the OwfPassword and returns this as the key. Arguments: LmResponse - The response sent during session setup. LmOwfPassword - The hashed version of the user's password. Return Values: STATUS_SUCCESS - The function was completed successfully. The UserSessionKey is in UserSessionKey. STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined. --*/ { BOOL Status; NT_PASSWORD NtPassword; // // Make the Owf password look like an NT password // NtPassword.Buffer = (PWSTR)LmOwfPassword; // We can do this cast because we // know the OWF routine treats this // pointer as a byte pointer. NtPassword.Length = sizeof(*LmOwfPassword); NtPassword.MaximumLength = sizeof(*LmOwfPassword); // // Calculate the OWF of the OwfPassword // Status = CalculateNtOwfPassword( &NtPassword, (PNT_OWF_PASSWORD)UserSessionKey ); if (!Status) { return(Status); } // // Check if we've generated the error session key // if (!_fmemcmp(UserSessionKey, &ErrorSessionKey, sizeof(*UserSessionKey))) { // // Move away from the error session key // UserSessionKey->data[0].data[0] ++; } return(TRUE); UNREFERENCED_PARAMETER(LmResponse); } BOOL CalculateUserSessionKeyNt( IN PNT_RESPONSE NtResponse, IN PNT_OWF_PASSWORD NtOwfPassword, OUT PUSER_SESSION_KEY UserSessionKey) /*++ Routine Description: Takes the passed Response and OwfPassword and generates a UserSessionKey. Arguments: NtResponse - The response sent during session setup. NtOwfPassword - The hashed version of the user's password. Return Values: STATUS_SUCCESS - The function was completed successfully. The UserSessionKey is in UserSessionKey. STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined. --*/ { // Just call the LM version return(CalculateUserSessionKeyLm((PLM_RESPONSE)NtResponse, (PLM_OWF_PASSWORD)NtOwfPassword, UserSessionKey)); }