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.

2478 lines
68 KiB

  1. /*++
  2. Copyright (c) 1997-1998 Microsoft Corporation
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. This module contains the code to process OS Chooser message
  7. for the BINL server.
  8. Author:
  9. Adam Barr (adamba) 9-Jul-1997
  10. Geoff Pease (gpease) 10-Nov-1997
  11. Environment:
  12. User Mode - Win32
  13. Revision History:
  14. --*/
  15. #include "binl.h"
  16. #pragma hdrstop
  17. //
  18. // When all else fails "Error screen".
  19. //
  20. CHAR ErrorScreenHeaders[] =
  21. "<OSCML>"\
  22. "<META KEY=F3 ACTION=\"REBOOT\">"
  23. "<META KEY=ENTER ACTION=\"REBOOT\">"
  24. "<TITLE> Client Installation Wizard Error "; // there is a %08x after this
  25. CHAR ErrorScreenBody[] =
  26. " </TITLE>"
  27. "<FOOTER> Press F3 to reboot</FOOTER>"
  28. "<BODY LEFT=3 RIGHT=76><BR><BR>"; // the error message is inserted here
  29. CHAR ErrorScreenTrailer[] =
  30. "An error occurred on the server. Please notify your administrator.<BR>"
  31. "%SUBERROR%<BR>"
  32. "</BODY>"
  33. "</OSCML>";
  34. #define RANDOM_SEED (98725757)
  35. static PCWSTR gUsableChars = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  36. void
  37. OscCreateWin32SubError(
  38. PCLIENT_STATE clientState,
  39. DWORD Error )
  40. /*++
  41. Routine Description:
  42. Create a OSC Variable SUBERROR with the actual Win32 error code that
  43. caused the BINL error.
  44. Arguments:
  45. clientState - client state to add the variable too.
  46. Error - the Win32 error that occurred.
  47. --*/
  48. {
  49. DWORD dwLen;
  50. PWCHAR ErrorResponse = NULL;
  51. PWCHAR ErrorMsg = NULL;
  52. BOOL UsedFallback = FALSE;
  53. PWCHAR pch;
  54. DWORD ErrorLength;
  55. const WCHAR UnknownErrorMsg[] = L"Unknown Error.";
  56. const WCHAR ErrorString[] = L"Error: 0x%08x - %s";
  57. TraceFunc( "OscCreateWin32SubError( )\n" );
  58. // Retrieve the error message from system resources.
  59. dwLen = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  60. FORMAT_MESSAGE_IGNORE_INSERTS |
  61. FORMAT_MESSAGE_FROM_HMODULE |
  62. FORMAT_MESSAGE_FROM_SYSTEM,
  63. NULL,
  64. Error,
  65. 0,
  66. (LPWSTR) &ErrorMsg,
  67. 0,
  68. NULL );
  69. if ( dwLen == 0 )
  70. goto Cleanup;
  71. #if DBG
  72. if ( ErrorMsg )
  73. DebugMemoryAdd( ErrorMsg, __FILE__, __LINE__, "BINL", LPTR, wcslen(ErrorMsg), "ErrorMsg" );
  74. #endif
  75. // If all else fails, just print an error code out.
  76. if ( ErrorMsg == NULL ) {
  77. UsedFallback = TRUE;
  78. ErrorMsg = (PWCHAR) UnknownErrorMsg;
  79. dwLen = wcslen(ErrorMsg);
  80. }
  81. // The + 4 is the extra characters of the "%08x" of the generated error message.
  82. ErrorLength = dwLen + (sizeof( ErrorString )/sizeof(ErrorString[0])) + 4;
  83. ErrorResponse = (PWCHAR) BinlAllocateMemory( ErrorLength * sizeof(WCHAR) );
  84. if ( ErrorResponse == NULL ) {
  85. goto Cleanup;
  86. }
  87. wsprintf( ErrorResponse, ErrorString, Error, ErrorMsg );
  88. // We need to go through the string and elminate any CRs or LFs that
  89. // FormatMessageA() might have introduced.
  90. pch = ErrorResponse;
  91. while ( *pch )
  92. {
  93. if ( *pch == '\r' || * pch == '\n' )
  94. *pch = 32; // change to space
  95. pch++;
  96. }
  97. OscAddVariableW( clientState, "SUBERROR", ErrorResponse );
  98. Cleanup:
  99. if ( ErrorResponse ) {
  100. BinlFreeMemory( ErrorResponse );
  101. }
  102. if ( ErrorMsg && !UsedFallback ) {
  103. BinlFreeMemory( ErrorMsg );
  104. }
  105. }
  106. void
  107. OscCreateLDAPSubError(
  108. PCLIENT_STATE clientState,
  109. DWORD Error )
  110. /*++
  111. Routine Description:
  112. Create a OSC Variable SUBERROR with the actual LDAP error code that
  113. caused the BINL error.
  114. Arguments:
  115. clientState - client state to add the variable too.
  116. Error - the LDAP error that occurred.
  117. --*/
  118. {
  119. DWORD dwLen;
  120. PWCHAR ErrorResponse = NULL;
  121. DWORD ErrorLength;
  122. const WCHAR LdapErrorMsg[] = L"LDAP Error: 0x%08x";
  123. TraceFunc( "OscCreateLDAPSubError( )\n" );
  124. // The + 13 is the "0x12345678 - " of the generated error message.
  125. ErrorLength = wcslen(LdapErrorMsg) + 1 + 13;
  126. ErrorResponse = (PWCHAR) BinlAllocateMemory( ErrorLength * sizeof(WCHAR) );
  127. if ( ErrorResponse == NULL ) {
  128. goto Cleanup;
  129. }
  130. wsprintf( ErrorResponse, LdapErrorMsg, Error );
  131. OscAddVariableW( clientState, "SUBERROR", ErrorResponse );
  132. Cleanup:
  133. if ( ErrorResponse ) {
  134. BinlFreeMemory( ErrorResponse );
  135. }
  136. }
  137. //
  138. // This routine was stolen from private\ntos\rtl\sertl.c\RtlRunEncodeUnicodeString().
  139. //
  140. VOID
  141. OscGenerateSeed(
  142. UCHAR Seed[1]
  143. )
  144. /*++
  145. Routine Description:
  146. Generates a one-byte seed for use in run encoding/decoding client
  147. state variables such as passwords.
  148. Arguments:
  149. Seed - points to a single byte that holds the generated seed.
  150. Return Value:
  151. None.
  152. --*/
  153. {
  154. LARGE_INTEGER Time;
  155. PUCHAR LocalSeed;
  156. NTSTATUS Status;
  157. ULONG i;
  158. //
  159. // Use the 2nd byte of current time as the seed.
  160. // This byte seems to be sufficiently random (by observation).
  161. //
  162. Status = NtQuerySystemTime ( &Time );
  163. BinlAssert(NT_SUCCESS(Status));
  164. LocalSeed = (PUCHAR)((PVOID)&Time);
  165. i = 1;
  166. (*Seed) = LocalSeed[ i ];
  167. //
  168. // Occasionally, this byte could be zero. That would cause the
  169. // string to become un-decodable, since 0 is the magic value that
  170. // causes us to re-gen the seed. This loop makes sure that we
  171. // never end up with a zero byte (unless time is zero, as well).
  172. //
  173. while ( ((*Seed) == 0) && ( i < sizeof( Time ) ) )
  174. {
  175. (*Seed) |= LocalSeed[ i++ ] ;
  176. }
  177. if ( (*Seed) == 0 )
  178. {
  179. (*Seed) = 1;
  180. }
  181. }
  182. DWORD
  183. OscRunEncode(
  184. IN PCLIENT_STATE ClientState,
  185. IN LPSTR Data,
  186. OUT LPSTR * EncodedData
  187. )
  188. /*++
  189. Routine Description:
  190. Calls RtlRunEncodeUnicodeString for the Data, using the client
  191. state's random seed. Then convert each byte into a 2-byte
  192. value so that there are no NULLs in the result.
  193. Each byte is encoded into a 2-byte values as follows:
  194. The first byte has the low 4 bits of the byte in its low 4 bits,
  195. with 0xf in the high 4 bits
  196. The second byte has the high 4 bits of the byte in its high 4 bits,
  197. with 0xf in the low 4 bits
  198. Arguments:
  199. ClientState - the client state.
  200. Data - The data which is to be encoded.
  201. EncodedData - An allocated buffer which holds the encoded result.
  202. Return Value:
  203. The result of the operation.
  204. --*/
  205. {
  206. STRING String;
  207. ULONG i;
  208. LPSTR p;
  209. RtlInitAnsiString(&String, Data);
  210. *EncodedData = BinlAllocateMemory((String.Length * 2) + 1);
  211. if (*EncodedData == NULL) {
  212. return ERROR_NOT_ENOUGH_SERVER_MEMORY;
  213. }
  214. RtlRunEncodeUnicodeString(&ClientState->Seed, (PUNICODE_STRING)&String);
  215. for (i = 0, p = *EncodedData; i < String.Length; i++) {
  216. *(p++) = Data[i] | 0xf0;
  217. *(p++) = Data[i] | 0x0f;
  218. }
  219. *p = '\0';
  220. return ERROR_SUCCESS;
  221. }
  222. DWORD
  223. OscRunDecode(
  224. IN PCLIENT_STATE ClientState,
  225. IN LPSTR EncodedData,
  226. OUT LPSTR * Data
  227. )
  228. /*++
  229. Routine Description:
  230. Convert the encoded data (see OscRunEncode) into the real bytes,
  231. then calls RtlRunDecodeUnicodeString on that, using the client
  232. state's random seed.
  233. Arguments:
  234. ClientState - the client state.
  235. EncodedData - the encoded data from OscRunEncode.
  236. Data - An allocated buffer which holds the decoded result.
  237. Return Value:
  238. The result of the operation.
  239. --*/
  240. {
  241. STRING String;
  242. ULONG Count = strlen(EncodedData) / 2;
  243. ULONG i, j;
  244. LPSTR p;
  245. *Data = BinlAllocateMemory(Count + 1);
  246. if (*Data == NULL) {
  247. return ERROR_NOT_ENOUGH_SERVER_MEMORY;
  248. }
  249. for (i = 0, j = 0, p = *Data; i < Count; i++, j+=2) {
  250. *(p++) = (EncodedData[j] & 0x0f) | (EncodedData[j+1] & 0xf0);
  251. }
  252. *p = '\0';
  253. //
  254. // Set up the string ourselves since there may be NULLs in
  255. // the decoded data.
  256. //
  257. String.Buffer = *Data;
  258. String.Length = (USHORT)Count;
  259. String.MaximumLength = (USHORT)(Count+1);
  260. RtlRunDecodeUnicodeString(ClientState->Seed, (PUNICODE_STRING)&String);
  261. return ERROR_SUCCESS;
  262. }
  263. //
  264. // This routine was stolen from net\svcdlls\logonsrv\server\ssiauth.c.
  265. //
  266. BOOLEAN
  267. OscGenerateRandomBits(
  268. PUCHAR Buffer,
  269. ULONG BufferLen
  270. )
  271. /*++
  272. Routine Description:
  273. Generates random bits
  274. Arguments:
  275. pBuffer - Buffer to fill
  276. cbBuffer - Number of bytes in buffer
  277. Return Value:
  278. Status of the operation.
  279. --*/
  280. {
  281. BOOL Status = TRUE;
  282. HCRYPTPROV CryptProvider = 0;
  283. Status = CryptAcquireContext( &CryptProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT );
  284. if ( Status ) {
  285. Status = CryptGenRandom( CryptProvider, BufferLen, ( LPBYTE )Buffer );
  286. CryptReleaseContext( CryptProvider, 0 );
  287. } else {
  288. BinlPrintDbg((DEBUG_ERRORS, "CryptAcquireContext failed with %lu\n", GetLastError() ));
  289. }
  290. return ( Status != 0);
  291. }
  292. VOID
  293. OscGeneratePassword(
  294. OUT PWCHAR Password,
  295. OUT PULONG PasswordLength
  296. )
  297. {
  298. ULONG i;
  299. DWORD UsableCount = 0;
  300. DWORD Seed = 0;
  301. WCHAR GeneratedCharacter;
  302. BOOLEAN Proceed = FALSE;
  303. //
  304. // Set return password length and initialize
  305. // the generated password.
  306. //
  307. *PasswordLength = LM20_PWLEN * sizeof(WCHAR);
  308. memset( Password, 0, *PasswordLength );
  309. //
  310. // Initialize for random password generation.
  311. //
  312. UsableCount = lstrlen(gUsableChars);
  313. Seed = RANDOM_SEED ^ GetCurrentTime();
  314. srand( Seed );
  315. //
  316. // Ensure we have at least one period in the password.
  317. //
  318. Password[rand() % LM20_PWLEN] = L'.';
  319. //
  320. // Ensure there's at least one digit in the password.
  321. //
  322. do {
  323. i = rand() % LM20_PWLEN;
  324. } while ( Password[i] != 0 );
  325. Password[i] = (rand() % 10) + 0x30;
  326. //
  327. // Now fill in the rest of the password.
  328. //
  329. for (i = 0; i < LM20_PWLEN; i++) {
  330. if ( Password[i] == 0 ) {
  331. Password[i] = gUsableChars[rand() % UsableCount];
  332. }
  333. }
  334. }
  335. //
  336. // GenerateErrorScreen( )
  337. //
  338. DWORD
  339. GenerateErrorScreen(
  340. PCHAR *OutMessage,
  341. PULONG OutMessageLength,
  342. DWORD Error,
  343. PCLIENT_STATE clientState
  344. )
  345. {
  346. DWORD Err;
  347. DWORD dwLen;
  348. PCHAR ErrorMsg;
  349. DWORD ErrorScreenLength = strlen(ErrorScreenHeaders) + strlen(ErrorScreenBody) + strlen(ErrorScreenTrailer);
  350. PCHAR pch;
  351. PCHAR RspMessage = NULL;
  352. ULONG RspMessageLength = 0;
  353. const CHAR UnknownErrorMsg[] = "Unknown Error.";
  354. WCHAR ErrorMsgFilename[ MAX_PATH ];
  355. HANDLE hfile;
  356. LPSTR Messages[5];
  357. Messages[0] = OscFindVariableA( clientState, "USERNAME" );
  358. Messages[1] = OscFindVariableA( clientState, "USERDOMAIN" );
  359. Messages[2] = OscFindVariableA( clientState, "MACHINENAME" );
  360. Messages[3] = OscFindVariableA( clientState, "SUBERROR" );
  361. Messages[4] = NULL; // paranoid
  362. if ( _snwprintf( ErrorMsgFilename,
  363. sizeof(ErrorMsgFilename) / sizeof(ErrorMsgFilename[0]),
  364. L"%ws\\OSChooser\\%ws\\%08x.OSC",
  365. IntelliMirrorPathW,
  366. OscFindVariableW( clientState, "LANGUAGE" ),
  367. Error ) > 0 ) {
  368. ErrorMsgFilename[MAX_PATH-1] = L'\0'; // throw in terminating null just to be safe
  369. //
  370. // If we find the file, load it into memory.
  371. //
  372. hfile = CreateFile( ErrorMsgFilename, GENERIC_READ,
  373. FILE_SHARE_READ | FILE_SHARE_WRITE,
  374. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  375. if ( hfile != INVALID_HANDLE_VALUE ) {
  376. DWORD FileSize;
  377. //
  378. // Find out how big this screen is, if bigger than 0xFFFFFFFF we won't
  379. // display it.
  380. //
  381. FileSize = GetFileSize( hfile, NULL );
  382. if ( FileSize != 0xFFFFffff )
  383. {
  384. DWORD dwRead = 0;
  385. RspMessage = BinlAllocateMemory( FileSize + 3 );
  386. if ( RspMessage == NULL )
  387. {
  388. //
  389. // Ignore error and fall thru to generate an error screen
  390. //
  391. }
  392. else
  393. {
  394. RspMessageLength = 0;
  395. RspMessage[0] = '\0';
  396. while ( dwRead != FileSize )
  397. {
  398. BOOL b;
  399. DWORD dw;
  400. b = ReadFile( hfile, &RspMessage[dwRead], FileSize - dwRead, &dw, NULL );
  401. if (!b)
  402. {
  403. PWCHAR strings[2];
  404. strings[0] = ErrorMsgFilename;
  405. strings[1] = NULL;
  406. Err = GetLastError( );
  407. BinlPrint(( DEBUG_OSC_ERROR, "Error reading screen file: Seek=%u, Size=%u, File=%ws\n",
  408. dwRead, FileSize - dwRead, ErrorMsgFilename ));
  409. BinlReportEventW( EVENT_ERROR_READING_OSC_SCREEN,
  410. EVENTLOG_ERROR_TYPE,
  411. 1,
  412. sizeof(Err),
  413. strings,
  414. &Err
  415. );
  416. break;
  417. }
  418. dwRead += dw;
  419. }
  420. RspMessageLength = dwRead;
  421. RspMessage[dwRead] = '\0'; // paranoid
  422. CloseHandle( hfile );
  423. Err = ERROR_SUCCESS;
  424. goto Cleanup;
  425. }
  426. }
  427. else
  428. {
  429. BinlPrintDbg((DEBUG_OSC_ERROR, "!!Error 0x%08x - Could not determine file size.\n", GetLastError( )));
  430. //
  431. // Ignore error and fall thru to generate an error screen
  432. //
  433. }
  434. CloseHandle( hfile );
  435. }
  436. }
  437. BinlPrintDbg((DEBUG_OSC_ERROR, "no friendly OSC error screen available.\n" ));
  438. //
  439. // See if this is a BINL error or a system error and
  440. // get the text from the error tables.
  441. //
  442. dwLen = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  443. FORMAT_MESSAGE_FROM_HMODULE |
  444. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  445. GetModuleHandle(L"BINLSVC.DLL"),
  446. Error,
  447. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  448. (LPSTR) &ErrorMsg,
  449. 0,
  450. (va_list*) Messages );
  451. if ( dwLen == 0 )
  452. {
  453. BinlAssert( ErrorMsg == NULL );
  454. Err = GetLastError( );
  455. BinlPrintDbg((DEBUG_OSC_ERROR, "!! Error 0x%08x - no BINLSVC specific message available.\n", Err ));
  456. dwLen = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  457. FORMAT_MESSAGE_IGNORE_INSERTS |
  458. FORMAT_MESSAGE_FROM_SYSTEM,
  459. NULL,
  460. Error,
  461. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  462. (LPSTR) &ErrorMsg,
  463. 0,
  464. NULL );
  465. if ( dwLen == 0 )
  466. {
  467. BinlAssert( ErrorMsg == NULL );
  468. Err = GetLastError( );
  469. BinlPrintDbg((DEBUG_OSC_ERROR, "!! Error 0x%08x - no SYSTEM specific message available.\n", Err ));
  470. }
  471. }
  472. #if DBG
  473. if ( ErrorMsg )
  474. DebugMemoryAdd( ErrorMsg, __FILE__, __LINE__, "BINL", LPTR, strlen(ErrorMsg), "ErrorMsg" );
  475. #endif
  476. //
  477. // If all else fails, just print an error code.
  478. //
  479. if ( ErrorMsg == NULL ) {
  480. BinlPrintDbg(( DEBUG_OSC_ERROR, "sending using generic error message.\n" ));
  481. ErrorMsg = (PCHAR) UnknownErrorMsg;
  482. dwLen = strlen(ErrorMsg);
  483. }
  484. #define ERRORITEM "%s%08x%s<BR><BOLD>%s</BOLD><BR><BR>%s"
  485. //
  486. // The + 13 is the "0x12345678 - " of the generated error message.
  487. //
  488. RspMessageLength = ErrorScreenLength + strlen(ERRORITEM) + dwLen + 1 + 13;
  489. RspMessage = (PCHAR) BinlAllocateMemory( RspMessageLength );
  490. if ( RspMessage == NULL )
  491. {
  492. Err = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  493. goto Cleanup;
  494. }
  495. wsprintfA( RspMessage, ERRORITEM, ErrorScreenHeaders, Error, ErrorScreenBody, ErrorMsg, ErrorScreenTrailer );
  496. Err = ERROR_SUCCESS;
  497. Cleanup:
  498. if ( Err == ERROR_SUCCESS )
  499. {
  500. // BinlPrint(( DEBUG_OSC, "Generated Error Response:\n%s\n", RspMessage ));
  501. *OutMessage = RspMessage;
  502. *OutMessageLength = RspMessageLength;
  503. BinlReportEventA( EVENT_ERROR_SERVER_SIDE_ERROR,
  504. EVENTLOG_ERROR_TYPE,
  505. 4,
  506. sizeof(Error),
  507. Messages,
  508. &Error
  509. );
  510. }
  511. else
  512. {
  513. BinlPrintDbg(( DEBUG_OSC_ERROR, "!! Error 0x%08x - Couldn't generate error screen.\n", Err ));
  514. BinlReportEventA( EVENT_ERROR_GENERATING_SERVER_SIDE_ERROR,
  515. EVENTLOG_ERROR_TYPE,
  516. 4,
  517. sizeof(Err),
  518. Messages,
  519. &Err
  520. );
  521. *OutMessage = NULL;
  522. *OutMessageLength = 0;
  523. if ( RspMessage )
  524. {
  525. BinlFreeMemory( RspMessage );
  526. }
  527. }
  528. return Err;
  529. }
  530. //
  531. // Returns a pointer point to the next 'ch' or NULL character.
  532. //
  533. PCHAR
  534. FindNext(
  535. PCHAR Start,
  536. CHAR ch,
  537. PCHAR End
  538. )
  539. {
  540. TraceFunc("FindNext( )\n");
  541. while( Start != End && *Start && *Start !=ch ) {
  542. Start++;
  543. }
  544. if ( Start != End && *Start ) {
  545. return Start;
  546. } else {
  547. return NULL;
  548. }
  549. }
  550. //
  551. // Finds the screen name.
  552. //
  553. PCHAR
  554. FindScreenName(
  555. PCHAR Screen
  556. )
  557. {
  558. PCHAR Name;
  559. TraceFunc("FindScreenName( )\n");
  560. Name = strstr( Screen, "NAME" );
  561. if ( Name == NULL ) {
  562. return NULL;
  563. }
  564. Name += 5; // "Name" plus space
  565. return Name;
  566. }
  567. DWORD
  568. OscImpersonate(
  569. IN PCLIENT_STATE ClientState
  570. )
  571. /*++
  572. Routine Description:
  573. Makes the current thread impersonate the client. It is assumed
  574. that the client has already sent up a login screen. If this call
  575. succeeds, ClientState->AuthenticatedDCLdapHandle is valid.
  576. Arguments:
  577. ClientState - The client state.
  578. Return Value:
  579. Windows Error.
  580. --*/
  581. {
  582. DWORD Error = ERROR_SUCCESS;
  583. LPSTR pUserName;
  584. LPSTR pUserDomain;
  585. LPSTR pUserPassword;
  586. LPSTR pDecodedPassword = NULL;
  587. LPSTR tempptr;
  588. ULONG temp;
  589. ULONG LdapError = 0;
  590. SEC_WINNT_AUTH_IDENTITY_A authIdentity;
  591. BOOL bResult;
  592. BOOL Impersonating = FALSE;
  593. LPWSTR pCrossDsDc;
  594. TraceFunc( "OscImpersonate( ... )\n" );
  595. pCrossDsDc = OscFindVariableW( ClientState, "DCNAME" );
  596. if (*pCrossDsDc == L'\0') {
  597. //
  598. // Clean up any old client state.
  599. //
  600. if (ClientState->AuthenticatedDCLdapHandle &&
  601. ClientState->UserToken) {
  602. bResult = ImpersonateLoggedOnUser(ClientState->UserToken);
  603. if (bResult) {
  604. return STATUS_SUCCESS;
  605. }
  606. }
  607. }
  608. if (ClientState->AuthenticatedDCLdapHandle) {
  609. // Reconnecting again. Use new credentials.
  610. ldap_unbind(ClientState->AuthenticatedDCLdapHandle);
  611. ClientState->AuthenticatedDCLdapHandle = NULL;
  612. }
  613. if (ClientState->UserToken) {
  614. CloseHandle(ClientState->UserToken);
  615. ClientState->UserToken = NULL;
  616. }
  617. //
  618. // Get the login variables from the client state.
  619. //
  620. pUserName = OscFindVariableA( ClientState, "USERNAME" );
  621. pUserDomain = OscFindVariableA( ClientState, "USERDOMAIN" );
  622. pUserPassword = OscFindVariableA( ClientState, "*PASSWORD" );
  623. if (pUserName[0] == '\0') {
  624. OscAddVariableA( ClientState, "SUBERROR", "USERNAME" );
  625. Error = ERROR_BINL_MISSING_VARIABLE;
  626. goto ImpersonateFailed;
  627. }
  628. //
  629. // Decode the password.
  630. //
  631. Error = OscRunDecode(ClientState, pUserPassword, &pDecodedPassword);
  632. if (Error != ERROR_SUCCESS) {
  633. goto ImpersonateFailed;
  634. }
  635. //
  636. // if the user didn't enter a domain name, use the server's
  637. //
  638. if (pUserDomain == NULL || pUserDomain[0] == '\0') {
  639. OscAddVariableW( ClientState, "USERDOMAIN", BinlGlobalOurDomainName );
  640. pUserDomain = OscFindVariableA( ClientState, "USERDOMAIN" );
  641. }
  642. //
  643. // Do a LogonUser with the credentials, since we
  644. // need that to change the machine password (even the
  645. // authenticated LDAP handle won't do that if we don't
  646. // have 128-bit SSL setup on this machine).
  647. //
  648. bResult = LogonUserA(
  649. pUserName,
  650. pUserDomain,
  651. pDecodedPassword,
  652. LOGON32_LOGON_NETWORK_CLEARTEXT,
  653. LOGON32_PROVIDER_DEFAULT,
  654. &ClientState->UserToken);
  655. if (!bResult) {
  656. Error = GetLastError();
  657. BinlPrintDbg(( DEBUG_ERRORS, "LogonUser failed %lx\n", Error));
  658. ClientState->UserToken = NULL; // this may be set even on failure
  659. goto ImpersonateFailed;
  660. }
  661. //
  662. // if the user didn't enter a domain name, grab it out of the user token.
  663. //
  664. if (pUserDomain == NULL || pUserDomain[0] == '\0') {
  665. PTOKEN_USER userToken;
  666. DWORD tokenSize = 4096;
  667. userToken = (PTOKEN_USER) BinlAllocateMemory( tokenSize );
  668. if (userToken != NULL) {
  669. DWORD returnLength;
  670. BOOL bRC;
  671. bRC = GetTokenInformation( ClientState->UserToken,
  672. TokenUser,
  673. (LPVOID) userToken,
  674. tokenSize,
  675. &returnLength
  676. );
  677. if (bRC) {
  678. WCHAR uUser[128];
  679. DWORD cUser = 128;
  680. WCHAR uDomain[128];
  681. DWORD cDomain = 128;
  682. SID_NAME_USE peType;
  683. uDomain[0] = L'\0';
  684. uUser[0] = L'\0';
  685. bRC = LookupAccountSidW( NULL, // system name
  686. userToken->User.Sid,
  687. uUser, // user name
  688. &cUser, // user name count
  689. uDomain, // domain name
  690. &cDomain, // domain name count
  691. &peType
  692. );
  693. if (bRC && uDomain[0] != L'\0') {
  694. OscAddVariableW( ClientState, "USERDOMAIN", &uDomain[0] );
  695. }
  696. }
  697. BinlFreeMemory( userToken );
  698. }
  699. }
  700. //
  701. // Now impersonate the user.
  702. //
  703. bResult = ImpersonateLoggedOnUser(ClientState->UserToken);
  704. if (!bResult) {
  705. BinlPrintDbg(( DEBUG_ERRORS,
  706. "ImpersonateLoggedOnUser failed %x\n", GetLastError()));
  707. Error = GetLastError();
  708. goto ImpersonateFailed;
  709. }
  710. Impersonating = TRUE;
  711. //
  712. // Create authenticated DC connection for use in machine object creation
  713. // or modification.
  714. //
  715. BinlPrintDbg(( DEBUG_OSC,
  716. "ldap_init %S or %S\n", pCrossDsDc, BinlGlobalDefaultDS ));
  717. ClientState->AuthenticatedDCLdapHandle = ldap_init(
  718. (*pCrossDsDc != L'\0')
  719. ? pCrossDsDc
  720. : BinlGlobalDefaultDS,
  721. LDAP_PORT);
  722. BinlPrintDbg(( DEBUG_OSC,
  723. "ldap_init handle %x\n", ClientState->AuthenticatedDCLdapHandle ));
  724. temp = DS_DIRECTORY_SERVICE_REQUIRED | DS_IP_REQUIRED;
  725. Error = ldap_set_option(ClientState->AuthenticatedDCLdapHandle, LDAP_OPT_GETDSNAME_FLAGS, &temp );
  726. if (Error != ERROR_SUCCESS) {
  727. BinlPrintDbg(( DEBUG_ERRORS, "OscImpersonate: Error %x when setting ldap options\n" ));
  728. goto ImpersonateFailed;
  729. }
  730. temp = LDAP_VERSION3;
  731. Error = ldap_set_option(ClientState->AuthenticatedDCLdapHandle, LDAP_OPT_VERSION, &temp );
  732. if (Error != ERROR_SUCCESS) {
  733. BinlPrintDbg(( DEBUG_ERRORS, "OscImpersonate: Error %x when setting ldap options\n" ));
  734. goto ImpersonateFailed;
  735. }
  736. //
  737. // Tell LDAP to keep connections referenced after searches.
  738. //
  739. temp = (ULONG)((ULONG_PTR)LDAP_OPT_ON);
  740. Error = ldap_set_option(ClientState->AuthenticatedDCLdapHandle, LDAP_OPT_REF_DEREF_CONN_PER_MSG, &temp);
  741. if (Error != ERROR_SUCCESS) {
  742. BinlPrintDbg(( DEBUG_ERRORS, "OscImpersonate: Error %x when setting ldap options\n" ));
  743. goto ImpersonateFailed;
  744. }
  745. LdapError = ldap_connect(ClientState->AuthenticatedDCLdapHandle,0);
  746. if (LdapError != LDAP_SUCCESS) {
  747. BinlPrintDbg(( DEBUG_ERRORS,
  748. "this ldap_connect() failed %x\n", LdapError));
  749. goto ImpersonateFailed;
  750. }
  751. //
  752. // LDAP_AUTH_NEGOTIATE tells it to use the credentials of the user
  753. // we are impersonating.
  754. //
  755. LdapError = ldap_bind_sA(ClientState->AuthenticatedDCLdapHandle,
  756. NULL,
  757. NULL,
  758. LDAP_AUTH_NEGOTIATE);
  759. if (LdapError != LDAP_SUCCESS) {
  760. BinlPrintDbg(( DEBUG_ERRORS,
  761. "ldap_bind_s() failed %x\n", LdapError));
  762. goto ImpersonateFailed;
  763. }
  764. ImpersonateFailed:
  765. //
  766. // If we decoded the password, then erase and free it.
  767. //
  768. if (pDecodedPassword != NULL) {
  769. RtlSecureZeroMemory(pDecodedPassword, strlen(pDecodedPassword));
  770. BinlFreeMemory(pDecodedPassword);
  771. }
  772. if (LdapError != LDAP_SUCCESS) {
  773. Error = LdapMapErrorToWin32(LdapError);
  774. }
  775. if (Error) {
  776. PWCHAR strings[3];
  777. strings[0] = OscFindVariableW( ClientState, "USERNAME" );
  778. strings[1] = OscFindVariableW( ClientState, "USERDOMAIN" );
  779. strings[2] = NULL;
  780. BinlReportEventW( ERROR_BINL_ERR_USER_LOGIN_FAILED,
  781. EVENTLOG_WARNING_TYPE,
  782. 2,
  783. sizeof(ULONG),
  784. strings,
  785. &Error
  786. );
  787. if (ClientState->AuthenticatedDCLdapHandle) {
  788. ldap_unbind(ClientState->AuthenticatedDCLdapHandle);
  789. ClientState->AuthenticatedDCLdapHandle = NULL;
  790. }
  791. if (ClientState->UserToken) {
  792. CloseHandle(ClientState->UserToken);
  793. ClientState->UserToken = NULL;
  794. }
  795. if (Impersonating) {
  796. RevertToSelf();
  797. }
  798. }
  799. return Error;
  800. }
  801. DWORD
  802. OscRevert(
  803. IN PCLIENT_STATE ClientState
  804. )
  805. /*++
  806. Routine Description:
  807. Stops the current thread impersonating.
  808. Arguments:
  809. ClientState - The client state.
  810. Return Value:
  811. Windows Error.
  812. --*/
  813. {
  814. DWORD Error = ERROR_SUCCESS;
  815. BOOL bResult;
  816. TraceFunc( "OscRevert( ... )\n" );
  817. //
  818. // We are done impersonating for the moment.
  819. //
  820. bResult = RevertToSelf();
  821. if (!bResult) {
  822. BinlPrintDbg(( DEBUG_ERRORS,
  823. "RevertToSelf failed %x\n", GetLastError()));
  824. Error = GetLastError();
  825. }
  826. // keep the ldap handle around in case we need it again.
  827. // if (ClientState->AuthenticatedDCLdapHandle) {
  828. // ldap_unbind(ClientState->AuthenticatedDCLdapHandle);
  829. // ClientState->AuthenticatedDCLdapHandle = NULL;
  830. // }
  831. // if (ClientState->UserToken) {
  832. // CloseHandle(ClientState->UserToken);
  833. // ClientState->UserToken = NULL;
  834. // }
  835. return Error;
  836. }
  837. //
  838. // OscGuidToBytes( )
  839. //
  840. // Change CHAR Guid to bytes
  841. //
  842. DWORD
  843. OscGuidToBytes(
  844. LPSTR pszGuid,
  845. LPBYTE Guid )
  846. {
  847. PCHAR psz;
  848. ULONG len;
  849. ULONG i;
  850. TraceFunc( "OscGuidToBytes( ... )\n" );
  851. len = strlen(pszGuid);
  852. BinlAssert( len == 32 );
  853. if ( len != 32 ) {
  854. return ERROR_BINL_INVALID_GUID;
  855. }
  856. psz = pszGuid;
  857. i = 0;
  858. while ( i * 2 < 32 )
  859. {
  860. //
  861. // Upper 4-bits
  862. //
  863. CHAR c = *psz;
  864. psz++;
  865. Guid[i] = ( c > 59 ? (toupper(c) - 55) << 4 : (c - 48) << 4);
  866. //
  867. // Lower 4-bits
  868. //
  869. c = *psz;
  870. psz++;
  871. Guid[i] += ( c > 59 ? (toupper(c) - 55) : (c - 48) );
  872. //
  873. // Next byte
  874. //
  875. i++;
  876. }
  877. return ERROR_SUCCESS;
  878. }
  879. BOOLEAN
  880. OscSifIsSysPrep(
  881. LPWSTR pSysPrepSifPath
  882. )
  883. {
  884. DWORD dwErr;
  885. WCHAR Buffer[256];
  886. UNICODE_STRING UnicodeString;
  887. TraceFunc("OscSifIsSysPrep( )\n");
  888. Buffer[0] = UNICODE_NULL;
  889. GetPrivateProfileString(OSCHOOSER_SIF_SECTIONW,
  890. L"ImageType",
  891. Buffer, // default
  892. Buffer,
  893. 256,
  894. pSysPrepSifPath
  895. );
  896. RtlInitUnicodeString(&UnicodeString, Buffer);
  897. RtlUpcaseUnicodeString(&UnicodeString, &UnicodeString, FALSE);
  898. if (_wcsicmp(L"SYSPREP", Buffer)) {
  899. return FALSE;
  900. }
  901. return TRUE;
  902. }
  903. BOOLEAN
  904. OscSifIsCmdConsA(
  905. PCHAR pSifPath
  906. )
  907. {
  908. DWORD dwErr;
  909. CHAR Buffer[256];
  910. TraceFunc("OscSifIsCmdCons( )\n");
  911. Buffer[0] = '\0';
  912. GetPrivateProfileStringA(OSCHOOSER_SIF_SECTIONA,
  913. "ImageType",
  914. Buffer, // default
  915. Buffer,
  916. 256,
  917. pSifPath
  918. );
  919. if (_stricmp("CMDCONS", Buffer)) {
  920. return FALSE;
  921. }
  922. return TRUE;
  923. }
  924. BOOLEAN
  925. OscSifIsASR(
  926. PCHAR pSifPath
  927. )
  928. {
  929. DWORD dwErr;
  930. CHAR Buffer[256];
  931. TraceFunc("OscSifIsASR( )\n");
  932. Buffer[0] = '\0';
  933. GetPrivateProfileStringA(OSCHOOSER_SIF_SECTIONA,
  934. "ImageType",
  935. Buffer, // default
  936. Buffer,
  937. 256,
  938. pSifPath
  939. );
  940. if (_stricmp("ASR", Buffer)) {
  941. return FALSE;
  942. }
  943. return TRUE;
  944. }
  945. BOOLEAN
  946. OscSifIsWinPE(
  947. PCHAR pSifPath
  948. )
  949. {
  950. DWORD dwErr;
  951. CHAR Buffer[256];
  952. TraceFunc("OscSifIsWinPE( )\n");
  953. Buffer[0] = '\0';
  954. GetPrivateProfileStringA(OSCHOOSER_SIF_SECTIONA,
  955. "ImageType",
  956. Buffer, // default
  957. Buffer,
  958. 256,
  959. pSifPath
  960. );
  961. if (_stricmp("WinPE", Buffer)) {
  962. return FALSE;
  963. }
  964. return TRUE;
  965. }
  966. BOOLEAN
  967. OscSifIsWinPEW(
  968. PWCHAR pSifPath
  969. )
  970. {
  971. DWORD dwErr;
  972. WCHAR Buffer[256];
  973. TraceFunc("OscSifIsWinPE( )\n");
  974. Buffer[0] = UNICODE_NULL;
  975. GetPrivateProfileString(OSCHOOSER_SIF_SECTIONW,
  976. L"ImageType",
  977. Buffer, // default
  978. Buffer,
  979. 256,
  980. pSifPath
  981. );
  982. if (_wcsicmp(L"WinPE", Buffer)) {
  983. return FALSE;
  984. }
  985. return TRUE;
  986. }
  987. DWORD
  988. OscGetSkuType(
  989. PWSTR PathToTxtSetupSif
  990. )
  991. {
  992. PWSTR SifFile;
  993. DWORD SkuType = 0;
  994. SifFile = BinlAllocateMemory(
  995. (wcslen(PathToTxtSetupSif) +
  996. sizeof(L"\\txtsetup.sif")/sizeof(WCHAR) ) * sizeof(WCHAR));
  997. if (!SifFile) {
  998. return 0; //default to professional on failure
  999. }
  1000. wcscpy(SifFile, PathToTxtSetupSif);
  1001. if (SifFile[wcslen(SifFile)-1] == L'\\') {
  1002. wcscat( SifFile, L"txtsetup.sif" );
  1003. } else {
  1004. wcscat( SifFile, L"\\txtsetup.sif" );
  1005. }
  1006. SkuType = GetPrivateProfileInt(
  1007. L"SetupData",
  1008. L"ProductType",
  1009. 0,
  1010. SifFile );
  1011. BinlFreeMemory( SifFile );
  1012. return (SkuType);
  1013. }
  1014. BOOLEAN
  1015. OscGetClosestNt(
  1016. IN LPWSTR PathToKernel,
  1017. IN DWORD SkuType,
  1018. IN PCLIENT_STATE ClientState,
  1019. OUT LPWSTR SetupPath,
  1020. IN DWORD SetupPathSize,
  1021. OUT PBOOLEAN ExactMatch
  1022. )
  1023. {
  1024. DWORD Error = ERROR_SUCCESS;
  1025. WIN32_FIND_DATA FindData,TemplateData;
  1026. HANDLE hFind = INVALID_HANDLE_VALUE,hTemplate = INVALID_HANDLE_VALUE;
  1027. BOOLEAN Impersonated = FALSE;
  1028. WCHAR Path[MAX_PATH],TemplatesPath[MAX_PATH];
  1029. PWSTR p;
  1030. ULONGLONG BestVersion = (ULONGLONG)0;
  1031. ULONGLONG ThisVersion;
  1032. ULONGLONG KernelVersion;
  1033. DWORD dwPathLen;
  1034. BOOLEAN ReturnValue = FALSE;
  1035. BOOLEAN FoundWinPE;
  1036. TraceFunc("OscGetClosestNt( )\n");
  1037. Error = ImpersonateSecurityContext(&ClientState->ServerContextHandle);
  1038. if (Error != STATUS_SUCCESS) {
  1039. BinlPrintDbg(( DEBUG_OSC_ERROR, "ImpersonateSecurityContext: 0x%08x\n", Error ));
  1040. goto Cleanup;
  1041. }
  1042. Impersonated = TRUE;
  1043. //
  1044. // Get the version info of the kernel passed in
  1045. //
  1046. if (!OscGetNtVersionInfo(&KernelVersion, PathToKernel, ClientState)) {
  1047. BinlPrintDbg(( DEBUG_OSC_ERROR, "OscGetNtVersionInfo failed\n" ));
  1048. goto Cleanup;
  1049. }
  1050. //
  1051. // Resulting string should be something like:
  1052. // "D:\RemoteInstall\Setup\English\Images\*"
  1053. if ( _snwprintf( Path,
  1054. sizeof(Path) / sizeof(Path[0]),
  1055. L"%ws\\Setup\\%ws\\%ws\\*",
  1056. IntelliMirrorPathW,
  1057. OscFindVariableW(ClientState, "LANGUAGE"),
  1058. REMOTE_INSTALL_IMAGE_DIR_W
  1059. ) < 0 ) {
  1060. goto Cleanup;
  1061. }
  1062. Path[MAX_PATH-1] = L'\0'; // throw in terminating null just to be safe
  1063. hFind = FindFirstFile(Path, (LPVOID) &FindData);
  1064. if (hFind == INVALID_HANDLE_VALUE) {
  1065. goto Cleanup;
  1066. }
  1067. dwPathLen = wcslen(Path);
  1068. //
  1069. // Loop enumerating each subdirectory
  1070. //
  1071. do {
  1072. //
  1073. // Ignore directories "." and ".."
  1074. //
  1075. if (wcscmp(FindData.cFileName, L".") &&
  1076. wcscmp(FindData.cFileName, L"..") &&
  1077. (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  1078. DWORD ThisSkuType;
  1079. DWORD dwFileNameLen;
  1080. DWORD dwTemplatesPathLen;
  1081. //
  1082. // Add the sub-directory to the path
  1083. //
  1084. dwFileNameLen = wcslen(FindData.cFileName);
  1085. if (dwPathLen + dwFileNameLen + MAX_ARCHITECTURE_LENGTH + 1 > sizeof(Path)/sizeof(Path[0])) {
  1086. continue; // path too long, skip it
  1087. }
  1088. wcscpy(&Path[dwPathLen - 1], FindData.cFileName );
  1089. BinlPrintDbg(( DEBUG_OSC, "Found OS Directory: %ws\n", Path ));
  1090. // Resulting string should be something like:
  1091. // "D:\RemoteInstall\Setup\English\Images\nt50.wks\i386"
  1092. p = OscFindVariableW(ClientState, "MACHINETYPE");
  1093. if (!p) {
  1094. continue;
  1095. }
  1096. if (wcslen(Path) + (sizeof(L"\\")/sizeof(WCHAR)) + wcslen(p) > sizeof(Path)/sizeof(Path[0])) {
  1097. continue;
  1098. }
  1099. wcscat(Path, L"\\");
  1100. wcscat(Path, p);
  1101. //
  1102. // get a path to the templates folder and make sure we dont' have
  1103. // a winpe image. if we do then we're in trouble because we can't
  1104. // treat that as a normal image.
  1105. //
  1106. FoundWinPE = FALSE;
  1107. if (0 > _snwprintf(
  1108. TemplatesPath,
  1109. MAX_PATH,
  1110. L"%ws\\templates\\*.sif",
  1111. Path)) {
  1112. continue;
  1113. }
  1114. TemplatesPath[MAX_PATH-1] = L'\0'; // throw in terminating null just to be safe
  1115. dwTemplatesPathLen = wcslen(TemplatesPath);
  1116. p = wcsrchr(TemplatesPath,L'*');
  1117. BinlAssert( p != NULL );
  1118. dwTemplatesPathLen = (p - TemplatesPath)/sizeof(WCHAR);
  1119. hTemplate = FindFirstFile(TemplatesPath, (LPVOID) &TemplateData);
  1120. if (hTemplate != INVALID_HANDLE_VALUE) {
  1121. do {
  1122. if (wcscmp(TemplateData.cFileName, L".") &&
  1123. wcscmp(TemplateData.cFileName, L"..") &&
  1124. (TemplateData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
  1125. // make sure there is enough room.
  1126. if (dwTemplatesPathLen + wcslen(TemplateData.cFileName) + 1 > sizeof(TemplatesPath)/sizeof(WCHAR)) {
  1127. continue;
  1128. }
  1129. wcscpy(&TemplatesPath[dwTemplatesPathLen],TemplateData.cFileName);
  1130. if (OscSifIsWinPEW(TemplatesPath)) {
  1131. BinlPrintDbg(( DEBUG_OSC, "OS Directory %ws is really a WinPE image, skipping it.\n", Path ));
  1132. FoundWinPE = TRUE;
  1133. break;
  1134. }
  1135. }
  1136. } while (FindNextFile(hTemplate, (LPVOID) &TemplateData));
  1137. FindClose(hTemplate);
  1138. hTemplate = INVALID_HANDLE_VALUE;
  1139. }
  1140. if (FoundWinPE) {
  1141. continue;
  1142. }
  1143. ThisSkuType = OscGetSkuType( Path );
  1144. if (OscGetNtVersionInfo(&ThisVersion, Path, ClientState)) {
  1145. //
  1146. // if the sku we're looking for is ads and we've found srv,
  1147. // then lie and say it's really
  1148. // ads. This gets around a problem where txtsetup.sif didn't
  1149. // specify the SKU type correctly in 2195.
  1150. //
  1151. if (ThisSkuType == 1 && SkuType == 2) {
  1152. ThisSkuType = 2;
  1153. }
  1154. if ((ThisVersion >= KernelVersion) &&
  1155. (ThisSkuType == SkuType) &&
  1156. ((BestVersion == (ULONGLONG)0) || (ThisVersion < BestVersion))) {
  1157. if (SetupPathSize >= wcslen(Path)) {
  1158. wcscpy(SetupPath, Path);
  1159. BestVersion = ThisVersion;
  1160. }
  1161. }
  1162. }
  1163. }
  1164. } while (FindNextFile(hFind, (LPVOID) &FindData));
  1165. if (BestVersion != 0) {
  1166. ReturnValue = TRUE;
  1167. *ExactMatch = (BOOLEAN)(BestVersion == KernelVersion);
  1168. } else {
  1169. ReturnValue = FALSE;
  1170. }
  1171. Cleanup:
  1172. if (hFind != INVALID_HANDLE_VALUE) {
  1173. FindClose(hFind);
  1174. }
  1175. if (Impersonated) {
  1176. Error = RevertSecurityContext(&ClientState->ServerContextHandle);
  1177. if (Error != STATUS_SUCCESS) {
  1178. BinlPrintDbg(( DEBUG_OSC_ERROR, "RevertSecurityContext: 0x%08x\n", Error ));
  1179. return FALSE;
  1180. }
  1181. }
  1182. return ReturnValue;
  1183. }
  1184. BOOLEAN
  1185. OscGetNtVersionInfo(
  1186. PULONGLONG Version,
  1187. PWCHAR SearchDir,
  1188. PCLIENT_STATE ClientState
  1189. )
  1190. {
  1191. DWORD Error = ERROR_SUCCESS;
  1192. DWORD FileVersionInfoSize;
  1193. DWORD VersionHandle;
  1194. ULARGE_INTEGER TmpVersion;
  1195. PVOID VersionInfo;
  1196. VS_FIXEDFILEINFO * FixedFileInfo;
  1197. UINT FixedFileInfoLength;
  1198. WCHAR Path[MAX_PATH];
  1199. BOOLEAN fResult = FALSE;
  1200. TraceFunc("OscGetNtVersionInfo( )\n");
  1201. if (!SearchDir) {
  1202. goto e0;
  1203. }
  1204. //
  1205. // Resulting string should be something like:
  1206. // "D:\RemoteInstall\Setup\English\Images\nt50.wks\i386\ntoskrnl.exe"
  1207. //
  1208. if (0 > _snwprintf(
  1209. Path,
  1210. MAX_PATH,
  1211. L"%ws\\ntoskrnl.exe",
  1212. SearchDir)) {
  1213. goto e0; // path too long, skip it
  1214. }
  1215. Path[MAX_PATH-1] = L'\0'; // throw in terminating null just to be safe
  1216. BinlPrintDbg((DEBUG_OSC, "Checking version: %ws\n", Path));
  1217. FileVersionInfoSize = GetFileVersionInfoSize(Path, &VersionHandle);
  1218. if (FileVersionInfoSize == 0) {
  1219. goto e0;
  1220. }
  1221. VersionInfo = BinlAllocateMemory(FileVersionInfoSize);
  1222. if (VersionInfo == NULL) {
  1223. goto e0;
  1224. }
  1225. if (!GetFileVersionInfo(
  1226. Path,
  1227. VersionHandle,
  1228. FileVersionInfoSize,
  1229. VersionInfo)) {
  1230. goto e1;
  1231. }
  1232. if (!VerQueryValue(
  1233. VersionInfo,
  1234. L"\\",
  1235. &FixedFileInfo,
  1236. &FixedFileInfoLength)) {
  1237. goto e1;
  1238. }
  1239. TmpVersion.HighPart = FixedFileInfo->dwFileVersionMS;
  1240. TmpVersion.LowPart = FixedFileInfo->dwFileVersionLS;
  1241. //
  1242. // We need to whack the low 16 bits of the .LowPart so that
  1243. // we ignore the service pack value. For example, WindowsXP has a
  1244. // version number of 5.1.2600.0. XP-ServicePack1 has a version
  1245. // number of 5.1.2600.1038. We'd like those to match, so just whack
  1246. // the servicepack number portion.
  1247. //
  1248. TmpVersion.LowPart &= 0xFFFF0000;
  1249. *Version = TmpVersion.QuadPart;
  1250. fResult = TRUE;
  1251. e1:
  1252. BinlFreeMemory(VersionInfo);
  1253. e0:
  1254. return fResult;
  1255. }
  1256. //
  1257. // Send a message on our socket. If the message is too long, then it
  1258. // splits it into fragments of MAXIMUM_FRAGMENT_LENGTH bytes.
  1259. //
  1260. #define MAXIMUM_FRAGMENT_LENGTH 1400
  1261. DWORD
  1262. SendUdpMessage(
  1263. LPBINL_REQUEST_CONTEXT RequestContext,
  1264. PCLIENT_STATE clientState,
  1265. BOOL bFragment,
  1266. BOOL bResend
  1267. )
  1268. {
  1269. DWORD error;
  1270. FRAGMENT_PACKET FragmentHeader;
  1271. USHORT FragmentNumber;
  1272. USHORT FragmentTotal;
  1273. ULONG MessageLengthWithoutHeader;
  1274. ULONG BytesSent;
  1275. ULONG BytesThisSend;
  1276. UCHAR TempMessage[1500];
  1277. FRAGMENT_PACKET UNALIGNED * SendFragmentPacket =
  1278. (FRAGMENT_PACKET UNALIGNED *)TempMessage;
  1279. TraceFunc("SendUdpMessage( )\n");
  1280. //
  1281. // The message starts with a signature, a length, a sequence number (all
  1282. // four bytes), then two ushorts for fragment count and total. If
  1283. // we have to split it we preserve this header in each packet, with
  1284. // fragment count modified for each one.
  1285. //
  1286. MessageLengthWithoutHeader =
  1287. clientState->LastResponseLength - FRAGMENT_PACKET_DATA_OFFSET;
  1288. if (!bFragment ||
  1289. ((FragmentTotal = (USHORT)((MessageLengthWithoutHeader + MAXIMUM_FRAGMENT_LENGTH - 1) / MAXIMUM_FRAGMENT_LENGTH)) <= 1))
  1290. {
  1291. #ifdef _TRACE_FUNC_
  1292. SendFragmentPacket = (FRAGMENT_PACKET UNALIGNED *)clientState->LastResponse;
  1293. TraceFunc("Sending packet with ");
  1294. BinlPrintDbg(( DEBUG_OSC, " SequenceNumber = %u )\n", SendFragmentPacket->SequenceNumber ));
  1295. #endif
  1296. error = sendto(
  1297. RequestContext->ActiveEndpoint->Socket,
  1298. clientState->LastResponse,
  1299. clientState->LastResponseLength,
  1300. 0,
  1301. &RequestContext->SourceName,
  1302. RequestContext->SourceNameLength
  1303. );
  1304. } else {
  1305. FragmentHeader = *((FRAGMENT_PACKET UNALIGNED *)clientState->LastResponse); // struct copy -- save the header
  1306. BytesSent = 0;
  1307. for (FragmentNumber = 0; FragmentNumber < FragmentTotal; FragmentNumber++) {
  1308. if (FragmentNumber == (FragmentTotal - 1)) {
  1309. BytesThisSend = MessageLengthWithoutHeader - BytesSent;
  1310. } else {
  1311. BytesThisSend = MAXIMUM_FRAGMENT_LENGTH;
  1312. }
  1313. memcpy(
  1314. TempMessage + FRAGMENT_PACKET_DATA_OFFSET,
  1315. clientState->LastResponse + FRAGMENT_PACKET_DATA_OFFSET + (FragmentNumber * MAXIMUM_FRAGMENT_LENGTH),
  1316. BytesThisSend);
  1317. memcpy(SendFragmentPacket, &FragmentHeader, FRAGMENT_PACKET_DATA_OFFSET);
  1318. SendFragmentPacket->Length = BytesThisSend + FRAGMENT_PACKET_EMPTY_LENGTH;
  1319. SendFragmentPacket->FragmentNumber = FragmentNumber + 1;
  1320. SendFragmentPacket->FragmentTotal = FragmentTotal;
  1321. #ifdef TEST_FAILURE
  1322. if (FailFirstFragment) {
  1323. FailFirstFragment = FALSE;
  1324. BinlPrintDbg((DEBUG_OSC, "NOT sending first fragment, %ld bytes\n", BytesThisSend + FRAGMENT_PACKET_DATA_OFFSET));
  1325. error = ERROR_SUCCESS;
  1326. } else
  1327. #endif
  1328. //
  1329. // On resends, wait between fragments in case the resend is
  1330. // because the card can't handle quick bursts of packets.
  1331. //
  1332. if (bResend && (FragmentNumber != 0)) {
  1333. Sleep(10); // wait 10 milliseconds
  1334. }
  1335. error = sendto(
  1336. RequestContext->ActiveEndpoint->Socket,
  1337. TempMessage,
  1338. BytesThisSend + FRAGMENT_PACKET_DATA_OFFSET,
  1339. 0,
  1340. &RequestContext->SourceName,
  1341. RequestContext->SourceNameLength
  1342. );
  1343. if (error == SOCKET_ERROR) {
  1344. break;
  1345. }
  1346. BytesSent += BytesThisSend;
  1347. }
  1348. }
  1349. if ( error == SOCKET_ERROR ) {
  1350. error = WSAGetLastError();
  1351. BinlPrintDbg(( DEBUG_OSC_ERROR, "Sendto() failed, error = %ld\n", error ));
  1352. } else {
  1353. error = ERROR_SUCCESS;
  1354. }
  1355. return( error );
  1356. }
  1357. //
  1358. // Verifies the packets signature is authentic
  1359. //
  1360. DWORD
  1361. OscVerifySignature(
  1362. PCLIENT_STATE clientState,
  1363. SIGNED_PACKET UNALIGNED * signedMessage
  1364. )
  1365. {
  1366. SECURITY_STATUS SecStatus;
  1367. SecBuffer SigBuffers[2];
  1368. ULONG MessageLength, SignLength;
  1369. SecBufferDesc SignMessage;
  1370. TraceFunc("OscVerifySignature( )\n");
  1371. MessageLength = signedMessage->Length;
  1372. SignLength = signedMessage->SignLength;
  1373. //
  1374. // Verify the signature
  1375. //
  1376. SigBuffers[0].pvBuffer = signedMessage->Data;
  1377. SigBuffers[0].cbBuffer = MessageLength - SIGNED_PACKET_EMPTY_LENGTH;
  1378. SigBuffers[0].BufferType = SECBUFFER_DATA;
  1379. SigBuffers[1].pvBuffer = signedMessage->Sign;
  1380. SigBuffers[1].cbBuffer = SignLength;
  1381. SigBuffers[1].BufferType = SECBUFFER_TOKEN;
  1382. SignMessage.pBuffers = SigBuffers;
  1383. SignMessage.cBuffers = 2;
  1384. SignMessage.ulVersion = 0;
  1385. #ifndef ONLY_SIGN_MESSAGES
  1386. SecStatus = UnsealMessage(
  1387. &clientState->ServerContextHandle,
  1388. &SignMessage,
  1389. 0,
  1390. 0 );
  1391. #else
  1392. SecStatus = VerifySignature(
  1393. &clientState->ServerContextHandle,
  1394. &SignMessage,
  1395. 0,
  1396. 0 );
  1397. #endif
  1398. if (SecStatus != STATUS_SUCCESS)
  1399. {
  1400. DWORD Error;
  1401. SIGNED_PACKET UNALIGNED * SendSignedMessage;
  1402. BinlPrintDbg(( DEBUG_OSC_ERROR, "Sending ERR packet from Verify/Unseal!!\n"));
  1403. clientState->LastResponseLength = SIGNED_PACKET_ERROR_LENGTH;
  1404. Error = OscVerifyLastResponseSize(clientState);
  1405. if (Error != ERROR_SUCCESS) {
  1406. return SecStatus; // we can't send anything back
  1407. }
  1408. SendSignedMessage = (SIGNED_PACKET UNALIGNED *)(clientState->LastResponse);
  1409. memcpy(SendSignedMessage->Signature, ErrorSignedSignature, 4);
  1410. SendSignedMessage->Length = 4;
  1411. SendSignedMessage->SequenceNumber = clientState->LastSequenceNumber;
  1412. }
  1413. return SecStatus;
  1414. }
  1415. //
  1416. //
  1417. //
  1418. DWORD
  1419. OscSendSignedMessage(
  1420. LPBINL_REQUEST_CONTEXT RequestContext,
  1421. PCLIENT_STATE clientState,
  1422. PCHAR Message,
  1423. ULONG MessageLength
  1424. )
  1425. {
  1426. DWORD Error = ERROR_SUCCESS;
  1427. SIGNED_PACKET UNALIGNED * SendSignedMessage;
  1428. SecBuffer SigBuffers[2];
  1429. SecBufferDesc SignMessage;
  1430. SECURITY_STATUS SecStatus;
  1431. #ifdef _TRACE_FUNC_
  1432. TraceFunc("OscSendSignedMessage( ");
  1433. BinlPrintDbg(( DEBUG_OSC, "SequenceNumber = %u )\n", clientState->LastSequenceNumber ));
  1434. #endif
  1435. //
  1436. // Make sure we have space for the message
  1437. //
  1438. clientState->LastResponseLength = MessageLength + SIGNED_PACKET_DATA_OFFSET;
  1439. Error = OscVerifyLastResponseSize(clientState);
  1440. if (Error != ERROR_SUCCESS)
  1441. return Error;
  1442. //
  1443. // copy the message
  1444. //
  1445. SendSignedMessage = (SIGNED_PACKET UNALIGNED *) clientState->LastResponse;
  1446. memcpy(SendSignedMessage->Data, Message, MessageLength);
  1447. //
  1448. // sign the message
  1449. //
  1450. memcpy(SendSignedMessage->Signature, ResponseSignedSignature, 4);
  1451. SendSignedMessage->Length = MessageLength + SIGNED_PACKET_EMPTY_LENGTH;
  1452. SendSignedMessage->SequenceNumber = clientState->LastSequenceNumber;
  1453. SendSignedMessage->FragmentNumber = 1; // fragment count
  1454. SendSignedMessage->FragmentTotal = 1; // fragment total
  1455. SendSignedMessage->SignLength = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  1456. #if 0
  1457. //
  1458. // Send out an unsealed copy to a different port.
  1459. //
  1460. {
  1461. USHORT TmpPort;
  1462. PCHAR TmpSignature[4];
  1463. TmpPort = ((struct sockaddr_in *)&RequestContext->SourceName)->sin_port;
  1464. memcpy(TmpSignature, SendSignedMessage->Signature, 4);
  1465. ((struct sockaddr_in *)&RequestContext->SourceName)->sin_port = 0xabcd;
  1466. memcpy(SendSignedMessage->Signature, "FAKE", 4);
  1467. Error = SendUdpMessage(RequestContext, clientState, TRUE, FALSE);
  1468. ((struct sockaddr_in *)&RequestContext->SourceName)->sin_port = TmpPort;
  1469. memcpy(SendSignedMessage->Signature, TmpSignature, 4);
  1470. }
  1471. #endif
  1472. SigBuffers[0].pvBuffer = SendSignedMessage->Data;
  1473. SigBuffers[0].cbBuffer = MessageLength;
  1474. SigBuffers[0].BufferType = SECBUFFER_DATA;
  1475. SigBuffers[1].pvBuffer = SendSignedMessage->Sign;
  1476. SigBuffers[1].cbBuffer = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  1477. SigBuffers[1].BufferType = SECBUFFER_TOKEN;
  1478. SignMessage.pBuffers = SigBuffers;
  1479. SignMessage.cBuffers = 2;
  1480. SignMessage.ulVersion = 0;
  1481. #ifndef ONLY_SIGN_MESSAGES
  1482. SecStatus = SealMessage(
  1483. &clientState->ServerContextHandle,
  1484. 0,
  1485. &SignMessage,
  1486. 0 );
  1487. #else
  1488. SecStatus = MakeSignature(
  1489. &clientState->ServerContextHandle,
  1490. 0,
  1491. &SignMessage,
  1492. 0 );
  1493. #endif
  1494. //
  1495. // Make sure the signature worked. If not, send error packet.
  1496. //
  1497. if (SecStatus != STATUS_SUCCESS)
  1498. {
  1499. BinlPrintDbg(( DEBUG_OSC_ERROR, "Sending ERR packet from Make/Seal!!\n"));
  1500. clientState->LastResponseLength = SIGNED_PACKET_ERROR_LENGTH;
  1501. Error = OscVerifyLastResponseSize(clientState);
  1502. if (Error != ERROR_SUCCESS)
  1503. return Error;
  1504. memcpy(SendSignedMessage->Signature, ErrorSignedSignature, 4);
  1505. SendSignedMessage->Length = 4;
  1506. }
  1507. else
  1508. {
  1509. BinlPrintDbg(( DEBUG_OSC, "Sending RSPS, %d bytes\n", clientState->LastResponseLength));
  1510. }
  1511. #ifdef TEST_FAILURE
  1512. if (FailFirstResponse)
  1513. {
  1514. BinlPrintDbg(( DEBUG_OSC, "NOT Sending RSP, %d bytes\n", clientState->LastResponseLength));
  1515. FailFirstResponse = FALSE;
  1516. Error = ERROR_SUCCESS;
  1517. } else
  1518. #endif
  1519. Error = SendUdpMessage(RequestContext, clientState, TRUE, FALSE);
  1520. if (Error != ERROR_SUCCESS)
  1521. {
  1522. BinlPrintDbg(( DEBUG_OSC_ERROR, "Could not send RSP message %d\n", Error ));
  1523. }
  1524. return Error;
  1525. }
  1526. //
  1527. //
  1528. //
  1529. DWORD
  1530. OscSendUnsignedMessage(
  1531. LPBINL_REQUEST_CONTEXT RequestContext,
  1532. PCLIENT_STATE clientState,
  1533. PCHAR Message,
  1534. ULONG MessageLength
  1535. )
  1536. {
  1537. DWORD Error = ERROR_SUCCESS;
  1538. SIGNED_PACKET UNALIGNED * SendSignedMessage;
  1539. SecBuffer SigBuffers[2];
  1540. SecBufferDesc SignMessage;
  1541. SECURITY_STATUS SecStatus;
  1542. #ifdef _TRACE_FUNC_
  1543. TraceFunc("OscSendUnsignedMessage( ");
  1544. BinlPrintDbg(( DEBUG_OSC, "SequenceNumber = %u )\n", clientState->LastSequenceNumber ));
  1545. #endif
  1546. //
  1547. // Make sure we have space for the message
  1548. //
  1549. clientState->LastResponseLength = MessageLength + SIGNED_PACKET_DATA_OFFSET;
  1550. Error = OscVerifyLastResponseSize(clientState);
  1551. if (Error != ERROR_SUCCESS) {
  1552. return Error;
  1553. }
  1554. //
  1555. // copy the message
  1556. //
  1557. SendSignedMessage = (SIGNED_PACKET UNALIGNED *) clientState->LastResponse;
  1558. memcpy(SendSignedMessage->Data, Message, MessageLength);
  1559. //
  1560. // sign the message
  1561. //
  1562. memcpy(SendSignedMessage->Signature, ResponseUnsignedSignature, 4);
  1563. SendSignedMessage->Length = MessageLength + SIGNED_PACKET_EMPTY_LENGTH;
  1564. SendSignedMessage->SequenceNumber = clientState->LastSequenceNumber;
  1565. SendSignedMessage->FragmentNumber = 1; // fragment count
  1566. SendSignedMessage->FragmentTotal = 1; // fragment total
  1567. SendSignedMessage->SignLength = 0;
  1568. Error = SendUdpMessage(RequestContext, clientState, TRUE, FALSE);
  1569. if (Error != ERROR_SUCCESS)
  1570. {
  1571. BinlPrintDbg(( DEBUG_OSC_ERROR, "Could not send RSU message %d\n", Error ));
  1572. }
  1573. return Error;
  1574. }
  1575. DWORD
  1576. OscSendSetupMessage(
  1577. LPBINL_REQUEST_CONTEXT RequestContext,
  1578. PCLIENT_STATE clientState,
  1579. ULONG RequestType,
  1580. PCHAR Message,
  1581. ULONG MessageLength
  1582. )
  1583. {
  1584. DWORD Error = ERROR_SUCCESS;
  1585. SPUDP_PACKET UNALIGNED * SendMessage;
  1586. #ifdef _TRACE_FUNC_
  1587. TraceFunc("OscSendSetupMessage( ");
  1588. BinlPrintDbg(( DEBUG_OSC, "SequenceNumber = %u )\n", clientState->LastSequenceNumber ));
  1589. #endif
  1590. //
  1591. // Make sure we have space for the message
  1592. //
  1593. clientState->LastResponseLength = MessageLength + SPUDP_PACKET_DATA_OFFSET;
  1594. Error = OscVerifyLastResponseSize(clientState);
  1595. if (Error != ERROR_SUCCESS) {
  1596. return Error;
  1597. }
  1598. //
  1599. // copy the message
  1600. //
  1601. SendMessage = (SPUDP_PACKET UNALIGNED *) clientState->LastResponse;
  1602. memcpy(SendMessage->Data, Message, MessageLength);
  1603. //
  1604. // fill in the message stuff
  1605. //
  1606. memcpy(SendMessage->Signature, SetupResponseSignature, 4);
  1607. SendMessage->Length = MessageLength + SPUDP_PACKET_EMPTY_LENGTH;
  1608. SendMessage->Status = STATUS_SUCCESS;
  1609. SendMessage->SequenceNumber = clientState->LastSequenceNumber;
  1610. SendMessage->RequestType = RequestType;
  1611. SendMessage->FragmentNumber = 1; // fragment count
  1612. SendMessage->FragmentTotal = 1; // fragment total
  1613. Error = SendUdpMessage(RequestContext, clientState, TRUE, FALSE);
  1614. if (Error != ERROR_SUCCESS) {
  1615. BinlPrintDbg(( DEBUG_OSC_ERROR, "Could not send SPR message %d\n", Error ));
  1616. }
  1617. return Error;
  1618. }
  1619. #ifdef SET_ACLS_ON_CLIENT_DIRS
  1620. //
  1621. //
  1622. //
  1623. DWORD
  1624. OscSetClientDirectoryPermissions(
  1625. PCLIENT_STATE clientState )
  1626. {
  1627. DWORD Err = ERROR_SUCCESS;
  1628. WCHAR DirPath[ MAX_PATH ];
  1629. WCHAR Domain[ 80 ];
  1630. DWORD dwDomainSize = 80;
  1631. PSECURITY_DESCRIPTOR pSD;
  1632. PACL pDACL;
  1633. PSID pSID;
  1634. BOOL bOwnerDefault;
  1635. DWORD dwLengthRequired;
  1636. SID_NAME_USE snu;
  1637. PWCHAR pMachineName = OscFindVariableW( clientState, "MACHINENAME" );
  1638. if ( !pMachineName || _snwprintf (
  1639. DirPath,
  1640. sizeof(DirPath) / sizeof(DirPath[0]),
  1641. L"%ws\\REMINST\\Clients\\%ws",
  1642. OscFindVariableW( clientState, "SERVERNAME" ),
  1643. pMachineName ) < 0 ) {
  1644. Err = ERROR_BAD_PATHNAME;
  1645. goto Cleanup;
  1646. }
  1647. DirPath[MAX_PATH-1] = L'\0'; // throw in terminating null just to be safe
  1648. //
  1649. // Figure out how big the machine account's SID is
  1650. //
  1651. LookupAccountName( NULL,
  1652. pMachineName,
  1653. pSID,
  1654. &dwLengthRequired,
  1655. Domain,
  1656. &dwDomainSize,
  1657. &snu );
  1658. //
  1659. // make space
  1660. //
  1661. pSID = (PSID) BinlAllocateMemory( dwLengthRequired );
  1662. if ( pSID == NULL ) {
  1663. goto OutOfMemory;
  1664. }
  1665. //
  1666. // get the machine account's SID
  1667. //
  1668. if (!LookupAccountName( NULL, pMachineName, pSID, &dwLengthRequired, Domain, &dwDomainSize, &snu ) ) {
  1669. goto Error;
  1670. }
  1671. dwLengthRequired += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid ( pSID );
  1672. pDACL = (PACL) BinlAllocateMemory( dwLengthRequired );
  1673. if ( pDACL == NULL ) {
  1674. goto OutOfMemory;
  1675. }
  1676. pSD = ( PSECURITY_DESCRIPTOR) BinlAllocateMemory( SECURITY_DESCRIPTOR_MIN_LENGTH + dwLengthRequired );
  1677. if ( pSD == NULL ) {
  1678. goto OutOfMemory;
  1679. }
  1680. if ( !InitializeSecurityDescriptor ( pSD, SECURITY_DESCRIPTOR_REVISION) ) {
  1681. goto Error;
  1682. }
  1683. if ( !InitializeAcl( pDACL, dwLengthRequired, ACL_REVISION ) ) {
  1684. goto Error;
  1685. }
  1686. if ( !AddAccessAllowedAce( pDACL, ACL_REVISION, FILE_ALL_ACCESS, pSID ) ) {
  1687. goto Error;
  1688. }
  1689. if ( !IsValidAcl( pDACL ) ) {
  1690. goto Error;
  1691. }
  1692. if ( !SetSecurityDescriptorDacl( pSD, TRUE, pDACL, FALSE ) ) {
  1693. goto Error;
  1694. }
  1695. if ( !SetSecurityDescriptorOwner( pSD, pSID, FALSE ) ) {
  1696. goto Error;
  1697. }
  1698. if ( ! IsValidSecurityDescriptor ( pSD ) ) {
  1699. goto Error;
  1700. }
  1701. if ( !SetFileSecurity( DirPath,
  1702. OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  1703. pSD ) ) {
  1704. goto Error;
  1705. }
  1706. goto Cleanup;
  1707. OutOfMemory:
  1708. Err = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  1709. goto Cleanup;
  1710. Error:
  1711. Err = GetLastError( );
  1712. Cleanup:
  1713. if ( pSID )
  1714. BinlFreeMemory( pSID );
  1715. if ( pSD )
  1716. BinlFreeMemory( pSD );
  1717. return Err;
  1718. }
  1719. #endif // SET_ACLS_ON_CLIENT_DIRS
  1720. DWORD
  1721. OscConstructSecret(
  1722. PCLIENT_STATE clientState,
  1723. PWCHAR UnicodePassword,
  1724. ULONG UnicodePasswordLength,
  1725. PCREATE_DATA CreateData
  1726. )
  1727. {
  1728. DWORD dwErr = ERROR_SUCCESS;
  1729. UINT i;
  1730. WCHAR DomainBuffer[64];
  1731. DWORD SidLength, DomainLength;
  1732. SID_NAME_USE NameUse;
  1733. BOOL b;
  1734. PCHAR pBootFile;
  1735. PCHAR pSifFile;
  1736. TraceFunc( "OscConstructSecret( )\n" );
  1737. RtlZeroMemory(CreateData, sizeof(CREATE_DATA));
  1738. //
  1739. // Copy the machine data into the response packet
  1740. //
  1741. // The following fields aren't necessary unless we're supporting remote boot.
  1742. // UCHAR Sid[28];
  1743. // UCHAR Domain[32];
  1744. // UCHAR Name[32];
  1745. // UCHAR Password[32];
  1746. // ULONG UnicodePasswordLength; // in bytes
  1747. // WCHAR UnicodePassword[32];
  1748. // UCHAR Installation[32];
  1749. // UCHAR MachineType[6]; // 'i386\0' or 'Alpha\0'
  1750. //
  1751. pBootFile = OscFindVariableA( clientState, "BOOTFILE" );
  1752. if ( pBootFile[0] == L'\0' ) {
  1753. OscAddVariableA( clientState, "SUBERROR", "BOOTFILE" );
  1754. return ERROR_BINL_MISSING_VARIABLE;
  1755. }
  1756. pSifFile = OscFindVariableA( clientState, "SIFFILE" );
  1757. if ( pSifFile[0] == L'\0' ) {
  1758. OscAddVariableA( clientState, "SUBERROR", "SIFFILE" );
  1759. return ERROR_BINL_MISSING_VARIABLE;
  1760. }
  1761. memcpy( CreateData->Id, "ACCT", 4);
  1762. CreateData->VersionNumber = OSC_CREATE_DATA_VERSION;
  1763. strncpy( CreateData->NextBootfile, pBootFile, 128 );
  1764. CreateData->NextBootfile[128-1]='\0';
  1765. strncpy( CreateData->SifFile, pSifFile, 128 );
  1766. CreateData->SifFile[128-1]='\0';
  1767. BinlAssertMsg( CreateData->NextBootfile[0], "No boot file" );
  1768. return dwErr;
  1769. }
  1770. DWORD
  1771. GetOurServerInfo (
  1772. VOID
  1773. )
  1774. //
  1775. // This routine gets several global names that we need to handle client
  1776. // requests. We store them in globals because they change very infrequently
  1777. // and they're relatively expense to retrieve.
  1778. //
  1779. {
  1780. PWCHAR fqdn = NULL;
  1781. DWORD uSize;
  1782. DWORD dnsError = ERROR_SUCCESS;
  1783. DWORD fqdnError = ERROR_SUCCESS;
  1784. DWORD netbiosServerError = ERROR_SUCCESS;
  1785. DWORD netbiosDomainError = ERROR_SUCCESS;
  1786. PWCHAR ourDNSName = NULL;
  1787. PWCHAR tmp;
  1788. PWCHAR pDomain;
  1789. WCHAR ServerName[32] = { 0 };
  1790. DWORD ServerSize = sizeof(ServerName) / sizeof(WCHAR);
  1791. ULONG Error;
  1792. // first grab the netbios name of our server
  1793. if ( !GetComputerNameEx( ComputerNameNetBIOS, ServerName, &ServerSize ) ) {
  1794. netbiosServerError = GetLastError();
  1795. BinlPrintDbg(( DEBUG_OSC_ERROR, "!! Error 0x%08x - GetComputerNameEx failed.\n", netbiosServerError ));
  1796. } else {
  1797. tmp = BinlStrDup( ServerName );
  1798. if (tmp == NULL) {
  1799. netbiosServerError = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  1800. } else {
  1801. EnterCriticalSection( &gcsParameters );
  1802. if (BinlGlobalOurServerName) {
  1803. BinlFreeMemory( BinlGlobalOurServerName );
  1804. }
  1805. BinlGlobalOurServerName = tmp;
  1806. LeaveCriticalSection( &gcsParameters );
  1807. }
  1808. }
  1809. // Next grab the fully qualified domain name of our server
  1810. uSize = 0;
  1811. if ( !GetComputerObjectName( NameFullyQualifiedDN, NULL, &uSize ) ) {
  1812. fqdnError = GetLastError( );
  1813. if ( fqdnError != ERROR_MORE_DATA ) {
  1814. BinlPrint((DEBUG_OSC_ERROR, "!! Error 0x%08x - GetComputerObjectName failed.\n", fqdnError ));
  1815. goto GetDNS;
  1816. }
  1817. fqdnError = ERROR_SUCCESS;
  1818. }
  1819. fqdn = BinlAllocateMemory( uSize * sizeof(WCHAR) );
  1820. if ( fqdn ) {
  1821. if ( !GetComputerObjectName( NameFullyQualifiedDN, fqdn, &uSize ) ) {
  1822. fqdnError = GetLastError( );
  1823. BinlPrint((DEBUG_OSC_ERROR, "!! Error 0x%08x - GetComputerObjectName failed.\n", fqdnError ));
  1824. } else {
  1825. EnterCriticalSection( &gcsParameters );
  1826. tmp = BinlGlobalOurFQDNName;
  1827. BinlGlobalOurFQDNName = fqdn;
  1828. fqdn = tmp; // we'll free it below
  1829. // next setup the netbios domain name
  1830. pDomain = StrStrIW( BinlGlobalOurFQDNName, L"DC=" );
  1831. if ( pDomain ) {
  1832. PDS_NAME_RESULTW pResults;
  1833. BinlPrintDbg(( DEBUG_OSC, "Converting %ws to a NetBIOS domain name...\n", pDomain ));
  1834. netbiosDomainError = DsCrackNames( INVALID_HANDLE_VALUE,
  1835. DS_NAME_FLAG_SYNTACTICAL_ONLY,
  1836. DS_FQDN_1779_NAME,
  1837. DS_CANONICAL_NAME,
  1838. 1,
  1839. &pDomain,
  1840. &pResults );
  1841. if (netbiosDomainError != ERROR_SUCCESS) {
  1842. BinlPrint(( DEBUG_ERRORS, "GetOurServerInfo error in DsCrackNames %u\n", netbiosDomainError ));
  1843. }
  1844. if ( netbiosDomainError == ERROR_SUCCESS ) {
  1845. if ( pResults->cItems == 1
  1846. && pResults->rItems[0].status == DS_NAME_NO_ERROR
  1847. && pResults->rItems[0].pName ) { // paranoid
  1848. pResults->rItems[0].pName[wcslen(pResults->rItems[0].pName)-1] = L'\0';
  1849. tmp = BinlStrDup( pResults->rItems[0].pName );
  1850. if (tmp == NULL) {
  1851. netbiosDomainError = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  1852. } else {
  1853. if (BinlGlobalOurDomainName) {
  1854. BinlFreeMemory( BinlGlobalOurDomainName );
  1855. }
  1856. BinlGlobalOurDomainName = tmp;
  1857. }
  1858. }
  1859. DsFreeNameResult( pResults );
  1860. }
  1861. }
  1862. LeaveCriticalSection( &gcsParameters );
  1863. }
  1864. } else {
  1865. fqdnError = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  1866. }
  1867. GetDNS:
  1868. // Retrieve the FQDNS name of the server
  1869. uSize = 0;
  1870. if ( !GetComputerNameEx( ComputerNameDnsFullyQualified, NULL, &uSize ) ) {
  1871. dnsError = GetLastError( );
  1872. if ( dnsError != ERROR_MORE_DATA ) {
  1873. BinlPrint((DEBUG_OSC_ERROR, "!! Error 0x%08x - GetComputerNameEx failed.\n", dnsError ));
  1874. goto returnError;
  1875. }
  1876. dnsError = ERROR_SUCCESS;
  1877. }
  1878. ourDNSName = (PWCHAR) BinlAllocateMemory( uSize * sizeof(WCHAR) );
  1879. if ( ourDNSName ) {
  1880. if ( !GetComputerNameEx( ComputerNameDnsFullyQualified, ourDNSName, &uSize ) ) {
  1881. dnsError = GetLastError( );
  1882. BinlPrint((DEBUG_OSC_ERROR, "!! Error 0x%08x - GetComputerNameEx failed.\n", dnsError ));
  1883. } else {
  1884. EnterCriticalSection( &gcsParameters );
  1885. tmp = BinlGlobalOurDnsName;
  1886. BinlGlobalOurDnsName = ourDNSName;
  1887. LeaveCriticalSection( &gcsParameters );
  1888. ourDNSName = tmp; // we'll free it below
  1889. }
  1890. } else {
  1891. dnsError = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  1892. }
  1893. returnError:
  1894. if (ourDNSName) {
  1895. BinlFreeMemory( ourDNSName );
  1896. }
  1897. if (fqdn) {
  1898. BinlFreeMemory( fqdn );
  1899. }
  1900. if (fqdnError != ERROR_SUCCESS) {
  1901. Error = fqdnError;
  1902. } else if (dnsError != ERROR_SUCCESS) {
  1903. Error = dnsError;
  1904. } else if (netbiosServerError != ERROR_SUCCESS) {
  1905. Error = netbiosServerError;
  1906. } else {
  1907. Error = netbiosDomainError;
  1908. }
  1909. return Error;
  1910. }
  1911. DWORD
  1912. GetDomainNetBIOSName(
  1913. IN PCWSTR DomainNameInAnyFormat,
  1914. OUT PWSTR *NetBIOSName
  1915. )
  1916. /*++
  1917. Routine Description:
  1918. Retrieves the netbios name for a domain given an input name. The input
  1919. name may be in DNS form or netbios form, it doesn't really matter.
  1920. Arguments:
  1921. DomainNameInAnyFormat - string representing the name of the domain to query
  1922. NetBIOSName - receives string that represents the domain netbios name.
  1923. The string must be freed via BinlFreeMemory.
  1924. Return Value:
  1925. win32 error code indicating outcome.
  1926. --*/
  1927. {
  1928. PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL;
  1929. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC DomainInfo = NULL;
  1930. DWORD Error;
  1931. Error = DsGetDcName(
  1932. NULL,
  1933. DomainNameInAnyFormat,
  1934. NULL,
  1935. NULL,
  1936. DS_RETURN_DNS_NAME,
  1937. &DomainControllerInfo );
  1938. if (Error != ERROR_SUCCESS) {
  1939. BinlPrintDbg((
  1940. DEBUG_ERRORS,
  1941. "DsGetDcName (%ws) failed, ec = %d.\r\n",
  1942. DomainNameInAnyFormat,
  1943. Error ));
  1944. goto exit;
  1945. }
  1946. Error = DsRoleGetPrimaryDomainInformation(
  1947. DomainControllerInfo->DomainControllerName,
  1948. DsRolePrimaryDomainInfoBasic,
  1949. (PBYTE *) &DomainInfo);
  1950. if (Error != ERROR_SUCCESS) {
  1951. BinlPrintDbg((
  1952. DEBUG_ERRORS,
  1953. "DsRoleGetPrimaryDomainInformation (%ws) failed, ec = %d.\r\n",
  1954. DomainControllerInfo->DomainControllerName,
  1955. Error ));
  1956. goto exit;
  1957. }
  1958. *NetBIOSName = BinlStrDup( DomainInfo->DomainNameFlat );
  1959. if (!*NetBIOSName) {
  1960. BinlPrintDbg((
  1961. DEBUG_ERRORS,
  1962. "GetDomainNetBIOSName: failed to allocate memory (%d bytes) .\r\n",
  1963. (wcslen(DomainInfo->DomainNameFlat)+1) * sizeof(WCHAR) ));
  1964. Error = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  1965. }
  1966. exit:
  1967. if (DomainInfo) {
  1968. DsRoleFreeMemory( DomainInfo );
  1969. }
  1970. if (DomainControllerInfo) {
  1971. NetApiBufferFree( DomainControllerInfo );
  1972. }
  1973. return(Error);
  1974. }