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.

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