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.

3633 lines
109 KiB

  1. /*++
  2. Copyright (c) 1987-1992 Microsoft Corporation
  3. Module Name:
  4. ssiapi.c
  5. Abstract:
  6. Authentication and replication API routines (client side).
  7. Author:
  8. Cliff Van Dyke (cliffv) 30-Jul-1991
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. --*/
  15. #include <nt.h> // LARGE_INTEGER definition
  16. #include <ntrtl.h> // LARGE_INTEGER definition
  17. #include <nturtl.h> // LARGE_INTEGER definition
  18. #include <rpc.h> // Needed by logon.h
  19. #include <ntrpcp.h> // needed by rpcasync.h
  20. #include <rpcasync.h> // I_RpcExceptionFilter
  21. #include <logon_c.h> // includes lmcons.h, lmaccess.h, netlogon.h, ssi.h, windef.h
  22. #include <debuglib.h> // IF_DEBUG()
  23. #include <lmerr.h> // NERR_* defines
  24. #include <lmapibuf.h> // NetApiBufferFree()
  25. #include <netdebug.h> // NetpKdPrint
  26. #include <netlibnt.h> // NetpNtStatusToApiStatus()
  27. #include "..\server\ssiapi.h"
  28. #include <winsock2.h> // Needed by nlcommon.h
  29. #include <netlib.h> // Needed by nlcommon.h
  30. #include <ntddbrow.h> // Needed by nlcommon.h
  31. #include "nlcommon.h"
  32. #include <netlogp.h>
  33. #include <tstring.h> // NetpCopyStrToWStr()
  34. #include <align.h> // ROUND_UP_COUNT ...
  35. #include <strarray.h> // NetpIsTStrArrayEmpty
  36. #include <ftnfoctx.h> // NetpMergeFtinfo
  37. NTSTATUS
  38. I_NetServerReqChallenge(
  39. IN LPWSTR PrimaryName OPTIONAL,
  40. IN LPWSTR ComputerName,
  41. IN PNETLOGON_CREDENTIAL ClientChallenge,
  42. OUT PNETLOGON_CREDENTIAL ServerChallenge
  43. )
  44. /*++
  45. Routine Description:
  46. This is the client side of I_NetServerReqChallenge.
  47. I_NetLogonRequestChallenge is the first of two functions used by a client
  48. to process an authentication with a domain controller (DC). (See
  49. I_NetServerAuthenticate below.) It is called for
  50. a BDC (or member server) authenticating with a PDC for replication
  51. purposes.
  52. This function passes a challenge to the PDC and the PDC passes a challenge
  53. back to the caller.
  54. Arguments:
  55. PrimaryName -- Supplies the name of the PrimaryDomainController we wish to
  56. authenticate with.
  57. ComputerName -- Name of the BDC or member server making the call.
  58. ClientChallenge -- 64 bit challenge supplied by the BDC or member server.
  59. ServerChallenge -- Receives 64 bit challenge from the PDC.
  60. Return Value:
  61. The status of the operation.
  62. --*/
  63. {
  64. NTSTATUS Status = 0;
  65. //
  66. // Do the RPC call with an exception handler since RPC will raise an
  67. // exception if anything fails. It is up to us to figure out what
  68. // to do once the exception is raised.
  69. //
  70. RpcTryExcept {
  71. //
  72. // Call RPC version of the API.
  73. //
  74. Status = NetrServerReqChallenge(
  75. PrimaryName,
  76. ComputerName,
  77. ClientChallenge,
  78. ServerChallenge );
  79. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  80. Status = I_RpcMapWin32Status(RpcExceptionCode());
  81. } RpcEndExcept;
  82. IF_DEBUG( LOGON ) {
  83. NetpKdPrint(("I_NetServerReqChallenge rc = %lu 0x%lx\n",
  84. Status, Status));
  85. }
  86. return Status;
  87. }
  88. NTSTATUS
  89. I_NetServerAuthenticate(
  90. IN LPWSTR PrimaryName OPTIONAL,
  91. IN LPWSTR AccountName,
  92. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  93. IN LPWSTR ComputerName,
  94. IN PNETLOGON_CREDENTIAL ClientCredential,
  95. OUT PNETLOGON_CREDENTIAL ServerCredential
  96. )
  97. /*++
  98. Routine Description:
  99. This is the client side of I_NetServerAuthenticate
  100. I_NetServerAuthenticate is the second of two functions used by a client
  101. Netlogon service to authenticate with another Netlogon service.
  102. (See I_NetServerReqChallenge above.) Both a SAM or UAS server authenticates
  103. using this function.
  104. This function passes a credential to the DC and the DC passes a credential
  105. back to the caller.
  106. Arguments:
  107. PrimaryName -- Supplies the name of the DC we wish to authenticate with.
  108. AccountName -- Name of the Account to authenticate with.
  109. SecureChannelType -- The type of the account being accessed. This field
  110. must be set to UasServerSecureChannel to indicate a call from
  111. downlevel (LanMan 2.x and below) BDC or member server.
  112. ComputerName -- Name of the BDC or member server making the call.
  113. ClientCredential -- 64 bit credential supplied by the BDC or member server.
  114. ServerCredential -- Receives 64 bit credential from the PDC.
  115. Return Value:
  116. The status of the operation.
  117. --*/
  118. {
  119. NTSTATUS Status = 0;
  120. //
  121. // Do the RPC call with an exception handler since RPC will raise an
  122. // exception if anything fails. It is up to us to figure out what
  123. // to do once the exception is raised.
  124. //
  125. RpcTryExcept {
  126. //
  127. // Call RPC version of the API.
  128. //
  129. Status = NetrServerAuthenticate(
  130. PrimaryName,
  131. AccountName,
  132. AccountType,
  133. ComputerName,
  134. ClientCredential,
  135. ServerCredential );
  136. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  137. Status = I_RpcMapWin32Status(RpcExceptionCode());
  138. } RpcEndExcept;
  139. IF_DEBUG( LOGON ) {
  140. NetpKdPrint(("I_NetServerAuthenticate rc = %lu 0x%lx\n",
  141. Status, Status));
  142. }
  143. return Status;
  144. }
  145. NTSTATUS
  146. I_NetServerAuthenticate2(
  147. IN LPWSTR PrimaryName OPTIONAL,
  148. IN LPWSTR AccountName,
  149. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  150. IN LPWSTR ComputerName,
  151. IN PNETLOGON_CREDENTIAL ClientCredential,
  152. OUT PNETLOGON_CREDENTIAL ServerCredential,
  153. IN OUT PULONG NegotiatedFlags
  154. )
  155. /*++
  156. Routine Description:
  157. This is the client side of I_NetServerAuthenticate
  158. I_NetServerAuthenticate is the second of two functions used by a client
  159. Netlogon service to authenticate with another Netlogon service.
  160. (See I_NetServerReqChallenge above.) Both a SAM or UAS server authenticates
  161. using this function.
  162. This function passes a credential to the DC and the DC passes a credential
  163. back to the caller.
  164. Arguments:
  165. PrimaryName -- Supplies the name of the DC we wish to authenticate with.
  166. AccountName -- Name of the Account to authenticate with.
  167. SecureChannelType -- The type of the account being accessed. This field
  168. must be set to UasServerSecureChannel to indicate a call from
  169. downlevel (LanMan 2.x and below) BDC or member server.
  170. ComputerName -- Name of the BDC or member server making the call.
  171. ClientCredential -- 64 bit credential supplied by the BDC or member server.
  172. ServerCredential -- Receives 64 bit credential from the PDC.
  173. NegotiatedFlags -- Specifies flags indicating what features the BDC supports.
  174. Returns a subset of those flags indicating what features the PDC supports.
  175. The PDC/BDC should ignore any bits that it doesn't understand.
  176. Return Value:
  177. The status of the operation.
  178. --*/
  179. {
  180. NTSTATUS Status = 0;
  181. //
  182. // Do the RPC call with an exception handler since RPC will raise an
  183. // exception if anything fails. It is up to us to figure out what
  184. // to do once the exception is raised.
  185. //
  186. RpcTryExcept {
  187. //
  188. // Call RPC version of the API.
  189. //
  190. Status = NetrServerAuthenticate2(
  191. PrimaryName,
  192. AccountName,
  193. AccountType,
  194. ComputerName,
  195. ClientCredential,
  196. ServerCredential,
  197. NegotiatedFlags );
  198. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  199. Status = I_RpcMapWin32Status(RpcExceptionCode());
  200. } RpcEndExcept;
  201. IF_DEBUG( LOGON ) {
  202. NetpKdPrint(("I_NetServerAuthenticate2 rc = %lu 0x%lx\n",
  203. Status, Status));
  204. }
  205. return Status;
  206. }
  207. NTSTATUS
  208. I_NetServerAuthenticate3(
  209. IN LPWSTR PrimaryName OPTIONAL,
  210. IN LPWSTR AccountName,
  211. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  212. IN LPWSTR ComputerName,
  213. IN PNETLOGON_CREDENTIAL ClientCredential,
  214. OUT PNETLOGON_CREDENTIAL ServerCredential,
  215. IN OUT PULONG NegotiatedFlags,
  216. OUT PULONG AccountRid
  217. )
  218. /*++
  219. Routine Description:
  220. This is the client side of I_NetServerAuthenticate
  221. I_NetServerAuthenticate is the second of two functions used by a client
  222. Netlogon service to authenticate with another Netlogon service.
  223. (See I_NetServerReqChallenge above.) Both a SAM or UAS server authenticates
  224. using this function.
  225. This function passes a credential to the DC and the DC passes a credential
  226. back to the caller.
  227. Arguments:
  228. PrimaryName -- Supplies the name of the DC we wish to authenticate with.
  229. AccountName -- Name of the Account to authenticate with.
  230. SecureChannelType -- The type of the account being accessed. This field
  231. must be set to UasServerSecureChannel to indicate a call from
  232. downlevel (LanMan 2.x and below) BDC or member server.
  233. ComputerName -- Name of the BDC or member server making the call.
  234. ClientCredential -- 64 bit credential supplied by the BDC or member server.
  235. ServerCredential -- Receives 64 bit credential from the PDC.
  236. NegotiatedFlags -- Specifies flags indicating what features the BDC supports.
  237. Returns a subset of those flags indicating what features the PDC supports.
  238. The PDC/BDC should ignore any bits that it doesn't understand.
  239. AccountRid - Returns the relative ID of the account used for authentication.
  240. Return Value:
  241. The status of the operation.
  242. --*/
  243. {
  244. NTSTATUS Status = 0;
  245. //
  246. // Do the RPC call with an exception handler since RPC will raise an
  247. // exception if anything fails. It is up to us to figure out what
  248. // to do once the exception is raised.
  249. //
  250. RpcTryExcept {
  251. //
  252. // Call RPC version of the API.
  253. //
  254. Status = NetrServerAuthenticate3(
  255. PrimaryName,
  256. AccountName,
  257. AccountType,
  258. ComputerName,
  259. ClientCredential,
  260. ServerCredential,
  261. NegotiatedFlags,
  262. AccountRid );
  263. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  264. Status = I_RpcMapWin32Status(RpcExceptionCode());
  265. } RpcEndExcept;
  266. IF_DEBUG( LOGON ) {
  267. NetpKdPrint(("I_NetServerAuthenticate3 rc = %lu 0x%lx\n",
  268. Status, Status));
  269. }
  270. return Status;
  271. }
  272. NTSTATUS
  273. I_NetServerPasswordSet(
  274. IN LPWSTR PrimaryName OPTIONAL,
  275. IN LPWSTR AccountName,
  276. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  277. IN LPWSTR ComputerName,
  278. IN PNETLOGON_AUTHENTICATOR Authenticator,
  279. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  280. IN PENCRYPTED_LM_OWF_PASSWORD UasNewPassword
  281. )
  282. /*++
  283. Routine Description:
  284. This function is used to change the password for the account being
  285. used to maintain a secure channel. This function can only be called
  286. by a server which has previously authenticated with a DC by calling
  287. I_NetServerAuthenticate.
  288. The call is made differently depending on the account type:
  289. * A domain account password is changed from the PDC in the
  290. trusting domain. The I_NetServerPasswordSet call is made to any
  291. DC in the trusted domain.
  292. * A server account password is changed from the specific server.
  293. The I_NetServerPasswordSet call is made to the PDC in the domain
  294. the server belongs to.
  295. * A workstation account password is changed from the specific
  296. workstation. The I_NetServerPasswordSet call is made to a DC in
  297. the domain the server belongs to.
  298. For domain accounts and workstation accounts, the server being called
  299. may be a BDC in the specific domain. In that case, the BDC will
  300. validate the request and pass it on to the PDC of the domain using
  301. the server account secure channel. If the PDC of the domain is
  302. currently not available, the BDC will return STATUS_NO_LOGON_SERVERS. Since
  303. the UasNewPassword is passed encrypted by the session key, such a BDC
  304. will decrypt the UasNewPassword using the original session key and
  305. will re-encrypt it with the session key for its session to its PDC
  306. before passing the request on.
  307. This function uses RPC to contact the DC named by PrimaryName.
  308. Arguments:
  309. PrimaryName -- Name of the PDC to change the servers password
  310. with. NULL indicates this call is a local call being made on
  311. behalf of a UAS server by the XACT server.
  312. AccountName -- Name of the account to change the password for.
  313. AccountType -- The type of account being accessed. This field must
  314. be set to UasServerAccount to indicate a call from a downlevel
  315. ComputerName -- Name of the BDC or member making the call.
  316. Authenticator -- supplied by the server.
  317. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  318. UasNewPassword -- The new password for the server. This
  319. Password is generated by automatic means using
  320. random number genertaor seeded with the current Time
  321. It is assumed that the machine generated password
  322. was used as key to encrypt STD text and "sesskey"
  323. obtained via Challenge/Authenticate sequence was
  324. used to further encrypt it before passing to this api.
  325. i.e. UasNewPassword = E2(E1(STD_TXT, PW), SK)
  326. Return Value:
  327. NT status code.
  328. --*/
  329. {
  330. NTSTATUS Status = 0;
  331. //
  332. // Do the RPC call with an exception handler since RPC will raise an
  333. // exception if anything fails. It is up to us to figure out what
  334. // to do once the exception is raised.
  335. //
  336. RpcTryExcept {
  337. //
  338. // Call RPC version of the API.
  339. //
  340. Status = NetrServerPasswordSet(
  341. PrimaryName,
  342. AccountName,
  343. AccountType,
  344. ComputerName,
  345. Authenticator,
  346. ReturnAuthenticator,
  347. UasNewPassword );
  348. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  349. Status = I_RpcMapWin32Status(RpcExceptionCode());
  350. } RpcEndExcept;
  351. IF_DEBUG( LOGON ) {
  352. NetpKdPrint(("I_NetServerPasswordSet rc = %lu 0x%lx\n",
  353. Status, Status));
  354. }
  355. return Status;
  356. }
  357. NTSTATUS
  358. I_NetServerPasswordSet2(
  359. IN LPWSTR PrimaryName OPTIONAL,
  360. IN LPWSTR AccountName,
  361. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  362. IN LPWSTR ComputerName,
  363. IN PNETLOGON_AUTHENTICATOR Authenticator,
  364. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  365. IN PNL_TRUST_PASSWORD ClearNewPassword
  366. )
  367. /*++
  368. Routine Description:
  369. This function is used to change the password for the account being
  370. used to maintain a secure channel. This function can only be called
  371. by a server which has previously authenticated with a DC by calling
  372. I_NetServerAuthenticate.
  373. The call is made differently depending on the account type:
  374. * A domain account password is changed from the PDC in the
  375. trusting domain. The I_NetServerPasswordSet call is made to any
  376. DC in the trusted domain.
  377. * A server account password is changed from the specific server.
  378. The I_NetServerPasswordSet call is made to the PDC in the domain
  379. the server belongs to.
  380. * A workstation account password is changed from the specific
  381. workstation. The I_NetServerPasswordSet call is made to a DC in
  382. the domain the server belongs to.
  383. For domain accounts and workstation accounts, the server being called
  384. may be a BDC in the specific domain. In that case, the BDC will
  385. validate the request and pass it on to the PDC of the domain using
  386. the server account secure channel. If the PDC of the domain is
  387. currently not available, the BDC will return STATUS_NO_LOGON_SERVERS. Since
  388. the UasNewPassword is passed encrypted by the session key, such a BDC
  389. will decrypt the UasNewPassword using the original session key and
  390. will re-encrypt it with the session key for its session to its PDC
  391. before passing the request on.
  392. This function uses RPC to contact the DC named by PrimaryName.
  393. Arguments:
  394. PrimaryName -- Name of the PDC to change the servers password
  395. with. NULL indicates this call is a local call being made on
  396. behalf of a UAS server by the XACT server.
  397. AccountName -- Name of the account to change the password for.
  398. AccountType -- The type of account being accessed. This field must
  399. be set to UasServerAccount to indicate a call from a downlevel
  400. ComputerName -- Name of the BDC or member making the call.
  401. Authenticator -- supplied by the server.
  402. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  403. ClearNewPassword - The new password for the server.
  404. Appropriately encrypted.
  405. Return Value:
  406. NT status code.
  407. --*/
  408. {
  409. NTSTATUS Status = 0;
  410. //
  411. // Do the RPC call with an exception handler since RPC will raise an
  412. // exception if anything fails. It is up to us to figure out what
  413. // to do once the exception is raised.
  414. //
  415. RpcTryExcept {
  416. //
  417. // Call RPC version of the API.
  418. //
  419. Status = NetrServerPasswordSet2(
  420. PrimaryName,
  421. AccountName,
  422. AccountType,
  423. ComputerName,
  424. Authenticator,
  425. ReturnAuthenticator,
  426. ClearNewPassword );
  427. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  428. Status = I_RpcMapWin32Status(RpcExceptionCode());
  429. } RpcEndExcept;
  430. IF_DEBUG( LOGON ) {
  431. NetpKdPrint(("I_NetServerPasswordSet2 rc = %lu 0x%lx\n",
  432. Status, Status));
  433. }
  434. return Status;
  435. }
  436. NTSTATUS
  437. I_NetDatabaseDeltas (
  438. IN LPWSTR PrimaryName,
  439. IN LPWSTR ComputerName,
  440. IN PNETLOGON_AUTHENTICATOR Authenticator,
  441. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  442. IN DWORD DatabaseID,
  443. IN OUT PNLPR_MODIFIED_COUNT DomainModifiedCount,
  444. OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray,
  445. IN DWORD PreferredMaximumLength
  446. )
  447. /*++
  448. Routine Description:
  449. This function is used by a SAM BDC or SAM member server to request
  450. SAM-style account delta information from a SAM PDC. This function
  451. can only be called by a server which has previously authenticated
  452. with the PDC by calling I_NetServerAuthenticate. This function uses
  453. RPC to contact the Netlogon service on the PDC.
  454. This function returns a list of deltas. A delta describes an
  455. individual domain, user or group and all of the field values for that
  456. object. The PDC maintains a list of deltas not including all of the
  457. field values for that object. Rather, the PDC retrieves the field
  458. values from SAM and returns those values from this call. The PDC
  459. optimizes the data returned on this call by only returning the field
  460. values for a particular object once on a single invocation of this
  461. function. This optimizes the typical case where multiple deltas
  462. exist for a single object (e.g., an application modified many fields
  463. of the same user during a short period of time using different calls
  464. to the SAM service).
  465. Arguments:
  466. PrimaryName -- Name of the PDC to retrieve the deltas from.
  467. ComputerName -- Name of the BDC or member server making the call.
  468. Authenticator -- supplied by the server.
  469. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  470. DomainModifiedCount -- Specifies the DomainModifiedCount of the
  471. last delta retrieved by the server. Returns the
  472. DomainModifiedCount of the last delta returned from the PDC
  473. on this call.
  474. DeltaArray -- Receives a pointer to a buffer where the information
  475. is placed. The information returned is an array of
  476. NETLOGON_DELTA_ENUM structures.
  477. PreferredMaximumLength - Preferred maximum length of returned
  478. data (in 8-bit bytes). This is not a hard upper limit, but
  479. serves as a guide to the server. Due to data conversion
  480. between systems with different natural data sizes, the actual
  481. amount of data returned may be greater than this value.
  482. Return Value:
  483. STATUS_SUCCESS -- The function completed successfully.
  484. STATUS_SYNCHRONIZATION_REQUIRED -- The replicant is totally out of sync and
  485. should call I_NetDatabaseSync to do a full synchronization with
  486. the PDC.
  487. STATUS_MORE_ENTRIES -- The replicant should call again to get more
  488. data.
  489. STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
  490. the PDC.
  491. --*/
  492. {
  493. NTSTATUS Status = 0;
  494. //
  495. // Do the RPC call with an exception handler since RPC will raise an
  496. // exception if anything fails. It is up to us to figure out what
  497. // to do once the exception is raised.
  498. //
  499. RpcTryExcept {
  500. //
  501. // Call RPC version of the API.
  502. //
  503. *DeltaArray = NULL; // Force RPC to allocate
  504. Status = NetrDatabaseDeltas(
  505. PrimaryName,
  506. ComputerName,
  507. Authenticator,
  508. ReturnAuthenticator,
  509. DatabaseID,
  510. DomainModifiedCount,
  511. DeltaArray,
  512. PreferredMaximumLength );
  513. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  514. Status = I_RpcMapWin32Status(RpcExceptionCode());
  515. } RpcEndExcept;
  516. NetpKdPrint(("I_NetDatabaseDeltas rc = %lu 0x%lx\n", Status, Status));
  517. return Status;
  518. }
  519. NTSTATUS
  520. I_NetDatabaseSync (
  521. IN LPWSTR PrimaryName,
  522. IN LPWSTR ComputerName,
  523. IN PNETLOGON_AUTHENTICATOR Authenticator,
  524. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  525. IN DWORD DatabaseID,
  526. IN OUT PULONG SamSyncContext,
  527. OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray,
  528. IN DWORD PreferredMaximumLength
  529. )
  530. /*++
  531. Routine Description:
  532. This function is used by a SAM BDC or SAM member server to request
  533. the entire SAM database from a SAM PDC in SAM-style format. This
  534. function can only be called by a server which has previously
  535. authenticated with the PDC by calling I_NetServerAuthenticate. This
  536. function uses RPC to contact the Netlogon service on the PDC.
  537. This function uses the find-first find-next model to return portions
  538. of the SAM database at a time. The SAM database is returned as a
  539. list of deltas like those returned from I_NetDatabaseDeltas. The
  540. following deltas are returned for each domain:
  541. * One AddOrChangeDomain delta, followed by
  542. * One AddOrChangeGroup delta for each group, followed by,
  543. * One AddOrChangeUser delta for each user, followed by
  544. * One ChangeGroupMembership delta for each group
  545. Arguments:
  546. PrimaryName -- Name of the PDC to retrieve the deltas from.
  547. ComputerName -- Name of the BDC or member server making the call.
  548. Authenticator -- supplied by the server.
  549. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  550. SamSyncContext -- Specifies context needed to continue the
  551. operation. The caller should treat this as an opaque
  552. value. The value should be zero before the first call.
  553. DeltaArray -- Receives a pointer to a buffer where the information
  554. is placed. The information returned is an array of
  555. NETLOGON_DELTA_ENUM structures.
  556. PreferredMaximumLength - Preferred maximum length of returned
  557. data (in 8-bit bytes). This is not a hard upper limit, but
  558. serves as a guide to the server. Due to data conversion
  559. between systems with different natural data sizes, the actual
  560. amount of data returned may be greater than this value.
  561. Return Value:
  562. STATUS_SUCCESS -- The function completed successfully.
  563. STATUS_SYNCHRONIZATION_REQUIRED -- The replicant is totally out of sync and
  564. should call I_NetDatabaseSync to do a full synchronization with
  565. the PDC.
  566. STATUS_MORE_ENTRIES -- The replicant should call again to get more
  567. data.
  568. STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
  569. the PDC.
  570. --*/
  571. {
  572. NTSTATUS Status = 0;
  573. //
  574. // Do the RPC call with an exception handler since RPC will raise an
  575. // exception if anything fails. It is up to us to figure out what
  576. // to do once the exception is raised.
  577. //
  578. RpcTryExcept {
  579. //
  580. // Call RPC version of the API.
  581. //
  582. *DeltaArray = NULL; // Force RPC to allocate
  583. Status = NetrDatabaseSync(
  584. PrimaryName,
  585. ComputerName,
  586. Authenticator,
  587. ReturnAuthenticator,
  588. DatabaseID,
  589. SamSyncContext,
  590. DeltaArray,
  591. PreferredMaximumLength );
  592. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  593. Status = I_RpcMapWin32Status(RpcExceptionCode());
  594. } RpcEndExcept;
  595. IF_DEBUG( LOGON ) {
  596. NetpKdPrint(("I_NetDatabaseSync rc = %lu 0x%lx\n", Status, Status));
  597. }
  598. return Status;
  599. }
  600. NTSTATUS
  601. I_NetDatabaseSync2 (
  602. IN LPWSTR PrimaryName,
  603. IN LPWSTR ComputerName,
  604. IN PNETLOGON_AUTHENTICATOR Authenticator,
  605. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  606. IN DWORD DatabaseID,
  607. IN SYNC_STATE RestartState,
  608. IN OUT PULONG SamSyncContext,
  609. OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray,
  610. IN DWORD PreferredMaximumLength
  611. )
  612. /*++
  613. Routine Description:
  614. This function is used by a SAM BDC or SAM member server to request
  615. the entire SAM database from a SAM PDC in SAM-style format. This
  616. function can only be called by a server which has previously
  617. authenticated with the PDC by calling I_NetServerAuthenticate. This
  618. function uses RPC to contact the Netlogon service on the PDC.
  619. This function uses the find-first find-next model to return portions
  620. of the SAM database at a time. The SAM database is returned as a
  621. list of deltas like those returned from I_NetDatabaseDeltas. The
  622. following deltas are returned for each domain:
  623. * One AddOrChangeDomain delta, followed by
  624. * One AddOrChangeGroup delta for each group, followed by,
  625. * One AddOrChangeUser delta for each user, followed by
  626. * One ChangeGroupMembership delta for each group
  627. Arguments:
  628. PrimaryName -- Name of the PDC to retrieve the deltas from.
  629. ComputerName -- Name of the BDC or member server making the call.
  630. Authenticator -- supplied by the server.
  631. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  632. RestartState -- Specifies whether this is a restart of the full sync and how
  633. to interpret SyncContext. This value should be NormalState unless this
  634. is the restart of a full sync.
  635. However, if the caller is continuing a full sync after a reboot,
  636. the following values are used:
  637. GroupState - SyncContext is the global group rid to continue with.
  638. UserState - SyncContext is the user rid to continue with
  639. GroupMemberState - SyncContext is the global group rid to continue with
  640. AliasState - SyncContext should be zero to restart at first alias
  641. AliasMemberState - SyncContext should be zero to restart at first alias
  642. One cannot continue the LSA database in this way.
  643. SamSyncContext -- Specifies context needed to continue the
  644. operation. The caller should treat this as an opaque
  645. value. The value should be zero before the first call.
  646. DeltaArray -- Receives a pointer to a buffer where the information
  647. is placed. The information returned is an array of
  648. NETLOGON_DELTA_ENUM structures.
  649. PreferredMaximumLength - Preferred maximum length of returned
  650. data (in 8-bit bytes). This is not a hard upper limit, but
  651. serves as a guide to the server. Due to data conversion
  652. between systems with different natural data sizes, the actual
  653. amount of data returned may be greater than this value.
  654. Return Value:
  655. STATUS_SUCCESS -- The function completed successfully.
  656. STATUS_SYNCHRONIZATION_REQUIRED -- The replicant is totally out of sync and
  657. should call I_NetDatabaseSync to do a full synchronization with
  658. the PDC.
  659. STATUS_MORE_ENTRIES -- The replicant should call again to get more
  660. data.
  661. STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
  662. the PDC.
  663. --*/
  664. {
  665. NTSTATUS Status = 0;
  666. //
  667. // Do the RPC call with an exception handler since RPC will raise an
  668. // exception if anything fails. It is up to us to figure out what
  669. // to do once the exception is raised.
  670. //
  671. RpcTryExcept {
  672. //
  673. // Call RPC version of the API.
  674. //
  675. *DeltaArray = NULL; // Force RPC to allocate
  676. Status = NetrDatabaseSync2(
  677. PrimaryName,
  678. ComputerName,
  679. Authenticator,
  680. ReturnAuthenticator,
  681. DatabaseID,
  682. RestartState,
  683. SamSyncContext,
  684. DeltaArray,
  685. PreferredMaximumLength );
  686. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  687. Status = I_RpcMapWin32Status(RpcExceptionCode());
  688. } RpcEndExcept;
  689. IF_DEBUG( LOGON ) {
  690. NetpKdPrint(("I_NetDatabaseSync rc = %lu 0x%lx\n", Status, Status));
  691. }
  692. return Status;
  693. }
  694. NET_API_STATUS NET_API_FUNCTION
  695. I_NetAccountDeltas (
  696. IN LPWSTR PrimaryName,
  697. IN LPWSTR ComputerName,
  698. IN PNETLOGON_AUTHENTICATOR Authenticator,
  699. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  700. IN PUAS_INFO_0 RecordId,
  701. IN DWORD Count,
  702. IN DWORD Level,
  703. OUT LPBYTE Buffer,
  704. IN DWORD BufferSize,
  705. OUT PULONG CountReturned,
  706. OUT PULONG TotalEntries,
  707. OUT PUAS_INFO_0 NextRecordId
  708. )
  709. /*++
  710. Routine Description:
  711. This function is used by a UAS BDC or UAS member server to request
  712. UAS-style account change information. This function can only be
  713. called by a server which has previously authenticated with the PDC by
  714. calling I_NetServerAuthenticate.
  715. This function is only called by the XACT server upon receipt of a
  716. I_NetAccountDeltas XACT SMB from a UAS BDC or a UAS member server.
  717. As such, many of the parameters are opaque since the XACT server
  718. doesn't need to interpret any of that data. This function uses RPC
  719. to contact the Netlogon service.
  720. The LanMan 3.0 SSI Functional Specification describes the operation
  721. of this function.
  722. Arguments:
  723. PrimaryName -- Must be NULL to indicate this call is a local call
  724. being made on behalf of a UAS server by the XACT server.
  725. ComputerName -- Name of the BDC or member making the call.
  726. Authenticator -- supplied by the server.
  727. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  728. RecordId -- Supplies an opaque buffer indicating the last record
  729. received from a previous call to this function.
  730. Count -- Supplies the number of Delta records requested.
  731. Level -- Reserved. Must be zero.
  732. Buffer -- Returns opaque data representing the information to be
  733. returned.
  734. BufferSize -- Size of buffer in bytes.
  735. CountReturned -- Returns the number of records returned in buffer.
  736. TotalEntries -- Returns the total number of records available.
  737. NextRecordId -- Returns an opaque buffer identifying the last
  738. record received by this function.
  739. Return Value:
  740. Status code
  741. --*/
  742. {
  743. NET_API_STATUS NetStatus;
  744. //
  745. // Do the RPC call with an exception handler since RPC will raise an
  746. // exception if anything fails. It is up to us to figure out what
  747. // to do once the exception is raised.
  748. //
  749. RpcTryExcept {
  750. //
  751. // Call RPC version of the API.
  752. //
  753. NetStatus = NetrAccountDeltas (
  754. PrimaryName,
  755. ComputerName,
  756. Authenticator,
  757. ReturnAuthenticator,
  758. RecordId,
  759. Count,
  760. Level,
  761. Buffer,
  762. BufferSize,
  763. CountReturned,
  764. TotalEntries,
  765. NextRecordId );
  766. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  767. NetStatus = RpcExceptionCode();
  768. } RpcEndExcept;
  769. IF_DEBUG( LOGON ) {
  770. NetpKdPrint(("I_NetAccountDeltas rc = %lu 0x%lx\n",
  771. NetStatus, NetStatus));
  772. }
  773. return NetStatus;
  774. }
  775. NET_API_STATUS NET_API_FUNCTION
  776. I_NetAccountSync (
  777. IN LPWSTR PrimaryName,
  778. IN LPWSTR ComputerName,
  779. IN PNETLOGON_AUTHENTICATOR Authenticator,
  780. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  781. IN DWORD Reference,
  782. IN DWORD Level,
  783. OUT LPBYTE Buffer,
  784. IN DWORD BufferSize,
  785. OUT PULONG CountReturned,
  786. OUT PULONG TotalEntries,
  787. OUT PULONG NextReference,
  788. OUT PUAS_INFO_0 LastRecordId
  789. )
  790. /*++
  791. Routine Description:
  792. This function is used by a UAS BDC or UAS member server to request
  793. the entire user accounts database. This function can only be called
  794. by a server which has previously authenticated with the PDC by
  795. calling I_NetServerAuthenticate.
  796. This function is only called by the XACT server upon receipt of a
  797. I_NetAccountSync XACT SMB from a UAS BDC or a UAS member server. As
  798. such, many of the parameters are opaque since the XACT server doesn't
  799. need to interpret any of that data. This function uses RPC to
  800. contact the Netlogon service.
  801. The LanMan 3.0 SSI Functional Specification describes the operation
  802. of this function.
  803. "Reference" and "NextReference" are treated as below.
  804. 1. "Reference" should hold either 0 or value of "NextReference"
  805. from previous call to this API.
  806. 2. Send the modals and ALL group records in the first call. The API
  807. expects the bufffer to be large enough to hold this info (worst
  808. case size would be
  809. MAXGROUP * (sizeof(struct group_info_1) + MAXCOMMENTSZ)
  810. + sizeof(struct user_modals_info_0)
  811. which, for now, will be 256 * (26 + 49) + 16 = 19216 bytes
  812. Arguments:
  813. PrimaryName -- Must be NULL to indicate this call is a local call
  814. being made on behalf of a UAS server by the XACT server.
  815. ComputerName -- Name of the BDC or member making the call.
  816. Authenticator -- supplied by the server.
  817. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  818. Reference -- Supplies find-first find-next handle returned by the
  819. previous call to this function or 0 if it is the first call.
  820. Level -- Reserved. Must be zero.
  821. Buffer -- Returns opaque data representing the information to be
  822. returned.
  823. BufferLen -- Length of buffer in bytes.
  824. CountReturned -- Returns the number of records returned in buffer.
  825. TotalEntries -- Returns the total number of records available.
  826. NextReference -- Returns a find-first find-next handle to be
  827. provided on the next call.
  828. LastRecordId -- Returns an opaque buffer identifying the last
  829. record received by this function.
  830. Return Value:
  831. Status code.
  832. --*/
  833. {
  834. NET_API_STATUS NetStatus;
  835. //
  836. // Do the RPC call with an exception handler since RPC will raise an
  837. // exception if anything fails. It is up to us to figure out what
  838. // to do once the exception is raised.
  839. //
  840. RpcTryExcept {
  841. //
  842. // Call RPC version of the API.
  843. //
  844. NetStatus = NetrAccountSync (
  845. PrimaryName,
  846. ComputerName,
  847. Authenticator,
  848. ReturnAuthenticator,
  849. Reference,
  850. Level,
  851. Buffer,
  852. BufferSize,
  853. CountReturned,
  854. TotalEntries,
  855. NextReference,
  856. LastRecordId );
  857. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  858. NetStatus = RpcExceptionCode();
  859. } RpcEndExcept;
  860. IF_DEBUG( LOGON ) {
  861. NetpKdPrint(("I_NetAccountSync rc = %lu 0x%lx\n",
  862. NetStatus, NetStatus));
  863. }
  864. return NetStatus;
  865. }
  866. NET_API_STATUS NET_API_FUNCTION
  867. I_NetLogonControl(
  868. IN LPCWSTR ServerName OPTIONAL,
  869. IN DWORD FunctionCode,
  870. IN DWORD QueryLevel,
  871. OUT LPBYTE *QueryInformation
  872. )
  873. /*++
  874. Routine Description:
  875. This function controls various aspects of the Netlogon service. It
  876. can be used to request that a BDC ensure that its copy of the SAM
  877. database is brought up to date. It can, also, be used to determine
  878. if a BDC currently has a secure channel open to the PDC.
  879. Only an Admin, Account Operator or Server Operator may call this
  880. function.
  881. Arguments:
  882. ServerName - The name of the remote server.
  883. FunctionCode - Defines the operation to be performed. The valid
  884. values are:
  885. FunctionCode Values
  886. NETLOGON_CONTROL_QUERY - No operation. Merely returns the
  887. information requested.
  888. NETLOGON_CONTROL_REPLICATE: Forces the SAM database on a BDC
  889. to be brought in sync with the copy on the PDC. This
  890. operation does NOT imply a full synchronize. The
  891. Netlogon service will merely replicate any outstanding
  892. differences if possible.
  893. NETLOGON_CONTROL_SYNCHRONIZE: Forces a BDC to get a
  894. completely new copy of the SAM database from the PDC.
  895. This operation will perform a full synchronize.
  896. NETLOGON_CONTROL_PDC_REPLICATE: Forces a PDC to ask each BDC
  897. to replicate now.
  898. QueryLevel - Indicates what information should be returned from
  899. the Netlogon Service. Must be 1.
  900. QueryInformation - Returns a pointer to a buffer which contains the
  901. requested information. The buffer must be freed using
  902. NetApiBufferFree.
  903. Return Value:
  904. NERR_Success: the operation was successful
  905. ERROR_NOT_SUPPORTED: Function code is not valid on the specified
  906. server. (e.g. NETLOGON_CONTROL_REPLICATE was passed to a PDC).
  907. --*/
  908. {
  909. NET_API_STATUS NetStatus;
  910. NETLOGON_CONTROL_QUERY_INFORMATION RpcQueryInformation;
  911. //
  912. // Do the RPC call with an exception handler since RPC will raise an
  913. // exception if anything fails. It is up to us to figure out what
  914. // to do once the exception is raised.
  915. //
  916. RpcTryExcept {
  917. //
  918. // Call RPC version of the API.
  919. //
  920. RpcQueryInformation.NetlogonInfo1 = NULL; // Force RPC to allocate
  921. NetStatus = NetrLogonControl (
  922. (LPWSTR) ServerName OPTIONAL,
  923. FunctionCode,
  924. QueryLevel,
  925. &RpcQueryInformation );
  926. *QueryInformation = (LPBYTE) RpcQueryInformation.NetlogonInfo1;
  927. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  928. NetStatus = RpcExceptionCode();
  929. } RpcEndExcept;
  930. IF_DEBUG( LOGON ) {
  931. NetpKdPrint(("I_NetLogonControl rc = %lu 0x%lx\n",
  932. NetStatus, NetStatus));
  933. }
  934. return NetStatus;
  935. }
  936. NET_API_STATUS NET_API_FUNCTION
  937. I_NetLogonControl2(
  938. IN LPCWSTR ServerName OPTIONAL,
  939. IN DWORD FunctionCode,
  940. IN DWORD QueryLevel,
  941. IN LPBYTE InputData,
  942. OUT LPBYTE *QueryInformation
  943. )
  944. /*++
  945. Routine Description:
  946. This is similar to the I_NetLogonControl function but it accepts
  947. more generic input data according to the function code specified.
  948. This function controls various aspects of the Netlogon service. It
  949. can be used to request that a BDC ensure that its copy of the SAM
  950. database is brought up to date. It can, also, be used to determine
  951. if a BDC currently has a secure channel open to the PDC.
  952. Only an Admin, Account Operator or Server Operator may call this
  953. function.
  954. Arguments:
  955. ServerName - The name of the remote server.
  956. FunctionCode - Defines the operation to be performed. The valid
  957. values are:
  958. FunctionCode Values
  959. NETLOGON_CONTROL_QUERY - No operation. Merely returns the
  960. information requested.
  961. NETLOGON_CONTROL_REPLICATE: Forces the SAM database on a BDC
  962. to be brought in sync with the copy on the PDC. This
  963. operation does NOT imply a full synchronize. The
  964. Netlogon service will merely replicate any outstanding
  965. differences if possible.
  966. NETLOGON_CONTROL_SYNCHRONIZE: Forces a BDC to get a
  967. completely new copy of the SAM database from the PDC.
  968. This operation will perform a full synchronize.
  969. NETLOGON_CONTROL_PDC_REPLICATE: Forces a PDC to ask each BDC
  970. to replicate now.
  971. NETLOGON_CONTROL_REDISCOVER: Forces a DC to rediscover the
  972. specified trusted domain DC.
  973. NETLOGON_CONTROL_TC_QUERY: Query the status of the specified
  974. trusted domain secure channel.
  975. NETLOGON_CONTROL_TC_VERIFY: Verify the status of the specified
  976. trusted domain secure channel. If the current status is
  977. success (which means that the last operation performed
  978. over the secure channel was successful), ping the DC. If the
  979. current status is not success or the ping fails, rediscover
  980. a new DC.
  981. NETLOGON_CONTROL_CHANGE_PASSWORD: Forces a password change on
  982. a secure channel to a trusted domain.
  983. NETLOGON_CONTROL_FORCE_DNS_REG: Forces the DC to re-register all
  984. of its DNS records. QueryLevel parameter must be 1.
  985. NETLOGON_CONTROL_QUERY_DNS_REG: Query the status of DNS updates
  986. performed by netlogon. If there was any DNS registration or
  987. deregistration error for any of the records as they were
  988. updated last time, the query result will be negative;
  989. otherwise the query result will be positive.
  990. QueryLevel parameter must be 1.
  991. QueryLevel - Indicates what information should be returned from
  992. the Netlogon Service.
  993. InputData - According to the function code specified this parameter
  994. will carry input data. NETLOGON_CONTROL_REDISCOVER and
  995. NETLOGON_CONTROL_TC_QUERY function code specify the trusted
  996. domain name (LPWSTR type) here.
  997. QueryInformation - Returns a pointer to a buffer which contains the
  998. requested information. The buffer must be freed using
  999. NetApiBufferFree.
  1000. Return Value:
  1001. NERR_Success: the operation was successful
  1002. ERROR_NOT_SUPPORTED: Function code is not valid on the specified
  1003. server. (e.g. NETLOGON_CONTROL_REPLICATE was passed to a PDC).
  1004. --*/
  1005. {
  1006. NET_API_STATUS NetStatus;
  1007. NETLOGON_CONTROL_QUERY_INFORMATION RpcQueryInformation;
  1008. //
  1009. // Do the RPC call with an exception handler since RPC will raise an
  1010. // exception if anything fails. It is up to us to figure out what
  1011. // to do once the exception is raised.
  1012. //
  1013. RpcTryExcept {
  1014. //
  1015. // Call RPC version of the API.
  1016. //
  1017. // Use new Control2Ex if either QueryLevel or FunctionCode is new
  1018. //
  1019. RpcQueryInformation.NetlogonInfo1 = NULL; // Force RPC to allocate
  1020. switch ( FunctionCode ) {
  1021. case NETLOGON_CONTROL_QUERY:
  1022. case NETLOGON_CONTROL_REPLICATE:
  1023. case NETLOGON_CONTROL_SYNCHRONIZE:
  1024. case NETLOGON_CONTROL_PDC_REPLICATE:
  1025. case NETLOGON_CONTROL_REDISCOVER:
  1026. case NETLOGON_CONTROL_TC_QUERY:
  1027. case NETLOGON_CONTROL_TRANSPORT_NOTIFY:
  1028. case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
  1029. case NETLOGON_CONTROL_TRUNCATE_LOG:
  1030. case NETLOGON_CONTROL_SET_DBFLAG:
  1031. case NETLOGON_CONTROL_BREAKPOINT:
  1032. if ( QueryLevel >= 1 && QueryLevel <= 3 ) {
  1033. NetStatus = NetrLogonControl2 (
  1034. (LPWSTR) ServerName OPTIONAL,
  1035. FunctionCode,
  1036. QueryLevel,
  1037. (PNETLOGON_CONTROL_DATA_INFORMATION)InputData,
  1038. &RpcQueryInformation );
  1039. } else if ( QueryLevel == 4 ) {
  1040. NetStatus = NetrLogonControl2Ex (
  1041. (LPWSTR) ServerName OPTIONAL,
  1042. FunctionCode,
  1043. QueryLevel,
  1044. (PNETLOGON_CONTROL_DATA_INFORMATION)InputData,
  1045. &RpcQueryInformation );
  1046. } else {
  1047. NetStatus = ERROR_INVALID_LEVEL;
  1048. }
  1049. break;
  1050. case NETLOGON_CONTROL_FIND_USER:
  1051. case NETLOGON_CONTROL_UNLOAD_NETLOGON_DLL:
  1052. case NETLOGON_CONTROL_CHANGE_PASSWORD:
  1053. case NETLOGON_CONTROL_TC_VERIFY:
  1054. case NETLOGON_CONTROL_FORCE_DNS_REG:
  1055. case NETLOGON_CONTROL_QUERY_DNS_REG:
  1056. if ( QueryLevel >= 1 && QueryLevel <= 4 ) {
  1057. NetStatus = NetrLogonControl2Ex (
  1058. (LPWSTR) ServerName OPTIONAL,
  1059. FunctionCode,
  1060. QueryLevel,
  1061. (PNETLOGON_CONTROL_DATA_INFORMATION)InputData,
  1062. &RpcQueryInformation );
  1063. } else {
  1064. NetStatus = ERROR_INVALID_LEVEL;
  1065. }
  1066. break;
  1067. default:
  1068. NetStatus = ERROR_INVALID_LEVEL;
  1069. }
  1070. *QueryInformation = (LPBYTE) RpcQueryInformation.NetlogonInfo1;
  1071. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1072. NetStatus = RpcExceptionCode();
  1073. } RpcEndExcept;
  1074. IF_DEBUG( LOGON ) {
  1075. NetpKdPrint(("I_NetLogonControl rc = %lu 0x%lx\n",
  1076. NetStatus, NetStatus));
  1077. }
  1078. return NetStatus;
  1079. }
  1080. NTSTATUS
  1081. I_NetDatabaseRedo(
  1082. IN LPWSTR PrimaryName,
  1083. IN LPWSTR ComputerName,
  1084. IN PNETLOGON_AUTHENTICATOR Authenticator,
  1085. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  1086. IN LPBYTE ChangeLogEntry,
  1087. IN DWORD ChangeLogEntrySize,
  1088. OUT PNETLOGON_DELTA_ENUM_ARRAY *DeltaArray
  1089. )
  1090. /*++
  1091. Routine Description:
  1092. This function is used by a SAM BDC to request infomation about a single
  1093. account. This function can only be called by a server which has previously
  1094. authenticated with the PDC by calling I_NetServerAuthenticate. This
  1095. function uses RPC to contact the Netlogon service on the PDC.
  1096. Arguments:
  1097. PrimaryName -- Name of the PDC to retrieve the delta from.
  1098. ComputerName -- Name of the BDC making the call.
  1099. Authenticator -- supplied by the server.
  1100. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  1101. ChangeLogEntry -- A description of the account to be queried.
  1102. ChangeLogEntrySize -- Size (in bytes) of the ChangeLogEntry.
  1103. DeltaArray -- Receives a pointer to a buffer where the information
  1104. is placed. The information returned is an array of
  1105. NETLOGON_DELTA_ENUM structures.
  1106. Return Value:
  1107. STATUS_SUCCESS -- The function completed successfully.
  1108. STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
  1109. the PDC.
  1110. --*/
  1111. {
  1112. NTSTATUS Status = 0;
  1113. //
  1114. // Do the RPC call with an exception handler since RPC will raise an
  1115. // exception if anything fails. It is up to us to figure out what
  1116. // to do once the exception is raised.
  1117. //
  1118. RpcTryExcept {
  1119. //
  1120. // Call RPC version of the API.
  1121. //
  1122. *DeltaArray = NULL; // Force RPC to allocate
  1123. Status = NetrDatabaseRedo(
  1124. PrimaryName,
  1125. ComputerName,
  1126. Authenticator,
  1127. ReturnAuthenticator,
  1128. ChangeLogEntry,
  1129. ChangeLogEntrySize,
  1130. DeltaArray );
  1131. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1132. Status = I_RpcMapWin32Status(RpcExceptionCode());
  1133. } RpcEndExcept;
  1134. IF_DEBUG( LOGON ) {
  1135. NetpKdPrint(("I_NetDatabaseSync rc = %lu 0x%lx\n", Status, Status));
  1136. }
  1137. return Status;
  1138. }
  1139. NTSTATUS
  1140. NetEnumerateTrustedDomains (
  1141. IN LPWSTR ServerName OPTIONAL,
  1142. OUT LPWSTR *DomainNames
  1143. )
  1144. /*++
  1145. Routine Description:
  1146. This API returns the names of the domains trusted by the domain ServerName is a member of.
  1147. ServerName must be an NT workstation or NT non-DC server.
  1148. The returned list does not include the domain ServerName is directly a member of.
  1149. Netlogon implements this API by calling LsaEnumerateTrustedDomains on a DC in the
  1150. domain ServerName is a member of. However, Netlogon returns cached information if
  1151. it has been less than 5 minutes since the last call was made or if no DC is available.
  1152. Netlogon's cache of Trusted domain names is maintained in the registry across reboots.
  1153. As such, the list is available upon boot even if no DC is available.
  1154. Arguments:
  1155. ServerName - name of remote server (null for local). ServerName must be an NT workstation
  1156. or NT non-DC server.
  1157. DomainNames - Returns an allocated buffer containing the list of trusted domains in
  1158. MULTI-SZ format (i.e., each string is terminated by a zero character, the next string
  1159. immediately follows, the sequence is terminated by zero length domain name). The
  1160. buffer should be freed using NetApiBufferFree.
  1161. Return Value:
  1162. ERROR_SUCCESS - Success.
  1163. STATUS_NOT_SUPPORTED - ServerName is not an NT workstation or NT non-DC server.
  1164. STATUS_NO_LOGON_SERVERS - No DC could be found and no cached information is available.
  1165. STATUS_NO_TRUST_LSA_SECRET - The client side of the trust relationship is
  1166. broken and no cached information is available.
  1167. STATUS_NO_TRUST_SAM_ACCOUNT - The server side of the trust relationship is
  1168. broken or the password is broken and no cached information is available.
  1169. --*/
  1170. {
  1171. NTSTATUS Status = 0;
  1172. DOMAIN_NAME_BUFFER DomainNameBuffer;
  1173. //
  1174. // Do the RPC call with an exception handler since RPC will raise an
  1175. // exception if anything fails. It is up to us to figure out what
  1176. // to do once the exception is raised.
  1177. //
  1178. RpcTryExcept {
  1179. //
  1180. // Call RPC version of the API.
  1181. //
  1182. DomainNameBuffer.DomainNameByteCount = 0;
  1183. DomainNameBuffer.DomainNames = NULL; // Force RPC to allocate
  1184. Status = NetrEnumerateTrustedDomains(
  1185. ServerName,
  1186. &DomainNameBuffer );
  1187. if ( NT_SUCCESS(Status) ) {
  1188. *DomainNames = (LPWSTR) DomainNameBuffer.DomainNames;
  1189. }
  1190. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1191. Status = I_RpcMapWin32Status(RpcExceptionCode());
  1192. } RpcEndExcept;
  1193. IF_DEBUG( LOGON ) {
  1194. NetpKdPrint(("NetEnumerateDomainNames rc = %lu 0x%lx\n", Status, Status));
  1195. }
  1196. return Status;
  1197. }
  1198. NET_API_STATUS NET_API_FUNCTION
  1199. NlpEnumerateNt4DomainTrusts (
  1200. IN LPWSTR ServerName OPTIONAL,
  1201. IN ULONG Flags,
  1202. OUT PDS_DOMAIN_TRUSTSW *Domains,
  1203. OUT PULONG DomainCount
  1204. )
  1205. /*++
  1206. Routine Description:
  1207. This API returns the names of the domains trusted by the domain ServerName
  1208. is a member of. ServerName is an NT4 machine.
  1209. Netlogon's cache of Trusted domain names is maintained in a file across reboots.
  1210. As such, the list is available upon boot even if no DC is available.
  1211. Arguments:
  1212. ServerName - name of remote server (null for local).
  1213. Flags - Specifies attributes of trusts which should be returned. These are the flags
  1214. of the DS_DOMAIN_TRUSTSW strusture. If a trust entry has any of the bits specified
  1215. in Flags set, it will be returned.
  1216. Domains - Returns an array of trusted domains.
  1217. Buffer must be free using NetApiBufferFree().
  1218. DomainCount - Returns a count of the number elements in the Domains array.
  1219. Return Value:
  1220. NO_ERROR - Success.
  1221. ERROR_NO_LOGON_SERVERS - No DC could be found and no cached information is available.
  1222. ERROR_NO_TRUST_LSA_SECRET - The client side of the trust relationship is
  1223. broken and no cached information is available.
  1224. ERROR_NO_TRUST_SAM_ACCOUNT - The server side of the trust relationship is
  1225. broken or the password is broken and no cached information is available.
  1226. ERROR_INVALID_FLAGS - The Flags parameter has invalid bit(s) set.
  1227. ERROR_NOT_SUPPORTED - The server specified is not capable of returning the domain
  1228. trusts requested.
  1229. --*/
  1230. {
  1231. NET_API_STATUS NetStatus = NO_ERROR;
  1232. NTSTATUS Status;
  1233. BUFFER_DESCRIPTOR BufferDescriptor;
  1234. ULONG LocalDomainCount;
  1235. LSA_HANDLE LsaHandle = NULL;
  1236. PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo = NULL;
  1237. LPWSTR DomainNames = NULL;
  1238. PDS_DOMAIN_TRUSTSW TrustedDomain;
  1239. ULONG DummySize;
  1240. //
  1241. // Initialization
  1242. //
  1243. BufferDescriptor.Buffer = NULL;
  1244. LocalDomainCount = 0;
  1245. *Domains = NULL;
  1246. *DomainCount = 0;
  1247. //
  1248. // Validate Flags
  1249. //
  1250. if ( (Flags & DS_DOMAIN_VALID_FLAGS) == 0 ||
  1251. (Flags & ~DS_DOMAIN_VALID_FLAGS) != 0 ) {
  1252. NetStatus = ERROR_INVALID_FLAGS;
  1253. goto Cleanup;
  1254. }
  1255. //
  1256. // This routine uses old APIs which are not capable of returning
  1257. // directly trusting domains. So error out if such trusts are requested.
  1258. //
  1259. if ( (Flags & DS_DOMAIN_DIRECT_INBOUND) != 0 ) {
  1260. NetStatus = ERROR_NOT_SUPPORTED;
  1261. goto Cleanup;
  1262. }
  1263. //
  1264. // NetEnumerateTrustedDomains targeted at NT4 server returns directly
  1265. // trusted domains only. So call it only if such domains are requested.
  1266. // Nothing will be returned for domains in forest if such were requested.
  1267. //
  1268. if ( Flags & DS_DOMAIN_DIRECT_OUTBOUND ) {
  1269. LPTSTR_ARRAY TStrArray;
  1270. Status = NetEnumerateTrustedDomains (
  1271. ServerName,
  1272. &DomainNames );
  1273. if (!NT_SUCCESS(Status)) {
  1274. NetStatus = NetpNtStatusToApiStatus( Status );
  1275. if ( NetStatus == RPC_S_PROCNUM_OUT_OF_RANGE ) {
  1276. NetStatus = ERROR_NOT_SUPPORTED;
  1277. }
  1278. goto Cleanup;
  1279. }
  1280. //
  1281. // Handle each trusted domain.
  1282. //
  1283. TStrArray = (LPTSTR_ARRAY) DomainNames;
  1284. while ( !NetpIsTStrArrayEmpty(TStrArray) ) {
  1285. UNICODE_STRING CurrentNetbiosDomainName;
  1286. //
  1287. // Add the domain to the list
  1288. //
  1289. RtlInitUnicodeString( &CurrentNetbiosDomainName, TStrArray );
  1290. Status = NlAllocateForestTrustListEntry (
  1291. &BufferDescriptor,
  1292. &CurrentNetbiosDomainName,
  1293. NULL, // No DNS domain name
  1294. DS_DOMAIN_DIRECT_OUTBOUND,
  1295. 0, // No ParentIndex
  1296. TRUST_TYPE_DOWNLEVEL,
  1297. 0, // No TrustAttributes
  1298. NULL, // No Domain Sid
  1299. NULL, // No DomainGuid
  1300. &DummySize,
  1301. &TrustedDomain );
  1302. if ( !NT_SUCCESS(Status) ) {
  1303. NetStatus = NetpNtStatusToApiStatus( Status );
  1304. goto Cleanup;
  1305. }
  1306. //
  1307. // Account for the newly allocated entry
  1308. //
  1309. LocalDomainCount ++;
  1310. //
  1311. // Move to the next entry
  1312. //
  1313. TStrArray = NetpNextTStrArrayEntry( TStrArray );
  1314. }
  1315. }
  1316. //
  1317. // NetEnumerateDomainTrusts doesn't return primary domain
  1318. // in the list of trusted domains. If the primary domain
  1319. // is requested, add it here using info from LSA.
  1320. //
  1321. if ( Flags & DS_DOMAIN_PRIMARY ) {
  1322. UNICODE_STRING UncServerNameString;
  1323. OBJECT_ATTRIBUTES ObjectAttributes;
  1324. //
  1325. // First, open the policy database on the server.
  1326. //
  1327. RtlInitUnicodeString( &UncServerNameString, ServerName );
  1328. InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
  1329. Status = LsaOpenPolicy( &UncServerNameString,
  1330. &ObjectAttributes,
  1331. POLICY_VIEW_LOCAL_INFORMATION,
  1332. &LsaHandle );
  1333. if ( !NT_SUCCESS(Status) ) {
  1334. LsaHandle = NULL;
  1335. NetStatus = NetpNtStatusToApiStatus( Status );
  1336. goto Cleanup;
  1337. }
  1338. //
  1339. // Get the name of the primary domain from LSA
  1340. //
  1341. Status = LsaQueryInformationPolicy(
  1342. LsaHandle,
  1343. PolicyPrimaryDomainInformation,
  1344. (PVOID *) &PrimaryDomainInfo
  1345. );
  1346. if ( !NT_SUCCESS(Status) ) {
  1347. NetStatus = NetpNtStatusToApiStatus( Status );
  1348. goto Cleanup;
  1349. }
  1350. //
  1351. // Now, add it to our list here.
  1352. //
  1353. Status = NlAllocateForestTrustListEntry (
  1354. &BufferDescriptor,
  1355. &PrimaryDomainInfo->Name,
  1356. NULL, // No DNS domain name
  1357. DS_DOMAIN_PRIMARY,
  1358. 0, // No ParentIndex
  1359. TRUST_TYPE_DOWNLEVEL,
  1360. 0, // No TrustAttributes
  1361. PrimaryDomainInfo->Sid,
  1362. NULL, // No DomainGuid
  1363. &DummySize,
  1364. &TrustedDomain );
  1365. if ( !NT_SUCCESS(Status) ) {
  1366. NetStatus = NetpNtStatusToApiStatus( Status );
  1367. goto Cleanup;
  1368. }
  1369. //
  1370. // And account for the newly allocated entry.
  1371. //
  1372. LocalDomainCount ++;
  1373. }
  1374. //
  1375. // If we made it up to this point, it's a success!
  1376. //
  1377. NetStatus = NO_ERROR;
  1378. Cleanup:
  1379. if ( DomainNames != NULL) {
  1380. NetApiBufferFree( DomainNames );
  1381. }
  1382. if ( LsaHandle != NULL ) {
  1383. (VOID) LsaClose( LsaHandle );
  1384. }
  1385. if ( PrimaryDomainInfo != NULL ) {
  1386. (void) LsaFreeMemory( PrimaryDomainInfo );
  1387. }
  1388. //
  1389. // Return the trusted domain list
  1390. //
  1391. if ( NetStatus == NO_ERROR ) {
  1392. *Domains = (PDS_DOMAIN_TRUSTSW)BufferDescriptor.Buffer;
  1393. *DomainCount = LocalDomainCount;
  1394. } else {
  1395. if ( BufferDescriptor.Buffer != NULL ) {
  1396. NetApiBufferFree( BufferDescriptor.Buffer );
  1397. }
  1398. *Domains = NULL;
  1399. *DomainCount = 0;
  1400. }
  1401. return NetStatus;
  1402. }
  1403. NET_API_STATUS NET_API_FUNCTION
  1404. DsEnumerateDomainTrustsW (
  1405. IN LPWSTR ServerName OPTIONAL,
  1406. IN ULONG Flags,
  1407. OUT PDS_DOMAIN_TRUSTSW *Domains,
  1408. OUT PULONG DomainCount
  1409. )
  1410. /*++
  1411. Routine Description:
  1412. This API returns the names of the domains trusting and trusted by the domain ServerName
  1413. is a member of.
  1414. Netlogon's cache of Trusted domain names is maintained in a file across reboots.
  1415. As such, the list is available upon boot even if no DC is available.
  1416. Arguments:
  1417. ServerName - name of remote server (null for local).
  1418. Flags - Specifies attributes of trusts which should be returned. These are the flags
  1419. of the DS_DOMAIN_TRUSTSW strusture. If a trust entry has any of the bits specified
  1420. in Flags set, it will be returned.
  1421. Domains - Returns an array of trusted domains.
  1422. Buffer must be free using NetApiBufferFree().
  1423. DomainCount - Returns a count of the number elements in the Domains array.
  1424. Return Value:
  1425. NO_ERROR - Success.
  1426. ERROR_NO_LOGON_SERVERS - No DC could be found and no cached information is available.
  1427. ERROR_NO_TRUST_LSA_SECRET - The client side of the trust relationship is
  1428. broken and no cached information is available.
  1429. ERROR_NO_TRUST_SAM_ACCOUNT - The server side of the trust relationship is
  1430. broken or the password is broken and no cached information is available.
  1431. ERROR_INVALID_FLAGS - The Flags parameter has invalid bit(s) set.
  1432. ERROR_NOT_SUPPORTED - The server specified is not capable of returning the domain
  1433. trusts requested.
  1434. --*/
  1435. {
  1436. NET_API_STATUS NetStatus;
  1437. NETLOGON_TRUSTED_DOMAIN_ARRAY LocalDomains;
  1438. //
  1439. // Validate the Flags parameter
  1440. //
  1441. if ( (Flags & DS_DOMAIN_VALID_FLAGS) == 0 ||
  1442. (Flags & ~DS_DOMAIN_VALID_FLAGS) != 0 ) {
  1443. return ERROR_INVALID_FLAGS;
  1444. }
  1445. //
  1446. // Initialization
  1447. //
  1448. *DomainCount = 0;
  1449. *Domains = NULL;
  1450. //
  1451. // Do the RPC call with an exception handler since RPC will raise an
  1452. // exception if anything fails. It is up to us to figure out what
  1453. // to do once the exception is raised.
  1454. //
  1455. RpcTryExcept {
  1456. //
  1457. // Call RPC version of the API.
  1458. //
  1459. LocalDomains.Domains = NULL;
  1460. LocalDomains.DomainCount = 0;
  1461. NetStatus = DsrEnumerateDomainTrusts (
  1462. ServerName,
  1463. Flags,
  1464. &LocalDomains );
  1465. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1466. NetStatus = RpcExceptionCode();
  1467. } RpcEndExcept;
  1468. if ( NetStatus == NO_ERROR ) {
  1469. *Domains = LocalDomains.Domains;
  1470. *DomainCount = LocalDomains.DomainCount;
  1471. //
  1472. // Handle the case where the server is an NT4 machine
  1473. //
  1474. } else if ( NetStatus == RPC_S_PROCNUM_OUT_OF_RANGE ) {
  1475. NetStatus = NlpEnumerateNt4DomainTrusts (
  1476. ServerName,
  1477. Flags,
  1478. Domains,
  1479. DomainCount );
  1480. }
  1481. IF_DEBUG( LOGON ) {
  1482. NetpKdPrint(("DsEnumerateDomainTrustsW rc = %lu 0x%lx\n",
  1483. NetStatus, NetStatus));
  1484. }
  1485. return NetStatus;
  1486. }
  1487. NET_API_STATUS NET_API_FUNCTION
  1488. DsEnumerateDomainTrustsA (
  1489. IN LPSTR ServerName OPTIONAL,
  1490. IN ULONG Flags,
  1491. OUT PDS_DOMAIN_TRUSTSA *Domains,
  1492. OUT PULONG DomainCount
  1493. )
  1494. /*++
  1495. Routine Description:
  1496. This API returns the names of the domains trusting and trusted by the domain ServerName
  1497. is a member of.
  1498. Netlogon's cache of Trusted domain names is maintained in a file across reboots.
  1499. As such, the list is available upon boot even if no DC is available.
  1500. Arguments:
  1501. ServerName - name of remote server (null for local).
  1502. Flags - Specifies attributes of trusts which should be returned. These are the flags
  1503. of the DS_DOMAIN_TRUSTSW strusture. If a trust entry has any of the bits specified
  1504. in Flags set, it will be returned.
  1505. Domains - Returns an array of trusted domains.
  1506. Buffer must be free using NetApiBufferFree().
  1507. DomainCount - Returns a count of the number elements in the Domains array.
  1508. ERROR_NOT_SUPPORTED - The server specified is not capable of returning the domain
  1509. trusts requested.
  1510. Return Value:
  1511. NO_ERROR - Success.
  1512. ERROR_NO_LOGON_SERVERS - No DC could be found and no cached information is available.
  1513. ERROR_NO_TRUST_LSA_SECRET - The client side of the trust relationship is
  1514. broken and no cached information is available.
  1515. ERROR_NO_TRUST_SAM_ACCOUNT - The server side of the trust relationship is
  1516. broken or the password is broken and no cached information is available.
  1517. ERROR_INVALID_FLAGS - The Flags parameter has invalid bit(s) set.
  1518. --*/
  1519. {
  1520. NET_API_STATUS NetStatus;
  1521. PDS_DOMAIN_TRUSTSW DomainsW = NULL;
  1522. LPWSTR UnicodeServerName = NULL;
  1523. LPSTR *TmpNetbiosDomainNameArray = NULL;
  1524. LPSTR *TmpDnsDomainNameArray = NULL;
  1525. ULONG Size;
  1526. ULONG NameSize;
  1527. ULONG i;
  1528. LPBYTE Where;
  1529. //
  1530. // Initialization
  1531. //
  1532. *Domains = NULL;
  1533. *DomainCount = 0;
  1534. //
  1535. // Convert input parameters to Unicode.
  1536. //
  1537. if ( ServerName != NULL ) {
  1538. UnicodeServerName = NetpAllocWStrFromAStr( ServerName );
  1539. if ( UnicodeServerName == NULL ) {
  1540. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  1541. goto Cleanup;
  1542. }
  1543. }
  1544. //
  1545. // Call the Unicode version of the API
  1546. //
  1547. NetStatus = DsEnumerateDomainTrustsW ( UnicodeServerName,
  1548. Flags,
  1549. &DomainsW,
  1550. DomainCount );
  1551. if ( NetStatus != NO_ERROR || *DomainCount == 0 ) {
  1552. goto Cleanup;
  1553. }
  1554. //
  1555. // Allocate the buffer to return to the caller
  1556. //
  1557. // First allocate temprory ANSI arrays to store the domain names. This is needed
  1558. // because there is no easy way to compute the size of ANSI names other than to
  1559. // allocate them from Unicode strings and then compute the sizes of the resulting
  1560. // ANSI strings.
  1561. //
  1562. NetStatus = NetApiBufferAllocate( (*DomainCount)*sizeof(LPSTR),
  1563. (LPVOID *) &TmpNetbiosDomainNameArray );
  1564. if ( NetStatus != NO_ERROR ) {
  1565. goto Cleanup;
  1566. }
  1567. NetStatus = NetApiBufferAllocate( (*DomainCount)*sizeof(LPSTR),
  1568. (LPVOID *) &TmpDnsDomainNameArray );
  1569. if ( NetStatus != NO_ERROR ) {
  1570. goto Cleanup;
  1571. }
  1572. RtlZeroMemory( TmpNetbiosDomainNameArray, (*DomainCount)*sizeof(LPSTR) );
  1573. RtlZeroMemory( TmpDnsDomainNameArray, (*DomainCount)*sizeof(LPSTR) );
  1574. Size = 0;
  1575. for ( i = 0; i < *DomainCount; i++ ) {
  1576. Size += sizeof(DS_DOMAIN_TRUSTSA);
  1577. //
  1578. // Add the size of the Netbios domain name
  1579. //
  1580. if ( DomainsW[i].NetbiosDomainName != NULL ) {
  1581. TmpNetbiosDomainNameArray[i] = NetpAllocAStrFromWStr( DomainsW[i].NetbiosDomainName );
  1582. if ( TmpNetbiosDomainNameArray[i] == NULL ) {
  1583. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  1584. goto Cleanup;
  1585. }
  1586. Size += lstrlenA( TmpNetbiosDomainNameArray[i] ) + 1;
  1587. } else {
  1588. TmpNetbiosDomainNameArray[i] = NULL;
  1589. }
  1590. //
  1591. // Add the size of the DNS domain name
  1592. //
  1593. if ( DomainsW[i].DnsDomainName != NULL ) {
  1594. TmpDnsDomainNameArray[i] = NetpAllocAStrFromWStr( DomainsW[i].DnsDomainName );
  1595. if ( TmpDnsDomainNameArray[i] == NULL ) {
  1596. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  1597. goto Cleanup;
  1598. }
  1599. Size += lstrlenA( TmpDnsDomainNameArray[i] ) + 1;
  1600. } else {
  1601. TmpDnsDomainNameArray[i] = NULL;
  1602. }
  1603. //
  1604. // Add the size of the SID
  1605. //
  1606. if ( DomainsW[i].DomainSid != NULL ) {
  1607. Size += RtlLengthSid( DomainsW[i].DomainSid );
  1608. }
  1609. Size = ROUND_UP_COUNT( Size, ALIGN_DWORD );
  1610. }
  1611. NetStatus = NetApiBufferAllocate( Size, Domains );
  1612. if ( NetStatus != NO_ERROR ) {
  1613. goto Cleanup;
  1614. }
  1615. //
  1616. // Loop copying domains to the caller.
  1617. //
  1618. Where = (LPBYTE) &((*Domains)[*DomainCount]);
  1619. for ( i = 0; i < *DomainCount; i++) {
  1620. NTSTATUS Status;
  1621. //
  1622. // Copy constant length variables
  1623. //
  1624. (*Domains)[i].Flags = DomainsW[i].Flags;
  1625. (*Domains)[i].ParentIndex = DomainsW[i].ParentIndex;
  1626. (*Domains)[i].TrustType = DomainsW[i].TrustType;
  1627. (*Domains)[i].TrustAttributes = DomainsW[i].TrustAttributes;
  1628. (*Domains)[i].DomainGuid = DomainsW[i].DomainGuid;
  1629. //
  1630. // Copy the (DWORD aligned) SID into the return buffer
  1631. //
  1632. if ( DomainsW[i].DomainSid != NULL ) {
  1633. ULONG SidSize;
  1634. (*Domains)[i].DomainSid = (PSID) Where;
  1635. SidSize = RtlLengthSid( DomainsW[i].DomainSid );
  1636. RtlCopyMemory( Where,
  1637. DomainsW[i].DomainSid,
  1638. SidSize );
  1639. Where += SidSize;
  1640. } else {
  1641. (*Domains)[i].DomainSid = NULL;
  1642. }
  1643. //
  1644. // Copy the Netbios domain name into the return buffer.
  1645. //
  1646. if ( DomainsW[i].NetbiosDomainName != NULL ) {
  1647. NameSize = lstrlenA( TmpNetbiosDomainNameArray[i] ) + 1;
  1648. (*Domains)[i].NetbiosDomainName = (LPSTR) Where;
  1649. RtlCopyMemory( Where,
  1650. TmpNetbiosDomainNameArray[i],
  1651. NameSize );
  1652. Where += NameSize;
  1653. } else {
  1654. (*Domains)[i].NetbiosDomainName = NULL;
  1655. }
  1656. //
  1657. // Copy the DNS domain name into the return buffer.
  1658. //
  1659. if ( DomainsW[i].DnsDomainName != NULL ) {
  1660. NameSize = lstrlenA( TmpDnsDomainNameArray[i] ) + 1;
  1661. (*Domains)[i].DnsDomainName = (LPSTR) Where;
  1662. RtlCopyMemory( Where,
  1663. TmpDnsDomainNameArray[i],
  1664. NameSize );
  1665. Where += NameSize;
  1666. } else {
  1667. (*Domains)[i].DnsDomainName = NULL;
  1668. }
  1669. Where = ROUND_UP_POINTER( Where, ALIGN_DWORD);
  1670. }
  1671. Cleanup:
  1672. if ( DomainsW != NULL ) {
  1673. NetApiBufferFree( DomainsW );
  1674. }
  1675. if ( UnicodeServerName != NULL ) {
  1676. NetApiBufferFree( UnicodeServerName );
  1677. }
  1678. if ( TmpNetbiosDomainNameArray != NULL ) {
  1679. for ( i = 0; i < *DomainCount; i++ ) {
  1680. if ( TmpNetbiosDomainNameArray[i] != NULL ) {
  1681. NetApiBufferFree( TmpNetbiosDomainNameArray[i] );
  1682. }
  1683. }
  1684. NetApiBufferFree( TmpNetbiosDomainNameArray );
  1685. }
  1686. if ( TmpDnsDomainNameArray != NULL ) {
  1687. for ( i = 0; i < *DomainCount; i++ ) {
  1688. if ( TmpDnsDomainNameArray[i] != NULL ) {
  1689. NetApiBufferFree( TmpDnsDomainNameArray[i] );
  1690. }
  1691. }
  1692. NetApiBufferFree( TmpDnsDomainNameArray );
  1693. }
  1694. if ( NetStatus != NO_ERROR && *Domains != NULL ) {
  1695. NetApiBufferFree( *Domains );
  1696. *Domains = NULL;
  1697. *DomainCount = 0;
  1698. }
  1699. IF_DEBUG( LOGON ) {
  1700. NetpKdPrint(("DsEnumerateDomainTrustsA rc = %lu 0x%lx\n",
  1701. NetStatus, NetStatus));
  1702. }
  1703. return NetStatus;
  1704. }
  1705. NTSTATUS
  1706. I_NetLogonGetDomainInfo(
  1707. IN LPWSTR ServerName,
  1708. IN LPWSTR ComputerName,
  1709. IN PNETLOGON_AUTHENTICATOR Authenticator,
  1710. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  1711. IN DWORD QueryLevel,
  1712. IN LPBYTE InBuffer,
  1713. OUT LPBYTE *OutBuffer
  1714. )
  1715. /*++
  1716. Routine Description:
  1717. This function is used by an NT workstation to query information about the
  1718. domain it is a member of.
  1719. Arguments:
  1720. ServerName -- Name of the DC to retrieve the data from.
  1721. ComputerName -- Name of the workstation making the call.
  1722. Authenticator -- supplied by the workstation.
  1723. ReturnAuthenticator -- Receives an authenticator returned by the DC.
  1724. QueryLevel - Level of information to return from the DC. Valid values are:
  1725. 1: Return NETLOGON_DOMAIN_INFO structure.
  1726. InBuffer - Buffer to pass to DC
  1727. OutBuffer - Returns a pointer to an allocated buffer containing the queried
  1728. information.
  1729. Return Value:
  1730. STATUS_SUCCESS -- The function completed successfully.
  1731. STATUS_ACCESS_DENIED -- The workstations should re-authenticate with
  1732. the DC.
  1733. --*/
  1734. {
  1735. NTSTATUS Status = 0;
  1736. NETLOGON_DOMAIN_INFORMATION NetlogonDomainInfo;
  1737. NETLOGON_WORKSTATION_INFORMATION NetlogonWorkstationInfo;
  1738. //
  1739. // Do the RPC call with an exception handler since RPC will raise an
  1740. // exception if anything fails. It is up to us to figure out what
  1741. // to do once the exception is raised.
  1742. //
  1743. *OutBuffer = NULL;
  1744. RpcTryExcept {
  1745. //
  1746. // Call RPC version of the API.
  1747. //
  1748. NetlogonDomainInfo.DomainInfo = NULL; // Force RPC to allocate
  1749. NetlogonWorkstationInfo.WorkstationInfo = (PNETLOGON_WORKSTATION_INFO)InBuffer;
  1750. Status = NetrLogonGetDomainInfo(
  1751. ServerName,
  1752. ComputerName,
  1753. Authenticator,
  1754. ReturnAuthenticator,
  1755. QueryLevel,
  1756. &NetlogonWorkstationInfo,
  1757. &NetlogonDomainInfo );
  1758. if ( NT_SUCCESS(Status) ) {
  1759. *OutBuffer = (LPBYTE) NetlogonDomainInfo.DomainInfo;
  1760. }
  1761. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1762. Status = I_RpcMapWin32Status(RpcExceptionCode());
  1763. } RpcEndExcept;
  1764. IF_DEBUG( LOGON ) {
  1765. NetpKdPrint(("I_NetLogonGetDomainInfo rc = %lu 0x%lx\n", Status, Status));
  1766. }
  1767. return Status;
  1768. }
  1769. NTSTATUS
  1770. NetLogonSetServiceBits(
  1771. IN LPWSTR ServerName,
  1772. IN DWORD ServiceBitsOfInterest,
  1773. IN DWORD ServiceBits
  1774. )
  1775. /*++
  1776. Routine Description:
  1777. Inidcates whether this DC is currently running the specified service.
  1778. For instance,
  1779. NetLogonSetServiceBits( DS_KDC_FLAG, DS_KDC_FLAG );
  1780. tells Netlogon the KDC is running. And
  1781. NetLogonSetServiceBits( DS_KDC_FLAG, 0 );
  1782. tells Netlogon the KDC is not running.
  1783. This out of proc API can set only a certain set of bits:
  1784. DS_TIMESERV_FLAG
  1785. DS_GOOD_TIMESERV_FLAG
  1786. If other bits are attempted to be set, access denied is returned.
  1787. Arguments:
  1788. ServerName -- Name of the DC to retrieve the data from.
  1789. ServiceBitsOfInterest - A mask of the service bits being changed, set,
  1790. or reset by this call. Only the following flags are valid:
  1791. DS_KDC_FLAG
  1792. DS_DS_FLAG
  1793. DS_TIMESERV_FLAG
  1794. ServiceBits - A mask indicating what the bits specified by ServiceBitsOfInterest
  1795. should be set to.
  1796. Return Value:
  1797. STATUS_SUCCESS - Success.
  1798. STATUS_INVALID_PARAMETER - The parameters have extaneous bits set.
  1799. --*/
  1800. {
  1801. NTSTATUS Status = 0;
  1802. //
  1803. // Do the RPC call with an exception handler since RPC will raise an
  1804. // exception if anything fails. It is up to us to figure out what
  1805. // to do once the exception is raised.
  1806. //
  1807. RpcTryExcept {
  1808. //
  1809. // Call RPC version of the API.
  1810. //
  1811. Status = NetrLogonSetServiceBits(
  1812. ServerName,
  1813. ServiceBitsOfInterest,
  1814. ServiceBits );
  1815. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1816. Status = I_RpcMapWin32Status(RpcExceptionCode());
  1817. } RpcEndExcept;
  1818. IF_DEBUG( LOGON ) {
  1819. NetpKdPrint(("NetLogonSetServiceBits rc = %lu 0x%lx\n", Status, Status));
  1820. }
  1821. return Status;
  1822. }
  1823. NET_API_STATUS NET_API_FUNCTION
  1824. I_NetlogonGetTrustRid(
  1825. IN LPWSTR ServerName OPTIONAL,
  1826. IN LPWSTR DomainName OPTIONAL,
  1827. OUT PULONG Rid
  1828. )
  1829. /*++
  1830. Routine Description:
  1831. Returns the Rid of the account that ServerName uses in its secure channel to DomainName.
  1832. This routine performs an access check to determine if the caller can access
  1833. the requested RID. If the caller wants RID for the local machine account
  1834. (in which case the caller should specify by passing NULL for both ServerName
  1835. and DomainName), this routine requires Authenticated Users access. Otherwise,
  1836. if the caller wants a RID for a trust account on a DC, the admin or local
  1837. system access right is required.
  1838. Arguments:
  1839. ServerName - The name of the remote server.
  1840. DomainName - The name (DNS or Netbios) of the domain the trust is to.
  1841. NULL implies the domain the machine is a member of.
  1842. Rid - Rid is the RID of the account in the specified domain that represents the
  1843. trust relationship between the ServerName and DomainName.
  1844. Return Value:
  1845. NERR_Success: the operation was successful
  1846. ERROR_NO_SUCH_DOMAIN: The specified domain does not exist.
  1847. ERROR_NO_LOGON_SERVERS: There are currently no logon server available for the domain or
  1848. there is some problem with the secure channel.
  1849. ERROR_NOT_SUPPORTED: The specified trusted domain does not support digesting.
  1850. --*/
  1851. {
  1852. NET_API_STATUS NetStatus;
  1853. //
  1854. // Do the RPC call with an exception handler since RPC will raise an
  1855. // exception if anything fails. It is up to us to figure out what
  1856. // to do once the exception is raised.
  1857. //
  1858. RpcTryExcept {
  1859. //
  1860. // Call RPC version of the API.
  1861. //
  1862. NetStatus = NetrLogonGetTrustRid (
  1863. ServerName,
  1864. DomainName,
  1865. Rid );
  1866. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1867. NetStatus = RpcExceptionCode();
  1868. } RpcEndExcept;
  1869. IF_DEBUG( LOGON ) {
  1870. NetpKdPrint(("I_NetLogonGetTrustRid rc = %lu 0x%lx\n",
  1871. NetStatus, NetStatus));
  1872. }
  1873. return NetStatus;
  1874. }
  1875. NET_API_STATUS NET_API_FUNCTION
  1876. I_NetlogonComputeServerDigest(
  1877. IN LPWSTR ServerName OPTIONAL,
  1878. IN ULONG Rid,
  1879. IN LPBYTE Message,
  1880. IN ULONG MessageSize,
  1881. OUT CHAR NewMessageDigest[NL_DIGEST_SIZE],
  1882. OUT CHAR OldMessageDigest[NL_DIGEST_SIZE]
  1883. )
  1884. /*++
  1885. Routine Description:
  1886. Compute the message digest for Message on the server.
  1887. A digest is computed given the message and the password used on
  1888. the account identified by teh account RID. Since there may be up
  1889. to 2 passwords on the account (for interdomain trust), this routine
  1890. returns 2 digets corresponding to the 2 passwords. If the account
  1891. has just one password on the server side (true for any account other
  1892. than the intedomain trust account) or the two passwords are the same
  1893. the 2 digests returned will be identical.
  1894. Only an Admin or LocalSystem or LocalService may call this function.
  1895. Arguments:
  1896. ServerName - The name of the remote server.
  1897. Rid - The RID of the account to create the digest for.
  1898. The RID must be the RID of a machine account or the API returns an error.
  1899. Message - The message to compute the digest for.
  1900. MessageSize - The size of Message in bytes.
  1901. NewMessageDigest - Returns the 128-bit digest of the message corresponding to
  1902. the new account password.
  1903. OldMessageDigest - Returns the 128-bit digest of the message corresponding to
  1904. the old account password.
  1905. Return Value:
  1906. NERR_Success: the operation was successful
  1907. --*/
  1908. {
  1909. NET_API_STATUS NetStatus;
  1910. //
  1911. // Do the RPC call with an exception handler since RPC will raise an
  1912. // exception if anything fails. It is up to us to figure out what
  1913. // to do once the exception is raised.
  1914. //
  1915. RpcTryExcept {
  1916. //
  1917. // Call RPC version of the API.
  1918. //
  1919. NetStatus = NetrLogonComputeServerDigest(
  1920. ServerName,
  1921. Rid,
  1922. Message,
  1923. MessageSize,
  1924. NewMessageDigest,
  1925. OldMessageDigest );
  1926. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1927. NetStatus = RpcExceptionCode();
  1928. } RpcEndExcept;
  1929. IF_DEBUG( LOGON ) {
  1930. NetpKdPrint(("I_NetLogonComputeServerDigest rc = %lu 0x%lx\n",
  1931. NetStatus, NetStatus));
  1932. }
  1933. return NetStatus;
  1934. }
  1935. NET_API_STATUS NET_API_FUNCTION
  1936. I_NetlogonComputeClientDigest(
  1937. IN LPWSTR ServerName OPTIONAL,
  1938. IN LPWSTR DomainName OPTIONAL,
  1939. IN LPBYTE Message,
  1940. IN ULONG MessageSize,
  1941. OUT CHAR NewMessageDigest[NL_DIGEST_SIZE],
  1942. OUT CHAR OldMessageDigest[NL_DIGEST_SIZE]
  1943. )
  1944. /*++
  1945. Routine Description:
  1946. Compute the message digest for Message on the client.
  1947. A digest is computed given the message and the password used on
  1948. the account identified by the domain name. Since there are two
  1949. passwords on the account on the client side, this routine
  1950. returns 2 digests corresponding to the 2 passwords. If the two
  1951. passwords are the same the 2 digests returned will be identical.
  1952. Only an Admin or LocalSystem or LocalService may call this function.
  1953. Arguments:
  1954. ServerName - The name of the remote server.
  1955. DomainName - The name (DNS or Netbios) of the domain the trust is to.
  1956. NULL implies the domain the machine is a member of.
  1957. Message - The message to compute the digest for.
  1958. MessageSize - The size of Message in bytes.
  1959. NewMessageDigest - Returns the 128-bit digest of the message corresponding
  1960. to the new password
  1961. NewMessageDigest - Returns the 128-bit digest of the message corresponding
  1962. to the new password
  1963. Return Value:
  1964. NERR_Success: the operation was successful
  1965. --*/
  1966. {
  1967. NET_API_STATUS NetStatus;
  1968. //
  1969. // Do the RPC call with an exception handler since RPC will raise an
  1970. // exception if anything fails. It is up to us to figure out what
  1971. // to do once the exception is raised.
  1972. //
  1973. RpcTryExcept {
  1974. //
  1975. // Call RPC version of the API.
  1976. //
  1977. NetStatus = NetrLogonComputeClientDigest(
  1978. ServerName,
  1979. DomainName,
  1980. Message,
  1981. MessageSize,
  1982. NewMessageDigest,
  1983. OldMessageDigest );
  1984. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  1985. NetStatus = RpcExceptionCode();
  1986. } RpcEndExcept;
  1987. IF_DEBUG( LOGON ) {
  1988. NetpKdPrint(("I_NetLogonComputeClientDigest rc = %lu 0x%lx\n",
  1989. NetStatus, NetStatus));
  1990. }
  1991. return NetStatus;
  1992. }
  1993. NTSTATUS
  1994. I_NetServerPasswordGet(
  1995. IN LPWSTR PrimaryName,
  1996. IN LPWSTR AccountName,
  1997. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  1998. IN LPWSTR ComputerName,
  1999. IN PNETLOGON_AUTHENTICATOR Authenticator,
  2000. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  2001. OUT PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword
  2002. )
  2003. /*++
  2004. Routine Description:
  2005. This function is used to by a BDC to get a machine account password
  2006. from the PDC in the doamin.
  2007. This function can only be called by a server which has previously
  2008. authenticated with a DC by calling I_NetServerAuthenticate.
  2009. This function uses RPC to contact the DC named by PrimaryName.
  2010. Arguments:
  2011. PrimaryName -- Computer name of the PDC to remote the call to.
  2012. AccountName -- Name of the account to get the password for.
  2013. AccountType -- The type of account being accessed.
  2014. ComputerName -- Name of the BDC making the call.
  2015. Authenticator -- supplied by the server.
  2016. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  2017. EncryptedNtOwfPassword -- Returns the OWF password of the account.
  2018. Return Value:
  2019. NT status code.
  2020. --*/
  2021. {
  2022. NTSTATUS Status;
  2023. //
  2024. // Do the RPC call with an exception handler since RPC will raise an
  2025. // exception if anything fails. It is up to us to figure out what
  2026. // to do once the exception is raised.
  2027. //
  2028. RpcTryExcept {
  2029. //
  2030. // Call RPC version of the API.
  2031. //
  2032. Status = NetrServerPasswordGet (
  2033. PrimaryName,
  2034. AccountName,
  2035. AccountType,
  2036. ComputerName,
  2037. Authenticator,
  2038. ReturnAuthenticator,
  2039. EncryptedNtOwfPassword );
  2040. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2041. Status = I_RpcMapWin32Status(RpcExceptionCode());
  2042. } RpcEndExcept;
  2043. IF_DEBUG( LOGON ) {
  2044. NetpKdPrint(("I_NetServerPasswordGet rc = %lu 0x%lx\n", Status, Status));
  2045. }
  2046. return Status;
  2047. }
  2048. NTSTATUS
  2049. I_NetServerTrustPasswordsGet(
  2050. IN LPWSTR TrustedDcName,
  2051. IN LPWSTR AccountName,
  2052. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  2053. IN LPWSTR ComputerName,
  2054. IN PNETLOGON_AUTHENTICATOR Authenticator,
  2055. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  2056. OUT PENCRYPTED_NT_OWF_PASSWORD EncryptedNewOwfPassword,
  2057. OUT PENCRYPTED_NT_OWF_PASSWORD EncryptedOldOwfPassword
  2058. )
  2059. /*++
  2060. Routine Description:
  2061. This function is used by a trusting side DC/workstation to get the
  2062. new and old passwords from the trusted side. The account name
  2063. requested must match the account name used at the secure channel
  2064. setup time unless the call is made by a BDC to its PDC; the BDC
  2065. has full access to the entire trust info.
  2066. This function can only be called by a server which has previously
  2067. authenticated with a DC by calling I_NetServerAuthenticate.
  2068. This function uses RPC to contact the DC named by TrustedDcName.
  2069. Arguments:
  2070. TrustedDcName -- Computer name of the DC to remote the call to.
  2071. AccountName -- Name of the account to get the password for.
  2072. AccountType -- The type of account being accessed.
  2073. ComputerName -- Name of the DC making the call.
  2074. Authenticator -- supplied by this server.
  2075. ReturnAuthenticator -- Receives an authenticator returned by the
  2076. trusted side DC.
  2077. EncryptedNewOwfPassword -- Returns the new OWF password of the account.
  2078. EncryptedOldOwfPassword -- Returns the old OWF password of the account.
  2079. Return Value:
  2080. NT status code.
  2081. --*/
  2082. {
  2083. NTSTATUS Status;
  2084. //
  2085. // Do the RPC call with an exception handler since RPC will raise an
  2086. // exception if anything fails. It is up to us to figure out what
  2087. // to do once the exception is raised.
  2088. //
  2089. RpcTryExcept {
  2090. //
  2091. // Call RPC version of the API.
  2092. //
  2093. Status = NetrServerTrustPasswordsGet (
  2094. TrustedDcName,
  2095. AccountName,
  2096. AccountType,
  2097. ComputerName,
  2098. Authenticator,
  2099. ReturnAuthenticator,
  2100. EncryptedNewOwfPassword,
  2101. EncryptedOldOwfPassword );
  2102. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2103. Status = I_RpcMapWin32Status(RpcExceptionCode());
  2104. } RpcEndExcept;
  2105. IF_DEBUG( LOGON ) {
  2106. NetpKdPrint(("I_NetServerTrustPasswordsGet rc = %lu 0x%lx\n", Status, Status));
  2107. }
  2108. return Status;
  2109. }
  2110. NTSTATUS
  2111. I_NetServerGetTrustInfo(
  2112. IN LPWSTR TrustedDcName,
  2113. IN LPWSTR AccountName,
  2114. IN NETLOGON_SECURE_CHANNEL_TYPE AccountType,
  2115. IN LPWSTR ComputerName,
  2116. IN PNETLOGON_AUTHENTICATOR Authenticator,
  2117. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  2118. OUT PENCRYPTED_NT_OWF_PASSWORD EncryptedNewOwfPassword,
  2119. OUT PENCRYPTED_NT_OWF_PASSWORD EncryptedOldOwfPassword,
  2120. OUT PNL_GENERIC_RPC_DATA *TrustInfo
  2121. )
  2122. /*++
  2123. Routine Description:
  2124. This function is used by a trusting side DC/workstation to get the
  2125. trust info (new and old passwords and trust attributes) from the
  2126. trusted side. The account name requested must match the account
  2127. name used at the secure channel setup time unless the call is made
  2128. by a BDC to its PDC; the BDC has full access to the entire trust info.
  2129. This function can only be called by a server which has previously
  2130. authenticated with a DC by calling I_NetServerAuthenticate.
  2131. This function uses RPC to contact the DC named by TrustedDcName.
  2132. Arguments:
  2133. TrustedDcName -- Computer name of the DC to remote the call to.
  2134. AccountName -- Name of the account to get the password for.
  2135. AccountType -- The type of account being accessed.
  2136. ComputerName -- Name of the DC making the call.
  2137. Authenticator -- supplied by this server.
  2138. ReturnAuthenticator -- Receives an authenticator returned by the
  2139. trusted side DC.
  2140. EncryptedNewOwfPassword -- Returns the new OWF password of the account.
  2141. EncryptedOldOwfPassword -- Returns the old OWF password of the account.
  2142. TrustInfo -- Returns trust info data (currently trust attributes)
  2143. Return Value:
  2144. NT status code.
  2145. --*/
  2146. {
  2147. NTSTATUS Status;
  2148. //
  2149. // Do the RPC call with an exception handler since RPC will raise an
  2150. // exception if anything fails. It is up to us to figure out what
  2151. // to do once the exception is raised.
  2152. //
  2153. RpcTryExcept {
  2154. //
  2155. // Call RPC version of the API.
  2156. //
  2157. *TrustInfo = NULL; // Force RPC to allocate
  2158. Status = NetrServerGetTrustInfo(
  2159. TrustedDcName,
  2160. AccountName,
  2161. AccountType,
  2162. ComputerName,
  2163. Authenticator,
  2164. ReturnAuthenticator,
  2165. EncryptedNewOwfPassword,
  2166. EncryptedOldOwfPassword,
  2167. TrustInfo );
  2168. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2169. Status = I_RpcMapWin32Status(RpcExceptionCode());
  2170. } RpcEndExcept;
  2171. IF_DEBUG( LOGON ) {
  2172. NetpKdPrint(("I_NetServerGetTrustInfo rc = %lu 0x%lx\n", Status, Status));
  2173. }
  2174. return Status;
  2175. }
  2176. NET_API_STATUS
  2177. NetLogonGetTimeServiceParentDomain(
  2178. IN LPWSTR ServerName OPTIONAL,
  2179. OUT LPWSTR *DomainName,
  2180. OUT PBOOL PdcSameSite
  2181. )
  2182. /*++
  2183. Routine Description:
  2184. Returns the domain name of the domain that is logically the "parent" of this
  2185. domain. The returned domain name is suitable for passing into the
  2186. NetLogonGetTrustRid and NetLogonComputeClientDigest API.
  2187. On a workstation or member server, the returned domain name is that of the
  2188. domain that ServerName is a member of.
  2189. On a DC that is at the root of the forest, ERROR_NO_SUCH_DOMAIN is returned.
  2190. On a DC that is at the root of a tree in the forest, the name of a trusted
  2191. domain that is also at the root of a tree in the forest is returned.
  2192. On any other DC, the name of the domain that is directly the parent domain
  2193. is returned.
  2194. (See the notes on multiple hosted domains in the code below.)
  2195. Only an Admin or LocalSystem may call this function.
  2196. Arguments:
  2197. ServerName - The name of the remote server.
  2198. DomainName - Returns the name of the parent domain.
  2199. The returned buffer should be freed using NetApiBufferFree
  2200. PdcSameSite - Return TRUE if the PDC of ServerName's domain is in the same
  2201. site as ServerName.
  2202. (This value should be ignored if ServerName is not a DC.)
  2203. Return Value:
  2204. NERR_Success: the operation was successful
  2205. ERROR_NO_SUCH_DOMAIN: This server is a DC in the domain that is at the
  2206. root of the forest.
  2207. --*/
  2208. {
  2209. NET_API_STATUS NetStatus;
  2210. //
  2211. // Do the RPC call with an exception handler since RPC will raise an
  2212. // exception if anything fails. It is up to us to figure out what
  2213. // to do once the exception is raised.
  2214. //
  2215. RpcTryExcept {
  2216. //
  2217. // Call RPC version of the API.
  2218. //
  2219. *DomainName = NULL;
  2220. NetStatus = NetrLogonGetTimeServiceParentDomain (
  2221. ServerName,
  2222. DomainName,
  2223. PdcSameSite );
  2224. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2225. NetStatus = RpcExceptionCode();
  2226. } RpcEndExcept;
  2227. return NetStatus;
  2228. }
  2229. NET_API_STATUS NET_API_FUNCTION
  2230. DsDeregisterDnsHostRecordsW (
  2231. IN LPWSTR ServerName OPTIONAL,
  2232. IN LPWSTR DnsDomainName OPTIONAL,
  2233. IN GUID *DomainGuid OPTIONAL,
  2234. IN GUID *DsaGuid OPTIONAL,
  2235. IN LPWSTR DnsHostName
  2236. )
  2237. /*++
  2238. Routine Description:
  2239. This function deletes all DNS entries associated with a particular
  2240. NtDsDsa object.
  2241. This routine does NOT delete A records registered by the DC. We have
  2242. no way of finding out the IP addresses of the long gone DC.
  2243. Only an Admin, Account Operator or Server Operator may call this
  2244. function.
  2245. Arguments:
  2246. ServerName - name of remote server (null for local).
  2247. DnsDomainName - DNS domain name of the domain the DC was in.
  2248. This need not be a domain hosted by this DC.
  2249. If NULL, it is implied to be the DnsHostName with the leftmost label
  2250. removed.
  2251. DomainGuid - Domain Guid of the domain.
  2252. If NULL, GUID specific names will not be removed.
  2253. DsaGuid - GUID of the NtdsDsa object that will be deleted.
  2254. If NULL, NtdsDsa specific names will not be removed.
  2255. DnsHostName - DNS host name of the DC whose DNS records are being deleted.
  2256. Return Value:
  2257. NO_ERROR - Success.
  2258. ERROR_NOT_SUPPORTED - The server specified is not a DC.
  2259. ERROR_ACCESS_DENIED - The caller is not allowed to perform this operation.
  2260. --*/
  2261. {
  2262. NET_API_STATUS NetStatus;
  2263. //
  2264. // Do the RPC call with an exception handler since RPC will raise an
  2265. // exception if anything fails. It is up to us to figure out what
  2266. // to do once the exception is raised.
  2267. //
  2268. RpcTryExcept {
  2269. //
  2270. // Call RPC version of the API.
  2271. //
  2272. NetStatus = DsrDeregisterDnsHostRecords (
  2273. ServerName,
  2274. DnsDomainName,
  2275. DomainGuid,
  2276. DsaGuid,
  2277. DnsHostName );
  2278. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2279. NetStatus = RpcExceptionCode();
  2280. } RpcEndExcept;
  2281. IF_DEBUG( LOGON ) {
  2282. NetpKdPrint(("DsDeregisterDnsHostRecordsW rc = %lu 0x%lx\n",
  2283. NetStatus, NetStatus));
  2284. }
  2285. return NetStatus;
  2286. }
  2287. NET_API_STATUS NET_API_FUNCTION
  2288. DsDeregisterDnsHostRecordsA (
  2289. IN LPSTR ServerName OPTIONAL,
  2290. IN LPSTR DnsDomainName OPTIONAL,
  2291. IN GUID *DomainGuid OPTIONAL,
  2292. IN GUID *DsaGuid OPTIONAL,
  2293. IN LPSTR DnsHostName
  2294. )
  2295. /*++
  2296. Routine Description:
  2297. This function deletes all DNS entries associated with a particular
  2298. NtDsDsa object.
  2299. This routine does NOT delete A records registered by the DC. We have
  2300. no way of finding out the IP addresses of the long gone DC.
  2301. Only an Admin, Account Operator or Server Operator may call this
  2302. function.
  2303. Arguments:
  2304. ServerName - name of remote server (null for local).
  2305. DnsDomainName - DNS domain name of the domain the DC was in.
  2306. This need not be a domain hosted by this DC.
  2307. If NULL, it is implied to be the DnsHostName with the leftmost label
  2308. removed.
  2309. DomainGuid - Domain Guid of the domain specified
  2310. by DnsDomainName. If NULL, GUID specific names will not be removed.
  2311. DsaGuid - GUID of the NtdsDsa object that will be deleted.
  2312. If NULL, NtdsDsa specific names will not be removed.
  2313. DnsHostName - DNS host name of the DC whose DNS records are being deleted.
  2314. Return Value:
  2315. NO_ERROR - Success.
  2316. ERROR_NOT_SUPPORTED - The server specified is not a DC.
  2317. ERROR_ACCESS_DENIED - The caller is not allowed to perform this operation.
  2318. --*/
  2319. {
  2320. NET_API_STATUS NetStatus;
  2321. LPWSTR UnicodeServerName = NULL;
  2322. LPWSTR UnicodeDnsDomainName = NULL;
  2323. LPWSTR UnicodeDnsHostName = NULL;
  2324. //
  2325. // Convert input parameters to Unicode.
  2326. //
  2327. if ( ServerName != NULL ) {
  2328. UnicodeServerName = NetpAllocWStrFromAStr( ServerName );
  2329. if ( UnicodeServerName == NULL ) {
  2330. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  2331. goto Cleanup;
  2332. }
  2333. }
  2334. if ( DnsDomainName != NULL ) {
  2335. UnicodeDnsDomainName = NetpAllocWStrFromAStr( DnsDomainName );
  2336. if ( UnicodeDnsDomainName == NULL ) {
  2337. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  2338. goto Cleanup;
  2339. }
  2340. }
  2341. if ( DnsHostName != NULL ) {
  2342. UnicodeDnsHostName = NetpAllocWStrFromAStr( DnsHostName );
  2343. if ( UnicodeDnsHostName == NULL ) {
  2344. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  2345. goto Cleanup;
  2346. }
  2347. }
  2348. //
  2349. // Call the Unicode routine
  2350. //
  2351. NetStatus = DsDeregisterDnsHostRecordsW (
  2352. UnicodeServerName,
  2353. UnicodeDnsDomainName,
  2354. DomainGuid,
  2355. DsaGuid,
  2356. UnicodeDnsHostName );
  2357. Cleanup:
  2358. if ( UnicodeServerName != NULL ) {
  2359. NetApiBufferFree( UnicodeServerName );
  2360. }
  2361. if ( UnicodeDnsDomainName != NULL ) {
  2362. NetApiBufferFree( UnicodeDnsDomainName );
  2363. }
  2364. if ( UnicodeDnsHostName != NULL ) {
  2365. NetApiBufferFree( UnicodeDnsHostName );
  2366. }
  2367. return NetStatus;
  2368. }
  2369. NET_API_STATUS NET_API_FUNCTION
  2370. DsGetForestTrustInformationW (
  2371. IN LPCWSTR ServerName OPTIONAL,
  2372. IN LPCWSTR TrustedDomainName OPTIONAL,
  2373. IN DWORD Flags,
  2374. OUT PLSA_FOREST_TRUST_INFORMATION *ForestTrustInfo
  2375. )
  2376. /*++
  2377. Routine Description:
  2378. DsGetForestTrustInformation returns an array of FTInfo records. The records can
  2379. be TLN or domain NscType records.
  2380. The TLN records returned by DsGetForestTrustInformation are collected from three
  2381. sources:
  2382. * The DNS domain names of each tree in the forest.
  2383. * The values of the Upn-Suffixes attribute on the Partitions container object
  2384. within the config container.
  2385. * The values of the Spn-Suffixes attribute on the Partitions container object
  2386. within the config container.
  2387. Each of these names is a candidate for being a TLN returned from the API.
  2388. However, some names are not returned if they are a suffix of one of the other
  2389. TLN candidates. For instance, if acme.com is a Upn Suffix and a.acme.com is
  2390. the dns domain name of one of the trees in the forest, only acme.com will be
  2391. returned.
  2392. The domain records returned from DsGetForestTrustInformation are collected by
  2393. internally calling DsEnumerateDomainTrusts with the DS_DOMAIN_IN_FOREST.
  2394. For each domain returned from that API, the Dns domain name, netbios domain name
  2395. and domain sid are returned in the domain FTinfo entry.
  2396. This section describes the DS_GFTI_UPDATE_TDO flag bit in more detail. When
  2397. this bit is specified, the FTinfo records written to the TDO is a combination
  2398. of the FTInfo records currently on the TDO and the FTInfo records returned from
  2399. the trusted domain. The merge is done as described for the
  2400. DsMergeForestTrustInformationW API.
  2401. Arguments:
  2402. ServerName - The name of the domain controller this API is remoted to.
  2403. The caller must be an "Authenticated User" on ServerName.
  2404. If NULL is specified, the local server is implied.
  2405. TrustedDomainName - The name of the TrustedDomain that the forest trust information
  2406. is to be gathered for. If TrustedDomainName is NULL, the forest trust
  2407. information for the domain hosted by ServerName is returned.
  2408. If TrustedDomainInformation is not null, it must specify the netbios domain
  2409. name or dns domain name of an outbound trusted domain with the
  2410. TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit set. In that case, this API obtains
  2411. the forest trust information by making an RPC call over netlogon's secure
  2412. channel to obtain the forest trust information from that domain.
  2413. Flags - Specifies a set of bits that modify the behavior of the API.
  2414. Valid bits are:
  2415. DS_GFTI_UPDATE_TDO - If this bit is set, the API will update
  2416. the FTinfo attribute of the TDO named by the TrustedDomainName
  2417. parameter. The TrustedDomainName parameter may not be NULL.
  2418. The caller must have access to modify the FTinfo attribute or
  2419. ERROR_ACCESS_DENIED will be returned. The algorithm describing
  2420. how the FTinfo from the trusted domain is merged with the FTinfo
  2421. from the TDO is described below.
  2422. This bit in only valid if ServerName specifies the PDC of its domain.
  2423. ForestTrustInfo - Returns a pointer to a structure containing a count and an
  2424. array of FTInfo records describing the namespaces claimed by the
  2425. domain specified by TrustedDomainName. The Accepted field and Time
  2426. field of all returned records will be zero. The buffer should be freed
  2427. by calling NetApiBufferFree.
  2428. Return Value:
  2429. NO_ERROR - Success.
  2430. ERROR_INVALID_FLAGS - An invalid value was passed for FLAGS
  2431. ERROR_INVALID_FUNCTION - The domain specified by TrustedDomainName does not have the
  2432. TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit set on the TDO on the trusted DC.
  2433. ERROR_NO_SUCH_DOMAIN - The domain specified by TrustedDomainName does not exist or
  2434. does not have that TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit set on the TDO on ServerName.
  2435. --*/
  2436. {
  2437. NET_API_STATUS NetStatus;
  2438. PLSA_FOREST_TRUST_INFORMATION LocalForestTrustInfo = NULL;
  2439. //
  2440. // Do the RPC call with an exception handler since RPC will raise an
  2441. // exception if anything fails. It is up to us to figure out what
  2442. // to do once the exception is raised.
  2443. //
  2444. RpcTryExcept {
  2445. //
  2446. // Call RPC version of the API.
  2447. //
  2448. NetStatus = DsrGetForestTrustInformation (
  2449. (LPWSTR) ServerName,
  2450. (LPWSTR) TrustedDomainName,
  2451. Flags,
  2452. &LocalForestTrustInfo );
  2453. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2454. NetStatus = RpcExceptionCode();
  2455. } RpcEndExcept;
  2456. if ( NetStatus == NO_ERROR ) {
  2457. *ForestTrustInfo = LocalForestTrustInfo;
  2458. }
  2459. return NetStatus;
  2460. }
  2461. NTSTATUS
  2462. I_NetGetForestTrustInformation (
  2463. IN LPWSTR ServerName OPTIONAL,
  2464. IN LPWSTR ComputerName,
  2465. IN PNETLOGON_AUTHENTICATOR Authenticator,
  2466. OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator,
  2467. IN DWORD Flags,
  2468. OUT PLSA_FOREST_TRUST_INFORMATION *ForestTrustInfo
  2469. )
  2470. /*++
  2471. Routine Description:
  2472. The secure channel version of DsGetForestTrustInformation.
  2473. The inbound secure channel identified by ComputerName must be for an interdomain trust
  2474. and the inbound TDO must have the TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit set.
  2475. Arguments:
  2476. ServerName - The name of the domain controller this API is remoted to.
  2477. ComputerName -- Name of the DC server making the call.
  2478. Authenticator -- supplied by the server.
  2479. ReturnAuthenticator -- Receives an authenticator returned by the PDC.
  2480. Flags - Specifies a set of bits that modify the behavior of the API.
  2481. No values are currently defined. The caller should pass zero.
  2482. ForestTrustInfo - Returns a pointer to a structure containing a count and an
  2483. array of FTInfo records describing the namespaces claimed by the
  2484. domain specified by TrustedDomainName. The Accepted field and Time
  2485. field of all returned records will be zero. The buffer should be freed
  2486. by calling NetApiBufferFree.
  2487. Return Value:
  2488. STATUS_SUCCESS -- The function completed successfully.
  2489. STATUS_ACCESS_DENIED -- The replicant should re-authenticate with
  2490. the PDC.
  2491. --*/
  2492. {
  2493. NTSTATUS Status;
  2494. //
  2495. // Do the RPC call with an exception handler since RPC will raise an
  2496. // exception if anything fails. It is up to us to figure out what
  2497. // to do once the exception is raised.
  2498. //
  2499. RpcTryExcept {
  2500. //
  2501. // Call RPC version of the API.
  2502. //
  2503. Status = NetrGetForestTrustInformation(
  2504. ServerName,
  2505. ComputerName,
  2506. Authenticator,
  2507. ReturnAuthenticator,
  2508. Flags,
  2509. ForestTrustInfo );
  2510. } RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) ) {
  2511. Status = I_RpcMapWin32Status(RpcExceptionCode());
  2512. } RpcEndExcept;
  2513. IF_DEBUG( LOGON ) {
  2514. NetpKdPrint(("I_NetGetForestTrustInformation rc = %lu 0x%lx\n",
  2515. Status, Status));
  2516. }
  2517. return Status;
  2518. }
  2519. NET_API_STATUS NET_API_FUNCTION
  2520. DsMergeForestTrustInformationW(
  2521. IN LPCWSTR DomainName,
  2522. IN PLSA_FOREST_TRUST_INFORMATION NewForestTrustInfo,
  2523. IN PLSA_FOREST_TRUST_INFORMATION OldForestTrustInfo OPTIONAL,
  2524. OUT PLSA_FOREST_TRUST_INFORMATION *MergedForestTrustInfo
  2525. )
  2526. /*++
  2527. Routine Description:
  2528. This function merges the changes from a new FTinfo into an old FTinfo and
  2529. produces the resultant FTinfo.
  2530. This routine will be modified in future releases to support new forest trust record
  2531. types. It is intended that the OldForestTrustInfo describes the FTinfo as currently
  2532. stored on the local TDO. It is intended that the NewForestTrustInfo is the FTinfo as
  2533. returned from DsGetForestTrustInformationW for DomainName. The MergedForestTrustInfo is
  2534. the resultant ForestTrustInfo that should be written to the local TDO. Don't use this
  2535. routine for any other purpose.
  2536. The merged FTinfo records are a combinition of the new and old records.
  2537. Here's where the merged records come from:
  2538. ??? Add more here about where records are valid etc.
  2539. * The TLN exclusion records are copied from the TDO intact.
  2540. * The TLN record from the trusted domain that maps to the dns domain name of the
  2541. TDO is copied enabled. This reflects the LSA requirement that such a TLN not
  2542. be disabled. For instance, if the TDO is for a.acme.com and there is a TLN for
  2543. a.acme.com that TLN will be enabled. Also, if the TDO is for a.acme.com and
  2544. there is a TLN for acme.com, that TLN will be enabled.
  2545. * All other TLN records from the trusted domain are copied disabled with the
  2546. following exceptions. If there is an enabled TLN on the TDO, all TLNs from the
  2547. trusted domain that equal (or are subordinate to) the TDO TLN are marked as
  2548. enabled. This follows the philosophy that new TLNs are imported as disabled.
  2549. For instance, if the TDO had an enabled TLN for a.acme.com that TLN will still
  2550. be enabled after the automatic update. If the TDO had an enabled TLN for
  2551. acme.com and the trusted forest now has a TLN for a.acme.com, the resultant
  2552. FTinfo will have an enabled TLN for a.acme.com.
  2553. * The domain records from the trusted domain are copied enabled with the
  2554. following exceptions. If there is a disabled domain record on the TDO whose
  2555. dns domain name, or domain sid exactly matches the domain record, then the domain
  2556. remains disabled. If there is a domain record on the TDO whose netbios name is
  2557. disabled and whose netbios name exactly matches the netbios name on a domain
  2558. record, then the netbios name is disabled.
  2559. Arguments:
  2560. TrustedDomainName - Trusted domain that is to be updated.
  2561. NewForestTrustInfo - Specified the new array of FTinfo records as returned from the
  2562. TrustedDomainName.
  2563. The Flags field and Time field of the TLN entries are ignored.
  2564. OldForestTrustInfo - Specified the array of FTinfo records as returned from the
  2565. TDO. This field may be NULL if there is no existing records.
  2566. MergedForestTrustInfo - Returns the resulant FTinfo records.
  2567. The caller should free this buffer using MIDL_user_free.
  2568. Return Value:
  2569. NO_ERROR: Success
  2570. --*/
  2571. {
  2572. NTSTATUS Status;
  2573. UNICODE_STRING DomainNameString;
  2574. RtlInitUnicodeString( &DomainNameString, DomainName );
  2575. //
  2576. // Call the worker routine
  2577. //
  2578. Status = NetpMergeFtinfo( &DomainNameString,
  2579. NewForestTrustInfo,
  2580. OldForestTrustInfo,
  2581. MergedForestTrustInfo );
  2582. return NetpNtStatusToApiStatus( Status );
  2583. }