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.

1110 lines
29 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ApiLogon.c
  5. Abstract:
  6. This module contains individual API handlers for the NetLogon APIs.
  7. SUPPORTED : NetGetDCName, NetLogonEnum, NetServerAuthenticate,
  8. NetServerPasswordSet, NetServerReqChallenge,
  9. NetWkstaUserLogoff, NetWkstaUserLogon.
  10. SEE ALSO : NetAccountDeltas, NetAccountSync - in ApiAcct.c.
  11. Author:
  12. Shanku Niyogi (w-shanku) 04-Apr-1991
  13. Revision History:
  14. --*/
  15. //
  16. // Logon APIs are Unicode only.
  17. //
  18. #ifndef UNICODE
  19. #define UNICODE
  20. #endif
  21. #include "xactsrvp.h"
  22. #include <netlibnt.h>
  23. #include <crypt.h> // must be included before <logonmsv.h>
  24. #include <ntsam.h> // must be included before <logonmsv.h>
  25. #include <logonmsv.h> // must be included before <ssi.h>
  26. #include <ssi.h> // I_NetAccountDeltas and I_NetAccountSync prototypes
  27. //
  28. // Declaration of descriptor strings.
  29. //
  30. STATIC const LPDESC Desc16_user_logon_info_0 = REM16_user_logon_info_0;
  31. STATIC const LPDESC Desc32_user_logon_info_0 = REM32_user_logon_info_0;
  32. STATIC const LPDESC Desc16_user_logon_info_1 = REM16_user_logon_info_1;
  33. STATIC const LPDESC Desc32_user_logon_info_1 = REM32_user_logon_info_1;
  34. STATIC const LPDESC Desc16_user_logon_info_2 = REM16_user_logon_info_2;
  35. STATIC const LPDESC Desc32_user_logon_info_2 = REM32_user_logon_info_2;
  36. STATIC const LPDESC Desc16_user_logoff_info_1 = REM16_user_logoff_info_1;
  37. STATIC const LPDESC Desc32_user_logoff_info_1 = REM32_user_logoff_info_1;
  38. NTSTATUS
  39. XsNetGetDCName (
  40. API_HANDLER_PARAMETERS
  41. )
  42. /*++
  43. Routine Description:
  44. This routine handles a call to NetGetDCName.
  45. Arguments:
  46. API_HANDLER_PARAMETERS - Information about the API call. See
  47. XsTypes.h for details.
  48. Return Value:
  49. NTSTATUS - STATUS_SUCCESS or reason for failure.
  50. --*/
  51. {
  52. NET_API_STATUS status;
  53. PXS_NET_GET_DC_NAME parameters = Parameters;
  54. LPTSTR nativeDomain = NULL; // Native parameters
  55. LPTSTR dcName = NULL;
  56. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  57. try {
  58. //
  59. // Translate parameters, check for errors.
  60. //
  61. XsConvertTextParameter(
  62. nativeDomain,
  63. (LPSTR)XsSmbGetPointer( &parameters->Domain )
  64. );
  65. //
  66. // Make the local call.
  67. //
  68. status = NetGetDCName(
  69. NULL,
  70. nativeDomain,
  71. (LPBYTE *)&dcName
  72. );
  73. if ( !XsApiSuccess( status )) {
  74. IF_DEBUG(ERRORS) {
  75. NetpKdPrint(( "XsNetGetDCName: NetGetDCName failed: %X\n",
  76. status ));
  77. }
  78. goto cleanup;
  79. }
  80. //
  81. // Put string into buffer. Convert from Unicode if necessary.
  82. //
  83. if ( (DWORD)SmbGetUshort( &parameters->BufLen ) <= NetpUnicodeToDBCSLen( dcName )) {
  84. status = NERR_BufTooSmall;
  85. } else {
  86. NetpCopyWStrToStrDBCS( (LPSTR)XsSmbGetPointer( &parameters->Buffer ), dcName );
  87. }
  88. IF_DEBUG(LOGON) {
  89. NetpKdPrint(( "Name is %ws\n", dcName ));
  90. }
  91. cleanup:
  92. ;
  93. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  94. status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  95. }
  96. //
  97. // Set return data count.
  98. //
  99. if ( status == NERR_Success ) {
  100. SmbPutUshort( &parameters->BufLen, (USHORT)( STRLEN( dcName ) + 1 ));
  101. } else {
  102. SmbPutUshort( &parameters->BufLen, 0 );
  103. }
  104. Header->Status = (WORD)status;
  105. NetpMemoryFree( nativeDomain );
  106. NetApiBufferFree( dcName );
  107. return STATUS_SUCCESS;
  108. } // XsNetGetDCName
  109. NTSTATUS
  110. XsNetLogonEnum (
  111. API_HANDLER_PARAMETERS
  112. )
  113. /*++
  114. Routine Description:
  115. This routine handles a call to NetLogonEnum.
  116. Arguments:
  117. API_HANDLER_PARAMETERS - Information about the API call. See
  118. XsTypes.h for details.
  119. Return Value:
  120. NTSTATUS - STATUS_SUCCESS or reason for failure.
  121. --*/
  122. {
  123. NET_API_STATUS status;
  124. PXS_NET_LOGON_ENUM parameters = Parameters;
  125. LPVOID outBuffer= NULL;
  126. DWORD entriesRead = 0;
  127. DWORD totalEntries = 0;
  128. DWORD entriesFilled = 0;
  129. DWORD bytesRequired = 0;
  130. LPDESC nativeStructureDesc;
  131. API_HANDLER_PARAMETERS_REFERENCE;
  132. IF_DEBUG(LOGON) {
  133. NetpKdPrint(( "XsNetLogonEnum: header at %lx, params at %lx, "
  134. "level %ld, buf size %ld\n",
  135. Header, parameters, SmbGetUshort( &parameters->Level ),
  136. SmbGetUshort( &parameters->BufLen )));
  137. }
  138. try {
  139. //
  140. // Check for errors.
  141. //
  142. if (( SmbGetUshort( &parameters->Level ) != 0 )
  143. && ( SmbGetUshort( &parameters->Level ) != 2 )) {
  144. Header->Status = ERROR_INVALID_LEVEL;
  145. goto cleanup;
  146. }
  147. //
  148. // Make the local call.
  149. //
  150. #ifdef LOGON_ENUM_SUPPORTED
  151. status = NetLogonEnum(
  152. NULL,
  153. (DWORD)SmbGetUshort( &parameters->Level ),
  154. (LPBYTE *)&outBuffer,
  155. XsNativeBufferSize( SmbGetUshort( &parameters->BufLen )),
  156. &entriesRead,
  157. &totalEntries,
  158. NULL
  159. );
  160. #else // LOGON_ENUM_SUPPORTED
  161. status = NERR_InvalidAPI;
  162. #endif // LOGON_ENUM_SUPPORTED
  163. if ( !XsApiSuccess( status )) {
  164. IF_DEBUG(API_ERRORS) {
  165. NetpKdPrint(( "XsNetLogonEnum: NetLogonEnum failed: "
  166. "%X\n", status ));
  167. }
  168. Header->Status = (WORD)status;
  169. goto cleanup;
  170. }
  171. IF_DEBUG(LOGON) {
  172. NetpKdPrint(( "XsNetLogonEnum: received %ld entries at %lx\n",
  173. entriesRead, outBuffer ));
  174. }
  175. //
  176. // Use the requested level to determine the format of the
  177. // data structure.
  178. //
  179. switch ( SmbGetUshort( &parameters->Level ) ) {
  180. case 0:
  181. nativeStructureDesc = Desc32_user_logon_info_0;
  182. StructureDesc = Desc16_user_logon_info_0;
  183. break;
  184. case 2:
  185. nativeStructureDesc = Desc32_user_logon_info_2;
  186. StructureDesc = Desc16_user_logon_info_2;
  187. break;
  188. }
  189. //
  190. // Do the actual conversion from the 32-bit structures to 16-bit
  191. // structures.
  192. //
  193. XsFillEnumBuffer(
  194. outBuffer,
  195. entriesRead,
  196. nativeStructureDesc,
  197. (LPVOID)XsSmbGetPointer( &parameters->Buffer ),
  198. (LPVOID)XsSmbGetPointer( &parameters->Buffer ),
  199. SmbGetUshort( &parameters->BufLen ),
  200. StructureDesc,
  201. NULL, // verify function
  202. &bytesRequired,
  203. &entriesFilled,
  204. NULL
  205. );
  206. IF_DEBUG(LOGON) {
  207. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR,"
  208. " Entries %ld of %ld\n",
  209. outBuffer, SmbGetUlong( &parameters->Buffer ),
  210. bytesRequired, entriesFilled, totalEntries ));
  211. }
  212. //
  213. // If all the entries could not be filled, return ERROR_MORE_DATA,
  214. // and return the buffer as is. Otherwise, the data needs to be
  215. // packed so that we don't send too much useless data.
  216. //
  217. if ( entriesFilled < totalEntries ) {
  218. Header->Status = ERROR_MORE_DATA;
  219. } else {
  220. Header->Converter = XsPackReturnData(
  221. (LPVOID)XsSmbGetPointer( &parameters->Buffer ),
  222. SmbGetUshort( &parameters->BufLen ),
  223. StructureDesc,
  224. entriesFilled
  225. );
  226. }
  227. //
  228. // Set up the response parameters.
  229. //
  230. SmbPutUshort( &parameters->EntriesRead, (WORD)entriesFilled );
  231. SmbPutUshort( &parameters->TotalAvail, (WORD)totalEntries );
  232. cleanup:
  233. ;
  234. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  235. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  236. }
  237. NetApiBufferFree( outBuffer );
  238. //
  239. // Determine return buffer size.
  240. //
  241. XsSetDataCount(
  242. &parameters->BufLen,
  243. StructureDesc,
  244. Header->Converter,
  245. entriesFilled,
  246. Header->Status
  247. );
  248. return STATUS_SUCCESS;
  249. } // XsNetLogonEnum
  250. NTSTATUS
  251. XsNetServerAuthenticate (
  252. API_HANDLER_PARAMETERS
  253. )
  254. /*++
  255. Routine Description:
  256. This routine handles a call to NetServerAuthenticate.
  257. Arguments:
  258. API_HANDLER_PARAMETERS - Information about the API call. See
  259. XsTypes.h for details.
  260. Return Value:
  261. NTSTATUS - STATUS_SUCCESS or reason for failure.
  262. --*/
  263. {
  264. PXS_NET_SERVER_AUTHENTICATE parameters = Parameters;
  265. NET_API_STATUS status; // Native parameters
  266. LPTSTR nativeRequestor = NULL;
  267. NETLOGON_CREDENTIAL inCredential = {0};
  268. NETLOGON_CREDENTIAL outCredential = {0};
  269. WCHAR AccountName[MAX_PATH+1];
  270. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  271. try {
  272. //
  273. // Translate parameters, check for errors.
  274. //
  275. XsConvertTextParameter(
  276. nativeRequestor,
  277. (LPSTR)XsSmbGetPointer( &parameters->Requestor )
  278. );
  279. //
  280. // Copy the source credential, and zero out the destination
  281. // credential.
  282. //
  283. RtlCopyMemory(
  284. &inCredential,
  285. (PVOID)XsSmbGetPointer( &parameters->Caller ),
  286. sizeof(NETLOGON_CREDENTIAL)
  287. );
  288. RtlZeroMemory(
  289. &outCredential,
  290. sizeof(NETLOGON_CREDENTIAL)
  291. );
  292. //
  293. // Build the account name.
  294. //
  295. NetpNCopyTStrToWStr( AccountName, nativeRequestor, MAX_PATH );
  296. //
  297. // Make the local call.
  298. //
  299. status = NetpNtStatusToApiStatus(
  300. I_NetServerAuthenticate(
  301. NULL,
  302. AccountName,
  303. UasServerSecureChannel,
  304. nativeRequestor,
  305. &inCredential,
  306. &outCredential
  307. ));
  308. if ( !XsApiSuccess( status )) {
  309. IF_DEBUG(ERRORS) {
  310. NetpKdPrint(( "XsNetServerAuthenticate: I_NetServerAuthenticate "
  311. "failed: %X\n", status ));
  312. }
  313. Header->Status = (WORD)status;
  314. goto cleanup;
  315. }
  316. cleanup:
  317. //
  318. // Set the return credential.
  319. //
  320. RtlCopyMemory(
  321. parameters->Primary,
  322. &outCredential,
  323. sizeof(NETLOGON_CREDENTIAL)
  324. );
  325. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  326. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  327. }
  328. NetpMemoryFree( nativeRequestor );
  329. return STATUS_SUCCESS;
  330. } // XsNetServerAuthenticate
  331. NTSTATUS
  332. XsNetServerPasswordSet (
  333. API_HANDLER_PARAMETERS
  334. )
  335. /*++
  336. Routine Description:
  337. This routine handles a call to NetGetDCName.
  338. Arguments:
  339. API_HANDLER_PARAMETERS - Information about the API call. See
  340. XsTypes.h for details.
  341. Return Value:
  342. NTSTATUS - STATUS_SUCCESS or reason for failure.
  343. --*/
  344. {
  345. PXS_NET_SERVER_PASSWORD_SET parameters = Parameters;
  346. NET_API_STATUS status; // Native parameters
  347. LPTSTR nativeRequestor = NULL;
  348. NETLOGON_AUTHENTICATOR authIn = {0};
  349. NETLOGON_AUTHENTICATOR authOut = {0};
  350. ENCRYPTED_LM_OWF_PASSWORD password;
  351. WCHAR AccountName[MAX_PATH+1];
  352. LPBYTE structure = NULL; // Conversion variables
  353. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  354. try {
  355. //
  356. // Translate parameters, check for errors.
  357. //
  358. XsConvertTextParameter(
  359. nativeRequestor,
  360. (LPSTR)XsSmbGetPointer( &parameters->Requestor )
  361. );
  362. //
  363. // Copy the source authenticator and password, and zero out the
  364. // destination authenticator.
  365. //
  366. structure = (LPBYTE)XsSmbGetPointer( &parameters->Authenticator );
  367. RtlCopyMemory(
  368. &authIn.Credential,
  369. structure,
  370. sizeof(NETLOGON_CREDENTIAL)
  371. );
  372. structure += sizeof(NETLOGON_CREDENTIAL);
  373. authIn.timestamp = SmbGetUlong( structure );
  374. RtlCopyMemory(
  375. &password,
  376. parameters->Password,
  377. sizeof(ENCRYPTED_LM_OWF_PASSWORD)
  378. );
  379. RtlZeroMemory(
  380. &authOut,
  381. sizeof(NETLOGON_CREDENTIAL)
  382. );
  383. //
  384. // Build the account name.
  385. //
  386. if( STRLEN( nativeRequestor ) >= MAX_PATH )
  387. {
  388. Header->Status = NERR_PasswordTooShort;
  389. goto cleanup;
  390. }
  391. // Make sure its NULL terminated
  392. AccountName[MAX_PATH] = L'\0';
  393. NetpNCopyTStrToWStr( AccountName, nativeRequestor, MAX_PATH );
  394. //
  395. // Make the local call.
  396. //
  397. status = NetpNtStatusToApiStatus(
  398. I_NetServerPasswordSet(
  399. NULL,
  400. AccountName,
  401. UasServerSecureChannel,
  402. nativeRequestor,
  403. &authIn,
  404. &authOut,
  405. &password
  406. ));
  407. if ( !XsApiSuccess( status )) {
  408. IF_DEBUG(ERRORS) {
  409. NetpKdPrint(( "XsNetServerPasswordSet: "
  410. "I_NetServerPasswordSet failed: %X\n",
  411. status ));
  412. }
  413. //
  414. // !!! When protocol level is available in the header information,
  415. // we can check it. Right now, we ignore this code.
  416. //
  417. // For clients older than LanMan 2.1, return a different error code.
  418. // LANMAN 2.1 Protocol Level is 6.
  419. //
  420. #if 0
  421. if ( status == NERR_TimeDiffAtDC && Header->ProtocolLevel < 6 ) {
  422. status = NERR_SyncRequired;
  423. }
  424. #endif
  425. Header->Status = (WORD)status;
  426. goto cleanup;
  427. }
  428. cleanup:
  429. //
  430. // Fill in 16 bit return structures.
  431. //
  432. structure = parameters->RetAuth;
  433. RtlCopyMemory(
  434. structure,
  435. &authOut.Credential,
  436. sizeof(NETLOGON_CREDENTIAL)
  437. );
  438. structure += sizeof(NETLOGON_CREDENTIAL);
  439. SmbPutUlong( (LPDWORD)structure, authOut.timestamp );
  440. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  441. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  442. }
  443. NetpMemoryFree( nativeRequestor );
  444. return STATUS_SUCCESS;
  445. } // XsNetServerPasswordSet
  446. NTSTATUS
  447. XsNetServerReqChallenge (
  448. API_HANDLER_PARAMETERS
  449. )
  450. /*++
  451. Routine Description:
  452. This routine handles a call to NetGetDCName.
  453. Arguments:
  454. API_HANDLER_PARAMETERS - Information about the API call. See
  455. XsTypes.h for details.
  456. Return Value:
  457. NTSTATUS - STATUS_SUCCESS or reason for failure.
  458. --*/
  459. {
  460. PXS_NET_SERVER_REQ_CHALLENGE parameters = Parameters;
  461. NET_API_STATUS status; // Native parameters
  462. LPTSTR nativeRequestor = NULL;
  463. NETLOGON_CREDENTIAL inChallenge = {0};
  464. NETLOGON_CREDENTIAL outChallenge = {0};
  465. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  466. try {
  467. //
  468. // Translate parameters, check for errors.
  469. //
  470. XsConvertTextParameter(
  471. nativeRequestor,
  472. (LPSTR)XsSmbGetPointer( &parameters->Requestor )
  473. );
  474. //
  475. // Copy the source challenge, and zero out the destination
  476. // challenge.
  477. //
  478. RtlCopyMemory(
  479. &inChallenge,
  480. (PVOID)XsSmbGetPointer( &parameters->Caller ),
  481. sizeof(NETLOGON_CREDENTIAL)
  482. );
  483. RtlZeroMemory(
  484. &outChallenge,
  485. sizeof(NETLOGON_CREDENTIAL)
  486. );
  487. //
  488. // Make the local call.
  489. //
  490. status = NetpNtStatusToApiStatus(
  491. I_NetServerReqChallenge(
  492. NULL,
  493. nativeRequestor,
  494. &inChallenge,
  495. &outChallenge
  496. ));
  497. if ( !XsApiSuccess( status )) {
  498. IF_DEBUG(ERRORS) {
  499. NetpKdPrint(( "XsNetServerReqChallenge: "
  500. "I_NetServerReqChallenge failed: %X\n",
  501. status ));
  502. }
  503. Header->Status = (WORD)status;
  504. goto cleanup;
  505. }
  506. cleanup:
  507. //
  508. // Set the return credential.
  509. //
  510. RtlCopyMemory(
  511. parameters->Primary,
  512. &outChallenge,
  513. sizeof(NETLOGON_CREDENTIAL)
  514. );
  515. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  516. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  517. }
  518. NetpMemoryFree( nativeRequestor );
  519. return STATUS_SUCCESS;
  520. } // XsNetServerReqChallenge
  521. NTSTATUS
  522. XsNetWkstaUserLogoff (
  523. API_HANDLER_PARAMETERS
  524. )
  525. /*++
  526. Routine Description:
  527. This temporary routine just returns STATUS_NOT_IMPLEMENTED.
  528. Arguments:
  529. API_HANDLER_PARAMETERS - information about the API call. See
  530. XsTypes.h for details.
  531. Return Value:
  532. NTSTATUS - STATUS_SUCCESS or reason for failure.
  533. --*/
  534. {
  535. NET_API_STATUS status;
  536. PXS_NET_WKSTA_USER_LOGOFF parameters = Parameters;
  537. LPWSTR machineName = NULL; // Native parameters
  538. LPWSTR userName = NULL;
  539. NETLOGON_LOGOFF_UAS_INFORMATION buffer;
  540. LPBYTE stringLocation = NULL; // Conversion variables
  541. DWORD bytesRequired = 0;
  542. PWKSTA_16_USER_LOGOFF_REQUEST_1 usrLogoffReq =
  543. (PWKSTA_16_USER_LOGOFF_REQUEST_1)parameters->InBuf;
  544. PUSER_16_LOGOFF_INFO_1 logoffInfo;
  545. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  546. try {
  547. //
  548. // Translate parameters, check for errors.
  549. //
  550. XsConvertUnicodeTextParameter(
  551. userName,
  552. (LPSTR)( usrLogoffReq->wlreq1_name )
  553. );
  554. XsConvertUnicodeTextParameter(
  555. machineName,
  556. (LPSTR)( usrLogoffReq->wlreq1_workstation )
  557. );
  558. if ( SmbGetUshort( &parameters->Level ) != 1 ) {
  559. Header->Status = ERROR_INVALID_LEVEL;
  560. goto cleanup;
  561. }
  562. //
  563. // Make sure the workstation name in the logon request is the
  564. // name of the workstation from which the request came.
  565. //
  566. if ( wcscmp( machineName, Header->ClientMachineName ) ) {
  567. Header->Status = (WORD)ERROR_ACCESS_DENIED;
  568. goto cleanup;
  569. }
  570. //
  571. // Make the local call.
  572. //
  573. status = I_NetLogonUasLogoff(
  574. userName,
  575. machineName,
  576. &buffer
  577. );
  578. if ( !XsApiSuccess(status)) {
  579. IF_DEBUG(ERRORS) {
  580. NetpKdPrint(( "XsNetWkstaUserLogoff: I_NetLogonUasLogoff "
  581. "failed: %X\n", status ));
  582. }
  583. Header->Status = (WORD)status;
  584. goto cleanup;
  585. }
  586. //
  587. // Convert the structure returned by the 32-bit call to a 16-bit
  588. // structure. The last possible location for variable data is
  589. // calculated from buffer location and length.
  590. //
  591. stringLocation = (LPBYTE)( XsSmbGetPointer( &parameters->OutBuf )
  592. + SmbGetUshort( &parameters->OutBufLen ) );
  593. status = RapConvertSingleEntry(
  594. (LPBYTE)&buffer,
  595. Desc32_user_logoff_info_1,
  596. FALSE,
  597. (LPBYTE)XsSmbGetPointer( &parameters->OutBuf ),
  598. (LPBYTE)XsSmbGetPointer( &parameters->OutBuf ),
  599. Desc16_user_logoff_info_1,
  600. TRUE,
  601. &stringLocation,
  602. &bytesRequired,
  603. Response,
  604. NativeToRap
  605. );
  606. if ( status != NERR_Success ) {
  607. IF_DEBUG(ERRORS) {
  608. NetpKdPrint(( "XsNetWkstaUserLogoff: RapConvertSingleEntry "
  609. "failed: %X\n", status ));
  610. }
  611. Header->Status = NERR_InternalError;
  612. goto cleanup;
  613. }
  614. IF_DEBUG(LOGON) {
  615. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
  616. &buffer, SmbGetUlong( &parameters->OutBuf ),
  617. bytesRequired ));
  618. }
  619. //
  620. // Determine return code based on the size of the buffer.
  621. // The user_logoff_info_1 structure has no variable data to pack,
  622. // but we do need to fill in the code field of the return structure.
  623. //
  624. if ( !XsCheckBufferSize(
  625. SmbGetUshort( &parameters->OutBufLen ),
  626. Desc16_user_logoff_info_1,
  627. FALSE // not in native format
  628. )) {
  629. IF_DEBUG(ERRORS) {
  630. NetpKdPrint(( "XsNetWkstaUserLogoff: Buffer too small.\n" ));
  631. }
  632. Header->Status = NERR_BufTooSmall;
  633. } else if ( bytesRequired > (DWORD)SmbGetUshort( &parameters->OutBufLen )) {
  634. IF_DEBUG(ERRORS) {
  635. NetpKdPrint(( "XsNetWkstaUserLogoff: More data available.\n" ));
  636. }
  637. Header->Status = ERROR_MORE_DATA;
  638. }
  639. if ( SmbGetUshort( &parameters->OutBufLen ) > sizeof(WORD)) {
  640. logoffInfo = (PUSER_16_LOGOFF_INFO_1)XsSmbGetPointer(
  641. &parameters->OutBuf );
  642. SmbPutUshort( &logoffInfo->usrlogf1_code, VALID_LOGOFF );
  643. }
  644. //
  645. // Set up the response parameters.
  646. //
  647. SmbPutUshort( &parameters->TotalAvail, (WORD)bytesRequired );
  648. cleanup:
  649. ;
  650. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  651. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  652. }
  653. NetpMemoryFree( userName );
  654. NetpMemoryFree( machineName );
  655. //
  656. // Determine return buffer size.
  657. //
  658. XsSetDataCount(
  659. &parameters->OutBufLen,
  660. Desc16_user_logoff_info_1,
  661. Header->Converter,
  662. 1,
  663. Header->Status
  664. );
  665. return STATUS_SUCCESS;
  666. } // XsNetWkstaUserLogoff
  667. NTSTATUS
  668. XsNetWkstaUserLogon (
  669. API_HANDLER_PARAMETERS
  670. )
  671. /*++
  672. Routine Description:
  673. This routine handles a call to NetWkstaUserLogon.
  674. Arguments:
  675. API_HANDLER_PARAMETERS - information about the API call. See
  676. XsTypes.h for details.
  677. Return Value:
  678. NTSTATUS - STATUS_SUCCESS or reason for failure.
  679. --*/
  680. {
  681. NET_API_STATUS status;
  682. PXS_NET_WKSTA_USER_LOGON parameters = Parameters;
  683. LPWSTR machineName = NULL; // Native parameters
  684. LPWSTR userName = NULL;
  685. PNETLOGON_VALIDATION_UAS_INFO buffer = NULL;
  686. LPBYTE stringLocation = NULL; // Conversion variables
  687. DWORD bytesRequired = 0;
  688. PWKSTA_16_USER_LOGON_REQUEST_1 usrLogonReq =
  689. (PWKSTA_16_USER_LOGON_REQUEST_1)parameters->InBuf;
  690. PUSER_16_LOGON_INFO_1 logonInfo;
  691. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  692. try {
  693. //
  694. // Translate parameters, check for errors.
  695. //
  696. XsConvertUnicodeTextParameter(
  697. userName,
  698. (LPSTR)( usrLogonReq->wlreq1_name )
  699. );
  700. XsConvertUnicodeTextParameter(
  701. machineName,
  702. (LPSTR)( usrLogonReq->wlreq1_workstation )
  703. );
  704. if ( SmbGetUshort( &parameters->Level ) != 1 ) {
  705. Header->Status = ERROR_INVALID_LEVEL;
  706. goto cleanup;
  707. }
  708. //
  709. // Make sure the workstation name in the logon request is the
  710. // name of the workstation from which the request came.
  711. //
  712. if ( wcscmp( machineName, Header->ClientMachineName ) ) {
  713. Header->Status = (WORD)ERROR_ACCESS_DENIED;
  714. goto cleanup;
  715. }
  716. //
  717. // Make the local call.
  718. //
  719. status = I_NetLogonUasLogon(
  720. userName,
  721. machineName,
  722. &buffer
  723. );
  724. if ( !XsApiSuccess ( status )) {
  725. IF_DEBUG(API_ERRORS) {
  726. NetpKdPrint(( "XsNetWkstaUserLogon: I_NetLogonUasLogon failed: "
  727. "%X\n", status));
  728. }
  729. Header->Status = (WORD) status;
  730. goto cleanup;
  731. }
  732. //
  733. // Convert the structure returned by the 32-bit call to a 16-bit
  734. // structure. The last possible location for variable data is
  735. // calculated from buffer location and length.
  736. //
  737. stringLocation = (LPBYTE)( XsSmbGetPointer( &parameters->OutBuf )
  738. + SmbGetUshort( &parameters->OutBufLen ) );
  739. status = RapConvertSingleEntry(
  740. (LPBYTE)buffer,
  741. Desc32_user_logon_info_1,
  742. FALSE,
  743. (LPBYTE)XsSmbGetPointer( &parameters->OutBuf ),
  744. (LPBYTE)XsSmbGetPointer( &parameters->OutBuf ),
  745. Desc16_user_logon_info_1,
  746. TRUE,
  747. &stringLocation,
  748. &bytesRequired,
  749. Response,
  750. NativeToRap
  751. );
  752. if ( status != NERR_Success ) {
  753. IF_DEBUG(ERRORS) {
  754. NetpKdPrint(( "XsNetWkstaUserLogon: RapConvertSingleEntry "
  755. "failed: %X\n", status ));
  756. }
  757. Header->Status = NERR_InternalError;
  758. goto cleanup;
  759. }
  760. IF_DEBUG(LOGON) {
  761. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
  762. buffer, SmbGetUlong( &parameters->OutBuf ),
  763. bytesRequired ));
  764. }
  765. //
  766. // Determine return code based on the size of the buffer.
  767. // The user_logoff_info_1 structure has no variable data to pack,
  768. // but we do need to fill in the code field of the return structure.
  769. //
  770. if ( !XsCheckBufferSize(
  771. SmbGetUshort( &parameters->OutBufLen ),
  772. Desc16_user_logon_info_1,
  773. FALSE // not in native format
  774. )) {
  775. IF_DEBUG(ERRORS) {
  776. NetpKdPrint(( "XsNetWkstaUserLogon: Buffer too small.\n" ));
  777. }
  778. Header->Status = NERR_BufTooSmall;
  779. } else if ( bytesRequired > (DWORD)SmbGetUshort( &parameters->OutBufLen )) {
  780. IF_DEBUG(ERRORS) {
  781. NetpKdPrint(( "XsNetWkstaUserLogoff: More data available.\n" ));
  782. }
  783. Header->Status = ERROR_MORE_DATA;
  784. } else {
  785. //
  786. // Pack the response data.
  787. //
  788. Header->Converter = XsPackReturnData(
  789. (LPVOID)XsSmbGetPointer( &parameters->OutBuf ),
  790. SmbGetUshort( &parameters->OutBufLen ),
  791. Desc16_user_logon_info_1,
  792. 1
  793. );
  794. }
  795. if ( SmbGetUshort( &parameters->OutBufLen ) > sizeof(WORD)) {
  796. logonInfo = (PUSER_16_LOGON_INFO_1)XsSmbGetPointer(
  797. &parameters->OutBuf );
  798. SmbPutUshort( &logonInfo->usrlog1_code, VALIDATED_LOGON );
  799. }
  800. //
  801. // Set up the response parameters.
  802. //
  803. SmbPutUshort( &parameters->TotalAvail, (WORD)bytesRequired );
  804. cleanup:
  805. ;
  806. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  807. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  808. }
  809. NetpMemoryFree( userName );
  810. NetpMemoryFree( machineName );
  811. if ( buffer != NULL ) {
  812. NetApiBufferFree( buffer );
  813. }
  814. //
  815. // Determine return buffer size.
  816. //
  817. XsSetDataCount(
  818. &parameters->OutBufLen,
  819. Desc16_user_logon_info_1,
  820. Header->Converter,
  821. 1,
  822. Header->Status
  823. );
  824. return STATUS_SUCCESS;
  825. } // XsNetWkstaUserLogon