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.

315 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name :
  4. certmapprovider.cxx
  5. Abstract:
  6. Active Directory Certificate Mapper provider
  7. Author:
  8. Bilal Alam (balam) 10-Jan-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. ULW3.DLL
  13. --*/
  14. #include "precomp.hxx"
  15. #include "certmapprovider.hxx"
  16. HRESULT
  17. CERTMAP_AUTH_PROVIDER::DoesApply(
  18. W3_MAIN_CONTEXT * pMainContext,
  19. BOOL * pfApplies
  20. )
  21. /*++
  22. Routine Description:
  23. Does Active Directory certificate map authentication apply?
  24. MD_ACCESS_MAP_CERT covers 2 kinds of mappings (DS mapper and IIS mapper)
  25. CERT_AUTH_PROVIDER represents only the DS mapper
  26. Arguments:
  27. pMainContext - Main context
  28. pfApplies - Set to TRUE if cert map auth applies
  29. Return Value:
  30. HRESULT
  31. --*/
  32. {
  33. CERTIFICATE_CONTEXT * pCertificateContext;
  34. URL_CONTEXT * pUrlContext = NULL;
  35. W3_METADATA * pMetaData = NULL;
  36. BOOL fApplies = FALSE;
  37. if ( pMainContext == NULL ||
  38. pfApplies == NULL )
  39. {
  40. DBG_ASSERT( FALSE );
  41. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  42. }
  43. //
  44. // If cert mapping is not allowed for this vroot, then ignore client
  45. // cert token and let other authentication mechanisms do their thing
  46. //
  47. pUrlContext = pMainContext->QueryUrlContext();
  48. DBG_ASSERT( pUrlContext != NULL );
  49. pMetaData = pUrlContext->QueryMetaData();
  50. DBG_ASSERT( pMetaData != NULL );
  51. //
  52. // Are certmappings allowed?
  53. //
  54. if ( pMetaData->QuerySslAccessPerms() & MD_ACCESS_MAP_CERT )
  55. {
  56. DBG_ASSERT( pMainContext->QuerySite() );
  57. //
  58. // Is Active Directory mapping allowed
  59. //
  60. if ( pMainContext->QuerySite()->QueryUseDSMapper() )
  61. {
  62. pCertificateContext = pMainContext->QueryCertificateContext();
  63. //
  64. // Did schannel successfully mapped client certificate to token?
  65. //
  66. if ( pCertificateContext != NULL )
  67. {
  68. if ( pCertificateContext->QueryImpersonationToken() != NULL )
  69. {
  70. fApplies = TRUE;
  71. }
  72. }
  73. }
  74. }
  75. *pfApplies = fApplies;
  76. return NO_ERROR;
  77. }
  78. HRESULT
  79. CERTMAP_AUTH_PROVIDER::DoAuthenticate(
  80. W3_MAIN_CONTEXT * pMainContext,
  81. BOOL * // unused
  82. )
  83. /*++
  84. Routine Description:
  85. Create a user context representing a cert mapped token
  86. Arguments:
  87. pMainContext - Main context
  88. pfFilterFinished - Set to TRUE if filter wants out
  89. Return Value:
  90. HRESULT
  91. --*/
  92. {
  93. CERTMAP_USER_CONTEXT * pUserContext = NULL;
  94. CERTIFICATE_CONTEXT * pCertificateContext = NULL;
  95. HANDLE hImpersonation;
  96. HRESULT hr = NO_ERROR;
  97. if ( pMainContext == NULL )
  98. {
  99. DBG_ASSERT( FALSE );
  100. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  101. }
  102. pCertificateContext = pMainContext->QueryCertificateContext();
  103. DBG_ASSERT( pCertificateContext != NULL );
  104. hImpersonation = pCertificateContext->QueryImpersonationToken();
  105. DBG_ASSERT( hImpersonation != NULL );
  106. //
  107. // Create the user context for this request
  108. //
  109. pUserContext = new CERTMAP_USER_CONTEXT( this );
  110. if ( pUserContext == NULL )
  111. {
  112. return HRESULT_FROM_WIN32( GetLastError() );
  113. }
  114. //
  115. // Is this a delegatable token? Put another way is this token mapped
  116. // using an IIS cert mapper (IIS cert mapper creates delegatable token,
  117. // the DS mapper does not)
  118. //
  119. hr = pUserContext->Create( hImpersonation );
  120. if ( FAILED( hr ) )
  121. {
  122. pUserContext->DereferenceUserContext();
  123. pUserContext = NULL;
  124. return hr;
  125. }
  126. pMainContext->SetUserContext( pUserContext );
  127. return NO_ERROR;
  128. }
  129. HRESULT
  130. CERTMAP_AUTH_PROVIDER::OnAccessDenied(
  131. W3_MAIN_CONTEXT * /*pMainContext*/
  132. )
  133. /*++
  134. Routine Description:
  135. NOP since we have nothing to do on access denied
  136. Arguments:
  137. pMainContext - Main context (not used)
  138. Return Value:
  139. HRESULT
  140. --*/
  141. {
  142. //
  143. // No headers to add
  144. //
  145. return NO_ERROR;
  146. }
  147. HRESULT
  148. CERTMAP_USER_CONTEXT::Create(
  149. HANDLE hImpersonation
  150. )
  151. /*++
  152. Routine Description:
  153. Create a certificate mapped user context
  154. Arguments:
  155. hImpersonation - Impersonation token
  156. Return Value:
  157. HRESULT
  158. --*/
  159. {
  160. HRESULT hr = E_FAIL;
  161. if ( hImpersonation == NULL )
  162. {
  163. DBG_ASSERT( FALSE );
  164. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  165. }
  166. //
  167. // First the easy stuff
  168. //
  169. if ( !DuplicateTokenEx( hImpersonation,
  170. TOKEN_ALL_ACCESS,
  171. NULL,
  172. SecurityImpersonation,
  173. TokenImpersonation,
  174. &_hImpersonationToken ) )
  175. {
  176. hr = HRESULT_FROM_WIN32( GetLastError() );
  177. DBGPRINTF(( DBG_CONTEXT,
  178. "DuplicateTokenEx failed, hr = 0x%x\n",
  179. hr ));
  180. return hr;
  181. }
  182. DBG_ASSERT( _hImpersonationToken != NULL );
  183. //
  184. // Disable the backup privilege for the token
  185. //
  186. DisableTokenBackupPrivilege( _hImpersonationToken );
  187. //
  188. // Now get the user name
  189. //
  190. if ( !SetThreadToken( NULL, _hImpersonationToken ) )
  191. {
  192. return HRESULT_FROM_WIN32( GetLastError() );
  193. }
  194. // cchUserName includes buffer size in characters including terminating 0
  195. DWORD cchUserName = sizeof( _achUserName ) / sizeof( WCHAR );
  196. if ( !GetUserNameEx( NameSamCompatible,
  197. _achUserName,
  198. &cchUserName ) )
  199. {
  200. hr = HRESULT_FROM_WIN32( GetLastError() );
  201. RevertToSelf();
  202. return hr;
  203. }
  204. RevertToSelf();
  205. return NO_ERROR;
  206. }
  207. HANDLE
  208. CERTMAP_USER_CONTEXT::QueryPrimaryToken(
  209. VOID
  210. )
  211. /*++
  212. Routine Description:
  213. Get a primary token
  214. Arguments:
  215. None
  216. Return Value:
  217. HANDLE
  218. --*/
  219. {
  220. if ( _hPrimaryToken == NULL )
  221. {
  222. if ( DuplicateTokenEx( _hImpersonationToken,
  223. TOKEN_ALL_ACCESS,
  224. NULL,
  225. SecurityImpersonation,
  226. TokenPrimary,
  227. &_hPrimaryToken ) )
  228. {
  229. DBG_ASSERT( _hImpersonationToken != NULL );
  230. }
  231. else
  232. {
  233. DBGPRINTF(( DBG_CONTEXT,
  234. "DuplicateTokenEx failed, hr = 0x%x\n",
  235. HRESULT_FROM_WIN32( GetLastError() ) ));
  236. }
  237. }
  238. return _hPrimaryToken;
  239. }