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.

2707 lines
76 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: credapi.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 9-18-96 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "sslp.h"
  18. #include "mapper.h"
  19. #include "rpc.h"
  20. #include <sslwow64.h>
  21. typedef struct _SCH_CRED_SECRET {
  22. union {
  23. SCH_CRED_SECRET_CAPI Capi;
  24. SCH_CRED_SECRET_PRIVKEY PrivKey;
  25. } u;
  26. } SCH_CRED_SECRET, * PSCH_CRED_SECRET ;
  27. extern CHAR CertTag[ 13 ];
  28. //+-------------------------------------------------------------------------
  29. //
  30. // Function: CopyClientString
  31. //
  32. // Synopsis: copies a client string to local memory, including
  33. // allocating space for it locally.
  34. //
  35. // Arguments:
  36. // SourceString - Could be Ansi or Wchar in client process
  37. // SourceLength - bytes
  38. // DoUnicode - whether the string is Wchar
  39. //
  40. // Returns:
  41. // DestinationString - Unicode String in Lsa Process
  42. //
  43. // Notes:
  44. //
  45. //--------------------------------------------------------------------------
  46. HRESULT
  47. CopyClientString(
  48. IN PWSTR SourceString,
  49. IN ULONG SourceLength,
  50. IN BOOLEAN DoUnicode,
  51. OUT PUNICODE_STRING DestinationString
  52. )
  53. {
  54. NTSTATUS Status = STATUS_SUCCESS;
  55. STRING TemporaryString;
  56. ULONG SourceSize = 0;
  57. ULONG CharacterSize = sizeof(CHAR);
  58. //
  59. // First initialize the string to zero, in case the source is a null
  60. // string
  61. //
  62. DestinationString->Length = DestinationString->MaximumLength = 0;
  63. DestinationString->Buffer = NULL;
  64. TemporaryString.Buffer = NULL;
  65. if (SourceString != NULL)
  66. {
  67. //
  68. // If the length is zero, allocate one byte for a "\0" terminator
  69. //
  70. if (SourceLength == 0)
  71. {
  72. DestinationString->Buffer = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR));
  73. if (DestinationString->Buffer == NULL)
  74. {
  75. Status = SP_LOG_RESULT(STATUS_NO_MEMORY);
  76. goto Cleanup;
  77. }
  78. DestinationString->MaximumLength = sizeof(WCHAR);
  79. *DestinationString->Buffer = L'\0';
  80. }
  81. else
  82. {
  83. //
  84. // Allocate a temporary buffer to hold the client string. We may
  85. // then create a buffer for the unicode version. The length
  86. // is the length in characters, so possible expand to hold unicode
  87. // characters and a null terminator.
  88. //
  89. if (DoUnicode)
  90. {
  91. CharacterSize = sizeof(WCHAR);
  92. }
  93. SourceSize = (SourceLength + 1) * CharacterSize;
  94. //
  95. // insure no overflow aggainst UNICODE_STRING
  96. //
  97. if ( (SourceSize > 0xFFFF) ||
  98. ((SourceSize - CharacterSize) > 0xFFFF)
  99. )
  100. {
  101. Status = SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
  102. goto Cleanup;
  103. }
  104. TemporaryString.Buffer = (LPSTR) LocalAlloc(LPTR, SourceSize);
  105. if (TemporaryString.Buffer == NULL)
  106. {
  107. Status = SP_LOG_RESULT(STATUS_NO_MEMORY);
  108. goto Cleanup;
  109. }
  110. TemporaryString.Length = (USHORT) (SourceSize - CharacterSize);
  111. TemporaryString.MaximumLength = (USHORT) SourceSize;
  112. //
  113. // Finally copy the string from the client
  114. //
  115. Status = LsaTable->CopyFromClientBuffer(
  116. NULL,
  117. SourceSize - CharacterSize,
  118. TemporaryString.Buffer,
  119. SourceString
  120. );
  121. if (!NT_SUCCESS(Status))
  122. {
  123. SP_LOG_RESULT(Status);
  124. goto Cleanup;
  125. }
  126. //
  127. // If we are doing unicode, finish up now
  128. //
  129. if (DoUnicode)
  130. {
  131. DestinationString->Buffer = (LPWSTR) TemporaryString.Buffer;
  132. DestinationString->Length = (USHORT) (SourceSize - CharacterSize);
  133. DestinationString->MaximumLength = (USHORT) SourceSize;
  134. }
  135. else
  136. {
  137. NTSTATUS Status1;
  138. Status1 = RtlAnsiStringToUnicodeString(
  139. DestinationString,
  140. &TemporaryString,
  141. TRUE
  142. ); // allocate destination
  143. if (!NT_SUCCESS(Status1))
  144. {
  145. Status = SP_LOG_RESULT(STATUS_NO_MEMORY);
  146. goto Cleanup;
  147. }
  148. }
  149. }
  150. }
  151. Cleanup:
  152. if (TemporaryString.Buffer != NULL)
  153. {
  154. //
  155. // Free this if we failed and were doing unicode or if we weren't
  156. // doing unicode
  157. //
  158. if ((DoUnicode && !NT_SUCCESS(Status)) || !DoUnicode)
  159. {
  160. LocalFree(TemporaryString.Buffer);
  161. }
  162. }
  163. return(Status);
  164. }
  165. //+---------------------------------------------------------------------------
  166. //
  167. // Function: SpAcceptCredentials
  168. //
  169. // Synopsis: Accept Credentials - logon notification
  170. //
  171. // Arguments: [LogonType] --
  172. // [UserName] --
  173. // [PrimaryCred] --
  174. // [SupplementalCreds] --
  175. //
  176. // History: 10-04-96 RichardW Created
  177. //
  178. // Notes:
  179. //
  180. //----------------------------------------------------------------------------
  181. SECURITY_STATUS
  182. SEC_ENTRY
  183. SpAcceptCredentials(
  184. IN SECURITY_LOGON_TYPE LogonType,
  185. IN PUNICODE_STRING UserName,
  186. IN PSECPKG_PRIMARY_CRED PrimaryCred,
  187. IN PSECPKG_SUPPLEMENTAL_CRED SupplementalCreds)
  188. {
  189. UNREFERENCED_PARAMETER(LogonType);
  190. UNREFERENCED_PARAMETER(UserName);
  191. UNREFERENCED_PARAMETER(PrimaryCred);
  192. UNREFERENCED_PARAMETER(SupplementalCreds);
  193. return( SEC_E_OK );
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Function: SpMapSchPublic
  198. //
  199. // Synopsis: Maps a public key credential into LSA memory
  200. //
  201. // Arguments: [pRemotePubs] --
  202. //
  203. // History: 10-06-96 RichardW Created
  204. //
  205. // Notes:
  206. //
  207. //----------------------------------------------------------------------------
  208. PVOID
  209. SpMapSchPublic(
  210. PVOID pRemotePubs
  211. )
  212. {
  213. SECURITY_STATUS Status ;
  214. SCH_CRED_PUBLIC_CERTCHAIN Pub, * pPub ;
  215. Status = LsaTable->CopyFromClientBuffer( NULL,
  216. sizeof( SCH_CRED_PUBLIC_CERTCHAIN ),
  217. &Pub,
  218. pRemotePubs );
  219. if ( !NT_SUCCESS( Status ) )
  220. {
  221. return( NULL );
  222. }
  223. // Reality check
  224. if(Pub.cbCertChain > 0x00100000)
  225. {
  226. return( NULL );
  227. }
  228. pPub = SPExternalAlloc( sizeof( SCH_CRED_PUBLIC_CERTCHAIN ) +
  229. Pub.cbCertChain );
  230. if ( pPub )
  231. {
  232. pPub->dwType = Pub.dwType ;
  233. pPub->cbCertChain = Pub.cbCertChain ;
  234. pPub->pCertChain = (PUCHAR) ( pPub + 1 );
  235. Status = LsaTable->CopyFromClientBuffer( NULL,
  236. Pub.cbCertChain,
  237. pPub->pCertChain,
  238. Pub.pCertChain );
  239. }
  240. else
  241. {
  242. Status = SEC_E_INSUFFICIENT_MEMORY ;
  243. }
  244. if ( NT_SUCCESS( Status ) )
  245. {
  246. return( pPub );
  247. }
  248. if ( pPub )
  249. {
  250. SPExternalFree( pPub );
  251. }
  252. return( NULL );
  253. }
  254. #ifdef _WIN64
  255. PVOID
  256. SpWow64MapSchPublic(
  257. SSLWOW64_PVOID pRemotePubs)
  258. {
  259. SECURITY_STATUS Status;
  260. SSLWOW64_SCH_CRED_PUBLIC_CERTCHAIN Pub;
  261. SCH_CRED_PUBLIC_CERTCHAIN * pPub;
  262. Status = LsaTable->CopyFromClientBuffer( NULL,
  263. sizeof( SSLWOW64_SCH_CRED_PUBLIC_CERTCHAIN ),
  264. &Pub,
  265. ULongToPtr(pRemotePubs));
  266. if ( !NT_SUCCESS( Status ) )
  267. {
  268. return( NULL );
  269. }
  270. // Reality check
  271. if(Pub.cbCertChain > 0x00100000)
  272. {
  273. return( NULL );
  274. }
  275. pPub = SPExternalAlloc( sizeof( SCH_CRED_PUBLIC_CERTCHAIN ) +
  276. Pub.cbCertChain );
  277. if ( pPub )
  278. {
  279. pPub->dwType = Pub.dwType ;
  280. pPub->cbCertChain = Pub.cbCertChain ;
  281. pPub->pCertChain = (PUCHAR) ( pPub + 1 );
  282. Status = LsaTable->CopyFromClientBuffer( NULL,
  283. Pub.cbCertChain,
  284. pPub->pCertChain,
  285. ULongToPtr(Pub.pCertChain));
  286. }
  287. else
  288. {
  289. Status = SEC_E_INSUFFICIENT_MEMORY ;
  290. }
  291. if ( NT_SUCCESS( Status ) )
  292. {
  293. return( pPub );
  294. }
  295. if ( pPub )
  296. {
  297. SPExternalFree( pPub );
  298. }
  299. return( NULL );
  300. }
  301. #endif // _WIN64
  302. PVOID
  303. SpMapSchCred(
  304. PVOID pRemoteCred )
  305. {
  306. SCH_CRED_SECRET Cred ;
  307. SECURITY_STATUS Status ;
  308. DWORD Size ;
  309. DWORD dwType;
  310. Status = LsaTable->CopyFromClientBuffer( NULL,
  311. sizeof( DWORD ),
  312. &Cred,
  313. pRemoteCred );
  314. if ( !NT_SUCCESS( Status ) )
  315. {
  316. return( NULL );
  317. }
  318. dwType = Cred.u.Capi.dwType;
  319. switch ( dwType )
  320. {
  321. case SCHANNEL_SECRET_TYPE_CAPI:
  322. Size = sizeof( SCH_CRED_SECRET_CAPI );
  323. break;
  324. case SCHANNEL_SECRET_PRIVKEY:
  325. Size = sizeof( SCH_CRED_SECRET_PRIVKEY );
  326. break;
  327. default:
  328. DebugOut(( DEB_ERROR, "Caller specified an unknown cred type\n" ));
  329. return( NULL );
  330. }
  331. if ( Size )
  332. {
  333. Status = LsaTable->CopyFromClientBuffer(NULL,
  334. Size,
  335. &Cred,
  336. pRemoteCred );
  337. }
  338. else
  339. {
  340. Status = SEC_E_INVALID_HANDLE ;
  341. }
  342. if(dwType != Cred.u.Capi.dwType)
  343. {
  344. Status = SEC_E_INVALID_HANDLE ;
  345. }
  346. if ( !NT_SUCCESS( Status ) )
  347. {
  348. return( NULL );
  349. }
  350. if(Cred.u.Capi.dwType == SCHANNEL_SECRET_TYPE_CAPI)
  351. {
  352. SCH_CRED_SECRET_CAPI *pCapiCred;
  353. pCapiCred = SPExternalAlloc( Size );
  354. if ( !pCapiCred )
  355. {
  356. return( NULL );
  357. }
  358. pCapiCred->dwType = Cred.u.Capi.dwType;
  359. pCapiCred->hProv = Cred.u.Capi.hProv;
  360. return( pCapiCred );
  361. }
  362. if(Cred.u.Capi.dwType == SCHANNEL_SECRET_PRIVKEY)
  363. {
  364. UCHAR Password[ MAX_PATH + 1 ];
  365. DWORD PasswordLen = 0;
  366. SCH_CRED_SECRET_PRIVKEY *pCred;
  367. //
  368. // The password is the painful part. Since it is a string, we don't know
  369. // how long it is. So, we have to take a stab at it:
  370. //
  371. Status = LsaTable->CopyFromClientBuffer( NULL,
  372. MAX_PATH,
  373. Password,
  374. Cred.u.PrivKey.pszPassword );
  375. if ( !NT_SUCCESS( Status ) )
  376. {
  377. return( NULL );
  378. }
  379. Password[ MAX_PATH ] = '\0';
  380. PasswordLen = lstrlenA( (LPSTR)Password );
  381. // Reality check private key length.
  382. if(Cred.u.PrivKey.cbPrivateKey > 0x10000)
  383. {
  384. return( NULL );
  385. }
  386. Size = PasswordLen + 1 + Cred.u.PrivKey.cbPrivateKey +
  387. sizeof( SCH_CRED_SECRET_PRIVKEY ) ;
  388. pCred = SPExternalAlloc( Size );
  389. if ( !pCred )
  390. {
  391. return( NULL );
  392. }
  393. pCred->dwType = Cred.u.PrivKey.dwType ;
  394. pCred->cbPrivateKey = Cred.u.PrivKey.cbPrivateKey ;
  395. pCred->pPrivateKey = (PBYTE) ( pCred + 1 );
  396. pCred->pszPassword = (LPSTR) (pCred->pPrivateKey + pCred->cbPrivateKey );
  397. RtlCopyMemory( pCred->pszPassword, Password, PasswordLen + 1 );
  398. Status = LsaTable->CopyFromClientBuffer( NULL,
  399. pCred->cbPrivateKey,
  400. pCred->pPrivateKey,
  401. Cred.u.PrivKey.pPrivateKey );
  402. if ( !NT_SUCCESS( Status ) )
  403. {
  404. SPExternalFree( pCred );
  405. return( NULL );
  406. }
  407. return( pCred );
  408. }
  409. return( NULL );
  410. }
  411. #ifdef _WIN64
  412. PVOID
  413. SpWow64MapSchCred(
  414. SSLWOW64_PVOID pRemoteCred )
  415. {
  416. SSLWOW64_SCH_CRED_SECRET_PRIVKEY LocalCred;
  417. SCH_CRED_SECRET_PRIVKEY *pCred;
  418. CHAR Password[MAX_PATH + 1];
  419. DWORD PasswordLen = 0;
  420. SECURITY_STATUS Status ;
  421. DWORD dwType;
  422. DWORD Size;
  423. Status = LsaTable->CopyFromClientBuffer( NULL,
  424. sizeof( DWORD ),
  425. &dwType,
  426. ULongToPtr(pRemoteCred));
  427. if ( !NT_SUCCESS( Status ) )
  428. {
  429. return( NULL );
  430. }
  431. if(dwType != SCHANNEL_SECRET_PRIVKEY)
  432. {
  433. DebugOut(( DEB_ERROR, "Caller specified an unknown cred type\n" ));
  434. return( NULL );
  435. }
  436. Status = LsaTable->CopyFromClientBuffer(NULL,
  437. sizeof(SSLWOW64_SCH_CRED_SECRET_PRIVKEY),
  438. &LocalCred,
  439. ULongToPtr(pRemoteCred));
  440. if ( !NT_SUCCESS( Status ) )
  441. {
  442. return( NULL );
  443. }
  444. //
  445. // The password is the painful part. Since it is a string, we don't know
  446. // how long it is. So, we have to take a stab at it:
  447. //
  448. Status = LsaTable->CopyFromClientBuffer( NULL,
  449. MAX_PATH,
  450. Password,
  451. ULongToPtr(LocalCred.pszPassword));
  452. if ( !NT_SUCCESS( Status ) )
  453. {
  454. return( NULL );
  455. }
  456. Password[ MAX_PATH ] = '\0';
  457. PasswordLen = lstrlenA( Password );
  458. // Reality check private key length.
  459. if(LocalCred.cbPrivateKey > 0x10000)
  460. {
  461. return( NULL );
  462. }
  463. Size = PasswordLen + 1 + LocalCred.cbPrivateKey +
  464. sizeof( SCH_CRED_SECRET_PRIVKEY ) ;
  465. pCred = SPExternalAlloc( Size );
  466. if ( !pCred )
  467. {
  468. return( NULL );
  469. }
  470. pCred->dwType = SCHANNEL_SECRET_PRIVKEY;
  471. pCred->cbPrivateKey = LocalCred.cbPrivateKey ;
  472. pCred->pPrivateKey = (PBYTE) ( pCred + 1 );
  473. pCred->pszPassword = (LPSTR) (pCred->pPrivateKey + pCred->cbPrivateKey );
  474. RtlCopyMemory( pCred->pszPassword, Password, PasswordLen + 1 );
  475. Status = LsaTable->CopyFromClientBuffer( NULL,
  476. pCred->cbPrivateKey,
  477. pCred->pPrivateKey,
  478. ULongToPtr(LocalCred.pPrivateKey));
  479. if ( !NT_SUCCESS( Status ) )
  480. {
  481. SPExternalFree( pCred );
  482. return( NULL );
  483. }
  484. return( pCred );
  485. }
  486. #endif // _WIN64
  487. VOID
  488. SpFreeVersion2Certificate(
  489. SCH_CRED * pCred
  490. )
  491. {
  492. DWORD i;
  493. for ( i = 0 ; i < pCred->cCreds ; i++ )
  494. {
  495. if ( pCred->paSecret[ i ] )
  496. {
  497. SPExternalFree( pCred->paSecret[ i ] );
  498. }
  499. if ( pCred->paPublic[ i ] )
  500. {
  501. SPExternalFree( pCred->paPublic[ i ] );
  502. }
  503. }
  504. SPExternalFree( pCred );
  505. }
  506. VOID
  507. SpFreeVersion3Certificate(
  508. PLSA_SCHANNEL_CRED pSchannelCred)
  509. {
  510. DWORD i;
  511. if(pSchannelCred->paSubCred)
  512. {
  513. for(i = 0; i < pSchannelCred->cSubCreds; i++)
  514. {
  515. PLSA_SCHANNEL_SUB_CRED pSubCred = pSchannelCred->paSubCred + i;
  516. if(pSubCred->pCert)
  517. {
  518. CertFreeCertificateContext(pSubCred->pCert);
  519. }
  520. if(pSubCred->pszPin)
  521. {
  522. SPExternalFree(pSubCred->pszPin);
  523. }
  524. if(pSubCred->pPrivateKey)
  525. {
  526. SPExternalFree(pSubCred->pPrivateKey);
  527. }
  528. if(pSubCred->pszPassword)
  529. {
  530. SPExternalFree(pSubCred->pszPassword);
  531. }
  532. memset(pSubCred, 0, sizeof(LSA_SCHANNEL_SUB_CRED));
  533. }
  534. SPExternalFree((PVOID)pSchannelCred->paSubCred);
  535. pSchannelCred->paSubCred = NULL;
  536. }
  537. if(pSchannelCred->hRootStore)
  538. {
  539. CertCloseStore(pSchannelCred->hRootStore, 0);
  540. pSchannelCred->hRootStore = 0;
  541. }
  542. if(pSchannelCred->palgSupportedAlgs)
  543. {
  544. SPExternalFree(pSchannelCred->palgSupportedAlgs);
  545. pSchannelCred->palgSupportedAlgs = 0;
  546. }
  547. ZeroMemory(pSchannelCred, sizeof(SCHANNEL_CRED));
  548. }
  549. SECURITY_STATUS
  550. SpMapProtoCredential(
  551. SSL_CREDENTIAL_CERTIFICATE *pSslCert,
  552. PSCH_CRED *ppSchCred)
  553. {
  554. SCH_CRED * pCred = NULL;
  555. SCH_CRED_PUBLIC_CERTCHAIN * pPub = NULL;
  556. SCH_CRED_SECRET_PRIVKEY * pPriv = NULL;
  557. CHAR Password[ MAX_PATH + 1 ];
  558. DWORD PasswordLen = 0;
  559. SECURITY_STATUS Status ;
  560. DWORD Size;
  561. #if DBG
  562. DebugLog((DEB_TRACE, "SpMapProtoCredential\n"));
  563. DBG_HEX_STRING(DEB_TRACE, (PBYTE)pSslCert, sizeof(SSL_CREDENTIAL_CERTIFICATE));
  564. #endif
  565. //
  566. // Map over the certificate.
  567. //
  568. // Reality check
  569. if(pSslCert->cbCertificate > 0x00100000)
  570. {
  571. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  572. goto error;
  573. }
  574. pPub = SPExternalAlloc( sizeof( SCH_CRED_PUBLIC_CERTCHAIN ) +
  575. pSslCert->cbCertificate );
  576. if ( pPub == NULL)
  577. {
  578. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  579. goto error;
  580. }
  581. pPub->dwType = SCH_CRED_X509_CERTCHAIN;
  582. pPub->cbCertChain = pSslCert->cbCertificate;
  583. pPub->pCertChain = (PUCHAR) ( pPub + 1 );
  584. Status = LsaTable->CopyFromClientBuffer( NULL,
  585. pSslCert->cbCertificate,
  586. pPub->pCertChain,
  587. pSslCert->pCertificate );
  588. if ( !NT_SUCCESS( Status ) )
  589. {
  590. goto error;
  591. }
  592. //
  593. // Map over the private key and password.
  594. //
  595. //
  596. // The password is the painful part. Since it is a string, we don't know
  597. // how long it is. So, we have to take a stab at it:
  598. //
  599. Status = LsaTable->CopyFromClientBuffer( NULL,
  600. MAX_PATH,
  601. Password,
  602. pSslCert->pszPassword );
  603. if ( !NT_SUCCESS( Status ) )
  604. {
  605. goto error;
  606. }
  607. Password[ MAX_PATH ] = '\0';
  608. PasswordLen = lstrlenA( Password );
  609. // Reality check private key length.
  610. if(pSslCert->cbPrivateKey > 0x100000)
  611. {
  612. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  613. goto error;
  614. }
  615. Size = PasswordLen + 1 + pSslCert->cbPrivateKey +
  616. sizeof( SCH_CRED_SECRET_PRIVKEY ) ;
  617. pPriv = SPExternalAlloc( Size );
  618. if(pPriv == NULL)
  619. {
  620. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  621. goto error;
  622. }
  623. pPriv->dwType = SCHANNEL_SECRET_PRIVKEY;
  624. pPriv->cbPrivateKey = pSslCert->cbPrivateKey ;
  625. pPriv->pPrivateKey = (PBYTE) ( pPriv + 1 );
  626. pPriv->pszPassword = (LPSTR) (pPriv->pPrivateKey + pPriv->cbPrivateKey );
  627. RtlCopyMemory( pPriv->pszPassword, Password, PasswordLen + 1 );
  628. Status = LsaTable->CopyFromClientBuffer( NULL,
  629. pSslCert->cbPrivateKey,
  630. pPriv->pPrivateKey,
  631. pSslCert->pPrivateKey );
  632. if ( !NT_SUCCESS( Status ) )
  633. {
  634. goto error;
  635. }
  636. //
  637. // Allocate SCH_CRED structure.
  638. //
  639. pCred = SPExternalAlloc(sizeof(SCH_CRED) + 2 * sizeof(PVOID));
  640. if(pCred == NULL)
  641. {
  642. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  643. goto error;
  644. }
  645. pCred->dwVersion = SCH_CRED_VERSION ;
  646. pCred->cCreds = 1 ;
  647. pCred->paSecret = (PVOID) ( pCred + 1 );
  648. pCred->paPublic = (PVOID) ( pCred->paSecret + 1 );
  649. pCred->paSecret[0] = pPriv;
  650. pCred->paPublic[0] = pPub;
  651. *ppSchCred = pCred;
  652. return SEC_E_OK;
  653. error:
  654. if(pCred) SPExternalFree(pCred);
  655. if(pPub) SPExternalFree(pPub);
  656. if(pPriv) SPExternalFree(pPriv);
  657. return Status;
  658. }
  659. #ifdef _WIN64
  660. SECURITY_STATUS
  661. SpWow64MapProtoCredential(
  662. SSLWOW64_CREDENTIAL_CERTIFICATE *pSslCert,
  663. PSCH_CRED *ppSchCred)
  664. {
  665. SCH_CRED * pCred = NULL;
  666. SCH_CRED_PUBLIC_CERTCHAIN * pPub = NULL;
  667. SCH_CRED_SECRET_PRIVKEY * pPriv = NULL;
  668. CHAR Password[ MAX_PATH + 1 ];
  669. DWORD PasswordLen = 0;
  670. SECURITY_STATUS Status ;
  671. DWORD Size;
  672. #if DBG
  673. DebugLog((DEB_TRACE, "SpWow64MapProtoCredential\n"));
  674. DBG_HEX_STRING(DEB_TRACE, (PBYTE)pSslCert, sizeof(SSLWOW64_CREDENTIAL_CERTIFICATE));
  675. #endif
  676. //
  677. // Map over the certificate.
  678. //
  679. // Reality check
  680. if(pSslCert->cbCertificate > 0x00100000)
  681. {
  682. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  683. goto error;
  684. }
  685. pPub = SPExternalAlloc( sizeof( SCH_CRED_PUBLIC_CERTCHAIN ) +
  686. pSslCert->cbCertificate );
  687. if ( pPub == NULL)
  688. {
  689. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  690. goto error;
  691. }
  692. pPub->dwType = SCH_CRED_X509_CERTCHAIN;
  693. pPub->cbCertChain = pSslCert->cbCertificate;
  694. pPub->pCertChain = (PUCHAR) ( pPub + 1 );
  695. Status = LsaTable->CopyFromClientBuffer( NULL,
  696. pSslCert->cbCertificate,
  697. pPub->pCertChain,
  698. ULongToPtr(pSslCert->pCertificate));
  699. if ( !NT_SUCCESS( Status ) )
  700. {
  701. goto error;
  702. }
  703. //
  704. // Map over the private key and password.
  705. //
  706. //
  707. // The password is the painful part. Since it is a string, we don't know
  708. // how long it is. So, we have to take a stab at it:
  709. //
  710. Status = LsaTable->CopyFromClientBuffer( NULL,
  711. MAX_PATH,
  712. Password,
  713. ULongToPtr(pSslCert->pszPassword));
  714. if ( !NT_SUCCESS( Status ) )
  715. {
  716. goto error;
  717. }
  718. Password[ MAX_PATH ] = '\0';
  719. PasswordLen = lstrlenA( Password );
  720. // Reality check private key length.
  721. if(pSslCert->cbPrivateKey > 0x100000)
  722. {
  723. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  724. goto error;
  725. }
  726. Size = PasswordLen + 1 + pSslCert->cbPrivateKey +
  727. sizeof( SCH_CRED_SECRET_PRIVKEY ) ;
  728. pPriv = SPExternalAlloc( Size );
  729. if(pPriv == NULL)
  730. {
  731. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  732. goto error;
  733. }
  734. pPriv->dwType = SCHANNEL_SECRET_PRIVKEY;
  735. pPriv->cbPrivateKey = pSslCert->cbPrivateKey ;
  736. pPriv->pPrivateKey = (PBYTE) ( pPriv + 1 );
  737. pPriv->pszPassword = (LPSTR) (pPriv->pPrivateKey + pPriv->cbPrivateKey );
  738. RtlCopyMemory( pPriv->pszPassword, Password, PasswordLen + 1 );
  739. Status = LsaTable->CopyFromClientBuffer( NULL,
  740. pSslCert->cbPrivateKey,
  741. pPriv->pPrivateKey,
  742. ULongToPtr(pSslCert->pPrivateKey));
  743. if ( !NT_SUCCESS( Status ) )
  744. {
  745. goto error;
  746. }
  747. //
  748. // Allocate SCH_CRED structure.
  749. //
  750. pCred = SPExternalAlloc(sizeof(SCH_CRED) + 2 * sizeof(PVOID));
  751. if(pCred == NULL)
  752. {
  753. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  754. goto error;
  755. }
  756. pCred->dwVersion = SCH_CRED_VERSION ;
  757. pCred->cCreds = 1 ;
  758. pCred->paSecret = (PVOID) ( pCred + 1 );
  759. pCred->paPublic = (PVOID) ( pCred->paSecret + 1 );
  760. pCred->paSecret[0] = pPriv;
  761. pCred->paPublic[0] = pPub;
  762. *ppSchCred = pCred;
  763. return SEC_E_OK;
  764. error:
  765. if(pCred) SPExternalFree(pCred);
  766. if(pPub) SPExternalFree(pPub);
  767. if(pPriv) SPExternalFree(pPriv);
  768. return Status;
  769. }
  770. #endif // _WIN64
  771. SECURITY_STATUS
  772. SpMapVersion2Certificate(
  773. PVOID pvAuthData,
  774. SCH_CRED * *ppCred
  775. )
  776. {
  777. SECURITY_STATUS Status ;
  778. SCH_CRED Cred;
  779. PSCH_CRED pCred;
  780. DWORD Size;
  781. DWORD i;
  782. BOOL Failed = FALSE ;
  783. Status = LsaTable->CopyFromClientBuffer( NULL,
  784. sizeof( SCH_CRED ),
  785. &Cred,
  786. pvAuthData );
  787. if ( !NT_SUCCESS( Status ) )
  788. {
  789. return( Status );
  790. }
  791. #if DBG
  792. DebugLog((DEB_TRACE, "SpMapVersion2Certificate: %d certificates in cred\n", Cred.cCreds));
  793. DBG_HEX_STRING(DEB_TRACE, (PBYTE)&Cred, sizeof(SCH_CRED));
  794. #endif
  795. // Reality check credential count.
  796. if(Cred.cCreds > 100)
  797. {
  798. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  799. }
  800. Size = sizeof( SCH_CRED ) + (2 * Cred.cCreds * sizeof( PVOID ) );
  801. pCred = SPExternalAlloc( Size );
  802. if(pCred == NULL)
  803. {
  804. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  805. }
  806. pCred->dwVersion = Cred.dwVersion ;
  807. pCred->cCreds = Cred.cCreds ;
  808. pCred->paSecret = (PVOID) ( pCred + 1 );
  809. pCred->paPublic = (PVOID) ( pCred->paSecret + Cred.cCreds );
  810. Status = LsaTable->CopyFromClientBuffer( NULL,
  811. sizeof( PVOID ) * Cred.cCreds,
  812. pCred->paSecret,
  813. Cred.paSecret );
  814. if ( NT_SUCCESS( Status ) )
  815. {
  816. Status = LsaTable->CopyFromClientBuffer( NULL,
  817. sizeof( PVOID ) * Cred.cCreds,
  818. pCred->paPublic,
  819. Cred.paPublic );
  820. }
  821. if ( !NT_SUCCESS( Status ) )
  822. {
  823. SPExternalFree( pCred );
  824. return( Status );
  825. }
  826. //
  827. // Ok. We have pCred in local memory, with a chain of cert/private key
  828. // stuff hanging off of it. We now have to map in each one. Happy, happy.
  829. //
  830. for ( i = 0 ; i < Cred.cCreds ; i++ )
  831. {
  832. pCred->paSecret[i] = SpMapSchCred( pCred->paSecret[i] );
  833. if ( pCred->paSecret[i] == NULL )
  834. {
  835. Failed = TRUE ;
  836. }
  837. }
  838. for ( i = 0 ; i < Cred.cCreds ; i++ )
  839. {
  840. pCred->paPublic[i] = SpMapSchPublic( pCred->paPublic[i] );
  841. if ( pCred->paPublic[i] == NULL )
  842. {
  843. Failed = TRUE ;
  844. }
  845. }
  846. if ( Failed )
  847. {
  848. SpFreeVersion2Certificate( pCred );
  849. pCred = NULL ;
  850. Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS) ;
  851. }
  852. *ppCred = pCred ;
  853. return( Status );
  854. }
  855. #ifdef _WIN64
  856. SECURITY_STATUS
  857. SpWow64MapVersion2Certificate(
  858. PVOID pvAuthData,
  859. SCH_CRED * *ppCred
  860. )
  861. {
  862. SECURITY_STATUS Status ;
  863. SSLWOW64_SCH_CRED Cred;
  864. PSCH_CRED pCred;
  865. DWORD Size;
  866. BOOL Failed = FALSE ;
  867. Status = LsaTable->CopyFromClientBuffer( NULL,
  868. sizeof( SSLWOW64_SCH_CRED ),
  869. &Cred,
  870. pvAuthData );
  871. if ( !NT_SUCCESS( Status ) )
  872. {
  873. return( Status );
  874. }
  875. #if DBG
  876. DebugLog((DEB_TRACE, "SpMapVersion2Certificate: %d certificates in cred\n", Cred.cCreds));
  877. DBG_HEX_STRING(DEB_TRACE, (PBYTE)&Cred, sizeof(SCH_CRED));
  878. #endif
  879. if(Cred.cCreds > 100)
  880. {
  881. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  882. }
  883. if(Cred.cCreds > 1)
  884. {
  885. // Only support a single certificate, which is all that anyone
  886. // ever uses anyway.
  887. Cred.cCreds = 1;
  888. }
  889. Size = sizeof( SCH_CRED ) + (2 * Cred.cCreds * sizeof( PVOID ) );
  890. pCred = SPExternalAlloc( Size );
  891. if(pCred == NULL)
  892. {
  893. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  894. }
  895. pCred->dwVersion = Cred.dwVersion;
  896. pCred->cCreds = Cred.cCreds;
  897. if(pCred->cCreds > 0)
  898. {
  899. SSLWOW64_PVOID ClientSecret = 0;
  900. SSLWOW64_PVOID ClientPublic = 0;
  901. pCred->paSecret = (PVOID) ( pCred + 1 );
  902. pCred->paPublic = (PVOID) ( pCred->paSecret + Cred.cCreds );
  903. Status = LsaTable->CopyFromClientBuffer( NULL,
  904. sizeof(SSLWOW64_PVOID),
  905. &ClientSecret,
  906. ULongToPtr(Cred.paSecret));
  907. if ( NT_SUCCESS( Status ) )
  908. {
  909. Status = LsaTable->CopyFromClientBuffer( NULL,
  910. sizeof(SSLWOW64_PVOID),
  911. &ClientPublic,
  912. ULongToPtr(Cred.paPublic));
  913. }
  914. if ( !NT_SUCCESS( Status ) )
  915. {
  916. SPExternalFree( pCred );
  917. return( Status );
  918. }
  919. pCred->paSecret[0] = SpWow64MapSchCred(ClientSecret);
  920. if ( pCred->paSecret[0] == NULL )
  921. {
  922. Failed = TRUE ;
  923. }
  924. pCred->paPublic[0] = SpWow64MapSchPublic(ClientPublic);
  925. if ( pCred->paPublic[0] == NULL )
  926. {
  927. Failed = TRUE ;
  928. }
  929. }
  930. if ( Failed )
  931. {
  932. SpFreeVersion2Certificate( pCred );
  933. pCred = NULL ;
  934. Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS) ;
  935. }
  936. *ppCred = pCred ;
  937. return( Status );
  938. }
  939. #endif // _WIN64
  940. // Selectively enable the unified protocol.
  941. DWORD
  942. EnableUnifiedProtocol(DWORD dwPackageType, DWORD dwProtocol)
  943. {
  944. DWORD cProts = 0;
  945. // Disable unified.
  946. dwProtocol &= ~SP_PROT_UNI;
  947. if(dwPackageType & SP_PROT_UNI)
  948. {
  949. // Count enabled protocols.
  950. if(dwProtocol & SP_PROT_PCT1) cProts++;
  951. if(dwProtocol & SP_PROT_SSL2) cProts++;
  952. if(dwProtocol & (SP_PROT_SSL3 | SP_PROT_TLS1)) cProts++;
  953. // Enable unified if multiple protocols enabled.
  954. if(cProts > 1)
  955. {
  956. if(dwPackageType & SP_PROT_CLIENTS)
  957. {
  958. dwProtocol |= SP_PROT_UNI_CLIENT;
  959. }
  960. else
  961. {
  962. dwProtocol |= SP_PROT_UNI_SERVER;
  963. }
  964. }
  965. }
  966. return dwProtocol;
  967. }
  968. typedef struct _V3_SCHANNEL_CRED
  969. {
  970. DWORD dwVersion; // always SCHANNEL_CRED_VERSION
  971. DWORD cCreds;
  972. PCCERT_CONTEXT *paCred;
  973. HCERTSTORE hRootStore;
  974. DWORD cMappers;
  975. struct _HMAPPER **aphMappers;
  976. DWORD cSupportedAlgs;
  977. ALG_ID * palgSupportedAlgs;
  978. DWORD grbitEnabledProtocols;
  979. DWORD dwMinimumCipherStrength;
  980. DWORD dwMaximumCipherStrength;
  981. DWORD dwSessionLifespan;
  982. } V3_SCHANNEL_CRED;
  983. //+---------------------------------------------------------------------------
  984. //
  985. // Function: SpMapVersion3Certificate
  986. //
  987. // Synopsis: Maps a version 3 schannel credential into LSA memory
  988. //
  989. // Arguments: [pvAuthData] -- pointer to cred in application process
  990. // [pCred] -- pointer to cred in LSA process
  991. //
  992. // History: 09-23-97 jbanes Created
  993. //
  994. // Notes: The credential consists of the following structure. Note
  995. // that all CryptoAPI 2.0 handles must be mapped over as well,
  996. // via the callback mechanism.
  997. //
  998. // typedef struct _SCHANNEL_CRED
  999. // {
  1000. // DWORD dwVersion;
  1001. // DWORD cCreds;
  1002. // PCCERT_CONTEXT *paCred;
  1003. // HCERTSTORE hRootStore;
  1004. //
  1005. // DWORD cMappers;
  1006. // struct _HMAPPER **aphMappers;
  1007. //
  1008. // DWORD cSupportedAlgs;
  1009. // ALG_ID *palgSupportedAlgs;
  1010. //
  1011. // DWORD grbitEnabledProtocols;
  1012. // DWORD dwMinimumCipherStrength;
  1013. // DWORD dwMaximumCipherStrength;
  1014. // DWORD dwSessionLifespan;
  1015. //
  1016. // } SCHANNEL_CRED, *PSCHANNEL_CRED;
  1017. //
  1018. //----------------------------------------------------------------------------
  1019. SECURITY_STATUS
  1020. SpMapVersion3Certificate(
  1021. PVOID pvAuthData, // in
  1022. DWORD dwVersion, // in
  1023. PLSA_SCHANNEL_CRED pCred) // out
  1024. {
  1025. PCERT_CONTEXT * pLocalCredList = NULL;
  1026. HCERTSTORE hStore = NULL;
  1027. CRYPT_DATA_BLOB Serialized;
  1028. SCHANNEL_CRED LocalCred;
  1029. SecBuffer Input;
  1030. SecBuffer Output;
  1031. PBYTE pbBuffer;
  1032. DWORD cbBuffer;
  1033. DWORD cbData;
  1034. SECURITY_STATUS scRet;
  1035. DWORD Size;
  1036. DWORD iCred;
  1037. Output.pvBuffer = NULL;
  1038. //
  1039. // Copy over the SCHANNEL_CRED structure.
  1040. //
  1041. if(dwVersion == SCH_CRED_V3)
  1042. {
  1043. scRet = LsaTable->CopyFromClientBuffer(NULL,
  1044. sizeof(V3_SCHANNEL_CRED),
  1045. &LocalCred,
  1046. pvAuthData);
  1047. if(!NT_SUCCESS(scRet))
  1048. {
  1049. goto cleanup;
  1050. }
  1051. LocalCred.dwFlags = 0;
  1052. LocalCred.reserved = 0;
  1053. #if DBG
  1054. DebugLog((DEB_TRACE, "SpMapVersion3Certificate: %d certificates in cred\n", LocalCred.cCreds));
  1055. DBG_HEX_STRING(DEB_TRACE, (PBYTE)&LocalCred, sizeof(V3_SCHANNEL_CRED));
  1056. #endif
  1057. }
  1058. else
  1059. {
  1060. scRet = LsaTable->CopyFromClientBuffer(NULL,
  1061. sizeof(SCHANNEL_CRED),
  1062. &LocalCred,
  1063. pvAuthData);
  1064. if(!NT_SUCCESS(scRet))
  1065. {
  1066. goto cleanup;
  1067. }
  1068. #if DBG
  1069. DebugLog((DEB_TRACE, "SpMapVersion4Certificate: %d certificates in cred\n", LocalCred.cCreds));
  1070. DBG_HEX_STRING(DEB_TRACE, (PBYTE)&LocalCred, sizeof(SCHANNEL_CRED));
  1071. #endif
  1072. }
  1073. //
  1074. // DWORD dwVersion;
  1075. //
  1076. memset(pCred, 0, sizeof(LSA_SCHANNEL_CRED));
  1077. pCred->dwVersion = LocalCred.dwVersion;
  1078. //
  1079. // DWORD cCreds;
  1080. // PCCERT_CONTEXT *paCred;
  1081. //
  1082. if(LocalCred.cCreds && LocalCred.paCred)
  1083. {
  1084. Size = LocalCred.cCreds * sizeof(PVOID);
  1085. // Reality check credential count.
  1086. if(LocalCred.cCreds > 1000)
  1087. {
  1088. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1089. goto cleanup;
  1090. }
  1091. // Make local copy of application cred list.
  1092. pLocalCredList = SPExternalAlloc(Size);
  1093. if(pLocalCredList == NULL)
  1094. {
  1095. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1096. goto cleanup;
  1097. }
  1098. scRet = LsaTable->CopyFromClientBuffer(
  1099. NULL,
  1100. Size,
  1101. pLocalCredList,
  1102. (PCERT_CONTEXT *)LocalCred.paCred);
  1103. if(!NT_SUCCESS(scRet))
  1104. {
  1105. goto cleanup;
  1106. }
  1107. // Allocate memory for our cred list.
  1108. pCred->cSubCreds = LocalCred.cCreds;
  1109. pCred->paSubCred = SPExternalAlloc(pCred->cSubCreds * sizeof(LSA_SCHANNEL_SUB_CRED));
  1110. if(pCred->paSubCred == NULL)
  1111. {
  1112. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1113. goto cleanup;
  1114. }
  1115. // Create an in-memory certificate store.
  1116. hStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
  1117. 0, 0,
  1118. CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
  1119. 0);
  1120. if(hStore == NULL)
  1121. {
  1122. SP_LOG_RESULT(GetLastError());
  1123. scRet = SEC_E_INSUFFICIENT_MEMORY;
  1124. goto cleanup;
  1125. }
  1126. // Copy over each certificate context.
  1127. for(iCred = 0; iCred < LocalCred.cCreds; iCred++)
  1128. {
  1129. PLSA_SCHANNEL_SUB_CRED pSubCred;
  1130. pSubCred = pCred->paSubCred + iCred;
  1131. Input.BufferType = SECBUFFER_DATA;
  1132. Input.cbBuffer = sizeof(PVOID);
  1133. Input.pvBuffer = (PVOID)&pLocalCredList[iCred];
  1134. scRet = PerformApplicationCallback(SCH_UPLOAD_CREDENTIAL_CALLBACK,
  1135. 0, 0,
  1136. &Input,
  1137. &Output,
  1138. TRUE);
  1139. if(!NT_SUCCESS(scRet))
  1140. {
  1141. Output.pvBuffer = NULL;
  1142. goto cleanup;
  1143. }
  1144. pbBuffer = Output.pvBuffer;
  1145. cbBuffer = Output.cbBuffer;
  1146. if(pbBuffer == NULL ||
  1147. cbBuffer < sizeof(HCRYPTPROV) + sizeof(DWORD))
  1148. {
  1149. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1150. goto cleanup;
  1151. }
  1152. // Parse hProv.
  1153. pSubCred->hRemoteProv = *(HCRYPTPROV *)pbBuffer;
  1154. pbBuffer += sizeof(HCRYPTPROV);
  1155. cbBuffer -= sizeof(HCRYPTPROV);
  1156. // Parse certificate context length.
  1157. cbData = *(DWORD *)pbBuffer;
  1158. pbBuffer += sizeof(DWORD);
  1159. cbBuffer -= sizeof(DWORD);
  1160. // Parse certificate context.
  1161. if(cbBuffer < cbData)
  1162. {
  1163. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1164. goto cleanup;
  1165. }
  1166. if(!CertAddSerializedElementToStore(hStore,
  1167. pbBuffer,
  1168. cbData,
  1169. CERT_STORE_ADD_ALWAYS,
  1170. 0,
  1171. CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
  1172. NULL,
  1173. &pSubCred->pCert))
  1174. {
  1175. scRet = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1176. goto cleanup;
  1177. }
  1178. // Free the output buffer.
  1179. SPExternalFree(Output.pvBuffer);
  1180. Output.pvBuffer = NULL;
  1181. }
  1182. }
  1183. //
  1184. // HCERTSTORE hRootStore;
  1185. //
  1186. if(LocalCred.hRootStore != NULL)
  1187. {
  1188. Input.BufferType = SECBUFFER_DATA;
  1189. Input.cbBuffer = sizeof(HCERTSTORE);
  1190. Input.pvBuffer = (PVOID)&LocalCred.hRootStore;
  1191. scRet = PerformApplicationCallback(SCH_UPLOAD_CERT_STORE_CALLBACK,
  1192. 0, 0,
  1193. &Input,
  1194. &Output,
  1195. TRUE);
  1196. if(scRet != SEC_E_OK)
  1197. {
  1198. goto cleanup;
  1199. }
  1200. pbBuffer = Output.pvBuffer;
  1201. cbBuffer = Output.cbBuffer;
  1202. if(pbBuffer == NULL || cbBuffer < sizeof(DWORD))
  1203. {
  1204. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1205. goto cleanup;
  1206. }
  1207. // Parse certificate store.
  1208. Serialized.cbData = *(DWORD *)pbBuffer;
  1209. Serialized.pbData = pbBuffer + sizeof(DWORD);
  1210. if(cbBuffer - sizeof(DWORD) < Serialized.cbData)
  1211. {
  1212. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1213. goto cleanup;
  1214. }
  1215. pCred->hRootStore = CertOpenStore( CERT_STORE_PROV_SERIALIZED,
  1216. X509_ASN_ENCODING,
  1217. 0, 0,
  1218. &Serialized);
  1219. if(pCred->hRootStore == NULL)
  1220. {
  1221. scRet = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1222. goto cleanup;
  1223. }
  1224. // Free the output buffer.
  1225. SPExternalFree(Output.pvBuffer);
  1226. Output.pvBuffer = NULL;
  1227. }
  1228. //
  1229. // DWORD cSupportedAlgs;
  1230. // ALG_ID *palgSupportedAlgs;
  1231. //
  1232. if(LocalCred.cSupportedAlgs && LocalCred.palgSupportedAlgs)
  1233. {
  1234. // Reality check.
  1235. if(LocalCred.cSupportedAlgs > 1000)
  1236. {
  1237. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1238. goto cleanup;
  1239. }
  1240. Size = LocalCred.cSupportedAlgs * sizeof(ALG_ID);
  1241. pCred->cSupportedAlgs = LocalCred.cSupportedAlgs;
  1242. pCred->palgSupportedAlgs = SPExternalAlloc(Size);
  1243. if(pCred->palgSupportedAlgs == NULL)
  1244. {
  1245. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1246. goto cleanup;
  1247. }
  1248. scRet = LsaTable->CopyFromClientBuffer(NULL,
  1249. Size,
  1250. pCred->palgSupportedAlgs,
  1251. LocalCred.palgSupportedAlgs);
  1252. if(!NT_SUCCESS(scRet))
  1253. {
  1254. goto cleanup;
  1255. }
  1256. }
  1257. //
  1258. // DWORD grbitEnabledProtocols;
  1259. // DWORD dwMinimumCipherStrength;
  1260. // DWORD dwMaximumCipherStrength;
  1261. // DWORD dwSessionLifespan;
  1262. // DWORD dwFlags;
  1263. // DWORD reserved;
  1264. //
  1265. pCred->grbitEnabledProtocols = LocalCred.grbitEnabledProtocols;
  1266. pCred->dwMinimumCipherStrength = LocalCred.dwMinimumCipherStrength;
  1267. pCred->dwMaximumCipherStrength = LocalCred.dwMaximumCipherStrength;
  1268. pCred->dwSessionLifespan = LocalCred.dwSessionLifespan;
  1269. pCred->dwFlags = LocalCred.dwFlags;
  1270. pCred->reserved = LocalCred.reserved;
  1271. scRet = SEC_E_OK;
  1272. cleanup:
  1273. if(Output.pvBuffer)
  1274. {
  1275. SPExternalFree(Output.pvBuffer);
  1276. }
  1277. if(pLocalCredList)
  1278. {
  1279. SPExternalFree(pLocalCredList);
  1280. }
  1281. if(hStore)
  1282. {
  1283. CertCloseStore(hStore, 0);
  1284. }
  1285. if(!NT_SUCCESS(scRet))
  1286. {
  1287. SpFreeVersion3Certificate(pCred);
  1288. }
  1289. return scRet;
  1290. }
  1291. #ifdef _WIN64
  1292. SECURITY_STATUS
  1293. SpWow64MapVersion3Certificate(
  1294. PVOID pvAuthData, // in
  1295. DWORD dwVersion, // in
  1296. PLSA_SCHANNEL_CRED pCred) // out
  1297. {
  1298. SSLWOW64_PCCERT_CONTEXT *pLocalCredList = NULL;
  1299. HCERTSTORE hStore = NULL;
  1300. CRYPT_DATA_BLOB Serialized;
  1301. SSLWOW64_SCHANNEL_CRED LocalCred;
  1302. SecBuffer Input;
  1303. SecBuffer Output;
  1304. PBYTE pbBuffer;
  1305. DWORD cbBuffer;
  1306. DWORD cbData;
  1307. SECURITY_STATUS scRet;
  1308. DWORD Size;
  1309. DWORD iCred;
  1310. Output.pvBuffer = NULL;
  1311. //
  1312. // Copy over the SCHANNEL_CRED structure.
  1313. //
  1314. if(dwVersion == SCH_CRED_V3)
  1315. {
  1316. scRet = LsaTable->CopyFromClientBuffer(NULL,
  1317. sizeof(SSLWOW64_SCHANNEL3_CRED),
  1318. &LocalCred,
  1319. pvAuthData);
  1320. if(!NT_SUCCESS(scRet))
  1321. {
  1322. goto cleanup;
  1323. }
  1324. LocalCred.dwFlags = 0;
  1325. LocalCred.reserved = 0;
  1326. #if DBG
  1327. DebugLog((DEB_TRACE, "SpMapVersion3Certificate: %d certificates in cred\n", LocalCred.cCreds));
  1328. DBG_HEX_STRING(DEB_TRACE, (PBYTE)&LocalCred, sizeof(SSLWOW64_SCHANNEL_CRED));
  1329. #endif
  1330. }
  1331. else
  1332. {
  1333. scRet = LsaTable->CopyFromClientBuffer(NULL,
  1334. sizeof(SSLWOW64_SCHANNEL_CRED),
  1335. &LocalCred,
  1336. pvAuthData);
  1337. if(!NT_SUCCESS(scRet))
  1338. {
  1339. goto cleanup;
  1340. }
  1341. #if DBG
  1342. DebugLog((DEB_TRACE, "SpMapVersion4Certificate: %d certificates in cred\n", LocalCred.cCreds));
  1343. DBG_HEX_STRING(DEB_TRACE, (PBYTE)&LocalCred, sizeof(SSLWOW64_SCHANNEL_CRED));
  1344. #endif
  1345. }
  1346. //
  1347. // DWORD dwVersion;
  1348. //
  1349. memset(pCred, 0, sizeof(LSA_SCHANNEL_CRED));
  1350. pCred->dwVersion = LocalCred.dwVersion;
  1351. //
  1352. // DWORD cCreds;
  1353. // PCCERT_CONTEXT *paCred;
  1354. //
  1355. if(LocalCred.cCreds && LocalCred.paCred)
  1356. {
  1357. Size = LocalCred.cCreds * sizeof(SSLWOW64_PCCERT_CONTEXT);
  1358. // Reality check credential count.
  1359. if(LocalCred.cCreds > 1000)
  1360. {
  1361. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1362. goto cleanup;
  1363. }
  1364. // Make local copy of application cred list.
  1365. pLocalCredList = SPExternalAlloc(Size);
  1366. if(pLocalCredList == NULL)
  1367. {
  1368. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1369. goto cleanup;
  1370. }
  1371. scRet = LsaTable->CopyFromClientBuffer(
  1372. NULL,
  1373. Size,
  1374. pLocalCredList,
  1375. ULongToPtr(LocalCred.paCred));
  1376. if(!NT_SUCCESS(scRet))
  1377. {
  1378. goto cleanup;
  1379. }
  1380. // Allocate memory for our cred list.
  1381. pCred->cSubCreds = LocalCred.cCreds;
  1382. pCred->paSubCred = SPExternalAlloc(pCred->cSubCreds * sizeof(LSA_SCHANNEL_SUB_CRED));
  1383. if(pCred->paSubCred == NULL)
  1384. {
  1385. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1386. goto cleanup;
  1387. }
  1388. // Create an in-memory certificate store.
  1389. hStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
  1390. 0, 0,
  1391. CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
  1392. 0);
  1393. if(hStore == NULL)
  1394. {
  1395. SP_LOG_RESULT(GetLastError());
  1396. scRet = SEC_E_INSUFFICIENT_MEMORY;
  1397. goto cleanup;
  1398. }
  1399. // Copy over each certificate context.
  1400. for(iCred = 0; iCred < LocalCred.cCreds; iCred++)
  1401. {
  1402. PLSA_SCHANNEL_SUB_CRED pSubCred;
  1403. pSubCred = pCred->paSubCred + iCred;
  1404. Input.BufferType = SECBUFFER_DATA;
  1405. Input.cbBuffer = sizeof(SSLWOW64_PCCERT_CONTEXT);
  1406. Input.pvBuffer = (PVOID)&pLocalCredList[iCred];
  1407. scRet = PerformApplicationCallback(SCH_UPLOAD_CREDENTIAL_CALLBACK,
  1408. 0, 0,
  1409. &Input,
  1410. &Output,
  1411. TRUE);
  1412. if(!NT_SUCCESS(scRet))
  1413. {
  1414. Output.pvBuffer = NULL;
  1415. goto cleanup;
  1416. }
  1417. pbBuffer = Output.pvBuffer;
  1418. cbBuffer = Output.cbBuffer;
  1419. if(pbBuffer == NULL ||
  1420. cbBuffer < sizeof(HCRYPTPROV) + sizeof(DWORD))
  1421. {
  1422. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1423. goto cleanup;
  1424. }
  1425. // Parse hProv.
  1426. pSubCred->hRemoteProv = *(SSLWOW64_HCRYPTPROV *)pbBuffer;
  1427. pbBuffer += sizeof(SSLWOW64_HCRYPTPROV);
  1428. cbBuffer -= sizeof(SSLWOW64_HCRYPTPROV);
  1429. // Parse certificate context length.
  1430. cbData = *(DWORD *)pbBuffer;
  1431. pbBuffer += sizeof(DWORD);
  1432. cbBuffer -= sizeof(DWORD);
  1433. // Parse certificate context.
  1434. if(cbBuffer < cbData)
  1435. {
  1436. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1437. goto cleanup;
  1438. }
  1439. if(!CertAddSerializedElementToStore(hStore,
  1440. pbBuffer,
  1441. cbData,
  1442. CERT_STORE_ADD_ALWAYS,
  1443. 0,
  1444. CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
  1445. NULL,
  1446. &pSubCred->pCert))
  1447. {
  1448. SP_LOG_RESULT(GetLastError());
  1449. scRet = SEC_E_UNKNOWN_CREDENTIALS;
  1450. goto cleanup;
  1451. }
  1452. // Free the output buffer.
  1453. SPExternalFree(Output.pvBuffer);
  1454. Output.pvBuffer = NULL;
  1455. }
  1456. }
  1457. //
  1458. // HCERTSTORE hRootStore;
  1459. //
  1460. if(LocalCred.hRootStore)
  1461. {
  1462. Input.BufferType = SECBUFFER_DATA;
  1463. Input.cbBuffer = sizeof(SSLWOW64_HCERTSTORE);
  1464. Input.pvBuffer = (PVOID)&LocalCred.hRootStore;
  1465. scRet = PerformApplicationCallback(SCH_UPLOAD_CERT_STORE_CALLBACK,
  1466. 0, 0,
  1467. &Input,
  1468. &Output,
  1469. TRUE);
  1470. if(scRet != SEC_E_OK)
  1471. {
  1472. goto cleanup;
  1473. }
  1474. pbBuffer = Output.pvBuffer;
  1475. cbBuffer = Output.cbBuffer;
  1476. if(pbBuffer == NULL || cbBuffer < sizeof(DWORD))
  1477. {
  1478. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1479. goto cleanup;
  1480. }
  1481. // Parse certificate store.
  1482. Serialized.cbData = *(DWORD *)pbBuffer;
  1483. Serialized.pbData = pbBuffer + sizeof(DWORD);
  1484. if(cbBuffer - sizeof(DWORD) < Serialized.cbData)
  1485. {
  1486. scRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1487. goto cleanup;
  1488. }
  1489. pCred->hRootStore = CertOpenStore( CERT_STORE_PROV_SERIALIZED,
  1490. X509_ASN_ENCODING,
  1491. 0, 0,
  1492. &Serialized);
  1493. if(pCred->hRootStore == NULL)
  1494. {
  1495. scRet = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1496. goto cleanup;
  1497. }
  1498. // Free the output buffer.
  1499. SPExternalFree(Output.pvBuffer);
  1500. Output.pvBuffer = NULL;
  1501. }
  1502. //
  1503. // DWORD cSupportedAlgs;
  1504. // ALG_ID *palgSupportedAlgs;
  1505. //
  1506. if(LocalCred.cSupportedAlgs && LocalCred.palgSupportedAlgs)
  1507. {
  1508. // Reality check.
  1509. if(LocalCred.cSupportedAlgs > 1000)
  1510. {
  1511. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1512. goto cleanup;
  1513. }
  1514. Size = LocalCred.cSupportedAlgs * sizeof(ALG_ID);
  1515. pCred->cSupportedAlgs = LocalCred.cSupportedAlgs;
  1516. pCred->palgSupportedAlgs = SPExternalAlloc(Size);
  1517. if(pCred->palgSupportedAlgs == NULL)
  1518. {
  1519. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1520. goto cleanup;
  1521. }
  1522. scRet = LsaTable->CopyFromClientBuffer(NULL,
  1523. Size,
  1524. pCred->palgSupportedAlgs,
  1525. ULongToPtr(LocalCred.palgSupportedAlgs));
  1526. if(!NT_SUCCESS(scRet))
  1527. {
  1528. goto cleanup;
  1529. }
  1530. }
  1531. //
  1532. // DWORD grbitEnabledProtocols;
  1533. // DWORD dwMinimumCipherStrength;
  1534. // DWORD dwMaximumCipherStrength;
  1535. // DWORD dwSessionLifespan;
  1536. // DWORD dwFlags;
  1537. // DWORD reserved;
  1538. //
  1539. pCred->grbitEnabledProtocols = LocalCred.grbitEnabledProtocols;
  1540. pCred->dwMinimumCipherStrength = LocalCred.dwMinimumCipherStrength;
  1541. pCred->dwMaximumCipherStrength = LocalCred.dwMaximumCipherStrength;
  1542. pCred->dwSessionLifespan = LocalCred.dwSessionLifespan;
  1543. pCred->dwFlags = LocalCred.dwFlags;
  1544. pCred->reserved = LocalCred.reserved;
  1545. scRet = SEC_E_OK;
  1546. cleanup:
  1547. if(Output.pvBuffer)
  1548. {
  1549. SPExternalFree(Output.pvBuffer);
  1550. }
  1551. if(pLocalCredList)
  1552. {
  1553. SPExternalFree(pLocalCredList);
  1554. }
  1555. if(hStore)
  1556. {
  1557. CertCloseStore(hStore, 0);
  1558. }
  1559. if(!NT_SUCCESS(scRet))
  1560. {
  1561. SpFreeVersion3Certificate(pCred);
  1562. }
  1563. return scRet;
  1564. }
  1565. #endif // _WIN64
  1566. SECURITY_STATUS
  1567. SpMapAuthIdentity(
  1568. PVOID pAuthData,
  1569. PLSA_SCHANNEL_CRED pSchannelCred)
  1570. {
  1571. PSEC_WINNT_AUTH_IDENTITY_EXW pAuthIdentity = NULL;
  1572. SEC_WINNT_AUTH_IDENTITY_EX32 AuthIdentity32 = {0};
  1573. BOOLEAN DoUnicode = TRUE;
  1574. UNICODE_STRING UserName;
  1575. UNICODE_STRING Password;
  1576. NTSTATUS Status;
  1577. CRED_MARSHAL_TYPE CredType;
  1578. PCERT_CREDENTIAL_INFO pCertInfo = NULL;
  1579. PCCERT_CONTEXT pCertContext = NULL;
  1580. HCERTSTORE hStore = 0;
  1581. CRYPT_HASH_BLOB HashBlob;
  1582. BOOL fImpersonating = FALSE;
  1583. BOOL fWow64Client = FALSE;
  1584. #ifdef _WIN64
  1585. SECPKG_CALL_INFO CallInfo;
  1586. if(!LsaTable->GetCallInfo(&CallInfo))
  1587. {
  1588. Status = STATUS_INTERNAL_ERROR;
  1589. return SP_LOG_RESULT(Status);
  1590. }
  1591. fWow64Client = (CallInfo.Attributes & SECPKG_CALL_WOWCLIENT) != 0;
  1592. #endif
  1593. DebugLog((DEB_TRACE, "SpMapAuthIdentity\n"));
  1594. //
  1595. // Initialize.
  1596. //
  1597. RtlInitUnicodeString(
  1598. &UserName,
  1599. NULL);
  1600. RtlInitUnicodeString(
  1601. &Password,
  1602. NULL);
  1603. //
  1604. // Copy over the SEC_WINNT_AUTH_IDENTITY_EX structure from client memory.
  1605. //
  1606. pAuthIdentity = (PSEC_WINNT_AUTH_IDENTITY_EXW)SPExternalAlloc(sizeof(SEC_WINNT_AUTH_IDENTITY_EXW));
  1607. if(pAuthIdentity == NULL)
  1608. {
  1609. Status = SEC_E_INSUFFICIENT_MEMORY;
  1610. goto cleanup;
  1611. }
  1612. if(fWow64Client)
  1613. {
  1614. Status = LsaTable->CopyFromClientBuffer(
  1615. NULL,
  1616. sizeof(SEC_WINNT_AUTH_IDENTITY_EX32),
  1617. &AuthIdentity32,
  1618. pAuthData);
  1619. if (!NT_SUCCESS(Status))
  1620. {
  1621. SP_LOG_RESULT(Status);
  1622. goto cleanup;
  1623. }
  1624. pAuthIdentity->Version = AuthIdentity32.Version;
  1625. pAuthIdentity->Length = (AuthIdentity32.Length < sizeof(SEC_WINNT_AUTH_IDENTITY_EX) ?
  1626. sizeof(SEC_WINNT_AUTH_IDENTITY_EX) : AuthIdentity32.Length);
  1627. pAuthIdentity->UserLength = AuthIdentity32.UserLength;
  1628. pAuthIdentity->User = (PWSTR) UlongToPtr(AuthIdentity32.User);
  1629. pAuthIdentity->DomainLength = AuthIdentity32.DomainLength ;
  1630. pAuthIdentity->Domain = (PWSTR) UlongToPtr( AuthIdentity32.Domain );
  1631. pAuthIdentity->PasswordLength = AuthIdentity32.PasswordLength ;
  1632. pAuthIdentity->Password = (PWSTR) UlongToPtr( AuthIdentity32.Password );
  1633. pAuthIdentity->Flags = AuthIdentity32.Flags ;
  1634. pAuthIdentity->PackageListLength = AuthIdentity32.PackageListLength ;
  1635. pAuthIdentity->PackageList = (PWSTR) UlongToPtr( AuthIdentity32.PackageList );
  1636. }
  1637. else
  1638. {
  1639. Status = LsaTable->CopyFromClientBuffer(
  1640. NULL,
  1641. sizeof(SEC_WINNT_AUTH_IDENTITY_EXW),
  1642. pAuthIdentity,
  1643. pAuthData);
  1644. if (!NT_SUCCESS(Status))
  1645. {
  1646. SP_LOG_RESULT(Status);
  1647. goto cleanup;
  1648. }
  1649. }
  1650. if ((pAuthIdentity->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI) != 0)
  1651. {
  1652. DoUnicode = FALSE;
  1653. }
  1654. //
  1655. // Copy over the user name and password.
  1656. //
  1657. if (pAuthIdentity->User != NULL)
  1658. {
  1659. Status = CopyClientString(
  1660. pAuthIdentity->User,
  1661. pAuthIdentity->UserLength,
  1662. DoUnicode,
  1663. &UserName);
  1664. if (!NT_SUCCESS(Status))
  1665. {
  1666. DebugLog((DEB_ERROR, "SpAcquireCredentialsHandle, Error from CopyClientString is 0x%lx\n", Status));
  1667. goto cleanup;
  1668. }
  1669. }
  1670. if (pAuthIdentity->Password != NULL)
  1671. {
  1672. Status = CopyClientString(
  1673. pAuthIdentity->Password,
  1674. pAuthIdentity->PasswordLength,
  1675. DoUnicode,
  1676. &Password);
  1677. if (!NT_SUCCESS(Status))
  1678. {
  1679. DebugLog((DEB_ERROR, "SpAcquireCredentialsHandle, Error from CopyClientString is 0x%lx\n", Status));
  1680. goto cleanup;
  1681. }
  1682. }
  1683. //
  1684. // Extract the certificate thumbprint.
  1685. //
  1686. if(!CredIsMarshaledCredentialW(UserName.Buffer))
  1687. {
  1688. Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1689. goto cleanup;
  1690. }
  1691. if(!CredUnmarshalCredentialW(UserName.Buffer,
  1692. &CredType,
  1693. &pCertInfo))
  1694. {
  1695. Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1696. goto cleanup;
  1697. }
  1698. if(CredType != CertCredential)
  1699. {
  1700. Status = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1701. goto cleanup;
  1702. }
  1703. //
  1704. // Look up the certificate in the MY certificate store.
  1705. //
  1706. fImpersonating = SslImpersonateClient();
  1707. hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  1708. X509_ASN_ENCODING, 0,
  1709. CERT_SYSTEM_STORE_CURRENT_USER |
  1710. CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
  1711. L"MY");
  1712. if(!hStore)
  1713. {
  1714. SP_LOG_RESULT(GetLastError());
  1715. Status = SEC_E_NO_CREDENTIALS;
  1716. goto cleanup;
  1717. }
  1718. HashBlob.cbData = sizeof(pCertInfo->rgbHashOfCert);
  1719. HashBlob.pbData = pCertInfo->rgbHashOfCert;
  1720. pCertContext = CertFindCertificateInStore(hStore,
  1721. X509_ASN_ENCODING,
  1722. 0,
  1723. CERT_FIND_HASH,
  1724. &HashBlob,
  1725. NULL);
  1726. if(pCertContext == NULL)
  1727. {
  1728. DebugLog((DEB_ERROR, "Certificate designated by authority info was not found in certificate store (0x%x).\n", GetLastError()));
  1729. Status = SEC_E_NO_CREDENTIALS;
  1730. goto cleanup;
  1731. }
  1732. //
  1733. // Build sub cred structure and attach it to the credential.
  1734. //
  1735. pSchannelCred->paSubCred = SPExternalAlloc(sizeof(LSA_SCHANNEL_SUB_CRED));
  1736. if(pSchannelCred->paSubCred == NULL)
  1737. {
  1738. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1739. goto cleanup;
  1740. }
  1741. pSchannelCred->paSubCred[0].pCert = pCertContext;
  1742. pSchannelCred->paSubCred[0].pszPin = Password.Buffer;
  1743. Password.Buffer = NULL;
  1744. pSchannelCred->cSubCreds = 1;
  1745. Status = STATUS_SUCCESS;
  1746. cleanup:
  1747. if(pAuthIdentity)
  1748. {
  1749. SPExternalFree(pAuthIdentity);
  1750. }
  1751. if(UserName.Buffer)
  1752. {
  1753. LocalFree(UserName.Buffer);
  1754. }
  1755. if(Password.Buffer)
  1756. {
  1757. LocalFree(Password.Buffer);
  1758. }
  1759. if(pCertInfo)
  1760. {
  1761. CredFree(pCertInfo);
  1762. }
  1763. if(hStore)
  1764. {
  1765. CertCloseStore(hStore, 0);
  1766. }
  1767. if(fImpersonating)
  1768. {
  1769. RevertToSelf();
  1770. }
  1771. return Status;
  1772. }
  1773. //+---------------------------------------------------------------------------
  1774. //
  1775. // Function: SpCommonAcquireCredentialsHandle
  1776. //
  1777. // Synopsis: Common AcquireCredentialsHandle function.
  1778. //
  1779. // Arguments: [Type] -- Type expected (Unified v. specific)
  1780. // [pLogonID] --
  1781. // [pvAuthData] --
  1782. // [pvGetKeyFn] --
  1783. // [pvGetKeyArgument] --
  1784. // [pdwHandle] --
  1785. // [ptsExpiry] --
  1786. //
  1787. // History: 10-06-96 RichardW Created
  1788. //
  1789. // Notes:
  1790. //
  1791. //----------------------------------------------------------------------------
  1792. SECURITY_STATUS
  1793. SpCommonAcquireCredentialsHandle(
  1794. ULONG Type,
  1795. PLUID pLogonID,
  1796. PVOID pvAuthData,
  1797. PVOID pvGetKeyFn,
  1798. PVOID pvGetKeyArgument,
  1799. PLSA_SEC_HANDLE pdwHandle,
  1800. PTimeStamp ptsExpiry)
  1801. {
  1802. SP_STATUS pctRet;
  1803. PSPCredentialGroup pCredGroup;
  1804. LSA_SCHANNEL_CRED SchannelCred;
  1805. PSCH_CRED pSchCred;
  1806. SECURITY_STATUS Status;
  1807. SSL_CREDENTIAL_CERTIFICATE SslCert;
  1808. DWORD dwVersion;
  1809. SECPKG_CLIENT_INFO ClientInfo;
  1810. #ifdef _WIN64
  1811. SECPKG_CALL_INFO CallInfo;
  1812. BOOL fWow64Client = FALSE;
  1813. #endif
  1814. UNREFERENCED_PARAMETER(pLogonID);
  1815. UNREFERENCED_PARAMETER(pvGetKeyFn);
  1816. UNREFERENCED_PARAMETER(pvGetKeyArgument);
  1817. TRACE_ENTER( SpCommonAcquireCredentialsHandle );
  1818. if(!SchannelInit(FALSE))
  1819. {
  1820. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1821. }
  1822. #ifdef _WIN64
  1823. if(!LsaTable->GetCallInfo(&CallInfo))
  1824. {
  1825. Status = STATUS_INTERNAL_ERROR;
  1826. return SP_LOG_RESULT(Status);
  1827. }
  1828. fWow64Client = (CallInfo.Attributes & SECPKG_CALL_WOWCLIENT) != 0;
  1829. #endif
  1830. Status = LsaTable->GetClientInfo( &ClientInfo );
  1831. if (!NT_SUCCESS( Status ))
  1832. {
  1833. Status = STATUS_INTERNAL_ERROR;
  1834. return SP_LOG_RESULT(Status);
  1835. }
  1836. //
  1837. // Got to have an impersonation level token in order to call ACH.
  1838. // This check used to be in lsa, but moved here to enable
  1839. // some S4Uproxy scenarios to work w/o tcb.
  1840. //
  1841. if (ClientInfo.ImpersonationLevel <= SecurityIdentification)
  1842. {
  1843. Status = SEC_E_NO_CREDENTIALS;
  1844. return SP_LOG_RESULT(Status);
  1845. }
  1846. __try
  1847. {
  1848. // Default to null credential
  1849. memset(&SchannelCred, 0, sizeof(SchannelCred));
  1850. SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
  1851. if ( pvAuthData )
  1852. {
  1853. //
  1854. // Read in the first few bytes of data so we can see what's there.
  1855. //
  1856. Status = LsaTable->CopyFromClientBuffer( NULL,
  1857. sizeof( SSL_CREDENTIAL_CERTIFICATE ),
  1858. &SslCert,
  1859. pvAuthData );
  1860. if ( !NT_SUCCESS( Status ) )
  1861. {
  1862. return( Status );
  1863. }
  1864. dwVersion = SslCert.cbPrivateKey;
  1865. //
  1866. // Ok, see what kind of blob we got:
  1867. //
  1868. switch(dwVersion)
  1869. {
  1870. case SEC_WINNT_AUTH_IDENTITY_VERSION:
  1871. //
  1872. // The application passed in a SEC_WINNT_AUTH_IDENTITY_EXW
  1873. // structure.
  1874. //
  1875. Status = SpMapAuthIdentity(pvAuthData, &SchannelCred);
  1876. if(!NT_SUCCESS(Status))
  1877. {
  1878. return Status;
  1879. }
  1880. break;
  1881. case SCH_CRED_V3:
  1882. case SCHANNEL_CRED_VERSION:
  1883. //
  1884. // The application is using modern (version 3) credentials.
  1885. //
  1886. #ifdef _WIN64
  1887. if(fWow64Client)
  1888. {
  1889. Status = SpWow64MapVersion3Certificate(pvAuthData, dwVersion, &SchannelCred);
  1890. }
  1891. else
  1892. #endif
  1893. {
  1894. Status = SpMapVersion3Certificate(pvAuthData, dwVersion, &SchannelCred);
  1895. }
  1896. if(!NT_SUCCESS(Status))
  1897. {
  1898. return Status;
  1899. }
  1900. // Selectively enable the unified protocol.
  1901. SchannelCred.grbitEnabledProtocols = EnableUnifiedProtocol(
  1902. Type,
  1903. SchannelCred.grbitEnabledProtocols);
  1904. break;
  1905. case SCH_CRED_V1:
  1906. case SCH_CRED_V2:
  1907. //
  1908. // Okay, it's a V1 or V2 style request. Map it in, following
  1909. // its scary chains.
  1910. //
  1911. #ifdef _WIN64
  1912. if(fWow64Client)
  1913. {
  1914. Status = SpWow64MapVersion2Certificate(pvAuthData, &pSchCred);
  1915. }
  1916. else
  1917. #endif
  1918. {
  1919. Status = SpMapVersion2Certificate(pvAuthData, &pSchCred);
  1920. }
  1921. if(!NT_SUCCESS(Status))
  1922. {
  1923. return Status;
  1924. }
  1925. //
  1926. // Convert this version 2 credential to a version 3 credential.
  1927. //
  1928. Status = UpdateCredentialFormat(pSchCred, &SchannelCred);
  1929. SpFreeVersion2Certificate( pSchCred );
  1930. if(!NT_SUCCESS(Status))
  1931. {
  1932. return Status;
  1933. }
  1934. break;
  1935. default:
  1936. //
  1937. // A really old-style credential.
  1938. //
  1939. #ifdef _WIN64
  1940. if(fWow64Client)
  1941. {
  1942. Status = SpWow64MapProtoCredential((SSLWOW64_CREDENTIAL_CERTIFICATE *)&SslCert, &pSchCred);
  1943. }
  1944. else
  1945. #endif
  1946. {
  1947. Status = SpMapProtoCredential(&SslCert, &pSchCred);
  1948. }
  1949. if(!NT_SUCCESS(Status))
  1950. {
  1951. return Status;
  1952. }
  1953. //
  1954. // Convert this version 2 credential to a version 3 credential.
  1955. //
  1956. Status = UpdateCredentialFormat(pSchCred, &SchannelCred);
  1957. SpFreeVersion2Certificate( pSchCred );
  1958. if(!NT_SUCCESS(Status))
  1959. {
  1960. return Status;
  1961. }
  1962. break;
  1963. }
  1964. // Set the legacy flags if this is an old-style credential.
  1965. if(dwVersion != SCHANNEL_CRED_VERSION &&
  1966. dwVersion != SEC_WINNT_AUTH_IDENTITY_VERSION)
  1967. {
  1968. SchannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
  1969. SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
  1970. }
  1971. }
  1972. }
  1973. __except(EXCEPTION_EXECUTE_HANDLER)
  1974. {
  1975. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1976. }
  1977. if(pvAuthData == NULL && (Type & SP_PROT_SERVERS))
  1978. {
  1979. //
  1980. // A server is creating credential without specifying any
  1981. // authentication data, so attempt to acquire a default
  1982. // machine credential.
  1983. //
  1984. Status = FindDefaultMachineCred(&pCredGroup, Type);
  1985. if(!NT_SUCCESS(Status))
  1986. {
  1987. DebugLog((DEB_ERROR, "Unable to create default server credential (0x%x)\n", Status));
  1988. return Status;
  1989. }
  1990. ComputeCredExpiry(pCredGroup, ptsExpiry);
  1991. *pdwHandle = (LSA_SEC_HANDLE) pCredGroup;
  1992. return SEC_E_OK;
  1993. }
  1994. pctRet = SPCreateCredential( &pCredGroup,
  1995. Type,
  1996. &SchannelCred );
  1997. SpFreeVersion3Certificate( &SchannelCred );
  1998. if (PCT_ERR_OK == pctRet)
  1999. {
  2000. ComputeCredExpiry(pCredGroup, ptsExpiry);
  2001. *pdwHandle = (LSA_SEC_HANDLE) pCredGroup;
  2002. return SEC_E_OK;
  2003. }
  2004. return PctTranslateError(pctRet);
  2005. }
  2006. SECURITY_STATUS
  2007. SEC_ENTRY
  2008. SpUniAcquireCredentialsHandle(
  2009. PSECURITY_STRING psPrincipal,
  2010. ULONG fCredentials,
  2011. PLUID pLogonID,
  2012. PVOID pvAuthData,
  2013. PVOID pvGetKeyFn,
  2014. PVOID pvGetKeyArgument,
  2015. PLSA_SEC_HANDLE pdwHandle,
  2016. PTimeStamp ptsExpiry)
  2017. {
  2018. DWORD Type;
  2019. UNREFERENCED_PARAMETER(psPrincipal);
  2020. DebugLog((DEB_TRACE, "SpUniAcquireCredentialsHandle(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
  2021. fCredentials, pLogonID, pvAuthData,
  2022. pvGetKeyFn, pvGetKeyArgument, pdwHandle, ptsExpiry));
  2023. if ( fCredentials & SECPKG_CRED_INBOUND )
  2024. {
  2025. Type = SP_PROT_UNI_SERVER ;
  2026. }
  2027. else if ( fCredentials & SECPKG_CRED_OUTBOUND )
  2028. {
  2029. Type = SP_PROT_UNI_CLIENT ;
  2030. }
  2031. else
  2032. {
  2033. return SP_LOG_RESULT(SEC_E_NO_CREDENTIALS);
  2034. }
  2035. return( SpCommonAcquireCredentialsHandle( Type,
  2036. pLogonID,
  2037. pvAuthData,
  2038. pvGetKeyFn,
  2039. pvGetKeyArgument,
  2040. pdwHandle,
  2041. ptsExpiry ) );
  2042. }
  2043. SECURITY_STATUS
  2044. SEC_ENTRY
  2045. SpQueryCredentialsAttributes(
  2046. LSA_SEC_HANDLE dwCredHandle,
  2047. ULONG dwAttribute,
  2048. PVOID Buffer)
  2049. {
  2050. PSPCredentialGroup pCred;
  2051. ULONG Size;
  2052. PVOID pvClient = NULL;
  2053. DWORD cbClient;
  2054. SECURITY_STATUS Status;
  2055. BOOL fWow64Client = FALSE;
  2056. #ifdef _WIN64
  2057. SECPKG_CALL_INFO CallInfo;
  2058. #endif
  2059. typedef struct _SecPkgCred_SupportedAlgsWow64
  2060. {
  2061. DWORD cSupportedAlgs;
  2062. SSLWOW64_PVOID palgSupportedAlgs;
  2063. } SecPkgCred_SupportedAlgsWow64, *PSecPkgCred_SupportedAlgsWow64;
  2064. union {
  2065. SecPkgCred_SupportedAlgs SupportedAlgs;
  2066. SecPkgCred_SupportedAlgsWow64 SupportedAlgsWow64;
  2067. SecPkgCred_CipherStrengths CipherStrengths;
  2068. SecPkgCred_SupportedProtocols SupportedProtocols;
  2069. } LocalBuffer;
  2070. pCred = (PSPCredentialGroup)dwCredHandle;
  2071. if(pCred == NULL)
  2072. {
  2073. return(SEC_E_INVALID_HANDLE);
  2074. }
  2075. #ifdef _WIN64
  2076. if(!LsaTable->GetCallInfo(&CallInfo))
  2077. {
  2078. Status = STATUS_INTERNAL_ERROR;
  2079. return SP_LOG_RESULT(Status);
  2080. }
  2081. fWow64Client = (CallInfo.Attributes & SECPKG_CALL_WOWCLIENT) != 0;
  2082. #endif
  2083. __try
  2084. {
  2085. switch (dwAttribute)
  2086. {
  2087. case SECPKG_ATTR_SUPPORTED_ALGS:
  2088. DebugLog((DEB_TRACE, "QueryCredentialsAttributes(SECPKG_ATTR_SUPPORTED_ALGS)\n"));
  2089. if(fWow64Client)
  2090. {
  2091. Size = sizeof(SecPkgCred_SupportedAlgsWow64);
  2092. }
  2093. else
  2094. {
  2095. Size = sizeof(SecPkgCred_SupportedAlgs);
  2096. }
  2097. break;
  2098. case SECPKG_ATTR_CIPHER_STRENGTHS:
  2099. DebugLog((DEB_TRACE, "QueryCredentialsAttributes(SECPKG_ATTR_CIPHER_STRENGTHS)\n"));
  2100. Size = sizeof(SecPkgCred_CipherStrengths);
  2101. break;
  2102. case SECPKG_ATTR_SUPPORTED_PROTOCOLS:
  2103. DebugLog((DEB_TRACE, "QueryCredentialsAttributes(SECPKG_ATTR_SUPPORTED_PROTOCOLS)\n"));
  2104. Size = sizeof(SecPkgCred_SupportedProtocols);
  2105. break;
  2106. default:
  2107. DebugLog((DEB_WARN, "QueryCredentialsAttributes(unsupported function %d)\n", dwAttribute));
  2108. return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
  2109. }
  2110. // Copy structure from client memory, just in case any of this
  2111. // stuff is in/out.
  2112. Status = LsaTable->CopyFromClientBuffer( NULL,
  2113. Size,
  2114. &LocalBuffer,
  2115. Buffer );
  2116. if(FAILED(Status))
  2117. {
  2118. return Status;
  2119. }
  2120. switch (dwAttribute)
  2121. {
  2122. case SECPKG_ATTR_SUPPORTED_ALGS:
  2123. {
  2124. cbClient = pCred->cSupportedAlgs * sizeof(ALG_ID);
  2125. // Allocate client memory for algorithm list.
  2126. Status = LsaTable->AllocateClientBuffer(NULL, cbClient, &pvClient);
  2127. if(FAILED(Status))
  2128. {
  2129. return Status;
  2130. }
  2131. if(fWow64Client)
  2132. {
  2133. LocalBuffer.SupportedAlgsWow64.cSupportedAlgs = pCred->cSupportedAlgs;
  2134. LocalBuffer.SupportedAlgsWow64.palgSupportedAlgs = PtrToUlong(pvClient);
  2135. }
  2136. else
  2137. {
  2138. LocalBuffer.SupportedAlgs.cSupportedAlgs = pCred->cSupportedAlgs;
  2139. LocalBuffer.SupportedAlgs.palgSupportedAlgs = pvClient;
  2140. }
  2141. // Copy algorithm list to client memory.
  2142. Status = LsaTable->CopyToClientBuffer(
  2143. NULL,
  2144. cbClient,
  2145. pvClient,
  2146. pCred->palgSupportedAlgs);
  2147. if(FAILED(Status))
  2148. {
  2149. LsaTable->FreeClientBuffer(NULL, pvClient);
  2150. return Status;
  2151. }
  2152. break;
  2153. }
  2154. case SECPKG_ATTR_CIPHER_STRENGTHS:
  2155. GetDisplayCipherSizes(pCred,
  2156. &LocalBuffer.CipherStrengths.dwMinimumCipherStrength,
  2157. &LocalBuffer.CipherStrengths.dwMaximumCipherStrength);
  2158. break;
  2159. case SECPKG_ATTR_SUPPORTED_PROTOCOLS:
  2160. LocalBuffer.SupportedProtocols.grbitProtocol = pCred->grbitEnabledProtocols;
  2161. break;
  2162. }
  2163. // Copy structure back to client memory.
  2164. Status = LsaTable->CopyToClientBuffer( NULL,
  2165. Size,
  2166. Buffer,
  2167. &LocalBuffer );
  2168. if(FAILED(Status))
  2169. {
  2170. if(pvClient) LsaTable->FreeClientBuffer(NULL, pvClient);
  2171. return Status;
  2172. }
  2173. }
  2174. __except(EXCEPTION_EXECUTE_HANDLER)
  2175. {
  2176. return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
  2177. }
  2178. return SEC_E_OK;
  2179. }
  2180. SECURITY_STATUS
  2181. SEC_ENTRY
  2182. SpFreeCredentialsHandle(LSA_SEC_HANDLE dwHandle)
  2183. {
  2184. PSPCredentialGroup pCred;
  2185. SECPKG_CALL_INFO CallInfo;
  2186. DebugLog((DEB_TRACE, "SpFreeCredentialsHandle(0x%x)\n", dwHandle));
  2187. pCred = (PSPCredentialGroup) dwHandle ;
  2188. __try
  2189. {
  2190. if (pCred)
  2191. {
  2192. // Delete all mention of this credential from the cache.
  2193. SPCachePurgeCredential(pCred);
  2194. // Was this call made from the LSA cleanup code? In other
  2195. // words, did the application terminate without cleaning up
  2196. // properly? If so, then throw away all unreferenced zombies
  2197. // associated with that process.
  2198. if(LsaTable->GetCallInfo(&CallInfo))
  2199. {
  2200. if(CallInfo.Attributes & SECPKG_CALL_CLEANUP)
  2201. {
  2202. SPCachePurgeProcessId(pCred->ProcessId);
  2203. }
  2204. }
  2205. pCred->dwFlags |= CRED_FLAG_DELETED;
  2206. SPDereferenceCredential(pCred, TRUE);
  2207. return(SEC_E_OK);
  2208. }
  2209. }
  2210. __except(EXCEPTION_EXECUTE_HANDLER)
  2211. {
  2212. return SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
  2213. }
  2214. return SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
  2215. }