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.

267 lines
5.2 KiB

  1. //
  2. //
  3. #include <nt.h>
  4. #include <ntrtl.h>
  5. #include <nturtl.h>
  6. #include <windows.h>
  7. #ifdef KERNEL_MODE
  8. #include <ntos.h>
  9. #endif
  10. #include <security.h>
  11. #include <cryptdll.h>
  12. #include <crypt.h>
  13. #include <kerbcon.h>
  14. #include <lmcons.h>
  15. #ifdef WIN32_CHICAGO
  16. NTSTATUS
  17. MyRtlUpcaseUnicodeStringToOemString(
  18. OUT POEM_STRING DestinationString,
  19. IN PUNICODE_STRING SourceString,
  20. IN BOOLEAN AllocateDestinationString
  21. );
  22. #define RtlUpcaseUnicodeStringToOemString(x, y, z) MyRtlUpcaseUnicodeStringToOemString(x, y, z)
  23. #endif // WIN32_CHICAGO
  24. typedef struct _LM_STATE_BUFFER {
  25. LM_OWF_PASSWORD Password;
  26. } LM_STATE_BUFFER, *PLM_STATE_BUFFER;
  27. NTSTATUS
  28. LmWrapInitialize(ULONG dwSeed,
  29. PCHECKSUM_BUFFER * ppcsBuffer);
  30. NTSTATUS
  31. LmWrapSum( PCHECKSUM_BUFFER pcsBuffer,
  32. ULONG cbData,
  33. PUCHAR pbData );
  34. NTSTATUS
  35. LmWrapFinalize( PCHECKSUM_BUFFER pcsBuffer,
  36. PUCHAR pbSum);
  37. NTSTATUS
  38. LmWrapFinish(PCHECKSUM_BUFFER * ppcsBuffer);
  39. CHECKSUM_FUNCTION csfLM = {
  40. KERB_CHECKSUM_LM,
  41. LM_OWF_PASSWORD_LENGTH,
  42. CKSUM_COLLISION,
  43. LmWrapInitialize,
  44. LmWrapSum,
  45. LmWrapFinalize,
  46. LmWrapFinish
  47. // Note : missing last function
  48. };
  49. #ifdef KERNEL_MODE
  50. #pragma alloc_text( PAGEMSG, LmWrapInitialize )
  51. #pragma alloc_text( PAGEMSG, LmWrapSum )
  52. #pragma alloc_text( PAGEMSG, LmWrapFinalize )
  53. #pragma alloc_text( PAGEMSG, LmWrapFinish );
  54. #endif
  55. NTSTATUS
  56. LmWrapInitialize(
  57. ULONG dwSeed,
  58. PCHECKSUM_BUFFER * ppcsBuffer)
  59. {
  60. PLM_STATE_BUFFER pContext;
  61. #ifdef KERNEL_MODE
  62. pContext = ExAllocatePool( NonPagedPool, sizeof( LM_STATE_BUFFER ) );
  63. #else
  64. pContext = LocalAlloc( LMEM_ZEROINIT, sizeof( LM_STATE_BUFFER ) );
  65. #endif
  66. if ( pContext != NULL )
  67. {
  68. *ppcsBuffer = pContext;
  69. return( SEC_E_OK );
  70. }
  71. return( STATUS_INSUFFICIENT_RESOURCES );
  72. }
  73. NTSTATUS
  74. LmCalculateLmPassword(
  75. IN PUNICODE_STRING NtPassword,
  76. OUT PCHAR *LmPasswordBuffer
  77. )
  78. /*++
  79. Routine Description:
  80. This service converts an NT password into a LM password.
  81. Parameters:
  82. NtPassword - The Nt password to be converted.
  83. LmPasswordBuffer - On successful return, points at the LM password
  84. The buffer should be freed using MIDL_user_free
  85. Return Values:
  86. STATUS_SUCCESS - LMPassword contains the LM version of the password.
  87. STATUS_NULL_LM_PASSWORD - The password is too complex to be represented
  88. by a LM password. The LM password returned is a NULL string.
  89. --*/
  90. {
  91. #define LM_BUFFER_LENGTH (LM20_PWLEN + 1)
  92. NTSTATUS NtStatus;
  93. ANSI_STRING LmPassword;
  94. //
  95. // Prepare for failure
  96. //
  97. *LmPasswordBuffer = NULL;
  98. //
  99. // Compute the Ansi version to the Unicode password.
  100. //
  101. // The Ansi version of the Cleartext password is at most 14 bytes long,
  102. // exists in a trailing zero filled 15 byte buffer,
  103. // is uppercased.
  104. //
  105. #ifdef KERNEL_MODE
  106. LmPassword.Buffer = ExAllocatePool(NonPagedPool,LM_BUFFER_LENGTH);
  107. #else
  108. LmPassword.Buffer = LocalAlloc(0,LM_BUFFER_LENGTH);
  109. #endif
  110. if (LmPassword.Buffer == NULL) {
  111. return(STATUS_INSUFFICIENT_RESOURCES);
  112. }
  113. LmPassword.MaximumLength = LmPassword.Length = LM_BUFFER_LENGTH;
  114. RtlZeroMemory( LmPassword.Buffer, LM_BUFFER_LENGTH );
  115. NtStatus = RtlUpcaseUnicodeStringToOemString( &LmPassword, NtPassword, FALSE );
  116. if ( !NT_SUCCESS(NtStatus) ) {
  117. //
  118. // The password is longer than the max LM password length
  119. //
  120. NtStatus = STATUS_NULL_LM_PASSWORD; // Informational return code
  121. RtlZeroMemory( LmPassword.Buffer, LM_BUFFER_LENGTH );
  122. }
  123. //
  124. // Return a pointer to the allocated LM password
  125. //
  126. if (NT_SUCCESS(NtStatus)) {
  127. *LmPasswordBuffer = LmPassword.Buffer;
  128. } else {
  129. #ifdef KERNEL_MODE
  130. ExFreePool(LmPassword.Buffer);
  131. #else
  132. LocalFree(LmPassword.Buffer);
  133. #endif
  134. }
  135. return(NtStatus);
  136. }
  137. NTSTATUS
  138. LmWrapSum(
  139. PCHECKSUM_BUFFER pcsBuffer,
  140. ULONG cbData,
  141. PUCHAR pbData )
  142. {
  143. PLM_STATE_BUFFER pContext = (PLM_STATE_BUFFER) pcsBuffer;
  144. UNICODE_STRING TempString;
  145. PUCHAR LmPassword;
  146. NTSTATUS Status;
  147. TempString.Length = TempString.MaximumLength = (USHORT) cbData;
  148. TempString.Buffer = (LPWSTR) pbData;
  149. Status = LmCalculateLmPassword(
  150. &TempString,
  151. &LmPassword
  152. );
  153. if (!NT_SUCCESS(Status))
  154. {
  155. return(Status);
  156. }
  157. Status = RtlCalculateLmOwfPassword(
  158. LmPassword,
  159. &pContext->Password
  160. );
  161. #ifdef KERNEL_MODE
  162. ExFreePool(LmPassword);
  163. #else
  164. LocalFree(LmPassword);
  165. #endif
  166. return( Status );
  167. }
  168. NTSTATUS
  169. LmWrapFinalize(
  170. PCHECKSUM_BUFFER pcsBuffer,
  171. PUCHAR pbSum)
  172. {
  173. PLM_STATE_BUFFER pContext = (PLM_STATE_BUFFER) pcsBuffer;
  174. RtlCopyMemory(
  175. pbSum,
  176. &pContext->Password,
  177. LM_OWF_PASSWORD_LENGTH
  178. );
  179. return( STATUS_SUCCESS );
  180. }
  181. NTSTATUS
  182. LmWrapFinish(
  183. PCHECKSUM_BUFFER * ppcsBuffer)
  184. {
  185. RtlZeroMemory( *ppcsBuffer, sizeof( PLM_STATE_BUFFER ) );
  186. #ifdef KERNEL_MODE
  187. ExFreePool( *ppcsBuffer );
  188. #else
  189. LocalFree( *ppcsBuffer );
  190. #endif
  191. *ppcsBuffer = NULL ;
  192. return( STATUS_SUCCESS );
  193. }