Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
5.8 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. response.c
  5. Abstract:
  6. Contains functions that calculate the correct response to return
  7. to the server when logging on.
  8. CalculateLmResponse
  9. Author:
  10. David Chalmers (Davidc) 10-21-91
  11. David Arnold (DavidAr) 12-15-93 (Adapted for RPC SSP)
  12. Revision History:
  13. --*/
  14. #ifdef BLDR_KERNEL_RUNTIME
  15. #include <bootdefs.h>
  16. #endif
  17. #include <ntlmsspi.h>
  18. #include <descrypt.h>
  19. #include <crypt.h>
  20. #include <string.h>
  21. //
  22. // Define the user session key that represents an error.
  23. // This value will be generated by other parts of the system on failure.
  24. // We will check for it in our query code and return an error if it's found.
  25. //
  26. USER_SESSION_KEY ErrorSessionKey = { 0, 0, 0, 0, 0, 0, 0, 0,
  27. 0, 0, 0, 0, 0, 0, 0, 0
  28. };
  29. BOOL
  30. CalculateLmResponse(
  31. IN PLM_CHALLENGE LmChallenge,
  32. IN PLM_OWF_PASSWORD LmOwfPassword,
  33. OUT PLM_RESPONSE LmResponse
  34. )
  35. /*++
  36. Routine Description:
  37. Takes the challenge sent by the server and the OwfPassword generated
  38. from the password the user entered and calculates the response to
  39. return to the server.
  40. Arguments:
  41. LmChallenge - The challenge sent by the server
  42. LmOwfPassword - The hashed password.
  43. LmResponse - The response is returned here.
  44. Return Values:
  45. TRUE - The function completed successfully. The response
  46. is in LmResponse.
  47. FALSE - Something failed. The LmResponse is undefined.
  48. --*/
  49. {
  50. BLOCK_KEY Key;
  51. PCHAR pKey, pData;
  52. // The first 2 keys we can get at by type-casting
  53. if (DES_ECB_LM(ENCR_KEY,
  54. (unsigned char *)&(((PBLOCK_KEY)(LmOwfPassword->data))[0]),
  55. (unsigned char *)LmChallenge,
  56. (unsigned char *)&(LmResponse->data[0])
  57. ) != CRYPT_OK) {
  58. return (FALSE);
  59. }
  60. if (DES_ECB_LM(ENCR_KEY,
  61. (unsigned char *)&(((PBLOCK_KEY)(LmOwfPassword->data))[1]),
  62. (unsigned char *)LmChallenge,
  63. (unsigned char *)&(LmResponse->data[1])
  64. ) != CRYPT_OK) {
  65. return (FALSE);
  66. }
  67. // To get the last key we must copy the remainder of the OwfPassword
  68. // and fill the rest of the key with 0s
  69. pKey = &(Key.data[0]);
  70. pData = (PCHAR)&(((PBLOCK_KEY)(LmOwfPassword->data))[2]);
  71. while (pData < (PCHAR)&(LmOwfPassword->data[2])) {
  72. *pKey++ = *pData++;
  73. }
  74. // Zero extend
  75. while (pKey < (PCHAR)&((&Key)[1])) {
  76. *pKey++ = 0;
  77. }
  78. // Use the 3rd key
  79. if (DES_ECB_LM(ENCR_KEY,
  80. (const char *)&Key,
  81. (unsigned char *)LmChallenge,
  82. (unsigned char *)&(LmResponse->data[2])
  83. ) != CRYPT_OK) {
  84. return (FALSE);
  85. }
  86. return(TRUE);
  87. }
  88. BOOL
  89. CalculateNtResponse(
  90. IN PNT_CHALLENGE NtChallenge,
  91. IN PNT_OWF_PASSWORD NtOwfPassword,
  92. OUT PNT_RESPONSE NtResponse
  93. )
  94. /*++
  95. Routine Description:
  96. Calculates the NT challenge response. Currently just calls the
  97. LM function.
  98. --*/
  99. {
  100. return CalculateLmResponse(
  101. (PLM_CHALLENGE)NtChallenge,
  102. (PLM_OWF_PASSWORD)NtOwfPassword,
  103. (PLM_RESPONSE)NtResponse);
  104. }
  105. BOOL
  106. CalculateUserSessionKeyLm(
  107. IN PLM_RESPONSE LmResponse,
  108. IN PLM_OWF_PASSWORD LmOwfPassword,
  109. OUT PUSER_SESSION_KEY UserSessionKey)
  110. /*++
  111. Routine Description:
  112. Takes the passed Response and OwfPassword and generates a UserSessionKey.
  113. The current implementation takes the one-way-function of the OwfPassword
  114. and returns this as the key.
  115. Arguments:
  116. LmResponse - The response sent during session setup.
  117. LmOwfPassword - The hashed version of the user's password.
  118. Return Values:
  119. STATUS_SUCCESS - The function was completed successfully.
  120. The UserSessionKey is in UserSessionKey.
  121. STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined.
  122. --*/
  123. {
  124. BOOL Status;
  125. NT_PASSWORD NtPassword;
  126. //
  127. // Make the Owf password look like an NT password
  128. //
  129. NtPassword.Buffer = (PWSTR)LmOwfPassword; // We can do this cast because we
  130. // know the OWF routine treats this
  131. // pointer as a byte pointer.
  132. NtPassword.Length = sizeof(*LmOwfPassword);
  133. NtPassword.MaximumLength = sizeof(*LmOwfPassword);
  134. //
  135. // Calculate the OWF of the OwfPassword
  136. //
  137. Status = CalculateNtOwfPassword( &NtPassword,
  138. (PNT_OWF_PASSWORD)UserSessionKey
  139. );
  140. if (!Status) {
  141. return(Status);
  142. }
  143. //
  144. // Check if we've generated the error session key
  145. //
  146. if (!_fmemcmp(UserSessionKey, &ErrorSessionKey, sizeof(*UserSessionKey))) {
  147. //
  148. // Move away from the error session key
  149. //
  150. UserSessionKey->data[0].data[0] ++;
  151. }
  152. return(TRUE);
  153. UNREFERENCED_PARAMETER(LmResponse);
  154. }
  155. BOOL
  156. CalculateUserSessionKeyNt(
  157. IN PNT_RESPONSE NtResponse,
  158. IN PNT_OWF_PASSWORD NtOwfPassword,
  159. OUT PUSER_SESSION_KEY UserSessionKey)
  160. /*++
  161. Routine Description:
  162. Takes the passed Response and OwfPassword and generates a UserSessionKey.
  163. Arguments:
  164. NtResponse - The response sent during session setup.
  165. NtOwfPassword - The hashed version of the user's password.
  166. Return Values:
  167. STATUS_SUCCESS - The function was completed successfully.
  168. The UserSessionKey is in UserSessionKey.
  169. STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined.
  170. --*/
  171. {
  172. // Just call the LM version
  173. return(CalculateUserSessionKeyLm((PLM_RESPONSE)NtResponse,
  174. (PLM_OWF_PASSWORD)NtOwfPassword,
  175. UserSessionKey));
  176. }