Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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