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.

263 lines
6.6 KiB

  1. /****************************************************************************
  2. PROGRAM: LSA.C
  3. PURPOSE: Utility routines that access the LSA.
  4. ****************************************************************************/
  5. #include "msgina.h"
  6. // #define DEBUG_LSA
  7. #ifdef DEBUG_LSA
  8. #define VerbosePrint(s) WLPrint(s)
  9. #else
  10. #define VerbosePrint(s)
  11. #endif
  12. NTSTATUS NtStatusGPDEx = 0;
  13. /***************************************************************************\
  14. * GetPrimaryDomainEx
  15. *
  16. * Purpose : Returns the primary domain name for authentication
  17. *
  18. * Returns : TRUE if primary domain exists and returned, otherwise FALSE
  19. *
  20. * The primary domain name should be freed using RtlFreeUnicodeString().
  21. * The primary domain sid should be freed using Free()
  22. *
  23. * History:
  24. * 02-13-92 Davidc Created.
  25. \***************************************************************************/
  26. BOOL
  27. GetPrimaryDomainEx(
  28. PUNICODE_STRING PrimaryDomainName OPTIONAL,
  29. PUNICODE_STRING PrimaryDomainDnsName OPTIONAL,
  30. PSID *PrimaryDomainSid OPTIONAL,
  31. PBOOL SidPresent OPTIONAL
  32. )
  33. {
  34. NTSTATUS IgnoreStatus;
  35. OBJECT_ATTRIBUTES ObjectAttributes;
  36. LSA_HANDLE LsaHandle;
  37. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  38. PPOLICY_DNS_DOMAIN_INFO DnsDomainInfo;
  39. BOOL PrimaryDomainPresent = FALSE;
  40. DWORD dwRetry = 10;
  41. //
  42. // Set up the Security Quality Of Service
  43. //
  44. SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  45. SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
  46. SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  47. SecurityQualityOfService.EffectiveOnly = FALSE;
  48. //
  49. // Set up the object attributes to open the Lsa policy object
  50. //
  51. InitializeObjectAttributes(&ObjectAttributes,
  52. NULL,
  53. 0L,
  54. (HANDLE)NULL,
  55. NULL);
  56. ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;
  57. //
  58. // Open the local LSA policy object
  59. //
  60. Retry:
  61. NtStatusGPDEx = LsaOpenPolicy( NULL,
  62. &ObjectAttributes,
  63. POLICY_VIEW_LOCAL_INFORMATION,
  64. &LsaHandle
  65. );
  66. if (!NT_SUCCESS(NtStatusGPDEx)) {
  67. DebugLog((DEB_ERROR, "Failed to open local LsaPolicyObject, Status = 0x%lx\n", NtStatusGPDEx));
  68. if ((NtStatusGPDEx == RPC_NT_SERVER_TOO_BUSY) && (--dwRetry))
  69. {
  70. Sleep(100);
  71. goto Retry; // Likely to be too soon to call Lsa
  72. }
  73. return(FALSE);
  74. }
  75. //
  76. // Get the primary domain info
  77. //
  78. NtStatusGPDEx = LsaQueryInformationPolicy(LsaHandle,
  79. PolicyDnsDomainInformation,
  80. (PVOID *)&DnsDomainInfo);
  81. if (!NT_SUCCESS(NtStatusGPDEx)) {
  82. DebugLog((DEB_ERROR, "Failed to query primary domain from Lsa, Status = 0x%lx\n", NtStatusGPDEx));
  83. IgnoreStatus = LsaClose(LsaHandle);
  84. ASSERT(NT_SUCCESS(IgnoreStatus));
  85. return(FALSE);
  86. }
  87. //
  88. // Copy the primary domain name into the return string
  89. //
  90. if ( SidPresent )
  91. {
  92. *SidPresent = ( DnsDomainInfo->Sid != NULL );
  93. }
  94. if (DnsDomainInfo->Sid != NULL) {
  95. PrimaryDomainPresent = TRUE;
  96. if (PrimaryDomainName)
  97. {
  98. if (DuplicateUnicodeString(PrimaryDomainName, &(DnsDomainInfo->Name))) {
  99. if (PrimaryDomainSid != NULL) {
  100. ULONG SidLength = RtlLengthSid(DnsDomainInfo->Sid);
  101. *PrimaryDomainSid = Alloc(SidLength);
  102. if (*PrimaryDomainSid != NULL) {
  103. NtStatusGPDEx = RtlCopySid(SidLength, *PrimaryDomainSid, DnsDomainInfo->Sid);
  104. ASSERT(NT_SUCCESS(NtStatusGPDEx));
  105. } else {
  106. RtlFreeUnicodeString(PrimaryDomainName);
  107. PrimaryDomainPresent = FALSE;
  108. }
  109. }
  110. } else {
  111. PrimaryDomainPresent = FALSE;
  112. }
  113. }
  114. } else if (DnsDomainInfo->DnsDomainName.Length != 0) {
  115. PrimaryDomainPresent = TRUE;
  116. if (PrimaryDomainName) {
  117. if (DuplicateUnicodeString(
  118. PrimaryDomainName,
  119. &DnsDomainInfo->DnsDomainName)) {
  120. ASSERT(!ARGUMENT_PRESENT(PrimaryDomainSid));
  121. } else {
  122. PrimaryDomainPresent = FALSE;
  123. }
  124. }
  125. }
  126. if ( ( DnsDomainInfo->DnsDomainName.Length != 0 ) &&
  127. ( PrimaryDomainDnsName != NULL ) )
  128. {
  129. DuplicateUnicodeString( PrimaryDomainDnsName,
  130. &DnsDomainInfo->DnsDomainName );
  131. }
  132. //
  133. // We're finished with the Lsa
  134. //
  135. IgnoreStatus = LsaFreeMemory(DnsDomainInfo);
  136. ASSERT(NT_SUCCESS(IgnoreStatus));
  137. IgnoreStatus = LsaClose(LsaHandle);
  138. ASSERT(NT_SUCCESS(IgnoreStatus));
  139. return(PrimaryDomainPresent);
  140. }
  141. //
  142. // Since this isn't going to change without a reboot, we can easily cache the info
  143. //
  144. BOOL
  145. IsMachineDomainMember(
  146. VOID
  147. )
  148. {
  149. static BOOL s_bIsDomainMember = FALSE;
  150. static BOOL s_bDomainCached = FALSE;
  151. if (!s_bDomainCached)
  152. {
  153. s_bIsDomainMember = GetPrimaryDomainEx(NULL, NULL, NULL, NULL);
  154. if (NT_SUCCESS(NtStatusGPDEx))
  155. s_bDomainCached = TRUE;
  156. }
  157. return s_bIsDomainMember;
  158. }
  159. ULONG
  160. GetMaxPasswordAge(
  161. LPWSTR Domain,
  162. PULONG MaxAge
  163. )
  164. {
  165. DWORD Error;
  166. PUSER_MODALS_INFO_0 Modals;
  167. WCHAR ComputerName[ CNLEN+2 ];
  168. ULONG Length ;
  169. PDOMAIN_CONTROLLER_INFO DcInfo ;
  170. PWSTR DcNameBuffer ;
  171. Length = CNLEN + 2;
  172. GetComputerName( ComputerName, &Length );
  173. if (_wcsicmp( ComputerName, Domain ) == 0 )
  174. {
  175. DcNameBuffer = NULL ;
  176. DcInfo = NULL ;
  177. }
  178. else
  179. {
  180. Error = DsGetDcName( NULL,
  181. Domain,
  182. NULL,
  183. NULL,
  184. 0,
  185. &DcInfo );
  186. if ( Error )
  187. {
  188. return Error ;
  189. }
  190. DcNameBuffer = DcInfo->DomainControllerAddress ;
  191. }
  192. Error = NetUserModalsGet( DcNameBuffer,
  193. 0,
  194. (PUCHAR *) &Modals );
  195. if ( Error == 0 )
  196. {
  197. *MaxAge = Modals->usrmod0_max_passwd_age ;
  198. NetApiBufferFree( Modals );
  199. }
  200. if ( DcInfo )
  201. {
  202. NetApiBufferFree( DcInfo );
  203. }
  204. return Error ;
  205. }