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.

414 lines
9.7 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. disptrus.c(pp)
  5. Author:
  6. Scott Field (sfield) 16-Mar-96
  7. Revision:
  8. JonY 16-Apr-96 Modified to .cpp
  9. --*/
  10. #include "stdafx.h"
  11. #include "trstlist.h"
  12. #define RTN_OK 0
  13. #define RTN_ERROR 13
  14. //
  15. // if you have the ddk, include ntstatus.h
  16. //
  17. #ifndef STATUS_SUCCESS
  18. #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  19. #define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
  20. #define STATUS_NO_MORE_ENTRIES ((NTSTATUS)0x8000001AL)
  21. #endif
  22. #define ELEMENT_COUNT 64 // number of array elements to allocate
  23. CTrustList::CTrustList()
  24. {
  25. m_dwTrustCount = 0;
  26. m_ppszTrustList = (LPWSTR *)HeapAlloc(
  27. GetProcessHeap(), HEAP_ZERO_MEMORY,
  28. ELEMENT_COUNT * sizeof(LPWSTR)
  29. );
  30. }
  31. CTrustList::~CTrustList()
  32. {
  33. //
  34. // free trust list
  35. //
  36. unsigned int i;
  37. for(i = 0 ; i < m_dwTrustCount ; i++) {
  38. if(m_ppszTrustList[i] != NULL)
  39. HeapFree(GetProcessHeap(), 0, m_ppszTrustList[i]);
  40. }
  41. HeapFree(GetProcessHeap(), 0, m_ppszTrustList);
  42. }
  43. BOOL
  44. CTrustList::BuildTrustList(
  45. LPTSTR Target
  46. )
  47. {
  48. LSA_HANDLE PolicyHandle;
  49. NTSTATUS Status;
  50. PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomain;
  51. BOOL bDC;
  52. NET_API_STATUS nas = NERR_Success; // assume success
  53. BOOL bSuccess = FALSE; // assume this function will fail
  54. //
  55. // open the policy on the specified machine
  56. //
  57. Status = OpenPolicy(
  58. Target,
  59. POLICY_VIEW_LOCAL_INFORMATION,
  60. &PolicyHandle
  61. );
  62. if(Status != STATUS_SUCCESS) {
  63. SetLastError( LsaNtStatusToWinError(Status) );
  64. return FALSE;
  65. }
  66. //
  67. // obtain the AccountDomain, which is common to all three cases
  68. //
  69. Status = LsaQueryInformationPolicy(
  70. PolicyHandle,
  71. PolicyAccountDomainInformation,
  72. (LPVOID*)&AccountDomain
  73. );
  74. if(Status != STATUS_SUCCESS)
  75. goto cleanup;
  76. //
  77. // Note: AccountDomain->DomainSid will contain binary Sid
  78. //
  79. AddTrustToList(&AccountDomain->DomainName);
  80. //
  81. // free memory allocated for account domain
  82. //
  83. LsaFreeMemory(AccountDomain);
  84. //
  85. // find out if the target machine is a domain controller
  86. //
  87. if(!IsDomainController(Target, &bDC)) {
  88. ////
  89. goto cleanup;
  90. }
  91. if(!bDC) {
  92. PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomain;
  93. TCHAR* szPrimaryDomainName = NULL;
  94. TCHAR* DomainController = NULL;
  95. //
  96. // get the primary domain
  97. //
  98. Status = LsaQueryInformationPolicy(
  99. PolicyHandle,
  100. PolicyPrimaryDomainInformation,
  101. (LPVOID*)&PrimaryDomain
  102. );
  103. if(Status != STATUS_SUCCESS)
  104. goto cleanup;
  105. //
  106. // if the primary domain Sid is NULL, we are a non-member, and
  107. // our work is done.
  108. //
  109. if(PrimaryDomain->Sid == NULL) {
  110. LsaFreeMemory(PrimaryDomain);
  111. bSuccess = TRUE;
  112. goto cleanup;
  113. }
  114. AddTrustToList(&PrimaryDomain->Name);
  115. //
  116. // build a copy of what we just added. This is necessary in order
  117. // to lookup the domain controller for the specified domain.
  118. // the Domain name must be NULL terminated for NetGetDCName(),
  119. // and the LSA_UNICODE_STRING buffer is not necessarilly NULL
  120. // terminated. Note that in a practical implementation, we
  121. // could just extract the element we added, since it ends up
  122. // NULL terminated.
  123. //
  124. szPrimaryDomainName = (LPTSTR)HeapAlloc(
  125. GetProcessHeap(), 0,
  126. PrimaryDomain->Name.Length + sizeof(WCHAR) // existing length + NULL
  127. );
  128. if(szPrimaryDomainName != NULL) {
  129. //
  130. // copy the existing buffer to the new storage, appending a NULL
  131. //
  132. _tcsncpy(
  133. szPrimaryDomainName,
  134. PrimaryDomain->Name.Buffer,
  135. (PrimaryDomain->Name.Length / 2) + 1
  136. );
  137. }
  138. LsaFreeMemory(PrimaryDomain);
  139. if(szPrimaryDomainName == NULL) goto cleanup;
  140. //
  141. // get the primary domain controller computer name
  142. //
  143. nas = NetGetDCName(
  144. NULL,
  145. szPrimaryDomainName,
  146. (LPBYTE *)&DomainController
  147. );
  148. HeapFree(GetProcessHeap(), 0, szPrimaryDomainName);
  149. if(nas != NERR_Success)
  150. goto cleanup;
  151. //
  152. // close the policy handle, because we don't need it anymore
  153. // for the workstation case, as we open a handle to a DC
  154. // policy below
  155. //
  156. LsaClose(PolicyHandle);
  157. PolicyHandle = INVALID_HANDLE_VALUE; // invalidate handle value
  158. //
  159. // open the policy on the domain controller
  160. //
  161. Status = OpenPolicy(
  162. DomainController,
  163. POLICY_VIEW_LOCAL_INFORMATION,
  164. &PolicyHandle
  165. );
  166. //
  167. // free the domaincontroller buffer
  168. //
  169. NetApiBufferFree(DomainController);
  170. if(Status != STATUS_SUCCESS)
  171. goto cleanup;
  172. }
  173. //
  174. // build additional trusted domain(s) list and indicate if successful
  175. //
  176. bSuccess = EnumTrustedDomains(PolicyHandle);
  177. cleanup:
  178. //
  179. // close the policy handle
  180. //
  181. if(PolicyHandle != INVALID_HANDLE_VALUE)
  182. LsaClose(PolicyHandle);
  183. if(!bSuccess) {
  184. if(Status != STATUS_SUCCESS)
  185. SetLastError( LsaNtStatusToWinError(Status) );
  186. else if(nas != NERR_Success)
  187. SetLastError( nas );
  188. }
  189. return bSuccess;
  190. }
  191. BOOL
  192. CTrustList::EnumTrustedDomains(
  193. LSA_HANDLE PolicyHandle
  194. )
  195. {
  196. LSA_ENUMERATION_HANDLE lsaEnumHandle=0; // start an enum
  197. PLSA_TRUST_INFORMATION TrustInfo;
  198. ULONG ulReturned; // number of items returned
  199. ULONG ulCounter; // counter for items returned
  200. NTSTATUS Status;
  201. do {
  202. Status = LsaEnumerateTrustedDomains(
  203. PolicyHandle, // open policy handle
  204. &lsaEnumHandle, // enumeration tracker
  205. (LPVOID*)&TrustInfo, // buffer to receive data
  206. 32000, // recommended buffer size
  207. &ulReturned // number of items returned
  208. );
  209. //
  210. // get out if an error occurred
  211. //
  212. if( (Status != STATUS_SUCCESS) &&
  213. (Status != STATUS_MORE_ENTRIES) &&
  214. (Status != STATUS_NO_MORE_ENTRIES)
  215. ) {
  216. SetLastError( LsaNtStatusToWinError(Status) );
  217. return FALSE;
  218. }
  219. //
  220. // Display results
  221. // Note: Sids are in TrustInfo[ulCounter].Sid
  222. //
  223. for(ulCounter = 0 ; ulCounter < ulReturned ; ulCounter++)
  224. AddTrustToList(&TrustInfo[ulCounter].Name);
  225. //
  226. // free the buffer
  227. //
  228. LsaFreeMemory(TrustInfo);
  229. } while (Status != STATUS_NO_MORE_ENTRIES);
  230. return TRUE;
  231. }
  232. BOOL
  233. CTrustList::IsDomainController(
  234. LPTSTR Server,
  235. LPBOOL bDomainController
  236. )
  237. {
  238. PSERVER_INFO_101 si101;
  239. NET_API_STATUS nas;
  240. nas = NetServerGetInfo(
  241. Server,
  242. 101, // info-level
  243. (LPBYTE *)&si101
  244. );
  245. if(nas != NERR_Success) {
  246. SetLastError(nas);
  247. return FALSE;
  248. }
  249. if( (si101->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
  250. (si101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ) {
  251. //
  252. // we are dealing with a DC
  253. //
  254. *bDomainController = TRUE;
  255. } else {
  256. *bDomainController = FALSE;
  257. }
  258. NetApiBufferFree(si101);
  259. return TRUE;
  260. }
  261. BOOL
  262. CTrustList::AddTrustToList(
  263. PLSA_UNICODE_STRING UnicodeString
  264. )
  265. {
  266. if(m_dwTrustCount > ELEMENT_COUNT) return FALSE;
  267. //
  268. // allocate storage for array element
  269. //
  270. m_ppszTrustList[m_dwTrustCount] = (LPWSTR)HeapAlloc(
  271. GetProcessHeap(), 0,
  272. UnicodeString->Length + sizeof(WCHAR) // existing length + NULL
  273. );
  274. if(m_ppszTrustList[m_dwTrustCount] == NULL) return FALSE;
  275. //
  276. // copy the existing buffer to the new storage, appending a NULL
  277. //
  278. lstrcpynW(
  279. m_ppszTrustList[m_dwTrustCount],
  280. UnicodeString->Buffer,
  281. (UnicodeString->Length / 2) + 1
  282. );
  283. m_dwTrustCount++; // increment the trust count
  284. return TRUE;
  285. }
  286. void
  287. CTrustList::InitLsaString(
  288. PLSA_UNICODE_STRING LsaString,
  289. LPTSTR String
  290. )
  291. {
  292. DWORD StringLength;
  293. if (String == NULL) {
  294. LsaString->Buffer = NULL;
  295. LsaString->Length = 0;
  296. LsaString->MaximumLength = 0;
  297. return;
  298. }
  299. StringLength = _tcslen(String);
  300. LsaString->Buffer = String;
  301. LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  302. LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
  303. }
  304. NTSTATUS
  305. CTrustList::OpenPolicy(
  306. LPTSTR ServerName,
  307. DWORD DesiredAccess,
  308. PLSA_HANDLE PolicyHandle
  309. )
  310. {
  311. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  312. LSA_UNICODE_STRING ServerString;
  313. PLSA_UNICODE_STRING Server;
  314. //
  315. // Always initialize the object attributes to all zeroes
  316. //
  317. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  318. if(ServerName != NULL) {
  319. //
  320. // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  321. //
  322. InitLsaString(&ServerString, ServerName);
  323. Server = &ServerString;
  324. } else {
  325. Server = NULL;
  326. }
  327. //
  328. // Attempt to open the policy
  329. //
  330. return LsaOpenPolicy(
  331. Server,
  332. &ObjectAttributes,
  333. DesiredAccess,
  334. PolicyHandle
  335. );
  336. }