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.

1347 lines
33 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: pwdssp.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 9-07-97 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "pwdsspp.h"
  18. typedef struct _PWD_CRED {
  19. DWORD Ref;
  20. } PWD_CRED, * PPWD_CRED;
  21. typedef struct _PWD_CONTEXT {
  22. DWORD Tag;
  23. HANDLE Token;
  24. } PWD_CONTEXT, *PPWD_CONTEXT ;
  25. PWD_CRED PwdGlobalAnsi;
  26. PWD_CRED PwdGlobalUnicode;
  27. #define CONTEXT_TAG 'txtC'
  28. #define ANONYMOUS_TOKEN ((HANDLE) 1)
  29. SecPkgInfoA PwdInfoA = { SECPKG_FLAG_CONNECTION |
  30. SECPKG_FLAG_ACCEPT_WIN32_NAME,
  31. 1,
  32. (WORD) -1,
  33. 768,
  34. PWDSSP_NAME_A,
  35. "Microsoft Clear Text Password Security Provider" };
  36. SecPkgInfoW PwdInfoW = { SECPKG_FLAG_CONNECTION |
  37. SECPKG_FLAG_ACCEPT_WIN32_NAME,
  38. 1,
  39. (WORD) -1,
  40. 768,
  41. PWDSSP_NAME_W,
  42. L"Microsoft Clear Text Password Security Provider" };
  43. SecurityFunctionTableA PwdTableA = {
  44. SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
  45. EnumerateSecurityPackagesA,
  46. NULL,
  47. AcquireCredentialsHandleA,
  48. FreeCredentialsHandle,
  49. NULL,
  50. InitializeSecurityContextA,
  51. AcceptSecurityContext,
  52. CompleteAuthToken,
  53. DeleteSecurityContext,
  54. ApplyControlToken,
  55. QueryContextAttributesA,
  56. ImpersonateSecurityContext,
  57. RevertSecurityContext,
  58. MakeSignature,
  59. VerifySignature,
  60. FreeContextBuffer,
  61. QuerySecurityPackageInfoA,
  62. NULL,
  63. NULL,
  64. NULL,
  65. NULL,
  66. NULL,
  67. NULL,
  68. QuerySecurityContextToken
  69. };
  70. SecurityFunctionTableW PwdTableW = {
  71. SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
  72. EnumerateSecurityPackagesW,
  73. NULL,
  74. AcquireCredentialsHandleW,
  75. FreeCredentialsHandle,
  76. NULL,
  77. InitializeSecurityContextW,
  78. AcceptSecurityContext,
  79. CompleteAuthToken,
  80. DeleteSecurityContext,
  81. ApplyControlToken,
  82. QueryContextAttributesW,
  83. ImpersonateSecurityContext,
  84. RevertSecurityContext,
  85. MakeSignature,
  86. VerifySignature,
  87. FreeContextBuffer,
  88. QuerySecurityPackageInfoW,
  89. NULL,
  90. NULL,
  91. NULL,
  92. NULL,
  93. NULL,
  94. NULL,
  95. QuerySecurityContextToken
  96. };
  97. //#define PwdAlloc(x) LsaIAllocateHeap(x)
  98. //#define PwdFree(x) LsaIFreeHeap(x)
  99. #define PwdAlloc(x) LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,x)
  100. #define PwdFree(x) LocalFree(x)
  101. NTSTATUS
  102. VerifyCredentials(
  103. IN PWSTR UserName,
  104. IN PWSTR DomainName,
  105. IN PWSTR Password,
  106. IN ULONG VerifyFlags
  107. );
  108. UNICODE_STRING AuthenticationPackage;
  109. //+---------------------------------------------------------------------------
  110. //
  111. // Function: DllMain
  112. //
  113. // Synopsis: Entry point
  114. //
  115. // Arguments: [hInstance] --
  116. // [dwReason] --
  117. // [lpReserved] --
  118. //
  119. // Notes:
  120. //
  121. //----------------------------------------------------------------------------
  122. BOOL
  123. WINAPI
  124. DllMain(
  125. HINSTANCE hInstance,
  126. DWORD dwReason,
  127. LPVOID lpReserved)
  128. {
  129. if (dwReason == DLL_PROCESS_ATTACH)
  130. {
  131. DisableThreadLibraryCalls( hInstance );
  132. RtlInitUnicodeString(&AuthenticationPackage, MICROSOFT_KERBEROS_NAME_W);
  133. if ( !CacheInitialize() ) {
  134. return FALSE;
  135. }
  136. }
  137. return(TRUE);
  138. }
  139. //+---------------------------------------------------------------------------
  140. //
  141. // Function: PwdpParseBuffers
  142. //
  143. // Synopsis: Parse out right buffer descriptor
  144. //
  145. // Arguments: [pMessage] --
  146. // [pToken] --
  147. // [pEmpty] --
  148. //
  149. // Notes:
  150. //
  151. //----------------------------------------------------------------------------
  152. VOID
  153. PwdpParseBuffers(
  154. PSecBufferDesc pMessage,
  155. PSecBuffer * pToken,
  156. PSecBuffer * pEmpty)
  157. {
  158. ULONG i;
  159. PSecBuffer pFirstBlank = NULL;
  160. PSecBuffer pWholeMessage = NULL;
  161. for (i = 0 ; i < pMessage->cBuffers ; i++ )
  162. {
  163. if ( (pMessage->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN )
  164. {
  165. pWholeMessage = &pMessage->pBuffers[i];
  166. if (pFirstBlank)
  167. {
  168. break;
  169. }
  170. }
  171. else if ( (pMessage->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_EMPTY )
  172. {
  173. pFirstBlank = &pMessage->pBuffers[i];
  174. if (pWholeMessage)
  175. {
  176. break;
  177. }
  178. }
  179. }
  180. if (pToken)
  181. {
  182. *pToken = pWholeMessage;
  183. }
  184. if (pEmpty)
  185. {
  186. *pEmpty = pFirstBlank;
  187. }
  188. }
  189. //+---------------------------------------------------------------------------
  190. //
  191. // Function: AcquireCredentialsHandleW
  192. //
  193. // Synopsis: Get the credential handle
  194. //
  195. // Arguments: [pszPrincipal] --
  196. // [pszPackageName] --
  197. // [fCredentialUse] --
  198. // [pvLogonId] --
  199. // [pAuthData] --
  200. // [pGetKeyFn] --
  201. // [GetKey] --
  202. // [pvGetKeyArgument] --
  203. // [GetKey] --
  204. // [phCredential] --
  205. // [PTimeStamp] --
  206. //
  207. // Notes:
  208. //
  209. //----------------------------------------------------------------------------
  210. SECURITY_STATUS
  211. SEC_ENTRY
  212. AcquireCredentialsHandleW(
  213. SEC_WCHAR SEC_FAR * pszPrincipal, // Name of principal
  214. SEC_WCHAR SEC_FAR * pszPackageName, // Name of package
  215. unsigned long fCredentialUse, // Flags indicating use
  216. void SEC_FAR * pvLogonId, // Pointer to logon ID
  217. void SEC_FAR * pAuthData, // Package specific data
  218. SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
  219. void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
  220. PCredHandle phCredential, // (out) Cred Handle
  221. PTimeStamp ptsExpiry // (out) Lifetime (optional)
  222. )
  223. {
  224. if (_wcsicmp(pszPackageName, PWDSSP_NAME_W))
  225. {
  226. return( SEC_E_SECPKG_NOT_FOUND );
  227. }
  228. if ( fCredentialUse & SECPKG_CRED_OUTBOUND )
  229. {
  230. return( SEC_E_NO_CREDENTIALS );
  231. }
  232. InterlockedIncrement( &PwdGlobalUnicode.Ref );
  233. phCredential->dwUpper = (ULONG_PTR) &PwdGlobalUnicode ;
  234. if ( ptsExpiry )
  235. {
  236. ptsExpiry->LowPart = (DWORD) 0xFFFFFFFF;
  237. ptsExpiry->HighPart = (DWORD) 0x7FFFFFFF;
  238. }
  239. return( SEC_E_OK );
  240. }
  241. //+---------------------------------------------------------------------------
  242. //
  243. // Function: AcquireCredentialsHandleA
  244. //
  245. // Synopsis: ANSI entry
  246. //
  247. // Arguments: [pszPrincipal] --
  248. // [pszPackageName] --
  249. // [fCredentialUse] --
  250. // [pvLogonId] --
  251. // [pAuthData] --
  252. // [pGetKeyFn] --
  253. // [GetKey] --
  254. // [pvGetKeyArgument] --
  255. // [GetKey] --
  256. // [phCredential] --
  257. //
  258. // Notes:
  259. //
  260. //----------------------------------------------------------------------------
  261. SECURITY_STATUS SEC_ENTRY
  262. AcquireCredentialsHandleA(
  263. SEC_CHAR SEC_FAR * pszPrincipal, // Name of principal
  264. SEC_CHAR SEC_FAR * pszPackageName, // Name of package
  265. unsigned long fCredentialUse, // Flags indicating use
  266. void SEC_FAR * pvLogonId, // Pointer to logon ID
  267. void SEC_FAR * pAuthData, // Package specific data
  268. SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
  269. void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
  270. PCredHandle phCredential, // (out) Cred Handle
  271. PTimeStamp ptsExpiry // (out) Lifetime (optional)
  272. )
  273. {
  274. if (_stricmp(pszPackageName, PWDSSP_NAME_A))
  275. {
  276. return( SEC_E_SECPKG_NOT_FOUND );
  277. }
  278. if ( fCredentialUse & SECPKG_CRED_OUTBOUND )
  279. {
  280. return( SEC_E_NO_CREDENTIALS );
  281. }
  282. InterlockedIncrement( &PwdGlobalAnsi.Ref );
  283. phCredential->dwUpper = (ULONG_PTR) &PwdGlobalAnsi ;
  284. if ( ptsExpiry )
  285. {
  286. ptsExpiry->LowPart = (DWORD) 0xFFFFFFFF;
  287. ptsExpiry->HighPart = (DWORD) 0x7FFFFFFF;
  288. }
  289. return(SEC_E_OK);
  290. }
  291. //+---------------------------------------------------------------------------
  292. //
  293. // Function: FreeCredentialHandle
  294. //
  295. // Synopsis: Free a credential handle
  296. //
  297. // Arguments: [free] --
  298. //
  299. // Notes:
  300. //
  301. //----------------------------------------------------------------------------
  302. SECURITY_STATUS
  303. SEC_ENTRY
  304. FreeCredentialsHandle(
  305. PCredHandle phCredential // Handle to free
  306. )
  307. {
  308. PPWD_CRED Cred;
  309. if ( (phCredential->dwUpper != (ULONG_PTR) &PwdGlobalAnsi ) &&
  310. (phCredential->dwUpper != (ULONG_PTR) &PwdGlobalUnicode ) )
  311. {
  312. return( SEC_E_INVALID_HANDLE );
  313. }
  314. Cred = (PPWD_CRED) phCredential->dwUpper ;
  315. InterlockedDecrement( &Cred->Ref );
  316. return( SEC_E_OK );
  317. }
  318. //+---------------------------------------------------------------------------
  319. //
  320. // Function: InitializeSecurityContextW
  321. //
  322. // Synopsis: Initialize a security context (outbound) NOT SUPPORTED
  323. //
  324. // Arguments: [phCredential] --
  325. // [phContext] --
  326. // [pszTargetName] --
  327. // [fContextReq] --
  328. // [Reserved1] --
  329. // [Reserved] --
  330. // [TargetDataRep] --
  331. // [pInput] --
  332. // [Reserved2] --
  333. // [Reserved] --
  334. // [phNewContext] --
  335. // [pOutput] --
  336. // [pfContextAttr] --
  337. //
  338. // Notes:
  339. //
  340. //----------------------------------------------------------------------------
  341. SECURITY_STATUS
  342. SEC_ENTRY
  343. InitializeSecurityContextW(
  344. PCredHandle phCredential, // Cred to base context
  345. PCtxtHandle phContext, // Existing context (OPT)
  346. SEC_WCHAR SEC_FAR * pszTargetName, // Name of target
  347. unsigned long fContextReq, // Context Requirements
  348. unsigned long Reserved1, // Reserved, MBZ
  349. unsigned long TargetDataRep, // Data rep of target
  350. PSecBufferDesc pInput, // Input Buffers
  351. unsigned long Reserved2, // Reserved, MBZ
  352. PCtxtHandle phNewContext, // (out) New Context handle
  353. PSecBufferDesc pOutput, // (inout) Output Buffers
  354. unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
  355. PTimeStamp ptsExpiry // (out) Life span (OPT)
  356. )
  357. {
  358. return( SEC_E_UNSUPPORTED_FUNCTION );
  359. }
  360. //+---------------------------------------------------------------------------
  361. //
  362. // Function: InitializeSecurityContextA
  363. //
  364. // Synopsis: NOT SUPPORTED
  365. //
  366. // Arguments: [phCredential] --
  367. // [phContext] --
  368. // [pszTargetName] --
  369. // [fContextReq] --
  370. // [Reserved1] --
  371. // [TargetDataRep] --
  372. // [pInput] --
  373. // [Reserved2] --
  374. // [phNewContext] --
  375. // [pOutput] --
  376. // [pfContextAttr] --
  377. //
  378. // Notes:
  379. //
  380. //----------------------------------------------------------------------------
  381. SECURITY_STATUS
  382. SEC_ENTRY
  383. InitializeSecurityContextA(
  384. PCredHandle phCredential, // Cred to base context
  385. PCtxtHandle phContext, // Existing context (OPT)
  386. SEC_CHAR SEC_FAR * pszTargetName, // Name of target
  387. unsigned long fContextReq, // Context Requirements
  388. unsigned long Reserved1, // Reserved, MBZ
  389. unsigned long TargetDataRep, // Data rep of target
  390. PSecBufferDesc pInput, // Input Buffers
  391. unsigned long Reserved2, // Reserved, MBZ
  392. PCtxtHandle phNewContext, // (out) New Context handle
  393. PSecBufferDesc pOutput, // (inout) Output Buffers
  394. unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
  395. PTimeStamp ptsExpiry // (out) Life span (OPT)
  396. )
  397. {
  398. return( SEC_E_UNSUPPORTED_FUNCTION );
  399. }
  400. PSEC_WINNT_AUTH_IDENTITY_A
  401. PwdpMakeAnsiCopy(
  402. PSEC_WINNT_AUTH_IDENTITY_A Ansi
  403. )
  404. {
  405. PSEC_WINNT_AUTH_IDENTITY_A New ;
  406. New = PwdAlloc( sizeof( SEC_WINNT_AUTH_IDENTITY_A ) +
  407. Ansi->UserLength + 1 +
  408. Ansi->DomainLength + 1 +
  409. Ansi->PasswordLength + 1 );
  410. if ( New )
  411. {
  412. New->User = (PSTR) (New + 1);
  413. CopyMemory( New->User, Ansi->User, Ansi->UserLength );
  414. New->User[ Ansi->UserLength ] = '\0';
  415. New->Domain = New->User + Ansi->UserLength + 1 ;
  416. CopyMemory( New->Domain, Ansi->Domain, Ansi->DomainLength );
  417. New->Domain[ Ansi->DomainLength ] = '\0';
  418. New->Password = New->Domain + Ansi->DomainLength + 1 ;
  419. CopyMemory( New->Password, Ansi->Password, Ansi->PasswordLength );
  420. New->Password[ Ansi->PasswordLength ] = '\0';
  421. }
  422. return( New );
  423. }
  424. PSEC_WINNT_AUTH_IDENTITY_W
  425. PwdpMakeWideCopy(
  426. PSEC_WINNT_AUTH_IDENTITY_W Wide,
  427. BOOLEAN ValidateOnly
  428. )
  429. {
  430. PSEC_WINNT_AUTH_IDENTITY_W New ;
  431. ULONG FlatUserLength ;
  432. PWSTR FlatUser = NULL;
  433. WCHAR FlatDomain[ DNLEN + 2 ];
  434. SEC_WINNT_AUTH_IDENTITY_W Local ;
  435. if ( (Wide->Domain == NULL) )
  436. {
  437. if( ValidateOnly )
  438. {
  439. ULONG Index;
  440. Local = *Wide ;
  441. FlatUserLength = wcslen( Wide->User );
  442. for( Index = 0 ; Index < FlatUserLength ; Index++ )
  443. {
  444. if( Wide->User[ Index ] == '\\' )
  445. {
  446. Local.Domain = Wide->User;
  447. Local.DomainLength = Index;
  448. Local.User = &(Wide->User[Index+1]);
  449. Local.UserLength = FlatUserLength - Index - 1;
  450. break;
  451. }
  452. }
  453. } else {
  454. FlatUserLength = wcslen( Wide->User ) + 1;
  455. if ( FlatUserLength < UNLEN+2 )
  456. {
  457. FlatUserLength = UNLEN + 2;
  458. }
  459. FlatUser = PwdAlloc(FlatUserLength * sizeof( WCHAR ));
  460. if ( FlatUser == NULL )
  461. {
  462. return NULL ;
  463. }
  464. if ( ! PwdCrackName( Wide->User,
  465. FlatDomain,
  466. FlatUser ) )
  467. {
  468. PwdFree( FlatUser );
  469. SetLastError( ERROR_NO_SUCH_USER );
  470. return NULL ;
  471. }
  472. Local = *Wide ;
  473. Local.User = FlatUser ;
  474. Local.Domain = FlatDomain ;
  475. Local.UserLength = wcslen( FlatUser );
  476. Local.DomainLength = wcslen( FlatDomain );
  477. }
  478. Wide = &Local ;
  479. }
  480. New = PwdAlloc( sizeof( SEC_WINNT_AUTH_IDENTITY_W ) +
  481. (Wide->UserLength + 1) * sizeof(WCHAR) +
  482. (Wide->DomainLength + 1) * sizeof(WCHAR) +
  483. (Wide->PasswordLength + 1) * sizeof(WCHAR) );
  484. if ( New )
  485. {
  486. New->User = (PWSTR) (New + 1);
  487. CopyMemory( New->User, Wide->User, Wide->UserLength * 2 );
  488. New->User[ Wide->UserLength ] = L'\0';
  489. New->UserLength = Wide->UserLength;
  490. New->Domain = New->User + Wide->UserLength + 1 ;
  491. CopyMemory( New->Domain, Wide->Domain, Wide->DomainLength * 2 );
  492. New->Domain[ Wide->DomainLength ] = L'\0';
  493. New->DomainLength = Wide->DomainLength;
  494. New->Password = New->Domain + Wide->DomainLength + 1 ;
  495. CopyMemory( New->Password, Wide->Password, Wide->PasswordLength * 2);
  496. New->Password[ Wide->PasswordLength ] = '\0';
  497. New->PasswordLength = Wide->PasswordLength;
  498. }
  499. if ( Wide == &Local )
  500. {
  501. if( FlatUser != NULL )
  502. {
  503. PwdFree( FlatUser );
  504. }
  505. }
  506. return( New );
  507. }
  508. //+---------------------------------------------------------------------------
  509. //
  510. // Function: AcceptSecurityContext
  511. //
  512. // Synopsis: Server side accept security context
  513. //
  514. // Arguments: [phCredential] --
  515. // [phContext] --
  516. // [pInput] --
  517. // [fContextReq] --
  518. // [TargetDataRep] --
  519. // [phNewContext] --
  520. // [pOutput] --
  521. // [pfContextAttr] --
  522. //
  523. // Notes:
  524. //
  525. //----------------------------------------------------------------------------
  526. SECURITY_STATUS
  527. SEC_ENTRY
  528. AcceptSecurityContext(
  529. PCredHandle phCredential, // Cred to base context
  530. PCtxtHandle phContext, // Existing context (OPT)
  531. PSecBufferDesc pInput, // Input buffer
  532. unsigned long fContextReq, // Context Requirements
  533. unsigned long TargetDataRep, // Target Data Rep
  534. PCtxtHandle phNewContext, // (out) New context handle
  535. PSecBufferDesc pOutput, // (inout) Output buffers
  536. unsigned long SEC_FAR * pfContextAttr, // (out) Context attributes
  537. PTimeStamp ptsExpiry // (out) Life span (OPT)
  538. )
  539. {
  540. PPWD_CONTEXT Context ;
  541. PSecBuffer Buffer ;
  542. DWORD Type;
  543. PSEC_WINNT_AUTH_IDENTITY_W Unknown ;
  544. PSEC_WINNT_AUTH_IDENTITY_A Ansi;
  545. PSEC_WINNT_AUTH_IDENTITY_W Unicode;
  546. HANDLE Token;
  547. BOOL Ret;
  548. if ( phCredential->dwUpper == (ULONG_PTR) &PwdGlobalAnsi )
  549. {
  550. Type = 1;
  551. }
  552. else
  553. {
  554. if ( phCredential->dwUpper == (ULONG_PTR) &PwdGlobalUnicode )
  555. {
  556. Type = 2;
  557. }
  558. else
  559. {
  560. return( SEC_E_INVALID_HANDLE );
  561. }
  562. }
  563. PwdpParseBuffers( pInput, &Buffer, NULL );
  564. if ( !Buffer )
  565. {
  566. return( SEC_E_INVALID_TOKEN );
  567. }
  568. Unknown = (PSEC_WINNT_AUTH_IDENTITY_W) Buffer->pvBuffer ;
  569. if ( Unknown->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE )
  570. {
  571. Type = 2 ;
  572. }
  573. if ( Type == 1 )
  574. {
  575. //
  576. // ANSI:
  577. //
  578. Ansi = PwdpMakeAnsiCopy( (PSEC_WINNT_AUTH_IDENTITY_A) Buffer->pvBuffer);
  579. if ( Ansi )
  580. {
  581. Ret = LogonUserA( Ansi->User, Ansi->Domain, Ansi->Password,
  582. LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
  583. &Token ) ;
  584. PwdFree( Ansi );
  585. }
  586. else
  587. {
  588. Ret = FALSE ;
  589. }
  590. }
  591. else
  592. {
  593. BOOLEAN ValidateOnly = ((fContextReq & ASC_REQ_ALLOW_NON_USER_LOGONS) != 0);
  594. Unicode = PwdpMakeWideCopy(
  595. (PSEC_WINNT_AUTH_IDENTITY_W) Buffer->pvBuffer,
  596. ValidateOnly
  597. );
  598. if ( Unicode )
  599. {
  600. if( ValidateOnly )
  601. {
  602. PVOID DsContext = THSave();
  603. NTSTATUS Status;
  604. Status = VerifyCredentials(
  605. Unicode->User,
  606. Unicode->Domain,
  607. Unicode->Password,
  608. 0
  609. );
  610. THRestore( DsContext );
  611. if( NT_SUCCESS(Status) )
  612. {
  613. Ret = TRUE;
  614. Token = ANONYMOUS_TOKEN ;
  615. } else {
  616. Ret = FALSE;
  617. }
  618. } else {
  619. Ret = LogonUserW(
  620. Unicode->User,
  621. Unicode->Domain,
  622. Unicode->Password,
  623. LOGON32_LOGON_NETWORK,
  624. LOGON32_PROVIDER_DEFAULT,
  625. &Token
  626. );
  627. }
  628. PwdFree( Unicode );
  629. }
  630. else
  631. {
  632. Ret = FALSE ;
  633. if ( GetLastError() == ERROR_NO_SUCH_USER )
  634. {
  635. Unicode = (PSEC_WINNT_AUTH_IDENTITY_W) Buffer->pvBuffer ;
  636. __try
  637. {
  638. if ( Unicode->PasswordLength == 0 )
  639. {
  640. Ret = TRUE ;
  641. Token = ANONYMOUS_TOKEN ;
  642. }
  643. }
  644. __except( EXCEPTION_EXECUTE_HANDLER )
  645. {
  646. NOTHING ;
  647. }
  648. }
  649. }
  650. }
  651. if ( Ret )
  652. {
  653. Context = (PPWD_CONTEXT) PwdAlloc( sizeof( PWD_CONTEXT ) );
  654. if ( Context )
  655. {
  656. Context->Tag = CONTEXT_TAG ;
  657. Context->Token = Token ;
  658. phNewContext->dwUpper = (ULONG_PTR) Context ;
  659. return( SEC_E_OK );
  660. }
  661. if ( Token != ANONYMOUS_TOKEN )
  662. {
  663. CloseHandle( Token );
  664. }
  665. return( SEC_E_INSUFFICIENT_MEMORY );
  666. }
  667. return( SEC_E_INVALID_TOKEN );
  668. }
  669. //+---------------------------------------------------------------------------
  670. //
  671. // Function: DeleteSecurityContext
  672. //
  673. // Synopsis: Deletes a security context
  674. //
  675. // Arguments: [phContext] --
  676. //
  677. // Notes:
  678. //
  679. //----------------------------------------------------------------------------
  680. SECURITY_STATUS
  681. SEC_ENTRY
  682. DeleteSecurityContext(
  683. PCtxtHandle phContext )
  684. {
  685. PPWD_CONTEXT Context;
  686. Context = (PPWD_CONTEXT) phContext->dwUpper ;
  687. #if DBG
  688. // What is the appropriate assert model? This dll does not seem to
  689. // nt specific, win32 does not provide a model, and the crt requires
  690. // NDEBUG to set, which is not always the case.
  691. if (!Context) {
  692. OutputDebugStringA("[PWDSSP]: !!Error!! - Context is NULL\n");
  693. DebugBreak();
  694. }
  695. #endif
  696. if ( Context->Tag == CONTEXT_TAG )
  697. {
  698. if ( Context->Token != ANONYMOUS_TOKEN )
  699. {
  700. CloseHandle( Context->Token );
  701. }
  702. PwdFree( Context );
  703. return( SEC_E_OK );
  704. }
  705. return( SEC_E_INVALID_HANDLE );
  706. }
  707. //+---------------------------------------------------------------------------
  708. //
  709. // Function: ImpersonateSecurityContext
  710. //
  711. // Synopsis: Impersonate the security context
  712. //
  713. // Arguments: [impersonate] --
  714. //
  715. // Notes:
  716. //
  717. //----------------------------------------------------------------------------
  718. SECURITY_STATUS
  719. SEC_ENTRY
  720. ImpersonateSecurityContext(
  721. PCtxtHandle phContext // Context to impersonate
  722. )
  723. {
  724. PPWD_CONTEXT Context;
  725. HANDLE hThread;
  726. NTSTATUS Status ;
  727. Context = (PPWD_CONTEXT) phContext->dwUpper ;
  728. if ( Context->Tag == CONTEXT_TAG )
  729. {
  730. if ( Context->Token != ANONYMOUS_TOKEN )
  731. {
  732. hThread = GetCurrentThread();
  733. SetThreadToken( &hThread, Context->Token );
  734. Status = SEC_E_OK ;
  735. }
  736. else
  737. {
  738. Status = NtImpersonateAnonymousToken(
  739. NtCurrentThread() );
  740. }
  741. return( Status );
  742. }
  743. return( SEC_E_INVALID_HANDLE );
  744. }
  745. //+---------------------------------------------------------------------------
  746. //
  747. // Function: RevertSecurityContext
  748. //
  749. // Synopsis: Revert the security context
  750. //
  751. // Notes:
  752. //
  753. //----------------------------------------------------------------------------
  754. SECURITY_STATUS
  755. SEC_ENTRY
  756. RevertSecurityContext(
  757. PCtxtHandle phContext // Context from which to re
  758. )
  759. {
  760. PPWD_CONTEXT Context;
  761. Context = (PPWD_CONTEXT) phContext->dwUpper ;
  762. if ( Context->Tag == CONTEXT_TAG )
  763. {
  764. RevertToSelf();
  765. return( SEC_E_OK );
  766. }
  767. return( SEC_E_INVALID_HANDLE );
  768. }
  769. SECURITY_STATUS
  770. SEC_ENTRY
  771. QueryContextAttributesA(
  772. PCtxtHandle phContext, // Context to query
  773. unsigned long ulAttribute, // Attribute to query
  774. void SEC_FAR * pBuffer // Buffer for attributes
  775. )
  776. {
  777. return( SEC_E_UNSUPPORTED_FUNCTION );
  778. }
  779. SECURITY_STATUS
  780. SEC_ENTRY
  781. QueryContextAttributesW(
  782. PCtxtHandle phContext, // Context to query
  783. unsigned long ulAttribute, // Attribute to query
  784. void SEC_FAR * pBuffer // Buffer for attributes
  785. )
  786. {
  787. return( SEC_E_UNSUPPORTED_FUNCTION );
  788. }
  789. //+---------------------------------------------------------------------------
  790. //
  791. // Function: PwdpCopyInfoW
  792. //
  793. // Synopsis: Helper - copy package info around
  794. //
  795. // Arguments: [ppPackageInfo] --
  796. //
  797. // Notes:
  798. //
  799. //----------------------------------------------------------------------------
  800. SECURITY_STATUS
  801. PwdpCopyInfoW(
  802. PSecPkgInfoW * ppPackageInfo)
  803. {
  804. DWORD cbTotal;
  805. PSecPkgInfoW pInfo;
  806. PWSTR pszCopy;
  807. cbTotal = sizeof(SecPkgInfoW) +
  808. (wcslen(PwdInfoW.Name) + wcslen(PwdInfoW.Comment) + 2) * 2;
  809. pInfo = PwdAlloc( cbTotal );
  810. if (pInfo)
  811. {
  812. *pInfo = PwdInfoW;
  813. pszCopy = (PWSTR) (pInfo + 1);
  814. pInfo->Name = pszCopy;
  815. wcscpy(pszCopy, PwdInfoW.Name);
  816. pszCopy += wcslen(PwdInfoW.Name) + 1;
  817. pInfo->Comment = pszCopy;
  818. wcscpy(pszCopy, PwdInfoW.Comment);
  819. *ppPackageInfo = pInfo;
  820. return(SEC_E_OK);
  821. }
  822. return(SEC_E_INSUFFICIENT_MEMORY);
  823. }
  824. //+---------------------------------------------------------------------------
  825. //
  826. // Function: PwdpCopyInfoA
  827. //
  828. // Synopsis: copy ansi package info around
  829. //
  830. // Notes:
  831. //
  832. //----------------------------------------------------------------------------
  833. SECURITY_STATUS
  834. PwdpCopyInfoA(
  835. PSecPkgInfoA * ppPackageInfo)
  836. {
  837. DWORD cbTotal;
  838. PSecPkgInfoA pInfo;
  839. PSTR pszCopy;
  840. cbTotal = sizeof(SecPkgInfoA) +
  841. (strlen(PwdInfoA.Name) + strlen(PwdInfoA.Comment) + 2) * 2;
  842. pInfo = PwdAlloc( cbTotal );
  843. if (pInfo)
  844. {
  845. *pInfo = PwdInfoA;
  846. pszCopy = (PSTR) (pInfo + 1);
  847. pInfo->Name = pszCopy;
  848. strcpy(pszCopy, PwdInfoA.Name);
  849. pszCopy += strlen(PwdInfoA.Name) + 1;
  850. pInfo->Comment = pszCopy;
  851. strcpy(pszCopy, PwdInfoA.Comment);
  852. *ppPackageInfo = pInfo;
  853. return(SEC_E_OK);
  854. }
  855. return(SEC_E_INSUFFICIENT_MEMORY);
  856. }
  857. //+---------------------------------------------------------------------------
  858. //
  859. // Function: EnumerateSecurityPackagesW
  860. //
  861. // Synopsis: Enumerate packages in this DLL
  862. //
  863. // Arguments: [pcPackages] --
  864. // [info] --
  865. //
  866. // Notes:
  867. //
  868. //----------------------------------------------------------------------------
  869. SECURITY_STATUS
  870. SEC_ENTRY
  871. EnumerateSecurityPackagesW(
  872. unsigned long SEC_FAR * pcPackages, // Receives num. packages
  873. PSecPkgInfoW SEC_FAR * ppPackageInfo // Receives array of info
  874. )
  875. {
  876. SECURITY_STATUS scRet;
  877. *ppPackageInfo = NULL;
  878. scRet = PwdpCopyInfoW(ppPackageInfo);
  879. if (SUCCEEDED(scRet))
  880. {
  881. *pcPackages = 1;
  882. return(scRet);
  883. }
  884. *pcPackages = 0;
  885. return(scRet);
  886. }
  887. //+---------------------------------------------------------------------------
  888. //
  889. // Function: EnumerateSecurityPackagesA
  890. //
  891. // Synopsis: Enumerate
  892. //
  893. // Arguments: [pcPackages] --
  894. // [info] --
  895. //
  896. // Notes:
  897. //
  898. //----------------------------------------------------------------------------
  899. SECURITY_STATUS SEC_ENTRY
  900. EnumerateSecurityPackagesA(
  901. unsigned long SEC_FAR * pcPackages, // Receives num. packages
  902. PSecPkgInfoA SEC_FAR * ppPackageInfo // Receives array of info
  903. )
  904. {
  905. SECURITY_STATUS scRet;
  906. *ppPackageInfo = NULL;
  907. scRet = PwdpCopyInfoA(ppPackageInfo);
  908. if (SUCCEEDED(scRet))
  909. {
  910. *pcPackages = 1;
  911. return(scRet);
  912. }
  913. *pcPackages = 0;
  914. return(scRet);
  915. }
  916. //+---------------------------------------------------------------------------
  917. //
  918. // Function: QuerySecurityPackageInfoW
  919. //
  920. // Synopsis: Query individual package info
  921. //
  922. // Arguments: [pszPackageName] --
  923. // [info] --
  924. //
  925. // Notes:
  926. //
  927. //----------------------------------------------------------------------------
  928. SECURITY_STATUS SEC_ENTRY
  929. QuerySecurityPackageInfoW(
  930. SEC_WCHAR SEC_FAR * pszPackageName, // Name of package
  931. PSecPkgInfoW * ppPackageInfo // Receives package info
  932. )
  933. {
  934. if (_wcsicmp(pszPackageName, PWDSSP_NAME_W))
  935. {
  936. return(SEC_E_SECPKG_NOT_FOUND);
  937. }
  938. return(PwdpCopyInfoW(ppPackageInfo));
  939. }
  940. //+---------------------------------------------------------------------------
  941. //
  942. // Function: QuerySecurityPackageInfoA
  943. //
  944. // Synopsis: Same, ansi
  945. //
  946. // Arguments: [pszPackageName] --
  947. // [info] --
  948. //
  949. // Notes:
  950. //
  951. //----------------------------------------------------------------------------
  952. SECURITY_STATUS SEC_ENTRY
  953. QuerySecurityPackageInfoA(
  954. SEC_CHAR SEC_FAR * pszPackageName, // Name of package
  955. PSecPkgInfoA * ppPackageInfo // Receives package info
  956. )
  957. {
  958. if (_stricmp(pszPackageName, PWDSSP_NAME_A))
  959. {
  960. return(SEC_E_SECPKG_NOT_FOUND);
  961. }
  962. return(PwdpCopyInfoA(ppPackageInfo));
  963. }
  964. SECURITY_STATUS
  965. SEC_ENTRY
  966. MakeSignature(PCtxtHandle phContext,
  967. DWORD fQOP,
  968. PSecBufferDesc pMessage,
  969. ULONG MessageSeqNo)
  970. {
  971. return(SEC_E_UNSUPPORTED_FUNCTION);
  972. }
  973. SECURITY_STATUS SEC_ENTRY
  974. VerifySignature(PCtxtHandle phContext,
  975. PSecBufferDesc pMessage,
  976. ULONG MessageSeqNo,
  977. DWORD * pfQOP)
  978. {
  979. return(SEC_E_UNSUPPORTED_FUNCTION);
  980. }
  981. SECURITY_STATUS
  982. SEC_ENTRY
  983. SealMessage(PCtxtHandle phContext,
  984. DWORD fQOP,
  985. PSecBufferDesc pMessage,
  986. ULONG MessageSeqNo)
  987. {
  988. return(SEC_E_UNSUPPORTED_FUNCTION);
  989. }
  990. SECURITY_STATUS SEC_ENTRY
  991. UnsealMessage(PCtxtHandle phContext,
  992. PSecBufferDesc pMessage,
  993. ULONG MessageSeqNo,
  994. DWORD * pfQOP)
  995. {
  996. return(SEC_E_UNSUPPORTED_FUNCTION);
  997. }
  998. SECURITY_STATUS SEC_ENTRY
  999. ApplyControlToken(
  1000. PCtxtHandle phContext, // Context to modify
  1001. PSecBufferDesc pInput // Input token to apply
  1002. )
  1003. {
  1004. return( SEC_E_UNSUPPORTED_FUNCTION );
  1005. }
  1006. SECURITY_STATUS
  1007. SEC_ENTRY
  1008. FreeContextBuffer(
  1009. PVOID p)
  1010. {
  1011. if( p != NULL )
  1012. {
  1013. PwdFree( p );
  1014. }
  1015. return( SEC_E_OK );
  1016. }
  1017. SECURITY_STATUS
  1018. SEC_ENTRY
  1019. QuerySecurityContextToken(
  1020. PCtxtHandle phContext,
  1021. PHANDLE Token)
  1022. {
  1023. PPWD_CONTEXT Context;
  1024. Context = (PPWD_CONTEXT) phContext->dwUpper ;
  1025. if ( Context->Tag == CONTEXT_TAG )
  1026. {
  1027. *Token = Context->Token ;
  1028. return( SEC_E_OK );
  1029. }
  1030. return( SEC_E_INVALID_HANDLE );
  1031. }
  1032. SECURITY_STATUS SEC_ENTRY
  1033. CompleteAuthToken(
  1034. PCtxtHandle phContext, // Context to complete
  1035. PSecBufferDesc pToken // Token to complete
  1036. )
  1037. {
  1038. return( SEC_E_UNSUPPORTED_FUNCTION );
  1039. }
  1040. PSecurityFunctionTableA
  1041. SEC_ENTRY
  1042. InitSecurityInterfaceA( VOID )
  1043. {
  1044. return( &PwdTableA );
  1045. }
  1046. PSecurityFunctionTableW
  1047. SEC_ENTRY
  1048. InitSecurityInterfaceW( VOID )
  1049. {
  1050. return( &PwdTableW );
  1051. }
  1052. NTSTATUS
  1053. VerifyCredentials(
  1054. IN PWSTR UserName,
  1055. IN PWSTR DomainName,
  1056. IN PWSTR Password,
  1057. IN ULONG VerifyFlags
  1058. )
  1059. {
  1060. PKERB_VERIFY_CREDENTIALS_REQUEST pVerifyRequest;
  1061. KERB_VERIFY_CREDENTIALS_REQUEST VerifyRequest;
  1062. ULONG cbVerifyRequest;
  1063. PVOID pResponse = NULL;
  1064. ULONG cbResponse;
  1065. USHORT cbUserName;
  1066. USHORT cbDomainName;
  1067. USHORT cbPassword;
  1068. NTSTATUS ProtocolStatus = STATUS_LOGON_FAILURE;
  1069. NTSTATUS Status;
  1070. cbUserName = (USHORT)(lstrlenW(UserName) * sizeof(WCHAR)) ;
  1071. cbDomainName = (USHORT)(lstrlenW(DomainName) * sizeof(WCHAR)) ;
  1072. cbPassword = (USHORT)(lstrlenW(Password) * sizeof(WCHAR)) ;
  1073. cbVerifyRequest = sizeof(VerifyRequest) +
  1074. cbUserName +
  1075. cbDomainName +
  1076. cbPassword ;
  1077. pVerifyRequest = &VerifyRequest;
  1078. ZeroMemory( &VerifyRequest, sizeof(VerifyRequest) );
  1079. pVerifyRequest->MessageType = KerbVerifyCredentialsMessage ;
  1080. //
  1081. // do the length, buffers, copy, marshall dance.
  1082. //
  1083. pVerifyRequest->UserName.Length = cbUserName;
  1084. pVerifyRequest->UserName.MaximumLength = cbUserName;
  1085. pVerifyRequest->UserName.Buffer = UserName;
  1086. pVerifyRequest->DomainName.Length = cbDomainName;
  1087. pVerifyRequest->DomainName.MaximumLength = cbDomainName;
  1088. pVerifyRequest->DomainName.Buffer = DomainName;
  1089. pVerifyRequest->Password.Length = cbPassword;
  1090. pVerifyRequest->Password.MaximumLength = cbPassword;
  1091. pVerifyRequest->Password.Buffer = Password;
  1092. pVerifyRequest->VerifyFlags = VerifyFlags;
  1093. Status = I_LsaICallPackage(
  1094. &AuthenticationPackage,
  1095. pVerifyRequest,
  1096. cbVerifyRequest,
  1097. &pResponse,
  1098. &cbResponse,
  1099. &ProtocolStatus
  1100. );
  1101. if(!NT_SUCCESS(Status))
  1102. {
  1103. goto Cleanup;
  1104. }
  1105. Status = ProtocolStatus;
  1106. Cleanup:
  1107. return Status;
  1108. }