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.

234 lines
5.4 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // md5port.c
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the NT5 specific routines used for MD5-CHAP support.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 10/13/1998 Original version.
  16. // 11/17/1998 Strip the trailing null.
  17. // 02/24/1999 Check for empty OWF password when credentials are
  18. // zero length.
  19. // 05/24/1999 SAM now returns error if cleartext password not set.
  20. // 10/21/1999 Return STATUS_DS_NO_ATTRIBUTE_OR_VALUE if reversibly
  21. // encyrpted password is not set.
  22. //
  23. ///////////////////////////////////////////////////////////////////////////////
  24. #include <nt.h>
  25. #include <ntrtl.h>
  26. #include <nturtl.h>
  27. #include <windows.h>
  28. #define SECURITY_WIN32
  29. #define SECURITY_PACKAGE
  30. #include <security.h>
  31. #include <secint.h>
  32. #include <samrpc.h>
  33. #include <samisrv.h>
  34. #include <lsarpc.h>
  35. #include <lsaisrv.h>
  36. #include <cleartxt.h>
  37. #include <subauth.h>
  38. // TRUE if this API has been successfully initialized.
  39. static BOOL theInitFlag;
  40. //////////
  41. // Macro that ensures the API has been initialized and bails on failure.
  42. //////////
  43. #define CHECK_INIT() \
  44. if (!theInitFlag) { \
  45. status = InitializePolicy(); \
  46. if (!NT_SUCCESS(status)) { return status; } \
  47. }
  48. // Name of the cleartext package.
  49. static UNICODE_STRING CLEARTEXT_PACKAGE_NAME = { 18, 20, L"CLEARTEXT" };
  50. // Flag indicating whether this is a native-mode DC.
  51. static BOOL theNativeFlag;
  52. //////////
  53. // Initializes theNativeFlag.
  54. //////////
  55. NTSTATUS
  56. NTAPI
  57. InitializePolicy( VOID )
  58. {
  59. NTSTATUS status;
  60. SAMPR_HANDLE hDomain;
  61. status = GetDomainHandle(&hDomain);
  62. if (NT_SUCCESS(status))
  63. {
  64. if (SampUsingDsData() && !SamIMixedDomain(hDomain))
  65. {
  66. theNativeFlag = TRUE;
  67. }
  68. }
  69. return status;
  70. }
  71. //////////
  72. // Determines whether a cleartext password should be stored for the user.
  73. //////////
  74. NTSTATUS
  75. NTAPI
  76. IsCleartextEnabled(
  77. IN SAMPR_HANDLE UserHandle,
  78. OUT PBOOL Enabled
  79. )
  80. {
  81. NTSTATUS status;
  82. PUSER_CONTROL_INFORMATION uci;
  83. SAMPR_HANDLE hDomain;
  84. PDOMAIN_PASSWORD_INFORMATION dpi;
  85. CHECK_INIT();
  86. if (theNativeFlag)
  87. {
  88. // In native-mode domains, we never store the cleartext password since
  89. // the DS will take care of this for us.
  90. *Enabled = FALSE;
  91. return STATUS_SUCCESS;
  92. }
  93. //////////
  94. // First check the user's flags since we already have the handle.
  95. //////////
  96. uci = NULL;
  97. status = SamrQueryInformationUser(
  98. UserHandle,
  99. UserControlInformation,
  100. (PSAMPR_USER_INFO_BUFFER*)&uci
  101. );
  102. if (!NT_SUCCESS(status)) { goto exit; }
  103. if (uci->UserAccountControl & USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED)
  104. {
  105. *Enabled = TRUE;
  106. goto free_user_info;
  107. }
  108. //////////
  109. // Then check the domain flags.
  110. //////////
  111. status = GetDomainHandle(&hDomain);
  112. if (!NT_SUCCESS(status)) { goto free_user_info; }
  113. dpi = NULL;
  114. status = SamrQueryInformationDomain(
  115. hDomain,
  116. DomainPasswordInformation,
  117. (PSAMPR_DOMAIN_INFO_BUFFER*)&dpi
  118. );
  119. if (!NT_SUCCESS(status)) { goto free_user_info; }
  120. if (dpi->PasswordProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
  121. {
  122. *Enabled = TRUE;
  123. }
  124. else
  125. {
  126. *Enabled = FALSE;
  127. }
  128. SamIFree_SAMPR_DOMAIN_INFO_BUFFER(
  129. (PSAMPR_DOMAIN_INFO_BUFFER)dpi,
  130. DomainPasswordInformation
  131. );
  132. free_user_info:
  133. SamIFree_SAMPR_USER_INFO_BUFFER(
  134. (PSAMPR_USER_INFO_BUFFER)uci,
  135. UserControlInformation
  136. );
  137. exit:
  138. return status;
  139. }
  140. //////////
  141. // Retrieves the user's cleartext password. The returned password should be
  142. // freed through RtlFreeUnicodeString.
  143. //////////
  144. NTSTATUS
  145. NTAPI
  146. RetrieveCleartextPassword(
  147. IN SAM_HANDLE UserHandle,
  148. IN PUSER_ALL_INFORMATION UserAll,
  149. OUT PUNICODE_STRING Password
  150. )
  151. {
  152. NTSTATUS status;
  153. PWCHAR credentials;
  154. ULONG credentialSize;
  155. if (SampUsingDsData())
  156. {
  157. // If we're a DC, then retrieve the credentials from the DS.
  158. status = SamIRetrievePrimaryCredentials(
  159. UserHandle,
  160. &CLEARTEXT_PACKAGE_NAME,
  161. (PVOID *)&credentials,
  162. &credentialSize
  163. );
  164. if (NT_SUCCESS(status))
  165. {
  166. Password->Buffer = (PWSTR)credentials;
  167. Password->Length = Password->MaximumLength = (USHORT)credentialSize;
  168. // Strip the trailing null (if any).
  169. if (credentialSize >= sizeof(WCHAR) &&
  170. Password->Buffer[credentialSize / sizeof(WCHAR) - 1] == L'\0')
  171. {
  172. Password->Length -= (USHORT)sizeof(WCHAR);
  173. }
  174. }
  175. }
  176. else if (UserAll->Parameters.Length > 0)
  177. {
  178. // Otherwise, we'll have to retrieve them from UserParameters.
  179. status = IASParmsGetUserPassword(
  180. UserAll->Parameters.Buffer,
  181. &credentials
  182. );
  183. if (status == NO_ERROR)
  184. {
  185. if (credentials)
  186. {
  187. RtlInitUnicodeString(
  188. Password,
  189. credentials
  190. );
  191. }
  192. else
  193. {
  194. // The reversibly encyrpted password isn't set.
  195. status = STATUS_DS_NO_ATTRIBUTE_OR_VALUE;
  196. }
  197. }
  198. }
  199. else
  200. {
  201. // No DC and no UserParameters.
  202. status = STATUS_DS_NO_ATTRIBUTE_OR_VALUE;
  203. }
  204. return status;
  205. }