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.

1245 lines
34 KiB

  1. /*++
  2. Copyright (c) 1993, 1994 Microsoft Corporation
  3. Module Name:
  4. credentl.c
  5. Abstract:
  6. This module contains credential management routines supported by
  7. NetWare Workstation service.
  8. Author:
  9. Rita Wong (ritaw) 15-Feb-1993
  10. Revision History:
  11. 13-Apr-1994 Added change password code written by ColinW, AndyHe,
  12. TerenceS, and RitaW.
  13. --*/
  14. #include <nw.h>
  15. #include <nwreg.h>
  16. #include <nwauth.h>
  17. #include <nwxchg.h>
  18. #include <nwapi.h>
  19. #include <ntlsa.h>
  20. //-------------------------------------------------------------------//
  21. // //
  22. // Global variables //
  23. // //
  24. //-------------------------------------------------------------------//
  25. //
  26. // Variables to coordinate reading of user logon credential from the
  27. // registry if the user logged on before the workstation is started.
  28. //
  29. STATIC BOOL NwLogonNotifiedRdr;
  30. STATIC
  31. DWORD
  32. NwpRegisterLogonProcess(
  33. OUT PHANDLE LsaHandle,
  34. OUT PULONG AuthPackageId
  35. );
  36. STATIC
  37. VOID
  38. NwpGetServiceCredentials(
  39. IN HANDLE LsaHandle,
  40. IN ULONG AuthPackageId
  41. );
  42. STATIC
  43. DWORD
  44. NwpGetCredentialInLsa(
  45. IN HANDLE LsaHandle,
  46. IN ULONG AuthPackageId,
  47. IN PLUID LogonId,
  48. OUT LPWSTR *UserName,
  49. OUT LPWSTR *Password
  50. );
  51. STATIC
  52. VOID
  53. NwpGetInteractiveCredentials(
  54. IN HANDLE LsaHandle,
  55. IN ULONG AuthPackageId
  56. );
  57. DWORD
  58. NwrLogonUser(
  59. IN LPWSTR Reserved OPTIONAL,
  60. IN PLUID LogonId,
  61. IN LPWSTR UserName,
  62. IN LPWSTR Password OPTIONAL,
  63. IN LPWSTR PreferredServerName OPTIONAL,
  64. IN LPWSTR NdsPreferredServerName OPTIONAL,
  65. OUT LPWSTR LogonCommand OPTIONAL,
  66. IN DWORD LogonCommandLength,
  67. IN DWORD PrintOption
  68. )
  69. /*++
  70. Routine Description:
  71. This function logs on the user to NetWare network. It passes the
  72. user logon credential to the redirector to be used as the default
  73. credential when attaching to any server.
  74. Arguments:
  75. Reserved - Must be NULL.
  76. UserName - Specifies the name of the user who logged on.
  77. Password - Specifies the password of the user who logged on.
  78. PreferredServerName - Specifies the user's preferred server.
  79. LogonCommand - Receives the string which is the command to execute
  80. on the command prompt for the user if logon is successful.
  81. Return Value:
  82. NO_ERROR or error from redirector.
  83. --*/
  84. {
  85. DWORD status;
  86. UNREFERENCED_PARAMETER(Reserved);
  87. EnterCriticalSection(&NwLoggedOnCritSec);
  88. status = NwRdrLogonUser(
  89. LogonId,
  90. UserName,
  91. wcslen(UserName) * sizeof(WCHAR),
  92. Password,
  93. (ARGUMENT_PRESENT(Password) ?
  94. wcslen(Password) * sizeof(WCHAR) :
  95. 0),
  96. PreferredServerName,
  97. (ARGUMENT_PRESENT(PreferredServerName) ?
  98. wcslen(PreferredServerName) * sizeof(WCHAR) :
  99. 0),
  100. NdsPreferredServerName,
  101. (ARGUMENT_PRESENT(NdsPreferredServerName) ?
  102. wcslen(NdsPreferredServerName) * sizeof(WCHAR) :
  103. 0),
  104. PrintOption
  105. );
  106. if (status == NO_ERROR || status == NW_PASSWORD_HAS_EXPIRED) {
  107. NwLogonNotifiedRdr = TRUE;
  108. }
  109. LeaveCriticalSection(&NwLoggedOnCritSec);
  110. if (ARGUMENT_PRESENT(LogonCommand) && (LogonCommandLength >= sizeof(WCHAR))) {
  111. LogonCommand[0] = 0;
  112. }
  113. return status;
  114. }
  115. DWORD
  116. NwrLogoffUser(
  117. IN LPWSTR Reserved OPTIONAL,
  118. IN PLUID LogonId
  119. )
  120. /*++
  121. Routine Description:
  122. This function tells the redirector to log off the interactive
  123. user.
  124. Arguments:
  125. Reserved - Must be NULL.
  126. LogonId - PLUID identifying the logged on process.
  127. Return Value:
  128. --*/
  129. {
  130. DWORD status = NO_ERROR ;
  131. UNREFERENCED_PARAMETER(Reserved);
  132. EnterCriticalSection(&NwLoggedOnCritSec);
  133. status = NwRdrLogoffUser(LogonId);
  134. LeaveCriticalSection(&NwLoggedOnCritSec);
  135. return status ;
  136. }
  137. DWORD
  138. NwrSetInfo(
  139. IN LPWSTR Reserved OPTIONAL,
  140. IN DWORD PrintOption,
  141. IN LPWSTR PreferredServerName OPTIONAL
  142. )
  143. /*++
  144. Routine Description:
  145. This function sets the preferred server and print option in
  146. the redirector for the interactive user.
  147. Arguments:
  148. Reserved - Must be NULL.
  149. PreferredServerName - Specifies the user's preferred server.
  150. PrintOption - Specifies the user's print option flag
  151. Return Value:
  152. NO_ERROR or error from redirector.
  153. --*/
  154. {
  155. DWORD err;
  156. UNREFERENCED_PARAMETER(Reserved);
  157. err = NwRdrSetInfo(
  158. PrintOption,
  159. NwPacketBurstSize, // just reset to current
  160. PreferredServerName,
  161. (PreferredServerName != NULL ?
  162. wcslen( PreferredServerName) * sizeof( WCHAR ) : 0 ),
  163. NwProviderName, // just reset to current
  164. wcslen( NwProviderName ) * sizeof( WCHAR )
  165. );
  166. return err;
  167. }
  168. DWORD
  169. NwrSetLogonScript(
  170. IN LPWSTR Reserved OPTIONAL,
  171. IN DWORD ScriptOptions
  172. )
  173. /*++
  174. Routine Description:
  175. This function sets logon script related info. Currently, all that is
  176. supported is to turn the Run Logon Scripts Synchronously flag on and off.
  177. We do this using the global flag and not per user because at NPLogonNotify
  178. time we dont have per user registry yet. And rather than turn on & leave
  179. on, we turn on as need so that users that dont run NW scripts dont need
  180. wait.
  181. Arguments:
  182. Reserved - Must be NULL.
  183. ScriptOptions - options for logon scripts.
  184. Return Value:
  185. Win32 error from calls made.
  186. --*/
  187. {
  188. DWORD dwSync, err = NO_ERROR ;
  189. HKEY hKeyWinLogon = NULL, hKeyNWC = NULL ;
  190. UNREFERENCED_PARAMETER(Reserved);
  191. if (!IsTerminalServer()) {
  192. // Setting global flags isn't multi-user, see userinit.c for multi-user implementation
  193. //
  194. // *** Note that in this function we intentionally do not impersonate ***
  195. // *** since we are modifying registry under \SOFTWARE & \SYSTEM. ***
  196. //
  197. //
  198. // Check the parameters.
  199. //
  200. if (ScriptOptions == SYNC_LOGONSCRIPT) {
  201. dwSync = 1 ; // this is value WinLogon needs to sync login scripts.
  202. } else if (ScriptOptions == RESET_SYNC_LOGONSCRIPT) {
  203. dwSync = 0 ;
  204. } else {
  205. return(ERROR_INVALID_PARAMETER) ;
  206. }
  207. //
  208. //
  209. // Open HKEY_LOCAL_MACHINE\System\CurrentVersion\Services\NwcWorkstation
  210. // \Parameters. We use this location to record the fact we temporarily
  211. // turned on the Sync Scripts Flag.
  212. //
  213. err = RegOpenKeyExW(
  214. HKEY_LOCAL_MACHINE,
  215. NW_WORKSTATION_REGKEY,
  216. 0,
  217. KEY_READ | KEY_WRITE, // desired access
  218. &hKeyNWC) ;
  219. if ( err ) {
  220. return err ;
  221. }
  222. //
  223. // We are resetting. Check if we turned the flag on. If no, then leave
  224. // it be.
  225. //
  226. if (ScriptOptions == RESET_SYNC_LOGONSCRIPT) {
  227. DWORD dwType, dwValue = 0 ;
  228. DWORD dwSize = sizeof(dwValue) ;
  229. err = RegQueryValueExW(
  230. hKeyNWC,
  231. NW_SYNCLOGONSCRIPT_VALUENAME,
  232. NULL,
  233. &dwType, // ignored
  234. (LPBYTE) &dwValue,
  235. &dwSize) ;
  236. if ((err != NO_ERROR) || (dwValue == 0)) {
  237. //
  238. // value not there or zero. ie. assume we didnt set. quit now.
  239. //
  240. goto ExitPoint ;
  241. }
  242. }
  243. //
  244. //
  245. // Open HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion
  246. // \WinLogon.
  247. //
  248. err = RegOpenKeyExW(
  249. HKEY_LOCAL_MACHINE,
  250. WINLOGON_REGKEY,
  251. 0,
  252. KEY_READ | KEY_WRITE, // desired access
  253. &hKeyWinLogon) ;
  254. if ( err ) {
  255. goto ExitPoint ;
  256. }
  257. //
  258. // We are setting. Check if flag is already on. If yes, then leave
  259. // it be.
  260. //
  261. if (ScriptOptions == SYNC_LOGONSCRIPT) {
  262. DWORD dwType, dwValue = 0 ;
  263. DWORD dwSize = sizeof(dwValue) ;
  264. err = RegQueryValueExW(
  265. hKeyWinLogon,
  266. SYNCLOGONSCRIPT_VALUENAME,
  267. NULL,
  268. &dwType, // ignored
  269. (LPBYTE) &dwValue,
  270. &dwSize) ;
  271. if ((err == NO_ERROR) && (dwValue == 1)) {
  272. //
  273. // already on. nothing to do. just return.
  274. //
  275. goto ExitPoint ;
  276. }
  277. }
  278. //
  279. // Write out value to make logon scripts synchronous. Or to reset it.
  280. //
  281. err = RegSetValueExW(
  282. hKeyWinLogon,
  283. SYNCLOGONSCRIPT_VALUENAME,
  284. 0,
  285. REG_DWORD,
  286. (LPBYTE) &dwSync, // either 1 or 0.
  287. sizeof(dwSync)) ;
  288. if (err == NO_ERROR) {
  289. DWORD dwValue = (ScriptOptions == SYNC_LOGONSCRIPT) ? 1 : 0 ;
  290. //
  291. // We have successfully set WinLogon flag. Record (or clear)
  292. // our own flag.
  293. //
  294. err = RegSetValueExW(
  295. hKeyNWC,
  296. NW_SYNCLOGONSCRIPT_VALUENAME,
  297. 0,
  298. REG_DWORD,
  299. (LPBYTE) &dwValue,
  300. sizeof(dwValue)) ;
  301. }
  302. } //if IsTerminalServer()
  303. ExitPoint:
  304. if (hKeyWinLogon)
  305. (void) RegCloseKey( hKeyWinLogon );
  306. if (hKeyNWC)
  307. (void) RegCloseKey( hKeyNWC );
  308. return err;
  309. }
  310. DWORD
  311. NwrValidateUser(
  312. IN LPWSTR Reserved OPTIONAL,
  313. IN LPWSTR PreferredServerName
  314. )
  315. /*++
  316. Routine Description:
  317. This function checks whether the user can be authenticated
  318. successfully on the given server.
  319. Arguments:
  320. Reserved - Must be NULL.
  321. PreferredServerName - Specifies the user's preferred server.
  322. Return Value:
  323. NO_ERROR or error that occurred during authentication.
  324. --*/
  325. {
  326. DWORD status ;
  327. UNREFERENCED_PARAMETER(Reserved);
  328. if ( ( PreferredServerName != NULL )
  329. && ( *PreferredServerName != 0 )
  330. )
  331. {
  332. //
  333. // Impersonate the client
  334. //
  335. if ((status = NwImpersonateClient()) != NO_ERROR)
  336. {
  337. return status ;
  338. }
  339. status = NwConnectToServer( PreferredServerName ) ;
  340. (void) NwRevertToSelf() ;
  341. return status ;
  342. }
  343. return NO_ERROR;
  344. }
  345. VOID
  346. NwInitializeLogon(
  347. VOID
  348. )
  349. /*++
  350. Routine Description:
  351. This function initializes the data in the workstation which handles
  352. user logon. It is called by the initialization thread.
  353. Arguments:
  354. None.
  355. Return Value:
  356. None.
  357. --*/
  358. {
  359. //
  360. // Initialize logon flag. When the redirector LOGON FsCtl has been
  361. // called, this flag will be set to TRUE. Initialize the
  362. // critical section to serialize access to NwLogonNotifiedRdr flag.
  363. //
  364. NwLogonNotifiedRdr = FALSE;
  365. }
  366. VOID
  367. NwGetLogonCredential(
  368. VOID
  369. )
  370. /*++
  371. Routine Description:
  372. This function reads the user and service logon IDs from the registry so
  373. that it can get the credentials from LSA.
  374. It handles the case where the user has logged on before the workstation
  375. is started. This function is called by the initialization thread
  376. after opening up the RPC interface so that if user logon is happening
  377. concurrently, the provider is given a chance to call the NwrLogonUser API
  378. first, making it no longer necessary for the workstation to also
  379. retrieve the credential from the registry.
  380. Arguments:
  381. None.
  382. Return Value:
  383. None.
  384. --*/
  385. {
  386. DWORD status;
  387. HANDLE LsaHandle;
  388. ULONG AuthPackageId = 0;
  389. EnterCriticalSection(&NwLoggedOnCritSec);
  390. if (NwLogonNotifiedRdr) {
  391. //
  392. // Logon credential's already made known to the redirector by
  393. // the provider calling the NwrLogonUser API.
  394. //
  395. #if DBG
  396. IF_DEBUG(LOGON) {
  397. KdPrint(("\nNWWORKSTATION: Redirector already has logon credential\n"));
  398. }
  399. #endif
  400. LeaveCriticalSection(&NwLoggedOnCritSec);
  401. return;
  402. }
  403. #if DBG
  404. IF_DEBUG(LOGON) {
  405. KdPrint(("NWWORKSTATION: Main init--NwGetLogonCredential\n"));
  406. }
  407. #endif
  408. status = NwpRegisterLogonProcess(&LsaHandle, &AuthPackageId);
  409. if (status != NO_ERROR) {
  410. LeaveCriticalSection(&NwLoggedOnCritSec);
  411. return;
  412. }
  413. //
  414. // Tell the redirector about service credentials
  415. //
  416. NwpGetServiceCredentials(LsaHandle, AuthPackageId);
  417. //
  418. // Tell the redirector about interactive credentials
  419. //
  420. NwpGetInteractiveCredentials(LsaHandle, AuthPackageId);
  421. (void) LsaDeregisterLogonProcess(LsaHandle);
  422. LeaveCriticalSection(&NwLoggedOnCritSec);
  423. }
  424. STATIC
  425. VOID
  426. NwpGetServiceCredentials(
  427. IN HANDLE LsaHandle,
  428. IN ULONG AuthPackageId
  429. )
  430. /*++
  431. Routine Description:
  432. This function reads the service logon IDs from the registry
  433. so that it can get the service credentials from LSA. It then
  434. notifies the redirector of the service logons.
  435. Arguments:
  436. LsaHandle - Supplies the handle to LSA.
  437. AuthPackageId - Supplies the NetWare authentication package ID.
  438. Return Value:
  439. None.
  440. --*/
  441. {
  442. DWORD status;
  443. LONG RegError;
  444. LPWSTR UserName = NULL;
  445. LPWSTR Password = NULL;
  446. HKEY ServiceLogonKey;
  447. DWORD Index = 0;
  448. WCHAR LogonIdKey[NW_MAX_LOGON_ID_LEN];
  449. LUID LogonId;
  450. RegError = RegOpenKeyExW(
  451. HKEY_LOCAL_MACHINE,
  452. NW_SERVICE_LOGON_REGKEY,
  453. REG_OPTION_NON_VOLATILE,
  454. KEY_READ,
  455. &ServiceLogonKey
  456. );
  457. if (RegError == ERROR_SUCCESS) {
  458. do {
  459. RegError = RegEnumKeyW(
  460. ServiceLogonKey,
  461. Index,
  462. LogonIdKey,
  463. sizeof(LogonIdKey) / sizeof(WCHAR)
  464. );
  465. if (RegError == ERROR_SUCCESS) {
  466. //
  467. // Got a logon id key.
  468. //
  469. NwWStrToLuid(LogonIdKey, &LogonId);
  470. status = NwpGetCredentialInLsa(
  471. LsaHandle,
  472. AuthPackageId,
  473. &LogonId,
  474. &UserName,
  475. &Password
  476. );
  477. if (status == NO_ERROR) {
  478. (void) NwRdrLogonUser(
  479. &LogonId,
  480. UserName,
  481. wcslen(UserName) * sizeof(WCHAR),
  482. Password,
  483. wcslen(Password) * sizeof(WCHAR),
  484. NULL,
  485. 0,
  486. NULL,
  487. 0,
  488. NW_PRINT_OPTION_DEFAULT
  489. );
  490. //
  491. // Freeing the UserName pointer frees both the
  492. // username and password buffers.
  493. //
  494. (void) LsaFreeReturnBuffer((PVOID) UserName);
  495. }
  496. }
  497. else if (RegError != ERROR_NO_MORE_ITEMS) {
  498. KdPrint(("NWWORKSTATION: NwpGetServiceCredentials failed to enum logon IDs RegError=%lu\n",
  499. RegError));
  500. }
  501. Index++;
  502. } while (RegError == ERROR_SUCCESS);
  503. (void) RegCloseKey(ServiceLogonKey);
  504. }
  505. }
  506. STATIC
  507. VOID
  508. NwpGetInteractiveCredentials(
  509. IN HANDLE LsaHandle,
  510. IN ULONG AuthPackageId
  511. )
  512. /*++
  513. Routine Description:
  514. This function reads the interactive logon IDs from the registry
  515. so that it can get the interactive credentials from LSA. It then
  516. notifies the redirector of the interactive logons.
  517. Arguments:
  518. LsaHandle - Supplies the handle to LSA.
  519. AuthPackageId - Supplies the NetWare authentication package ID.
  520. Return Value:
  521. None.
  522. --*/
  523. {
  524. DWORD status;
  525. LONG RegError;
  526. LPWSTR UserName = NULL;
  527. LPWSTR Password = NULL;
  528. HKEY InteractiveLogonKey;
  529. DWORD Index = 0;
  530. WCHAR LogonIdName[NW_MAX_LOGON_ID_LEN];
  531. LUID LogonId;
  532. DWORD PrintOption;
  533. HKEY WkstaOptionKey = NULL;
  534. HKEY CurrentUserOptionKey = NULL;
  535. HKEY OneLogonKey;
  536. LPWSTR UserSid = NULL;
  537. PDWORD pPrintOption = NULL;
  538. LPWSTR PreferredServer = NULL;
  539. LPWSTR NdsPreferredServer = NULL;
  540. RegError = RegOpenKeyExW(
  541. HKEY_LOCAL_MACHINE,
  542. NW_INTERACTIVE_LOGON_REGKEY,
  543. REG_OPTION_NON_VOLATILE,
  544. KEY_READ,
  545. &InteractiveLogonKey
  546. );
  547. if (RegError == ERROR_SUCCESS) {
  548. do {
  549. RegError = RegEnumKeyW(
  550. InteractiveLogonKey,
  551. Index,
  552. LogonIdName,
  553. sizeof(LogonIdName) / sizeof(WCHAR)
  554. );
  555. if (RegError == ERROR_SUCCESS) {
  556. //
  557. // Got a logon id key.
  558. //
  559. NwWStrToLuid(LogonIdName, &LogonId);
  560. status = NwpGetCredentialInLsa(
  561. LsaHandle,
  562. AuthPackageId,
  563. &LogonId,
  564. &UserName,
  565. &Password
  566. );
  567. if (status == NO_ERROR) {
  568. UserSid = NULL;
  569. //
  570. // Open the <LogonIdName> key under Logon
  571. //
  572. RegError = RegOpenKeyExW(
  573. InteractiveLogonKey,
  574. LogonIdName,
  575. REG_OPTION_NON_VOLATILE,
  576. KEY_READ,
  577. &OneLogonKey
  578. );
  579. if ( RegError != ERROR_SUCCESS ) {
  580. KdPrint(("NWWORKSTATION: NwpGetInteractiveLogonCredential: RegOpenKeyExW failed, Not interactive Logon: Error %d\n", GetLastError()));
  581. }
  582. else {
  583. //
  584. // Read the SID value.
  585. //
  586. status = NwReadRegValue(
  587. OneLogonKey,
  588. NW_SID_VALUENAME,
  589. (LPWSTR *) &UserSid
  590. );
  591. (void) RegCloseKey(OneLogonKey);
  592. if ( status != NO_ERROR ) {
  593. KdPrint(("NWWORKSTATION: NwpGetInteractiveLogonCredential: Could not read SID from reg %lu\n", status));
  594. UserSid = NULL;
  595. }
  596. }
  597. if ( UserSid ) {
  598. PrintOption = NW_PRINT_OPTION_DEFAULT;
  599. PreferredServer = NULL;
  600. //
  601. // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet
  602. // \Services\NWCWorkstation\Parameters\Option
  603. //
  604. RegError = RegOpenKeyExW(
  605. HKEY_LOCAL_MACHINE,
  606. NW_WORKSTATION_OPTION_REGKEY,
  607. REG_OPTION_NON_VOLATILE, // options
  608. KEY_READ, // desired access
  609. &WkstaOptionKey
  610. );
  611. if (RegError != ERROR_SUCCESS) {
  612. KdPrint(("NWWORKSTATION: NwpGetInteractiveCredentials: RegOpenKeyExW Parameter\\Option returns unexpected error %lu!!\n",
  613. RegError));
  614. goto NoOption;
  615. }
  616. //
  617. // Open the <UserSid> key under Option
  618. //
  619. RegError = RegOpenKeyExW(
  620. WkstaOptionKey,
  621. UserSid,
  622. REG_OPTION_NON_VOLATILE,
  623. KEY_READ,
  624. &CurrentUserOptionKey
  625. );
  626. if (RegError != ERROR_SUCCESS) {
  627. KdPrint(("NWWORKSTATION: NwpGetInteractiveCredentials: RegOpenKeyExW Parameter\\Option\\SID returns unexpected error %lu!!\n",
  628. RegError));
  629. (void) RegCloseKey(WkstaOptionKey);
  630. goto NoOption;
  631. }
  632. //
  633. // Read the preferred server value.
  634. //
  635. status = NwReadRegValue(
  636. CurrentUserOptionKey,
  637. NW_SERVER_VALUENAME,
  638. &PreferredServer
  639. );
  640. if (status != NO_ERROR) {
  641. KdPrint(("NWWORKSTATION: NwpGetInteractiveCredentials: Could not read preferred server from reg %lu\n", status));
  642. PreferredServer = NULL;
  643. }
  644. //
  645. // Read the preferred NDS server value (if one exists).
  646. //
  647. status = NwReadRegValue(
  648. CurrentUserOptionKey,
  649. NW_NDS_SERVER_VALUENAME,
  650. &NdsPreferredServer
  651. );
  652. if (status != NO_ERROR) {
  653. #if DBG
  654. IF_DEBUG(LOGON) {
  655. KdPrint(("NWWORKSTATION: NwGetLogonCredential: Could not read preferred NDS server from reg %lu\n", status));
  656. }
  657. #endif
  658. NdsPreferredServer = NULL;
  659. }
  660. //
  661. // Read the print option value.
  662. //
  663. status = NwReadRegValue(
  664. CurrentUserOptionKey,
  665. NW_PRINTOPTION_VALUENAME,
  666. (LPWSTR *) &pPrintOption
  667. );
  668. if (status != NO_ERROR) {
  669. #if DBG
  670. IF_DEBUG(LOGON) {
  671. KdPrint(("NWWORKSTATION: NwGetLogonCredential: Could not read print option from reg %lu\n", status));
  672. }
  673. #endif
  674. PrintOption = NW_PRINT_OPTION_DEFAULT;
  675. }
  676. else {
  677. if ( pPrintOption != NULL ) {
  678. PrintOption = *pPrintOption;
  679. (void) LocalFree((HLOCAL) pPrintOption);
  680. pPrintOption = NULL;
  681. }
  682. else {
  683. PrintOption = NW_PRINT_OPTION_DEFAULT;
  684. }
  685. }
  686. (void) RegCloseKey(CurrentUserOptionKey);
  687. (void) RegCloseKey(WkstaOptionKey);
  688. NoOption:
  689. (void) NwRdrLogonUser(
  690. &LogonId,
  691. UserName,
  692. wcslen(UserName) * sizeof(WCHAR),
  693. Password,
  694. wcslen(Password) * sizeof(WCHAR),
  695. PreferredServer,
  696. ((PreferredServer != NULL) ?
  697. wcslen(PreferredServer) * sizeof(WCHAR) :
  698. 0),
  699. NdsPreferredServer,
  700. ((NdsPreferredServer != NULL) ?
  701. wcslen(NdsPreferredServer) * sizeof(WCHAR) :
  702. 0),
  703. PrintOption
  704. );
  705. //
  706. // Freeing the UserName pointer frees both the
  707. // username and password buffers.
  708. //
  709. (void) LsaFreeReturnBuffer((PVOID) UserName);
  710. if (UserSid != NULL) {
  711. (void) LocalFree((HLOCAL) UserSid);
  712. UserSid = NULL;
  713. }
  714. if (PreferredServer != NULL) {
  715. (void) LocalFree((HLOCAL) PreferredServer);
  716. PreferredServer = NULL;
  717. }
  718. }
  719. }
  720. }
  721. else if (RegError != ERROR_NO_MORE_ITEMS) {
  722. KdPrint(("NWWORKSTATION: NwpGetInteractiveCredentials failed to enum logon IDs RegError=%lu\n",
  723. RegError));
  724. }
  725. Index++;
  726. } while (RegError == ERROR_SUCCESS);
  727. (void) RegCloseKey(InteractiveLogonKey);
  728. }
  729. }
  730. STATIC
  731. DWORD
  732. NwpRegisterLogonProcess(
  733. OUT PHANDLE LsaHandle,
  734. OUT PULONG AuthPackageId
  735. )
  736. /*++
  737. Routine Description:
  738. This function registers the workstation service as a logon process
  739. so that it can call LSA to retrieve user credentials.
  740. Arguments:
  741. LsaHandle - Receives the handle to LSA.
  742. AuthPackageId - Receives the NetWare authentication package ID.
  743. Return Value:
  744. NO_ERROR or reason for failure.
  745. --*/
  746. {
  747. DWORD status = NO_ERROR;
  748. NTSTATUS ntstatus;
  749. STRING InputString;
  750. LSA_OPERATIONAL_MODE SecurityMode = 0;
  751. //
  752. // Register this process as a logon process so that we can call
  753. // NetWare authentication package.
  754. //
  755. RtlInitString(&InputString, "Client Service for NetWare");
  756. ntstatus = LsaRegisterLogonProcess(
  757. &InputString,
  758. LsaHandle,
  759. &SecurityMode
  760. );
  761. if (! NT_SUCCESS(ntstatus)) {
  762. KdPrint(("NWPROVAU: NwInitializeLogon: LsaRegisterLogonProcess returns x%08lx\n",
  763. ntstatus));
  764. return RtlNtStatusToDosError(ntstatus);
  765. }
  766. //
  767. // Look up the Netware authentication package
  768. //
  769. RtlInitString(&InputString, NW_AUTH_PACKAGE_NAME);
  770. ntstatus = LsaLookupAuthenticationPackage(
  771. *LsaHandle,
  772. &InputString,
  773. AuthPackageId
  774. );
  775. if (! NT_SUCCESS(ntstatus)) {
  776. KdPrint(("NWPROVAU: NwpSetCredential: LsaLookupAuthenticationPackage returns x%08lx\n",
  777. ntstatus));
  778. (void) LsaDeregisterLogonProcess(*LsaHandle);
  779. }
  780. status = RtlNtStatusToDosError(ntstatus);
  781. return status;
  782. }
  783. STATIC
  784. DWORD
  785. NwpGetCredentialInLsa(
  786. IN HANDLE LsaHandle,
  787. IN ULONG AuthPackageId,
  788. IN PLUID LogonId,
  789. OUT LPWSTR *UserName,
  790. OUT LPWSTR *Password
  791. )
  792. /*++
  793. Routine Description:
  794. This function retrieves the username and password information
  795. from LSA given the logon ID.
  796. Arguments:
  797. LsaHandle - Supplies the handle to LSA.
  798. AuthPackageId - Supplies the NetWare authentication package ID.
  799. LogonId - Supplies the logon ID.
  800. UserName - Receives a pointer to the username.
  801. Password - Receives a pointer to the password.
  802. Return Value:
  803. NO_ERROR or reason for failure.
  804. --*/
  805. {
  806. DWORD status;
  807. NTSTATUS ntstatus;
  808. NTSTATUS AuthPackageStatus;
  809. NWAUTH_GET_CREDENTIAL_REQUEST GetCredRequest;
  810. PNWAUTH_GET_CREDENTIAL_RESPONSE GetCredResponse;
  811. ULONG ResponseLength;
  812. UNICODE_STRING PasswordStr;
  813. //
  814. // Ask authentication package for credential.
  815. //
  816. GetCredRequest.MessageType = NwAuth_GetCredential;
  817. RtlCopyLuid(&GetCredRequest.LogonId, LogonId);
  818. ntstatus = LsaCallAuthenticationPackage(
  819. LsaHandle,
  820. AuthPackageId,
  821. &GetCredRequest,
  822. sizeof(GetCredRequest),
  823. (PVOID *) &GetCredResponse,
  824. &ResponseLength,
  825. &AuthPackageStatus
  826. );
  827. if (NT_SUCCESS(ntstatus)) {
  828. ntstatus = AuthPackageStatus;
  829. }
  830. if (! NT_SUCCESS(ntstatus)) {
  831. KdPrint(("NWPROVAU: NwpGetCredentialInLsa: LsaCallAuthenticationPackage returns x%08lx\n",
  832. ntstatus));
  833. status = RtlNtStatusToDosError(ntstatus);
  834. }
  835. else {
  836. *UserName = GetCredResponse->UserName;
  837. *Password = GetCredResponse->Password;
  838. //
  839. // Decode the password.
  840. //
  841. RtlInitUnicodeString(&PasswordStr, GetCredResponse->Password);
  842. RtlRunDecodeUnicodeString(NW_ENCODE_SEED, &PasswordStr);
  843. status = NO_ERROR;
  844. }
  845. return status;
  846. }
  847. DWORD
  848. NwrChangePassword(
  849. IN LPWSTR Reserved OPTIONAL,
  850. IN DWORD UserLuid,
  851. IN LPWSTR UserName,
  852. IN LPWSTR OldPassword,
  853. IN LPWSTR NewPassword,
  854. IN LPWSTR TreeName
  855. )
  856. /*++
  857. Routine Description:
  858. This function changes the password for the specified user on
  859. the list of servers. If we encounter a failure on changing
  860. password for a particular server, we:
  861. 1) Send the new password over to the server to verify if it is
  862. already the current password.
  863. 2) If not, return ERROR_INVALID_PASSWORD and the index into
  864. the Servers array indicating the server which failed so that
  865. we can prompt the user to enter an alternate old password.
  866. When the password has been changed successfully on a server, we
  867. notify the redirector so that the cached credential can be updated.
  868. NOTE: All errors returned from this routine, except for the fatal
  869. ERROR_NOT_ENOUGH_MEMORY error, indicates that the password
  870. could not be changed on a particular server indexed by
  871. LastProcessed. The client-side continues to call us with
  872. the remaining list of servers.
  873. If you add to this routine to return other fatal errors,
  874. please make sure the client-side code aborts from calling
  875. us with the rest of the servers on getting those errors.
  876. Arguments:
  877. Reserved - Must be NULL.
  878. Return Value:
  879. ERROR_BAD_NETPATH - Could not connect to the server indexed by
  880. LastProcessed.
  881. ERROR_BAD_USERNAME - The username could not be found on the server
  882. indexed by LastProcessed.
  883. ERROR_INVALID_PASSWORD - The change password operation failed on
  884. the server indexed by LastProcessed.
  885. ERROR_NOT_ENOUGH_MEMORY - Out of memory error. This fatal error
  886. will terminate the client-side from trying to process password
  887. change request on the remaining servers.
  888. --*/
  889. {
  890. DWORD status;
  891. NTSTATUS ntstatus;
  892. HANDLE hNwRdr = NULL;
  893. UNICODE_STRING UserNameStr;
  894. UNICODE_STRING OldPasswordStr;
  895. UNICODE_STRING NewPasswordStr;
  896. UNICODE_STRING TreeNameStr;
  897. BOOL fImpersonateClient = FALSE;
  898. UNREFERENCED_PARAMETER( Reserved ) ;
  899. UNREFERENCED_PARAMETER( UserLuid ) ;
  900. RtlInitUnicodeString( &UserNameStr, UserName );
  901. RtlInitUnicodeString( &OldPasswordStr, OldPassword );
  902. RtlRunDecodeUnicodeString( NW_ENCODE_SEED2, &OldPasswordStr );
  903. RtlInitUnicodeString( &NewPasswordStr, NewPassword );
  904. RtlRunDecodeUnicodeString( NW_ENCODE_SEED2, &NewPasswordStr );
  905. RtlInitUnicodeString( &TreeNameStr, TreeName );
  906. //
  907. // Impersonate the client
  908. //
  909. if ((status = NwImpersonateClient()) != NO_ERROR)
  910. {
  911. goto ErrorExit;
  912. }
  913. fImpersonateClient = TRUE;
  914. //
  915. // Open a NDS tree connection handle to \\treename
  916. //
  917. ntstatus = NwNdsOpenTreeHandle( &TreeNameStr, &hNwRdr );
  918. if ( ntstatus != STATUS_SUCCESS )
  919. {
  920. status = RtlNtStatusToDosError(ntstatus);
  921. goto ErrorExit;
  922. }
  923. (void) NwRevertToSelf() ;
  924. fImpersonateClient = FALSE;
  925. ntstatus = NwNdsChangePassword( hNwRdr,
  926. &TreeNameStr,
  927. &UserNameStr,
  928. &OldPasswordStr,
  929. &NewPasswordStr );
  930. if ( ntstatus != NO_ERROR )
  931. {
  932. status = RtlNtStatusToDosError(ntstatus);
  933. goto ErrorExit;
  934. }
  935. CloseHandle( hNwRdr );
  936. hNwRdr = NULL;
  937. return NO_ERROR ;
  938. ErrorExit:
  939. if ( fImpersonateClient )
  940. (void) NwRevertToSelf() ;
  941. if ( hNwRdr )
  942. CloseHandle( hNwRdr );
  943. hNwRdr = NULL;
  944. return status;
  945. }