Leaked source code of windows server 2003
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.

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