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.

269 lines
7.2 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. cliauth.cxx
  5. Abstract:
  6. Contains Schannel/SSPI specific code for handling Client Authenication
  7. multiplexed between several asynchronous requests using fibers
  8. Contents:
  9. CERT_CONTEXT_ARRAY::CERT_CONTEXT_ARRAY
  10. CERT_CONTEXT_ARRAY::Reset
  11. CERT_CONTEXT_ARRAY::~CERT_CONTEXT_ARRAY
  12. CliAuthSelectCredential
  13. Author:
  14. Arthur L Bierer (arthurbi) 13-Jun-1996
  15. Environment:
  16. Win32 user-mode DLL
  17. Revision History:
  18. 13-Jun-1996 arthurbi
  19. Created, based on orginal code from a-petesk.
  20. --*/
  21. #include <wininetp.h>
  22. extern "C" {
  23. #include <nt.h>
  24. #include <ntrtl.h>
  25. #include <nturtl.h>
  26. #include <ntsecapi.h>
  27. }
  28. CERT_FREE_CERTIFICATE_CONTEXT_FN g_pfnCertFreeCertificateContext = NULL;
  29. CERT_CONTEXT_ARRAY::CERT_CONTEXT_ARRAY(BOOL fNoRevert)
  30. {
  31. _error = ERROR_SUCCESS;
  32. _iSelected = -1;
  33. _ppCertContexts = (PCCERT_CONTEXT *)
  34. ALLOCATE_MEMORY(sizeof(PCERT_CONTEXT)* CERT_CONTEXT_ARRAY_ALLOC_UNIT);
  35. if ( _ppCertContexts == NULL ) {
  36. _error = GetLastError();
  37. }
  38. _cAlloced = CERT_CONTEXT_ARRAY_ALLOC_UNIT;
  39. _cCertContexts = 0;
  40. ClearCreds(_hCreds);
  41. _cs.Init();
  42. _fNoRevert = fNoRevert;
  43. }
  44. void CERT_CONTEXT_ARRAY::Reset(void)
  45. {
  46. if ( _ppCertContexts )
  47. {
  48. for ( DWORD i = 0; i < _cCertContexts; i++ )
  49. {
  50. INET_ASSERT(_ppCertContexts[i]);
  51. WRAP_REVERT_USER_VOID((*g_pfnCertFreeCertificateContext), _fNoRevert, (_ppCertContexts[i]));
  52. }
  53. }
  54. _cCertContexts = 0;
  55. // It is important that this Free is guarded by a try except.
  56. // These objects get freed up at dll unload time and there is a circular
  57. // dependency between winient and schannel which can cause schannel to
  58. // get unloaded. If that is the case we could fault here.
  59. if (!IsCredClear(_hCreds))
  60. {
  61. SAFE_WRAP_REVERT_USER_VOID(g_FreeCredentialsHandle, _fNoRevert, (&_hCreds));
  62. ClearCreds(_hCreds);
  63. }
  64. }
  65. CERT_CONTEXT_ARRAY::~CERT_CONTEXT_ARRAY()
  66. {
  67. Reset();
  68. FREE_MEMORY(_ppCertContexts);
  69. }
  70. DWORD
  71. CliAuthSelectCredential(
  72. IN PCtxtHandle phContext,
  73. IN LPTSTR pszPackageName,
  74. IN CERT_CONTEXT_ARRAY* pCertContextArray,
  75. OUT PCredHandle phCredential,
  76. IN LPDWORD pdwStatus,
  77. IN DWORD dwSecureProtocols,
  78. IN BOOL fNoRevert)
  79. /*++
  80. Routine Description:
  81. Uses a selected Certificate Chain to produce a Credential handle.
  82. The credential handle will be used by SCHANNEL to produce a valid Client
  83. Auth session with a server.
  84. Arguments:
  85. phContext - SSPI Context Handle
  86. pszPackageName - Name of the SSPI package we're using.
  87. pSelectedCert - Cert that User wishes us to use for Client Auth with this server.
  88. (BUGBUG who should free this? )
  89. phCredential - Outgoing SSPI Credential handle that we may generate
  90. IMPORTANT: Do not free the credential handle returned by this function.
  91. These have to be cached for the lifetime of the process so the user
  92. doesn't get prompted forthe password over and over. Unfortunately there is
  93. no ref-counting mechanism on CredHandle's so callers of this function need to
  94. make sure they don't free the handle.
  95. pdwStatus - Secure error status flag that's filled in if an error occurs.
  96. Pointer is assumed to be valid.
  97. dwSecureProtocols - Enabled secure protocols (SSL2, SSL3, and/or TLS1) when acquiring
  98. this credential.
  99. fNoRevert - Determines if any impersonation should be reverted for SSL handling.
  100. Return Value:
  101. DWORD
  102. Success - ERROR_SUCCESS
  103. Caller should return ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED,
  104. to its caller. The appropriate Cert chain was generated,
  105. and the User needs to select it using UI.
  106. Failure -
  107. ERROR_NOT_ENOUGH_MEMORY -
  108. Out of Memory
  109. ERROR_WINHTTP_SECURE_FAILURE -
  110. Call Down to SSPI or WinTrust failed.
  111. --*/
  112. {
  113. SCHANNEL_CRED CredData = {SCHANNEL_CRED_VERSION,
  114. 0,
  115. NULL,
  116. 0,
  117. 0,
  118. NULL,
  119. 0,
  120. NULL,
  121. DEFAULT_SECURE_PROTOCOLS,
  122. 0,
  123. 0,
  124. 0,
  125. SCH_CRED_MANUAL_CRED_VALIDATION |
  126. SCH_CRED_NO_DEFAULT_CREDS
  127. };
  128. SECURITY_STATUS scRet;
  129. DWORD error = ERROR_SUCCESS;
  130. PCCERT_CONTEXT pCert;
  131. UNREFERENCED_PARAMETER(phContext);
  132. DEBUG_ENTER((DBG_SOCKETS,
  133. Dword,
  134. "CliAuthSelectCredential",
  135. "%#x, %s, %x, %x",
  136. phContext,
  137. pszPackageName,
  138. pCertContextArray,
  139. phCredential
  140. ));
  141. INET_ASSERT(phContext);
  142. INET_ASSERT(pCertContextArray);
  143. INET_ASSERT(pszPackageName);
  144. if (!pCertContextArray->LockCredHandle( ))
  145. {
  146. error = ERROR_NOT_ENOUGH_MEMORY;
  147. goto quit;
  148. }
  149. if ( pCertContextArray->GetArraySize() == 0 )
  150. {
  151. goto cleanup;
  152. }
  153. else
  154. {
  155. // First check and see if the Cert context already has a CredHandle associated with it.
  156. CredHandle hCreds = pCertContextArray->GetCredHandle( );
  157. if (!IsCredClear(hCreds))
  158. {
  159. *phCredential = hCreds;
  160. error = ERROR_SUCCESS;
  161. goto cleanup;
  162. }
  163. }
  164. pCert = pCertContextArray->GetSelectedCertContext();
  165. //
  166. // Setup strucutres for AcquireCredentialsHandle call.
  167. //
  168. if ( pCert )
  169. {
  170. CredData.cCreds = 1;
  171. CredData.paCred = &pCert;
  172. }
  173. CredData.grbitEnabledProtocols = dwSecureProtocols;
  174. WRAP_REVERT_USER(g_AcquireCredentialsHandle,
  175. fNoRevert,
  176. (NULL,
  177. pszPackageName,
  178. SECPKG_CRED_OUTBOUND,
  179. NULL,
  180. &CredData,
  181. NULL,
  182. NULL,
  183. phCredential,
  184. NULL),
  185. scRet);
  186. error = MapInternetError((DWORD)scRet, pdwStatus);
  187. if (error == ERROR_SUCCESS)
  188. {
  189. pCertContextArray->SetCredHandle(*phCredential);
  190. }
  191. cleanup:
  192. pCertContextArray->UnlockCredHandle();
  193. quit:
  194. DEBUG_LEAVE(error);
  195. return error;
  196. }