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.

894 lines
20 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. api.c
  5. Abstract:
  6. This module contains exposed APIs that is used by the
  7. NetWare Control Panel Applet.
  8. Author:
  9. Yi-Hsin Sung 15-Jul-1993
  10. Revision History:
  11. ChuckC 23-Jul-93 Completed the stubs
  12. --*/
  13. #include <nwclient.h>
  14. #include <nwcanon.h>
  15. #include <validc.h>
  16. #include <nwdlg.h>
  17. #include <nwreg.h>
  18. #include <nwapi.h>
  19. #include <ntddnwfs.h>
  20. //Multi-User code merge
  21. DWORD
  22. NwpCitrixGetUserInfo(
  23. LPWSTR *ppszUserSid
  24. );
  25. //
  26. // forward declare
  27. //
  28. DWORD
  29. NwpGetCurrentUserRegKey(
  30. IN DWORD DesiredAccess,
  31. OUT HKEY *phKeyCurrentUser
  32. );
  33. DWORD
  34. NwQueryInfo(
  35. OUT PDWORD pnPrintOptions,
  36. OUT LPWSTR *ppszPreferredSrv
  37. )
  38. /*++
  39. Routine Description:
  40. This routine gets the user's preferred server and print options from
  41. the registry.
  42. Arguments:
  43. pnPrintOptions - Receives the user's print option
  44. ppszPreferredSrv - Receives the user's preferred server
  45. Return Value:
  46. Returns the appropriate Win32 error.
  47. --*/
  48. {
  49. HKEY hKeyCurrentUser = NULL;
  50. DWORD BufferSize;
  51. DWORD BytesNeeded;
  52. DWORD PrintOption;
  53. DWORD ValueType;
  54. LPWSTR PreferredServer ;
  55. DWORD err ;
  56. //
  57. // get to right place in registry and allocate dthe buffer
  58. //
  59. if (err = NwpGetCurrentUserRegKey( KEY_READ, &hKeyCurrentUser))
  60. {
  61. //
  62. // If somebody mess around with the registry and we can't find
  63. // the registry, just use the defaults.
  64. //
  65. *ppszPreferredSrv = NULL;
  66. *pnPrintOptions = NW_PRINT_OPTION_DEFAULT;
  67. return NO_ERROR;
  68. }
  69. BufferSize = sizeof(WCHAR) * (MAX_PATH + 2) ;
  70. PreferredServer = (LPWSTR) LocalAlloc(LPTR, BufferSize) ;
  71. if (!PreferredServer)
  72. return (GetLastError()) ;
  73. //
  74. // Read PreferredServer value into Buffer.
  75. //
  76. BytesNeeded = BufferSize ;
  77. err = RegQueryValueExW( hKeyCurrentUser,
  78. NW_SERVER_VALUENAME,
  79. NULL,
  80. &ValueType,
  81. (LPBYTE) PreferredServer,
  82. &BytesNeeded );
  83. if (err != NO_ERROR)
  84. {
  85. //
  86. // set to empty and carry on
  87. //
  88. PreferredServer[0] = 0;
  89. }
  90. //
  91. // Read PrintOption value into PrintOption.
  92. //
  93. BytesNeeded = sizeof(PrintOption);
  94. err = RegQueryValueExW( hKeyCurrentUser,
  95. NW_PRINTOPTION_VALUENAME,
  96. NULL,
  97. &ValueType,
  98. (LPBYTE) &PrintOption,
  99. &BytesNeeded );
  100. if (err != NO_ERROR)
  101. {
  102. //
  103. // set to default and carry on
  104. //
  105. PrintOption = NW_PRINT_OPTION_DEFAULT;
  106. }
  107. if (hKeyCurrentUser != NULL)
  108. (void) RegCloseKey(hKeyCurrentUser) ;
  109. *ppszPreferredSrv = PreferredServer ;
  110. *pnPrintOptions = PrintOption ;
  111. return NO_ERROR ;
  112. }
  113. DWORD
  114. NwSetInfoInRegistry(
  115. IN DWORD nPrintOptions,
  116. IN LPWSTR pszPreferredSrv
  117. )
  118. /*++
  119. Routine Description:
  120. This routine set the user's print option and preferred server into
  121. the registry.
  122. Arguments:
  123. nPrintOptions - Supplies the print option.
  124. pszPreferredSrv - Supplies the preferred server.
  125. Return Value:
  126. Returns the appropriate Win32 error.
  127. --*/
  128. {
  129. HKEY hKeyCurrentUser = NULL;
  130. DWORD err = NwpGetCurrentUserRegKey( KEY_SET_VALUE,
  131. &hKeyCurrentUser );
  132. if (err != NO_ERROR)
  133. return err;
  134. err = RegSetValueEx(hKeyCurrentUser,
  135. NW_SERVER_VALUENAME,
  136. 0,
  137. REG_SZ,
  138. (CONST BYTE *)pszPreferredSrv,
  139. (wcslen(pszPreferredSrv)+1) * sizeof(WCHAR)) ;
  140. if (err != NO_ERROR)
  141. {
  142. if (hKeyCurrentUser != NULL)
  143. (void) RegCloseKey(hKeyCurrentUser) ;
  144. return err;
  145. }
  146. err = RegSetValueEx(hKeyCurrentUser,
  147. NW_PRINTOPTION_VALUENAME,
  148. 0,
  149. REG_DWORD,
  150. (CONST BYTE *)&nPrintOptions,
  151. sizeof(nPrintOptions)) ;
  152. if (hKeyCurrentUser != NULL)
  153. (void) RegCloseKey(hKeyCurrentUser) ;
  154. return err;
  155. }
  156. DWORD
  157. NwQueryLogonOptions(
  158. OUT PDWORD pnLogonScriptOptions
  159. )
  160. /*++
  161. Routine Description:
  162. This routine gets the user's Logon script options from the registry.
  163. Arguments:
  164. pnLogonScriptOptions - Receives the user's Logon script options
  165. Return Value:
  166. Returns the appropriate Win32 error.
  167. --*/
  168. {
  169. HKEY hKeyCurrentUser;
  170. DWORD BytesNeeded;
  171. DWORD LogonScriptOption;
  172. DWORD ValueType;
  173. DWORD err ;
  174. //
  175. // get to right place in registry and allocate the buffer
  176. //
  177. if (err = NwpGetCurrentUserRegKey( KEY_READ, &hKeyCurrentUser))
  178. {
  179. //
  180. // If somebody mess around with the registry and we can't find
  181. // the registry, assume no.
  182. //
  183. *pnLogonScriptOptions = NW_LOGONSCRIPT_DEFAULT ;
  184. return NO_ERROR;
  185. }
  186. //
  187. // Read LogonScriptOption value into LogonScriptOption.
  188. //
  189. BytesNeeded = sizeof(LogonScriptOption);
  190. err = RegQueryValueExW( hKeyCurrentUser,
  191. NW_LOGONSCRIPT_VALUENAME,
  192. NULL,
  193. &ValueType,
  194. (LPBYTE) &LogonScriptOption,
  195. &BytesNeeded );
  196. if (err != NO_ERROR)
  197. {
  198. //
  199. // default to nothing and carry on
  200. //
  201. LogonScriptOption = NW_LOGONSCRIPT_DEFAULT;
  202. }
  203. *pnLogonScriptOptions = LogonScriptOption ;
  204. return NO_ERROR ;
  205. }
  206. DWORD
  207. NwSetLogonOptionsInRegistry(
  208. IN DWORD nLogonScriptOptions
  209. )
  210. /*++
  211. Routine Description:
  212. This routine set the logon script options in the registry.
  213. Arguments:
  214. nLogonScriptOptions - Supplies the logon options
  215. Return Value:
  216. Returns the appropriate Win32 error.
  217. --*/
  218. {
  219. HKEY hKeyCurrentUser;
  220. DWORD err = NwpGetCurrentUserRegKey( KEY_SET_VALUE,
  221. &hKeyCurrentUser );
  222. if (err != NO_ERROR)
  223. return err;
  224. err = RegSetValueEx(hKeyCurrentUser,
  225. NW_LOGONSCRIPT_VALUENAME,
  226. 0,
  227. REG_DWORD,
  228. (CONST BYTE *)&nLogonScriptOptions,
  229. sizeof(nLogonScriptOptions)) ;
  230. (void) RegCloseKey( hKeyCurrentUser );
  231. return err;
  232. }
  233. DWORD
  234. NwSetInfoInWksta(
  235. IN DWORD nPrintOption,
  236. IN LPWSTR pszPreferredSrv
  237. )
  238. /*++
  239. Routine Description:
  240. This routine notifies the workstation service and the redirector
  241. about the user's new print option and preferred server.
  242. Arguments:
  243. nPrintOptions - Supplies the print option.
  244. pszPreferredSrv - Supplies the preferred server.
  245. Return Value:
  246. Returns the appropriate Win32 error.
  247. --*/
  248. {
  249. DWORD err;
  250. RpcTryExcept {
  251. err = NwrSetInfo( NULL, nPrintOption, pszPreferredSrv );
  252. }
  253. RpcExcept(1) {
  254. err = NwpMapRpcError(RpcExceptionCode());
  255. }
  256. RpcEndExcept
  257. return err;
  258. }
  259. DWORD
  260. NwSetLogonScript(
  261. IN DWORD ScriptOptions
  262. )
  263. /*++
  264. Routine Description:
  265. This routine notifies the workstation service of login script
  266. options.
  267. Arguments:
  268. ScriptOptions - Supplies the options.
  269. Return Value:
  270. Returns the appropriate Win32 error.
  271. --*/
  272. {
  273. DWORD err;
  274. RpcTryExcept {
  275. err = NwrSetLogonScript( NULL, ScriptOptions );
  276. }
  277. RpcExcept(1) {
  278. err = NwpMapRpcError(RpcExceptionCode());
  279. }
  280. RpcEndExcept
  281. return err;
  282. }
  283. DWORD
  284. NwValidateUser(
  285. IN LPWSTR pszPreferredSrv
  286. )
  287. /*++
  288. Routine Description:
  289. This routine checks to see if the user can be authenticated on the
  290. chosen preferred server.
  291. Arguments:
  292. pszPreferredSrv - Supplies the preferred server name.
  293. Return Value:
  294. Returns the appropriate Win32 error.
  295. --*/
  296. {
  297. DWORD err;
  298. //
  299. // Don't need to validate if the preferred server is NULL or empty string
  300. //
  301. if ( ( pszPreferredSrv == NULL )
  302. || ( *pszPreferredSrv == 0 )
  303. )
  304. {
  305. return NO_ERROR;
  306. }
  307. //
  308. // See if the name contains any invalid characters
  309. //
  310. if ( !IS_VALID_SERVER_TOKEN( pszPreferredSrv, wcslen( pszPreferredSrv )))
  311. return ERROR_INVALID_NAME;
  312. RpcTryExcept {
  313. err = NwrValidateUser( NULL, pszPreferredSrv );
  314. }
  315. RpcExcept(1) {
  316. err = NwpMapRpcError( RpcExceptionCode() );
  317. }
  318. RpcEndExcept
  319. return err;
  320. }
  321. DWORD
  322. NwpGetCurrentUserRegKey(
  323. IN DWORD DesiredAccess,
  324. OUT HKEY *phKeyCurrentUser
  325. )
  326. /*++
  327. Routine Description:
  328. This routine opens the current user's registry key under
  329. \HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NWCWorkstation\Parameters
  330. Arguments:
  331. DesiredAccess - The access mask to open the key with
  332. phKeyCurrentUser - Receives the opened key handle
  333. Return Value:
  334. Returns the appropriate Win32 error.
  335. --*/
  336. {
  337. DWORD err;
  338. HKEY hkeyWksta;
  339. LPWSTR CurrentUser;
  340. //
  341. // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
  342. // \NWCWorkstation\Parameters
  343. //
  344. err = RegOpenKeyExW(
  345. HKEY_LOCAL_MACHINE,
  346. NW_WORKSTATION_REGKEY,
  347. REG_OPTION_NON_VOLATILE,
  348. KEY_READ,
  349. &hkeyWksta
  350. );
  351. if ( err ) {
  352. KdPrint(("NWPROVAU: NwGetCurrentUserRegKey open Parameters key unexpected error %lu!\n", err));
  353. return err;
  354. }
  355. // -- MultiUser code merge ----
  356. // Get the current user's SID string
  357. // DON'T look in the registry. This thread should be owned by the
  358. // user.
  359. //
  360. CurrentUser = NULL;
  361. err = NwpCitrixGetUserInfo( &CurrentUser );
  362. if ( err ) {
  363. KdPrint(("NWPROVAU: NwGetCurrentUserRegKey get CurrentUser SID unexpected error %lu!\n", err));
  364. (void) RegCloseKey( hkeyWksta );
  365. return err;
  366. }
  367. //
  368. // Get the current user's SID string.
  369. //
  370. //err = NwReadRegValue(
  371. // hkeyWksta,
  372. // NW_CURRENTUSER_VALUENAME,
  373. // &CurrentUser
  374. // );
  375. if ( err ) {
  376. KdPrint(("NWPROVAU: NwGetCurrentUserRegKey read CurrentUser value unexpected error %lu!\n", err));
  377. (void) RegCloseKey( hkeyWksta );
  378. return err;
  379. }
  380. (void) RegCloseKey( hkeyWksta );
  381. //
  382. // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
  383. // \NWCWorkstation\Parameters\Option
  384. //
  385. err = RegOpenKeyExW(
  386. HKEY_LOCAL_MACHINE,
  387. NW_WORKSTATION_OPTION_REGKEY,
  388. REG_OPTION_NON_VOLATILE,
  389. KEY_READ,
  390. &hkeyWksta
  391. );
  392. if ( err ) {
  393. KdPrint(("NWPROVAU: NwGetCurrentUserRegKey open Parameters\\Option key unexpected error %lu!\n", err));
  394. return err;
  395. }
  396. //
  397. // Open current user's key
  398. //
  399. err = RegOpenKeyExW(
  400. hkeyWksta,
  401. CurrentUser,
  402. REG_OPTION_NON_VOLATILE,
  403. DesiredAccess,
  404. phKeyCurrentUser
  405. );
  406. if ( err == ERROR_FILE_NOT_FOUND)
  407. {
  408. DWORD Disposition;
  409. //
  410. // Create <NewUser> key under NWCWorkstation\Parameters\Option
  411. //
  412. err = RegCreateKeyExW(
  413. hkeyWksta,
  414. CurrentUser,
  415. 0,
  416. WIN31_CLASS,
  417. REG_OPTION_NON_VOLATILE,
  418. DesiredAccess,
  419. NULL, // security attr
  420. phKeyCurrentUser,
  421. &Disposition
  422. );
  423. if ( err == NO_ERROR )
  424. {
  425. err = NwLibSetEverybodyPermission( *phKeyCurrentUser,
  426. KEY_SET_VALUE );
  427. if ( err != NO_ERROR )
  428. {
  429. KdPrint(("NWPROVAU: NwpSaveLogonCredential set security on Option\\%ws key unexpected error %lu!\n", CurrentUser, err));
  430. }
  431. }
  432. }
  433. if ( err ) {
  434. KdPrint(("NWPROVAU: NwGetCurrentUserRegKey open or create of Parameters\\Option\\%ws key failed %lu\n", CurrentUser, err));
  435. }
  436. (void) RegCloseKey( hkeyWksta );
  437. (void) LocalFree((HLOCAL)CurrentUser) ;
  438. return err;
  439. }
  440. NTSTATUS
  441. NwGetUserNameForServer(
  442. PUNICODE_STRING ServerName,
  443. PUNICODE_STRING UserName
  444. )
  445. /*++
  446. Routine Description:
  447. Calls the redir to get the User Name used to connect to the server
  448. in question.
  449. Arguments:
  450. ServerName - the server in question
  451. UserName - used to return the user name
  452. Return Value:
  453. Returns the appropriate NTSTATUS
  454. --*/
  455. {
  456. NTSTATUS Status;
  457. WCHAR LocalUserName[NW_MAX_USERNAME_LEN];
  458. ULONG UserNameLen = sizeof(LocalUserName);
  459. OBJECT_ATTRIBUTES ObjectAttributes;
  460. UNICODE_STRING DriverName;
  461. HANDLE RdrHandle = NULL;
  462. IO_STATUS_BLOCK IoStatus;
  463. //
  464. // Initialize variables
  465. //
  466. RtlInitUnicodeString( &DriverName, DD_NWFS_DEVICE_NAME_U );
  467. InitializeObjectAttributes(
  468. &ObjectAttributes,
  469. &DriverName,
  470. 0,
  471. NULL,
  472. NULL
  473. );
  474. //
  475. // open handle to the redir
  476. //
  477. Status = NtOpenFile(
  478. &RdrHandle,
  479. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  480. &ObjectAttributes,
  481. &IoStatus,
  482. FILE_SHARE_READ,
  483. 0 // open options
  484. );
  485. if (!NT_SUCCESS(Status) ||
  486. !NT_SUCCESS(IoStatus.Status) )
  487. {
  488. return( Status );
  489. }
  490. //
  491. // Call the driver to get use the user name
  492. //
  493. Status = NtFsControlFile(
  494. RdrHandle,
  495. NULL,
  496. NULL,
  497. NULL,
  498. &IoStatus,
  499. FSCTL_NWR_GET_USERNAME,
  500. ServerName->Buffer,
  501. ServerName->Length,
  502. LocalUserName,
  503. UserNameLen
  504. );
  505. NtClose(RdrHandle);
  506. if (!NT_SUCCESS(Status))
  507. {
  508. return(Status);
  509. }
  510. //
  511. // copy the info if it fits. set size required and fail otherwise.
  512. //
  513. if (UserName->MaximumLength >= IoStatus.Information)
  514. {
  515. UserName->Length = (USHORT) IoStatus.Information;
  516. RtlCopyMemory( UserName->Buffer,
  517. LocalUserName,
  518. UserNameLen );
  519. Status = STATUS_SUCCESS;
  520. }
  521. else
  522. {
  523. UserName->Length = (USHORT) IoStatus.Information;
  524. Status = STATUS_BUFFER_TOO_SMALL;
  525. }
  526. return(Status);
  527. }
  528. NTSTATUS
  529. NwEncryptChallenge(
  530. IN PUCHAR Challenge,
  531. IN ULONG ObjectId,
  532. IN OPTIONAL PUNICODE_STRING ServerName,
  533. IN OPTIONAL PUNICODE_STRING Password,
  534. OUT PUCHAR ChallengeResponse,
  535. OUT OPTIONAL PUCHAR SessionKey
  536. )
  537. /*++
  538. Routine Description:
  539. Calls the redir to encrypt a challenge
  540. Arguments:
  541. Challenge - Challenge key
  542. ObjectId - User's object ID
  543. ServerName - The server to authenticate against
  544. Password - Password supplied
  545. ChallengeResponse - Used to return the challenge response
  546. SessionKey - Used to return the session key
  547. Return Value:
  548. Returns the appropriate NTSTATUS
  549. --*/
  550. {
  551. NTSTATUS Status;
  552. OBJECT_ATTRIBUTES ObjectAttributes;
  553. UNICODE_STRING DriverName;
  554. HANDLE RdrHandle = NULL;
  555. IO_STATUS_BLOCK IoStatus;
  556. PNWR_GET_CHALLENGE_REQUEST ChallengeRequest = NULL;
  557. NWR_GET_CHALLENGE_REPLY ChallengeReply;
  558. ULONG ChallengeRequestSize;
  559. //
  560. // Initialize variables
  561. //
  562. RtlInitUnicodeString( &DriverName, DD_NWFS_DEVICE_NAME_U );
  563. InitializeObjectAttributes(
  564. &ObjectAttributes,
  565. &DriverName,
  566. 0,
  567. NULL,
  568. NULL
  569. );
  570. //
  571. // open handle to redirector
  572. //
  573. Status = NtOpenFile(
  574. &RdrHandle,
  575. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  576. &ObjectAttributes,
  577. &IoStatus,
  578. FILE_SHARE_READ,
  579. 0 // open options
  580. );
  581. if (!NT_SUCCESS(Status) ||
  582. !NT_SUCCESS(IoStatus.Status) )
  583. {
  584. return( Status );
  585. }
  586. ChallengeRequestSize = sizeof(NWR_GET_CHALLENGE_REQUEST) +
  587. ((Password != NULL) ? Password->Length : 0) +
  588. ((ServerName != NULL) ? ServerName->Length : 0);
  589. ChallengeRequest = (PNWR_GET_CHALLENGE_REQUEST) RtlAllocateHeap(
  590. RtlProcessHeap(),
  591. 0,
  592. ChallengeRequestSize
  593. );
  594. if (ChallengeRequest == NULL )
  595. {
  596. Status = STATUS_INSUFFICIENT_RESOURCES;
  597. goto Cleanup;
  598. }
  599. //
  600. // Marshall the challenge request structure. Only send servername if
  601. // password has not been specified.
  602. //
  603. ChallengeRequest->ObjectId = ObjectId;
  604. ChallengeRequest->Flags = 0;
  605. //
  606. // If both password and servername are present, use the password.
  607. //
  608. if ((Password != NULL) && (Password->Length != 0))
  609. {
  610. ChallengeRequest->ServerNameorPasswordLength = Password->Length;
  611. RtlCopyMemory(
  612. ChallengeRequest->ServerNameorPassword,
  613. Password->Buffer,
  614. Password->Length
  615. );
  616. ChallengeRequest->Flags = CHALLENGE_FLAGS_PASSWORD;
  617. }
  618. else if ((ServerName != NULL) && (ServerName->Length != 0))
  619. {
  620. ChallengeRequest->ServerNameorPasswordLength = ServerName->Length;
  621. RtlCopyMemory(
  622. ChallengeRequest->ServerNameorPassword,
  623. ServerName->Buffer,
  624. ServerName->Length
  625. );
  626. ChallengeRequest->Flags = CHALLENGE_FLAGS_SERVERNAME;
  627. }
  628. RtlCopyMemory(
  629. ChallengeRequest->Challenge,
  630. Challenge,
  631. 8
  632. );
  633. //
  634. // Issue FS control to redir to get challenge response
  635. //
  636. Status = NtFsControlFile(
  637. RdrHandle,
  638. NULL,
  639. NULL,
  640. NULL,
  641. &IoStatus,
  642. FSCTL_NWR_CHALLENGE,
  643. ChallengeRequest,
  644. ChallengeRequestSize,
  645. &ChallengeReply,
  646. sizeof(ChallengeReply)
  647. );
  648. if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status)) {
  649. goto Cleanup;
  650. }
  651. RtlCopyMemory(
  652. ChallengeResponse,
  653. ChallengeReply.Challenge,
  654. 8
  655. );
  656. if (SessionKey != NULL)
  657. {
  658. RtlCopyMemory(
  659. ChallengeResponse,
  660. ChallengeReply.Challenge,
  661. 8
  662. );
  663. }
  664. Cleanup:
  665. if (RdrHandle != NULL)
  666. {
  667. NtClose(RdrHandle);
  668. }
  669. if (ChallengeRequest != NULL)
  670. {
  671. RtlFreeHeap(
  672. RtlProcessHeap(),
  673. 0,
  674. ChallengeRequest
  675. );
  676. }
  677. return(Status);
  678. }