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.

5478 lines
154 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. rpcapi.c
  5. Abstract:
  6. This module contains the routines for the LSA API that use RPC. The
  7. routines in this module are merely wrappers that work as follows:
  8. o Client program calls LsaFoo in this module
  9. o LsaFoo calls RPC client stub interface routine LsapFoo with
  10. similar parameters. Some parameters are translated from types
  11. (e.g structures containing PVOIDs or certain kinds of variable length
  12. parameters such as pointers to SID's) that are not specifiable on an
  13. RPC interface, to specifiable form.
  14. o RPC client stub LsapFoo calls interface specific marshalling routines
  15. and RPC runtime to marshal parameters into a buffer and send them over
  16. to the server side of the LSA.
  17. o Server side calls RPC runtime and interface specific unmarshalling
  18. routines to unmarshal parameters.
  19. o Server side calls worker LsapFoo to perform API function.
  20. o Server side marshals response/output parameters and communicates these
  21. back to client stub LsapFoo
  22. o LsapFoo exits back to LsaFoo which returns to client program.
  23. Author:
  24. Scott Birrell (ScottBi) April 24, 1991
  25. Revision History:
  26. --*/
  27. #include "lsaclip.h"
  28. #include <align.h>
  29. #include <rpcasync.h>
  30. //
  31. // The following limit on the maximum number of Sids or Names is tentative,
  32. // so it is not being published.
  33. //
  34. #define LSAP_DB_TRIAL_MAXIMUM_SID_COUNT ((ULONG) 0x00005000L)
  35. #define LSAP_DB_TRIAL_MAXIMUM_NAME_COUNT ((ULONG) 0x00005000L)
  36. //
  37. // Functions private to this module
  38. //
  39. NTSTATUS
  40. LsapApiReturnResult(
  41. IN ULONG ExceptionCode
  42. );
  43. BOOLEAN
  44. LsapNeutralizeNt4Emulation()
  45. {
  46. BOOLEAN Result = FALSE;
  47. NTSTATUS Status;
  48. HKEY hkey;
  49. DWORD Type;
  50. DWORD Value;
  51. DWORD Size = sizeof( Value );
  52. static DWORD AmIDC = 0xFFFFFFFF;
  53. ULONG i;
  54. CHAR * Paths[] = {
  55. "SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters\\GpParameters",
  56. "SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters"
  57. };
  58. //
  59. // NT4 emulation is always disabled on domain controllers
  60. //
  61. if ( AmIDC == 0xFFFFFFFF ) {
  62. NT_PRODUCT_TYPE ProductType = NtProductWinNt;
  63. if ( TRUE == RtlGetNtProductType( &ProductType )) {
  64. if ( ProductType == NtProductLanManNt ) {
  65. AmIDC = TRUE;
  66. } else {
  67. AmIDC = FALSE;
  68. }
  69. }
  70. }
  71. if ( AmIDC == TRUE ) {
  72. return TRUE;
  73. }
  74. //
  75. // This is not a DC; must go to the registry for the special "neutralize" value
  76. // which could be either under NetLogon or NetLogon/GroupPolicy parameters key
  77. //
  78. for ( i = 0; i < sizeof( Paths ) / sizeof( Paths[0] ); i++ ) {
  79. if ( ERROR_SUCCESS != RegOpenKeyEx(
  80. HKEY_LOCAL_MACHINE,
  81. Paths[i],
  82. 0,
  83. KEY_READ,
  84. &hkey )) {
  85. continue;
  86. }
  87. if ( ERROR_SUCCESS != RegQueryValueEx(
  88. hkey,
  89. "NeutralizeNt4Emulator",
  90. NULL,
  91. &Type,
  92. (LPBYTE)&Value,
  93. &Size ) ||
  94. Type != REG_DWORD ||
  95. Size != sizeof( DWORD )) {
  96. RegCloseKey( hkey );
  97. continue;
  98. } else {
  99. RegCloseKey( hkey );
  100. Result = ( Value != 0 );
  101. break;
  102. }
  103. }
  104. return Result;
  105. }
  106. ////////////////////////////////////////////////////////////////////////////
  107. // //
  108. // Local Security Policy Administration API function prototypes //
  109. // //
  110. ////////////////////////////////////////////////////////////////////////////
  111. NTSTATUS
  112. LsaOpenPolicy(
  113. IN PUNICODE_STRING SystemName OPTIONAL,
  114. IN POBJECT_ATTRIBUTES ObjectAttributes,
  115. IN ACCESS_MASK DesiredAccess,
  116. IN OUT PLSA_HANDLE PolicyHandle
  117. )
  118. /*++
  119. Routine Description:
  120. To administer the Local Security Policy of a local or remote system,
  121. this API must be called to establish a session with that system's
  122. Local Security Authority (LSA) subsystem. This API connects to
  123. the LSA of the target system and opens the object representing
  124. the target system's Local Security Policy database. A handle to
  125. the object is returned. This handle must be used on all subsequent API
  126. calls to administer the Local Security Policy information for the
  127. target system.
  128. Arguments:
  129. SystemName - Name of the target system to be administered.
  130. Administration of the local system is assumed if NULL is specified.
  131. ObjectAttributes - Pointer to the set of attributes to use for this
  132. connection. The security Quality Of Service information is used and
  133. normally should provide Security Identification level of
  134. impersonation. Some operations, however, require Security
  135. Impersonation level of impersonation.
  136. DesiredAccess - This is an access mask indicating accesses being
  137. requested for the LSA Subsystem's LSA Database. These access types
  138. are reconciled with the Discretionary Access Control List of the
  139. target LsaDatabase object to determine whether the
  140. accesses will be granted or denied.
  141. PolicyHandle - Receives a handle to be used in future requests to
  142. access the Local Security Policy of the target system. This handle
  143. represents both the handle to the LsaDatabase object and
  144. the RPC Context Handle for the connection to the target LSA
  145. susbsystem.
  146. Return Values:
  147. NTSTATUS - Standard Nt Result Code
  148. STATUS_ACCESS_DENIED - Caller does not have access to the target
  149. system's LSA Database, or does not have other desired accesses.
  150. --*/
  151. {
  152. NTSTATUS Status = STATUS_SUCCESS;
  153. PLSAPR_SERVER_NAME ServerName = NULL;
  154. USHORT NullTerminatedServerNameLength;
  155. LSA_HANDLE LocalHandle = NULL ;
  156. RpcTryExcept {
  157. //
  158. // Get the Server Name as a Unicode String buffer. Set it to
  159. // NULL (i.e. local machine) if a zero length or NULL Unicode String
  160. // structure us passed. If a non NULL server name is given, we must
  161. // ensure that it is terminated with a NULL wide character. Allocate
  162. // a buffer that is one wide character longer than the server name
  163. // buffer, copy the server name to that buffer and append a trailing
  164. // NULL wide character.
  165. //
  166. if (ARGUMENT_PRESENT(SystemName) &&
  167. (SystemName->Buffer != NULL) &&
  168. (SystemName->Length > 0)) {
  169. NullTerminatedServerNameLength = SystemName->Length + (USHORT) sizeof (WCHAR);
  170. ServerName = MIDL_user_allocate( NullTerminatedServerNameLength );
  171. if (ServerName != NULL) {
  172. RtlZeroMemory( ServerName, NullTerminatedServerNameLength );
  173. RtlMoveMemory(
  174. ServerName,
  175. SystemName->Buffer,
  176. SystemName->Length
  177. );
  178. } else {
  179. Status = STATUS_INSUFFICIENT_RESOURCES;
  180. }
  181. }
  182. if (NT_SUCCESS(Status)) {
  183. *PolicyHandle = NULL;
  184. ObjectAttributes->RootDirectory = NULL;
  185. Status = LsarOpenPolicy2(
  186. ServerName,
  187. (PLSAPR_OBJECT_ATTRIBUTES) ObjectAttributes,
  188. DesiredAccess,
  189. (PLSAPR_HANDLE)&LocalHandle
  190. );
  191. }
  192. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  193. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  194. } RpcEndExcept;
  195. //
  196. // If the open failed because the new API doesn't exist, try the
  197. // old one.
  198. //
  199. if ((Status == RPC_NT_UNKNOWN_IF) ||
  200. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  201. RpcTryExcept {
  202. ASSERT(*PolicyHandle == NULL);
  203. ASSERT(ObjectAttributes->RootDirectory == NULL);
  204. Status = LsarOpenPolicy(
  205. ServerName,
  206. (PLSAPR_OBJECT_ATTRIBUTES) ObjectAttributes,
  207. DesiredAccess,
  208. (PLSAPR_HANDLE)&LocalHandle
  209. );
  210. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  211. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  212. } RpcEndExcept;
  213. }
  214. //
  215. // If necessary, free the NULL-terminated server name buffer.
  216. //
  217. if (ServerName != NULL) {
  218. MIDL_user_free( ServerName );
  219. }
  220. if ( NT_SUCCESS( Status ) ) {
  221. *PolicyHandle = LocalHandle;
  222. }
  223. return Status;
  224. }
  225. NTSTATUS
  226. LsaOpenPolicySce(
  227. IN PUNICODE_STRING SystemName OPTIONAL,
  228. IN POBJECT_ATTRIBUTES ObjectAttributes,
  229. IN ACCESS_MASK DesiredAccess,
  230. IN OUT PLSA_HANDLE PolicyHandle
  231. )
  232. /*++
  233. Routine Description:
  234. Essentially the same as LsaOpenPolicy, except used only by SCE
  235. to obtain a special "synchronized" policy handle that would serialize
  236. access to policy operations.
  237. Arguments:
  238. Same as LsaOpenPolicy
  239. Return Values:
  240. NTSTATUS - Standard Nt Result Code
  241. STATUS_ACCESS_DENIED - Caller does not have access to the target
  242. system's LSA Database, or does not have other desired accesses.
  243. STATUS_PRIVILEGE_NOT_HELD - Caller must come in with TCB privilege.
  244. STATUS_TIMEOUT - Timed out waiting on SCE to send pending changes
  245. --*/
  246. {
  247. NTSTATUS Status = STATUS_SUCCESS;
  248. PLSAPR_SERVER_NAME ServerName = NULL;
  249. USHORT NullTerminatedServerNameLength;
  250. LSA_HANDLE LocalHandle = NULL ;
  251. RpcTryExcept {
  252. //
  253. // Get the Server Name as a Unicode String buffer. Set it to
  254. // NULL (i.e. local machine) if a zero length or NULL Unicode String
  255. // structure us passed. If a non NULL server name is given, we must
  256. // ensure that it is terminated with a NULL wide character. Allocate
  257. // a buffer that is one wide character longer than the server name
  258. // buffer, copy the server name to that buffer and append a trailing
  259. // NULL wide character.
  260. //
  261. if (ARGUMENT_PRESENT(SystemName) &&
  262. (SystemName->Buffer != NULL) &&
  263. (SystemName->Length > 0)) {
  264. NullTerminatedServerNameLength = SystemName->Length + (USHORT) sizeof (WCHAR);
  265. ServerName = MIDL_user_allocate( NullTerminatedServerNameLength );
  266. if (ServerName != NULL) {
  267. RtlZeroMemory( ServerName, NullTerminatedServerNameLength );
  268. RtlMoveMemory(
  269. ServerName,
  270. SystemName->Buffer,
  271. SystemName->Length
  272. );
  273. } else {
  274. Status = STATUS_INSUFFICIENT_RESOURCES;
  275. }
  276. }
  277. if (NT_SUCCESS(Status)) {
  278. *PolicyHandle = NULL;
  279. ObjectAttributes->RootDirectory = NULL;
  280. Status = LsarOpenPolicySce(
  281. ServerName,
  282. (PLSAPR_OBJECT_ATTRIBUTES) ObjectAttributes,
  283. DesiredAccess,
  284. (PLSAPR_HANDLE)&LocalHandle
  285. );
  286. }
  287. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  288. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  289. } RpcEndExcept;
  290. //
  291. // If necessary, free the NULL-terminated server name buffer.
  292. //
  293. if (ServerName != NULL) {
  294. MIDL_user_free( ServerName );
  295. }
  296. if ( NT_SUCCESS( Status ) ) {
  297. *PolicyHandle = LocalHandle;
  298. }
  299. return Status;
  300. }
  301. NTSTATUS
  302. LsaQueryInformationPolicy(
  303. IN LSA_HANDLE PolicyHandle,
  304. IN POLICY_INFORMATION_CLASS InformationClass,
  305. OUT PVOID *Buffer
  306. )
  307. /*++
  308. Routine Description:
  309. The LsaQueryInformationPolicy API obtains information from the Policy
  310. object. The caller must have access appropriate to the information
  311. being requested (see InformationClass parameter).
  312. Arguments:
  313. PolicyHandle - Handle from an LsaOpenPolicy call.
  314. InformationClass - Specifies the information to be returned. The
  315. Information Classes and accesses required are as follows:
  316. Information Class Required Access Type
  317. PolicyAuditLogInformation POLICY_VIEW_AUDIT_INFORMATION
  318. PolicyAuditEventsInformation POLICY_VIEW_AUDIT_INFORMATION
  319. PolicyPrimaryDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  320. PolicyAccountDomainInformation POLICY_VIEW_LOCAL_INFORMATION
  321. PolicyPdAccountInformation POLICY_GET_PRIVATE_INFORMATION
  322. PolicyLsaServerRoleInformation POLICY_VIEW_LOCAL_INFORMATION
  323. PolicyReplicaSourceInformation POLICY_VIEW_LOCAL_INFORMATION
  324. PolicyDefaultQuotaInformation POLICY_VIEW_LOCAL_INFORMATION
  325. Buffer - receives a pointer to the buffer returned comtaining the
  326. requested information. This buffer is allocated by this service
  327. and must be freed when no longer needed by passing the returned
  328. value to LsaFreeMemory().
  329. Return Value:
  330. NTSTATUS - Standard Nt Result Code
  331. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  332. access to complete the operation.
  333. Others TBS
  334. --*/
  335. {
  336. NTSTATUS Status;
  337. PLSAPR_POLICY_INFORMATION PolicyInformation;
  338. if ( InformationClass == PolicyDnsDomainInformationInt ) {
  339. return STATUS_INVALID_PARAMETER;
  340. }
  341. Retry:
  342. PolicyInformation = NULL;
  343. RpcTryExcept {
  344. //
  345. // Call the Client Stub for LsaQueryInformationPolicy.
  346. //
  347. switch (InformationClass)
  348. {
  349. case PolicyDnsDomainInformation:
  350. case PolicyDnsDomainInformationInt:
  351. Status = LsarQueryInformationPolicy2(
  352. (LSAPR_HANDLE) PolicyHandle,
  353. InformationClass,
  354. &PolicyInformation
  355. );
  356. break;
  357. default:
  358. Status = LsarQueryInformationPolicy(
  359. (LSAPR_HANDLE) PolicyHandle,
  360. InformationClass,
  361. &PolicyInformation
  362. );
  363. }
  364. //
  365. // Return pointer to Policy Information for the given class, or NULL.
  366. //
  367. *Buffer = PolicyInformation;
  368. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  369. //
  370. // If memory was allocated for the returned Policy Information,
  371. // free it.
  372. //
  373. if (PolicyInformation != NULL) {
  374. MIDL_user_free(PolicyInformation);
  375. }
  376. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  377. } RpcEndExcept;
  378. //
  379. // If we suspect that the call failed due to NT4 emulation by the server,
  380. // and we're configured to neutralize emulation, try the call again, neutralizing
  381. //
  382. if ( Status == RPC_NT_PROCNUM_OUT_OF_RANGE &&
  383. InformationClass == PolicyDnsDomainInformation &&
  384. LsapNeutralizeNt4Emulation()) {
  385. InformationClass = PolicyDnsDomainInformationInt;
  386. goto Retry;
  387. }
  388. return Status;
  389. }
  390. NTSTATUS
  391. LsaSetInformationPolicy(
  392. IN LSA_HANDLE PolicyHandle,
  393. IN POLICY_INFORMATION_CLASS InformationClass,
  394. IN PVOID Buffer
  395. )
  396. /*++
  397. Routine Description:
  398. The LsaSetInformationPolicy API modifies information in the Policy Object.
  399. The caller must have access appropriate to the information to be changed
  400. in the Policy Object, see the InformationClass parameter.
  401. Arguments:
  402. PolicyHandle - Handle from an LsaOpenPolicy call.
  403. InformationClass - Specifies the type of information being changed.
  404. The information types and accesses required to change them are as
  405. follows:
  406. PolicyAuditLogInformation POLICY_AUDIT_LOG_ADMIN
  407. PolicyAuditEventsInformation POLICY_SET_AUDIT_REQUIREMENTS
  408. PolicyPrimaryDomainInformation POLICY_TRUST_ADMIN
  409. PolicyAccountDomainInformation POLICY_TRUST_ADMIN
  410. PolicyPdAccountInformation Not settable by this API
  411. PolicyLsaServerRoleInformation POLICY_SERVER_ADMIN
  412. PolicyReplicaSourceInformation POLICY_SERVER_ADMIN
  413. PolicyDefaultQuotaInformation POLICY_SET_DEFAULT_QUOTA_LIMITS
  414. PolicyDnsDomainInformation POLICY_DNS_DOMAIN_INFO
  415. PolicyDnsDomainInformationInt POLICY_DNS_DOMAIN_INFO
  416. Buffer - Points to a structure containing the information appropriate
  417. to the information type specified by the InformationClass parameter.
  418. Return Value:
  419. NTSTATUS - Standard Nt Result Code
  420. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  421. to complete the operation.
  422. Others TBS
  423. --*/
  424. {
  425. NTSTATUS Status;
  426. if ( InformationClass == PolicyDnsDomainInformationInt ) {
  427. return STATUS_INVALID_PARAMETER;
  428. }
  429. Retry:
  430. RpcTryExcept {
  431. //
  432. // Call the Client Stub for LsaSetInformationPolicy.
  433. //
  434. switch (InformationClass)
  435. {
  436. case PolicyDnsDomainInformation:
  437. case PolicyDnsDomainInformationInt:
  438. Status = LsarSetInformationPolicy2(
  439. (LSAPR_HANDLE) PolicyHandle,
  440. InformationClass,
  441. (PLSAPR_POLICY_INFORMATION) Buffer
  442. );
  443. break;
  444. default:
  445. Status = LsarSetInformationPolicy(
  446. (LSAPR_HANDLE) PolicyHandle,
  447. InformationClass,
  448. (PLSAPR_POLICY_INFORMATION) Buffer
  449. );
  450. }
  451. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  452. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  453. } RpcEndExcept;
  454. //
  455. // If we suspect that the call failed due to NT4 emulation by the server,
  456. // and we're configured to neutralize emulation, try the call again, neutralizing
  457. //
  458. if ( Status == RPC_NT_PROCNUM_OUT_OF_RANGE &&
  459. InformationClass == PolicyDnsDomainInformation &&
  460. LsapNeutralizeNt4Emulation()) {
  461. InformationClass = PolicyDnsDomainInformationInt;
  462. goto Retry;
  463. }
  464. return Status;
  465. }
  466. NTSTATUS
  467. LsaClearAuditLog(
  468. IN LSA_HANDLE PolicyHandle
  469. )
  470. /*++
  471. Routine Description:
  472. This function clears the Audit Log. Caller must have POLICY_AUDIT_LOG_ADMIN
  473. access to the Policy Object to perform this operation.
  474. Arguments:
  475. PolicyHandle - handle from an LsaOpenPolicy call.
  476. Return Values:
  477. NTSTATUS - Standard Nt Result Code.
  478. STATUS_SUCCESS - The call completed successfully.
  479. STATUS_ACCESS_DENIED - Caller does not have the required access
  480. to perform the operation.
  481. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  482. such as memory, to complete the call.
  483. STATUS_INVALID_HANDLE - PolicyHandle is not a valid handle to
  484. a Policy Object.
  485. --*/
  486. {
  487. NTSTATUS Status;
  488. RpcTryExcept {
  489. //
  490. // Call the Client Stub for LsaClearAuditLog.
  491. //
  492. Status = LsarClearAuditLog(
  493. (LSAPR_HANDLE) PolicyHandle
  494. );
  495. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  496. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  497. } RpcEndExcept;
  498. return(Status);
  499. }
  500. NTSTATUS
  501. LsaLookupPrivilegeValue(
  502. IN LSA_HANDLE PolicyHandle,
  503. IN PUNICODE_STRING Name,
  504. OUT PLUID Value
  505. )
  506. /*++
  507. Routine Description:
  508. This function retrieves the value used on the target system
  509. to locally represent the specified privilege. The privilege
  510. is specified by programmatic name.
  511. Arguments:
  512. PolicyHandle - Handle from an LsaOpenPolicy() call. This handle
  513. must be open for POLICY_LOOKUP_NAMES access.
  514. Name - Is the privilege's programmatic name.
  515. Value - Receives the locally unique ID the privilege is known by on the
  516. target machine.
  517. Return Value:
  518. NTSTATUS - The privilege was found and returned.
  519. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  520. to complete the operation.
  521. STATUS_NO_SUCH_PRIVILEGE - The specified privilege could not be
  522. found.
  523. --*/
  524. {
  525. NTSTATUS Status;
  526. LUID Buffer;
  527. RpcTryExcept {
  528. //
  529. // Call the Client Stub for LsaLookupPrivilegeValue.
  530. //
  531. Status = LsarLookupPrivilegeValue(
  532. (LSAPR_HANDLE) PolicyHandle,
  533. (PLSAPR_UNICODE_STRING)Name,
  534. &Buffer
  535. );
  536. *Value = Buffer;
  537. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  538. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  539. } RpcEndExcept;
  540. return(Status);
  541. }
  542. NTSTATUS
  543. LsaLookupPrivilegeName(
  544. IN LSA_HANDLE PolicyHandle,
  545. IN PLUID Value,
  546. OUT PUNICODE_STRING *Name
  547. )
  548. /*++
  549. Routine Description:
  550. This function programmatic name corresponding to the privilege
  551. represented on the target system by the provided LUID.
  552. Arguments:
  553. PolicyHandle - Handle from an LsaOpenPolicy() call. This handle
  554. must be open for POLICY_LOOKUP_NAMES access.
  555. Value - is the locally unique ID the privilege is known by on the
  556. target machine.
  557. Name - Receives the privilege's programmatic name.
  558. Return Value:
  559. NTSTATUS - The privilege was found and returned.
  560. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  561. to complete the operation.
  562. STATUS_NO_SUCH_PRIVILEGE - The specified privilege could not be
  563. found.
  564. --*/
  565. {
  566. NTSTATUS Status;
  567. PLSAPR_UNICODE_STRING Buffer = NULL;
  568. RpcTryExcept {
  569. //
  570. // Call the Client Stub for LsaLookupPrivilegeName.
  571. //
  572. Status = LsarLookupPrivilegeName(
  573. (LSAPR_HANDLE) PolicyHandle,
  574. Value,
  575. &Buffer
  576. );
  577. (*Name) = (PUNICODE_STRING)Buffer;
  578. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  579. //
  580. // If memory was allocated for the return buffer, free it.
  581. //
  582. if (Buffer != NULL) {
  583. MIDL_user_free(Buffer);
  584. }
  585. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  586. } RpcEndExcept;
  587. return(Status);
  588. }
  589. NTSTATUS
  590. LsaLookupPrivilegeDisplayName(
  591. IN LSA_HANDLE PolicyHandle,
  592. IN PUNICODE_STRING Name,
  593. OUT PUNICODE_STRING *DisplayName,
  594. OUT PSHORT LanguageReturned
  595. )
  596. /*++
  597. Routine Description:
  598. This function retrieves a displayable name representing the
  599. specified privilege.
  600. Arguments:
  601. PolicyHandle - Handle from an LsaOpenPolicy() call. This handle
  602. must be open for POLICY_LOOKUP_NAMES access.
  603. Name - The programmatic privilege name to look up.
  604. DisplayName - Receives a pointer to the privilege's displayable
  605. name.
  606. LanguageReturned - Receives the language of the returned displayable
  607. name.
  608. Return Value:
  609. NTSTATUS - The privilege text was found and returned.
  610. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  611. to complete the operation.
  612. STATUS_NO_SUCH_PRIVILEGE - The specified privilege could not be
  613. found.
  614. --*/
  615. {
  616. NTSTATUS Status;
  617. SHORT ClientLanguage, ClientSystemDefaultLanguage;
  618. PLSAPR_UNICODE_STRING Buffer = NULL;
  619. RpcTryExcept {
  620. //
  621. // Call the Client Stub for LsaLookupPrivilegeDisplayName.
  622. //
  623. ClientLanguage = (SHORT)NtCurrentTeb()->CurrentLocale;
  624. ClientSystemDefaultLanguage = ClientLanguage; //no sys default yet
  625. Status = LsarLookupPrivilegeDisplayName(
  626. (LSAPR_HANDLE) PolicyHandle,
  627. (PLSAPR_UNICODE_STRING)Name,
  628. ClientLanguage,
  629. ClientSystemDefaultLanguage,
  630. &Buffer,
  631. (PWORD)LanguageReturned
  632. );
  633. (*DisplayName) = (PUNICODE_STRING)Buffer;
  634. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  635. //
  636. // If memory was allocated for the return buffer, free it.
  637. //
  638. if (Buffer != NULL) {
  639. MIDL_user_free(Buffer);
  640. }
  641. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  642. } RpcEndExcept;
  643. return(Status);
  644. }
  645. NTSTATUS
  646. LsaClose(
  647. IN LSA_HANDLE ObjectHandle
  648. )
  649. /*++
  650. Routine Description:
  651. This API closes a handle to the LsaDatabase object or open object within
  652. the database. If a handle to the LsaDatabase object is closed and there
  653. are no objects still open within the current connection to the LSA, the
  654. connection is closed. If a handle to an object within the database is
  655. closed and the object is marked for DELETE access, the object will be
  656. deleted when the last handle to that object is closed.
  657. Arguments:
  658. ObjectHandle - This parameter is either a handle to the LsaDatabase
  659. object, which represents the entire LSA Database and also a
  660. connection to the LSA of a target system, or a handle to an
  661. object within the database.
  662. Return Value:
  663. NTSTATUS - Standard Nt Result Code
  664. --*/
  665. {
  666. NTSTATUS Status;
  667. LSAPR_HANDLE Handle = (LSAPR_HANDLE) ObjectHandle;
  668. RpcTryExcept {
  669. //
  670. // Call the Client Stub for LsaClose. Note that an additional
  671. // level of indirection for the context handle parameter is required
  672. // for the stub, because the server returns a NULL pointer to the handle
  673. // so that the handle will be unbound by the stub.
  674. //
  675. Status = LsarClose( &Handle );
  676. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  677. ULONG Code = RpcExceptionCode();
  678. // Don't assert on bad handles -- this will cause bogus stress breaks
  679. // ASSERT(Code != RPC_X_SS_CONTEXT_MISMATCH);
  680. ASSERT(Code != RPC_S_INVALID_BINDING);
  681. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  682. } RpcEndExcept;
  683. if ( !NT_SUCCESS(Status)
  684. && (0 != Handle)) {
  685. //
  686. // Make sure in all error cases to remove the client side resources
  687. // consumed by this handle.
  688. //
  689. RpcTryExcept {
  690. (void) RpcSsDestroyClientContext(&Handle);
  691. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  692. //
  693. // The try/except is for app compat so that bad handles don't bring
  694. // the process down
  695. //
  696. NOTHING;
  697. } RpcEndExcept;
  698. }
  699. ASSERT( Status != STATUS_INVALID_PARAMETER_12 );
  700. ASSERT( Status != STATUS_INVALID_HANDLE );
  701. return Status;
  702. }
  703. NTSTATUS
  704. LsaDelete(
  705. IN LSA_HANDLE ObjectHandle
  706. )
  707. /*++
  708. Routine Description:
  709. The LsaDelete API deletes an object. The object must be
  710. open for DELETE access.
  711. Arguments:
  712. ObjectHandle - Handle from an LsaOpen<object-type> call.
  713. None.
  714. Return Value:
  715. NTSTATUS - Standard Nt Result Code
  716. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  717. to complete the operation.
  718. STATUS_INVALID_HANDLE - The specified handle is not valid.
  719. Result codes from RPC.
  720. --*/
  721. {
  722. NTSTATUS Status;
  723. RpcTryExcept {
  724. //
  725. // Try calling the new worker routine LsarDeleteObject(). If
  726. // this fails because it does not exist (versions 1.369 and earlier)
  727. // then call the old routine LsarDelete().
  728. //
  729. Status = LsarDeleteObject((LSAPR_HANDLE *) &ObjectHandle);
  730. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  731. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  732. } RpcEndExcept;
  733. if ((Status == RPC_NT_UNKNOWN_IF) ||
  734. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE)) {
  735. RpcTryExcept {
  736. Status = LsarDelete((LSAPR_HANDLE) ObjectHandle);
  737. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  738. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  739. } RpcEndExcept;
  740. }
  741. return(Status);
  742. }
  743. NTSTATUS
  744. LsaQuerySecurityObject(
  745. IN LSA_HANDLE ObjectHandle,
  746. IN SECURITY_INFORMATION SecurityInformation,
  747. OUT PSECURITY_DESCRIPTOR *SecurityDescriptor
  748. )
  749. /*++
  750. Routine Description:
  751. The LsaQuerySecurityObject API returns security information assigned
  752. to an LSA Database object.
  753. Based on the caller's access rights and privileges, this procedure will
  754. return a security descriptor containing any or all of the object's owner
  755. ID, group ID, discretionary ACL or system ACL. To read the owner ID,
  756. group ID, or the discretionary ACL, the caller must be granted
  757. READ_CONTROL access to the object. To read the system ACL, the caller must
  758. have SeSecurityPrivilege privilege.
  759. This API is modelled after the NtQuerySecurityObject() system service.
  760. Arguments:
  761. ObjectHandle - A handle to an existing object in the LSA Database.
  762. SecurityInformation - Supplies a value describing which pieces of
  763. security information are being queried. The values that may be
  764. specified are the same as those defined in the NtSetSecurityObject()
  765. API section.
  766. SecurityDescriptor - receives a pointer to a buffer containing the
  767. requested security information. This information is returned in
  768. the form of a security descriptor. The caller is responsible for
  769. freeing the returned buffer using LsaFreeMemory() when no longer
  770. needed.
  771. Return Values:
  772. NTSTATUS - Standard Nt Result Code
  773. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  774. to complete the operation.
  775. STATUS_INVALID_PARAMETER - An invalid parameter has been specified.
  776. --*/
  777. {
  778. NTSTATUS Status;
  779. LSAPR_SR_SECURITY_DESCRIPTOR ReturnedSD;
  780. PLSAPR_SR_SECURITY_DESCRIPTOR PReturnedSD;
  781. //
  782. // The retrieved security descriptor is returned via a data structure that
  783. // looks like:
  784. //
  785. // +-----------------------+
  786. // | Length (bytes) |
  787. // |-----------------------| +--------------+
  788. // | SecurityDescriptor ---|--------->| Self-Relative|
  789. // +-----------------------+ | Security |
  790. // | Descriptor |
  791. // +--------------+
  792. //
  793. // The first of these buffers is a local stack variable. The buffer containing
  794. // the self-relative security descriptor is allocated by the RPC runtime. The
  795. // pointer to the self-relative security descriptor is what is passed back to our
  796. // caller.
  797. //
  798. //
  799. //
  800. // To prevent RPC from trying to marshal a self-relative security descriptor,
  801. // make sure its field values are appropriately initialized to zero and null.
  802. //
  803. ReturnedSD.Length = 0;
  804. ReturnedSD.SecurityDescriptor = NULL;
  805. //
  806. // Call the server ...
  807. //
  808. RpcTryExcept{
  809. PReturnedSD = &ReturnedSD;
  810. Status = LsarQuerySecurityObject(
  811. (LSAPR_HANDLE) ObjectHandle,
  812. SecurityInformation,
  813. &PReturnedSD
  814. );
  815. if (NT_SUCCESS(Status)) {
  816. (*SecurityDescriptor) = ReturnedSD.SecurityDescriptor;
  817. } else {
  818. (*SecurityDescriptor) = NULL;
  819. }
  820. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  821. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  822. } RpcEndExcept;
  823. if (!NT_SUCCESS(Status)) {
  824. goto QuerySecurityObjectError;
  825. }
  826. QuerySecurityObjectFinish:
  827. return(Status);
  828. QuerySecurityObjectError:
  829. goto QuerySecurityObjectFinish;
  830. }
  831. NTSTATUS
  832. LsaSetSecurityObject(
  833. IN LSA_HANDLE ObjectHandle,
  834. IN SECURITY_INFORMATION SecurityInformation,
  835. IN PSECURITY_DESCRIPTOR SecurityDescriptor
  836. )
  837. /*++
  838. Routine Description:
  839. The LsaSetSecurityObject API takes a well formaed Security Descriptor
  840. and assigns specified portions of it to an object. Based on the flags set
  841. in the SecurityInformation parameter and the caller's access rights, this
  842. procedure will replace any or alll of the security information associated
  843. with the object.
  844. The caller must have WRITE_OWNER access to the object to change the
  845. owner or Primary group of the object. The caller must have WRITE_DAC
  846. access to the object to change the Discretionary ACL. The caller must
  847. have SeSecurityPrivilege to assign a system ACL to an object.
  848. This API is modelled after the NtSetSecurityObject() system service.
  849. Arguments:
  850. ObjectHandle - A handle to an existing object in the LSA Database.
  851. SecurityInformation - Indicates which security information is to be
  852. applied to the object. The values that may be specified are the
  853. same as those defined in the NtSetSecurityObject() API section.
  854. The value(s) to be assigned are passed in the SecurityDescriptor
  855. parameter.
  856. SecurityDescriptor - A pointer to a well formed Security Descriptor.
  857. Return Values:
  858. NTSTATUS - Standard Nt Result Code
  859. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  860. to complete the operation.
  861. STATUS_INVALID_PARAMETER - An invalid parameter has been specified.
  862. --*/
  863. {
  864. NTSTATUS Status;
  865. ULONG SDLength;
  866. LSAPR_SR_SECURITY_DESCRIPTOR DescriptorToPass = { 0 };
  867. //
  868. // Make a self relative security descriptor for use in the RPC call..
  869. //
  870. SDLength = 0;
  871. Status = RtlMakeSelfRelativeSD( SecurityDescriptor, NULL, &SDLength);
  872. if (Status != STATUS_BUFFER_TOO_SMALL) {
  873. Status = STATUS_INVALID_PARAMETER;
  874. goto SetSecurityObjectError;
  875. }
  876. DescriptorToPass.SecurityDescriptor = MIDL_user_allocate( SDLength );
  877. Status = STATUS_INSUFFICIENT_RESOURCES;
  878. if (DescriptorToPass.SecurityDescriptor == NULL) {
  879. goto SetSecurityObjectError;
  880. }
  881. //
  882. // Make an appropriate self-relative security descriptor
  883. //
  884. Status = RtlMakeSelfRelativeSD(
  885. SecurityDescriptor,
  886. (PSECURITY_DESCRIPTOR)DescriptorToPass.SecurityDescriptor,
  887. &SDLength
  888. );
  889. if (!NT_SUCCESS(Status)) {
  890. goto SetSecurityObjectError;
  891. }
  892. DescriptorToPass.Length = SDLength;
  893. RpcTryExcept{
  894. Status = LsarSetSecurityObject(
  895. (LSAPR_HANDLE) ObjectHandle,
  896. SecurityInformation,
  897. &DescriptorToPass
  898. );
  899. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  900. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  901. } RpcEndExcept;
  902. if (!NT_SUCCESS(Status)) {
  903. goto SetSecurityObjectError;
  904. }
  905. SetSecurityObjectFinish:
  906. //
  907. // If necessary, free the Self Relative SD passed to the worker.
  908. //
  909. if (DescriptorToPass.SecurityDescriptor != NULL) {
  910. MIDL_user_free( DescriptorToPass.SecurityDescriptor );
  911. DescriptorToPass.SecurityDescriptor = NULL;
  912. }
  913. return(Status);
  914. SetSecurityObjectError:
  915. goto SetSecurityObjectFinish;
  916. }
  917. NTSTATUS
  918. LsaChangePassword(
  919. IN PUNICODE_STRING ServerName,
  920. IN PUNICODE_STRING DomainName,
  921. IN PUNICODE_STRING AccountName,
  922. IN PUNICODE_STRING OldPassword,
  923. IN PUNICODE_STRING NewPassword
  924. )
  925. /*++
  926. Routine Description:
  927. The LsaChangePassword API is used to change a user account's password.
  928. The user must have appropriate access to the user account and must
  929. know the current password value.
  930. Arguments:
  931. ServerName - The name of the Domain Controller at which the password
  932. can be changed.
  933. DomainName - The name of the domain in which the account exists.
  934. AccountName - The name of the account whose password is to be changed.
  935. NewPassword - The new password value.
  936. OldPassword - The old (current) password value.
  937. Return Values:
  938. NTSTATUS - Standard Nt Result Code
  939. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  940. to complete the operation.
  941. STATUS_ILL_FORMED_PASSWORD - The new password is poorly formed, e.g.
  942. contains characters that can't be entered from the keyboard.
  943. STATUS_PASSWORD_RESTRICTION - A restriction prevents the password
  944. from being changed. This may be for an number of reasons,
  945. including time restrictions on how often a password may be changed
  946. or length restrictions on the provided (new) password.
  947. This error might also be returned if the new password matched
  948. a password in the recent history log for the account. Security
  949. administrators indicate how many of the most recently used
  950. passwords may not be re-used.
  951. STATUS_WRONG_PASSWORD - OldPassword does not contain the user's
  952. current password.
  953. STATUS_NO_SUCH_USER - The SID provided does not lead to a user
  954. account.
  955. STATUS_CANT_UPDATE_MASTER - An attempt to update the master copy
  956. of the password was unsuccessful. Please try again later.
  957. --*/
  958. {
  959. NTSTATUS Status;
  960. DBG_UNREFERENCED_PARAMETER( ServerName );
  961. DBG_UNREFERENCED_PARAMETER( DomainName );
  962. DBG_UNREFERENCED_PARAMETER( AccountName );
  963. DBG_UNREFERENCED_PARAMETER( OldPassword );
  964. DBG_UNREFERENCED_PARAMETER( NewPassword );
  965. Status = STATUS_NOT_IMPLEMENTED;
  966. return(Status);
  967. }
  968. NTSTATUS
  969. LsaCreateAccount(
  970. IN LSA_HANDLE PolicyHandle,
  971. IN PSID AccountSid,
  972. IN ACCESS_MASK DesiredAccess,
  973. OUT PLSA_HANDLE AccountHandle
  974. )
  975. /*++
  976. Routine Description:
  977. The LsaCreateAccount API adds a user or group account to the
  978. list of accounts in the target system's LsaDatabase object. The
  979. newly added account object is initially placed in the opened state and
  980. a handle to it is returned. The caller must have LSA_CREATE_ACCOUNT
  981. access to the LsaDatabase object.
  982. Note that no check is made to determine whether there is an account
  983. of the given Sid in the target system's Primary Domain (if any), nor
  984. is any check made to verify that the Sid and name describe the same
  985. account.
  986. Arguments:
  987. PolicyHandle - Handle from an LsaOpenLsa call.
  988. AccountSid - Points to the SID of the Account object.
  989. DesiredAccess - Specifies the accesses to be granted to the newly
  990. created and opened account.
  991. AccountHandle - Receives a handle to the newly created and opened
  992. account. This handle is used on subsequent accesses to the account
  993. until closed.
  994. Return Values:
  995. NTSTATUS - Standard Nt Result Code
  996. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  997. to complete the operation.
  998. STATUS_ACCOUNT_ALREADY_EXISTS - A user or group account object having
  999. the Sid given in AccountInformation already exists.
  1000. STATUS_INVALID_PARAMETER - An invalid parameter has been specified,
  1001. one or more of the following apply.
  1002. - CreateDisposition not valid
  1003. - A user or group account having the Sid given AccountInformation
  1004. already exists, but CreateDisposition = LSA_OBJECT_CREATE.
  1005. --*/
  1006. {
  1007. NTSTATUS Status;
  1008. RpcTryExcept {
  1009. Status = LsarCreateAccount(
  1010. (LSAPR_HANDLE) PolicyHandle,
  1011. (PLSAPR_SID) AccountSid,
  1012. DesiredAccess,
  1013. (PLSAPR_HANDLE) AccountHandle
  1014. );
  1015. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1016. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1017. } RpcEndExcept;
  1018. return Status;
  1019. }
  1020. NTSTATUS
  1021. LsaEnumerateAccounts(
  1022. IN LSA_HANDLE PolicyHandle,
  1023. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  1024. OUT PVOID *Buffer,
  1025. IN ULONG PreferedMaximumLength,
  1026. OUT PULONG CountReturned
  1027. )
  1028. /*++
  1029. Routine Description:
  1030. The LsaEnumerateAccounts API returns information about
  1031. Account objects. This call requires
  1032. POLICY_VIEW_LOCAL_INFORMATION access to the Policy object. Since there
  1033. may be more information than can be returned in a single call of the
  1034. routine, multiple calls can be made to get all of the information. To
  1035. support this feature, the caller is provided with a handle that can
  1036. be used across calls to the API. On the initial call, EnumerationContext
  1037. should point to a variable that has been initialized to 0.
  1038. Arguments:
  1039. PolicyHandle - Handle from an LsaOpenLsa call.
  1040. EnumerationContext - API-specific handle to allow multiple calls
  1041. (see Routine Description above).
  1042. EnumerationInformation - Receives a pointer to an array of structures
  1043. each describing an Account object. Currently, each structure contains
  1044. a pointer to the Account Sid.
  1045. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  1046. bytes). This is not a hard upper limit, but serves as a guide. Due to
  1047. data conversion between systems with different natural data sizes, the
  1048. actual amount of data returned may be greater than this value.
  1049. CountReturned - Pointer to location which receives the number of entries
  1050. returned.
  1051. Return Values:
  1052. NTSTATUS - Standard Nt Result Code
  1053. STATUS_SUCCESS - The call completed successfully, there may be
  1054. more entries.
  1055. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1056. to complete the operation.
  1057. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  1058. is returned if there are no more objects to enumerate. Note that
  1059. one or more objects may be enumerated on a call that returns this
  1060. reply.
  1061. STATUS_INVALID_PARAMETER - Invalid parameter.
  1062. - NULL return pointer for enumeration buffer.
  1063. --*/
  1064. {
  1065. NTSTATUS Status;
  1066. LSAPR_ACCOUNT_ENUM_BUFFER EnumerationBuffer;
  1067. EnumerationBuffer.EntriesRead = 0;
  1068. EnumerationBuffer.Information = NULL;
  1069. RpcTryExcept {
  1070. //
  1071. // Enumerate the Accounts. On successful return,
  1072. // the Enumeration Buffer structure will receive a count
  1073. // of the number of Accounts enumerated this call
  1074. // and a pointer to an array of Account Information Entries.
  1075. //
  1076. // EnumerationBuffer -> EntriesRead
  1077. // Information -> Account Info for Domain 0
  1078. // Account Info for Domain 1
  1079. // ...
  1080. // Account Info for Domain
  1081. // (EntriesRead - 1)
  1082. //
  1083. Status = LsarEnumerateAccounts(
  1084. (LSAPR_HANDLE) PolicyHandle,
  1085. EnumerationContext,
  1086. &EnumerationBuffer,
  1087. PreferedMaximumLength
  1088. );
  1089. //
  1090. // Return enumeration information or NULL to caller.
  1091. //
  1092. // NOTE: "Information" is allocated by the called client stub
  1093. // as a single block via MIDL_user_allocate, because Information is
  1094. // allocated all-nodes. We can therefore pass back the pointer
  1095. // directly to the client, who will be able to free the memory after
  1096. // use via LsaFreeMemory() [which makes a MIDL_user_free call].
  1097. //
  1098. *CountReturned = EnumerationBuffer.EntriesRead;
  1099. *Buffer = EnumerationBuffer.Information;
  1100. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1101. //
  1102. // If memory was allocated for the Account Information array,
  1103. // free it.
  1104. //
  1105. if (EnumerationBuffer.Information != NULL) {
  1106. MIDL_user_free(EnumerationBuffer.Information);
  1107. }
  1108. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1109. } RpcEndExcept;
  1110. return Status;
  1111. }
  1112. NTSTATUS
  1113. LsaCreateTrustedDomain(
  1114. IN LSA_HANDLE PolicyHandle,
  1115. IN PLSA_TRUST_INFORMATION TrustedDomainInformation,
  1116. IN ACCESS_MASK DesiredAccess,
  1117. OUT PLSA_HANDLE TrustedDomainHandle
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. The LsaCreateTrustedDomain API creates a new TrustedDomain object. The
  1122. caller must have POLICY_TRUST_ADMIN access to the Policy Object.
  1123. Note that NO verification is done to check that the given domain name
  1124. matches the given SID or that the SID or name represent an actual domain.
  1125. Arguments:
  1126. PolicyHandle - Handle from an LsaOpenPolicy call.
  1127. TrustedDomainInformation - Pointer to structure containing the name and
  1128. SID of the new Trusted Domain.
  1129. DesiredAccess - Specifies the accesses to be granted for the newly
  1130. created object.
  1131. TrustedDomainHandle - receives a handle referencing the newly created
  1132. object. This handle is used on subsequent accesses to the object.
  1133. --*/
  1134. {
  1135. NTSTATUS Status;
  1136. *TrustedDomainHandle = NULL;
  1137. RpcTryExcept {
  1138. Status = LsarCreateTrustedDomain(
  1139. (LSAPR_HANDLE) PolicyHandle,
  1140. (PLSAPR_TRUST_INFORMATION) TrustedDomainInformation,
  1141. DesiredAccess,
  1142. (PLSAPR_HANDLE) TrustedDomainHandle
  1143. );
  1144. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1145. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1146. } RpcEndExcept;
  1147. return(Status);
  1148. }
  1149. NTSTATUS
  1150. LsaOpenTrustedDomain(
  1151. IN LSA_HANDLE PolicyHandle,
  1152. IN PSID TrustedDomainSid,
  1153. IN ACCESS_MASK DesiredAccess,
  1154. OUT PLSA_HANDLE TrustedDomainHandle
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. The LsaOpenTrustedDomain API opens an existing TrustedDomain object
  1159. using the SID as the primary key value.
  1160. Arguments:
  1161. PolicyHandle - An open handle to a Policy object.
  1162. TrustedDomainSid - Pointer to the account's Sid.
  1163. DesiredAccess - This is an access mask indicating accesses being
  1164. requested to the target object.
  1165. TrustedDomainHandle - Receives a handle to be used in future requests.
  1166. Return Values:
  1167. NTSTATUS - Standard Nt Result Code
  1168. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1169. to complete the operation.
  1170. STATUS_TRUSTED_DOMAIN_NOT_FOUND - There is no TrustedDomain object in the
  1171. target system's LSA Database having the specified AccountSid.
  1172. --*/
  1173. {
  1174. NTSTATUS Status;
  1175. RpcTryExcept {
  1176. Status = LsarOpenTrustedDomain(
  1177. (LSAPR_HANDLE) PolicyHandle,
  1178. (PLSAPR_SID) TrustedDomainSid,
  1179. DesiredAccess,
  1180. (PLSAPR_HANDLE) TrustedDomainHandle
  1181. );
  1182. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1183. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1184. } RpcEndExcept;
  1185. return Status;
  1186. }
  1187. NTSTATUS
  1188. LsaQueryInfoTrustedDomain(
  1189. IN LSA_HANDLE TrustedDomainHandle,
  1190. IN TRUSTED_INFORMATION_CLASS InformationClass,
  1191. OUT PVOID *Buffer
  1192. )
  1193. /*++
  1194. Routine Description:
  1195. The LsaQueryInfoTrustedDomain API obtains information from a
  1196. TrustedDomain object. The caller must have access appropriate to the
  1197. information being requested (see InformationClass parameter).
  1198. Arguments:
  1199. TrustedDomainHandle - Handle from an LsaOpenTrustedDomain or
  1200. LsaCreateTrustedDomain call.
  1201. InformationClass - Specifies the information to be returned. The
  1202. Information Classes and accesses required are as follows:
  1203. Information Class Required Access Type
  1204. TrustedAccountNameInformation TRUSTED_QUERY_ACCOUNT_NAME
  1205. TrustedControllersInformation TRUSTED_QUERY_CONTROLLERS
  1206. TrustedPosixInformation TRUSTED_QUERY_POSIX
  1207. Buffer - Receives a pointer to the buffer returned comtaining the
  1208. requested information. This buffer is allocated by this service
  1209. and must be freed when no longer needed by passing the returned
  1210. value to LsaFreeMemory().
  1211. Return Value:
  1212. NTSTATUS - Standard Nt Result Code
  1213. STATUS_ACCESS_DENIED - Caller does not have the appropriate
  1214. access to complete the operation.
  1215. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  1216. such as memory, to complete the call.
  1217. --*/
  1218. {
  1219. NTSTATUS Status;
  1220. PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation = NULL;
  1221. //
  1222. // Avoid the internal info levels that represent the encrypted version on
  1223. // the wire.
  1224. //
  1225. switch ( InformationClass ) {
  1226. case TrustedDomainAuthInformationInternal:
  1227. case TrustedDomainFullInformationInternal:
  1228. case TrustedDomainInformationEx2Internal:
  1229. case TrustedDomainFullInformation2Internal:
  1230. return STATUS_INVALID_INFO_CLASS;
  1231. }
  1232. RpcTryExcept {
  1233. //
  1234. // Call the Client Stub for LsaQueryInformationTrustedDomain.
  1235. //
  1236. Status = LsarQueryInfoTrustedDomain(
  1237. (LSAPR_HANDLE) TrustedDomainHandle,
  1238. InformationClass,
  1239. &TrustedDomainInformation
  1240. );
  1241. //
  1242. // Return pointer to Policy Information for the given class, or NULL.
  1243. //
  1244. *Buffer = TrustedDomainInformation;
  1245. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1246. //
  1247. // If memory was allocated for the returned Trusted Domain Information,
  1248. // free it.
  1249. //
  1250. if (TrustedDomainInformation != NULL) {
  1251. MIDL_user_free(TrustedDomainInformation);
  1252. }
  1253. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1254. } RpcEndExcept;
  1255. return Status;
  1256. }
  1257. NTSTATUS
  1258. LsaSetInformationTrustedDomain(
  1259. IN LSA_HANDLE TrustedDomainHandle,
  1260. IN TRUSTED_INFORMATION_CLASS InformationClass,
  1261. IN PVOID Buffer
  1262. )
  1263. /*++
  1264. Routine Description:
  1265. The LsaSetInformationTrustedDomain API modifies information in the Trusted
  1266. Domain Object. The caller must have access appropriate to the
  1267. information to be changedin the Policy Object, see the InformationClass
  1268. parameter.
  1269. Arguments:
  1270. TrustedDomainHandle - Handle from an LsaOpenTrustedDomain or
  1271. LsaCreateTrustedDomain call.
  1272. InformationClass - Specifies the type of information being changed.
  1273. The information types and accesses required to change them are as
  1274. follows:
  1275. TrustedAccountInformation ( Cannot be set )
  1276. TrustedControllersInformation TRUSTED_SET_CONTROLLERS
  1277. TrustedPosixOffsetInformation TRUSTED_POSIX_INFORMATION
  1278. Buffer - Points to a structure containing the information appropriate
  1279. to the InformationClass parameter.
  1280. Return Value:
  1281. NTSTATUS - Standard Nt Result Code
  1282. STATUS_SUCCESS - Call completed successfully.
  1283. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1284. to complete the operation.
  1285. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  1286. such as memory, to complete the call.
  1287. STATUS_INVALID_HANDLE - Handle is invalid or is of the wrong type.
  1288. STATUS_INVALID_PARAMETER - Invalid parameter:
  1289. Information class invalid
  1290. Information class cannot be set
  1291. --*/
  1292. {
  1293. NTSTATUS Status;
  1294. PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL InternalAuthBuffer = NULL;
  1295. PVOID InternalBuffer;
  1296. TRUSTED_INFORMATION_CLASS InternalInformationClass;
  1297. LSAPR_TRUSTED_DOMAIN_FULL_INFORMATION_INTERNAL InternalFullBuffer;
  1298. //
  1299. // Initialization
  1300. //
  1301. InternalInformationClass = InformationClass;
  1302. InternalBuffer = Buffer;
  1303. //
  1304. // Avoid the internal info levels that represent the encrypted version on
  1305. // the wire.
  1306. //
  1307. switch ( InformationClass ) {
  1308. case TrustedPasswordInformation:
  1309. case TrustedDomainInformationBasic:
  1310. case TrustedDomainAuthInformationInternal:
  1311. case TrustedDomainFullInformationInternal:
  1312. case TrustedDomainInformationEx2Internal:
  1313. case TrustedDomainFullInformation2Internal:
  1314. Status = STATUS_INVALID_INFO_CLASS;
  1315. goto Cleanup;
  1316. //
  1317. // Handle the info classes that need to be encrypted on the wire
  1318. //
  1319. case TrustedDomainAuthInformation: {
  1320. //
  1321. // Encrypt the data into an internal buffer.
  1322. //
  1323. Status = LsapEncryptAuthInfo( TrustedDomainHandle,
  1324. (PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION) Buffer,
  1325. &InternalAuthBuffer );
  1326. if ( !NT_SUCCESS(Status)) {
  1327. goto Cleanup;
  1328. }
  1329. //
  1330. // Use an internal info level to tell the server that the data is
  1331. // encrypted.
  1332. //
  1333. InternalInformationClass = TrustedDomainAuthInformationInternal;
  1334. InternalBuffer = InternalAuthBuffer;
  1335. break;
  1336. }
  1337. //
  1338. // Handle the info classes that need to be encrypted on the wire
  1339. //
  1340. case TrustedDomainFullInformation: {
  1341. PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION FullBuffer =
  1342. (PLSAPR_TRUSTED_DOMAIN_FULL_INFORMATION) Buffer;
  1343. //
  1344. // Encrypt the data into an internal buffer.
  1345. //
  1346. Status = LsapEncryptAuthInfo( TrustedDomainHandle,
  1347. &FullBuffer->AuthInformation,
  1348. &InternalAuthBuffer );
  1349. if ( !NT_SUCCESS(Status)) {
  1350. goto Cleanup;
  1351. }
  1352. //
  1353. // Copy all of the information into a single new structure.
  1354. //
  1355. InternalFullBuffer.Information = FullBuffer->Information;
  1356. InternalFullBuffer.PosixOffset = FullBuffer->PosixOffset;
  1357. InternalFullBuffer.AuthInformation = *InternalAuthBuffer;
  1358. //
  1359. // Use an internal info level to tell the server that the data is
  1360. // encrypted.
  1361. //
  1362. InternalInformationClass = TrustedDomainFullInformationInternal;
  1363. InternalBuffer = &InternalFullBuffer;
  1364. break;
  1365. }
  1366. }
  1367. //
  1368. // If the information class was morphed,
  1369. // try the morphed class.
  1370. //
  1371. if ( InternalInformationClass != InformationClass ) {
  1372. RpcTryExcept {
  1373. //
  1374. // Call the Client Stub
  1375. //
  1376. Status = LsarSetInformationTrustedDomain(
  1377. (LSAPR_HANDLE) TrustedDomainHandle,
  1378. InternalInformationClass,
  1379. (PLSAPR_TRUSTED_DOMAIN_INFO) InternalBuffer
  1380. );
  1381. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1382. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1383. } RpcEndExcept;
  1384. //
  1385. // If the morphed info class is valid,
  1386. // we're all done with this call.
  1387. // (Otherwise, drop through to try the non-morphed class.)
  1388. //
  1389. if ( Status != RPC_NT_INVALID_TAG ) {
  1390. goto Cleanup;
  1391. }
  1392. }
  1393. //
  1394. // Handle non-morphed information classes.
  1395. //
  1396. RpcTryExcept {
  1397. //
  1398. // Call the Client Stub
  1399. //
  1400. Status = LsarSetInformationTrustedDomain(
  1401. (LSAPR_HANDLE) TrustedDomainHandle,
  1402. InformationClass,
  1403. (PLSAPR_TRUSTED_DOMAIN_INFO) Buffer
  1404. );
  1405. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1406. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1407. } RpcEndExcept;
  1408. Cleanup:
  1409. if ( InternalAuthBuffer != NULL ) {
  1410. LocalFree( InternalAuthBuffer );
  1411. }
  1412. return(Status);
  1413. }
  1414. NTSTATUS
  1415. LsaEnumerateTrustedDomains(
  1416. IN LSA_HANDLE PolicyHandle,
  1417. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  1418. OUT PVOID *Buffer,
  1419. IN ULONG PreferedMaximumLength,
  1420. OUT PULONG CountReturned
  1421. )
  1422. /*++
  1423. Routine Description:
  1424. The LsaEnumerateTrustedDomains API returns information about the accounts
  1425. in the target system's Policy object. This call requires
  1426. POLICY_VIEW_LOCAL_INFORMATION access to the Policy object. Since there
  1427. may be more information than can be returned in a single call of the
  1428. routine, multiple calls can be made to get all of the information. To
  1429. support this feature, the caller is provided with a handle that can
  1430. be used across calls to the API. On the initial call, EnumerationContext
  1431. should point to a variable that has been initialized to 0.
  1432. Arguments:
  1433. PolicyHandle - Handle from an LsaOpenPolicy call.
  1434. EnumerationContext - API-specific handle to allow multiple calls
  1435. (see Routine Description above).
  1436. Buffer - Receives a pointer to a buffer containing enumeration
  1437. information. This buffer is an array of structures of type
  1438. LSA_TRUST_INFORMATION. If no trusted domains are found,
  1439. NULL is returned.
  1440. PreferedMaximumLength - Prefered maximum length of returned data (in 8-bit
  1441. bytes). This is not a hard upper limit, but serves as a guide. Due to
  1442. data conversion between systems with different natural data sizes, the
  1443. actual amount of data returned may be greater than this value.
  1444. CountReturned - Pointer to variable which will receive a count of the
  1445. entries returned.
  1446. Return Values:
  1447. NTSTATUS - Standard Nt Result Code
  1448. STATUS_SUCCESS - The call completed successfully, there may be
  1449. more entries.
  1450. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1451. to complete the operation.
  1452. STATUS_NO_MORE_ENTRIES - There are no more entries. This warning
  1453. is returned if there are no more objects to enumerate. Note that
  1454. one or more objects may be enumerated on a call that returns this
  1455. reply.
  1456. STATUS_INVALID_PARAMETER - Invalid parameter.
  1457. - NULL return pointer for enumeration buffer.
  1458. --*/
  1459. {
  1460. NTSTATUS Status;
  1461. LSAPR_TRUSTED_ENUM_BUFFER EnumerationBuffer;
  1462. EnumerationBuffer.EntriesRead = 0;
  1463. EnumerationBuffer.Information = NULL;
  1464. //
  1465. // Verify that caller has provided a return buffer pointer.
  1466. //
  1467. if (!ARGUMENT_PRESENT(Buffer)) {
  1468. return(STATUS_INVALID_PARAMETER);
  1469. }
  1470. RpcTryExcept {
  1471. //
  1472. // Enumerate the Trusted Domains. On successful return,
  1473. // the Enumeration Buffer structure will receive a count
  1474. // of the number of Trusted Domains enumerated this call
  1475. // and a pointer to an array of Trust Information Entries.
  1476. //
  1477. // EnumerationBuffer -> EntriesRead
  1478. // Information -> Trust Info for Domain 0
  1479. // Trust Info for Domain 1
  1480. // ...
  1481. // Trust Info for Domain
  1482. // (EntriesRead - 1)
  1483. //
  1484. //
  1485. Status = LsarEnumerateTrustedDomains(
  1486. (LSAPR_HANDLE) PolicyHandle,
  1487. EnumerationContext,
  1488. &EnumerationBuffer,
  1489. PreferedMaximumLength
  1490. );
  1491. //
  1492. // Return enumeration information or NULL to caller.
  1493. //
  1494. // NOTE: "Information" is allocated by the called client stub
  1495. // as a single block via MIDL_user_allocate, because Information is
  1496. // allocated all-nodes. We can therefore pass back the pointer
  1497. // directly to the client, who will be able to free the memory after
  1498. // use via LsaFreeMemory() [which makes a MIDL_user_free call].
  1499. //
  1500. *CountReturned = EnumerationBuffer.EntriesRead;
  1501. *Buffer = EnumerationBuffer.Information;
  1502. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1503. //
  1504. // If memory was allocated for the Trust Information array,
  1505. // free it.
  1506. //
  1507. if (EnumerationBuffer.Information != NULL) {
  1508. MIDL_user_free(EnumerationBuffer.Information);
  1509. }
  1510. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1511. } RpcEndExcept;
  1512. return Status;
  1513. }
  1514. NTSTATUS
  1515. LsaEnumeratePrivileges(
  1516. IN LSA_HANDLE PolicyHandle,
  1517. IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext,
  1518. OUT PVOID *Buffer,
  1519. IN ULONG PreferedMaximumLength,
  1520. OUT PULONG CountReturned
  1521. )
  1522. /*++
  1523. Routine Description:
  1524. This function returnes information about privileges known on this
  1525. system. This call requires POLICY_VIEW_LOCAL_INFORMATION access
  1526. to the Policy Object. Since there may be more information than
  1527. can be returned in a single call of the routine, multiple calls
  1528. can be made to get all of the information. To support this feature,
  1529. the caller is provided with a handle that can be used across calls to
  1530. the API. On the initial call, EnumerationContext should point to a
  1531. variable that has been initialized to 0.
  1532. WARNING! CURRENTLY, THIS FUNCTION ONLY RETURNS INFORMATION ABOUT
  1533. WELL-KNOWN PRIVILEGES. LATER, IT WILL RETURN INFORMATION
  1534. ABOUT LOADED PRIVILEGES.
  1535. Arguments:
  1536. PolicyHandle - Handle from an LsaOpenPolicy() call.
  1537. EnumerationContext - API specific handle to allow multiple calls
  1538. (see Routine Description).
  1539. Buffer - Receives a pointer to a buffer containing information for
  1540. one or more Privileges. This information is an array of structures
  1541. of type POLICY_PRIVILEGE_DEFINITION.
  1542. When this information is no longer needed, it must be released by
  1543. passing the returned pointer to LsaFreeMemory().
  1544. PreferedMaximumLength - Prefered maximim length of returned data
  1545. (in 8-bit bytes). This is not a hard upper limit, but serves as
  1546. a guide. Due to data conversion between systems with different
  1547. natural data sizes, the actual amount of data returned may be
  1548. greater than this value.
  1549. CountReturned - Number of entries returned.
  1550. Return Values:
  1551. NTSTATUS - Standard Nt Result Code.
  1552. STATUS_SUCCESS - The call completed successfully.
  1553. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources,
  1554. such as memory, to complete the call.
  1555. STATUS_INVALID_HANDLE - PolicyHandle is not a valid handle to
  1556. a Policy object.
  1557. STATUS_ACCESS_DENIED - The caller does not have the necessary
  1558. access to perform the operation.
  1559. STATUS_MORE_ENTRIES - There are more entries, so call again. This
  1560. is an informational status only.
  1561. STATUS_NO_MORE_ENTRIES - No entries were returned because there
  1562. are no more.
  1563. Errors from RPC.
  1564. --*/
  1565. {
  1566. NTSTATUS Status;
  1567. LSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer;
  1568. EnumerationBuffer.Entries = 0;
  1569. EnumerationBuffer.Privileges = NULL;
  1570. RpcTryExcept {
  1571. //
  1572. // Enumerate the Privileges. On successful return,
  1573. // the Enumeration Buffer structure will receive a count
  1574. // of the number of Privileges enumerated this call
  1575. // and a pointer to an array of Privilege Definition Entries.
  1576. //
  1577. // EnumerationBuffer -> Entries
  1578. // Privileges -> Privilege Definition 0
  1579. // Privilege Definition 1
  1580. // ...
  1581. // Privilege Definition
  1582. // (Entries - 1)
  1583. //
  1584. Status = LsarEnumeratePrivileges(
  1585. (LSAPR_HANDLE) PolicyHandle,
  1586. EnumerationContext,
  1587. &EnumerationBuffer,
  1588. PreferedMaximumLength
  1589. );
  1590. //
  1591. // Return enumeration information or NULL to caller.
  1592. //
  1593. // NOTE: "Information" is allocated by the called client stub
  1594. // as a single block via MIDL_user_allocate, because Information is
  1595. // allocated all-nodes. We can therefore pass back the pointer
  1596. // directly to the client, who will be able to free the memory after
  1597. // use via LsaFreeMemory() [which makes a MIDL_user_free call].
  1598. //
  1599. *CountReturned = EnumerationBuffer.Entries;
  1600. *Buffer = EnumerationBuffer.Privileges;
  1601. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1602. //
  1603. // If memory was allocated for the Account Information array,
  1604. // free it.
  1605. //
  1606. if (EnumerationBuffer.Privileges != NULL) {
  1607. MIDL_user_free(EnumerationBuffer.Privileges);
  1608. }
  1609. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1610. } RpcEndExcept;
  1611. return Status;
  1612. }
  1613. NTSTATUS
  1614. LsaCreateSecret(
  1615. IN LSA_HANDLE PolicyHandle,
  1616. IN PUNICODE_STRING SecretName,
  1617. IN ACCESS_MASK DesiredAccess,
  1618. OUT PLSA_HANDLE SecretHandle
  1619. )
  1620. /*++
  1621. Routine Description:
  1622. The LsaCreateSecretInLsa API creates a named Secret object in the
  1623. Lsa Database. Each Secret Object can have two values assigned,
  1624. called the Current Value and the Old Value. The meaning of these
  1625. values is known to the Secret object creator. The caller must have
  1626. LSA_CREATE_SECRET access to the LsaDatabase object.
  1627. Arguments:
  1628. PolicyHandle - Handle from an LsaOpenLsa call.
  1629. SecretName - Pointer to Unicode String specifying the name of the
  1630. secret.
  1631. DesiredAccess - Specifies the accesses to be granted to the newly
  1632. created and opened secret.
  1633. SecretHandle - Receives a handle to the newly created and opened
  1634. Secret object. This handle is used on subsequent accesses to
  1635. the object until closed.
  1636. Return Values:
  1637. NTSTATUS - Standard Nt Result Code
  1638. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1639. to complete the operation.
  1640. STATUS_OBJECT_NAME_COLLISION - A Secret object having the given name
  1641. already exists.
  1642. STATUS_TOO_MANY_SECRETS - The maximum number of Secret objects in the
  1643. system has been reached.
  1644. STATUS_PRIVILEGE_NOT_HELD - ACCESS_SYSTEM_SECURITY was specified as part
  1645. of DesiredAccess mask, but the caller does not hold SE_SECURITY_PRIVILEGE
  1646. --*/
  1647. {
  1648. NTSTATUS Status;
  1649. *SecretHandle = NULL;
  1650. RpcTryExcept {
  1651. //
  1652. // Verify that the given SecretName has non-null length. Currently
  1653. // midl cannot handle this.
  1654. //
  1655. if ((SecretName == NULL) ||
  1656. (SecretName->Buffer == NULL) ||
  1657. (SecretName->Length == 0) ||
  1658. (SecretName->Length > SecretName->MaximumLength)) {
  1659. Status = STATUS_INVALID_PARAMETER;
  1660. } else {
  1661. Status = LsarCreateSecret(
  1662. (LSAPR_HANDLE) PolicyHandle,
  1663. (PLSAPR_UNICODE_STRING) SecretName,
  1664. DesiredAccess,
  1665. (PLSAPR_HANDLE) SecretHandle
  1666. );
  1667. }
  1668. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1669. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  1670. } RpcEndExcept;
  1671. return(Status);
  1672. }
  1673. NTSTATUS
  1674. LsaLookupNames2(
  1675. IN LSA_HANDLE PolicyHandle,
  1676. IN ULONG Flags,
  1677. IN ULONG Count,
  1678. IN PUNICODE_STRING Names,
  1679. OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
  1680. OUT PLSA_TRANSLATED_SID2 *Sids
  1681. )
  1682. /*++
  1683. Routine Description:
  1684. The LsaLookupNames API attempts to translate names of domains, users,
  1685. groups or aliases to Sids. The caller must have POLICY_LOOKUP_NAMES
  1686. access to the Policy object.
  1687. Names may be either isolated (e.g. JohnH) or composite names containing
  1688. both the domain name and account name. Composite names must include a
  1689. backslash character separating the domain name from the account name
  1690. (e.g. Acctg\JohnH). An isolated name may be either an account name
  1691. (user, group, or alias) or a domain name.
  1692. Translation of isolated names introduces the possibility of name
  1693. collisions (since the same name may be used in multiple domains). An
  1694. isolated name will be translated using the following algorithm:
  1695. If the name is a well-known name (e.g. Local or Interactive), then the
  1696. corresponding well-known Sid is returned.
  1697. If the name is the Built-in Domain's name, then that domain's Sid
  1698. will be returned.
  1699. If the name is the Account Domain's name, then that domain's Sid
  1700. will be returned.
  1701. If the name is the Primary Domain's name, then that domain's Sid will
  1702. be returned.
  1703. If the name is a user, group, or alias in the Built-in Domain, then the
  1704. Sid of that account is returned.
  1705. If the name is a user, group, or alias in the Primary Domain, then the
  1706. Sid of that account is returned.
  1707. Otherwise, the name is not translated.
  1708. NOTE: Proxy, Machine, and Trust user accounts are not referenced
  1709. for name translation. Only normal user accounts are used for ID
  1710. translation. If translation of other account types is needed, then
  1711. SAM services should be used directly.
  1712. Arguments:
  1713. This function is the LSA server RPC worker routine for the
  1714. LsaLookupNamesInLsa API.
  1715. PolicyHandle - Handle from an LsaOpenPolicy call.
  1716. Flags - LSA_LOOKUP_ISOLATED_AS_LOCAL
  1717. Count - Specifies the number of names to be translated.
  1718. Names - Pointer to an array of Count Unicode String structures
  1719. specifying the names to be looked up and mapped to Sids.
  1720. The strings may be names of User, Group or Alias accounts or
  1721. domains.
  1722. ReferencedDomains - receives a pointer to a structure describing the
  1723. domains used for the translation. The entries in this structure
  1724. are referenced by the structure returned via the Sids parameter.
  1725. Unlike the Sids parameter, which contains an array entry for
  1726. each translated name, this structure will only contain one
  1727. component for each domain utilized in the translation.
  1728. When this information is no longer needed, it must be released
  1729. by passing the returned pointer to LsaFreeMemory().
  1730. Sids - Receives a pointer to an array of records describing each
  1731. translated Sid. The nth entry in this array provides a translation
  1732. for (the nth element in the Names parameter.
  1733. When this information is no longer needed, it must be released
  1734. by passing the returned pointer to LsaFreeMemory().
  1735. Return Values:
  1736. NTSTATUS - Standard Nt Result Code
  1737. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1738. to complete the operation.
  1739. STATUS_SOME_NOT_MAPPED - Some or all of the names provided could
  1740. not be mapped. This is an informational status only.
  1741. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
  1742. to complete the call.
  1743. STATUS_TOO_MANY_NAMES - Too many Names have been specified.
  1744. --*/
  1745. {
  1746. NTSTATUS Status = STATUS_SUCCESS;
  1747. ULONG MappedCount = 0;
  1748. ULONG i;
  1749. if ( (NULL == Sids)
  1750. || (NULL == ReferencedDomains ) ) {
  1751. return STATUS_INVALID_PARAMETER;
  1752. }
  1753. //
  1754. // Init the out parameters since LsaICLookupNames expects this
  1755. //
  1756. *ReferencedDomains = NULL;
  1757. *Sids = NULL;
  1758. Status = LsaICLookupNames(
  1759. PolicyHandle,
  1760. Flags,
  1761. Count,
  1762. Names,
  1763. (PLSA_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  1764. (PLSA_TRANSLATED_SID_EX2*)Sids,
  1765. LsapLookupWksta,
  1766. 0,
  1767. &MappedCount,
  1768. NULL
  1769. );
  1770. return(Status);
  1771. }
  1772. NTSTATUS
  1773. LsaLookupNames(
  1774. IN LSA_HANDLE PolicyHandle,
  1775. IN ULONG Count,
  1776. IN PUNICODE_STRING Names,
  1777. OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
  1778. OUT PLSA_TRANSLATED_SID *Sids
  1779. )
  1780. /*++
  1781. Routine Description:
  1782. The LsaLookupNames API attempts to translate names of domains, users,
  1783. groups or aliases to Sids. The caller must have POLICY_LOOKUP_NAMES
  1784. access to the Policy object.
  1785. Names may be either isolated (e.g. JohnH) or composite names containing
  1786. both the domain name and account name. Composite names must include a
  1787. backslash character separating the domain name from the account name
  1788. (e.g. Acctg\JohnH). An isolated name may be either an account name
  1789. (user, group, or alias) or a domain name.
  1790. Translation of isolated names introduces the possibility of name
  1791. collisions (since the same name may be used in multiple domains). An
  1792. isolated name will be translated using the following algorithm:
  1793. If the name is a well-known name (e.g. Local or Interactive), then the
  1794. corresponding well-known Sid is returned.
  1795. If the name is the Built-in Domain's name, then that domain's Sid
  1796. will be returned.
  1797. If the name is the Account Domain's name, then that domain's Sid
  1798. will be returned.
  1799. If the name is the Primary Domain's name, then that domain's Sid will
  1800. be returned.
  1801. If the name is a user, group, or alias in the Built-in Domain, then the
  1802. Sid of that account is returned.
  1803. If the name is a user, group, or alias in the Primary Domain, then the
  1804. Sid of that account is returned.
  1805. Otherwise, the name is not translated.
  1806. NOTE: Proxy, Machine, and Trust user accounts are not referenced
  1807. for name translation. Only normal user accounts are used for ID
  1808. translation. If translation of other account types is needed, then
  1809. SAM services should be used directly.
  1810. Arguments:
  1811. This function is the LSA server RPC worker routine for the
  1812. LsaLookupNamesInLsa API.
  1813. PolicyHandle - Handle from an LsaOpenPolicy call.
  1814. Count - Specifies the number of names to be translated.
  1815. Names - Pointer to an array of Count Unicode String structures
  1816. specifying the names to be looked up and mapped to Sids.
  1817. The strings may be names of User, Group or Alias accounts or
  1818. domains.
  1819. ReferencedDomains - receives a pointer to a structure describing the
  1820. domains used for the translation. The entries in this structure
  1821. are referenced by the structure returned via the Sids parameter.
  1822. Unlike the Sids parameter, which contains an array entry for
  1823. each translated name, this structure will only contain one
  1824. component for each domain utilized in the translation.
  1825. When this information is no longer needed, it must be released
  1826. by passing the returned pointer to LsaFreeMemory().
  1827. Sids - Receives a pointer to an array of records describing each
  1828. translated Sid. The nth entry in this array provides a translation
  1829. for (the nth element in the Names parameter.
  1830. When this information is no longer needed, it must be released
  1831. by passing the returned pointer to LsaFreeMemory().
  1832. Return Values:
  1833. NTSTATUS - Standard Nt Result Code
  1834. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1835. to complete the operation.
  1836. STATUS_SOME_NOT_MAPPED - Some or all of the names provided could
  1837. not be mapped. This is an informational status only.
  1838. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
  1839. to complete the call.
  1840. STATUS_TOO_MANY_NAMES - Too many Names have been specified.
  1841. --*/
  1842. {
  1843. NTSTATUS Status = STATUS_SUCCESS;
  1844. ULONG MappedCount = 0;
  1845. PLSA_TRANSLATED_SID_EX2 SidsEx = NULL;
  1846. ULONG i;
  1847. if ( (NULL == Sids)
  1848. || (NULL == ReferencedDomains ) ) {
  1849. return STATUS_INVALID_PARAMETER;
  1850. }
  1851. *Sids = NULL;
  1852. *ReferencedDomains = NULL;
  1853. Status = LsaICLookupNames(
  1854. PolicyHandle,
  1855. 0,
  1856. Count,
  1857. Names,
  1858. (PLSA_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  1859. &SidsEx,
  1860. LsapLookupWksta,
  1861. LSAIC_NO_LARGE_SID,
  1862. &MappedCount,
  1863. NULL
  1864. );
  1865. if ( SidsEx ) {
  1866. //
  1867. // Some sids were returned -- map the new structure to the old one
  1868. //
  1869. ULONG SizeNeeded = 0;
  1870. PLSA_TRANSLATED_SID TempSids = NULL;
  1871. SizeNeeded = Count * sizeof( LSA_TRANSLATED_SID );
  1872. TempSids = midl_user_allocate( SizeNeeded );
  1873. if ( TempSids ) {
  1874. RtlZeroMemory( TempSids, SizeNeeded );
  1875. for ( i = 0; i < Count; i++ ) {
  1876. TempSids[i].Use = SidsEx[i].Use;
  1877. if (SidTypeDomain == SidsEx[i].Use) {
  1878. TempSids[i].RelativeId = LSA_UNKNOWN_ID;
  1879. } else if (SidsEx[i].Sid) {
  1880. ULONG SubAuthCount = (ULONG) *RtlSubAuthorityCountSid(SidsEx[i].Sid);
  1881. TempSids[i].RelativeId = *RtlSubAuthoritySid(SidsEx[i].Sid, (SubAuthCount - 1));
  1882. } else {
  1883. TempSids[i].RelativeId = 0;
  1884. }
  1885. TempSids[i].DomainIndex = SidsEx[i].DomainIndex;
  1886. }
  1887. *Sids = TempSids;
  1888. } else {
  1889. Status = STATUS_INSUFFICIENT_RESOURCES;
  1890. if ( *ReferencedDomains ) {
  1891. midl_user_free( *ReferencedDomains );
  1892. *ReferencedDomains = NULL;
  1893. }
  1894. }
  1895. midl_user_free( SidsEx );
  1896. }
  1897. return(Status);
  1898. }
  1899. NTSTATUS
  1900. LsaICLookupNames(
  1901. IN LSA_HANDLE PolicyHandle,
  1902. IN ULONG LookupOptions,
  1903. IN ULONG Count,
  1904. IN PUNICODE_STRING Names,
  1905. OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
  1906. OUT PLSA_TRANSLATED_SID_EX2 *Sids,
  1907. IN LSAP_LOOKUP_LEVEL LookupLevel,
  1908. IN ULONG Flags,
  1909. IN OUT PULONG MappedCount,
  1910. IN OUT PULONG ServerRevision
  1911. )
  1912. /*++
  1913. Routine Description:
  1914. This function is the internal client side version of the LsaLookupNames
  1915. API. It is called both from the client side of the Lsa and also
  1916. the server side of the LSA (when calling out to another LSA). The
  1917. function is identical to the LsaLookupNames API except that there is an
  1918. additional parameter, the LookupLevel parameter.
  1919. The LsaLookupNames API attempts to translate names of domains, users,
  1920. groups or aliases to Sids. The caller must have POLICY_LOOKUP_NAMES
  1921. access to the Policy object.
  1922. Names may be either isolated (e.g. JohnH) or composite names containing
  1923. both the domain name and account name. Composite names must include a
  1924. backslash character separating the domain name from the account name
  1925. (e.g. Acctg\JohnH). An isolated name may be either an account name
  1926. (user, group, or alias) or a domain name.
  1927. Translation of isolated names introduces the possibility of name
  1928. collisions (since the same name may be used in multiple domains). An
  1929. isolated name will be translated using the following algorithm:
  1930. If the name is a well-known name (e.g. Local or Interactive), then the
  1931. corresponding well-known Sid is returned.
  1932. If the name is the Built-in Domain's name, then that domain's Sid
  1933. will be returned.
  1934. If the name is the Account Domain's name, then that domain's Sid
  1935. will be returned.
  1936. If the name is the Primary Domain's name, then that domain's Sid will
  1937. be returned.
  1938. If the name is a user, group, or alias in the Built-in Domain, then the
  1939. Sid of that account is returned.
  1940. If the name is a user, group, or alias in the Primary Domain, then the
  1941. Sid of that account is returned.
  1942. Otherwise, the name is not translated.
  1943. NOTE: Proxy, Machine, and Trust user accounts are not referenced
  1944. for name translation. Only normal user accounts are used for ID
  1945. translation. If translation of other account types is needed, then
  1946. SAM services should be used directly.
  1947. Arguments:
  1948. This function is the LSA server RPC worker routine for the
  1949. LsaLookupNamesInLsa API.
  1950. PolicyHandle - Handle from an LsaOpenPolicy call.
  1951. LookupOptions - Values to pass through to LsarLookupNames2 and above
  1952. Count - Specifies the number of names to be translated.
  1953. Names - Pointer to an array of Count Unicode String structures
  1954. specifying the names to be looked up and mapped to Sids.
  1955. The strings may be names of User, Group or Alias accounts or
  1956. domains.
  1957. ReferencedDomains - receives a pointer to a structure describing the
  1958. domains used for the translation. The entries in this structure
  1959. are referenced by the structure returned via the Sids parameter.
  1960. Unlike the Sids parameter, which contains an array entry for
  1961. each translated name, this structure will only contain one
  1962. component for each domain utilized in the translation.
  1963. When this information is no longer needed, it must be released
  1964. by passing the returned pointer to LsaFreeMemory().
  1965. Sids - Receives a pointer to an array of records describing each
  1966. translated Sid. The nth entry in this array provides a translation
  1967. for (the nth element in the Names parameter.
  1968. When this information is no longer needed, it must be released
  1969. by passing the returned pointer to LsaFreeMemory().
  1970. LookupLevel - Specifies the Level of Lookup to be performed on the
  1971. target machine. Values of this field are are follows:
  1972. LsapLookupWksta - First Level Lookup performed on a workstation
  1973. normally configured for Windows-Nt. The lookup searches the
  1974. Well-Known Sids/Names, and the Built-in Domain and Account Domain
  1975. in the local SAM Database. If not all Sids or Names are
  1976. identified, performs a "handoff" of a Second level Lookup to the
  1977. LSA running on a Controller for the workstation's Primary Domain
  1978. (if any).
  1979. LsapLookupPDC - Second Level Lookup performed on a Primary Domain
  1980. Controller. The lookup searches the Account Domain of the
  1981. SAM Database on the controller. If not all Sids or Names are
  1982. found, the Trusted Domain List (TDL) is obtained from the
  1983. LSA's Policy Database and Third Level lookups are performed
  1984. via "handoff" to each Trusted Domain in the List.
  1985. LsapLookupTDL - Third Level Lookup performed on a controller
  1986. for a Trusted Domain. The lookup searches the Account Domain of
  1987. the SAM Database on the controller only.
  1988. Flags - flags to control the operation of the function. Currently defined:
  1989. LSAIC_NO_LARGE_SID -- implies only call interfaces that will return
  1990. the old style format SID (no more than
  1991. 28 bytes)
  1992. LSAIC_NT4_TARGET -- target server is known to be NT4
  1993. LSAIC_WIN2K_TARGET -- target server is known to be Win2k
  1994. MappedCount - Pointer to location that contains a count of the Names
  1995. mapped so far. On exit, this count will be updated.
  1996. Return Values:
  1997. NTSTATUS - Standard Nt Result Code
  1998. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  1999. to complete the operation.
  2000. STATUS_SOME_NOT_MAPPED - Some or all of the names provided could
  2001. not be mapped. This is an informational status only.
  2002. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
  2003. to complete the call.
  2004. --*/
  2005. {
  2006. NTSTATUS Status = STATUS_SUCCESS;
  2007. ULONG LsaLookupNameRevision = 3;
  2008. LSAPR_TRANSLATED_SIDS_EX2 ReturnedSidsEx2 = { 0, NULL };
  2009. LSAPR_TRANSLATED_SIDS_EX ReturnedSidsEx = { 0, NULL };
  2010. LSAPR_TRANSLATED_SIDS ReturnedSids = { 0, NULL };
  2011. ULONG Size, SidCount = 0;
  2012. PBYTE NextSid;
  2013. ULONG i;
  2014. ULONG StartingRevision = 3;
  2015. //
  2016. // There are no known clients who pass in a value here
  2017. //
  2018. ASSERT( *ReferencedDomains == NULL );
  2019. ASSERT( *Sids == NULL );
  2020. //
  2021. // Init to NULL since these are considered to be a IN/OUT parameters
  2022. // for the Lsar Lookup API's
  2023. //
  2024. *ReferencedDomains = NULL;
  2025. *Sids = NULL;
  2026. //
  2027. // Check that we have not specfied more than the maximum number of names
  2028. // allowed.
  2029. //
  2030. if (Count > LSAP_DB_TRIAL_MAXIMUM_NAME_COUNT) {
  2031. return(STATUS_TOO_MANY_NAMES);
  2032. }
  2033. if ( ServerRevision ) {
  2034. // The latest client's will prefer the latest servers
  2035. *ServerRevision = LSA_LOOKUP_REVISION_LATEST;
  2036. }
  2037. //
  2038. // Adjust the starting version
  2039. //
  2040. StartingRevision = 3;
  2041. if ((Flags & LSAIC_NO_LARGE_SID)
  2042. || (Flags & LSAIC_WIN2K_TARGET) ) {
  2043. StartingRevision = 2;
  2044. }
  2045. if (Flags & LSAIC_NT4_TARGET) {
  2046. StartingRevision = 1;
  2047. }
  2048. switch (StartingRevision) {
  2049. case 3:
  2050. RpcTryExcept {
  2051. Status = LsarLookupNames3(
  2052. (LSAPR_HANDLE) PolicyHandle,
  2053. Count,
  2054. (PLSAPR_UNICODE_STRING) Names,
  2055. (PLSAPR_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  2056. &ReturnedSidsEx2,
  2057. LookupLevel,
  2058. MappedCount,
  2059. LookupOptions,
  2060. LSA_LOOKUP_REVISION_LATEST
  2061. );
  2062. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2063. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2064. } RpcEndExcept;
  2065. if ( (Status == RPC_NT_UNKNOWN_IF) ||
  2066. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE) ) {
  2067. //
  2068. // Continue on to next block;
  2069. //
  2070. NOTHING;
  2071. } else {
  2072. //
  2073. // The interface was supported; leave
  2074. //
  2075. break;
  2076. }
  2077. case 2:
  2078. RpcTryExcept {
  2079. Status = LsarLookupNames2(
  2080. (LSAPR_HANDLE) PolicyHandle,
  2081. Count,
  2082. (PLSAPR_UNICODE_STRING) Names,
  2083. (PLSAPR_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  2084. &ReturnedSidsEx,
  2085. LookupLevel,
  2086. MappedCount,
  2087. LookupOptions,
  2088. LSA_LOOKUP_REVISION_LATEST
  2089. );
  2090. LsaLookupNameRevision = 2;
  2091. if ( ReturnedSidsEx.Sids ) {
  2092. // Memory can be allocated on !NT_SUCCESS, namely
  2093. // STATUS_NONE_MAPPED
  2094. SidCount = ReturnedSidsEx.Entries;
  2095. }
  2096. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2097. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2098. } RpcEndExcept;
  2099. if ( (Status == RPC_NT_UNKNOWN_IF) ||
  2100. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE) ) {
  2101. //
  2102. // Continue on to next block;
  2103. //
  2104. NOTHING;
  2105. } else {
  2106. //
  2107. // The interface was supported; leave
  2108. //
  2109. break;
  2110. }
  2111. case 1:
  2112. if ( ServerRevision ) {
  2113. *ServerRevision = LSA_LOOKUP_REVISION_1;
  2114. }
  2115. RpcTryExcept {
  2116. Status = LsarLookupNames(
  2117. (LSAPR_HANDLE) PolicyHandle,
  2118. Count,
  2119. (PLSAPR_UNICODE_STRING) Names,
  2120. (PLSAPR_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  2121. &ReturnedSids,
  2122. LookupLevel,
  2123. MappedCount
  2124. );
  2125. LsaLookupNameRevision = 1;
  2126. if ( ReturnedSids.Sids ) {
  2127. // Memory can be allocated on !NT_SUCCESS, namely
  2128. // STATUS_NONE_MAPPED
  2129. SidCount = ReturnedSids.Entries;
  2130. }
  2131. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2132. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2133. } RpcEndExcept;
  2134. break;
  2135. default:
  2136. ASSERT(FALSE && "Programming error -- invalid revision" );
  2137. Status = STATUS_INVALID_PARAMETER;
  2138. goto Cleanup;
  2139. }
  2140. //
  2141. // Prevent against network hacks
  2142. //
  2143. if ( NT_SUCCESS( Status )
  2144. && (Count > 0)
  2145. && ( (LsaLookupNameRevision == 1) && ((ReturnedSids.Entries == 0)
  2146. || (ReturnedSids.Sids == NULL))
  2147. || (LsaLookupNameRevision == 2) && ((ReturnedSidsEx.Entries == 0)
  2148. || (ReturnedSidsEx.Sids == NULL))
  2149. || (LsaLookupNameRevision == 3) && ((ReturnedSidsEx2.Entries == 0)
  2150. || (ReturnedSidsEx2.Sids == NULL)))) {
  2151. //
  2152. // This is bogus -- an NT server would never return this
  2153. //
  2154. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2155. goto Cleanup;
  2156. }
  2157. //
  2158. // Ok at this point, we have a success -- map the return values
  2159. // to the latest revision: LSA_TRANSLATES_SID_EX2
  2160. //
  2161. if ( ((LsaLookupNameRevision == 2) && ReturnedSidsEx.Sids != NULL)
  2162. || ((LsaLookupNameRevision == 1) && ReturnedSids.Sids != NULL) ) {
  2163. //
  2164. // There should be a ReferencedDomains
  2165. //
  2166. ASSERT( NULL != *ReferencedDomains);
  2167. //
  2168. // Calculate the size necessary. All SID's from non Sid-Extended domains
  2169. // will be less than 28 bytes. However, we still sanity check the values
  2170. // returned from the untrusted net before copying in (see below).
  2171. //
  2172. #define MAX_DOWNLEVEL_SID_SIZE 28
  2173. //
  2174. // Since we are returning a buffer containing all allocations, make sure
  2175. // everything aligned properly
  2176. //
  2177. ASSERT(MAX_DOWNLEVEL_SID_SIZE ==
  2178. ROUND_UP_COUNT(MAX_DOWNLEVEL_SID_SIZE, ALIGN_DWORD));
  2179. ASSERT(sizeof(LSA_TRANSLATED_SID_EX2) ==
  2180. ROUND_UP_COUNT(sizeof(LSA_TRANSLATED_SID_EX2), ALIGN_DWORD));
  2181. Size = SidCount * sizeof(LSA_TRANSLATED_SID_EX2);
  2182. Size += SidCount * MAX_DOWNLEVEL_SID_SIZE;
  2183. ReturnedSidsEx2.Sids = MIDL_user_allocate(Size);
  2184. if (NULL == ReturnedSidsEx2.Sids) {
  2185. Status = STATUS_NO_MEMORY;
  2186. goto Cleanup;
  2187. }
  2188. RtlZeroMemory(ReturnedSidsEx2.Sids, Size);
  2189. NextSid = (PBYTE) ReturnedSidsEx2.Sids;
  2190. NextSid += (SidCount * sizeof(LSA_TRANSLATED_SID_EX2));
  2191. for ( i = 0; i < SidCount; i++ ) {
  2192. BYTE Buffer[MAX_DOWNLEVEL_SID_SIZE];
  2193. PSID Sid = (PSID)Buffer;
  2194. ULONG SidLength;
  2195. ULONG DomainIndex;
  2196. ULONG Rid;
  2197. SID_NAME_USE SidNameUse;
  2198. ULONG Flags;
  2199. PSID DomainSid;
  2200. if (1 == LsaLookupNameRevision) {
  2201. DomainIndex = ReturnedSids.Sids[i].DomainIndex;
  2202. Rid = ReturnedSids.Sids[i].RelativeId;
  2203. SidNameUse = ReturnedSids.Sids[i].Use;
  2204. Flags = 0;
  2205. } else {
  2206. ASSERT( 2 == LsaLookupNameRevision );
  2207. DomainIndex = ReturnedSidsEx.Sids[i].DomainIndex;
  2208. Rid = ReturnedSidsEx.Sids[i].RelativeId;
  2209. SidNameUse = ReturnedSidsEx.Sids[i].Use;
  2210. Flags = ReturnedSidsEx.Sids[i].Flags;
  2211. }
  2212. //
  2213. // Copy over the simple values
  2214. //
  2215. ReturnedSidsEx2.Sids[i].Use = SidNameUse;
  2216. ReturnedSidsEx2.Sids[i].DomainIndex = DomainIndex;
  2217. ReturnedSidsEx2.Sids[i].Flags = Flags;
  2218. //
  2219. // Copy over the sid if possible
  2220. //
  2221. // To support possible additions in the future, check for the negative cases.
  2222. // These types will never have any SIDs; all others must have a SID portion.
  2223. //
  2224. if ( (SidNameUse != SidTypeDeletedAccount)
  2225. && (SidNameUse != SidTypeInvalid)
  2226. && (SidNameUse != SidTypeUnknown) ) {
  2227. if (DomainIndex == LSA_UNKNOWN_INDEX) {
  2228. //
  2229. // This is a bogus return value
  2230. //
  2231. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2232. goto Cleanup;
  2233. }
  2234. //
  2235. // N.B. For domain names, the RID is set to LSA_UNKNOWN_ID and
  2236. // to be compatible with the LsarLookupName3 routine, return
  2237. // a SID in ReturedSidsEx2 structure.
  2238. //
  2239. DomainSid = (*ReferencedDomains)->Domains[DomainIndex].Sid;
  2240. if (RtlLengthSid(DomainSid) > (MAX_DOWNLEVEL_SID_SIZE - sizeof(DWORD))){
  2241. //
  2242. // This is a bogus return value
  2243. //
  2244. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2245. goto Cleanup;
  2246. }
  2247. RtlCopySid(sizeof(Buffer), Sid, DomainSid);
  2248. if ( Rid != LSA_UNKNOWN_ID ) {
  2249. ULONG RidAuthority;
  2250. RidAuthority= (*(RtlSubAuthorityCountSid(Sid)))++;
  2251. *RtlSubAuthoritySid(Sid,RidAuthority) = Rid;
  2252. }
  2253. SidLength = RtlLengthSid(Sid);
  2254. RtlCopySid(SidLength, (PSID)NextSid, Sid);
  2255. ReturnedSidsEx2.Sids[i].Sid = (PSID)NextSid;
  2256. NextSid += RtlLengthSid(Sid);
  2257. } else {
  2258. //
  2259. // Either no domain SID, or account is unknown
  2260. //
  2261. ReturnedSidsEx2.Sids[i].Sid = NULL;
  2262. }
  2263. }
  2264. }
  2265. *Sids = (PLSA_TRANSLATED_SID_EX2) ReturnedSidsEx2.Sids;
  2266. ReturnedSidsEx2.Sids = NULL;
  2267. Cleanup:
  2268. if ( (STATUS_INVALID_NETWORK_RESPONSE == Status)
  2269. || (STATUS_NO_MEMORY == Status) ) {
  2270. if ( *ReferencedDomains ) {
  2271. MIDL_user_free( *ReferencedDomains );
  2272. *ReferencedDomains = NULL;
  2273. }
  2274. *Sids = NULL;
  2275. }
  2276. if ( ReturnedSids.Sids ) {
  2277. MIDL_user_free( ReturnedSids.Sids );
  2278. }
  2279. if ( ReturnedSidsEx.Sids ) {
  2280. MIDL_user_free( ReturnedSidsEx.Sids );
  2281. }
  2282. if ( ReturnedSidsEx2.Sids ) {
  2283. MIDL_user_free( ReturnedSidsEx2.Sids );
  2284. }
  2285. return(Status);
  2286. }
  2287. NTSTATUS
  2288. LsaLookupSids(
  2289. IN LSA_HANDLE PolicyHandle,
  2290. IN ULONG Count,
  2291. IN PSID *Sids,
  2292. OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
  2293. OUT PLSA_TRANSLATED_NAME *Names
  2294. )
  2295. /*++
  2296. Routine Description:
  2297. The LsaLookupSids API attempts to find names corresponding to Sids.
  2298. If a name can not be mapped to a Sid, the Sid is converted to character
  2299. form. The caller must have POLICY_LOOKUP_NAMES access to the Policy
  2300. object.
  2301. WARNING: This routine allocates memory for its output. The caller is
  2302. responsible for freeing this memory after use. See description of the
  2303. Names parameter.
  2304. Arguments:
  2305. PolicyHandle - Handle from an LsaOpenPolicy call.
  2306. Count - Specifies the number of Sids to be translated.
  2307. Sids - Pointer to an array of Count pointers to Sids to be mapped
  2308. to names. The Sids may be well_known SIDs, SIDs of User accounts
  2309. Group Accounts, Alias accounts, or Domains.
  2310. ReferencedDomains - Receives a pointer to a structure describing the
  2311. domains used for the translation. The entries in this structure
  2312. are referenced by the strutcure returned via the Names parameter.
  2313. Unlike the Names paraemeter, which contains an array entry
  2314. for (each translated name, this strutcure will only contain
  2315. component for each domain utilized in the translation.
  2316. When this information is no longer needed, it must be released
  2317. by passing the returned pointer to LsaFreeMemory().
  2318. Names - Receives a pointer to array records describing each translated
  2319. name. The nth entry in this array provides a translation for
  2320. the nth entry in the Sids parameter.
  2321. All of the returned names will be isolated names or NULL strings
  2322. (domain names are returned as NULL strings). If the caller needs
  2323. composite names, they can be generated by prepending the
  2324. isolated name with the domain name and a backslash. For example,
  2325. if (the name Sally is returned, and it is from the domain Manufact,
  2326. then the composite name would be "Manufact" + "\" + "Sally" or
  2327. "Manufact\Sally".
  2328. When this information is no longer needed, it must be released
  2329. by passing the returned pointer to LsaFreeMemory().
  2330. If a Sid is not translatable, then the following will occur:
  2331. 1) If the SID's domain is known, then a reference domain record
  2332. will be generated with the domain's name. In this case, the
  2333. name returned via the Names parameter is a Unicode representation
  2334. of the relative ID of the account, such as "(314)" or the null
  2335. string, if the Sid is that of a domain. So, you might end up
  2336. with a resultant name of "Manufact\(314) for the example with
  2337. Sally above, if Sally's relative id is 314.
  2338. 2) If not even the SID's domain could be located, then a full
  2339. Unicode representation of the SID is generated and no domain
  2340. record is referenced. In this case, the returned string might
  2341. be something like: "(S-1-672194-21-314)".
  2342. When this information is no longer needed, it must be released
  2343. by passing the returned pointer to LsaFreeMemory().
  2344. Return Values:
  2345. NTSTATUS - Standard Nt Result Code
  2346. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2347. to complete the operation.
  2348. STATUS_SOME_NOT_MAPPED - Some or all of the names provided could not be
  2349. mapped. This is a warning only.
  2350. Rest TBS
  2351. --*/
  2352. {
  2353. NTSTATUS Status = STATUS_SUCCESS;
  2354. ULONG MappedCount = 0;
  2355. PLSA_TRANSLATED_NAME_EX NamesEx = NULL;
  2356. ULONG i;
  2357. if ( NULL == Names ) {
  2358. return STATUS_INVALID_PARAMETER;
  2359. }
  2360. Status = LsaICLookupSids(
  2361. PolicyHandle,
  2362. Count,
  2363. Sids,
  2364. ReferencedDomains,
  2365. &NamesEx,
  2366. LsapLookupWksta,
  2367. 0,
  2368. &MappedCount,
  2369. NULL
  2370. );
  2371. if ( NamesEx != NULL ) {
  2372. //
  2373. // Some names were returned -- map the new structure to the old one
  2374. // and keep allocations in the same block of memory so existing clients
  2375. // won't have memory leaks
  2376. //
  2377. ULONG SizeNeeded = 0;
  2378. PBYTE NextBuffer;
  2379. PLSA_TRANSLATED_NAME TempNames = NULL;
  2380. SizeNeeded = Count * sizeof( LSA_TRANSLATED_NAME );
  2381. for ( i = 0; i < Count; i++ ) {
  2382. SizeNeeded += NamesEx[i].Name.MaximumLength;
  2383. }
  2384. TempNames = MIDL_user_allocate( SizeNeeded );
  2385. if ( TempNames ) {
  2386. RtlZeroMemory( TempNames, SizeNeeded );
  2387. NextBuffer = ((PBYTE)TempNames) + (Count * sizeof( LSA_TRANSLATED_NAME ));
  2388. for ( i = 0; i < Count; i++ ) {
  2389. TempNames[i].Use = NamesEx[i].Use;
  2390. TempNames[i].DomainIndex = NamesEx[i].DomainIndex;
  2391. TempNames[i].Name = NamesEx[i].Name;
  2392. RtlCopyMemory( NextBuffer, NamesEx[i].Name.Buffer, NamesEx[i].Name.Length );
  2393. TempNames[i].Name.Buffer = (WCHAR*)NextBuffer;
  2394. NextBuffer += NamesEx[i].Name.MaximumLength;
  2395. }
  2396. } else {
  2397. //
  2398. // The call succeeded but the extra allocation didn't
  2399. //
  2400. if ( *ReferencedDomains ) {
  2401. MIDL_user_free( *ReferencedDomains );
  2402. *ReferencedDomains = NULL;
  2403. }
  2404. Status = STATUS_INSUFFICIENT_RESOURCES;
  2405. }
  2406. //
  2407. // Return the results (or NULL)
  2408. //
  2409. *Names = TempNames;
  2410. MIDL_user_free( NamesEx );
  2411. } else {
  2412. *Names = NULL;
  2413. }
  2414. return(Status);
  2415. }
  2416. NTSTATUS
  2417. LsapVerifyReturnedNames(
  2418. IN LSAPR_TRANSLATED_NAMES_EX *ReturnedNames,
  2419. IN ULONG Count,
  2420. IN PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains
  2421. )
  2422. /*++
  2423. Routine Description:
  2424. This routine validates the returned names structure from the server.
  2425. There are some checks that RPC can't make that the client assumes are
  2426. true and will AV otherwise.
  2427. Arguments:
  2428. Count -- the number of elements the client asked the server to resolve
  2429. ReturnedNames -- the structure holding the data returned from the server
  2430. ReferencedDomains -- the array of domains that ReturnedNames points into
  2431. (also returned from the server)
  2432. Return Values:
  2433. STATUS_SUCCESS
  2434. STATUS_INVALID_NETWORK_RESPONSE
  2435. --*/
  2436. {
  2437. NTSTATUS Status = STATUS_SUCCESS;
  2438. ULONG i;
  2439. if (ReturnedNames->Entries != Count) {
  2440. //
  2441. // Entries returned should always equal the number of items asked for
  2442. //
  2443. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2444. goto Finish;
  2445. }
  2446. if ( Count > 0
  2447. && (ReturnedNames->Names == NULL)) {
  2448. //
  2449. // If there are entries, then there must be an array
  2450. //
  2451. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2452. goto Finish;
  2453. }
  2454. for (i = 0; i < Count; i++) {
  2455. //
  2456. // All resolved names must have a valid domain index
  2457. //
  2458. if ( (ReturnedNames->Names[i].Use != SidTypeInvalid) &&
  2459. (ReturnedNames->Names[i].Use != SidTypeDeletedAccount) &&
  2460. (ReturnedNames->Names[i].Use != SidTypeUnknown) ) {
  2461. if (NULL == ReferencedDomains) {
  2462. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2463. goto Finish;
  2464. } else if ( (ReturnedNames->Names[i].DomainIndex == LSA_UNKNOWN_INDEX)
  2465. || (ReturnedNames->Names[i].DomainIndex < 0)
  2466. || ((ULONG)ReturnedNames->Names[i].DomainIndex >= ReferencedDomains->Entries)) {
  2467. ASSERT(FALSE && "Invalid network response!");
  2468. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2469. goto Finish;
  2470. }
  2471. }
  2472. }
  2473. Finish:
  2474. return Status;
  2475. }
  2476. NTSTATUS
  2477. LsaICLookupSids(
  2478. IN LSA_HANDLE PolicyHandle,
  2479. IN ULONG Count,
  2480. IN PSID *Sids,
  2481. OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
  2482. IN OUT PLSA_TRANSLATED_NAME_EX *Names,
  2483. IN LSAP_LOOKUP_LEVEL LookupLevel,
  2484. IN ULONG Flags,
  2485. IN OUT PULONG MappedCount,
  2486. OUT ULONG *ServerRevision OPTIONAL
  2487. )
  2488. /*++
  2489. Routine Description:
  2490. This function is the internal client side version of the LsaLookupSids
  2491. API. It is called both from the client side of the Lsa and also
  2492. the server side of the LSA (when calling out to another LSA). The
  2493. function is identical to the LsaLookupSids API except that there is an
  2494. additional parameter, the LookupLevel parameter.
  2495. The LsaLookupSids API attempts to find names corresponding to Sids.
  2496. If a name can not be mapped to a Sid, the Sid is converted to character
  2497. form. The caller must have POLICY_LOOKUP_NAMES access to the Policy
  2498. object.
  2499. WARNING: This routine allocates memory for its output. The caller is
  2500. responsible for freeing this memory after use. See description of the
  2501. Names parameter.
  2502. Arguments:
  2503. PolicyHandle - Handle from an LsaOpenPolicy call.
  2504. Count - Specifies the number of Sids to be translated.
  2505. Sids - Pointer to an array of Count pointers to Sids to be mapped
  2506. to names. The Sids may be well_known SIDs, SIDs of User accounts
  2507. Group Accounts, Alias accounts, or Domains.
  2508. ReferencedDomains - Receives a pointer to a structure describing the
  2509. domains used for the translation. The entries in this structure
  2510. are referenced by the strutcure returned via the Names parameter.
  2511. Unlike the Names paraemeter, which contains an array entry
  2512. for (each translated name, this strutcure will only contain
  2513. component for each domain utilized in the translation.
  2514. When this information is no longer needed, it must be released
  2515. by passing the returned pointer to LsaFreeMemory().
  2516. Names - Receives a pointer to array records describing each translated
  2517. name. The nth entry in this array provides a translation for
  2518. the nth entry in the Sids parameter.
  2519. All of the retruned names will be isolated names or NULL strings
  2520. (domain names are returned as NULL strings). If the caller needs
  2521. composite names, they can be generated by prepending the
  2522. isolated name with the domain name and a backslash. For example,
  2523. if (the name Sally is returned, and it is from the domain Manufact,
  2524. then the composite name would be "Manufact" + "\" + "Sally" or
  2525. "Manufact\Sally".
  2526. When this information is no longer needed, it must be released
  2527. by passing the returned pointer to LsaFreeMemory().
  2528. If a Sid is not translatable, then the following will occur:
  2529. 1) If the SID's domain is known, then a reference domain record
  2530. will be generated with the domain's name. In this case, the
  2531. name returned via the Names parameter is a Unicode representation
  2532. of the relative ID of the account, such as "(314)" or the null
  2533. string, if the Sid is that of a domain. So, you might end up
  2534. with a resultant name of "Manufact\(314) for the example with
  2535. Sally above, if Sally's relative id is 314.
  2536. 2) If not even the SID's domain could be located, then a full
  2537. Unicode representation of the SID is generated and no domain
  2538. record is referenced. In this case, the returned string might
  2539. be something like: "(S-1-672194-21-314)".
  2540. When this information is no longer needed, it must be released
  2541. by passing the returned pointer to LsaFreeMemory().
  2542. LookupLevel - Specifies the Level of Lookup to be performed on the
  2543. target machine. Values of this field are are follows:
  2544. LsapLookupWksta - First Level Lookup performed on a workstation
  2545. normally configured for Windows-Nt. The lookup searches the
  2546. Well-Known Sids, and the Built-in Domain and Account Domain
  2547. in the local SAM Database. If not all Sids are
  2548. identified, performs a "handoff" of a Second level Lookup to the
  2549. LSA running on a Controller for the workstation's Primary Domain
  2550. (if any).
  2551. LsapLookupPDC - Second Level Lookup performed on a Primary Domain
  2552. Controller. The lookup searches the Account Domain of the
  2553. SAM Database on the controller. If not all Sids are
  2554. found, the Trusted Domain List (TDL) is obtained from the
  2555. LSA's Policy Database and Third Level lookups are performed
  2556. via "handoff" to each Trusted Domain in the List.
  2557. LsapLookupTDL - Third Level Lookup performed on a controller
  2558. for a Trusted Domain. The lookup searches the Account Domain of
  2559. the SAM Database on the controller only.
  2560. Flags:
  2561. LSAIC_NT4_TARGET -- target server is known to be NT4
  2562. LSAIC_WIN2K_TARGET -- target server is known to be Win2k
  2563. MappedCount - Pointer to location that contains a count of the Sids
  2564. mapped so far. On exit, this count will be updated.
  2565. Return Values:
  2566. NTSTATUS - Standard Nt Result Code
  2567. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2568. to complete the operation.
  2569. STATUS_SOME_NOT_MAPPED - Some or all of the names provided could not be
  2570. mapped. This is a warning only.
  2571. STATUS_TOO_MANY_SIDS - Too many Sids have been specified.
  2572. --*/
  2573. {
  2574. NTSTATUS Status;
  2575. BOOLEAN NamesArraySpecified = FALSE;
  2576. LSAPR_SID_ENUM_BUFFER SidEnumBuffer;
  2577. LSAPR_TRANSLATED_NAMES_EX ReturnedNames = {0, NULL};
  2578. LSAPR_TRANSLATED_NAMES DownlevelNames = {0, NULL};
  2579. ULONG StartingRevision = 2;
  2580. if ( ServerRevision ) {
  2581. // The latest client's will prefer the latest servers
  2582. *ServerRevision = LSA_CLIENT_LATEST;
  2583. }
  2584. //
  2585. // Verify that the Count is positive and not too high
  2586. //
  2587. if (Count == 0) {
  2588. return STATUS_INVALID_PARAMETER;
  2589. }
  2590. if (Count > LSAP_DB_TRIAL_MAXIMUM_SID_COUNT) {
  2591. return STATUS_TOO_MANY_SIDS;
  2592. }
  2593. SidEnumBuffer.Entries = Count;
  2594. SidEnumBuffer.SidInfo = (PLSAPR_SID_INFORMATION) Sids;
  2595. //
  2596. // If this is a Workstation-Level lookup, the Names and
  2597. // ReferencedDomain Lists have not been created. Since these
  2598. // are input parameters in the general case, we need to set them
  2599. // to NULL.
  2600. //
  2601. if (LookupLevel == LsapLookupWksta) {
  2602. *ReferencedDomains = NULL;
  2603. *Names = NULL;
  2604. }
  2605. //
  2606. // There may already be a name translation array in cases where
  2607. // we are called internally (i.e. with lookup level higher than
  2608. // LsapLookupWksta). Initialize the ReturnedNames structure
  2609. // accordingly.
  2610. //
  2611. ReturnedNames.Entries = 0;
  2612. ReturnedNames.Names = NULL;
  2613. if (*Names != NULL) {
  2614. ReturnedNames.Entries = Count;
  2615. ReturnedNames.Names = (PLSAPR_TRANSLATED_NAME_EX) *Names;
  2616. NamesArraySpecified = TRUE;
  2617. }
  2618. //
  2619. // Adjust the StartingRevision
  2620. //
  2621. StartingRevision = 2;
  2622. if (Flags & LSAIC_NT4_TARGET) {
  2623. StartingRevision = 1;
  2624. }
  2625. //
  2626. // Lookup Sids on the Server..
  2627. //
  2628. switch (StartingRevision) {
  2629. case 2:
  2630. RpcTryExcept {
  2631. Status = LsarLookupSids2(
  2632. (LSAPR_HANDLE) PolicyHandle,
  2633. &SidEnumBuffer,
  2634. (PLSAPR_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  2635. &ReturnedNames,
  2636. LookupLevel,
  2637. MappedCount,
  2638. 0,
  2639. LSA_CLIENT_NT5
  2640. );
  2641. //
  2642. // Return the array of translation to name info or NULL.
  2643. //
  2644. // NOTE: The array of name translations is allocated by the called
  2645. // client stub as a single block via MIDL_user_allocate, because
  2646. // Information is allocated all-nodes. We can therefore pass back the pointer
  2647. // directly to the client, who will be able to free the memory after
  2648. // use via LsaFreeMemory() [which makes a MIDL_user_free call].
  2649. //
  2650. *Names = (PLSA_TRANSLATED_NAME_EX) ReturnedNames.Names;
  2651. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2652. //
  2653. // If memory was allocated for the name translation array,
  2654. // free it.
  2655. //
  2656. if ((!NamesArraySpecified) && ReturnedNames.Names != NULL) {
  2657. MIDL_user_free( ReturnedNames.Names );
  2658. ReturnedNames.Names = NULL;
  2659. }
  2660. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2661. } RpcEndExcept;
  2662. if ( (Status == RPC_NT_UNKNOWN_IF) ||
  2663. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE) ) {
  2664. //
  2665. // Continue on to next block;
  2666. //
  2667. NOTHING;
  2668. } else {
  2669. //
  2670. // The interface was supported; leave
  2671. //
  2672. break;
  2673. }
  2674. case 1:
  2675. if ( ServerRevision ) {
  2676. // This is pre nt5
  2677. *ServerRevision = LSA_CLIENT_PRE_NT5;
  2678. }
  2679. RpcTryExcept {
  2680. //
  2681. // Ok, lower down to the previous version
  2682. //
  2683. Status = LsarLookupSids(
  2684. (LSAPR_HANDLE) PolicyHandle,
  2685. &SidEnumBuffer,
  2686. (PLSAPR_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  2687. &DownlevelNames,
  2688. LookupLevel,
  2689. MappedCount
  2690. );
  2691. if ( DownlevelNames.Names != NULL ) {
  2692. ULONG i;
  2693. ULONG SizeNeeded = 0;
  2694. PBYTE NextBuffer;
  2695. //
  2696. // Package the results into a new structure. Note all memory
  2697. // must be in the same block as LSA_TRANSLATED_NAMES and
  2698. // LSA_TRANSLATED_NAMES_EX are NOT allocate all nodes
  2699. //
  2700. SizeNeeded = DownlevelNames.Entries * sizeof( LSA_TRANSLATED_NAME_EX );
  2701. for ( i = 0; i < DownlevelNames.Entries; i++ ) {
  2702. SizeNeeded += DownlevelNames.Names[i].Name.MaximumLength;
  2703. }
  2704. if ( !NamesArraySpecified ) {
  2705. ReturnedNames.Names = MIDL_user_allocate( SizeNeeded );
  2706. if ( !ReturnedNames.Names ) {
  2707. Status = STATUS_INSUFFICIENT_RESOURCES;
  2708. _leave;
  2709. }
  2710. RtlZeroMemory( ReturnedNames.Names, SizeNeeded );
  2711. ReturnedNames.Entries = Count;
  2712. }
  2713. NextBuffer = ((PBYTE)ReturnedNames.Names) + (Count * sizeof( LSA_TRANSLATED_NAME_EX ));
  2714. ReturnedNames.Entries = DownlevelNames.Entries;
  2715. for ( i = 0; i < DownlevelNames.Entries; i++ ) {
  2716. ReturnedNames.Names[i].Use = DownlevelNames.Names[i].Use;
  2717. ReturnedNames.Names[i].Name = DownlevelNames.Names[i].Name;
  2718. RtlCopyMemory( NextBuffer, DownlevelNames.Names[i].Name.Buffer, DownlevelNames.Names[i].Name.Length );
  2719. ReturnedNames.Names[i].Name.Buffer = (WCHAR*)NextBuffer;
  2720. ReturnedNames.Names[i].DomainIndex = DownlevelNames.Names[i].DomainIndex;
  2721. NextBuffer += DownlevelNames.Names[i].Name.MaximumLength;
  2722. }
  2723. }
  2724. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2725. if ( DownlevelNames.Names ) {
  2726. MIDL_user_free( DownlevelNames.Names );
  2727. DownlevelNames.Names = NULL;
  2728. }
  2729. if ((!NamesArraySpecified) && ReturnedNames.Names != NULL) {
  2730. MIDL_user_free( ReturnedNames.Names );
  2731. ReturnedNames.Names = NULL;
  2732. }
  2733. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2734. } RpcEndExcept;
  2735. break;
  2736. default:
  2737. ASSERT(FALSE && "Programming error -- wrong revision");
  2738. Status = STATUS_INVALID_PARAMETER;
  2739. }
  2740. //
  2741. // Return the array of translation to name info or NULL.
  2742. //
  2743. // NOTE: The array of name translations is allocated by the called
  2744. // client stub as a single block via MIDL_user_allocate, because
  2745. // Information is allocated all-nodes. We can therefore pass back the pointer
  2746. // directly to the client, who will be able to free the memory after
  2747. // use via LsaFreeMemory() [which makes a MIDL_user_free call].
  2748. //
  2749. *Names = (PLSA_TRANSLATED_NAME_EX) ReturnedNames.Names;
  2750. //
  2751. // This memory, if allocated is never returned to the caller, so free
  2752. //
  2753. if ( DownlevelNames.Names ) {
  2754. MIDL_user_free( DownlevelNames.Names );
  2755. }
  2756. //
  2757. // Prevent against network hacks
  2758. //
  2759. if (NT_SUCCESS(Status)) {
  2760. Status = LsapVerifyReturnedNames(&ReturnedNames,
  2761. Count,
  2762. *ReferencedDomains);
  2763. if (!NT_SUCCESS(Status)) {
  2764. if ( (!NamesArraySpecified) && ReturnedNames.Names ) {
  2765. MIDL_user_free( ReturnedNames.Names );
  2766. }
  2767. if ( *ReferencedDomains ) {
  2768. MIDL_user_free( *ReferencedDomains );
  2769. *ReferencedDomains = NULL;
  2770. }
  2771. }
  2772. }
  2773. return(Status);
  2774. }
  2775. NTSTATUS
  2776. LsaOpenAccount(
  2777. IN LSA_HANDLE PolicyHandle,
  2778. IN PSID AccountSid,
  2779. IN ACCESS_MASK DesiredAccess,
  2780. OUT PLSA_HANDLE AccountHandle
  2781. )
  2782. /*++
  2783. Routine Description:
  2784. The LsaOpenAccount API opens an account object in the Lsa Database of the
  2785. target system. An account must be opened before any operation can be
  2786. performed, including deletion of the account. A handle to the account
  2787. object is returned for use on subsequent API calls that access the
  2788. account. Before calling this API, the caller must have connected to
  2789. the target system's LSA and opened the Policy object by means
  2790. of a preceding call to LsaOpenPolicy.
  2791. Arguments:
  2792. PolicyHandle - Handle from an LsaOpenLsa call.
  2793. AccountSid - Pointer to the account's Sid.
  2794. DesiredAccess - This is an access mask indicating accesses being
  2795. requested for the LSA Subsystem's LSA Database. These access types
  2796. are reconciled with the Discretionary Access Control List of the
  2797. target Account object to determine whether the accesses will be
  2798. granted or denied.
  2799. AccountHandle - Pointer to location in which a handle to the opened
  2800. account object will be returned if the call succeeds.
  2801. Return Values:
  2802. NTSTATUS - Standard Nt Result Code
  2803. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2804. to complete the operation.
  2805. STATUS_ACCOUNT_DOES_NOT_EXIST - There is no account object in the
  2806. target system's LSA Database having the specified AccountSid.
  2807. --*/
  2808. {
  2809. NTSTATUS Status;
  2810. RpcTryExcept {
  2811. Status = LsarOpenAccount(
  2812. (LSAPR_HANDLE) PolicyHandle,
  2813. (PLSAPR_SID) AccountSid,
  2814. DesiredAccess,
  2815. (PLSAPR_HANDLE) AccountHandle
  2816. );
  2817. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2818. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2819. } RpcEndExcept;
  2820. return Status;
  2821. }
  2822. NTSTATUS
  2823. LsaEnumeratePrivilegesOfAccount(
  2824. IN LSA_HANDLE AccountHandle,
  2825. OUT PPRIVILEGE_SET *Privileges
  2826. )
  2827. /*++
  2828. Routine Description:
  2829. The LsaEnumeratePrivilegesOfAccount API obtains information which
  2830. describes the privileges assigned to an account. This call requires
  2831. LSA_ACCOUNT_VIEW access to the account object.
  2832. Arguments:
  2833. AccountHandle - The handle to the open account object whose privilege
  2834. information is to be obtained. This handle will have been returned
  2835. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  2836. Privileges - Receives a pointer to a buffer containing the Privilege
  2837. Set. The Privilege Set is an array of structures, one for each
  2838. privilege. Each structure contains the LUID of the privilege and
  2839. a mask of the privilege's attributes.
  2840. Return Values:
  2841. NTSTATUS - Standard Nt Result Code
  2842. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2843. to complete the operation.
  2844. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  2845. --*/
  2846. {
  2847. NTSTATUS Status;
  2848. RpcTryExcept {
  2849. *Privileges = NULL;
  2850. Status = LsarEnumeratePrivilegesAccount(
  2851. (LSAPR_HANDLE) AccountHandle,
  2852. (PLSAPR_PRIVILEGE_SET *) Privileges
  2853. );
  2854. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2855. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2856. } RpcEndExcept;
  2857. return Status;
  2858. }
  2859. NTSTATUS
  2860. LsaAddPrivilegesToAccount(
  2861. IN LSA_HANDLE AccountHandle,
  2862. IN PPRIVILEGE_SET Privileges
  2863. )
  2864. /*++
  2865. Routine Description:
  2866. The LsaAddPrivilegesToAccount API adds privileges and their attributes
  2867. to an account object. If any provided privilege is already assigned
  2868. to the account object, the attributes of that privilege are replaced
  2869. by the newly rpovided values. This API call requires
  2870. LSA_ACCOUNT_ADJUST_PRIVILEGES access to the account object.
  2871. Arguments:
  2872. AccountHandle - The handle to the open account object to which
  2873. privileges are to be added. This handle will have been returned
  2874. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  2875. Privileges - Points to a set of privileges (and their attributes) to
  2876. be assigned to the account.
  2877. Return Values:
  2878. NTSTATUS - Standard Nt Result Code
  2879. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2880. to complete the operation.
  2881. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  2882. --*/
  2883. {
  2884. NTSTATUS Status;
  2885. RpcTryExcept {
  2886. Status = LsarAddPrivilegesToAccount(
  2887. (LSAPR_HANDLE) AccountHandle,
  2888. (PLSAPR_PRIVILEGE_SET) Privileges
  2889. );
  2890. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2891. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2892. } RpcEndExcept;
  2893. return Status;
  2894. }
  2895. NTSTATUS
  2896. LsaRemovePrivilegesFromAccount(
  2897. IN LSA_HANDLE AccountHandle,
  2898. IN BOOLEAN AllPrivileges,
  2899. IN OPTIONAL PPRIVILEGE_SET Privileges
  2900. )
  2901. /*++
  2902. Routine Description:
  2903. The LsaRemovePrivilegesFromAccount API removes privileges from an
  2904. account object. This API call requires LSA_ACCOUNT_ADJUST_PRIVILEGES
  2905. access to the account object. Note that if all privileges are removed
  2906. from the account object, the account object remains in existence until
  2907. deleted explicitly via a call to the LsaDelete API.
  2908. Arguments:
  2909. AccountHandle - The handle to the open account object to which
  2910. privileges are to be removed. This handle will have been returned
  2911. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  2912. AllPrivileges - If TRUE, then all privileges are to be removed from
  2913. the account. In this case, the Privileges parameter must be
  2914. specified as NULL. If FALSE, the Privileges parameter specifies
  2915. the privileges to be removed, and must be non NULL.
  2916. Privileges - Optionally points to a set of privileges (and their
  2917. attributes) to be removed from the account object. The attributes
  2918. fields of this structure are ignored. This parameter must
  2919. be specified as non-NULL if and only if AllPrivileges is set to
  2920. FALSE.
  2921. Return Values:
  2922. NTSTATUS - Standard Nt Result Code
  2923. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  2924. to complete the operation.
  2925. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  2926. STATUS_INVALID_PARAMETER - The optional Privileges paraemter was
  2927. specified as NULL and AllPrivileges was set to FALSE.
  2928. --*/
  2929. {
  2930. NTSTATUS Status;
  2931. RpcTryExcept {
  2932. Status = LsarRemovePrivilegesFromAccount(
  2933. (LSAPR_HANDLE) AccountHandle,
  2934. AllPrivileges,
  2935. (PLSAPR_PRIVILEGE_SET) Privileges
  2936. );
  2937. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2938. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2939. } RpcEndExcept;
  2940. return Status;
  2941. }
  2942. NTSTATUS
  2943. LsaGetQuotasForAccount(
  2944. IN LSA_HANDLE AccountHandle,
  2945. OUT PQUOTA_LIMITS QuotaLimits
  2946. )
  2947. /*++
  2948. Routine Description:
  2949. The LsaGetQuotasForAccount API obtains the quota limits for pageable and
  2950. non-pageable memory (in Kilobytes) and the maximum execution time (in
  2951. seconds) for any session logged on to the account specified by
  2952. AccountHandle. For each quota and explicit value is returned. This
  2953. call requires LSA_ACCOUNT_VIEW access to the account object.
  2954. Arguments:
  2955. AccountHandle - The handle to the open account object whose quotas
  2956. are to be obtained. This handle will have been returned
  2957. from a prior LsaOpenAccount or LsaCreateAccountInLsa API call.
  2958. QuotaLimits - Pointer to structure in which the system resource
  2959. quota limits applicable to each session logged on to this account
  2960. will be returned. Note that all quotas, including those specified
  2961. as being the system default values, are returned as actual values.
  2962. Return Values:
  2963. NTSTATUS - Standard Nt Result Code
  2964. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  2965. --*/
  2966. {
  2967. NTSTATUS Status;
  2968. RpcTryExcept{
  2969. Status = LsarGetQuotasForAccount(
  2970. (LSAPR_HANDLE) AccountHandle,
  2971. QuotaLimits
  2972. );
  2973. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2974. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  2975. } RpcEndExcept;
  2976. return Status;
  2977. }
  2978. NTSTATUS
  2979. LsaSetQuotasForAccount(
  2980. IN LSA_HANDLE AccountHandle,
  2981. IN PQUOTA_LIMITS QuotaLimits
  2982. )
  2983. /*++
  2984. Routine Description:
  2985. The LsaSetQuotasForAccount API sets the quota limits for pageable and
  2986. non-pageable memory (in Kilobytes) and the maximum execution time (in
  2987. seconds) for any session logged on to the account specified by
  2988. AccountHandle. For each quota an explicit value or the system default
  2989. may be specified. This call requires LSA_ACCOUNT_ADJUST_QUOTAS
  2990. access to the account object.
  2991. Arguments:
  2992. AccountHandle - The handle to the open account object whose quotas
  2993. are to be set. This handle will have been returned from a prior
  2994. LsaOpenAccount or LsaCreateAccountInLsa API call.
  2995. QuotaLimits - Pointer to structure containing the system resource
  2996. quota limits applicable to each session logged on to this account.
  2997. A zero value specified in any field indicates that the current
  2998. System Default Quota Limit is to be applied.
  2999. Return Values:
  3000. NTSTATUS - Standard Nt Result Code
  3001. STATUS_INVALID_HANDLE - The specified AccountHandle is not valid.
  3002. --*/
  3003. {
  3004. NTSTATUS Status;
  3005. RpcTryExcept {
  3006. Status = LsarSetQuotasForAccount(
  3007. (LSAPR_HANDLE) AccountHandle,
  3008. QuotaLimits
  3009. );
  3010. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3011. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3012. } RpcEndExcept;
  3013. return Status;
  3014. }
  3015. NTSTATUS
  3016. LsaGetSystemAccessAccount(
  3017. IN LSA_HANDLE AccountHandle,
  3018. OUT PULONG SystemAccess
  3019. )
  3020. /*++
  3021. Routine Description:
  3022. The LsaGetSystemAccessAccount() service returns the System Access
  3023. account flags for an Account object.
  3024. Arguments:
  3025. AccountHandle - The handle to the Account object whose system access
  3026. flags are to be read. This handle will have been returned
  3027. from a preceding LsaOpenAccount() or LsaCreateAccount() call
  3028. an must be open for ACCOUNT_VIEW access.
  3029. SystemAccess - Points to location that will receive the system access
  3030. flags for the account.
  3031. Return Values:
  3032. NTSTATUS - Standard Nt Result Code
  3033. STATUS_SUCCESS - The call was successful.
  3034. STATUS_ACCESS_DENIED - The AccountHandle does not specify
  3035. ACCOUNT_VIEW access.
  3036. STATUS_INVALID_HANDLE - The specified AccountHandle is invalid.
  3037. --*/
  3038. {
  3039. NTSTATUS Status;
  3040. //
  3041. // Avoid RPC stub code raising exception on NULL handle so that
  3042. // we can return the error code STATUS_INVALID_HANDLE in this case
  3043. // too.
  3044. //
  3045. if (!ARGUMENT_PRESENT(AccountHandle)) {
  3046. return(STATUS_INVALID_HANDLE);
  3047. }
  3048. RpcTryExcept{
  3049. Status = LsarGetSystemAccessAccount(
  3050. (LSAPR_HANDLE) AccountHandle,
  3051. SystemAccess
  3052. );
  3053. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3054. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3055. } RpcEndExcept;
  3056. return(Status);
  3057. }
  3058. NTSTATUS
  3059. LsaSetSystemAccessAccount(
  3060. IN LSA_HANDLE AccountHandle,
  3061. IN ULONG SystemAccess
  3062. )
  3063. /*++
  3064. Routine Description:
  3065. The LsaSetSystemAccessAccount() service sets the System Access
  3066. account flags for an Account object.
  3067. Arguments:
  3068. AccountHandle - The handle to the Account object whose system access
  3069. flags are to be read. This handle will have been returned
  3070. from a preceding LsaOpenAccount() or LsaCreateAccount() call
  3071. an must be open for ACCOUNT_ADJUST_SYSTEM_ACCESS access.
  3072. SystemAccess - A mask of the system access flags to assign to the
  3073. Account object. The valid access flags include:
  3074. POLICY_MODE_INTERACTIVE - Account can be accessed interactively
  3075. POLICY_MODE_NETWORK - Account can be accessed remotely
  3076. POLICY_MODE_SERVICE - TBS
  3077. Return Values:
  3078. NTSTATUS - Standard Nt Result Code
  3079. STATUS_SUCCESS - The call was successful.
  3080. STATUS_ACCESS_DENIED - The AccountHandle does not specify
  3081. ACCOUNT_VIEW access.
  3082. STATUS_INVALID_HANDLE - The specified AccountHandle is invalid.
  3083. STATUS_INVALID_PARAMETER - The specified Access Flags are invalid.
  3084. --*/
  3085. {
  3086. NTSTATUS Status;
  3087. //
  3088. // Avoid RPC stub code raising exception on NULL handle so that
  3089. // we can return the error code STATUS_INVALID_HANDLE in this case
  3090. // too.
  3091. //
  3092. if (!ARGUMENT_PRESENT(AccountHandle)) {
  3093. return(STATUS_INVALID_HANDLE);
  3094. }
  3095. RpcTryExcept {
  3096. Status = LsarSetSystemAccessAccount(
  3097. (LSAPR_HANDLE) AccountHandle,
  3098. SystemAccess
  3099. );
  3100. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3101. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3102. } RpcEndExcept;
  3103. return(Status);
  3104. }
  3105. NTSTATUS
  3106. LsaFreeMemory(
  3107. IN PVOID Buffer
  3108. )
  3109. /*++
  3110. Routine Description:
  3111. Some LSA services that return a potentially large amount of memory,
  3112. such as an enumeration might, allocate the buffer in which the data
  3113. is returned. This function is used to free those buffers when they
  3114. are no longer needed.
  3115. Parameters:
  3116. Buffer - Pointer to the buffer to be freed. This buffer must
  3117. have been allocated by a previous LSA service call.
  3118. Return Values:
  3119. STATUS_SUCCESS - normal, successful completion.
  3120. --*/
  3121. {
  3122. NTSTATUS Status = STATUS_SUCCESS;
  3123. MIDL_user_free( Buffer );
  3124. return Status;
  3125. }
  3126. NTSTATUS
  3127. LsaOpenSecret(
  3128. IN LSA_HANDLE PolicyHandle,
  3129. IN PUNICODE_STRING SecretName,
  3130. IN ACCESS_MASK DesiredAccess,
  3131. OUT PLSA_HANDLE SecretHandle
  3132. )
  3133. /*++
  3134. Routine Description:
  3135. The LsaOpenSecret API opens a Secret Object within the LSA Database.
  3136. A handle is returned which must be used to perform operations on the
  3137. secret object.
  3138. Arguments:
  3139. PolicyHandle - Handle from an LsaOpenLsa call.
  3140. SecretName - Pointer to a Unicode String structure that references the
  3141. name of the Secret object to be opened.
  3142. DesiredAccess - This is an access mask indicating accesses being
  3143. requested for the secret object being opened. These access types
  3144. are reconciled with the Discretionary Access Control List of the
  3145. target secret object to determine whether the accesses will be
  3146. granted or denied.
  3147. SecretHandle - Pointer to location that will receive a handle to the
  3148. newly opened Secret object.
  3149. Return Value:
  3150. NTSTATUS - Standard Nt Result Code
  3151. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3152. to complete the operation.
  3153. STATUS_OBJECT_NAME_NOT_FOUND - There is no Secret object in the
  3154. target system's LSA Database having the specified SecretName.
  3155. --*/
  3156. {
  3157. NTSTATUS Status;
  3158. RpcTryExcept {
  3159. Status = LsarOpenSecret(
  3160. (LSAPR_HANDLE) PolicyHandle,
  3161. (PLSAPR_UNICODE_STRING) SecretName,
  3162. DesiredAccess,
  3163. (PLSAPR_HANDLE) SecretHandle
  3164. );
  3165. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3166. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3167. } RpcEndExcept;
  3168. return(Status);
  3169. }
  3170. NTSTATUS
  3171. LsaSetSecret(
  3172. IN LSA_HANDLE SecretHandle,
  3173. IN OPTIONAL PUNICODE_STRING CurrentValue,
  3174. IN OPTIONAL PUNICODE_STRING OldValue
  3175. )
  3176. /*++
  3177. Routine Description:
  3178. The LsaSetSecret API optionally sets one or both values associated with
  3179. a secret. These values are known as the "current value" and "old value"
  3180. of the secret and have a meaning known to the creator of the Secret
  3181. object. The values given are stored in encrypted form.
  3182. Arguments:
  3183. SecretHandle - Handle from an LsaOpenSecret or LsaCreateSecret call.
  3184. CurrentValue - Optional pointer to Unicode String containing the
  3185. value to be assigned as the "current value" of the Secret
  3186. object. The meaning of "current value" is dependent on the
  3187. purpose for which the Secret object is being used.
  3188. OldValue - Optional pointer to Unicode String containing the
  3189. value to be assigned as the "old value" of the Secret object.
  3190. The meaning of "old value" is dependent on the purpose for
  3191. which the Secret object is being used.
  3192. Return Value:
  3193. NTSTATUS - Standard Nt Result Code
  3194. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3195. to complete the operation.
  3196. STATUS_OBJECT_NAME_NOT_FOUND - There is no Secret object in the
  3197. target system's LSA Database having the specified SecretName.
  3198. --*/
  3199. {
  3200. NTSTATUS Status;
  3201. PLSAP_CR_CIPHER_VALUE CipherCurrentValue = NULL;
  3202. PLSAP_CR_CIPHER_VALUE CipherOldValue = NULL;
  3203. LSAP_CR_CLEAR_VALUE ClearCurrentValue;
  3204. LSAP_CR_CLEAR_VALUE ClearOldValue;
  3205. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  3206. //
  3207. // Convert input from Unicode Structures to Clear Value Structures.
  3208. //
  3209. LsapCrUnicodeToClearValue( CurrentValue, &ClearCurrentValue );
  3210. LsapCrUnicodeToClearValue( OldValue, &ClearOldValue );
  3211. //
  3212. // Obtain the Session Key to be used to two-way encrypt the
  3213. // Current Value and/or Old Values.
  3214. //
  3215. RpcTryExcept {
  3216. Status = LsapCrClientGetSessionKey( SecretHandle, &SessionKey );
  3217. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3218. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3219. } RpcEndExcept;
  3220. if (!NT_SUCCESS(Status)) {
  3221. goto SetSecretError;
  3222. }
  3223. //
  3224. // Encrypt the Current Value if specified and not too long.
  3225. //
  3226. if (ARGUMENT_PRESENT(CurrentValue)) {
  3227. Status = LsapCrEncryptValue(
  3228. &ClearCurrentValue,
  3229. SessionKey,
  3230. &CipherCurrentValue
  3231. );
  3232. if (!NT_SUCCESS(Status)) {
  3233. goto SetSecretError;
  3234. }
  3235. }
  3236. //
  3237. // Encrypt the Old Value if specified and not too long.
  3238. //
  3239. if (ARGUMENT_PRESENT(OldValue)) {
  3240. Status = LsapCrEncryptValue(
  3241. (PLSAP_CR_CLEAR_VALUE) &ClearOldValue,
  3242. SessionKey,
  3243. &CipherOldValue
  3244. );
  3245. if (!NT_SUCCESS(Status)) {
  3246. goto SetSecretError;
  3247. }
  3248. }
  3249. //
  3250. // Set the Secret Values.
  3251. //
  3252. RpcTryExcept {
  3253. Status = LsarSetSecret(
  3254. (LSAPR_HANDLE) SecretHandle,
  3255. (PLSAPR_CR_CIPHER_VALUE) CipherCurrentValue,
  3256. (PLSAPR_CR_CIPHER_VALUE) CipherOldValue
  3257. );
  3258. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3259. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3260. } RpcEndExcept;
  3261. if (!NT_SUCCESS(Status)) {
  3262. goto SetSecretError;
  3263. }
  3264. SetSecretFinish:
  3265. //
  3266. // If necessary, free memory allocated for the Encrypted Current Value.
  3267. //
  3268. if (CipherCurrentValue != NULL) {
  3269. LsaFreeMemory(CipherCurrentValue);
  3270. }
  3271. //
  3272. // If necessary, free memory allocated for the Encrypted Old Value.
  3273. //
  3274. if (CipherOldValue != NULL) {
  3275. LsaFreeMemory(CipherOldValue);
  3276. }
  3277. //
  3278. // If necessary, free memory allocated for the Session Key.
  3279. //
  3280. if (SessionKey != NULL) {
  3281. MIDL_user_free(SessionKey);
  3282. }
  3283. return(Status);
  3284. SetSecretError:
  3285. goto SetSecretFinish;
  3286. }
  3287. NTSTATUS
  3288. LsaQuerySecret(
  3289. IN LSA_HANDLE SecretHandle,
  3290. IN OUT OPTIONAL PUNICODE_STRING *CurrentValue,
  3291. OUT PLARGE_INTEGER CurrentValueSetTime,
  3292. IN OUT OPTIONAL PUNICODE_STRING *OldValue,
  3293. OUT PLARGE_INTEGER OldValueSetTime
  3294. )
  3295. /*++
  3296. Routine Description:
  3297. The LsaQuerySecret API optionally returns one or both of the values
  3298. assigned to a Secret object. These values are known as the "current value"
  3299. and the "old value", and they have a meaning known to the creator of the
  3300. Secret object. The values are returned in their original unencrypted form.
  3301. The caller must have LSA_QUERY_SECRET access to the Secret object.
  3302. Arguments:
  3303. SecretHandle - Handle from an LsaOpenSecret or LsaCreateSecret call.
  3304. CurrentValue - Optional pointer to location which will receive a pointer
  3305. to a Unicode String containing the value assigned as the "current
  3306. value" of the secret object. If no "current value" is assigned to
  3307. the Secret object, a NULL pointer is returned.
  3308. CurrentValueSetTime - The date/time at which the current secret value
  3309. was established.
  3310. OldValue - Optional pointer to location which will receive a pointer
  3311. to a Unicode String containing the value assigned as the "old
  3312. value" of the secret object. If no "current value" is assigned to
  3313. the Secret object, a NULL pointer is returned.
  3314. OldValueSetTime - The date/time at which the old secret value
  3315. was established.
  3316. Return Value:
  3317. NTSTATUS - Standard Nt Result Code
  3318. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3319. to complete the operation.
  3320. STATUS_OBJECT_NAME_NOT_FOUND - There is no Secret object in the
  3321. target system's LSA Database having the specified SecretName.
  3322. --*/
  3323. {
  3324. NTSTATUS Status = STATUS_SUCCESS;
  3325. PLSAP_CR_CIPHER_VALUE CipherCurrentValue = NULL;
  3326. PLSAP_CR_CIPHER_VALUE CipherOldValue = NULL;
  3327. PLSAP_CR_CLEAR_VALUE ClearCurrentValue = NULL;
  3328. PLSAP_CR_CLEAR_VALUE ClearOldValue = NULL;
  3329. PLSAP_CR_CIPHER_KEY SessionKey = NULL;
  3330. RpcTryExcept {
  3331. Status = LsarQuerySecret(
  3332. (PLSAPR_HANDLE) SecretHandle,
  3333. (PLSAPR_CR_CIPHER_VALUE *) &CipherCurrentValue,
  3334. CurrentValueSetTime,
  3335. (PLSAPR_CR_CIPHER_VALUE *) &CipherOldValue,
  3336. OldValueSetTime
  3337. );
  3338. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3339. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3340. } RpcEndExcept;
  3341. if (!NT_SUCCESS(Status)) {
  3342. goto QuerySecretError;
  3343. }
  3344. //
  3345. // Obtain the Session Key to be used to two-way encrypt the
  3346. // Current Value and/or Old Values.
  3347. //
  3348. RpcTryExcept {
  3349. Status = LsapCrClientGetSessionKey( SecretHandle, &SessionKey );
  3350. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3351. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3352. } RpcEndExcept;
  3353. if (!NT_SUCCESS(Status)) {
  3354. goto QuerySecretError;
  3355. }
  3356. //
  3357. // If the Current Value is requested and a Current Value exists,
  3358. // decrypt it using the Session key. Otherwise store NULL for return.
  3359. //
  3360. if (ARGUMENT_PRESENT(CurrentValue)) {
  3361. if (CipherCurrentValue != NULL) {
  3362. Status = LsapCrDecryptValue(
  3363. CipherCurrentValue,
  3364. SessionKey,
  3365. &ClearCurrentValue
  3366. );
  3367. if (!NT_SUCCESS(Status)) {
  3368. goto QuerySecretError;
  3369. }
  3370. //
  3371. // Convert Clear Current Value to Unicode
  3372. //
  3373. LsapCrClearValueToUnicode(
  3374. ClearCurrentValue,
  3375. (PUNICODE_STRING) ClearCurrentValue
  3376. );
  3377. *CurrentValue = (PUNICODE_STRING) ClearCurrentValue;
  3378. } else {
  3379. *CurrentValue = NULL;
  3380. }
  3381. }
  3382. //
  3383. // If the Old Value is requested and an Old Value exists,
  3384. // decrypt it using the Session key. Otherwise store NULL for return.
  3385. //
  3386. if (ARGUMENT_PRESENT(OldValue)) {
  3387. if (CipherOldValue != NULL) {
  3388. Status = LsapCrDecryptValue(
  3389. CipherOldValue,
  3390. SessionKey,
  3391. &ClearOldValue
  3392. );
  3393. if (!NT_SUCCESS(Status)) {
  3394. goto QuerySecretError;
  3395. }
  3396. //
  3397. // Convert Clear Old Value to Unicode
  3398. //
  3399. LsapCrClearValueToUnicode(
  3400. ClearOldValue,
  3401. (PUNICODE_STRING) ClearOldValue
  3402. );
  3403. *OldValue = (PUNICODE_STRING) ClearOldValue;
  3404. } else {
  3405. *OldValue = NULL;
  3406. }
  3407. }
  3408. //
  3409. // Getting here means that the operation completed successfully,
  3410. // but Status can be something other than STATUS_SUCCESS.
  3411. // For instance, if both output buffers are NULL, the value of Status
  3412. // at this point will be STATUS_LOCAL_USER_SESSION_KEY.
  3413. // Explicitly clear Status here and avoid confusion for the client.
  3414. //
  3415. Status = STATUS_SUCCESS;
  3416. QuerySecretFinish:
  3417. //
  3418. // If necessary, free memory allocated for the Session Key.
  3419. //
  3420. if (SessionKey != NULL) {
  3421. MIDL_user_free(SessionKey);
  3422. }
  3423. //
  3424. // If necessary, free memory allocated for the returned Encrypted
  3425. // Current Value.
  3426. //
  3427. if (CipherCurrentValue != NULL) {
  3428. LsapCrFreeMemoryValue(CipherCurrentValue);
  3429. }
  3430. //
  3431. // If necessary, free memory allocated for the returned Encrypted
  3432. // Old Value.
  3433. //
  3434. if (CipherOldValue != NULL) {
  3435. LsapCrFreeMemoryValue(CipherOldValue);
  3436. }
  3437. return(Status);
  3438. QuerySecretError:
  3439. //
  3440. // If necessary, free memory allocated for the Clear Current Value
  3441. //
  3442. if (ClearCurrentValue != NULL) {
  3443. LsapCrFreeMemoryValue(ClearCurrentValue);
  3444. }
  3445. //
  3446. // If necessary, free memory allocated for the Clear Old Value
  3447. // Unicode string (buffer and structure).
  3448. //
  3449. if (ClearOldValue != NULL) {
  3450. LsapCrFreeMemoryValue(ClearOldValue);
  3451. }
  3452. if (ARGUMENT_PRESENT(CurrentValue)) {
  3453. *CurrentValue = NULL;
  3454. }
  3455. if (ARGUMENT_PRESENT(OldValue)) {
  3456. *OldValue = NULL;
  3457. }
  3458. goto QuerySecretFinish;
  3459. }
  3460. NTSTATUS
  3461. LsaGetUserName(
  3462. OUT PUNICODE_STRING * UserName,
  3463. OUT OPTIONAL PUNICODE_STRING * DomainName
  3464. )
  3465. /*++
  3466. Routine Description:
  3467. This function returns the callers user name and domain name
  3468. Arguments:
  3469. UserName - Receives a pointer to the user's name.
  3470. DomainName - Optionally receives a pointer to the user's domain name.
  3471. Return Value:
  3472. NTSTATUS - The privilege was found and returned.
  3473. --*/
  3474. {
  3475. NTSTATUS Status;
  3476. PLSAPR_UNICODE_STRING UserNameBuffer = NULL;
  3477. PLSAPR_UNICODE_STRING DomainNameBuffer = NULL;
  3478. RpcTryExcept {
  3479. //
  3480. // Call the Client Stub for LsaGetUserName
  3481. //
  3482. Status = LsarGetUserName(
  3483. NULL,
  3484. &UserNameBuffer,
  3485. ARGUMENT_PRESENT(DomainName) ? &DomainNameBuffer : NULL
  3486. );
  3487. (*UserName) = (PUNICODE_STRING)UserNameBuffer;
  3488. if (ARGUMENT_PRESENT(DomainName)) {
  3489. (*DomainName) = (PUNICODE_STRING)DomainNameBuffer;
  3490. }
  3491. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3492. //
  3493. // If memory was allocated for the return buffer, free it.
  3494. //
  3495. if (UserNameBuffer != NULL) {
  3496. MIDL_user_free(UserNameBuffer);
  3497. }
  3498. if (DomainNameBuffer != NULL) {
  3499. MIDL_user_free(DomainNameBuffer);
  3500. }
  3501. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3502. } RpcEndExcept;
  3503. return(Status);
  3504. }
  3505. NTSTATUS
  3506. LsaGetRemoteUserName(
  3507. IN PUNICODE_STRING SystemName,
  3508. OUT PUNICODE_STRING * UserName,
  3509. OUT OPTIONAL PUNICODE_STRING * DomainName
  3510. )
  3511. /*++
  3512. Routine Description:
  3513. This function returns the callers user name and domain name
  3514. Arguments:
  3515. SystemName - Name of system on which to obtain the user name.
  3516. UserName - Receives a pointer to the user's name.
  3517. DomainName - Optionally receives a pointer to the user's domain name.
  3518. Return Value:
  3519. NTSTATUS - The privilege was found and returned.
  3520. --*/
  3521. {
  3522. NTSTATUS Status;
  3523. PLSAPR_UNICODE_STRING UserNameBuffer = NULL;
  3524. PLSAPR_UNICODE_STRING DomainNameBuffer = NULL;
  3525. PLSAPR_SERVER_NAME ServerName = NULL;
  3526. USHORT NullTerminatedServerNameLength;
  3527. if (ARGUMENT_PRESENT(SystemName) &&
  3528. (SystemName->Buffer != NULL) &&
  3529. (SystemName->Length > 0)) {
  3530. NullTerminatedServerNameLength = SystemName->Length + (USHORT) sizeof (WCHAR);
  3531. ServerName = MIDL_user_allocate( NullTerminatedServerNameLength );
  3532. if (ServerName != NULL) {
  3533. RtlZeroMemory( ServerName, NullTerminatedServerNameLength );
  3534. RtlMoveMemory(
  3535. ServerName,
  3536. SystemName->Buffer,
  3537. SystemName->Length
  3538. );
  3539. } else {
  3540. return(STATUS_INSUFFICIENT_RESOURCES);
  3541. }
  3542. }
  3543. RpcTryExcept {
  3544. //
  3545. // Call the Client Stub for LsaGetUserName
  3546. //
  3547. Status = LsarGetUserName(
  3548. ServerName,
  3549. &UserNameBuffer,
  3550. ARGUMENT_PRESENT(DomainName) ? &DomainNameBuffer : NULL
  3551. );
  3552. (*UserName) = (PUNICODE_STRING)UserNameBuffer;
  3553. if (ARGUMENT_PRESENT(DomainName)) {
  3554. (*DomainName) = (PUNICODE_STRING)DomainNameBuffer;
  3555. }
  3556. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3557. //
  3558. // If memory was allocated for the return buffer, free it.
  3559. //
  3560. if (UserNameBuffer != NULL) {
  3561. MIDL_user_free(UserNameBuffer);
  3562. }
  3563. if (DomainNameBuffer != NULL) {
  3564. MIDL_user_free(DomainNameBuffer);
  3565. }
  3566. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3567. } RpcEndExcept;
  3568. if (ServerName != NULL) {
  3569. MIDL_user_free(ServerName);
  3570. }
  3571. return(Status);
  3572. }
  3573. NTSTATUS
  3574. LsaICLookupNamesWithCreds(
  3575. IN LPWSTR ServerName,
  3576. IN LPWSTR ServerPrincipalName,
  3577. IN ULONG AuthnLevel,
  3578. IN ULONG AuthnSvc,
  3579. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity,
  3580. IN ULONG AuthzSvc,
  3581. IN ULONG Count,
  3582. IN PUNICODE_STRING Names,
  3583. OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
  3584. OUT PLSA_TRANSLATED_SID_EX2 *Sids,
  3585. IN LSAP_LOOKUP_LEVEL LookupLevel,
  3586. IN OUT PULONG MappedCount
  3587. )
  3588. /*++
  3589. Routine Description:
  3590. This routine performs a lookup with the using an LSA context handle.
  3591. Its purpose is to facilitate lookups over NETLOGON's secure channel.
  3592. N.B. The routine uses only TCP/IP as the transport.
  3593. Arguments:
  3594. ServerName -- the destination server, NULL terminated
  3595. ServerPrincipalName,
  3596. AuthnLevel,
  3597. AuthSvc,
  3598. AuthIdentity,
  3599. AuthzSvc -- see RpcSetAuthInfo
  3600. Rset of the parameters -- see LsaLookupNames2
  3601. Return Values:
  3602. NTSTATUS - Standard Nt Result Code
  3603. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3604. to complete the operation.
  3605. STATUS_SOME_NOT_MAPPED - Some or all of the names provided could
  3606. not be mapped. This is an informational status only.
  3607. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
  3608. to complete the call.
  3609. --*/
  3610. {
  3611. NTSTATUS Status = STATUS_SUCCESS;
  3612. DWORD RpcError = 0;
  3613. RPC_BINDING_HANDLE BindingHandle = NULL;
  3614. WCHAR *StringBinding = NULL;
  3615. LSAPR_TRANSLATED_SIDS_EX2 ReturnedSidsEx2 = { 0, NULL };
  3616. //
  3617. // Init to NULL since these are considered to be a IN/OUT parameters
  3618. // for the Lsar Lookup API's
  3619. //
  3620. if ((ServerName == NULL)
  3621. || (ReferencedDomains == NULL)
  3622. || (Sids == NULL)
  3623. || (MappedCount == NULL)) {
  3624. return STATUS_INVALID_PARAMETER;
  3625. }
  3626. *ReferencedDomains = NULL;
  3627. *Sids = NULL;
  3628. *MappedCount = 0;
  3629. if ( 0 == wcsncmp(ServerName, L"\\\\", 2) ) {
  3630. ServerName += 2;
  3631. }
  3632. RpcError = RpcStringBindingComposeW(
  3633. NULL,
  3634. L"ncacn_ip_tcp",
  3635. ServerName,
  3636. NULL,
  3637. NULL,
  3638. &StringBinding);
  3639. if (RPC_S_OK == RpcError) {
  3640. RpcError = RpcBindingFromStringBindingW(
  3641. StringBinding,
  3642. &BindingHandle);
  3643. if ( RPC_S_OK == RpcError ) {
  3644. RpcError = RpcEpResolveBinding(BindingHandle,
  3645. lsarpc_ClientIfHandle);
  3646. if ( RPC_S_OK == RpcError ) {
  3647. RpcError = RpcBindingSetAuthInfoW(
  3648. BindingHandle,
  3649. ServerPrincipalName,
  3650. AuthnLevel,
  3651. AuthnSvc,
  3652. AuthIdentity,
  3653. AuthzSvc
  3654. );
  3655. }
  3656. }
  3657. }
  3658. if (RPC_S_OK != RpcError) {
  3659. //
  3660. // This is fatal
  3661. //
  3662. Status = I_RpcMapWin32Status(RpcError);
  3663. goto Cleanup;
  3664. }
  3665. RpcTryExcept {
  3666. ReturnedSidsEx2.Entries = 0;
  3667. ReturnedSidsEx2.Sids = NULL;
  3668. Status = LsarLookupNames4(
  3669. BindingHandle,
  3670. Count,
  3671. (PLSAPR_UNICODE_STRING) Names,
  3672. (PLSAPR_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  3673. &ReturnedSidsEx2,
  3674. LookupLevel,
  3675. MappedCount,
  3676. 0, // no flags currently defined
  3677. LSA_LOOKUP_REVISION_LATEST
  3678. );
  3679. *Sids = (PLSA_TRANSLATED_SID_EX2)ReturnedSidsEx2.Sids;
  3680. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3681. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3682. } RpcEndExcept;
  3683. Cleanup:
  3684. //
  3685. // Make the handling of this unsupported condition simpler by returning
  3686. // one error code
  3687. //
  3688. if ( (Status == RPC_NT_UNKNOWN_IF) ||
  3689. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE) ||
  3690. (Status == EPT_NT_NOT_REGISTERED) ) {
  3691. Status = STATUS_NOT_SUPPORTED;
  3692. }
  3693. if (BindingHandle) {
  3694. RpcBindingFree(&BindingHandle);
  3695. }
  3696. if (StringBinding){
  3697. RpcStringFreeW(&StringBinding);
  3698. }
  3699. return(Status);
  3700. }
  3701. NTSTATUS
  3702. LsaICLookupSidsWithCreds(
  3703. IN LPWSTR ServerName,
  3704. IN LPWSTR ServerPrincipalName,
  3705. IN ULONG AuthnLevel,
  3706. IN ULONG AuthnSvc,
  3707. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity,
  3708. IN ULONG AuthzSvc,
  3709. IN ULONG Count,
  3710. IN PSID *Sids,
  3711. OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
  3712. OUT PLSA_TRANSLATED_NAME_EX *Names,
  3713. IN LSAP_LOOKUP_LEVEL LookupLevel,
  3714. IN OUT PULONG MappedCount
  3715. )
  3716. /*++
  3717. Routine Description:
  3718. This routine performs a lookup with the using an LSA context handle.
  3719. Its purpose is to facilitate lookups over NETLOGON's secure channel.
  3720. N.B. The routine uses only TCP/IP as the transport.
  3721. Arguments:
  3722. ServerName -- the destination server, NULL terminated
  3723. ServerPrincipalName,
  3724. AuthnLevel,
  3725. AuthSvc,
  3726. AuthIdentity,
  3727. AuthzSvc -- see RpcSetAuthInfo
  3728. Rset of the parameters -- see LsaLookupSids
  3729. Return Values:
  3730. NTSTATUS - Standard Nt Result Code
  3731. STATUS_ACCESS_DENIED - Caller does not have the appropriate access
  3732. to complete the operation.
  3733. STATUS_SOME_NOT_MAPPED - Some or all of the names provided could
  3734. not be mapped. This is an informational status only.
  3735. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
  3736. to complete the call.
  3737. --*/
  3738. {
  3739. NTSTATUS Status = STATUS_SUCCESS;
  3740. DWORD RpcError = 0;
  3741. RPC_BINDING_HANDLE BindingHandle = NULL;
  3742. WCHAR *StringBinding = NULL;
  3743. LSAPR_TRANSLATED_NAMES_EX ReturnedNames = { 0, NULL };
  3744. LSAPR_SID_ENUM_BUFFER SidEnumBuffer;
  3745. //
  3746. // Init to NULL since these are considered to be a IN/OUT parameters
  3747. // for the Lsar Lookup API's
  3748. //
  3749. if ((ServerName == NULL)
  3750. || (ReferencedDomains == NULL)
  3751. || (Names == NULL)
  3752. || (MappedCount == NULL)
  3753. || (Count == 0) ) {
  3754. return STATUS_INVALID_PARAMETER;
  3755. }
  3756. *ReferencedDomains = NULL;
  3757. *Names = NULL;
  3758. *MappedCount = 0;
  3759. SidEnumBuffer.Entries = Count;
  3760. SidEnumBuffer.SidInfo = (PLSAPR_SID_INFORMATION) Sids;
  3761. if ( 0 == wcsncmp(ServerName, L"\\\\", 2) ) {
  3762. ServerName += 2;
  3763. }
  3764. RpcError = RpcStringBindingComposeW(
  3765. NULL,
  3766. L"ncacn_ip_tcp",
  3767. ServerName,
  3768. NULL,
  3769. NULL,
  3770. &StringBinding);
  3771. if (RPC_S_OK == RpcError) {
  3772. RpcError = RpcBindingFromStringBindingW(
  3773. StringBinding,
  3774. &BindingHandle);
  3775. if ( RPC_S_OK == RpcError ) {
  3776. RpcError = RpcEpResolveBinding(BindingHandle,
  3777. lsarpc_ClientIfHandle);
  3778. if ( RPC_S_OK == RpcError ) {
  3779. RpcError = RpcBindingSetAuthInfoW(
  3780. BindingHandle,
  3781. ServerPrincipalName,
  3782. AuthnLevel,
  3783. AuthnSvc,
  3784. AuthIdentity,
  3785. AuthzSvc
  3786. );
  3787. }
  3788. }
  3789. }
  3790. if (RPC_S_OK != RpcError) {
  3791. Status = I_RpcMapWin32Status(RpcError);
  3792. goto Cleanup;
  3793. }
  3794. RpcTryExcept {
  3795. ReturnedNames.Entries = 0;
  3796. ReturnedNames.Names = NULL;
  3797. //
  3798. // Lookup Sids on the Server..
  3799. //
  3800. Status = LsarLookupSids3(
  3801. BindingHandle,
  3802. &SidEnumBuffer,
  3803. (PLSAPR_REFERENCED_DOMAIN_LIST *) ReferencedDomains,
  3804. &ReturnedNames,
  3805. LookupLevel,
  3806. MappedCount,
  3807. 0,
  3808. LSA_CLIENT_NT5
  3809. );
  3810. *Names = (PLSA_TRANSLATED_NAME_EX) ReturnedNames.Names;
  3811. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3812. Status = LsapApiReturnResult(I_RpcMapWin32Status(RpcExceptionCode()));
  3813. } RpcEndExcept;
  3814. //
  3815. // Prevent against network hacks
  3816. //
  3817. if (NT_SUCCESS(Status)) {
  3818. Status = LsapVerifyReturnedNames(&ReturnedNames,
  3819. Count,
  3820. *ReferencedDomains);
  3821. if (!NT_SUCCESS(Status)) {
  3822. if (*Names) {
  3823. MIDL_user_free(*Names);
  3824. *Names = NULL;
  3825. }
  3826. if ( *ReferencedDomains ) {
  3827. MIDL_user_free( *ReferencedDomains );
  3828. *ReferencedDomains = NULL;
  3829. }
  3830. }
  3831. }
  3832. Cleanup:
  3833. //
  3834. // Make the handling of this unsupported condition simpler by returning
  3835. // one error code
  3836. //
  3837. if ( (Status == RPC_NT_UNKNOWN_IF) ||
  3838. (Status == RPC_NT_PROCNUM_OUT_OF_RANGE) ||
  3839. (Status == EPT_NT_NOT_REGISTERED) ) {
  3840. Status = STATUS_NOT_SUPPORTED;
  3841. }
  3842. if (BindingHandle) {
  3843. RpcBindingFree(&BindingHandle);
  3844. }
  3845. if (StringBinding){
  3846. RpcStringFreeW(&StringBinding);
  3847. }
  3848. return(Status);
  3849. }