Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5014 lines
131 KiB

  1. /*--
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. nltest.c
  5. Abstract:
  6. Test program for the Netlogon service.
  7. This code is shared between the RESKIT and non-RESKIT versions of nltest
  8. Author:
  9. 13-Apr-1992 (cliffv)
  10. Environment:
  11. User mode only.
  12. Contains NT-specific code.
  13. Requires ANSI C extensions: slash-slash comments, long external names.
  14. Revision History:
  15. Madana - added various options.
  16. --*/
  17. //
  18. // Common include files.
  19. //
  20. #include <logonsrv.h> // Include files common to entire service
  21. //
  22. // Include files specific to this .c file
  23. //
  24. #include <align.h>
  25. #include <dsgetdcp.h>
  26. #include <netlogp.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <strarray.h>
  30. #include <tstring.h>
  31. #include <lmerr.h>
  32. #include <lmapibuf.h>
  33. #include <ssiapi.h>
  34. #include <winreg.h>
  35. #include <samregp.h>
  36. #include <wtypes.h>
  37. #include <ntstatus.dbg>
  38. #include <winerror.dbg>
  39. #include <iniparm.h>
  40. VOID
  41. ListDeltas(
  42. LPWSTR DeltaFileName
  43. );
  44. NETLOGON_PARAMETERS NlGlobalParameters;
  45. GUID NlGlobalZeroGuid;
  46. typedef struct _MAILSLOT_INFO {
  47. CHAR Name[DNLEN+NETLOGON_NT_MAILSLOT_LEN+3];
  48. HANDLE ResponseHandle;
  49. BOOL State;
  50. NETLOGON_SAM_LOGON_RESPONSE SamLogonResponse;
  51. OVERLAPPED OverLapped;
  52. BOOL ReadPending;
  53. } MAIL_INFO, PMAIL_INFO;
  54. MAIL_INFO GlobalMailInfo[64];
  55. DWORD GlobalIterationCount = 0;
  56. LPWSTR GlobalAccountName;
  57. HANDLE GlobalPostEvent;
  58. CRITICAL_SECTION GlobalPrintCritSect;
  59. HCRYPTPROV NlGlobalCryptProvider;
  60. VOID
  61. DumpBuffer(
  62. PVOID Buffer,
  63. DWORD BufferSize
  64. )
  65. /*++
  66. Routine Description:
  67. Dumps the buffer content on to the debugger output.
  68. Arguments:
  69. Buffer: buffer pointer.
  70. BufferSize: size of the buffer.
  71. Return Value:
  72. none
  73. --*/
  74. {
  75. DWORD j;
  76. PULONG LongBuffer;
  77. ULONG LongLength;
  78. LongBuffer = Buffer;
  79. LongLength = min( BufferSize, 512 )/4;
  80. for(j = 0; j < LongLength; j++) {
  81. printf("%08lx ", LongBuffer[j]);
  82. }
  83. if ( BufferSize != LongLength*4 ) {
  84. printf( "..." );
  85. }
  86. printf("\n");
  87. }
  88. VOID
  89. NlpDumpBuffer(
  90. IN DWORD DebugFlag,
  91. PVOID Buffer,
  92. DWORD BufferSize
  93. )
  94. /*++
  95. Routine Description:
  96. Dumps the buffer content on to the debugger output.
  97. Arguments:
  98. DebugFlag: Debug flag to pass on to NlPrintRoutine
  99. Buffer: buffer pointer.
  100. BufferSize: size of the buffer.
  101. Return Value:
  102. none
  103. --*/
  104. {
  105. #define NUM_CHARS 16
  106. DWORD i, limit;
  107. CHAR TextBuffer[NUM_CHARS + 1];
  108. LPBYTE BufferPtr = Buffer;
  109. //
  110. // Hex dump of the bytes
  111. //
  112. limit = ((BufferSize - 1) / NUM_CHARS + 1) * NUM_CHARS;
  113. for (i = 0; i < limit; i++) {
  114. if (i < BufferSize) {
  115. NlPrint((0,"%02x ", BufferPtr[i]));
  116. if (BufferPtr[i] < 31 ) {
  117. TextBuffer[i % NUM_CHARS] = '.';
  118. } else if (BufferPtr[i] == '\0') {
  119. TextBuffer[i % NUM_CHARS] = ' ';
  120. } else {
  121. TextBuffer[i % NUM_CHARS] = (CHAR) BufferPtr[i];
  122. }
  123. } else {
  124. NlPrint((0," "));
  125. TextBuffer[i % NUM_CHARS] = ' ';
  126. }
  127. if ((i + 1) % NUM_CHARS == 0) {
  128. TextBuffer[NUM_CHARS] = 0;
  129. NlPrint((0," %s\n", TextBuffer));
  130. }
  131. }
  132. UNREFERENCED_PARAMETER( DebugFlag );
  133. }
  134. VOID
  135. NlpDumpSid(
  136. IN DWORD DebugFlag,
  137. IN PSID Sid OPTIONAL
  138. )
  139. /*++
  140. Routine Description:
  141. Dumps a SID to the debugger output
  142. Arguments:
  143. DebugFlag - Debug flag to pass on to NlPrintRoutine
  144. Sid - SID to output
  145. Return Value:
  146. none
  147. --*/
  148. {
  149. //
  150. // Output the SID
  151. //
  152. if ( Sid == NULL ) {
  153. NlPrint((0, "(null)\n"));
  154. } else {
  155. UNICODE_STRING SidString;
  156. NTSTATUS Status;
  157. Status = RtlConvertSidToUnicodeString( &SidString, Sid, TRUE );
  158. if ( !NT_SUCCESS(Status) ) {
  159. NlPrint((0, "Invalid 0x%lX\n", Status ));
  160. } else {
  161. NlPrint((0, "%wZ\n", &SidString ));
  162. RtlFreeUnicodeString( &SidString );
  163. }
  164. }
  165. UNREFERENCED_PARAMETER( DebugFlag );
  166. }
  167. VOID
  168. PrintTime(
  169. LPSTR Comment,
  170. LARGE_INTEGER ConvertTime
  171. )
  172. /*++
  173. Routine Description:
  174. Print the specified time
  175. Arguments:
  176. Comment - Comment to print in front of the time
  177. Time - GMT time to print (Nothing is printed if this is zero)
  178. Return Value:
  179. None
  180. --*/
  181. {
  182. //
  183. // If we've been asked to convert an NT GMT time to ascii,
  184. // Do so
  185. //
  186. if ( ConvertTime.QuadPart != 0 ) {
  187. LARGE_INTEGER LocalTime;
  188. TIME_FIELDS TimeFields;
  189. NTSTATUS Status;
  190. printf( "%s", Comment );
  191. Status = RtlSystemTimeToLocalTime( &ConvertTime, &LocalTime );
  192. if ( !NT_SUCCESS( Status )) {
  193. printf( "Can't convert time from GMT to Local time\n" );
  194. LocalTime = ConvertTime;
  195. }
  196. RtlTimeToTimeFields( &LocalTime, &TimeFields );
  197. printf( "%8.8lx %8.8lx = %ld/%ld/%ld %ld:%2.2ld:%2.2ld\n",
  198. ConvertTime.LowPart,
  199. ConvertTime.HighPart,
  200. TimeFields.Month,
  201. TimeFields.Day,
  202. TimeFields.Year,
  203. TimeFields.Hour,
  204. TimeFields.Minute,
  205. TimeFields.Second );
  206. }
  207. }
  208. LPSTR
  209. FindSymbolicNameForStatus(
  210. DWORD Id
  211. )
  212. {
  213. ULONG i;
  214. i = 0;
  215. if (Id == 0) {
  216. return "STATUS_SUCCESS";
  217. }
  218. if (Id & 0xC0000000) {
  219. while (ntstatusSymbolicNames[ i ].SymbolicName) {
  220. if (ntstatusSymbolicNames[ i ].MessageId == (NTSTATUS)Id) {
  221. return ntstatusSymbolicNames[ i ].SymbolicName;
  222. } else {
  223. i += 1;
  224. }
  225. }
  226. }
  227. while (winerrorSymbolicNames[ i ].SymbolicName) {
  228. if (winerrorSymbolicNames[ i ].MessageId == Id) {
  229. return winerrorSymbolicNames[ i ].SymbolicName;
  230. } else {
  231. i += 1;
  232. }
  233. }
  234. #ifdef notdef
  235. while (neteventSymbolicNames[ i ].SymbolicName) {
  236. if (neteventSymbolicNames[ i ].MessageId == Id) {
  237. return neteventSymbolicNames[ i ].SymbolicName
  238. } else {
  239. i += 1;
  240. }
  241. }
  242. #endif // notdef
  243. return NULL;
  244. }
  245. VOID
  246. PrintStatus(
  247. NET_API_STATUS NetStatus
  248. )
  249. /*++
  250. Routine Description:
  251. Print a net status code.
  252. Arguments:
  253. NetStatus - The net status code to print.
  254. Return Value:
  255. None
  256. --*/
  257. {
  258. printf( "Status = %lu 0x%lx", NetStatus, NetStatus );
  259. switch (NetStatus) {
  260. case NERR_Success:
  261. printf( " NERR_Success" );
  262. break;
  263. case NERR_DCNotFound:
  264. printf( " NERR_DCNotFound" );
  265. break;
  266. case NERR_UserNotFound:
  267. printf( " NERR_UserNotFound" );
  268. break;
  269. case NERR_NetNotStarted:
  270. printf( " NERR_NetNotStarted" );
  271. break;
  272. case NERR_WkstaNotStarted:
  273. printf( " NERR_WkstaNotStarted" );
  274. break;
  275. case NERR_ServerNotStarted:
  276. printf( " NERR_ServerNotStarted" );
  277. break;
  278. case NERR_BrowserNotStarted:
  279. printf( " NERR_BrowserNotStarted" );
  280. break;
  281. case NERR_ServiceNotInstalled:
  282. printf( " NERR_ServiceNotInstalled" );
  283. break;
  284. case NERR_BadTransactConfig:
  285. printf( " NERR_BadTransactConfig" );
  286. break;
  287. default:
  288. printf( " %s", FindSymbolicNameForStatus( NetStatus ) );
  289. break;
  290. }
  291. printf( "\n" );
  292. }
  293. VOID
  294. NlAssertFailed(
  295. IN PVOID FailedAssertion,
  296. IN PVOID FileName,
  297. IN ULONG LineNumber,
  298. IN PCHAR Message OPTIONAL
  299. )
  300. {
  301. printf( "\n*** Assertion failed: %s%s\n*** Source File: %s, line %ld\n\n",
  302. Message ? Message : "",
  303. FailedAssertion,
  304. FileName,
  305. LineNumber
  306. );
  307. }
  308. NTSTATUS
  309. NlBrowserSendDatagram(
  310. IN PVOID ContextDomainInfo,
  311. IN ULONG IpAddress,
  312. IN LPWSTR UnicodeDestinationName,
  313. IN DGRECEIVER_NAME_TYPE NameType,
  314. IN LPWSTR TransportName,
  315. IN LPSTR OemMailslotName,
  316. IN PVOID Buffer,
  317. IN ULONG BufferSize,
  318. IN OUT PBOOL FlushNameOnOneIpTransport OPTIONAL
  319. )
  320. /*++
  321. Routine Description:
  322. Send the specified mailslot message to the specified mailslot on the
  323. specified server on the specified transport..
  324. Arguments:
  325. DomainInfo - Hosted domain sending the datagram
  326. IpAddress - IpAddress of the machine to send the pind to.
  327. If zero, UnicodeDestinationName must be specified.
  328. UnicodeDestinationName -- Name of the server to send to.
  329. NameType -- Type of name represented by UnicodeDestinationName.
  330. TransportName -- Name of the transport to send on.
  331. Use NULL to send on all transports.
  332. OemMailslotName -- Name of the mailslot to send to.
  333. Buffer -- Specifies a pointer to the mailslot message to send.
  334. BufferSize -- Size in bytes of the mailslot message
  335. Return Value:
  336. Status of the operation.
  337. --*/
  338. {
  339. return STATUS_INTERNAL_ERROR;
  340. // If this routine is ever needed, copy it from logonsrv\client\getdcnam.c
  341. UNREFERENCED_PARAMETER(ContextDomainInfo);
  342. UNREFERENCED_PARAMETER(IpAddress);
  343. UNREFERENCED_PARAMETER(UnicodeDestinationName);
  344. UNREFERENCED_PARAMETER(NameType);
  345. UNREFERENCED_PARAMETER(TransportName);
  346. UNREFERENCED_PARAMETER(OemMailslotName);
  347. UNREFERENCED_PARAMETER(Buffer);
  348. UNREFERENCED_PARAMETER(BufferSize);
  349. UNREFERENCED_PARAMETER(FlushNameOnOneIpTransport);
  350. }
  351. VOID
  352. WhoWillLogMeOnResponse(
  353. )
  354. /*++
  355. Routine Description:
  356. This routine reads the responses that are received for the query
  357. messages sent from the main thread.
  358. Arguments:
  359. none
  360. Return Value:
  361. None
  362. --*/
  363. {
  364. DWORD i;
  365. DWORD WaitCount;
  366. DWORD IndexArray[64];
  367. HANDLE HandleArray[64];
  368. PNL_DC_CACHE_ENTRY NlDcCacheEntry = NULL;
  369. // ULONG LocalDcIpAddress;
  370. SYSTEMTIME SystemTime;
  371. NETLOGON_SAM_LOGON_RESPONSE SamLogonResponse;
  372. DWORD SamLogonResponseSize;
  373. DWORD WaitStatus;
  374. NET_API_STATUS NetStatus;
  375. BOOL AllReceived;
  376. for(;;) {
  377. //
  378. // make wait array.
  379. //
  380. WaitCount = 0;
  381. AllReceived = TRUE;
  382. for (i = 0; i < GlobalIterationCount; i++ ) {
  383. //
  384. if( GlobalMailInfo[i].State == TRUE ) {
  385. //
  386. // if a response is received.
  387. //
  388. continue;
  389. }
  390. AllReceived = FALSE;
  391. //
  392. // post a read.
  393. //
  394. if( GlobalMailInfo[i].ReadPending == FALSE ) {
  395. if ( !ReadFile( GlobalMailInfo[i].ResponseHandle,
  396. (PCHAR)&GlobalMailInfo[i].SamLogonResponse,
  397. sizeof(NETLOGON_SAM_LOGON_RESPONSE),
  398. &SamLogonResponseSize,
  399. &GlobalMailInfo[i].OverLapped )) { // Overlapped I/O
  400. NetStatus = GetLastError();
  401. if( NetStatus != ERROR_IO_PENDING ) {
  402. printf( "Cannot read mailslot (%s) : %ld\n",
  403. GlobalMailInfo[i].Name,
  404. NetStatus);
  405. goto Cleanup;
  406. }
  407. }
  408. GlobalMailInfo[i].ReadPending = TRUE;
  409. }
  410. HandleArray[WaitCount] = GlobalMailInfo[i].ResponseHandle;
  411. IndexArray[WaitCount] = i;
  412. WaitCount++;
  413. }
  414. if( (WaitCount == 0) ) {
  415. if( AllReceived ) {
  416. //
  417. // we received responses for all messages, so we are
  418. // done.
  419. //
  420. goto Cleanup;
  421. }
  422. else {
  423. // wait for an query posted
  424. //
  425. WaitStatus = WaitForSingleObject( GlobalPostEvent, (DWORD) -1 );
  426. if( WaitStatus != 0 ) {
  427. printf("Can't successfully wait post event %ld\n",
  428. WaitStatus );
  429. goto Cleanup;
  430. }
  431. continue;
  432. }
  433. }
  434. //
  435. // wait for response.
  436. //
  437. WaitStatus = WaitForMultipleObjects(
  438. WaitCount,
  439. HandleArray,
  440. FALSE, // Wait for ANY handle
  441. 15000 ); // 3 * 5 Secs
  442. if( WaitStatus == WAIT_TIMEOUT ) {
  443. // we are done.
  444. break;
  445. }
  446. if ( WaitStatus == WAIT_FAILED ) {
  447. printf( "Can't successfully wait for multiple objects %ld\n",
  448. GetLastError() );
  449. goto Cleanup;
  450. }
  451. if( WaitStatus >= WaitCount ) {
  452. printf("Invalid WaitStatus returned %ld\n", WaitStatus );
  453. goto Cleanup;
  454. }
  455. //
  456. // get index
  457. //
  458. i = IndexArray[WaitStatus];
  459. //
  460. // read response
  461. //
  462. if( !GetOverlappedResult(
  463. GlobalMailInfo[i].ResponseHandle,
  464. &GlobalMailInfo[i].OverLapped,
  465. &SamLogonResponseSize,
  466. TRUE) ) { // wait for the read complete.
  467. printf("can't read overlapped response %ld",GetLastError() );
  468. goto Cleanup;
  469. }
  470. SamLogonResponse = GlobalMailInfo[i].SamLogonResponse;
  471. //
  472. // indicate that we received a response.
  473. //
  474. GlobalMailInfo[i].State = TRUE;
  475. GlobalMailInfo[i].ReadPending = FALSE;
  476. GetLocalTime( &SystemTime );
  477. EnterCriticalSection( &GlobalPrintCritSect );
  478. printf( "[%02u:%02u:%02u] ",
  479. SystemTime.wHour,
  480. SystemTime.wMinute,
  481. SystemTime.wSecond );
  482. printf( "Response %ld: ", i);
  483. NetStatus = NetpDcParsePingResponse(
  484. NULL,
  485. &SamLogonResponse,
  486. SamLogonResponseSize,
  487. &NlDcCacheEntry );
  488. if ( NetStatus != NO_ERROR ) {
  489. printf("Failure parsing response: ");
  490. PrintStatus( NetStatus );
  491. goto Continue;
  492. }
  493. //
  494. // If the response is for the correct account,
  495. // break out of the loop.
  496. //
  497. if ( NlNameCompare(
  498. GlobalAccountName,
  499. NlDcCacheEntry->UnicodeUserName,
  500. NAMETYPE_USER)!=0){
  501. printf("Response not for correct User name "
  502. FORMAT_LPWSTR " s.b. " FORMAT_LPWSTR "\n",
  503. NlDcCacheEntry->UnicodeUserName, GlobalAccountName );
  504. goto Continue;
  505. }
  506. printf( "S:" FORMAT_LPWSTR " D:" FORMAT_LPWSTR
  507. " A:" FORMAT_LPWSTR,
  508. NlDcCacheEntry->UnicodeNetbiosDcName,
  509. NlDcCacheEntry->UnicodeNetbiosDomainName,
  510. NlDcCacheEntry->UnicodeUserName );
  511. //
  512. // If the DC recognizes our account,
  513. // we've successfully found the DC.
  514. //
  515. switch (NlDcCacheEntry->Opcode) {
  516. case LOGON_SAM_LOGON_RESPONSE:
  517. printf( " (Act found)\n" );
  518. break;
  519. case LOGON_SAM_USER_UNKNOWN:
  520. printf( " (Act not found)\n" );
  521. break;
  522. case LOGON_PAUSE_RESPONSE:
  523. printf( " (netlogon paused)\n" );
  524. break;
  525. default:
  526. printf( " (Unknown opcode: %lx)\n", SamLogonResponse.Opcode );
  527. break;
  528. }
  529. //
  530. // Print the additional NT 5 specific information.
  531. //
  532. if ( NlDcCacheEntry->UnicodeDnsForestName != NULL ) {
  533. printf( " Tree: %ws\n", NlDcCacheEntry->UnicodeDnsForestName );
  534. }
  535. if ( NlDcCacheEntry->UnicodeDnsDomainName != NULL ) {
  536. printf( " Dom: %s\n", NlDcCacheEntry->UnicodeDnsDomainName );
  537. }
  538. if ( NlDcCacheEntry->UnicodeDnsHostName != NULL ) {
  539. printf( " Host: %s\n", NlDcCacheEntry->UnicodeDnsHostName );
  540. }
  541. if ( NlDcCacheEntry->ReturnFlags != 0 ) {
  542. printf( " Flags: 0x%lx\n", NlDcCacheEntry->ReturnFlags );
  543. }
  544. Continue:
  545. if ( NlDcCacheEntry != NULL ) {
  546. NetpMemoryFree( NlDcCacheEntry );
  547. NlDcCacheEntry = NULL;
  548. }
  549. LeaveCriticalSection( &GlobalPrintCritSect );
  550. }
  551. Cleanup:
  552. //
  553. // print non-responsed mailslots.
  554. //
  555. for( i = 0; i < GlobalIterationCount; i++ ) {
  556. if( GlobalMailInfo[i].State == FALSE ) {
  557. printf("Didn't receive a response for mail "
  558. "message %ld (%s)\n", i, GlobalMailInfo[i].Name );
  559. }
  560. }
  561. return;
  562. }
  563. VOID
  564. WhoWillLogMeOn(
  565. IN LPWSTR DomainName,
  566. IN LPWSTR AccountName,
  567. IN DWORD IterationCount
  568. )
  569. /*++
  570. Routine Description:
  571. Determine which DC will log the specified account on
  572. Arguments:
  573. DomainName - name of the "doamin" to send the message to
  574. AccountName - Name of our user account to find.
  575. IterationCount - Number of consecutive messages to send.
  576. Return Value:
  577. None
  578. --*/
  579. {
  580. NET_API_STATUS NetStatus;
  581. ULONG AllowableAccountControlBits = USER_ACCOUNT_TYPE_MASK;
  582. WCHAR NetlogonMailslotName[DNLEN+NETLOGON_NT_MAILSLOT_LEN+4];
  583. HANDLE *ResponseMailslotHandle = NULL;
  584. WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1];
  585. DWORD ComputerNameLength = MAX_COMPUTERNAME_LENGTH+1;
  586. DWORD i;
  587. DWORD j;
  588. SYSTEMTIME SystemTime;
  589. HANDLE ResponseThreadHandle = NULL;
  590. DWORD ThreadId;
  591. DWORD WaitStatus;
  592. DWORD SamLogonResponseSize;
  593. //
  594. // support only 64 iterations
  595. //
  596. if( IterationCount > 64 ) {
  597. printf("Interations set to 64, maximum supported\n");
  598. IterationCount = 64;
  599. }
  600. GlobalIterationCount = IterationCount;
  601. GlobalAccountName = AccountName;
  602. try {
  603. InitializeCriticalSection( &GlobalPrintCritSect );
  604. } except( EXCEPTION_EXECUTE_HANDLER ) {
  605. fprintf( stderr, "NLTEST.EXE: Cannot initialize GlobalPrintCritSect\n" );
  606. return;
  607. }
  608. //
  609. // Get out computer name
  610. //
  611. if (!GetComputerName( ComputerName, &ComputerNameLength ) ) {
  612. printf( "Can't GetComputerName\n" );
  613. return;
  614. }
  615. //
  616. // create mailslots
  617. //
  618. for (i = 0; i < IterationCount; i++ ) {
  619. //
  620. // Create a mailslot for the DC's to respond to.
  621. //
  622. if (NetStatus = NetpLogonCreateRandomMailslot(
  623. GlobalMailInfo[i].Name,
  624. &GlobalMailInfo[i].ResponseHandle)){
  625. printf( "Cannot create temp mailslot %ld\n", NetStatus );
  626. goto Cleanup;
  627. }
  628. if ( !SetMailslotInfo( GlobalMailInfo[i].ResponseHandle,
  629. (DWORD) MAILSLOT_WAIT_FOREVER ) ) {
  630. printf( "Cannot set mailslot info %ld\n", GetLastError() );
  631. goto Cleanup;
  632. }
  633. (void) memset( &GlobalMailInfo[i].OverLapped, '\0',
  634. sizeof(OVERLAPPED) );
  635. GlobalMailInfo[i].State = FALSE;
  636. GlobalMailInfo[i].ReadPending = FALSE;
  637. }
  638. //
  639. // create post event
  640. //
  641. GlobalPostEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  642. if( GlobalPostEvent == NULL ) {
  643. printf("can't create post event %ld \n", GetLastError() );
  644. goto Cleanup;
  645. }
  646. //
  647. // start response thread.
  648. //
  649. ResponseThreadHandle =
  650. CreateThread(
  651. NULL, // No security attributes
  652. 0,
  653. (LPTHREAD_START_ROUTINE)
  654. WhoWillLogMeOnResponse,
  655. NULL,
  656. 0, // No special creation flags
  657. &ThreadId );
  658. if ( ResponseThreadHandle == NULL ) {
  659. printf("can't create response thread %ld\n", GetLastError() );
  660. goto Cleanup;
  661. }
  662. wcscpy( NetlogonMailslotName, L"\\\\" );
  663. wcscat( NetlogonMailslotName, DomainName );
  664. // wcscat( NetlogonMailslotName, L"*" ); // Don't add for computer name
  665. wcscat( NetlogonMailslotName, NETLOGON_NT_MAILSLOT_W);
  666. //
  667. // Send atmost 3 messages/mailslot
  668. //
  669. for( j = 0; j < 3; j++ ) {
  670. //
  671. // Repeat the message multiple times to load the servers
  672. //
  673. for (i = 0; i < IterationCount; i++ ) {
  674. PNETLOGON_SAM_LOGON_REQUEST SamLogonRequest;
  675. ULONG SamLogonRequestSize;
  676. if( GlobalMailInfo[i].State == TRUE ) {
  677. //
  678. // if a response is received.
  679. //
  680. continue;
  681. }
  682. //
  683. // Build the query message.
  684. //
  685. NetStatus = NetpDcBuildPing (
  686. FALSE, // Not only PDC
  687. 0, // Retry count
  688. ComputerName,
  689. AccountName,
  690. GlobalMailInfo[i].Name,
  691. AllowableAccountControlBits,
  692. NULL, // No Domain SID
  693. 0, // Not NT Version 5
  694. &SamLogonRequest,
  695. &SamLogonRequestSize );
  696. if ( NetStatus != NO_ERROR ) {
  697. printf("can't allocate mailslot message %ld\n", NetStatus );
  698. goto Cleanup;
  699. }
  700. //
  701. // Send the message to a DC for the domain.
  702. //
  703. NetStatus = NetpLogonWriteMailslot(
  704. NetlogonMailslotName,
  705. (PCHAR)SamLogonRequest,
  706. SamLogonRequestSize );
  707. NetpMemoryFree( SamLogonRequest );
  708. if ( NetStatus != NERR_Success ) {
  709. printf( "Cannot write netlogon mailslot: %ld\n", NetStatus);
  710. goto Cleanup;
  711. }
  712. GetLocalTime( &SystemTime );
  713. EnterCriticalSection( &GlobalPrintCritSect );
  714. printf( "[%02u:%02u:%02u] ",
  715. SystemTime.wHour,
  716. SystemTime.wMinute,
  717. SystemTime.wSecond );
  718. printf( "Mail message %ld sent successfully (%s) \n",
  719. i, GlobalMailInfo[i].Name );
  720. LeaveCriticalSection( &GlobalPrintCritSect );
  721. if( !SetEvent( GlobalPostEvent ) ) {
  722. printf("Can't set post event %ld \n", GetLastError() );
  723. goto Cleanup;
  724. }
  725. }
  726. //
  727. // wait 5 secs to see response thread received all responses.
  728. //
  729. WaitStatus = WaitForSingleObject( ResponseThreadHandle, 5000 );
  730. // 15 secs. TIMEOUT
  731. if( WaitStatus != WAIT_TIMEOUT ) {
  732. if( WaitStatus != 0 ) {
  733. printf("can't do WaitForSingleObject %ld\n", WaitStatus);
  734. }
  735. goto Cleanup;
  736. }
  737. }
  738. Cleanup:
  739. //
  740. // Wait for the response thread to complete.
  741. //
  742. if( ResponseThreadHandle != NULL ) {
  743. WaitStatus = WaitForSingleObject( ResponseThreadHandle, 15000 );
  744. // 15 secs. TIMEOUT
  745. if( WaitStatus ) {
  746. if( WaitStatus == WAIT_TIMEOUT ) {
  747. printf("Can't stop response thread (TIMEOUT) \n");
  748. } else {
  749. printf("Can't stop response thread %ld \n", WaitStatus);
  750. }
  751. }
  752. }
  753. for (i = 0; i < IterationCount; i++ ) {
  754. if( GlobalMailInfo[i].ResponseHandle != NULL ) {
  755. CloseHandle( GlobalMailInfo[i].ResponseHandle);
  756. }
  757. }
  758. if( GlobalPostEvent != NULL ) {
  759. CloseHandle( GlobalPostEvent );
  760. }
  761. DeleteCriticalSection( &GlobalPrintCritSect );
  762. return;
  763. }
  764. #define MAX_PRINTF_LEN 1024 // Arbitrary.
  765. VOID
  766. NlPrintRoutine(
  767. IN DWORD DebugFlag,
  768. IN LPSTR Format,
  769. ...
  770. )
  771. {
  772. va_list arglist;
  773. char OutputBuffer[MAX_PRINTF_LEN];
  774. //
  775. // Put a the information requested by the caller onto the line
  776. //
  777. va_start(arglist, Format);
  778. (VOID) vsprintf(OutputBuffer, Format, arglist);
  779. va_end(arglist);
  780. printf( "%s", OutputBuffer );
  781. return;
  782. UNREFERENCED_PARAMETER( DebugFlag );
  783. }
  784. NTSTATUS
  785. SimulateFullSync(
  786. LPWSTR PdcName,
  787. LPWSTR MachineName
  788. )
  789. /*++
  790. Routine Description:
  791. This function simulate a full sync replication by calling
  792. NetDatabaseSync API and simply ignoring successfully returned data.
  793. Arguments:
  794. PdcName - Name of the PDC from where the database replicated.
  795. MachineName - Name of the machine account used to authenticate.
  796. Return Value:
  797. Network Status code.
  798. --*/
  799. {
  800. NTSTATUS Status;
  801. NETLOGON_CREDENTIAL ServerChallenge;
  802. NETLOGON_CREDENTIAL ClientChallenge;
  803. NETLOGON_CREDENTIAL ComputedServerCredential;
  804. NETLOGON_CREDENTIAL ReturnedServerCredential;
  805. NETLOGON_CREDENTIAL AuthenticationSeed;
  806. NETLOGON_SESSION_KEY SessionKey;
  807. NETLOGON_AUTHENTICATOR OurAuthenticator;
  808. NETLOGON_AUTHENTICATOR ReturnAuthenticator;
  809. UNICODE_STRING Password;
  810. NT_OWF_PASSWORD NtOwfPassword;
  811. ULONG SamSyncContext = 0;
  812. PNETLOGON_DELTA_ENUM_ARRAY DeltaArray = NULL;
  813. DWORD DatabaseIndex;
  814. DWORD i;
  815. WCHAR AccountName[SSI_ACCOUNT_NAME_LENGTH+1];
  816. //
  817. // Prepare our challenge
  818. //
  819. NlComputeChallenge( &ClientChallenge );
  820. printf("ClientChallenge = %lx %lx\n",
  821. ((DWORD*)&ClientChallenge)[0],
  822. ((DWORD *)&ClientChallenge)[1]);
  823. //
  824. // Get the primary's challenge
  825. //
  826. Status = I_NetServerReqChallenge(PdcName,
  827. MachineName,
  828. &ClientChallenge,
  829. &ServerChallenge );
  830. if ( !NT_SUCCESS( Status ) ) {
  831. fprintf( stderr,
  832. "I_NetServerReqChallenge to " FORMAT_LPWSTR
  833. " returned 0x%lx\n",
  834. PdcName,
  835. Status );
  836. return(Status);
  837. }
  838. printf("ServerChallenge = %lx %lx\n",
  839. ((DWORD *)&ServerChallenge)[0],
  840. ((DWORD *)&ServerChallenge)[1]);
  841. Password.Length =
  842. Password.MaximumLength = wcslen(MachineName) * sizeof(WCHAR);
  843. Password.Buffer = MachineName;
  844. //
  845. // Compute the NT OWF password for this user.
  846. //
  847. Status = RtlCalculateNtOwfPassword( &Password, &NtOwfPassword );
  848. if ( !NT_SUCCESS( Status ) ) {
  849. fprintf(stderr, "Can't compute OWF password 0x%lx \n", Status );
  850. return(Status);
  851. }
  852. printf("Password = %lx %lx %lx %lx\n",
  853. ((DWORD *) (&NtOwfPassword))[0],
  854. ((DWORD *) (&NtOwfPassword))[1],
  855. ((DWORD *) (&NtOwfPassword))[2],
  856. ((DWORD *) (&NtOwfPassword))[3]);
  857. //
  858. // Actually compute the session key given the two challenges and the
  859. // password.
  860. //
  861. NlMakeSessionKey(
  862. 0,
  863. &NtOwfPassword,
  864. &ClientChallenge,
  865. &ServerChallenge,
  866. &SessionKey );
  867. printf("SessionKey = %lx %lx %lx %lx\n",
  868. ((DWORD *) (&SessionKey))[0],
  869. ((DWORD *) (&SessionKey))[1],
  870. ((DWORD *) (&SessionKey))[2],
  871. ((DWORD *) (&SessionKey))[3]);
  872. //
  873. // Prepare credentials using our challenge.
  874. //
  875. NlComputeCredentials( &ClientChallenge,
  876. &AuthenticationSeed,
  877. &SessionKey );
  878. printf("ClientCredential = %lx %lx\n",
  879. ((DWORD *) (&AuthenticationSeed))[0],
  880. ((DWORD *) (&AuthenticationSeed))[1]);
  881. //
  882. // Send these credentials to primary. The primary will compute
  883. // credentials using the challenge supplied by us and compare
  884. // with these. If both match then it will compute credentials
  885. // using its challenge and return it to us for verification
  886. //
  887. wcscpy( AccountName, MachineName );
  888. wcscat( AccountName, SSI_ACCOUNT_NAME_POSTFIX);
  889. Status = I_NetServerAuthenticate( PdcName,
  890. AccountName,
  891. ServerSecureChannel,
  892. MachineName,
  893. &AuthenticationSeed,
  894. &ReturnedServerCredential );
  895. if ( !NT_SUCCESS( Status ) ) {
  896. fprintf(stderr,
  897. "I_NetServerAuthenticate to " FORMAT_LPWSTR " 0x%lx\n",
  898. &PdcName,
  899. Status );
  900. return(Status);
  901. }
  902. printf("ServerCredential GOT = %lx %lx\n",
  903. ((DWORD *) (&ReturnedServerCredential))[0],
  904. ((DWORD *) (&ReturnedServerCredential))[1]);
  905. //
  906. // The DC returned a server credential to us,
  907. // ensure the server credential matches the one we would compute.
  908. //
  909. NlComputeCredentials( &ServerChallenge,
  910. &ComputedServerCredential,
  911. &SessionKey);
  912. printf("ServerCredential MADE =%lx %lx\n",
  913. ((DWORD *) (&ComputedServerCredential))[0],
  914. ((DWORD *) (&ComputedServerCredential))[1]);
  915. if (RtlCompareMemory( &ReturnedServerCredential,
  916. &ComputedServerCredential,
  917. sizeof(ReturnedServerCredential)) !=
  918. sizeof(ReturnedServerCredential)) {
  919. fprintf( stderr, "Access Denied \n");
  920. return( STATUS_ACCESS_DENIED );
  921. }
  922. printf("Session Setup to " FORMAT_LPWSTR " completed successfully \n",
  923. PdcName);
  924. //
  925. // retrive database info
  926. //
  927. for( DatabaseIndex = 0 ; DatabaseIndex < 3; DatabaseIndex++) {
  928. SamSyncContext = 0;
  929. for( i = 0; ; i++) {
  930. NlBuildAuthenticator(
  931. &AuthenticationSeed,
  932. &SessionKey,
  933. &OurAuthenticator);
  934. Status = I_NetDatabaseSync(
  935. PdcName,
  936. MachineName,
  937. &OurAuthenticator,
  938. &ReturnAuthenticator,
  939. DatabaseIndex,
  940. &SamSyncContext,
  941. &DeltaArray,
  942. 128 * 1024 ); // 128K
  943. if ( !NT_SUCCESS( Status ) ) {
  944. fprintf( stderr,
  945. "I_NetDatabaseSync to " FORMAT_LPWSTR " failed 0x%lx\n",
  946. PdcName,
  947. Status );
  948. return(Status);
  949. }
  950. if ( ( !NlUpdateSeed(
  951. &AuthenticationSeed,
  952. &ReturnAuthenticator.Credential,
  953. &SessionKey) ) ) {
  954. fprintf(stderr, "NlUpdateSeed failed \n" );
  955. return( STATUS_ACCESS_DENIED );
  956. }
  957. printf( "Received %ld Buffer data \n", i);
  958. //
  959. // ignore return data
  960. //
  961. MIDL_user_free( DeltaArray );
  962. if ( Status == STATUS_SUCCESS ) {
  963. break;
  964. }
  965. }
  966. printf("FullSync replication of database %ld completed "
  967. "successfully \n", DatabaseIndex );
  968. }
  969. return Status;
  970. }
  971. LONG
  972. ForceRegOpenSubkey(
  973. HKEY ParentHandle,
  974. LPSTR KeyName,
  975. LPSTR Subkey,
  976. REGSAM DesiredAccess,
  977. PHKEY ReturnHandle
  978. )
  979. /*++
  980. Routine Description:
  981. Open the specified key one subkey at a time defeating access denied by
  982. setting the DACL to allow us access. This kludge is needed since the
  983. security tree is shipped not allowing Administrators access.
  984. Arguments:
  985. ParentHandle - Currently open handle
  986. KeyName - Entire key name (for error messages only)
  987. Subkey - Direct subkey of ParentHandle
  988. DesiredAccess - Desired access to the new key
  989. ReturnHandle - Returns an open handle to the newly opened key.
  990. Return Value:
  991. Return TRUE for success.
  992. --*/
  993. {
  994. LONG RegStatus;
  995. LONG SavedStatus;
  996. HKEY TempHandle = NULL;
  997. BOOLEAN DaclChanged = FALSE;
  998. SECURITY_INFORMATION SecurityInformation = DACL_SECURITY_INFORMATION;
  999. DWORD OldSecurityDescriptorSize;
  1000. CHAR OldSecurityDescriptor[1024];
  1001. CHAR NewSecurityDescriptor[1024];
  1002. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1003. PSID AdminSid = NULL;
  1004. BOOL DaclPresent;
  1005. BOOL DaclDefaulted;
  1006. PACL Dacl;
  1007. ACL_SIZE_INFORMATION AclSizeInfo;
  1008. ACCESS_ALLOWED_ACE *Ace;
  1009. DWORD i;
  1010. //
  1011. // Open the sub-key
  1012. //
  1013. SavedStatus = RegOpenKeyExA(
  1014. ParentHandle,
  1015. Subkey,
  1016. 0, //Reserved
  1017. DesiredAccess,
  1018. ReturnHandle );
  1019. if ( SavedStatus != ERROR_ACCESS_DENIED ) {
  1020. return SavedStatus;
  1021. }
  1022. //
  1023. // If access is denied,
  1024. // try changing the DACL to give us access
  1025. //
  1026. // printf( "Cannot RegOpenKey %s subkey %s ", KeyName, Subkey );
  1027. // PrintStatus( SavedStatus );
  1028. //
  1029. // Open again asking to change the DACL
  1030. //
  1031. RegStatus = RegOpenKeyExA(
  1032. ParentHandle,
  1033. Subkey,
  1034. 0, //Reserved
  1035. WRITE_DAC | READ_CONTROL,
  1036. &TempHandle );
  1037. if ( RegStatus != ERROR_SUCCESS) {
  1038. printf( "Cannot RegOpenKey to change DACL %s subkey %s ", KeyName, Subkey );
  1039. PrintStatus( RegStatus );
  1040. goto Cleanup;
  1041. }
  1042. //
  1043. // Get the current DACL so we can restore it.
  1044. //
  1045. OldSecurityDescriptorSize = sizeof(OldSecurityDescriptor);
  1046. RegStatus = RegGetKeySecurity(
  1047. TempHandle,
  1048. SecurityInformation,
  1049. (PSECURITY_DESCRIPTOR) OldSecurityDescriptor,
  1050. &OldSecurityDescriptorSize );
  1051. if ( RegStatus != ERROR_SUCCESS ) {
  1052. printf( "Cannot RegGetKeySecurity for %s subkey %s ", KeyName, Subkey );
  1053. PrintStatus( RegStatus );
  1054. goto Cleanup;
  1055. }
  1056. //
  1057. // Build the Administrators SID
  1058. //
  1059. if ( !AllocateAndInitializeSid( &NtAuthority,
  1060. 2, // two subauthorities
  1061. SECURITY_BUILTIN_DOMAIN_RID,
  1062. DOMAIN_ALIAS_RID_ADMINS,
  1063. 0,
  1064. 0,
  1065. 0,
  1066. 0,
  1067. 0,
  1068. 0,
  1069. &AdminSid ) ) {
  1070. printf( "Cannot AllocateAndInitializeSid " );
  1071. PrintStatus( GetLastError() );
  1072. goto Cleanup;
  1073. }
  1074. //
  1075. // Change the DACL to allow all access
  1076. //
  1077. RtlCopyMemory( NewSecurityDescriptor,
  1078. OldSecurityDescriptor,
  1079. OldSecurityDescriptorSize );
  1080. if ( !GetSecurityDescriptorDacl(
  1081. (PSECURITY_DESCRIPTOR)NewSecurityDescriptor,
  1082. &DaclPresent,
  1083. &Dacl,
  1084. &DaclDefaulted )) {
  1085. printf( "Cannot GetSecurityDescriptorDacl for %s subkey %s ", KeyName, Subkey );
  1086. PrintStatus( GetLastError() );
  1087. goto Cleanup;
  1088. }
  1089. if ( !DaclPresent ) {
  1090. printf( "Cannot GetSecurityDescriptorDacl " );
  1091. printf( "Cannot DaclNotPresent for %s subkey %s ", KeyName, Subkey );
  1092. goto Cleanup;
  1093. }
  1094. if ( !GetAclInformation(
  1095. Dacl,
  1096. &AclSizeInfo,
  1097. sizeof(AclSizeInfo),
  1098. AclSizeInformation )) {
  1099. printf( "Cannot GetAclInformation for %s subkey %s ", KeyName, Subkey );
  1100. PrintStatus( GetLastError() );
  1101. goto Cleanup;
  1102. }
  1103. //
  1104. // Search for an administrators ACE and give it "DesiredAccess"
  1105. //
  1106. for ( i=0; i<AclSizeInfo.AceCount ; i++ ) {
  1107. if ( !GetAce( Dacl, i, (LPVOID *) &Ace ) ) {
  1108. printf( "Cannot GetAce %ld for %s subkey %s ", i, KeyName, Subkey );
  1109. PrintStatus( GetLastError() );
  1110. goto Cleanup;
  1111. }
  1112. if ( Ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE ) {
  1113. continue;
  1114. }
  1115. if ( !EqualSid( AdminSid, (PSID)&Ace->SidStart ) ) {
  1116. continue;
  1117. }
  1118. Ace->Mask |= DesiredAccess;
  1119. break;
  1120. }
  1121. if ( i >= AclSizeInfo.AceCount ) {
  1122. printf( "No Administrators Ace for %s subkey %s\n", KeyName, Subkey );
  1123. goto Cleanup;
  1124. }
  1125. //
  1126. // Actually set the new DACL on the key
  1127. //
  1128. RegStatus = RegSetKeySecurity(
  1129. TempHandle,
  1130. SecurityInformation,
  1131. (PSECURITY_DESCRIPTOR)NewSecurityDescriptor );
  1132. if ( RegStatus != ERROR_SUCCESS ) {
  1133. printf( "Cannot RegSetKeySecurity for %s subkey %s ", KeyName, Subkey );
  1134. PrintStatus( RegStatus );
  1135. goto Cleanup;
  1136. }
  1137. DaclChanged = TRUE;
  1138. //
  1139. // Open the sub-key again with the desired access
  1140. //
  1141. SavedStatus = RegOpenKeyExA(
  1142. ParentHandle,
  1143. Subkey,
  1144. 0, //Reserved
  1145. DesiredAccess,
  1146. ReturnHandle );
  1147. if ( SavedStatus != ERROR_SUCCESS ) {
  1148. printf( "Cannot RegOpenKeyEx following DACL change for %s subkey %s ", KeyName, Subkey );
  1149. PrintStatus( SavedStatus );
  1150. goto Cleanup;
  1151. }
  1152. Cleanup:
  1153. if ( TempHandle != NULL ) {
  1154. //
  1155. // Restore DACL to original value.
  1156. //
  1157. if ( DaclChanged ) {
  1158. RegStatus = RegSetKeySecurity(
  1159. TempHandle,
  1160. SecurityInformation,
  1161. (PSECURITY_DESCRIPTOR)OldSecurityDescriptor );
  1162. if ( RegStatus != ERROR_SUCCESS ) {
  1163. printf( "Cannot RegSetKeySecurity to restore %s subkey %s ", KeyName, Subkey );
  1164. PrintStatus( RegStatus );
  1165. goto Cleanup;
  1166. }
  1167. }
  1168. (VOID) RegCloseKey( TempHandle );
  1169. }
  1170. if ( AdminSid != NULL ) {
  1171. (VOID) FreeSid( AdminSid );
  1172. }
  1173. return SavedStatus;
  1174. }
  1175. LONG
  1176. ForceRegOpenKey(
  1177. HKEY BaseHandle,
  1178. LPSTR KeyName,
  1179. REGSAM DesiredAccess,
  1180. PHKEY ReturnHandle
  1181. )
  1182. /*++
  1183. Routine Description:
  1184. Open the specified key one subkey at a time defeating access denied by
  1185. setting the DACL to allow us access. This kludge is needed since the
  1186. security tree is shipped not allowing Administrators access.
  1187. Arguments:
  1188. BaseHandle - Currently open handle
  1189. KeyName - Registry key to open relative to BaseHandle.
  1190. DesiredAccess - Desired access to the new key
  1191. ReturnHandle - Returns an open handle to the newly opened key.
  1192. Return Value:
  1193. Return TRUE for success.
  1194. --*/
  1195. {
  1196. LONG RegStatus;
  1197. PCHAR StartOfSubkey;
  1198. PCHAR EndOfSubkey;
  1199. CHAR Subkey[512];
  1200. HKEY ParentHandle;
  1201. ASSERT( KeyName[0] != '\0' );
  1202. //
  1203. // Loop opening the next subkey.
  1204. //
  1205. EndOfSubkey = KeyName;
  1206. ParentHandle = BaseHandle;
  1207. for (;;) {
  1208. //
  1209. // Compute the name of the next subkey.
  1210. //
  1211. StartOfSubkey = EndOfSubkey;
  1212. for ( ;; ) {
  1213. if ( *EndOfSubkey == '\0' || *EndOfSubkey == '\\' ) {
  1214. strncpy( Subkey, StartOfSubkey, (int)(EndOfSubkey-StartOfSubkey) );
  1215. Subkey[EndOfSubkey-StartOfSubkey] = '\0';
  1216. if ( *EndOfSubkey == '\\' ) {
  1217. EndOfSubkey ++;
  1218. }
  1219. break;
  1220. }
  1221. EndOfSubkey ++;
  1222. }
  1223. //
  1224. // Open the sub-key
  1225. //
  1226. RegStatus = ForceRegOpenSubkey(
  1227. ParentHandle,
  1228. KeyName,
  1229. Subkey,
  1230. DesiredAccess,
  1231. ReturnHandle );
  1232. //
  1233. // Close the parent handle and return any error condition.
  1234. //
  1235. if ( ParentHandle != BaseHandle ) {
  1236. (VOID) RegCloseKey( ParentHandle );
  1237. }
  1238. if( RegStatus != ERROR_SUCCESS ) {
  1239. *ReturnHandle = NULL;
  1240. return RegStatus;
  1241. }
  1242. //
  1243. // If this is the entire key name,
  1244. // we're done.
  1245. //
  1246. if ( *EndOfSubkey == '\0' ) {
  1247. return ERROR_SUCCESS;
  1248. }
  1249. ParentHandle = *ReturnHandle;
  1250. }
  1251. }
  1252. struct {
  1253. LPSTR Name;
  1254. enum {
  1255. UnicodeStringType,
  1256. HexDataType,
  1257. LmPasswordType,
  1258. NtPasswordType
  1259. } Type;
  1260. } UserVariableDataTypes[] = {
  1261. { "SecurityDescriptor" , HexDataType },
  1262. { "AccountName" , UnicodeStringType },
  1263. { "FullName" , UnicodeStringType },
  1264. { "AdminComment" , UnicodeStringType },
  1265. { "UserComment" , UnicodeStringType },
  1266. { "Parameters" , UnicodeStringType },
  1267. { "HomeDirectory" , UnicodeStringType },
  1268. { "HomeDirectoryDrive" , UnicodeStringType },
  1269. { "ScriptPath" , UnicodeStringType },
  1270. { "ProfilePath" , UnicodeStringType },
  1271. { "Workstations" , UnicodeStringType },
  1272. { "LogonHours" , HexDataType },
  1273. { "Groups" , HexDataType },
  1274. { "LmOwfPassword" , LmPasswordType },
  1275. { "NtOwfPassword" , NtPasswordType },
  1276. { "NtPasswordHistory" , HexDataType },
  1277. { "LmPasswordHistory" , HexDataType }
  1278. };
  1279. VOID
  1280. PrintUserInfo(
  1281. IN LPWSTR ServerName,
  1282. IN LPSTR UserName
  1283. )
  1284. /*++
  1285. Routine Description:
  1286. Print a user's description from the SAM database
  1287. Arguments:
  1288. ServerName - Name of server to query
  1289. UserName - Name of user to query
  1290. Return Value:
  1291. None
  1292. --*/
  1293. {
  1294. NTSTATUS Status;
  1295. LONG RegStatus;
  1296. ULONG i;
  1297. HKEY BaseHandle = NULL;
  1298. HKEY UserHandle = NULL;
  1299. HKEY RidHandle = NULL;
  1300. CHAR UserKey[200];
  1301. CHAR RidKey[200];
  1302. LONG Rid;
  1303. CHAR AnsiRid[20];
  1304. CHAR FixedData[1000];
  1305. ULONG FixedDataSize;
  1306. SAMP_V1_0A_FIXED_LENGTH_USER FixedUser1_0A;
  1307. PSAMP_V1_0A_FIXED_LENGTH_USER f;
  1308. PSAMP_V1_0_FIXED_LENGTH_USER f1_0;
  1309. BOOLEAN IsVersion1_0;
  1310. CHAR VariableData[32768];
  1311. ULONG VariableDataSize;
  1312. PSAMP_VARIABLE_LENGTH_ATTRIBUTE v;
  1313. LM_OWF_PASSWORD LmOwfPassword;
  1314. NT_OWF_PASSWORD NtOwfPassword;
  1315. //
  1316. // Open the registry
  1317. //
  1318. RegStatus = RegConnectRegistryW( ServerName,
  1319. HKEY_LOCAL_MACHINE,
  1320. &BaseHandle);
  1321. if ( RegStatus != ERROR_SUCCESS ) {
  1322. printf( "Cannot connect to registy on " FORMAT_LPWSTR " ", ServerName );
  1323. PrintStatus( RegStatus );
  1324. goto Cleanup;
  1325. }
  1326. //
  1327. // Open the key for this user name.
  1328. //
  1329. strcpy( UserKey, "SAM\\SAM\\Domains\\Account\\Users\\Names\\" );
  1330. strcat( UserKey, UserName );
  1331. RegStatus = ForceRegOpenKey( BaseHandle,
  1332. UserKey,
  1333. KEY_READ|KEY_QUERY_VALUE,
  1334. &UserHandle );
  1335. if ( RegStatus != ERROR_SUCCESS ) {
  1336. printf( "Cannot open %s ", UserKey );
  1337. PrintStatus( RegStatus );
  1338. goto Cleanup;
  1339. }
  1340. //
  1341. // Get the RID of the user
  1342. //
  1343. RegStatus = RegQueryValueExW( UserHandle,
  1344. NULL, // No name
  1345. NULL, // Reserved
  1346. &Rid, // Really the type
  1347. NULL, // Data not needed
  1348. NULL); // Data not needed
  1349. if ( RegStatus != ERROR_SUCCESS ) {
  1350. printf( "Cannot Query %s ", UserKey );
  1351. PrintStatus( RegStatus );
  1352. goto Cleanup;
  1353. }
  1354. printf( "User: %s\nRid: 0x%lx\n",
  1355. UserName,
  1356. Rid );
  1357. //
  1358. // Open the key for this user rid.
  1359. //
  1360. sprintf( AnsiRid, "%8.8lx", Rid );
  1361. strcpy( RidKey, "SAM\\SAM\\Domains\\Account\\Users\\" );
  1362. strcat( RidKey, AnsiRid );
  1363. RegStatus = ForceRegOpenKey( BaseHandle,
  1364. RidKey,
  1365. KEY_READ|KEY_QUERY_VALUE,
  1366. &RidHandle );
  1367. if ( RegStatus != ERROR_SUCCESS ) {
  1368. printf( "Cannot open %s ", RidKey );
  1369. PrintStatus( RegStatus );
  1370. goto Cleanup;
  1371. }
  1372. //
  1373. // Get the Fixed Values associated with this RID
  1374. //
  1375. FixedDataSize = sizeof(FixedData);
  1376. RegStatus = RegQueryValueExA( RidHandle,
  1377. "F", // Fixed value
  1378. NULL, // Reserved
  1379. NULL, // Type Not Needed
  1380. FixedData,
  1381. &FixedDataSize );
  1382. if ( RegStatus != ERROR_SUCCESS ) {
  1383. printf( "Cannot Query %s ", RidKey );
  1384. PrintStatus( RegStatus );
  1385. goto Cleanup;
  1386. }
  1387. //
  1388. // If the fixed length data is NT 3.1,
  1389. // convert it to NT 3.5x format.
  1390. //
  1391. if ( IsVersion1_0 = (FixedDataSize == sizeof(*f1_0)) ) {
  1392. f1_0 = (PSAMP_V1_0_FIXED_LENGTH_USER) &FixedData;
  1393. FixedUser1_0A.LastLogon = f1_0->LastLogon;
  1394. FixedUser1_0A.LastLogoff = f1_0->LastLogoff;
  1395. FixedUser1_0A.PasswordLastSet = f1_0->PasswordLastSet;
  1396. FixedUser1_0A.AccountExpires = f1_0->AccountExpires;
  1397. FixedUser1_0A.UserId = f1_0->UserId;
  1398. FixedUser1_0A.PrimaryGroupId = f1_0->PrimaryGroupId;
  1399. FixedUser1_0A.UserAccountControl = f1_0->UserAccountControl;
  1400. FixedUser1_0A.CountryCode = f1_0->CountryCode;
  1401. FixedUser1_0A.BadPasswordCount = f1_0->BadPasswordCount;
  1402. FixedUser1_0A.LogonCount = f1_0->LogonCount;
  1403. FixedUser1_0A.AdminCount = f1_0->AdminCount;
  1404. RtlCopyMemory( FixedData, &FixedUser1_0A, sizeof(FixedUser1_0A) );
  1405. }
  1406. //
  1407. // Print the fixed length data.
  1408. //
  1409. f = (PSAMP_V1_0A_FIXED_LENGTH_USER) &FixedData;
  1410. if ( !IsVersion1_0) {
  1411. printf( "Version: 0x%lx\n", f->Revision );
  1412. }
  1413. PrintTime( "LastLogon: ", f->LastLogon );
  1414. PrintTime( "LastLogoff: ", f->LastLogoff );
  1415. PrintTime( "PasswordLastSet: ", f->PasswordLastSet );
  1416. PrintTime( "AccountExpires: ", f->AccountExpires );
  1417. if ( !IsVersion1_0) {
  1418. PrintTime( "LastBadPasswordTime: ", f->LastBadPasswordTime );
  1419. }
  1420. printf( "PrimaryGroupId: 0x%lx\n", f->PrimaryGroupId );
  1421. printf( "UserAccountControl: 0x%lx\n", f->UserAccountControl );
  1422. printf( "CountryCode: 0x%lx\n", f->CountryCode );
  1423. printf( "CodePage: 0x%lx\n", f->CodePage );
  1424. printf( "BadPasswordCount: 0x%lx\n", f->BadPasswordCount );
  1425. printf( "LogonCount: 0x%lx\n", f->LogonCount );
  1426. printf( "AdminCount: 0x%lx\n", f->AdminCount );
  1427. //
  1428. // Get the Variable Values associated with this RID
  1429. //
  1430. VariableDataSize = sizeof(VariableData);
  1431. RegStatus = RegQueryValueExA( RidHandle,
  1432. "V", // Variable value
  1433. NULL, // Reserved
  1434. NULL, // Type Not Needed
  1435. VariableData,
  1436. &VariableDataSize );
  1437. if ( RegStatus != ERROR_SUCCESS ) {
  1438. printf( "Cannot Query %s \n", RidKey );
  1439. PrintStatus( RegStatus );
  1440. goto Cleanup;
  1441. }
  1442. //
  1443. // Loop printing all the attributes.
  1444. //
  1445. v = (PSAMP_VARIABLE_LENGTH_ATTRIBUTE) VariableData;
  1446. for ( i=0;
  1447. i<sizeof(UserVariableDataTypes)/sizeof(UserVariableDataTypes[0]);
  1448. i++ ) {
  1449. UNICODE_STRING UnicodeString;
  1450. //
  1451. // Make the offset relative to the beginning of the queried value.
  1452. //
  1453. v[i].Offset += SAMP_USER_VARIABLE_ATTRIBUTES *
  1454. sizeof(SAMP_VARIABLE_LENGTH_ATTRIBUTE);
  1455. //
  1456. // Ensure the data item descriptor is in the registry.
  1457. //
  1458. if ( ((PCHAR)&v[i]) > ((PCHAR)v)+VariableDataSize ) {
  1459. printf( "Variable data desc %ld not in variable value.\n", i );
  1460. goto Cleanup;
  1461. }
  1462. if ( v[i].Offset > (LONG) VariableDataSize ||
  1463. v[i].Offset + v[i].Length > VariableDataSize ) {
  1464. printf( "Variable data item %ld not in variable value.\n", i );
  1465. printf( "Offset: %ld Length: %ld Size: %ld\n",
  1466. v[i].Offset,
  1467. v[i].Length,
  1468. VariableDataSize );
  1469. goto Cleanup;
  1470. }
  1471. //
  1472. // Don't print null data.
  1473. //
  1474. if ( v[i].Length == 0 ) {
  1475. continue;
  1476. }
  1477. //
  1478. // Print the various types of data.
  1479. //
  1480. switch ( UserVariableDataTypes[i].Type ) {
  1481. case UnicodeStringType:
  1482. UnicodeString.Buffer = (PUSHORT)(((PCHAR)v)+v[i].Offset);
  1483. UnicodeString.Length = (USHORT)v[i].Length;
  1484. printf( "%s: %wZ\n", UserVariableDataTypes[i].Name, &UnicodeString);
  1485. break;
  1486. case LmPasswordType:
  1487. Status = RtlDecryptLmOwfPwdWithIndex(
  1488. (PENCRYPTED_LM_OWF_PASSWORD)(((PCHAR)v)+v[i].Offset),
  1489. &Rid,
  1490. &LmOwfPassword );
  1491. if ( !NT_SUCCESS( Status ) ) {
  1492. printf( "Cannot decrypt LM password: " );
  1493. PrintStatus( Status );
  1494. goto Cleanup;
  1495. }
  1496. printf( "%s: ", UserVariableDataTypes[i].Name);
  1497. DumpBuffer( &LmOwfPassword, sizeof(LmOwfPassword ));
  1498. break;
  1499. case NtPasswordType:
  1500. Status = RtlDecryptNtOwfPwdWithIndex(
  1501. (PENCRYPTED_NT_OWF_PASSWORD)(((PCHAR)v)+v[i].Offset),
  1502. &Rid,
  1503. &NtOwfPassword );
  1504. if ( !NT_SUCCESS( Status ) ) {
  1505. printf( "Cannot decrypt NT password: " );
  1506. PrintStatus( Status );
  1507. goto Cleanup;
  1508. }
  1509. printf( "%s: ", UserVariableDataTypes[i].Name);
  1510. DumpBuffer( &NtOwfPassword, sizeof(NtOwfPassword ));
  1511. break;
  1512. case HexDataType:
  1513. printf( "%s: ", UserVariableDataTypes[i].Name);
  1514. DumpBuffer( (((PCHAR)v)+v[i].Offset), v[i].Length );
  1515. break;
  1516. }
  1517. }
  1518. //
  1519. // Be tidy.
  1520. //
  1521. Cleanup:
  1522. if ( UserHandle != NULL ) {
  1523. RegCloseKey( UserHandle );
  1524. }
  1525. if ( RidHandle != NULL ) {
  1526. RegCloseKey( RidHandle );
  1527. }
  1528. if ( BaseHandle != NULL ) {
  1529. RegCloseKey( BaseHandle );
  1530. }
  1531. return;
  1532. }
  1533. VOID
  1534. SetDbflagInRegistry(
  1535. LPWSTR ServerName,
  1536. ULONG DbFlagValue
  1537. )
  1538. /*++
  1539. Routine Description:
  1540. Set the value DbFlagValue in the Netlogon service portion of the registry.
  1541. Arguments:
  1542. ServerName - Name of the server to update
  1543. DbFlagValue - Value to set dbflag to.
  1544. Return Value:
  1545. None.
  1546. --*/
  1547. {
  1548. LONG RegStatus;
  1549. UCHAR AnsiDbFlag[20];
  1550. DWORD AnsiDbFlagLength;
  1551. HKEY BaseHandle = NULL;
  1552. HKEY ParmHandle = NULL;
  1553. LPSTR KeyName;
  1554. //
  1555. // Open the registry
  1556. //
  1557. RegStatus = RegConnectRegistryW( ServerName,
  1558. HKEY_LOCAL_MACHINE,
  1559. &BaseHandle);
  1560. if ( RegStatus != ERROR_SUCCESS ) {
  1561. printf( "Cannot connect to registy on " FORMAT_LPWSTR " ", ServerName );
  1562. PrintStatus( RegStatus );
  1563. goto Cleanup;
  1564. }
  1565. //
  1566. // Open the key for Netlogon\parameters.
  1567. //
  1568. KeyName = NL_PARAM_KEY;
  1569. RegStatus = ForceRegOpenKey(
  1570. BaseHandle,
  1571. KeyName,
  1572. KEY_SET_VALUE,
  1573. &ParmHandle );
  1574. if ( RegStatus != ERROR_SUCCESS ) {
  1575. printf( "Cannot open " NL_PARAM_KEY );
  1576. PrintStatus( RegStatus );
  1577. goto Cleanup;
  1578. }
  1579. //
  1580. // Set the DbFlag value into the registry.
  1581. //
  1582. AnsiDbFlagLength = sprintf( AnsiDbFlag, "0x%8.8lx", DbFlagValue );
  1583. RegStatus = RegSetValueExA( ParmHandle,
  1584. "DbFlag",
  1585. 0, // Reserved
  1586. REG_SZ,
  1587. AnsiDbFlag,
  1588. AnsiDbFlagLength + 1 );
  1589. if ( RegStatus != ERROR_SUCCESS ) {
  1590. printf( "Cannot Set %s:", KeyName );
  1591. PrintStatus( RegStatus );
  1592. goto Cleanup;
  1593. }
  1594. printf( "%s set to %s\n", KeyName, AnsiDbFlag );
  1595. //
  1596. // Be tidy.
  1597. //
  1598. Cleanup:
  1599. if ( ParmHandle != NULL ) {
  1600. RegCloseKey( ParmHandle );
  1601. }
  1602. if ( BaseHandle != NULL ) {
  1603. RegCloseKey( BaseHandle );
  1604. }
  1605. return;
  1606. }
  1607. VOID
  1608. StopService(
  1609. LPWSTR ServiceName
  1610. )
  1611. /*++
  1612. Routine Description:
  1613. Stop the named service.
  1614. Arguments:
  1615. ServiceName (Name of service to stop)
  1616. None.
  1617. Return Status:
  1618. STATUS_SUCCESS - Indicates service successfully stopped
  1619. STATUS_NETLOGON_NOT_STARTED - Timeout occurred.
  1620. --*/
  1621. {
  1622. NTSTATUS Status;
  1623. NET_API_STATUS NetStatus;
  1624. SC_HANDLE ScManagerHandle = NULL;
  1625. SC_HANDLE ServiceHandle = NULL;
  1626. SERVICE_STATUS ServiceStatus;
  1627. DWORD Timeout;
  1628. //
  1629. // Open a handle to the Service.
  1630. //
  1631. ScManagerHandle = OpenSCManager(
  1632. NULL,
  1633. NULL,
  1634. SC_MANAGER_CONNECT );
  1635. if (ScManagerHandle == NULL) {
  1636. NetStatus = GetLastError();
  1637. printf( "OpenSCManager failed: " );
  1638. PrintStatus( NetStatus );
  1639. goto Cleanup;
  1640. }
  1641. ServiceHandle = OpenService(
  1642. ScManagerHandle,
  1643. ServiceName,
  1644. SERVICE_QUERY_STATUS |
  1645. SERVICE_INTERROGATE |
  1646. SERVICE_ENUMERATE_DEPENDENTS |
  1647. SERVICE_STOP |
  1648. SERVICE_QUERY_CONFIG );
  1649. if ( ServiceHandle == NULL ) {
  1650. NetStatus = GetLastError();
  1651. printf( "OpenService [%ws] failed: ", ServiceName );
  1652. PrintStatus( NetStatus );
  1653. goto Cleanup;
  1654. }
  1655. //
  1656. // Ask the service to stop.
  1657. //
  1658. if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) ) {
  1659. NetStatus = GetLastError();
  1660. //
  1661. // If there are dependent services running,
  1662. // determine their names and stop them.
  1663. //
  1664. if ( NetStatus == ERROR_DEPENDENT_SERVICES_RUNNING ) {
  1665. BYTE ConfigBuffer[4096];
  1666. LPENUM_SERVICE_STATUS ServiceConfig = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
  1667. DWORD BytesNeeded;
  1668. DWORD ServiceCount;
  1669. DWORD ServiceIndex;
  1670. //
  1671. // Get the names of the dependent services.
  1672. //
  1673. if ( !EnumDependentServicesW( ServiceHandle,
  1674. SERVICE_ACTIVE,
  1675. ServiceConfig,
  1676. sizeof(ConfigBuffer),
  1677. &BytesNeeded,
  1678. &ServiceCount ) ) {
  1679. NetStatus = GetLastError();
  1680. printf( "EnumDependentServicesW [Stop %ws] failed: ", ServiceName );
  1681. PrintStatus( NetStatus );
  1682. goto Cleanup;
  1683. }
  1684. //
  1685. // Stop those services.
  1686. //
  1687. for ( ServiceIndex=0; ServiceIndex<ServiceCount; ServiceIndex++ ) {
  1688. StopService( ServiceConfig[ServiceIndex].lpServiceName );
  1689. }
  1690. //
  1691. // Ask the original service to stop.
  1692. //
  1693. if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) ) {
  1694. NetStatus = GetLastError();
  1695. printf( "ControlService [Stop %ws] failed: ", ServiceName );
  1696. PrintStatus( NetStatus );
  1697. goto Cleanup;
  1698. }
  1699. } else {
  1700. printf( "ControlService [Stop %ws] failed: ", ServiceName );
  1701. PrintStatus( NetStatus );
  1702. goto Cleanup;
  1703. }
  1704. }
  1705. printf( "%ws service is stopping", ServiceName );
  1706. //
  1707. // Loop waiting for the service to stop.
  1708. //
  1709. for ( Timeout=0; Timeout<45; Timeout++ ) {
  1710. //
  1711. // Return or continue waiting depending on the state of
  1712. // the service.
  1713. //
  1714. if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED ) {
  1715. printf( "\n" );
  1716. goto Cleanup;
  1717. }
  1718. //
  1719. // Wait a second for the service to finish stopping.
  1720. //
  1721. Sleep( 1000 );
  1722. printf( "." );
  1723. //
  1724. // Query the status of the service again.
  1725. //
  1726. if (! QueryServiceStatus( ServiceHandle, &ServiceStatus )) {
  1727. NetStatus = GetLastError();
  1728. printf( "\nQueryServiceStatus [%ws] failed: ", ServiceName );
  1729. PrintStatus( NetStatus );
  1730. goto Cleanup;
  1731. }
  1732. }
  1733. printf( "%ws service failed to stop\n", ServiceName );
  1734. Cleanup:
  1735. if ( ScManagerHandle != NULL ) {
  1736. (VOID) CloseServiceHandle(ScManagerHandle);
  1737. }
  1738. if ( ServiceHandle != NULL ) {
  1739. (VOID) CloseServiceHandle(ServiceHandle);
  1740. }
  1741. return;
  1742. }
  1743. BOOL
  1744. GetDcListFromDs(
  1745. IN LPWSTR DomainName
  1746. )
  1747. /*++
  1748. Routine Description:
  1749. Get a list of DCs in this domain from the DS on an up DC.
  1750. Arguments:
  1751. DomainName - Domain to get the DC list for
  1752. Return Value:
  1753. TRUE: Test suceeded.
  1754. FALSE: Test failed
  1755. --*/
  1756. {
  1757. NET_API_STATUS NetStatus;
  1758. PDS_DOMAIN_CONTROLLER_INFO_1W DsDcInfo = NULL;
  1759. PDOMAIN_CONTROLLER_INFOW DcInfo = NULL;
  1760. HANDLE DsHandle = NULL;
  1761. DWORD DsDcCount = 0;
  1762. BOOL RetVal = TRUE;
  1763. ULONG i;
  1764. ULONG DnsLength;
  1765. //
  1766. // Get a DC to seed the algorithm with
  1767. //
  1768. NetStatus = DsGetDcName( NULL,
  1769. DomainName,
  1770. NULL,
  1771. NULL,
  1772. DS_DIRECTORY_SERVICE_PREFERRED,
  1773. &DcInfo );
  1774. if ( NetStatus != NO_ERROR ) {
  1775. printf("Cannot find DC to get DC list from." );
  1776. PrintStatus( NetStatus );
  1777. RetVal = TRUE;
  1778. goto Cleanup;
  1779. }
  1780. if ( (DcInfo->Flags & DS_DS_FLAG) == 0 ) {
  1781. printf( "Domain '%ws' is pre Windows 2000 domain. (Using NetServerEnum).\n",
  1782. DomainName );
  1783. RetVal = FALSE;
  1784. goto Cleanup;
  1785. }
  1786. printf("Get list of DCs in domain '%ws' from '%ws'.\n",
  1787. DomainName,
  1788. DcInfo->DomainControllerName );
  1789. //
  1790. // Bind to the target DC
  1791. //
  1792. NetStatus = DsBindW( DcInfo->DomainControllerName,
  1793. NULL,
  1794. &DsHandle );
  1795. if ( NetStatus != NO_ERROR ) {
  1796. //
  1797. // Only warn if we don't have access
  1798. //
  1799. if ( NetStatus == ERROR_ACCESS_DENIED ) {
  1800. printf("You don't have access to DsBind to %ws (%ws) (Trying NetServerEnum).\n",
  1801. DomainName,
  1802. DcInfo->DomainControllerName );
  1803. } else {
  1804. printf("Cannot DsBind to %ws (%ws).",
  1805. DomainName,
  1806. DcInfo->DomainControllerName );
  1807. PrintStatus( NetStatus );
  1808. }
  1809. RetVal = FALSE;
  1810. goto Cleanup;
  1811. }
  1812. //
  1813. // Get the list of DCs from the target DC.
  1814. //
  1815. NetStatus = DsGetDomainControllerInfoW(
  1816. DsHandle,
  1817. DcInfo->DomainName,
  1818. 1, // Info level
  1819. &DsDcCount,
  1820. &DsDcInfo );
  1821. if ( NetStatus != NO_ERROR ) {
  1822. printf("Cannot call DsGetDomainControllerInfoW to %ws (%ws).",
  1823. DomainName,
  1824. DcInfo->DomainControllerName );
  1825. PrintStatus( NetStatus );
  1826. RetVal = FALSE;
  1827. goto Cleanup;
  1828. }
  1829. //
  1830. // Compute the length of the
  1831. DnsLength = 1;
  1832. for ( i=0; i<DsDcCount; i++ ) {
  1833. ULONG Length;
  1834. Length = wcslen( DsDcInfo[i].DnsHostName != NULL ?
  1835. DsDcInfo[i].DnsHostName :
  1836. DsDcInfo[i].NetbiosName );
  1837. DnsLength = max( DnsLength, Length );
  1838. }
  1839. DnsLength = min( DnsLength, 50 );
  1840. //
  1841. // Loop though the list of DCs.
  1842. //
  1843. for ( i=0; i<DsDcCount; i++ ) {
  1844. printf(" %*ws",
  1845. DnsLength,
  1846. DsDcInfo[i].DnsHostName != NULL ?
  1847. DsDcInfo[i].DnsHostName :
  1848. DsDcInfo[i].NetbiosName );
  1849. if ( DsDcInfo[i].fIsPdc ) {
  1850. printf(" [PDC]");
  1851. } else {
  1852. printf(" ");
  1853. }
  1854. if ( DsDcInfo[i].fDsEnabled ) {
  1855. printf(" [DS]");
  1856. } else {
  1857. printf(" ");
  1858. }
  1859. if ( DsDcInfo[i].SiteName != NULL ) {
  1860. printf(" Site: %ws", DsDcInfo[i].SiteName );
  1861. }
  1862. printf("\n");
  1863. }
  1864. //
  1865. // Cleanup locally used resources
  1866. //
  1867. Cleanup:
  1868. if ( DsDcInfo != NULL ) {
  1869. DsFreeDomainControllerInfoW( 1, DsDcCount, DsDcInfo );
  1870. }
  1871. if ( DsHandle != NULL ) {
  1872. DsUnBindW( &DsHandle );
  1873. }
  1874. return RetVal;
  1875. }
  1876. NET_API_STATUS
  1877. NetpSockAddrToStr(
  1878. PSOCKADDR SockAddr,
  1879. ULONG SockAddrSize,
  1880. CHAR SockAddrString[NL_SOCK_ADDRESS_LENGTH+1]
  1881. );
  1882. int __cdecl
  1883. main(
  1884. IN int argc,
  1885. IN char ** argv
  1886. )
  1887. /*++
  1888. Routine Description:
  1889. Drive the Netlogon service by calling I_NetLogonControl2.
  1890. Arguments:
  1891. argc - the number of command-line arguments.
  1892. argv - an array of pointers to the arguments.
  1893. Return Value:
  1894. Exit status
  1895. --*/
  1896. {
  1897. NTSTATUS Status;
  1898. NET_API_STATUS NetStatus;
  1899. LPSTR argument;
  1900. int i;
  1901. DWORD FunctionCode = 0;
  1902. LPSTR AnsiServerName = NULL;
  1903. CHAR AnsiUncServerName[UNCLEN+1];
  1904. LPSTR AnsiDomainName = NULL;
  1905. LPSTR AnsiTrustedDomainName = NULL;
  1906. LPWSTR TrustedDomainName = NULL;
  1907. LPSTR AnsiUserName = NULL;
  1908. LPSTR AnsiSiteName = NULL;
  1909. #ifndef NTRK_RELEASE
  1910. LPSTR AnsiPassword = NULL;
  1911. BOOLEAN UnloadNetlogonFlag = FALSE;
  1912. #endif // NTRK_RELEASE
  1913. ULONG Rid = 0;
  1914. LPSTR AnsiSimMachineName = NULL;
  1915. LPSTR AnsiDeltaFileName = NULL;
  1916. LPSTR ShutdownReason = NULL;
  1917. LPWSTR ServerName = NULL;
  1918. LPWSTR UserName = NULL;
  1919. PNETLOGON_INFO_1 NetlogonInfo1 = NULL;
  1920. DWORD Level = 1;
  1921. DWORD ShutdownSeconds;
  1922. LPBYTE InputDataPtr = NULL;
  1923. PDOMAIN_CONTROLLER_INFOA DomainControllerInfo;
  1924. DWORD DbFlagValue;
  1925. LARGE_INTEGER ConvertTime;
  1926. ULONG IterationCount;
  1927. ULONG DsGetDcOpenFlags = 0;
  1928. NT_OWF_PASSWORD NtOwfPassword;
  1929. BOOLEAN NtPasswordPresent = FALSE;
  1930. LM_OWF_PASSWORD LmOwfPassword;
  1931. BOOLEAN LmPasswordPresent = FALSE;
  1932. BOOLEAN GetPdcName = FALSE;
  1933. BOOLEAN DoDsGetDcName = FALSE;
  1934. BOOLEAN DoDsGetDcOpen = FALSE;
  1935. BOOLEAN DoDsGetFtinfo = FALSE;
  1936. BOOLEAN DoDsGetSiteName = FALSE;
  1937. BOOLEAN DoDsGetDcSiteCoverage = FALSE;
  1938. BOOLEAN DoGetParentDomain = FALSE;
  1939. DWORD DsGetDcNameFlags = 0;
  1940. DWORD DsGetFtinfoFlags = 0;
  1941. BOOLEAN GetDcList = FALSE;
  1942. BOOLEAN WhoWill = FALSE;
  1943. BOOLEAN QuerySync = FALSE;
  1944. BOOLEAN SimFullSync = FALSE;
  1945. BOOLEAN QueryUser = FALSE;
  1946. BOOLEAN ListDeltasFlag = FALSE;
  1947. BOOLEAN ResetSecureChannelsFlag = FALSE;
  1948. BOOLEAN ShutdownAbort = FALSE;
  1949. BOOLEAN DomainTrustsFlag = FALSE;
  1950. BOOLEAN TrustedDomainsVerboseOutput = FALSE;
  1951. BOOLEAN DeregisterDnsHostRecords = FALSE;
  1952. BOOLEAN DoClientDigest = FALSE;
  1953. BOOLEAN DoServerDigest = FALSE;
  1954. char *StringGuid;
  1955. RPC_STATUS RpcStatus;
  1956. ULONG TrustsNeeded = 0;
  1957. LPSTR AnsiDnsHostName = NULL;
  1958. LPSTR AnsiDnsDomainName = NULL;
  1959. LPSTR StringDomainGuid = NULL;
  1960. LPSTR StringDsaGuid = NULL;
  1961. LPSTR Message = NULL;
  1962. #define QUERY_PARAM "/QUERY"
  1963. #define REPL_PARAM "/REPL"
  1964. #define SYNC_PARAM "/SYNC"
  1965. #define PDC_REPL_PARAM "/PDC_REPL"
  1966. #define SERVER_PARAM "/SERVER:"
  1967. #define PWD_PARAM "/PWD:"
  1968. #define RID_PARAM "/RID:"
  1969. #define USER_PARAM "/USER:"
  1970. #define BP_PARAM "/BP"
  1971. #define DBFLAG_PARAM "/DBFLAG:"
  1972. #define DCLIST_PARAM "/DCLIST:"
  1973. #define DCNAME_PARAM "/DCNAME:"
  1974. #define TRUNCATE_LOG_PARAM "/TRUNC"
  1975. #define TIME_PARAM "/TIME:"
  1976. #define WHOWILL_PARAM "/WHOWILL:"
  1977. #define BDC_QUERY_PARAM "/BDC_QUERY:"
  1978. #define LOGON_QUERY_PARAM "/LOGON_QUERY"
  1979. #define SIM_SYNC_PARAM "/SIM_SYNC:"
  1980. #define LIST_DELTAS_PARAM "/LIST_DELTAS:"
  1981. #define SC_RESET_PARAM "/SC_RESET:"
  1982. #define SC_QUERY_PARAM "/SC_QUERY:"
  1983. #define SC_VERIFY_PARAM "/SC_VERIFY:"
  1984. #define SC_CHANGE_PASSWORD_PARAM "/SC_CHANGE_PWD:"
  1985. #define SHUTDOWN_PARAM "/SHUTDOWN:"
  1986. #define SHUTDOWN_ABORT_PARAM "/SHUTDOWN_ABORT"
  1987. #define TRANSPORT_PARAM "/TRANSPORT_NOTIFY"
  1988. #define FINDUSER_PARAM "/FINDUSER:"
  1989. #define TRUSTED_DOMAINS_PARAM "/TRUSTED_DOMAINS"
  1990. #define DOMAIN_TRUSTS_PARAM "/DOMAIN_TRUSTS"
  1991. #define UNLOAD_PARAM "/UNLOAD"
  1992. #define DSGETSITE_PARAM "/DSGETSITE"
  1993. #define DSGETSITECOV_PARAM "/DSGETSITECOV"
  1994. #define DSDEREGISTERDNS_PARAM "/DSDEREGDNS:"
  1995. #define DSREGISTERDNS_PARAM "/DSREGDNS"
  1996. #define DSQUERYDNS_PARAM "/DSQUERYDNS"
  1997. #define DSGETFTI_PARAM "/DSGETFTI:"
  1998. #define UPDATE_TDO_PARAM "/UPDATE_TDO"
  1999. #define DSGETDC_PARAM "/DSGETDC:"
  2000. #define PARENTDOMAIN_PARAM "/PARENTDOMAIN"
  2001. #define PDC_PARAM "/PDC"
  2002. #define LDAPONLY_PARAM "/LDAPONLY"
  2003. #define DS_PARAM "/DS"
  2004. #define DSP_PARAM "/DSP"
  2005. #define GC_PARAM "/GC"
  2006. #define KDC_PARAM "/KDC"
  2007. #define TIMESERV_PARAM "/TIMESERV"
  2008. #define GTIMESERV_PARAM "/GTIMESERV"
  2009. #define AVOIDSELF_PARAM "/AVOIDSELF"
  2010. #define NETBIOS_PARAM "/NETBIOS"
  2011. #define DNS_PARAM "/DNS"
  2012. #define RET_DNS_PARAM "/RET_DNS"
  2013. #define RET_NETBIOS_PARAM "/RET_NETBIOS"
  2014. #define IP_PARAM "/IP"
  2015. #define BACKG_PARAM "/BACKG"
  2016. #define FORCE_PARAM "/FORCE"
  2017. #define WRITABLE_PARAM "/WRITABLE"
  2018. #define SITE_PARAM "/SITE:"
  2019. #define ACCOUNT_PARAM "/ACCOUNT:"
  2020. #define VERBOSE_PARAM "/V"
  2021. #define TRUSTS_PRIMARY_PARAM "/PRIMARY"
  2022. #define TRUSTS_FOREST_PARAM "/FOREST"
  2023. #define TRUSTS_DIRECT_OUT_PARAM "/DIRECT_OUT"
  2024. #define TRUSTS_DIRECT_IN_PARAM "/DIRECT_IN"
  2025. #define TRUSTS_ALL_PARAM "/ALL_TRUSTS"
  2026. #define DEREG_DOMAIN_PARAM "/DOM:"
  2027. #define DEREG_DOMAIN_GUID "/DOMGUID:"
  2028. #define DEREG_DSA_GUID "/DSAGUID:"
  2029. #define DSGETDCOPEN_PARAM "/DNSGETDC:"
  2030. #define DSGETDCOPEN_SITEONLY "/SITESPEC"
  2031. #define GET_SERVER_DIGEST "/SDIGEST:"
  2032. #define GET_CLIENT_DIGEST "/CDIGEST:"
  2033. #define GET_CLIENT_DIGEST_DOMAIN "/DOMAIN:"
  2034. //
  2035. // Set the netlib debug flag.
  2036. //
  2037. extern DWORD NetlibpTrace;
  2038. NetlibpTrace |= 0x8000; // NETLIB_DEBUG_LOGON
  2039. NlGlobalParameters.DbFlag = 0xFFFFFFFF;
  2040. ConvertTime.QuadPart = 0;
  2041. RtlZeroMemory( &NlGlobalZeroGuid, sizeof(NlGlobalZeroGuid) );
  2042. if ( !CryptAcquireContext(
  2043. &NlGlobalCryptProvider,
  2044. NULL,
  2045. NULL,
  2046. PROV_RSA_FULL,
  2047. CRYPT_VERIFYCONTEXT
  2048. ))
  2049. {
  2050. printf("Failed to acquire cryptographic CSP (error=%lu)\n", GetLastError());
  2051. return 2;
  2052. }
  2053. //
  2054. // Loop through the arguments handle each in turn
  2055. //
  2056. for ( i=1; i<argc; i++ ) {
  2057. argument = argv[i];
  2058. //
  2059. // Handle /QUERY
  2060. //
  2061. if ( _stricmp( argument, QUERY_PARAM ) == 0 ) {
  2062. if ( FunctionCode != 0 ) {
  2063. goto Usage;
  2064. }
  2065. FunctionCode = NETLOGON_CONTROL_QUERY;
  2066. //
  2067. // Handle /SC_QUERY
  2068. //
  2069. } else if ( _strnicmp( argument,
  2070. SC_QUERY_PARAM,
  2071. sizeof(SC_QUERY_PARAM) - 1 ) == 0 ) {
  2072. if ( FunctionCode != 0 ) {
  2073. goto Usage;
  2074. }
  2075. FunctionCode = NETLOGON_CONTROL_TC_QUERY;
  2076. AnsiTrustedDomainName = &argument[sizeof(SC_QUERY_PARAM)-1];
  2077. TrustedDomainName = NetpAllocWStrFromAStr( AnsiTrustedDomainName );
  2078. if ( TrustedDomainName == NULL ) {
  2079. fprintf( stderr, "Not enough memory\n" );
  2080. return(1);
  2081. }
  2082. Level = 2;
  2083. InputDataPtr = (LPBYTE)TrustedDomainName;
  2084. //
  2085. // Handle /SC_CHANGE_PWD
  2086. //
  2087. } else if ( _strnicmp( argument,
  2088. SC_CHANGE_PASSWORD_PARAM,
  2089. sizeof(SC_CHANGE_PASSWORD_PARAM) - 1 ) == 0 ) {
  2090. if ( FunctionCode != 0 ) {
  2091. goto Usage;
  2092. }
  2093. FunctionCode = NETLOGON_CONTROL_CHANGE_PASSWORD;
  2094. AnsiTrustedDomainName = &argument[sizeof(SC_CHANGE_PASSWORD_PARAM)-1];
  2095. TrustedDomainName = NetpAllocWStrFromAStr( AnsiTrustedDomainName );
  2096. if ( TrustedDomainName == NULL ) {
  2097. fprintf( stderr, "Not enough memory\n" );
  2098. return(1);
  2099. }
  2100. Level = 1;
  2101. InputDataPtr = (LPBYTE)TrustedDomainName;
  2102. //
  2103. // Handle /FINDUSER
  2104. //
  2105. } else if ( _strnicmp( argument,
  2106. FINDUSER_PARAM,
  2107. sizeof(FINDUSER_PARAM) - 1 ) == 0 ) {
  2108. if ( FunctionCode != 0 ) {
  2109. goto Usage;
  2110. }
  2111. FunctionCode = NETLOGON_CONTROL_FIND_USER;
  2112. AnsiUserName = &argument[sizeof(FINDUSER_PARAM)-1];
  2113. TrustedDomainName = NetpAllocWStrFromAStr( AnsiUserName );
  2114. if ( TrustedDomainName == NULL ) {
  2115. fprintf( stderr, "Not enough memory\n" );
  2116. return(1);
  2117. }
  2118. Level = 4;
  2119. InputDataPtr = (LPBYTE)TrustedDomainName;
  2120. //
  2121. // Handle /REPL
  2122. //
  2123. } else if (_stricmp(argument, REPL_PARAM ) == 0 ){
  2124. if ( FunctionCode != 0 ) {
  2125. goto Usage;
  2126. }
  2127. FunctionCode = NETLOGON_CONTROL_REPLICATE;
  2128. //
  2129. // Handle /SYNC
  2130. //
  2131. } else if (_stricmp(argument, SYNC_PARAM ) == 0 ){
  2132. if ( FunctionCode != 0 ) {
  2133. goto Usage;
  2134. }
  2135. FunctionCode = NETLOGON_CONTROL_SYNCHRONIZE;
  2136. //
  2137. // Handle /SC_RESET
  2138. //
  2139. } else if (_strnicmp(argument,
  2140. SC_RESET_PARAM,
  2141. sizeof(SC_RESET_PARAM) - 1 ) == 0 ){
  2142. if ( FunctionCode != 0 ) {
  2143. goto Usage;
  2144. }
  2145. FunctionCode = NETLOGON_CONTROL_REDISCOVER;
  2146. AnsiTrustedDomainName = &argument[sizeof(SC_RESET_PARAM)-1];
  2147. TrustedDomainName = NetpAllocWStrFromAStr( AnsiTrustedDomainName );
  2148. if ( TrustedDomainName == NULL ) {
  2149. fprintf( stderr, "Not enough memory\n" );
  2150. return(1);
  2151. }
  2152. Level = 2;
  2153. InputDataPtr = (LPBYTE)TrustedDomainName;
  2154. //
  2155. // Handle /SC_VERIFY
  2156. //
  2157. } else if (_strnicmp(argument,
  2158. SC_VERIFY_PARAM,
  2159. sizeof(SC_VERIFY_PARAM) - 1 ) == 0 ){
  2160. if ( FunctionCode != 0 ) {
  2161. goto Usage;
  2162. }
  2163. FunctionCode = NETLOGON_CONTROL_TC_VERIFY;
  2164. AnsiTrustedDomainName = &argument[sizeof(SC_VERIFY_PARAM)-1];
  2165. TrustedDomainName = NetpAllocWStrFromAStr( AnsiTrustedDomainName );
  2166. if ( TrustedDomainName == NULL ) {
  2167. fprintf( stderr, "Not enough memory\n" );
  2168. return(1);
  2169. }
  2170. Level = 2;
  2171. InputDataPtr = (LPBYTE)TrustedDomainName;
  2172. //
  2173. // Handle /QUERY
  2174. //
  2175. } else if ( _stricmp( argument, TRANSPORT_PARAM ) == 0 ) {
  2176. if ( FunctionCode != 0 ) {
  2177. goto Usage;
  2178. }
  2179. FunctionCode = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
  2180. //
  2181. // Handle /PDC_REPL
  2182. //
  2183. } else if (_stricmp(argument, PDC_REPL_PARAM ) == 0 ){
  2184. if ( FunctionCode != 0 ) {
  2185. goto Usage;
  2186. }
  2187. FunctionCode = NETLOGON_CONTROL_PDC_REPLICATE;
  2188. #ifndef NTRK_RELEASE
  2189. //
  2190. // Handle /BP
  2191. //
  2192. } else if (_stricmp(argument, BP_PARAM ) == 0 ){
  2193. if ( FunctionCode != 0 ) {
  2194. goto Usage;
  2195. }
  2196. FunctionCode = NETLOGON_CONTROL_BREAKPOINT;
  2197. #endif // NTRK_RELEASE
  2198. #ifndef NTRK_RELEASE
  2199. //
  2200. // Handle /TRUNCATE_LOG
  2201. //
  2202. } else if (_stricmp(argument, TRUNCATE_LOG_PARAM ) == 0 ){
  2203. if ( FunctionCode != 0 ) {
  2204. goto Usage;
  2205. }
  2206. FunctionCode = NETLOGON_CONTROL_TRUNCATE_LOG;
  2207. #endif // NTRK_RELEASE
  2208. //
  2209. // Handle /DBFLAG:dbflag
  2210. //
  2211. } else if (_strnicmp(argument,
  2212. DBFLAG_PARAM,
  2213. sizeof(DBFLAG_PARAM)-1 ) == 0 ){
  2214. char *end;
  2215. if ( FunctionCode != 0 ) {
  2216. goto Usage;
  2217. }
  2218. FunctionCode = NETLOGON_CONTROL_SET_DBFLAG;
  2219. DbFlagValue = strtoul( &argument[sizeof(DBFLAG_PARAM)-1], &end, 16 );
  2220. InputDataPtr = (LPBYTE) ULongToPtr( DbFlagValue );
  2221. //
  2222. // Handle /Time:LSL MSL
  2223. //
  2224. } else if (_strnicmp(argument,
  2225. TIME_PARAM,
  2226. sizeof(TIME_PARAM)-1 ) == 0 ){
  2227. char *end;
  2228. if ( ConvertTime.QuadPart != 0 ) {
  2229. goto Usage;
  2230. }
  2231. ConvertTime.LowPart = strtoul( &argument[sizeof(TIME_PARAM)-1], &end, 16 );
  2232. i++;
  2233. argument = argv[i];
  2234. ConvertTime.HighPart = strtoul( argument, &end, 16 );
  2235. //
  2236. // Handle /WHOWILL:Domain User [IterationCount]
  2237. //
  2238. } else if (_strnicmp(argument,
  2239. WHOWILL_PARAM,
  2240. sizeof(WHOWILL_PARAM)-1 ) == 0 ){
  2241. char *end;
  2242. if ( AnsiDomainName != NULL ) {
  2243. goto Usage;
  2244. }
  2245. AnsiDomainName = &argument[sizeof(WHOWILL_PARAM)-1];
  2246. i++;
  2247. argument = argv[i];
  2248. AnsiUserName = argument;
  2249. if ( i+1 < argc ) {
  2250. i++;
  2251. argument = argv[i];
  2252. IterationCount = strtoul( argument, &end, 16 );
  2253. } else {
  2254. IterationCount = 1;
  2255. }
  2256. WhoWill = TRUE;
  2257. //
  2258. // Handle /BDC_QUERY:Domain
  2259. //
  2260. } else if (_strnicmp(argument,
  2261. BDC_QUERY_PARAM,
  2262. sizeof(BDC_QUERY_PARAM)-1 ) == 0 ){
  2263. if ( AnsiDomainName != NULL ) {
  2264. goto Usage;
  2265. }
  2266. AnsiDomainName = &argument[sizeof(BDC_QUERY_PARAM)-1];
  2267. QuerySync = TRUE;
  2268. //
  2269. // Handle /LOGON_QUERY
  2270. //
  2271. } else if ( _stricmp( argument, LOGON_QUERY_PARAM ) == 0 ) {
  2272. if ( FunctionCode != 0 ) {
  2273. goto Usage;
  2274. }
  2275. FunctionCode = NETLOGON_CONTROL_QUERY;
  2276. Level = 3;
  2277. //
  2278. // Handle full sync simulation
  2279. //
  2280. } else if (_strnicmp(argument,
  2281. SIM_SYNC_PARAM,
  2282. sizeof(SIM_SYNC_PARAM)-1 ) == 0 ){
  2283. if ( AnsiDomainName != NULL ) {
  2284. goto Usage;
  2285. }
  2286. AnsiDomainName = &argument[sizeof(SIM_SYNC_PARAM)-1];
  2287. i++;
  2288. if( i >= argc ) {
  2289. goto Usage;
  2290. }
  2291. argument = argv[i];
  2292. AnsiSimMachineName = argument;
  2293. SimFullSync = TRUE;
  2294. //
  2295. // handle delta listing
  2296. //
  2297. } else if (_strnicmp(argument,
  2298. LIST_DELTAS_PARAM,
  2299. sizeof(LIST_DELTAS_PARAM)-1 ) == 0 ){
  2300. if ( AnsiDeltaFileName != NULL ) {
  2301. goto Usage;
  2302. }
  2303. AnsiDeltaFileName = &argument[sizeof(LIST_DELTAS_PARAM)-1];
  2304. ListDeltasFlag = TRUE;
  2305. //
  2306. // Handle /DCLIST
  2307. //
  2308. } else if (_strnicmp(argument,
  2309. DCLIST_PARAM,
  2310. sizeof(DCLIST_PARAM)-1 ) == 0 ){
  2311. if ( AnsiDomainName != NULL ) {
  2312. goto Usage;
  2313. }
  2314. AnsiDomainName = &argument[sizeof(DCLIST_PARAM)-1];
  2315. GetDcList = TRUE;
  2316. //
  2317. // Handle /DCNAME
  2318. //
  2319. } else if (_strnicmp(argument,
  2320. DCNAME_PARAM,
  2321. sizeof(DCNAME_PARAM)-1 ) == 0 ){
  2322. if ( AnsiDomainName != NULL ) {
  2323. goto Usage;
  2324. }
  2325. AnsiDomainName = &argument[sizeof(DCNAME_PARAM)-1];
  2326. GetPdcName = TRUE;
  2327. //
  2328. // Handle /DSGETDC
  2329. //
  2330. } else if (_strnicmp(argument,
  2331. DSGETDC_PARAM,
  2332. sizeof(DSGETDC_PARAM)-1 ) == 0 ){
  2333. if ( AnsiDomainName != NULL ) {
  2334. goto Usage;
  2335. }
  2336. AnsiDomainName = &argument[sizeof(DSGETDC_PARAM)-1];
  2337. DoDsGetDcName = TRUE;
  2338. //
  2339. // Handle /DSGETFTI
  2340. //
  2341. } else if (_strnicmp(argument,
  2342. DSGETFTI_PARAM,
  2343. sizeof(DSGETFTI_PARAM)-1 ) == 0 ){
  2344. if ( AnsiDomainName != NULL ) {
  2345. goto Usage;
  2346. }
  2347. AnsiDomainName = &argument[sizeof(DSGETFTI_PARAM)-1];
  2348. DoDsGetFtinfo = TRUE;
  2349. //
  2350. // Handle /UPDATE_TDO modifier to /DSGETFTI parameter
  2351. //
  2352. } else if ( _stricmp( argument, UPDATE_TDO_PARAM ) == 0 ) {
  2353. if ( !DoDsGetFtinfo ) {
  2354. goto Usage;
  2355. }
  2356. DsGetFtinfoFlags |= DS_GFTI_UPDATE_TDO;
  2357. //
  2358. // Handle /SERVER:servername
  2359. //
  2360. } else if (_strnicmp(argument, SERVER_PARAM, sizeof(SERVER_PARAM)-1 ) == 0 ){
  2361. if ( AnsiServerName != NULL ) {
  2362. goto Usage;
  2363. }
  2364. AnsiServerName = &argument[sizeof(SERVER_PARAM)-1];
  2365. #ifndef NTRK_RELEASE
  2366. //
  2367. // Handle /PWD:password
  2368. //
  2369. } else if (_strnicmp(argument, PWD_PARAM, sizeof(PWD_PARAM)-1 ) == 0 ){
  2370. if ( AnsiPassword != NULL ) {
  2371. goto Usage;
  2372. }
  2373. AnsiPassword = &argument[sizeof(PWD_PARAM)-1];
  2374. #endif // NTRK_RELEASE
  2375. //
  2376. // Handle /USER:username
  2377. //
  2378. } else if (_strnicmp(argument, USER_PARAM, sizeof(USER_PARAM)-1 ) == 0 ){
  2379. if ( AnsiUserName != NULL ) {
  2380. goto Usage;
  2381. }
  2382. AnsiUserName = &argument[sizeof(USER_PARAM)-1];
  2383. QueryUser = TRUE;
  2384. #ifndef NTRK_RELEASE
  2385. //
  2386. // Handle /RID:relative_id
  2387. //
  2388. } else if (_strnicmp(argument, RID_PARAM, sizeof(RID_PARAM)-1 ) == 0 ){
  2389. char *end;
  2390. if ( Rid != 0 ) {
  2391. goto Usage;
  2392. }
  2393. Rid = strtol( &argument[sizeof(RID_PARAM)-1], &end, 16 );
  2394. #endif // NTRK_RELEASE
  2395. //
  2396. // Handle /SHUTDOWN:Reason seconds
  2397. //
  2398. } else if (_strnicmp(argument,
  2399. SHUTDOWN_PARAM,
  2400. sizeof(SHUTDOWN_PARAM)-1 ) == 0 ){
  2401. if ( ShutdownReason != NULL ) {
  2402. goto Usage;
  2403. }
  2404. ShutdownReason = &argument[sizeof(SHUTDOWN_PARAM)-1];
  2405. if ( i+1 < argc ) {
  2406. char *end;
  2407. i++;
  2408. argument = argv[i];
  2409. if ( !ISDIGIT(argument[0]) ) {
  2410. fprintf(stderr, "Second argument to " SHUTDOWN_PARAM " must be a number.\n\n");
  2411. goto Usage;
  2412. }
  2413. ShutdownSeconds = strtoul( argument, &end, 10 );
  2414. } else {
  2415. ShutdownSeconds = 60;
  2416. }
  2417. //
  2418. // Handle /SHUTDOWN_ABORT
  2419. //
  2420. } else if (_stricmp(argument, SHUTDOWN_ABORT_PARAM ) == 0 ){
  2421. ShutdownAbort = TRUE;
  2422. //
  2423. // Handle /DOMAIN_TRUSTS
  2424. // Allow the old spelling of //TRUSTED_DOMAINS
  2425. //
  2426. } else if (_stricmp(argument, TRUSTED_DOMAINS_PARAM ) == 0 ||
  2427. _stricmp(argument, DOMAIN_TRUSTS_PARAM ) == 0 ){
  2428. DomainTrustsFlag = TRUE;
  2429. #ifndef NTRK_RELEASE
  2430. //
  2431. // Handle /UNLOAD
  2432. //
  2433. } else if ( _stricmp( argument, UNLOAD_PARAM ) == 0 ) {
  2434. if ( FunctionCode != 0 ) {
  2435. goto Usage;
  2436. }
  2437. FunctionCode = NETLOGON_CONTROL_UNLOAD_NETLOGON_DLL;
  2438. UnloadNetlogonFlag = TRUE;
  2439. #endif // NTRK_RELEASE
  2440. //
  2441. // Handle /DSGETSITE
  2442. //
  2443. } else if ( _stricmp( argument, DSGETSITE_PARAM ) == 0 ) {
  2444. DoDsGetSiteName = TRUE;
  2445. //
  2446. // Handle /DSGETSITECOV
  2447. //
  2448. } else if ( _stricmp( argument, DSGETSITECOV_PARAM ) == 0 ) {
  2449. DoDsGetDcSiteCoverage = TRUE;
  2450. //
  2451. // Handle /PARENTDOMAIN
  2452. //
  2453. } else if ( _stricmp( argument, PARENTDOMAIN_PARAM ) == 0 ) {
  2454. DoGetParentDomain = TRUE;
  2455. //
  2456. // Handle /DSDEREGDNS
  2457. //
  2458. } else if (_strnicmp(argument,
  2459. DSDEREGISTERDNS_PARAM,
  2460. sizeof(DSDEREGISTERDNS_PARAM)-1 ) == 0 ){
  2461. DeregisterDnsHostRecords = TRUE;
  2462. if ( AnsiDnsHostName != NULL ) {
  2463. goto Usage;
  2464. }
  2465. AnsiDnsHostName = &argument[sizeof(DSDEREGISTERDNS_PARAM)-1];
  2466. //
  2467. // Handle /DSREGDNS
  2468. //
  2469. } else if ( _stricmp( argument, DSREGISTERDNS_PARAM ) == 0 ) {
  2470. if ( FunctionCode != 0 ) {
  2471. goto Usage;
  2472. }
  2473. FunctionCode = NETLOGON_CONTROL_FORCE_DNS_REG;
  2474. //
  2475. // Handle /DSQUERYDNS
  2476. //
  2477. } else if ( _stricmp( argument, DSQUERYDNS_PARAM ) == 0 ) {
  2478. if ( FunctionCode != 0 ) {
  2479. goto Usage;
  2480. }
  2481. FunctionCode = NETLOGON_CONTROL_QUERY_DNS_REG;
  2482. //
  2483. // Handle /PDC modifier to /DSGETDC parameter
  2484. //
  2485. } else if ( _stricmp( argument, PDC_PARAM ) == 0 ) {
  2486. if ( !DoDsGetDcName && !DoDsGetDcOpen ) {
  2487. goto Usage;
  2488. }
  2489. DsGetDcNameFlags |= DS_PDC_REQUIRED;
  2490. //
  2491. // Handle /LDAPONLY modifier to /DSGETDC parameter
  2492. //
  2493. } else if ( _stricmp( argument, LDAPONLY_PARAM ) == 0 ) {
  2494. if ( !DoDsGetDcName && !DoDsGetDcOpen ) {
  2495. goto Usage;
  2496. }
  2497. DsGetDcNameFlags |= DS_ONLY_LDAP_NEEDED;
  2498. //
  2499. // Handle /DS modifier to /DSGETDC parameter
  2500. //
  2501. } else if ( _stricmp( argument, DS_PARAM ) == 0 ) {
  2502. if ( !DoDsGetDcName ) {
  2503. goto Usage;
  2504. }
  2505. DsGetDcNameFlags |= DS_DIRECTORY_SERVICE_REQUIRED;
  2506. //
  2507. // Handle /DSP modifier to /DSGETDC parameter
  2508. //
  2509. } else if ( _stricmp( argument, DSP_PARAM ) == 0 ) {
  2510. if ( !DoDsGetDcName ) {
  2511. goto Usage;
  2512. }
  2513. DsGetDcNameFlags |= DS_DIRECTORY_SERVICE_PREFERRED;
  2514. //
  2515. // Handle /KDC modifier to /DSGETDC parameter
  2516. //
  2517. } else if ( _stricmp( argument, KDC_PARAM ) == 0 ) {
  2518. if ( !DoDsGetDcName && !DoDsGetDcOpen ) {
  2519. goto Usage;
  2520. }
  2521. DsGetDcNameFlags |= DS_KDC_REQUIRED;
  2522. //
  2523. // Handle /TIMESERV modifier to /DSGETDC parameter
  2524. //
  2525. } else if ( _stricmp( argument, TIMESERV_PARAM ) == 0 ) {
  2526. if ( !DoDsGetDcName ) {
  2527. goto Usage;
  2528. }
  2529. DsGetDcNameFlags |= DS_TIMESERV_REQUIRED;
  2530. //
  2531. // Handle /GTIMESERV modifier to /DSGETDC parameter
  2532. //
  2533. } else if ( _stricmp( argument, GTIMESERV_PARAM ) == 0 ) {
  2534. if ( !DoDsGetDcName ) {
  2535. goto Usage;
  2536. }
  2537. DsGetDcNameFlags |= DS_GOOD_TIMESERV_PREFERRED;
  2538. //
  2539. // Handle /AVOIDSELF modifier to /DSGETDC parameter
  2540. //
  2541. } else if ( _stricmp( argument, AVOIDSELF_PARAM ) == 0 ) {
  2542. if ( !DoDsGetDcName ) {
  2543. goto Usage;
  2544. }
  2545. DsGetDcNameFlags |= DS_AVOID_SELF;
  2546. //
  2547. // Handle /GC modifier to /DSGETDC parameter
  2548. //
  2549. } else if ( _stricmp( argument, GC_PARAM ) == 0 ) {
  2550. if ( !DoDsGetDcName && !DoDsGetDcOpen ) {
  2551. goto Usage;
  2552. }
  2553. DsGetDcNameFlags |= DS_GC_SERVER_REQUIRED;
  2554. //
  2555. // Handle /NETBIOS modifier to /DSGETDC parameter
  2556. //
  2557. } else if ( _stricmp( argument, NETBIOS_PARAM ) == 0 ) {
  2558. if ( !DoDsGetDcName ) {
  2559. goto Usage;
  2560. }
  2561. DsGetDcNameFlags |= DS_IS_FLAT_NAME;
  2562. //
  2563. // Handle /DNS modifier to /DSGETDC parameter
  2564. //
  2565. } else if ( _stricmp( argument, DNS_PARAM ) == 0 ) {
  2566. if ( !DoDsGetDcName ) {
  2567. goto Usage;
  2568. }
  2569. DsGetDcNameFlags |= DS_IS_DNS_NAME;
  2570. //
  2571. // Handle /RET_DNS modifier to /DSGETDC parameter
  2572. //
  2573. } else if ( _stricmp( argument, RET_DNS_PARAM ) == 0 ) {
  2574. if ( !DoDsGetDcName ) {
  2575. goto Usage;
  2576. }
  2577. DsGetDcNameFlags |= DS_RETURN_DNS_NAME;
  2578. //
  2579. // Handle /RET_NETBIOS modifier to /DSGETDC parameter
  2580. //
  2581. } else if ( _stricmp( argument, RET_NETBIOS_PARAM ) == 0 ) {
  2582. if ( !DoDsGetDcName ) {
  2583. goto Usage;
  2584. }
  2585. DsGetDcNameFlags |= DS_RETURN_FLAT_NAME;
  2586. //
  2587. // Handle /IP modifier to /DSGETDC parameter
  2588. //
  2589. } else if ( _stricmp( argument, IP_PARAM ) == 0 ) {
  2590. if ( !DoDsGetDcName ) {
  2591. goto Usage;
  2592. }
  2593. DsGetDcNameFlags |= DS_IP_REQUIRED;
  2594. //
  2595. // Handle /BACKG modifier to /DSGETDC parameter
  2596. //
  2597. } else if ( _stricmp( argument, BACKG_PARAM ) == 0 ) {
  2598. if ( !DoDsGetDcName ) {
  2599. goto Usage;
  2600. }
  2601. DsGetDcNameFlags |= DS_BACKGROUND_ONLY;
  2602. //
  2603. // Handle /FORCE modifier to /DSGETDC parameter
  2604. //
  2605. } else if ( _stricmp( argument, FORCE_PARAM ) == 0 ) {
  2606. if ( !DoDsGetDcName && !DoDsGetDcOpen ) {
  2607. goto Usage;
  2608. }
  2609. DsGetDcNameFlags |= DS_FORCE_REDISCOVERY;
  2610. //
  2611. // Handle /WRITABLE modifier to /DSGETDC parameter
  2612. //
  2613. } else if ( _stricmp( argument, WRITABLE_PARAM ) == 0 ) {
  2614. if ( !DoDsGetDcName && !DoDsGetDcOpen ) {
  2615. goto Usage;
  2616. }
  2617. DsGetDcNameFlags |= DS_WRITABLE_REQUIRED;
  2618. //
  2619. // Handle /SITE:
  2620. //
  2621. } else if (_strnicmp(argument,
  2622. SITE_PARAM,
  2623. sizeof(SITE_PARAM)-1 ) == 0 ){
  2624. if ( !DoDsGetDcName && !DoDsGetDcOpen ) {
  2625. goto Usage;
  2626. }
  2627. if ( AnsiSiteName != NULL ) {
  2628. goto Usage;
  2629. }
  2630. AnsiSiteName = &argument[sizeof(SITE_PARAM)-1];
  2631. //
  2632. // Handle /ACCOUNT:
  2633. //
  2634. } else if (_strnicmp(argument,
  2635. ACCOUNT_PARAM,
  2636. sizeof(ACCOUNT_PARAM)-1 ) == 0 ){
  2637. if ( !DoDsGetDcName ) {
  2638. goto Usage;
  2639. }
  2640. if ( AnsiUserName != NULL ) {
  2641. goto Usage;
  2642. }
  2643. AnsiUserName = &argument[sizeof(ACCOUNT_PARAM)-1];
  2644. //
  2645. // Handle /PRIMARY modifier to DsEnumerateDomainTrusts
  2646. //
  2647. } else if ( _stricmp( argument, TRUSTS_PRIMARY_PARAM ) == 0 ) {
  2648. if ( !DomainTrustsFlag ) {
  2649. goto Usage;
  2650. }
  2651. TrustsNeeded |= DS_DOMAIN_PRIMARY;
  2652. //
  2653. // Handle /FOREST modifier to DsEnumerateDomainTrusts
  2654. //
  2655. } else if ( _stricmp( argument, TRUSTS_FOREST_PARAM ) == 0 ) {
  2656. if ( !DomainTrustsFlag ) {
  2657. goto Usage;
  2658. }
  2659. TrustsNeeded |= DS_DOMAIN_IN_FOREST;
  2660. //
  2661. // Handle /DIRECT_OUT modifier to DsEnumerateDomainTrusts
  2662. //
  2663. } else if ( _stricmp( argument, TRUSTS_DIRECT_OUT_PARAM ) == 0 ) {
  2664. if ( !DomainTrustsFlag ) {
  2665. goto Usage;
  2666. }
  2667. TrustsNeeded |= DS_DOMAIN_DIRECT_OUTBOUND;
  2668. //
  2669. // Handle /DIRECT_IN modifier to DsEnumerateDomainTrusts
  2670. //
  2671. } else if ( _stricmp( argument, TRUSTS_DIRECT_IN_PARAM ) == 0 ) {
  2672. if ( !DomainTrustsFlag ) {
  2673. goto Usage;
  2674. }
  2675. TrustsNeeded |= DS_DOMAIN_DIRECT_INBOUND;
  2676. //
  2677. // Handle /ALL_TRUSTS modifier to DsEnumerateDomainTrusts
  2678. //
  2679. } else if ( _stricmp( argument, TRUSTS_ALL_PARAM ) == 0 ) {
  2680. if ( !DomainTrustsFlag ) {
  2681. goto Usage;
  2682. }
  2683. TrustsNeeded |= (DS_DOMAIN_PRIMARY |
  2684. DS_DOMAIN_IN_FOREST |
  2685. DS_DOMAIN_DIRECT_OUTBOUND |
  2686. DS_DOMAIN_DIRECT_INBOUND);
  2687. //
  2688. // Handle the verbosity level of the trust output
  2689. //
  2690. } else if ( _stricmp( argument, VERBOSE_PARAM ) == 0 ) {
  2691. if ( !DomainTrustsFlag ) {
  2692. goto Usage;
  2693. }
  2694. TrustedDomainsVerboseOutput = TRUE;
  2695. //
  2696. // Handle /DOM: modifier to DsDeregesterHostDnsRecors
  2697. //
  2698. } else if (_strnicmp(argument,
  2699. DEREG_DOMAIN_PARAM,
  2700. sizeof(DEREG_DOMAIN_PARAM)-1 ) == 0 ){
  2701. if ( !DeregisterDnsHostRecords ) {
  2702. goto Usage;
  2703. }
  2704. if ( AnsiDnsDomainName != NULL ) {
  2705. goto Usage;
  2706. }
  2707. AnsiDnsDomainName = &argument[sizeof(DEREG_DOMAIN_PARAM)-1];
  2708. //
  2709. // Handle /DOMGUID: modifier to DsDeregesterHostDnsRecors
  2710. //
  2711. } else if (_strnicmp(argument,
  2712. DEREG_DOMAIN_GUID,
  2713. sizeof(DEREG_DOMAIN_GUID)-1 ) == 0 ){
  2714. if ( !DeregisterDnsHostRecords ) {
  2715. goto Usage;
  2716. }
  2717. if ( StringDomainGuid != NULL ) {
  2718. goto Usage;
  2719. }
  2720. StringDomainGuid = &argument[sizeof(DEREG_DOMAIN_GUID)-1];
  2721. //
  2722. // Handle /DSAGUID: modifier to DsDeregesterHostDnsRecors
  2723. //
  2724. } else if (_strnicmp(argument,
  2725. DEREG_DSA_GUID,
  2726. sizeof(DEREG_DSA_GUID)-1 ) == 0 ){
  2727. if ( !DeregisterDnsHostRecords ) {
  2728. goto Usage;
  2729. }
  2730. if ( StringDsaGuid != NULL ) {
  2731. goto Usage;
  2732. }
  2733. StringDsaGuid = &argument[sizeof(DEREG_DSA_GUID)-1];
  2734. //
  2735. // Handle /DNSGETDC
  2736. //
  2737. } else if (_strnicmp(argument,
  2738. DSGETDCOPEN_PARAM,
  2739. sizeof(DSGETDCOPEN_PARAM)-1 ) == 0 ){
  2740. if ( AnsiDomainName != NULL ) {
  2741. goto Usage;
  2742. }
  2743. AnsiDomainName = &argument[sizeof(DSGETDCOPEN_PARAM)-1];
  2744. DoDsGetDcOpen = TRUE;
  2745. //
  2746. // Handle /SITESPEC modifier to DsGetDcOpen
  2747. //
  2748. } else if ( _stricmp( argument, DSGETDCOPEN_SITEONLY ) == 0 ) {
  2749. if ( !DoDsGetDcOpen ) {
  2750. goto Usage;
  2751. }
  2752. DsGetDcOpenFlags |= DS_ONLY_DO_SITE_NAME;
  2753. //
  2754. // Handle /CDIGEST
  2755. //
  2756. } else if ( _strnicmp( argument,
  2757. GET_CLIENT_DIGEST,
  2758. sizeof(GET_CLIENT_DIGEST)-1 ) == 0 ) {
  2759. DoClientDigest = TRUE;
  2760. if ( Message != NULL ) {
  2761. goto Usage;
  2762. }
  2763. Message = &argument[sizeof(GET_CLIENT_DIGEST)-1];
  2764. //
  2765. // Handle domain name for /CDIGEST
  2766. //
  2767. } else if ( _strnicmp( argument,
  2768. GET_CLIENT_DIGEST_DOMAIN,
  2769. sizeof(GET_CLIENT_DIGEST_DOMAIN)-1 ) == 0 ) {
  2770. if ( !DoClientDigest ) {
  2771. goto Usage;
  2772. }
  2773. if ( AnsiDomainName != NULL ) {
  2774. goto Usage;
  2775. }
  2776. AnsiDomainName = &argument[sizeof(GET_CLIENT_DIGEST_DOMAIN)-1];
  2777. //
  2778. // Handle /SDIGEST
  2779. //
  2780. } else if ( _strnicmp( argument,
  2781. GET_SERVER_DIGEST,
  2782. sizeof(GET_SERVER_DIGEST)-1 ) == 0 ) {
  2783. DoServerDigest = TRUE;
  2784. if ( Message != NULL ) {
  2785. goto Usage;
  2786. }
  2787. Message = &argument[sizeof(GET_SERVER_DIGEST)-1];
  2788. //
  2789. // Handle all other parameters
  2790. //
  2791. } else {
  2792. Usage:
  2793. fprintf( stderr, "Usage: nltest [/OPTIONS]\n\n" );
  2794. fprintf(
  2795. stderr,
  2796. "\n"
  2797. " " SERVER_PARAM "<ServerName> - Specify <ServerName>\n"
  2798. "\n"
  2799. " " QUERY_PARAM " - Query <ServerName> netlogon service\n"
  2800. " " REPL_PARAM " - Force partial sync on <ServerName> BDC\n"
  2801. " " SYNC_PARAM " - Force full sync on <ServerName> BDC\n"
  2802. " " PDC_REPL_PARAM " - Force UAS change message from <ServerName> PDC\n"
  2803. "\n"
  2804. " " SC_QUERY_PARAM "<DomainName> - Query secure channel for <Domain> on <ServerName>\n"
  2805. " " SC_RESET_PARAM "<DomainName>[\\<DcName>] - Reset secure channel for <Domain> on <ServerName> to <DcName>\n"
  2806. " " SC_VERIFY_PARAM "<DomainName> - Verify secure channel for <Domain> on <ServerName>\n"
  2807. " " SC_CHANGE_PASSWORD_PARAM "<DomainName> - Change a secure channel password for <Domain> on <ServerName>\n"
  2808. " " DCLIST_PARAM "<DomainName> - Get list of DC's for <DomainName>\n"
  2809. " " DCNAME_PARAM "<DomainName> - Get the PDC name for <DomainName>\n"
  2810. " " DSGETDC_PARAM "<DomainName> - Call DsGetDcName"
  2811. " " PDC_PARAM
  2812. " " DS_PARAM
  2813. " " DSP_PARAM
  2814. " " GC_PARAM
  2815. " " KDC_PARAM
  2816. "\n "
  2817. " " TIMESERV_PARAM
  2818. " " GTIMESERV_PARAM
  2819. " " NETBIOS_PARAM
  2820. " " DNS_PARAM
  2821. " " IP_PARAM
  2822. " " FORCE_PARAM
  2823. " " WRITABLE_PARAM
  2824. " " AVOIDSELF_PARAM
  2825. " " LDAPONLY_PARAM
  2826. " " BACKG_PARAM
  2827. "\n "
  2828. " " SITE_PARAM "<SiteName>"
  2829. " " ACCOUNT_PARAM "<AccountName>"
  2830. " " RET_DNS_PARAM
  2831. " " RET_NETBIOS_PARAM
  2832. "\n"
  2833. " " DSGETDCOPEN_PARAM "<DomainName> - Call DsGetDcOpen/Next/Close"
  2834. " " PDC_PARAM
  2835. " " GC_PARAM
  2836. "\n "
  2837. " " KDC_PARAM
  2838. " " WRITABLE_PARAM
  2839. " " LDAPONLY_PARAM
  2840. " " FORCE_PARAM
  2841. " " DSGETDCOPEN_SITEONLY
  2842. "\n"
  2843. " " DSGETFTI_PARAM "<DomainName> - Call DsGetForestTrustInformation"
  2844. "\n "
  2845. " " UPDATE_TDO_PARAM
  2846. "\n"
  2847. " " DSGETSITE_PARAM " - Call DsGetSiteName\n"
  2848. " " DSGETSITECOV_PARAM " - Call DsGetDcSiteCoverage\n"
  2849. " " PARENTDOMAIN_PARAM " - Get the name of the parent domain of this machine\n"
  2850. " " WHOWILL_PARAM "<Domain>* <User> [<Iteration>] - See if <Domain> will log on <User>\n"
  2851. " " FINDUSER_PARAM "<User> - See which trusted domain will log on <User>\n"
  2852. " " TRANSPORT_PARAM " - Notify netlogon of new transport\n"
  2853. "\n"
  2854. #ifndef NTRK_RELEASE
  2855. " " BP_PARAM " - Force a BreakPoint in Netlogon on <ServerName>\n"
  2856. #endif // NTRK_RELEASE
  2857. " " DBFLAG_PARAM "<HexFlags> - New debug flag\n"
  2858. #ifndef NTRK_RELEASE
  2859. " " TRUNCATE_LOG_PARAM " - Truncate log file (rename to *.bak)\n"
  2860. " " UNLOAD_PARAM " - Unload netlogon.dll from lsass.exe\n"
  2861. #endif // NTRK_RELEASE
  2862. "\n"
  2863. #ifndef NTRK_RELEASE
  2864. " " PWD_PARAM "<CleartextPassword> - Specify Password to encrypt\n"
  2865. " " RID_PARAM "<HexRid> - RID to encrypt Password with\n"
  2866. #endif // NTRK_RELEASE
  2867. " " USER_PARAM "<UserName> - Query User info on <ServerName>\n"
  2868. "\n"
  2869. " " TIME_PARAM "<Hex LSL> <Hex MSL> - Convert NT GMT time to ascii\n"
  2870. " " LOGON_QUERY_PARAM " - Query number of cumulative logon attempts\n"
  2871. " " DOMAIN_TRUSTS_PARAM " - Query domain trusts on <ServerName>"
  2872. "\n "
  2873. " " TRUSTS_PRIMARY_PARAM
  2874. " " TRUSTS_FOREST_PARAM
  2875. " " TRUSTS_DIRECT_OUT_PARAM
  2876. " " TRUSTS_DIRECT_IN_PARAM
  2877. " " TRUSTS_ALL_PARAM
  2878. " " VERBOSE_PARAM
  2879. "\n"
  2880. " " DSREGISTERDNS_PARAM " - Force registration of all DC-specific DNS records"
  2881. "\n"
  2882. " " DSDEREGISTERDNS_PARAM "<DnsHostName> - Deregister DC-specific DNS records for specified DC"
  2883. "\n "
  2884. " " DEREG_DOMAIN_PARAM "<DnsDomainName>"
  2885. " " DEREG_DOMAIN_GUID "<DomainGuid>"
  2886. " " DEREG_DSA_GUID "<DsaGuid>"
  2887. "\n"
  2888. " " DSQUERYDNS_PARAM " - Query the status of the last update for all DC-specific DNS records"
  2889. "\n\n"
  2890. " " BDC_QUERY_PARAM "<DomainName> - Query replication status of BDCs for <DomainName>\n"
  2891. " " SIM_SYNC_PARAM "<DomainName> <MachineName> - Simulate full sync replication\n"
  2892. "\n"
  2893. " " LIST_DELTAS_PARAM "<FileName> - display the content of given change log file \n"
  2894. "\n"
  2895. " " GET_CLIENT_DIGEST "<Message> "GET_CLIENT_DIGEST_DOMAIN "<DomainName> - Get client digest\n"
  2896. " " GET_SERVER_DIGEST "<Message> "RID_PARAM "<RID in hex> - Get server digest\n"
  2897. "\n"
  2898. " " SHUTDOWN_PARAM "<Reason> [<Seconds>] - Shutdown <ServerName> for <Reason>\n"
  2899. " " SHUTDOWN_ABORT_PARAM " - Abort a system shutdown\n"
  2900. "\n" );
  2901. return(1);
  2902. }
  2903. }
  2904. //
  2905. // Convert the server name to unicode.
  2906. //
  2907. if ( AnsiServerName != NULL ) {
  2908. if ( AnsiServerName[0] == '\\' && AnsiServerName[1] == '\\' ) {
  2909. ServerName = NetpAllocWStrFromAStr( AnsiServerName );
  2910. } else {
  2911. AnsiUncServerName[0] = '\\';
  2912. AnsiUncServerName[1] = '\\';
  2913. strcpy(AnsiUncServerName+2, AnsiServerName);
  2914. ServerName = NetpAllocWStrFromAStr( AnsiUncServerName );
  2915. AnsiServerName = AnsiUncServerName;
  2916. }
  2917. }
  2918. //
  2919. // Convert the user name to unicode.
  2920. //
  2921. if ( AnsiUserName != NULL ) {
  2922. UserName = NetpAllocWStrFromAStr( AnsiUserName );
  2923. if ( UserName == NULL ) {
  2924. fprintf( stderr, "Not enough memory\n" );
  2925. return(1);
  2926. }
  2927. }
  2928. //
  2929. // If we've been asked to contact the Netlogon service,
  2930. // Do so
  2931. //
  2932. if ( FunctionCode != 0 ) {
  2933. //
  2934. // The dbflag should be set in the registry as well as in netlogon
  2935. // proper.
  2936. //
  2937. if ( FunctionCode == NETLOGON_CONTROL_SET_DBFLAG ) {
  2938. SetDbflagInRegistry( ServerName, DbFlagValue );
  2939. }
  2940. NetStatus = I_NetLogonControl2( ServerName,
  2941. FunctionCode,
  2942. Level,
  2943. (LPBYTE) &InputDataPtr,
  2944. (LPBYTE *)&NetlogonInfo1 );
  2945. if ( NetStatus != NERR_Success ) {
  2946. fprintf( stderr, "I_NetLogonControl failed: " );
  2947. PrintStatus( NetStatus );
  2948. return(1);
  2949. }
  2950. if( (Level == 1) || (Level == 2) ) {
  2951. //
  2952. // Print level 1 information
  2953. //
  2954. printf( "Flags: %lx", NetlogonInfo1->netlog1_flags );
  2955. if ( NetlogonInfo1->netlog1_flags & NETLOGON_REPLICATION_IN_PROGRESS ) {
  2956. if ( NetlogonInfo1->netlog1_flags & NETLOGON_FULL_SYNC_REPLICATION ) {
  2957. printf( " FULL_SYNC " );
  2958. }
  2959. else {
  2960. printf( " PARTIAL_SYNC " );
  2961. }
  2962. printf( " REPLICATION_IN_PROGRESS" );
  2963. }
  2964. else if ( NetlogonInfo1->netlog1_flags & NETLOGON_REPLICATION_NEEDED ) {
  2965. if ( NetlogonInfo1->netlog1_flags & NETLOGON_FULL_SYNC_REPLICATION ) {
  2966. printf( " FULL_SYNC " );
  2967. }
  2968. else {
  2969. printf( " PARTIAL_SYNC " );
  2970. }
  2971. printf( " REPLICATION_NEEDED" );
  2972. }
  2973. if ( NetlogonInfo1->netlog1_flags & NETLOGON_REDO_NEEDED) {
  2974. printf( " REDO_NEEDED" );
  2975. }
  2976. if ( Level != 2 ) {
  2977. printf( "\n" );
  2978. }
  2979. //
  2980. // For level 2, this is superfluous (same as tc_connection_status) or
  2981. // miss leading (the status for the BDC to PDC trust not for the queried domain).
  2982. //
  2983. if ( Level != 2 ) {
  2984. printf( "Connection ");
  2985. PrintStatus( NetlogonInfo1->netlog1_pdc_connection_status );
  2986. }
  2987. //
  2988. // Output the last DNS update status if asked
  2989. //
  2990. if ( FunctionCode == NETLOGON_CONTROL_QUERY_DNS_REG ) {
  2991. if ( NetlogonInfo1->netlog1_flags & NETLOGON_DNS_UPDATE_FAILURE ) {
  2992. printf( "There was a failure in the last update for one of the DC-specific DNS records\n" );
  2993. } else {
  2994. printf( "There was no failure in the last update for all DC-specific DNS records\n" );
  2995. }
  2996. }
  2997. }
  2998. if( Level == 2 ) {
  2999. //
  3000. // Print level 2 only information
  3001. //
  3002. PNETLOGON_INFO_2 NetlogonInfo2;
  3003. NetlogonInfo2 = (PNETLOGON_INFO_2)NetlogonInfo1;
  3004. if ( NetlogonInfo2->netlog2_flags & NETLOGON_HAS_IP ) {
  3005. printf( " HAS_IP " );
  3006. }
  3007. if ( NetlogonInfo2->netlog2_flags & NETLOGON_HAS_TIMESERV ) {
  3008. printf( " HAS_TIMESERV " );
  3009. }
  3010. printf("\n");
  3011. printf("Trusted DC Name %ws \n",
  3012. NetlogonInfo2->netlog2_trusted_dc_name );
  3013. printf("Trusted DC Connection Status ");
  3014. PrintStatus( NetlogonInfo2->netlog2_tc_connection_status );
  3015. //
  3016. // If the server returned the trust verification status,
  3017. // print it out
  3018. //
  3019. if ( NetlogonInfo2->netlog2_flags & NETLOGON_VERIFY_STATUS_RETURNED ) {
  3020. printf("Trust Verification ");
  3021. PrintStatus( NetlogonInfo2->netlog2_pdc_connection_status );
  3022. }
  3023. }
  3024. if ( Level == 3 ) {
  3025. printf( "Number of attempted logons: %ld\n",
  3026. ((PNETLOGON_INFO_3)NetlogonInfo1)->netlog3_logon_attempts );
  3027. }
  3028. if( Level == 4 ) {
  3029. PNETLOGON_INFO_4 NetlogonInfo4;
  3030. NetlogonInfo4 = (PNETLOGON_INFO_4)NetlogonInfo1;
  3031. printf("Domain Name: %ws\n",
  3032. NetlogonInfo4->netlog4_trusted_domain_name );
  3033. printf("Trusted DC Name %ws \n",
  3034. NetlogonInfo4->netlog4_trusted_dc_name );
  3035. }
  3036. NetApiBufferFree( NetlogonInfo1 );
  3037. }
  3038. #ifndef NTRK_RELEASE
  3039. //
  3040. // If we've been asked to debug password encryption,
  3041. // do so.
  3042. //
  3043. if ( AnsiPassword != NULL ) {
  3044. LPWSTR Password = NULL;
  3045. UNICODE_STRING UnicodePasswordString;
  3046. STRING AnsiPasswordString;
  3047. CHAR LmPasswordBuffer[LM20_PWLEN + 1];
  3048. Password = NetpAllocWStrFromAStr( AnsiPassword );
  3049. RtlInitUnicodeString( &UnicodePasswordString, Password );
  3050. //
  3051. // Compute the NT One-Way-Function of the password
  3052. //
  3053. Status = RtlCalculateNtOwfPassword( &UnicodePasswordString,
  3054. &NtOwfPassword );
  3055. if ( !NT_SUCCESS(Status) ) {
  3056. fprintf( stderr, "RtlCalculateNtOwfPassword failed: 0x%lx", Status);
  3057. return(1);
  3058. }
  3059. printf( "NT OWF Password for: %s ", AnsiPassword );
  3060. DumpBuffer( &NtOwfPassword, sizeof( NtOwfPassword ));
  3061. printf("\n");
  3062. NtPasswordPresent = TRUE;
  3063. //
  3064. // Compute the Ansi version to the Cleartext password.
  3065. //
  3066. // The Ansi version of the Cleartext password is at most 14 bytes long,
  3067. // exists in a trailing zero filled 15 byte buffer,
  3068. // is uppercased.
  3069. //
  3070. AnsiPasswordString.Buffer = LmPasswordBuffer;
  3071. AnsiPasswordString.MaximumLength = sizeof(LmPasswordBuffer);
  3072. RtlZeroMemory( LmPasswordBuffer, sizeof(LmPasswordBuffer) );
  3073. Status = RtlUpcaseUnicodeStringToOemString(
  3074. &AnsiPasswordString,
  3075. &UnicodePasswordString,
  3076. FALSE );
  3077. if ( !NT_SUCCESS(Status) ) {
  3078. RtlZeroMemory( LmPasswordBuffer, sizeof(LmPasswordBuffer) );
  3079. Status = STATUS_SUCCESS;
  3080. printf( "LM OWF Password for: %s\n", AnsiPassword );
  3081. printf( " ----- Password doesn't translate from unicode ----\n");
  3082. LmPasswordPresent = FALSE;
  3083. } else {
  3084. Status = RtlCalculateLmOwfPassword(
  3085. LmPasswordBuffer,
  3086. &LmOwfPassword);
  3087. printf( "LM OWF Password for: %s ", AnsiPassword );
  3088. DumpBuffer( &LmOwfPassword, sizeof( LmOwfPassword ));
  3089. printf("\n");
  3090. LmPasswordPresent = TRUE;
  3091. }
  3092. }
  3093. //
  3094. // If we've been given a Rid,
  3095. // use it to further encrypt the password
  3096. //
  3097. if ( Rid != 0 ) {
  3098. ENCRYPTED_LM_OWF_PASSWORD EncryptedLmOwfPassword;
  3099. ENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword;
  3100. if ( NtPasswordPresent ) {
  3101. Status = RtlEncryptNtOwfPwdWithIndex(
  3102. &NtOwfPassword,
  3103. &Rid,
  3104. &EncryptedNtOwfPassword
  3105. );
  3106. printf( "NT OWF Password encrypted by: 0x%lx ", Rid );
  3107. if ( NT_SUCCESS( Status ) ) {
  3108. DumpBuffer( &EncryptedNtOwfPassword,sizeof(EncryptedNtOwfPassword));
  3109. printf("\n");
  3110. } else {
  3111. printf( "RtlEncryptNtOwfPwdWithIndex returns 0x%lx\n", Status );
  3112. }
  3113. }
  3114. if ( LmPasswordPresent ) {
  3115. Status = RtlEncryptLmOwfPwdWithIndex(
  3116. &LmOwfPassword,
  3117. &Rid,
  3118. &EncryptedLmOwfPassword
  3119. );
  3120. printf( "LM OWF Password encrypted by: 0x%lx ", Rid );
  3121. if ( NT_SUCCESS( Status ) ) {
  3122. DumpBuffer( &EncryptedLmOwfPassword,sizeof(EncryptedLmOwfPassword));
  3123. printf("\n");
  3124. } else {
  3125. printf( "RtlEncryptNtOwfPwdWithIndex returns 0x%lx\n", Status );
  3126. }
  3127. }
  3128. }
  3129. #endif // NTRK_RELEASE
  3130. //
  3131. // If we've been asked to query a user,
  3132. // do so.
  3133. //
  3134. if ( QueryUser ) {
  3135. if ( AnsiUserName != NULL && *AnsiUserName != L'\0' ) {
  3136. PrintUserInfo( ServerName, AnsiUserName );
  3137. } else {
  3138. goto Usage;
  3139. }
  3140. }
  3141. //
  3142. // If we've been asked to get the list of domain controllers,
  3143. // Do so
  3144. //
  3145. if ( AnsiDomainName != NULL ) {
  3146. LPWSTR DomainName;
  3147. DomainName = NetpAllocWStrFromAStr( AnsiDomainName );
  3148. if ( DomainName == NULL ) {
  3149. fprintf( stderr, "Not enough memory\n" );
  3150. return(1);
  3151. }
  3152. if ( GetPdcName ) {
  3153. LPWSTR PdcName;
  3154. NetStatus = NetGetDCName(
  3155. ServerName,
  3156. DomainName,
  3157. (LPBYTE *)&PdcName );
  3158. if ( NetStatus != NERR_Success ) {
  3159. fprintf( stderr, "NetGetDCName failed: " );
  3160. PrintStatus( NetStatus );
  3161. return(1);
  3162. }
  3163. printf( "PDC for Domain " FORMAT_LPWSTR " is " FORMAT_LPWSTR "\n",
  3164. DomainName, PdcName );
  3165. } else if ( DoDsGetDcName ) {
  3166. NetStatus = DsGetDcNameWithAccountA(
  3167. AnsiServerName,
  3168. AnsiUserName,
  3169. AnsiUserName == NULL ? 0 : 0xFFFFFFFF,
  3170. AnsiDomainName,
  3171. NULL, // No domain guid
  3172. AnsiSiteName,
  3173. DsGetDcNameFlags,
  3174. &DomainControllerInfo );
  3175. if ( NetStatus != NERR_Success ) {
  3176. fprintf( stderr, "DsGetDcName failed: ");
  3177. PrintStatus( NetStatus );
  3178. return(1);
  3179. }
  3180. printf(" DC: %s\n", DomainControllerInfo->DomainControllerName );
  3181. printf(" Address: %s\n", DomainControllerInfo->DomainControllerAddress );
  3182. if ( !IsEqualGUID( &DomainControllerInfo->DomainGuid, &NlGlobalZeroGuid) ) {
  3183. RpcStatus = UuidToStringA( &DomainControllerInfo->DomainGuid, &StringGuid );
  3184. if ( RpcStatus != RPC_S_OK ) {
  3185. return ERROR_NOT_ENOUGH_MEMORY;
  3186. }
  3187. printf(" Dom Guid: %s\n", StringGuid );
  3188. RpcStringFreeA( &StringGuid );
  3189. }
  3190. if ( DomainControllerInfo->DomainName != NULL ) {
  3191. printf(" Dom Name: %s\n", DomainControllerInfo->DomainName );
  3192. }
  3193. if ( DomainControllerInfo->DnsForestName != NULL ) {
  3194. printf(" Forest Name: %s\n", DomainControllerInfo->DnsForestName );
  3195. }
  3196. if ( DomainControllerInfo->DcSiteName != NULL ) {
  3197. printf(" Dc Site Name: %s\n", DomainControllerInfo->DcSiteName );
  3198. }
  3199. if ( DomainControllerInfo->ClientSiteName != NULL ) {
  3200. printf("Our Site Name: %s\n", DomainControllerInfo->ClientSiteName );
  3201. }
  3202. if ( DomainControllerInfo->Flags ) {
  3203. printf(" Flags:" );
  3204. if ( DomainControllerInfo->Flags & DS_NDNC_FLAG ) {
  3205. printf(" NDNC");
  3206. DomainControllerInfo->Flags &= ~DS_NDNC_FLAG;
  3207. }
  3208. if ( DomainControllerInfo->Flags & DS_PDC_FLAG ) {
  3209. printf(" PDC");
  3210. DomainControllerInfo->Flags &= ~DS_PDC_FLAG;
  3211. }
  3212. if ( DomainControllerInfo->Flags & DS_GC_FLAG ) {
  3213. printf(" GC");
  3214. DomainControllerInfo->Flags &= ~DS_GC_FLAG;
  3215. }
  3216. if ( DomainControllerInfo->Flags & DS_DS_FLAG ) {
  3217. printf(" DS");
  3218. DomainControllerInfo->Flags &= ~DS_DS_FLAG;
  3219. }
  3220. if ( DomainControllerInfo->Flags & DS_LDAP_FLAG ) {
  3221. printf(" LDAP");
  3222. DomainControllerInfo->Flags &= ~DS_LDAP_FLAG;
  3223. }
  3224. if ( DomainControllerInfo->Flags & DS_KDC_FLAG ) {
  3225. printf(" KDC");
  3226. DomainControllerInfo->Flags &= ~DS_KDC_FLAG;
  3227. }
  3228. if ( DomainControllerInfo->Flags & DS_TIMESERV_FLAG ) {
  3229. printf(" TIMESERV");
  3230. DomainControllerInfo->Flags &= ~DS_TIMESERV_FLAG;
  3231. }
  3232. if ( DomainControllerInfo->Flags & DS_GOOD_TIMESERV_FLAG ) {
  3233. printf(" GTIMESERV");
  3234. DomainControllerInfo->Flags &= ~DS_GOOD_TIMESERV_FLAG;
  3235. }
  3236. if ( DomainControllerInfo->Flags & DS_WRITABLE_FLAG ) {
  3237. printf(" WRITABLE");
  3238. DomainControllerInfo->Flags &= ~DS_WRITABLE_FLAG;
  3239. }
  3240. if ( DomainControllerInfo->Flags & DS_DNS_CONTROLLER_FLAG ) {
  3241. printf(" DNS_DC");
  3242. DomainControllerInfo->Flags &= ~DS_DNS_CONTROLLER_FLAG;
  3243. }
  3244. if ( DomainControllerInfo->Flags & DS_DNS_DOMAIN_FLAG ) {
  3245. printf(" DNS_DOMAIN");
  3246. DomainControllerInfo->Flags &= ~DS_DNS_DOMAIN_FLAG;
  3247. }
  3248. if ( DomainControllerInfo->Flags & DS_DNS_FOREST_FLAG ) {
  3249. printf(" DNS_FOREST");
  3250. DomainControllerInfo->Flags &= ~DS_DNS_FOREST_FLAG;
  3251. }
  3252. if ( DomainControllerInfo->Flags & DS_CLOSEST_FLAG ) {
  3253. printf(" CLOSE_SITE");
  3254. DomainControllerInfo->Flags &= ~DS_CLOSEST_FLAG;
  3255. }
  3256. if ( DomainControllerInfo->Flags != 0 ) {
  3257. printf(" 0x%lX", DomainControllerInfo->Flags);
  3258. }
  3259. printf("\n");
  3260. }
  3261. } else if ( DoDsGetFtinfo ) {
  3262. PLSA_FOREST_TRUST_INFORMATION ForestTrustInfo;
  3263. ULONG Index;
  3264. NetStatus = DsGetForestTrustInformationW(
  3265. ServerName,
  3266. DomainName,
  3267. DsGetFtinfoFlags,
  3268. &ForestTrustInfo );
  3269. if ( NetStatus != NERR_Success ) {
  3270. fprintf( stderr, "DsGetForestTrustInformation failed: ");
  3271. PrintStatus( NetStatus );
  3272. return(1);
  3273. }
  3274. for ( Index=0; Index<ForestTrustInfo->RecordCount; Index++ ) {
  3275. switch ( ForestTrustInfo->Entries[Index]->ForestTrustType ) {
  3276. case ForestTrustTopLevelName:
  3277. printf( "TLN: %wZ\n",
  3278. &ForestTrustInfo->Entries[Index]->ForestTrustData.TopLevelName );
  3279. break;
  3280. case ForestTrustDomainInfo:
  3281. printf( "Dom: %wZ (%wZ)\n",
  3282. &ForestTrustInfo->Entries[Index]->ForestTrustData.DomainInfo.DnsName,
  3283. &ForestTrustInfo->Entries[Index]->ForestTrustData.DomainInfo.NetbiosName );
  3284. break;
  3285. default:
  3286. printf( "Invalid Type: %ld\n", ForestTrustInfo->Entries[Index]->ForestTrustType );
  3287. }
  3288. }
  3289. } else if ( GetDcList ) {
  3290. if ( !GetDcListFromDs( DomainName ) ) {
  3291. DWORD DCCount;
  3292. PUNICODE_STRING DCNames;
  3293. DWORD i;
  3294. NetStatus = I_NetGetDCList(
  3295. ServerName,
  3296. DomainName,
  3297. &DCCount,
  3298. &DCNames );
  3299. if ( NetStatus != NERR_Success ) {
  3300. fprintf( stderr, "I_NetGetDCList failed: ");
  3301. PrintStatus( NetStatus );
  3302. return(1);
  3303. }
  3304. printf( "List of DCs in Domain " FORMAT_LPWSTR "\n", DomainName );
  3305. for (i=0; i<DCCount; i++ ) {
  3306. if ( DCNames[i].Length > 0 ) {
  3307. printf(" %wZ", &DCNames[i] );
  3308. } else {
  3309. printf(" NULL");
  3310. }
  3311. if ( i==0 ) {
  3312. printf( " (PDC)");
  3313. }
  3314. printf("\n");
  3315. }
  3316. }
  3317. } else if ( WhoWill ) {
  3318. if ( DomainName != NULL && *DomainName != L'\0' ) {
  3319. WhoWillLogMeOn( DomainName, UserName, IterationCount );
  3320. } else {
  3321. goto Usage;
  3322. }
  3323. } else if( QuerySync ) {
  3324. DWORD DCCount;
  3325. PUNICODE_STRING DCNames;
  3326. DWORD i;
  3327. PNETLOGON_INFO_1 SyncNetlogonInfo1 = NULL;
  3328. LPWSTR SyncServerName = NULL;
  3329. NetStatus = I_NetGetDCList(
  3330. ServerName,
  3331. DomainName,
  3332. &DCCount,
  3333. &DCNames );
  3334. if ( NetStatus != NERR_Success ) {
  3335. fprintf( stderr, "I_NetGetDCList failed: ");
  3336. PrintStatus( NetStatus );
  3337. return(1);
  3338. }
  3339. for (i=1; i<DCCount; i++ ) {
  3340. if ( DCNames[i].Length > 0 ) {
  3341. SyncServerName = DCNames[i].Buffer;
  3342. } else {
  3343. SyncServerName = NULL;
  3344. }
  3345. NetStatus = I_NetLogonControl(
  3346. SyncServerName,
  3347. NETLOGON_CONTROL_QUERY,
  3348. 1,
  3349. (LPBYTE *)&SyncNetlogonInfo1 );
  3350. if ( NetStatus != NERR_Success ) {
  3351. printf( "Server : " FORMAT_LPWSTR "\n", SyncServerName );
  3352. printf( "\tI_NetLogonControl failed: ");
  3353. PrintStatus( NetStatus );
  3354. }
  3355. else {
  3356. printf( "Server : " FORMAT_LPWSTR "\n", SyncServerName );
  3357. printf( "\tSyncState : " );
  3358. if ( SyncNetlogonInfo1->netlog1_flags == 0 ) {
  3359. printf( " IN_SYNC \n" );
  3360. }
  3361. else if ( SyncNetlogonInfo1->netlog1_flags & NETLOGON_REPLICATION_IN_PROGRESS ) {
  3362. printf( " REPLICATION_IN_PROGRESS \n" );
  3363. }
  3364. else if ( SyncNetlogonInfo1->netlog1_flags & NETLOGON_REPLICATION_NEEDED ) {
  3365. printf( " REPLICATION_NEEDED \n" );
  3366. } else {
  3367. printf( " UNKNOWN \n" );
  3368. }
  3369. printf( "\tConnectionState : ");
  3370. PrintStatus( SyncNetlogonInfo1->netlog1_pdc_connection_status );
  3371. NetApiBufferFree( SyncNetlogonInfo1 );
  3372. }
  3373. }
  3374. } else if( SimFullSync ) {
  3375. LPWSTR MachineName;
  3376. LPWSTR PdcName;
  3377. MachineName = NetpAllocWStrFromAStr( AnsiSimMachineName );
  3378. if ( MachineName == NULL ) {
  3379. fprintf( stderr, "Not enough memory\n" );
  3380. return(1);
  3381. }
  3382. NetStatus = NetGetDCName(
  3383. ServerName,
  3384. DomainName,
  3385. (LPBYTE *)&PdcName );
  3386. if ( NetStatus != NERR_Success ) {
  3387. fprintf( stderr, "NetGetDCName failed: " );
  3388. PrintStatus( NetStatus );
  3389. return(1);
  3390. }
  3391. Status = SimulateFullSync( PdcName, MachineName );
  3392. if ( !NT_SUCCESS( Status )) {
  3393. return(1);
  3394. }
  3395. }
  3396. }
  3397. //
  3398. // if we are asked to display the change log file. do so.
  3399. //
  3400. if( ListDeltasFlag ) {
  3401. LPWSTR DeltaFileName;
  3402. DeltaFileName = NetpAllocWStrFromAStr( AnsiDeltaFileName );
  3403. if ( DeltaFileName == NULL ) {
  3404. fprintf( stderr, "Not enough memory\n" );
  3405. return(1);
  3406. }
  3407. ListDeltas( DeltaFileName );
  3408. }
  3409. //
  3410. // Handle shutting down a system.
  3411. //
  3412. if ( ShutdownReason != NULL ) {
  3413. if ( !InitiateSystemShutdownA( AnsiServerName,
  3414. ShutdownReason,
  3415. ShutdownSeconds,
  3416. FALSE, // Don't lose unsaved changes
  3417. TRUE ) ) { // Reboot when done
  3418. fprintf( stderr, "InitiateSystemShutdown failed: ");
  3419. PrintStatus( GetLastError() );
  3420. return 1;
  3421. }
  3422. }
  3423. if ( ShutdownAbort ) {
  3424. if ( !AbortSystemShutdownA( AnsiServerName ) ) {
  3425. fprintf( stderr, "AbortSystemShutdown failed: ");
  3426. PrintStatus( GetLastError() );
  3427. return 1;
  3428. }
  3429. }
  3430. //
  3431. // Print the list of domain trusts on a workstation.
  3432. //
  3433. if ( DomainTrustsFlag ) {
  3434. ULONG CurrentIndex;
  3435. ULONG EntryCount;
  3436. PDS_DOMAIN_TRUSTSA TrustedDomainList;
  3437. if ( TrustsNeeded == 0 ) {
  3438. TrustsNeeded = DS_DOMAIN_VALID_FLAGS;
  3439. }
  3440. NetStatus = DsEnumerateDomainTrustsA(
  3441. AnsiServerName,
  3442. TrustsNeeded,
  3443. &TrustedDomainList,
  3444. &EntryCount );
  3445. if ( NetStatus != NO_ERROR ) {
  3446. fprintf( stderr, "DsEnumerateDomainTrusts failed: ");
  3447. PrintStatus( NetStatus );
  3448. return 1;
  3449. }
  3450. printf( "List of domain trusts:\n" );
  3451. for ( CurrentIndex=0; CurrentIndex<EntryCount; CurrentIndex++ ) {
  3452. printf( " %ld:", CurrentIndex );
  3453. NlPrintTrustedDomain( (PDS_DOMAIN_TRUSTSW)&TrustedDomainList[CurrentIndex],
  3454. TrustedDomainsVerboseOutput,
  3455. TRUE );
  3456. }
  3457. NetApiBufferFree( TrustedDomainList );
  3458. }
  3459. //
  3460. // Print the site names of all sites covered by this DC
  3461. //
  3462. if ( DoDsGetDcSiteCoverage ) {
  3463. LPSTR *SiteNames;
  3464. ULONG Nsites, i;
  3465. NetStatus = DsGetDcSiteCoverageA(
  3466. AnsiServerName,
  3467. &Nsites,
  3468. &SiteNames);
  3469. if ( NetStatus != NERR_Success ) {
  3470. fprintf( stderr, "DsGetDcSiteCoverage failed: ");
  3471. PrintStatus( NetStatus );
  3472. return(1);
  3473. }
  3474. for ( i = 0; i < Nsites; i++ ) {
  3475. printf("%s\n", SiteNames[i]);
  3476. }
  3477. NetApiBufferFree( SiteNames );
  3478. }
  3479. //
  3480. // Get the site name of a machine.
  3481. //
  3482. if ( DoDsGetSiteName ) {
  3483. LPSTR SiteName;
  3484. NetStatus = DsGetSiteNameA(
  3485. AnsiServerName,
  3486. &SiteName );
  3487. if ( NetStatus != NERR_Success ) {
  3488. fprintf( stderr, "DsGetSiteName failed: ");
  3489. PrintStatus( NetStatus );
  3490. return(1);
  3491. }
  3492. printf("%s\n", SiteName );
  3493. }
  3494. //
  3495. // Get the parent domain of a machine.
  3496. //
  3497. if ( DoGetParentDomain ) {
  3498. LPWSTR ParentName;
  3499. BOOL PdcSameSite;
  3500. NetStatus = NetLogonGetTimeServiceParentDomain(
  3501. ServerName,
  3502. &ParentName,
  3503. &PdcSameSite );
  3504. if ( NetStatus != NERR_Success ) {
  3505. fprintf( stderr, "GetParentDomain failed: ");
  3506. PrintStatus( NetStatus );
  3507. return(1);
  3508. }
  3509. printf("%ws (%ld)\n", ParentName, PdcSameSite );
  3510. }
  3511. //
  3512. // Deregister DNS host records
  3513. //
  3514. if ( DeregisterDnsHostRecords ) {
  3515. RPC_STATUS RpcStatus;
  3516. GUID DomainGuid;
  3517. GUID DsaGuid;
  3518. //
  3519. // Convert domain Guid string into the domain Guid
  3520. //
  3521. if ( StringDomainGuid != NULL ) {
  3522. RpcStatus = UuidFromStringA ( StringDomainGuid, &DomainGuid );
  3523. if ( RpcStatus != RPC_S_OK ) {
  3524. fprintf( stderr, "ERROR: Invalid Domain GUID specified\n" );
  3525. return(1);
  3526. }
  3527. }
  3528. //
  3529. // Convert Dsa Guid string into the Dsa Guid
  3530. //
  3531. if ( StringDsaGuid != NULL ) {
  3532. RpcStatus = UuidFromStringA ( StringDsaGuid, &DsaGuid );
  3533. if ( RpcStatus != RPC_S_OK ) {
  3534. fprintf( stderr, "ERROR: Invalid DSA GUID specified\n" );
  3535. return(1);
  3536. }
  3537. }
  3538. NetStatus = DsDeregisterDnsHostRecordsA (
  3539. AnsiServerName,
  3540. AnsiDnsDomainName,
  3541. StringDomainGuid == NULL ? NULL : &DomainGuid,
  3542. StringDsaGuid == NULL ? NULL : &DsaGuid,
  3543. AnsiDnsHostName );
  3544. if ( NetStatus != NERR_Success ) {
  3545. fprintf( stderr, "DsDeregisterDnsHostRecordsA failed: ");
  3546. PrintStatus( NetStatus );
  3547. return(1);
  3548. }
  3549. }
  3550. //
  3551. // Get the list of DC records in DNS for a given domain
  3552. //
  3553. if ( DoDsGetDcOpen ) {
  3554. HANDLE DsGetDcHandle = NULL;
  3555. ULONG SockAddressCount = 0;
  3556. LPSOCKET_ADDRESS SockAddressList = NULL;
  3557. CHAR SockAddrString[NL_SOCK_ADDRESS_LENGTH+1];
  3558. LPSTR AnsiHostName = NULL;
  3559. BOOL PreamblePrinted = FALSE;
  3560. BOOL SiteSpecPrinted = FALSE;
  3561. BOOL NonSiteSpecPrinted = FALSE;
  3562. WORD wVersionRequested;
  3563. WSADATA wsaData;
  3564. //
  3565. // Initilaize Winsock (needed for NetpSockAddrToStr);
  3566. //
  3567. wVersionRequested = MAKEWORD( 1, 1 );
  3568. NetStatus = WSAStartup( wVersionRequested, &wsaData );
  3569. if ( NetStatus != 0 ) {
  3570. fprintf( stderr, "Cannot initialize winsock: " );
  3571. PrintStatus( NetStatus );
  3572. return(1);
  3573. }
  3574. //
  3575. // Get a context for the DNS name queries.
  3576. //
  3577. NetStatus = DsGetDcOpenA( AnsiDomainName,
  3578. DS_NOTIFY_AFTER_SITE_RECORDS | DsGetDcOpenFlags,
  3579. AnsiSiteName,
  3580. NULL, // No domain guid
  3581. NULL, // No forest name
  3582. DsGetDcNameFlags,
  3583. &DsGetDcHandle );
  3584. if ( NetStatus != NO_ERROR ) {
  3585. fprintf( stderr, "DsGetDcOpenA failed: ");
  3586. PrintStatus( NetStatus );
  3587. return(1);
  3588. }
  3589. //
  3590. // Loop getting addresses
  3591. //
  3592. for ( ;; ) {
  3593. //
  3594. // Free any memory from a previous iteration.
  3595. //
  3596. if ( SockAddressList != NULL ) {
  3597. LocalFree( SockAddressList );
  3598. SockAddressList = NULL;
  3599. }
  3600. if ( AnsiHostName != NULL ) {
  3601. NetApiBufferFree( AnsiHostName );
  3602. AnsiHostName = NULL;
  3603. }
  3604. //
  3605. // Get the next set of IP addresses from DNS
  3606. //
  3607. NetStatus = DsGetDcNextA( DsGetDcHandle,
  3608. &SockAddressCount,
  3609. &SockAddressList,
  3610. &AnsiHostName );
  3611. //
  3612. // Process the exeptional conditions
  3613. //
  3614. if ( NetStatus == NO_ERROR ) {
  3615. ULONG i;
  3616. if ( !PreamblePrinted ) {
  3617. printf( "List of DCs in pseudo-random order taking into account SRV priorities and weights:\n" );
  3618. PreamblePrinted = TRUE;
  3619. }
  3620. if ( AnsiSiteName != NULL && !SiteSpecPrinted ) {
  3621. printf( "Site specific:\n" );
  3622. SiteSpecPrinted = TRUE;
  3623. }
  3624. if ( AnsiSiteName == NULL && !NonSiteSpecPrinted ) {
  3625. printf( "Non-Site specific:\n" );
  3626. NonSiteSpecPrinted = TRUE;
  3627. }
  3628. printf( " %s", AnsiHostName );
  3629. for (i = 0; i < SockAddressCount; i++ ) {
  3630. NetStatus = NetpSockAddrToStr( SockAddressList[i].lpSockaddr,
  3631. SockAddressList[i].iSockaddrLength,
  3632. SockAddrString );
  3633. if ( NetStatus == NO_ERROR ) {
  3634. printf( " %s", SockAddrString );
  3635. }
  3636. }
  3637. printf( "\n" );
  3638. //
  3639. // If the A record cannot be found for the SRV record in DNS,
  3640. // try the other name type.
  3641. //
  3642. } else if ( NetStatus == DNS_ERROR_RCODE_NAME_ERROR ) {
  3643. printf( "WARNING: No records available of specified type\n" );
  3644. continue;
  3645. //
  3646. // If we've processed all of the site specific SRV records
  3647. // just indicate that we continue with non-site specific
  3648. //
  3649. } else if ( NetStatus == ERROR_FILEMARK_DETECTED ) {
  3650. AnsiSiteName = NULL;
  3651. continue;
  3652. //
  3653. // If we're done,
  3654. // break out of the loop.
  3655. //
  3656. } else if ( NetStatus == ERROR_NO_MORE_ITEMS ) {
  3657. break;
  3658. //
  3659. // If DNS isn't available,
  3660. // blow this request away.
  3661. //
  3662. } else if ( NetStatus == ERROR_TIMEOUT ||
  3663. NetStatus == DNS_ERROR_RCODE_SERVER_FAILURE ) { // Server failed
  3664. fprintf( stderr, "ERROR: DNS server failure: ");
  3665. PrintStatus( NetStatus );
  3666. return(1);
  3667. //
  3668. // If IP or DNS is not configured,
  3669. // tell the caller.
  3670. //
  3671. } else if ( NetStatus == DNS_ERROR_NO_TCPIP || // TCP/IP not configured
  3672. NetStatus == DNS_ERROR_NO_DNS_SERVERS ) { // DNS not configured
  3673. printf( "ERROR: DNS query indicates that IP is not configured on this machine\n" );
  3674. break;
  3675. //
  3676. // We don't handle any other error.
  3677. //
  3678. } else {
  3679. fprintf( stderr, "ERROR: DNS query failure: ");
  3680. PrintStatus( NetStatus );
  3681. return(1);
  3682. }
  3683. }
  3684. //
  3685. // Close
  3686. //
  3687. if ( DsGetDcHandle != NULL ) {
  3688. DsGetDcCloseW( DsGetDcHandle );
  3689. }
  3690. }
  3691. //
  3692. // Get the client digest
  3693. //
  3694. if ( DoClientDigest ) {
  3695. ULONG Rid;
  3696. LPWSTR UnicodeDomainName = NULL;
  3697. CHAR NewMessageDigest[NL_DIGEST_SIZE];
  3698. CHAR OldMessageDigest[NL_DIGEST_SIZE];
  3699. UnicodeDomainName = NetpAllocWStrFromAStr( AnsiDomainName );
  3700. if ( UnicodeDomainName == NULL ) {
  3701. fprintf( stderr, "Not enough memory\n");
  3702. return(1);
  3703. }
  3704. //
  3705. // First get the trust RID
  3706. //
  3707. NetStatus = I_NetlogonGetTrustRid( ServerName,
  3708. UnicodeDomainName,
  3709. &Rid );
  3710. if ( NetStatus != NO_ERROR ) {
  3711. fprintf( stderr, "I_NetlogonGetTrustRid failed: ");
  3712. PrintStatus( NetStatus );
  3713. return(1);
  3714. }
  3715. //
  3716. // Next calculate the client digest
  3717. //
  3718. NetStatus = I_NetlogonComputeClientDigest(
  3719. ServerName,
  3720. UnicodeDomainName,
  3721. Message,
  3722. strlen(Message)*sizeof(CHAR),
  3723. NewMessageDigest,
  3724. OldMessageDigest );
  3725. if ( NetStatus != NO_ERROR ) {
  3726. fprintf( stderr, "I_NetlogonComputeClientDigest failed: ");
  3727. PrintStatus( NetStatus );
  3728. return(1);
  3729. }
  3730. //
  3731. // Output the RID and the digest
  3732. //
  3733. printf( "Account RID: 0x%lx\n", Rid );
  3734. printf( "New digest: " );
  3735. NlpDumpBuffer(NL_ENCRYPT, NewMessageDigest, sizeof(NewMessageDigest) );
  3736. printf( "Old digest: " );
  3737. NlpDumpBuffer(NL_ENCRYPT, OldMessageDigest, sizeof(OldMessageDigest) );
  3738. }
  3739. //
  3740. // Get the server digest
  3741. //
  3742. if ( DoServerDigest ) {
  3743. CHAR NewMessageDigest[NL_DIGEST_SIZE];
  3744. CHAR OldMessageDigest[NL_DIGEST_SIZE];
  3745. NetStatus = I_NetlogonComputeServerDigest(
  3746. ServerName,
  3747. Rid,
  3748. Message,
  3749. strlen(Message)*sizeof(CHAR),
  3750. NewMessageDigest,
  3751. OldMessageDigest );
  3752. if ( NetStatus != NO_ERROR ) {
  3753. fprintf( stderr, "I_NetlogonComputeServerDigest failed: ");
  3754. PrintStatus( NetStatus );
  3755. return(1);
  3756. }
  3757. //
  3758. // Output the RID and the digest
  3759. //
  3760. printf( "Account RID: 0x%lx\n", Rid );
  3761. printf( "New digest: " );
  3762. NlpDumpBuffer(NL_ENCRYPT, NewMessageDigest, sizeof(NewMessageDigest) );
  3763. printf( "Old digest: " );
  3764. NlpDumpBuffer(NL_ENCRYPT, OldMessageDigest, sizeof(OldMessageDigest) );
  3765. }
  3766. //
  3767. // If we've been asked to convert an NT GMT time to ascii,
  3768. // Do so
  3769. //
  3770. PrintTime( "", ConvertTime );
  3771. #ifndef NTRK_RELEASE
  3772. //
  3773. // If we've been asked to unload netlogon.dll,
  3774. // stop the service.
  3775. //
  3776. if ( UnloadNetlogonFlag ) {
  3777. StopService( SERVICE_NETLOGON );
  3778. }
  3779. #endif // NTRK_RELEASE
  3780. printf("The command completed successfully\n");
  3781. return 0;
  3782. }