Source code of Windows XP (NT5)
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.

1137 lines
31 KiB

  1. /*++
  2. Copyright (c) 1987-1994 Microsoft Corporation
  3. Module Name:
  4. subauth.c
  5. Abstract:
  6. Interface to SubAuthentication Package.
  7. Author:
  8. Cliff Van Dyke (cliffv) 23-May-1994
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. Chandana Surlu 21-Jul-96 Stolen from \\kernel\razzle3\src\security\msv1_0\subauth.c
  15. --*/
  16. #include <global.h>
  17. #include "msp.h"
  18. #include "nlp.h"
  19. #include <winreg.h>
  20. #include <kerberos.h>
  21. //
  22. // Prototype for subauthentication routines.
  23. //
  24. // the pre NT 5.0 Subauth routine
  25. typedef NTSTATUS
  26. (*PSUBAUTHENTICATION_ROUTINE)(
  27. IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
  28. IN PVOID LogonInformation,
  29. IN ULONG Flags,
  30. IN PUSER_ALL_INFORMATION UserAll,
  31. OUT PULONG WhichFields,
  32. OUT PULONG UserFlags,
  33. OUT PBOOLEAN Authoritative,
  34. OUT PLARGE_INTEGER LogoffTime,
  35. OUT PLARGE_INTEGER KickoffTime
  36. );
  37. // the NT 5.0 Subauth routine
  38. typedef NTSTATUS
  39. (*PSUBAUTHENTICATION_ROUTINEEX)(
  40. IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
  41. IN PVOID LogonInformation,
  42. IN ULONG Flags,
  43. IN PUSER_ALL_INFORMATION UserAll,
  44. IN SAM_HANDLE UserHandle,
  45. IN OUT PMSV1_0_VALIDATION_INFO ValidationInfo,
  46. OUT PULONG ActionsPerfomed
  47. );
  48. // the NT 5.0 Generic Subauth routine
  49. typedef NTSTATUS
  50. (*PSUBAUTHENTICATION_ROUTINEGENERIC)(
  51. IN PVOID SubmitBuffer,
  52. IN ULONG SubmitBufferLength,
  53. OUT PULONG ReturnBufferLength,
  54. OUT PVOID *ReturnBuffer
  55. );
  56. typedef enum _SUBAUTH_TYPE {
  57. SubAuth = 1, // Pre NT 5.0 subAuth called using LogonUser
  58. SubAuthEx, // NT 5.0 subAuth called during LogonUser
  59. SubAuthGeneric // NT 5.0 subAuth called during LaCallAuthenticationPackage
  60. } SUBAUTH_TYPE;
  61. //
  62. // Structure describing a loaded SubAuthentication DLL.
  63. //
  64. typedef struct _SUBAUTHENTICATION_DLL {
  65. LIST_ENTRY Next;
  66. ULONG DllNumber;
  67. PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine;
  68. PSUBAUTHENTICATION_ROUTINEEX SubAuthenticationRoutineEx;
  69. PSUBAUTHENTICATION_ROUTINEGENERIC SubAuthenticationRoutineGeneric;
  70. } SUBAUTHENTICATION_DLL, *PSUBAUTHENTICATION_DLL;
  71. //
  72. // Global list of all loaded subauthentication DLLs
  73. //
  74. LIST_ENTRY SubAuthenticationDlls;
  75. RTL_RESOURCE SubAuthenticationCritSect;
  76. VOID
  77. Msv1_0SubAuthenticationInitialization(
  78. VOID
  79. )
  80. /*++
  81. Routine Description:
  82. Initialization routine for this source file.
  83. Arguments:
  84. None.
  85. Return Value:
  86. None.
  87. --*/
  88. {
  89. RtlInitializeResource( &SubAuthenticationCritSect );
  90. InitializeListHead( &SubAuthenticationDlls );
  91. }
  92. PSUBAUTHENTICATION_DLL
  93. ReferenceSubAuth (
  94. IN ULONG DllNumber,
  95. OUT PNTSTATUS SubStatus)
  96. {
  97. LONG RegStatus;
  98. PSUBAUTHENTICATION_DLL SubAuthenticationDll = NULL;
  99. HKEY ParmHandle = NULL;
  100. HINSTANCE DllHandle = NULL;
  101. CHAR ValueName[sizeof(MSV1_0_SUBAUTHENTICATION_VALUE)+3];
  102. CHAR DllName[MAXIMUM_FILENAME_LENGTH+1];
  103. DWORD DllNameSize;
  104. DWORD DllNameType;
  105. PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine = NULL;
  106. PSUBAUTHENTICATION_ROUTINEEX SubAuthenticationRoutineEx = NULL;
  107. PSUBAUTHENTICATION_ROUTINEGENERIC SubAuthenticationRoutineGeneric = NULL;
  108. PLIST_ENTRY ListEntry;
  109. *SubStatus = STATUS_SUCCESS;
  110. DllName[0] = 0;
  111. // See if the SubAuthentication Dll is already loaded.
  112. //
  113. RtlAcquireResourceShared(&SubAuthenticationCritSect, TRUE);
  114. for ( ListEntry = SubAuthenticationDlls.Flink ;
  115. ListEntry != &SubAuthenticationDlls ;
  116. ListEntry = ListEntry->Flink) {
  117. SubAuthenticationDll = CONTAINING_RECORD( ListEntry,
  118. SUBAUTHENTICATION_DLL,
  119. Next );
  120. if ( SubAuthenticationDll->DllNumber == DllNumber ) {
  121. break;
  122. }
  123. SubAuthenticationDll = NULL;
  124. }
  125. RtlReleaseResource(&SubAuthenticationCritSect);
  126. //
  127. // If the Dll is not already loaded,
  128. // load it.
  129. //
  130. if ( SubAuthenticationDll != NULL ) {
  131. goto Cleanup;
  132. }
  133. //
  134. // Build the name of the registry value.
  135. //
  136. RtlCopyMemory( ValueName,
  137. MSV1_0_SUBAUTHENTICATION_VALUE,
  138. sizeof(MSV1_0_SUBAUTHENTICATION_VALUE) );
  139. *SubStatus = RtlIntegerToChar(
  140. DllNumber & KERB_SUBAUTHENTICATION_MASK,
  141. 10, // Base
  142. 4, // Length of buffer
  143. &ValueName[sizeof(MSV1_0_SUBAUTHENTICATION_VALUE)-1] );
  144. if ( !NT_SUCCESS(*SubStatus) ) {
  145. goto Cleanup;
  146. }
  147. //
  148. // Open the MSV1_0_SUBAUTHENTICATION_KEY registry key.
  149. //
  150. if ((DllNumber & KERB_SUBAUTHENTICATION_FLAG) == 0) {
  151. RegStatus = RegOpenKeyExA(
  152. HKEY_LOCAL_MACHINE,
  153. MSV1_0_SUBAUTHENTICATION_KEY,
  154. 0, //Reserved
  155. KEY_QUERY_VALUE,
  156. &ParmHandle );
  157. } else {
  158. RegStatus = RegOpenKeyExA(
  159. HKEY_LOCAL_MACHINE,
  160. KERB_SUBAUTHENTICATION_KEY,
  161. 0, //Reserved
  162. KEY_QUERY_VALUE,
  163. &ParmHandle );
  164. }
  165. if ( RegStatus != ERROR_SUCCESS ) {
  166. SspPrint((SSP_MISC, "Cannot open registry key %s %ld.\n",
  167. MSV1_0_SUBAUTHENTICATION_KEY,
  168. RegStatus ));
  169. }
  170. else
  171. {
  172. //
  173. // Get the registry value.
  174. //
  175. DllNameSize = sizeof(DllName);
  176. RegStatus = RegQueryValueExA(
  177. ParmHandle,
  178. ValueName,
  179. NULL, // Reserved
  180. &DllNameType,
  181. DllName,
  182. &DllNameSize );
  183. if ( RegStatus == ERROR_SUCCESS ) {
  184. if ( DllNameType != REG_SZ ) {
  185. SspPrint((SSP_MISC, "Registry value %s isn't REG_SZ.\n",
  186. ValueName ));
  187. *SubStatus = STATUS_DLL_NOT_FOUND;
  188. goto Cleanup;
  189. }
  190. //
  191. // Load the DLL
  192. //
  193. DllHandle = LoadLibraryA( DllName );
  194. if ( DllHandle == NULL ) {
  195. SspPrint((SSP_MISC, "MSV1_0: Cannot load dll %s %ld.\n",
  196. DllName,
  197. GetLastError() ));
  198. *SubStatus = STATUS_DLL_NOT_FOUND;
  199. goto Cleanup;
  200. }
  201. //
  202. // Find the SubAuthenticationRoutine. For packages other than
  203. // zero, this will be Msv1_0SubauthenticationRoutine. For packge
  204. // zero it will be Msv1_0SubauthenticationFilter.
  205. //
  206. if ((DllNumber & KERB_SUBAUTHENTICATION_MASK) == 0)
  207. {
  208. SubAuthenticationRoutine = (PSUBAUTHENTICATION_ROUTINE)
  209. GetProcAddress(DllHandle, "Msv1_0SubAuthenticationFilter");
  210. }
  211. else
  212. {
  213. SubAuthenticationRoutine = (PSUBAUTHENTICATION_ROUTINE)
  214. GetProcAddress(DllHandle, "Msv1_0SubAuthenticationRoutine");
  215. }
  216. //
  217. // Find the SubAuthenticationRoutine
  218. //
  219. SubAuthenticationRoutineEx = (PSUBAUTHENTICATION_ROUTINEEX)
  220. GetProcAddress(DllHandle, "Msv1_0SubAuthenticationRoutineEx");
  221. //
  222. // Find the SubAuthenticationRoutineGeneric
  223. //
  224. SubAuthenticationRoutineGeneric = (PSUBAUTHENTICATION_ROUTINEGENERIC)
  225. GetProcAddress(DllHandle, "Msv1_0SubAuthenticationRoutineGeneric");
  226. }
  227. }
  228. //
  229. // If we didn't find the DLL or any routines, bail out now.
  230. //
  231. if ((DllHandle == NULL) ||
  232. ((SubAuthenticationRoutine == NULL) &&
  233. (SubAuthenticationRoutineEx == NULL) &&
  234. (SubAuthenticationRoutineGeneric == NULL))) {
  235. SspPrint((SSP_MISC, "Cannot find any of the subauth entry points in %s %ld.\n",
  236. DllName,
  237. GetLastError() ));
  238. *SubStatus = STATUS_PROCEDURE_NOT_FOUND;
  239. goto Cleanup;
  240. }
  241. //
  242. // Cache the address of the procedure.
  243. //
  244. SubAuthenticationDll =
  245. I_NtLmAllocate(sizeof(SUBAUTHENTICATION_DLL));
  246. if ( SubAuthenticationDll == NULL ) {
  247. *SubStatus = STATUS_NO_MEMORY;
  248. goto Cleanup;
  249. }
  250. SubAuthenticationDll->DllNumber = DllNumber;
  251. SubAuthenticationDll->SubAuthenticationRoutine = SubAuthenticationRoutine;
  252. SubAuthenticationDll->SubAuthenticationRoutineEx = SubAuthenticationRoutineEx;
  253. SubAuthenticationDll->SubAuthenticationRoutineGeneric = SubAuthenticationRoutineGeneric;
  254. RtlAcquireResourceExclusive(&SubAuthenticationCritSect, TRUE);
  255. InsertHeadList( &SubAuthenticationDlls, &SubAuthenticationDll->Next );
  256. RtlReleaseResource(&SubAuthenticationCritSect);
  257. DllHandle = NULL;
  258. //
  259. // Cleanup up before returning.
  260. //
  261. Cleanup:
  262. if ( ParmHandle != NULL ) {
  263. RegCloseKey( ParmHandle );
  264. }
  265. if ( !NT_SUCCESS( *SubStatus) ) {
  266. if ( DllHandle != NULL ) {
  267. FreeLibrary( DllHandle );
  268. }
  269. }
  270. return SubAuthenticationDll;
  271. }
  272. BOOLEAN
  273. Msv1_0SubAuthenticationPresent(
  274. IN ULONG DllNumber
  275. )
  276. /*++
  277. Routine Description:
  278. Returns TRUE if there is a subauthentication package with the given number
  279. Arguments:
  280. DllNumber - the number of the DLL to check
  281. Return Value:
  282. TRUE if there is a subauthentication DLL, otherwise FALSE.
  283. --*/
  284. {
  285. NTSTATUS SubStatus;
  286. BOOLEAN Present;
  287. if(ReferenceSubAuth( DllNumber, &SubStatus) != NULL) {
  288. Present = TRUE;
  289. } else {
  290. Present = FALSE;
  291. }
  292. return Present;
  293. }
  294. NTSTATUS
  295. Msv1_0SubAuthenticationRoutineZero(
  296. IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
  297. IN PVOID LogonInformation,
  298. IN ULONG Flags,
  299. IN PUSER_ALL_INFORMATION UserAll,
  300. OUT PULONG WhichFields,
  301. OUT PULONG UserFlags,
  302. OUT PBOOLEAN Authoritative,
  303. OUT PLARGE_INTEGER LogoffTime,
  304. OUT PLARGE_INTEGER KickoffTime
  305. )
  306. {
  307. PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
  308. ULONG DllNumber;
  309. LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
  310. DllNumber = LogonInfo->ParameterControl >> MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
  311. if( DllNumber != 0 ) {
  312. return STATUS_SUCCESS;
  313. }
  314. return Msv1_0SubAuthenticationRoutine(
  315. LogonLevel,
  316. LogonInformation,
  317. Flags,
  318. UserAll,
  319. WhichFields,
  320. UserFlags,
  321. Authoritative,
  322. LogoffTime,
  323. KickoffTime
  324. );
  325. }
  326. NTSTATUS
  327. Msv1_0SubAuthenticationRoutine(
  328. IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
  329. IN PVOID LogonInformation,
  330. IN ULONG Flags,
  331. IN PUSER_ALL_INFORMATION UserAll,
  332. OUT PULONG WhichFields,
  333. OUT PULONG UserFlags,
  334. OUT PBOOLEAN Authoritative,
  335. OUT PLARGE_INTEGER LogoffTime,
  336. OUT PLARGE_INTEGER KickoffTime
  337. )
  338. /*++
  339. Routine Description:
  340. The subauthentication routine does client/server specific authentication
  341. of a user. This stub routine loads the appropriate subauthentication
  342. package DLL and calls out to that DLL to do the actuall validation.
  343. Arguments:
  344. LogonLevel -- Specifies the level of information given in
  345. LogonInformation.
  346. LogonInformation -- Specifies the description for the user
  347. logging on. The LogonDomainName field should be ignored.
  348. Flags - Flags describing the circumstances of the logon.
  349. MSV1_0_PASSTHRU -- This is a PassThru authenication. (i.e., the
  350. user isn't connecting to this machine.)
  351. MSV1_0_GUEST_LOGON -- This is a retry of the logon using the GUEST
  352. user account.
  353. UserAll -- The description of the user as returned from SAM.
  354. WhichFields -- Returns which fields from UserAllInfo are to be written
  355. back to SAM. The fields will only be written if MSV returns success
  356. to it's caller. Only the following bits are valid.
  357. USER_ALL_PARAMETERS - Write UserAllInfo->Parameters back to SAM. If
  358. the size of the buffer is changed, Msv1_0SubAuthenticationRoutine
  359. must delete the old buffer using MIDL_user_free() and reallocate the
  360. buffer using MIDL_user_allocate().
  361. UserFlags -- Returns UserFlags to be returned from LsaLogonUser in the
  362. LogonProfile. The following bits are currently defined:
  363. LOGON_GUEST -- This was a guest logon
  364. LOGON_NOENCRYPTION -- The caller didn't specify encrypted credentials
  365. LOGON_GRACE_LOGON -- The caller's password has expired but logon
  366. was allowed during a grace period following the expiration.
  367. SubAuthentication packages should restrict themselves to returning
  368. bits in the high order byte of UserFlags. However, this convention
  369. isn't enforced giving the SubAuthentication package more flexibility.
  370. Authoritative -- Returns whether the status returned is an
  371. authoritative status which should be returned to the original
  372. caller. If not, this logon request may be tried again on another
  373. domain controller. This parameter is returned regardless of the
  374. status code.
  375. LogoffTime - Receives the time at which the user should logoff the
  376. system. This time is specified as a GMT relative NT system time.
  377. KickoffTime - Receives the time at which the user should be kicked
  378. off the system. This time is specified as a GMT relative NT system
  379. time. Specify, a full scale positive number if the user isn't to
  380. be kicked off.
  381. Return Value:
  382. STATUS_SUCCESS: if there was no error.
  383. STATUS_NO_SUCH_USER: The specified user has no account.
  384. STATUS_WRONG_PASSWORD: The password was invalid.
  385. STATUS_INVALID_INFO_CLASS: LogonLevel is invalid.
  386. STATUS_ACCOUNT_LOCKED_OUT: The account is locked out
  387. STATUS_ACCOUNT_DISABLED: The account is disabled
  388. STATUS_ACCOUNT_EXPIRED: The account has expired.
  389. STATUS_PASSWORD_MUST_CHANGE: Account is marked as Password must change
  390. on next logon.
  391. STATUS_PASSWORD_EXPIRED: The Password is expired.
  392. STATUS_INVALID_LOGON_HOURS - The user is not authorized to logon at
  393. this time.
  394. STATUS_INVALID_WORKSTATION - The user is not authorized to logon to
  395. the specified workstation.
  396. --*/
  397. {
  398. NTSTATUS Status;
  399. NTSTATUS SubStatus;
  400. ULONG DllNumber;
  401. PSUBAUTHENTICATION_DLL SubAuthenticationDll;
  402. PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine;
  403. PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
  404. //
  405. // Initialization
  406. //
  407. LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
  408. DllNumber = LogonInfo->ParameterControl >> MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
  409. *Authoritative = TRUE;
  410. //
  411. // Find the SubAuthentication Dll.
  412. //
  413. SubAuthenticationDll = ReferenceSubAuth ( DllNumber, &SubStatus);
  414. //
  415. // If this was package zero and we didn't find it, remember it for
  416. // next time.
  417. //
  418. if ( (DllNumber == 0) && (SubAuthenticationDll == NULL) ) {
  419. NlpSubAuthZeroExists = FALSE;
  420. Status = STATUS_SUCCESS;
  421. goto Cleanup;
  422. }
  423. if (SubStatus != STATUS_SUCCESS)
  424. {
  425. SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
  426. Status = SubStatus;
  427. goto Cleanup;
  428. }
  429. //
  430. // Leave the crit sect while calling the DLL
  431. //
  432. SubAuthenticationRoutine = SubAuthenticationDll->SubAuthenticationRoutine;
  433. if (SubAuthenticationRoutine == NULL)
  434. {
  435. if( DllNumber == 0 ) {
  436. //
  437. // If this was package zero and we didn't find it, remember it for
  438. // next time.
  439. //
  440. NlpSubAuthZeroExists = FALSE;
  441. Status = STATUS_SUCCESS;
  442. } else {
  443. Status = STATUS_PROCEDURE_NOT_FOUND;
  444. }
  445. goto Cleanup;
  446. }
  447. //
  448. // Call the actual authentication routine.
  449. //
  450. Status = (*SubAuthenticationRoutine)(
  451. LogonLevel,
  452. LogonInformation,
  453. Flags,
  454. UserAll,
  455. WhichFields,
  456. UserFlags,
  457. Authoritative,
  458. LogoffTime,
  459. KickoffTime );
  460. //
  461. // Cleanup up before returning.
  462. //
  463. Cleanup:
  464. return Status;
  465. }
  466. NTSTATUS
  467. Msv1_0ExportSubAuthenticationRoutine(
  468. IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
  469. IN PVOID LogonInformation,
  470. IN ULONG Flags,
  471. IN ULONG DllNumber,
  472. IN PUSER_ALL_INFORMATION UserAll,
  473. OUT PULONG WhichFields,
  474. OUT PULONG UserFlags,
  475. OUT PBOOLEAN Authoritative,
  476. OUT PLARGE_INTEGER LogoffTime,
  477. OUT PLARGE_INTEGER KickoffTime
  478. )
  479. /*++
  480. Routine Description:
  481. The subauthentication routine does client/server specific authentication
  482. of a user. This stub routine loads the appropriate subauthentication
  483. package DLL and calls out to that DLL to do the actuall validation.
  484. Arguments:
  485. LogonLevel -- Specifies the level of information given in
  486. LogonInformation.
  487. LogonInformation -- Specifies the description for the user
  488. logging on. The LogonDomainName field should be ignored.
  489. Flags -- Flags describing the circumstances of the logon.
  490. MSV1_0_PASSTHRU -- This is a PassThru authenication. (i.e., the
  491. user isn't connecting to this machine.)
  492. MSV1_0_GUEST_LOGON -- This is a retry of the logon using the GUEST
  493. user account.
  494. DllNumber - The number of the subauthentication DLL to call.
  495. UserAll -- The description of the user as returned from SAM.
  496. WhichFields -- Returns which fields from UserAllInfo are to be written
  497. back to SAM. The fields will only be written if MSV returns success
  498. to it's caller. Only the following bits are valid.
  499. USER_ALL_PARAMETERS - Write UserAllInfo->Parameters back to SAM. If
  500. the size of the buffer is changed, Msv1_0SubAuthenticationRoutine
  501. must delete the old buffer using MIDL_user_free() and reallocate the
  502. buffer using MIDL_user_allocate().
  503. UserFlags -- Returns UserFlags to be returned from LsaLogonUser in the
  504. LogonProfile. The following bits are currently defined:
  505. LOGON_GUEST -- This was a guest logon
  506. LOGON_NOENCRYPTION -- The caller didn't specify encrypted credentials
  507. LOGON_GRACE_LOGON -- The caller's password has expired but logon
  508. was allowed during a grace period following the expiration.
  509. SubAuthentication packages should restrict themselves to returning
  510. bits in the high order byte of UserFlags. However, this convention
  511. isn't enforced giving the SubAuthentication package more flexibility.
  512. Authoritative -- Returns whether the status returned is an
  513. authoritative status which should be returned to the original
  514. caller. If not, this logon request may be tried again on another
  515. domain controller. This parameter is returned regardless of the
  516. status code.
  517. LogoffTime - Receives the time at which the user should logoff the
  518. system. This time is specified as a GMT relative NT system time.
  519. KickoffTime - Receives the time at which the user should be kicked
  520. off the system. This time is specified as a GMT relative NT system
  521. time. Specify, a full scale positive number if the user isn't to
  522. be kicked off.
  523. Return Value:
  524. STATUS_SUCCESS: if there was no error.
  525. STATUS_NO_SUCH_USER: The specified user has no account.
  526. STATUS_WRONG_PASSWORD: The password was invalid.
  527. STATUS_INVALID_INFO_CLASS: LogonLevel is invalid.
  528. STATUS_ACCOUNT_LOCKED_OUT: The account is locked out
  529. STATUS_ACCOUNT_DISABLED: The account is disabled
  530. STATUS_ACCOUNT_EXPIRED: The account has expired.
  531. STATUS_PASSWORD_MUST_CHANGE: Account is marked as Password must change
  532. on next logon.
  533. STATUS_PASSWORD_EXPIRED: The Password is expired.
  534. STATUS_INVALID_LOGON_HOURS - The user is not authorized to logon at
  535. this time.
  536. STATUS_INVALID_WORKSTATION - The user is not authorized to logon to
  537. the specified workstation.
  538. --*/
  539. {
  540. NTSTATUS Status;
  541. NTSTATUS SubStatus;
  542. PSUBAUTHENTICATION_DLL SubAuthenticationDll;
  543. PSUBAUTHENTICATION_ROUTINE SubAuthenticationRoutine;
  544. PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
  545. //
  546. // Initialization
  547. //
  548. LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
  549. *Authoritative = TRUE;
  550. //
  551. // Find the SubAuthentication Dll.
  552. //
  553. SubAuthenticationDll = ReferenceSubAuth ( DllNumber, &SubStatus);
  554. if (SubStatus != STATUS_SUCCESS)
  555. {
  556. SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
  557. Status = SubStatus;
  558. goto Cleanup;
  559. }
  560. //
  561. // Leave the crit sect while calling the DLL
  562. //
  563. SubAuthenticationRoutine = SubAuthenticationDll->SubAuthenticationRoutine;
  564. if (SubAuthenticationRoutine == NULL)
  565. {
  566. Status = STATUS_PROCEDURE_NOT_FOUND;
  567. goto Cleanup;
  568. }
  569. //
  570. // Call the actual authentication routine.
  571. //
  572. Status = (*SubAuthenticationRoutine)(
  573. LogonLevel,
  574. LogonInformation,
  575. Flags,
  576. UserAll,
  577. WhichFields,
  578. UserFlags,
  579. Authoritative,
  580. LogoffTime,
  581. KickoffTime );
  582. //
  583. // Cleanup up before returning.
  584. //
  585. Cleanup:
  586. return Status;
  587. }
  588. NTSTATUS
  589. Msv1_0SubAuthenticationRoutineEx(
  590. IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
  591. IN PVOID LogonInformation,
  592. IN ULONG Flags,
  593. IN PUSER_ALL_INFORMATION UserAll,
  594. IN SAM_HANDLE UserHandle,
  595. IN OUT PMSV1_0_VALIDATION_INFO ValidationInfo,
  596. OUT PULONG ActionsPerformed
  597. )
  598. /*++
  599. Routine Description:
  600. The subauthentication routine does client/server specific authentication
  601. of a user. This stub routine loads the appropriate subauthentication
  602. package DLL and calls out to that DLL to do the actuall validation.
  603. Arguments:
  604. LogonLevel -- Specifies the level of information given in
  605. LogonInformation.
  606. LogonInformation -- Specifies the description for the user
  607. logging on. The LogonDomainName field should be ignored.
  608. Flags - Flags describing the circumstances of the logon.
  609. MSV1_0_PASSTHRU -- This is a PassThru authenication. (i.e., the
  610. user isn't connecting to this machine.)
  611. MSV1_0_GUEST_LOGON -- This is a retry of the logon using the GUEST
  612. user account.
  613. UserAll -- The description of the user as returned from SAM.
  614. WhichFields -- Returns which fields from UserAllInfo are to be written
  615. back to SAM. The fields will only be written if MSV returns success
  616. to it's caller. Only the following bits are valid.
  617. USER_ALL_PARAMETERS - Write UserAllInfo->Parameters back to SAM. If
  618. the size of the buffer is changed, Msv1_0SubAuthenticationRoutine
  619. must delete the old buffer using MIDL_user_free() and reallocate the
  620. buffer using MIDL_user_allocate().
  621. UserFlags -- Returns UserFlags to be returned from LsaLogonUser in the
  622. LogonProfile. The following bits are currently defined:
  623. LOGON_GUEST -- This was a guest logon
  624. LOGON_NOENCRYPTION -- The caller didn't specify encrypted credentials
  625. LOGON_GRACE_LOGON -- The caller's password has expired but logon
  626. was allowed during a grace period following the expiration.
  627. SubAuthentication packages should restrict themselves to returning
  628. bits in the high order byte of UserFlags. However, this convention
  629. isn't enforced giving the SubAuthentication package more flexibility.
  630. Authoritative -- Returns whether the status returned is an
  631. authoritative status which should be returned to the original
  632. caller. If not, this logon request may be tried again on another
  633. domain controller. This parameter is returned regardless of the
  634. status code.
  635. LogoffTime - Receives the time at which the user should logoff the
  636. system. This time is specified as a GMT relative NT system time.
  637. KickoffTime - Receives the time at which the user should be kicked
  638. off the system. This time is specified as a GMT relative NT system
  639. time. Specify, a full scale positive number if the user isn't to
  640. be kicked off.
  641. Return Value:
  642. STATUS_SUCCESS: if there was no error.
  643. STATUS_NO_SUCH_USER: The specified user has no account.
  644. STATUS_WRONG_PASSWORD: The password was invalid.
  645. STATUS_INVALID_INFO_CLASS: LogonLevel is invalid.
  646. STATUS_ACCOUNT_LOCKED_OUT: The account is locked out
  647. STATUS_ACCOUNT_DISABLED: The account is disabled
  648. STATUS_ACCOUNT_EXPIRED: The account has expired.
  649. STATUS_PASSWORD_MUST_CHANGE: Account is marked as Password must change
  650. on next logon.
  651. STATUS_PASSWORD_EXPIRED: The Password is expired.
  652. STATUS_INVALID_LOGON_HOURS - The user is not authorized to logon at
  653. this time.
  654. STATUS_INVALID_WORKSTATION - The user is not authorized to logon to
  655. the specified workstation.
  656. --*/
  657. {
  658. NTSTATUS Status;
  659. NTSTATUS SubStatus;
  660. ULONG DllNumber;
  661. PSUBAUTHENTICATION_DLL SubAuthenticationDll;
  662. PSUBAUTHENTICATION_ROUTINEEX SubAuthenticationRoutineEx;
  663. PNETLOGON_LOGON_IDENTITY_INFO LogonInfo;
  664. //
  665. // Initialization
  666. //
  667. LogonInfo = (PNETLOGON_LOGON_IDENTITY_INFO) LogonInformation;
  668. DllNumber = LogonInfo->ParameterControl >> MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
  669. //
  670. // Find the SubAuthentication Dll.
  671. //
  672. SubAuthenticationDll = ReferenceSubAuth (DllNumber, &SubStatus);;
  673. if (SubStatus != STATUS_SUCCESS)
  674. {
  675. SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
  676. Status = SubStatus;
  677. goto Cleanup;
  678. }
  679. //
  680. // Leave the crit sect while calling the DLL
  681. //
  682. SubAuthenticationRoutineEx = SubAuthenticationDll->SubAuthenticationRoutineEx;
  683. if (SubAuthenticationRoutineEx == NULL)
  684. {
  685. Status = STATUS_PROCEDURE_NOT_FOUND;
  686. goto Cleanup;
  687. }
  688. //
  689. // Call the actual authentication routine.
  690. //
  691. Status = (*SubAuthenticationRoutineEx)(
  692. LogonLevel,
  693. LogonInformation,
  694. Flags,
  695. UserAll,
  696. UserHandle,
  697. ValidationInfo,
  698. ActionsPerformed
  699. );
  700. //
  701. // Cleanup up before returning.
  702. //
  703. Cleanup:
  704. return Status;
  705. }
  706. NTSTATUS
  707. MspNtSubAuth(
  708. IN PLSA_CLIENT_REQUEST ClientRequest,
  709. IN PVOID ProtocolSubmitBuffer,
  710. IN PVOID ClientBufferBase,
  711. IN ULONG SubmitBufferSize,
  712. OUT PVOID *ProtocolReturnBuffer,
  713. OUT PULONG ReturnBufferSize,
  714. OUT PNTSTATUS ProtocolStatus
  715. )
  716. /*++
  717. Routine Description:
  718. This routine is the dispatch routine for LsaCallAuthenticationPackage()
  719. with a message type of MsV1_0SubAuthInfo.
  720. Arguments:
  721. The arguments to this routine are identical to those of LsaApCallPackage.
  722. Only the special attributes of these parameters as they apply to
  723. this routine are mentioned here.
  724. Return Value:
  725. STATUS_SUCCESS - Indicates the service completed successfully.
  726. STATUS_QUOTA_EXCEEDED - This error indicates that the logon
  727. could not be completed because the client does not have
  728. sufficient quota to allocate the return buffer.
  729. --*/
  730. {
  731. NTSTATUS Status = STATUS_SUCCESS;
  732. NTSTATUS SubStatus = STATUS_SUCCESS;
  733. PMSV1_0_SUBAUTH_REQUEST SubAuthRequest;
  734. PMSV1_0_SUBAUTH_RESPONSE SubAuthResponse;
  735. CLIENT_BUFFER_DESC ClientBufferDesc;
  736. ULONG ReturnDataLength = 0;
  737. PVOID ReturnDataBuffer = NULL;
  738. PSUBAUTHENTICATION_DLL SubAuthenticationDll;
  739. PSUBAUTHENTICATION_ROUTINEGENERIC SubAuthenticationRoutineGeneric;
  740. NlpInitClientBuffer( &ClientBufferDesc, ClientRequest );
  741. *ProtocolStatus = STATUS_SUCCESS;
  742. //
  743. // Ensure the specified Submit Buffer is of reasonable size and
  744. // relocate all of the pointers to be relative to the LSA allocated
  745. // buffer.
  746. //
  747. if ( SubmitBufferSize < sizeof(MSV1_0_SUBAUTH_REQUEST) ) {
  748. Status = STATUS_INVALID_PARAMETER;
  749. goto Cleanup;
  750. }
  751. SubAuthRequest = (PMSV1_0_SUBAUTH_REQUEST) ProtocolSubmitBuffer;
  752. //
  753. // Make sure the buffer fits in the supplied size
  754. //
  755. if (SubAuthRequest->SubAuthSubmitBuffer != NULL) {
  756. if (SubAuthRequest->SubAuthSubmitBuffer + SubAuthRequest->SubAuthInfoLength >
  757. (PUCHAR) ClientBufferBase + SubmitBufferSize) {
  758. Status = STATUS_INVALID_PARAMETER;
  759. goto Cleanup;
  760. }
  761. //
  762. // Reset the pointers for the validation data
  763. //
  764. SubAuthRequest->SubAuthSubmitBuffer =
  765. (PUCHAR) SubAuthRequest -
  766. (ULONG_PTR) ClientBufferBase +
  767. (ULONG_PTR) SubAuthRequest->SubAuthSubmitBuffer;
  768. }
  769. // If subauth package found, call the routine,
  770. //
  771. // Find the SubAuthentication Dll.
  772. //
  773. SubAuthenticationDll = ReferenceSubAuth (SubAuthRequest->SubAuthPackageId, &SubStatus);;
  774. if (SubStatus != STATUS_SUCCESS)
  775. {
  776. SspPrint((SSP_MISC, "SubAuth Error value is %ld.\n", SubStatus));
  777. Status = SubStatus;
  778. goto Cleanup;
  779. }
  780. //
  781. // Leave the crit sect while calling the DLL
  782. //
  783. SubAuthenticationRoutineGeneric = SubAuthenticationDll->SubAuthenticationRoutineGeneric;
  784. if (SubAuthenticationRoutineGeneric == NULL)
  785. {
  786. Status = STATUS_PROCEDURE_NOT_FOUND;
  787. goto Cleanup;
  788. }
  789. Status = (*SubAuthenticationRoutineGeneric)(
  790. (PVOID) SubAuthRequest->SubAuthSubmitBuffer,
  791. SubAuthRequest->SubAuthInfoLength,
  792. &ReturnDataLength,
  793. &ReturnDataBuffer);
  794. if (!NT_SUCCESS(Status)) {
  795. goto Cleanup;
  796. }
  797. //
  798. // Allocate a buffer to return to the caller.
  799. //
  800. *ReturnBufferSize = sizeof(MSV1_0_SUBAUTH_RESPONSE) +
  801. ReturnDataLength;
  802. Status = NlpAllocateClientBuffer( &ClientBufferDesc,
  803. sizeof(MSV1_0_SUBAUTH_RESPONSE),
  804. *ReturnBufferSize );
  805. if ( !NT_SUCCESS( Status ) ) {
  806. goto Cleanup;
  807. }
  808. SubAuthResponse = (PMSV1_0_SUBAUTH_RESPONSE) ClientBufferDesc.MsvBuffer;
  809. //
  810. // Fill in the return buffer.
  811. //
  812. SubAuthResponse->MessageType = MsV1_0SubAuth;
  813. SubAuthResponse->SubAuthInfoLength = ReturnDataLength;
  814. if (ReturnDataLength > 0)
  815. {
  816. SubAuthResponse->SubAuthReturnBuffer = ClientBufferDesc.UserBuffer + sizeof(MSV1_0_SUBAUTH_RESPONSE);
  817. if (ReturnDataBuffer)
  818. {
  819. RtlCopyMemory(
  820. SubAuthResponse + 1,
  821. ReturnDataBuffer,
  822. ReturnDataLength
  823. );
  824. // Make relative pointers
  825. SubAuthResponse->SubAuthReturnBuffer = (PUCHAR) sizeof(MSV1_0_SUBAUTH_RESPONSE);
  826. }
  827. else
  828. {
  829. SubAuthResponse->SubAuthReturnBuffer = NULL;
  830. SubStatus = STATUS_NO_MEMORY;
  831. }
  832. }
  833. else
  834. {
  835. SubAuthResponse->SubAuthReturnBuffer = 0;
  836. }
  837. //
  838. // Flush the buffer to the client's address space.
  839. //
  840. Status = NlpFlushClientBuffer( &ClientBufferDesc,
  841. ProtocolReturnBuffer );
  842. Cleanup:
  843. if (ReturnDataBuffer != NULL) {
  844. MIDL_user_free(ReturnDataBuffer);
  845. }
  846. if ( !NT_SUCCESS(Status)) {
  847. NlpFreeClientBuffer( &ClientBufferDesc );
  848. }
  849. *ProtocolStatus = SubStatus;
  850. return(Status);
  851. }