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.

375 lines
8.1 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: userctxt.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 10-10-96 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "sslp.h"
  18. #define SCHANNEL_USERLIST_COUNT (16) // count of lists
  19. #define SCHANNEL_USERLIST_LOCK_COUNT (2) // count of locks
  20. RTL_RESOURCE SslContextLock[ SCHANNEL_USERLIST_LOCK_COUNT ];
  21. LIST_ENTRY SslContextList[ SCHANNEL_USERLIST_COUNT ] ;
  22. ULONG
  23. HandleToListIndex(
  24. ULONG_PTR ContextHandle
  25. );
  26. ULONG
  27. __inline
  28. ListIndexToLockIndex(
  29. ULONG ListIndex
  30. );
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Function: SslInitContextManager
  34. //
  35. // Synopsis: Initializes the context manager controls
  36. //
  37. // History: 10-10-96 RichardW Created
  38. //
  39. // Notes:
  40. //
  41. //----------------------------------------------------------------------------
  42. BOOL
  43. SslInitContextManager(
  44. VOID
  45. )
  46. {
  47. ULONG Index;
  48. NTSTATUS Status = STATUS_SUCCESS;
  49. for( Index=0 ; Index < SCHANNEL_USERLIST_LOCK_COUNT ; Index++ )
  50. {
  51. __try {
  52. RtlInitializeResource (&SslContextLock[Index]);
  53. } __except(EXCEPTION_EXECUTE_HANDLER)
  54. {
  55. Status = STATUS_INSUFFICIENT_RESOURCES;
  56. break;
  57. }
  58. }
  59. if( !NT_SUCCESS(Status) )
  60. {
  61. DebugLog(( DEB_ERROR, "SslInitContextManager failed!\n" ));
  62. return FALSE;
  63. }
  64. for( Index = 0 ; Index < SCHANNEL_USERLIST_COUNT ; Index++ )
  65. {
  66. InitializeListHead( &SslContextList[Index] );
  67. }
  68. return( TRUE );
  69. }
  70. #if 0
  71. VOID
  72. SslFreeUserContextElements(PSPContext pContext)
  73. {
  74. if(pContext->hReadKey)
  75. {
  76. if(!CryptDestroyKey(pContext->hReadKey))
  77. {
  78. SP_LOG_RESULT(GetLastError());
  79. }
  80. }
  81. pContext->hReadKey = 0;
  82. if(pContext->hReadMAC)
  83. {
  84. if(!CryptDestroyKey(pContext->hReadMAC))
  85. {
  86. SP_LOG_RESULT(GetLastError());
  87. }
  88. }
  89. pContext->hReadMAC = 0;
  90. if(pContext->hWriteKey)
  91. {
  92. if(!CryptDestroyKey(pContext->hWriteKey))
  93. {
  94. SP_LOG_RESULT(GetLastError());
  95. }
  96. }
  97. pContext->hWriteKey = 0;
  98. if(pContext->hWriteMAC)
  99. {
  100. if(!CryptDestroyKey(pContext->hWriteMAC))
  101. {
  102. SP_LOG_RESULT(GetLastError());
  103. }
  104. }
  105. pContext->hWriteMAC = 0;
  106. }
  107. #endif
  108. SECURITY_STATUS
  109. SslAddUserContext(
  110. IN LSA_SEC_HANDLE LsaHandle,
  111. IN HANDLE Token, // optional
  112. IN PSecBuffer ContextData,
  113. IN BOOL fImportedContext)
  114. {
  115. DWORD Size;
  116. PSSL_USER_CONTEXT Context ;
  117. SP_STATUS Status ;
  118. ULONG ListIndex;
  119. ULONG LockIndex;
  120. DebugLog(( DEB_TRACE, "SslAddUserContext: 0x%p\n", LsaHandle ));
  121. if ( ContextData->cbBuffer < sizeof( SPPackedContext ) )
  122. {
  123. return( SEC_E_INVALID_TOKEN );
  124. }
  125. if(!fImportedContext)
  126. {
  127. Context = SslFindUserContext( LsaHandle );
  128. if ( Context )
  129. {
  130. DebugLog(( DEB_TRACE, "Replacing existing context!\n" ));
  131. // Destroy elements of existing context.
  132. LsaContextDelete(Context->pContext);
  133. SPExternalFree(Context->pContext);
  134. Context->pContext = NULL;
  135. Status = SPContextDeserialize( ContextData->pvBuffer,
  136. &Context->pContext);
  137. if(Status != PCT_ERR_OK)
  138. {
  139. return SP_LOG_RESULT(SEC_E_DECRYPT_FAILURE);
  140. }
  141. return( SEC_E_OK );
  142. }
  143. }
  144. Context = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
  145. sizeof( SSL_USER_CONTEXT ));
  146. if ( !Context )
  147. {
  148. return( SEC_E_INSUFFICIENT_MEMORY );
  149. }
  150. Status = SPContextDeserialize( ContextData->pvBuffer,
  151. &Context->pContext);
  152. if(Status != PCT_ERR_OK)
  153. {
  154. LocalFree(Context);
  155. return SP_LOG_RESULT(SEC_E_DECRYPT_FAILURE);
  156. }
  157. if(ARGUMENT_PRESENT(Token))
  158. {
  159. Context->pContext->RipeZombie->hLocator = (HLOCATOR)Token;
  160. }
  161. Context->LsaHandle = LsaHandle ;
  162. Context->Align = ContextData->cbBuffer ;
  163. ListIndex = HandleToListIndex( LsaHandle );
  164. LockIndex = ListIndexToLockIndex( ListIndex );
  165. RtlAcquireResourceExclusive( &SslContextLock[LockIndex], TRUE );
  166. InsertTailList( &SslContextList[ListIndex], &Context->List );
  167. RtlReleaseResource( &SslContextLock[LockIndex] );
  168. return( SEC_E_OK );
  169. }
  170. PSSL_USER_CONTEXT
  171. SslReferenceUserContext(
  172. IN LSA_SEC_HANDLE LsaHandle,
  173. IN BOOLEAN Delete
  174. )
  175. {
  176. PLIST_ENTRY List ;
  177. PSSL_USER_CONTEXT Context = NULL ;
  178. ULONG ListIndex;
  179. ULONG LockIndex;
  180. ListIndex = HandleToListIndex( LsaHandle );
  181. LockIndex = ListIndexToLockIndex( ListIndex );
  182. if( !Delete )
  183. {
  184. RtlAcquireResourceShared( &SslContextLock[LockIndex], TRUE );
  185. } else {
  186. RtlAcquireResourceExclusive( &SslContextLock[LockIndex], TRUE );
  187. }
  188. List = SslContextList[ListIndex].Flink ;
  189. while ( List != &SslContextList[ListIndex] )
  190. {
  191. Context = CONTAINING_RECORD( List, SSL_USER_CONTEXT, List.Flink );
  192. if ( Context->LsaHandle == LsaHandle )
  193. {
  194. if( Delete )
  195. {
  196. RemoveEntryList( &Context->List );
  197. }
  198. break;
  199. }
  200. Context = NULL ;
  201. List = List->Flink ;
  202. }
  203. RtlReleaseResource( &SslContextLock[LockIndex] );
  204. return( Context );
  205. }
  206. PSSL_USER_CONTEXT
  207. SslFindUserContext(
  208. IN LSA_SEC_HANDLE LsaHandle
  209. )
  210. {
  211. return SslReferenceUserContext( LsaHandle, FALSE );
  212. }
  213. PSSL_USER_CONTEXT
  214. SslFindUserContextEx(
  215. IN PCRED_THUMBPRINT pThumbprint
  216. )
  217. {
  218. PLIST_ENTRY List ;
  219. PSSL_USER_CONTEXT Context = NULL ;
  220. ULONG ListIndex;
  221. ULONG LockIndex;
  222. DebugLog(( DEB_TRACE, "SslFindUserContextEx: \n"));
  223. for (ListIndex = 0 ; ListIndex < SCHANNEL_USERLIST_COUNT ; ListIndex++)
  224. {
  225. LockIndex = ListIndexToLockIndex( ListIndex );
  226. RtlAcquireResourceShared( &SslContextLock[LockIndex], TRUE );
  227. List = SslContextList[ListIndex].Flink ;
  228. while ( List != &SslContextList[ListIndex] )
  229. {
  230. Context = CONTAINING_RECORD( List, SSL_USER_CONTEXT, List.Flink );
  231. if(Context->pContext != NULL &&
  232. IsSameThumbprint(pThumbprint, &Context->pContext->ContextThumbprint))
  233. {
  234. RtlReleaseResource( &SslContextLock[LockIndex] );
  235. goto done;
  236. }
  237. List = List->Flink ;
  238. }
  239. RtlReleaseResource( &SslContextLock[LockIndex] );
  240. }
  241. Context = NULL ;
  242. done:
  243. return( Context );
  244. }
  245. VOID
  246. SslDeleteUserContext(
  247. IN LSA_SEC_HANDLE LsaHandle
  248. )
  249. {
  250. PSSL_USER_CONTEXT Context ;
  251. Context = SslReferenceUserContext( LsaHandle, TRUE );
  252. if ( Context )
  253. {
  254. DebugLog(( DEB_TRACE, "Deleting user mode context %x, handle = %x\n",
  255. Context, LsaHandle ));
  256. LsaContextDelete(Context->pContext);
  257. SPExternalFree(Context->pContext);
  258. LocalFree( Context );
  259. }
  260. else
  261. {
  262. DebugLog(( DEB_TRACE, "No context found for handle %x\n", LsaHandle ));
  263. }
  264. }
  265. ULONG
  266. HandleToListIndex(
  267. ULONG_PTR ContextHandle
  268. )
  269. {
  270. ULONG Number ;
  271. ULONG Hash;
  272. ULONG HashFinal;
  273. ASSERT( (SCHANNEL_USERLIST_COUNT != 0) );
  274. ASSERT( (SCHANNEL_USERLIST_COUNT & 1) == 0 );
  275. Number = (ULONG)ContextHandle;
  276. Hash = Number;
  277. Hash += Number >> 8;
  278. Hash += Number >> 16;
  279. Hash += Number >> 24;
  280. HashFinal = Hash;
  281. HashFinal += Hash >> 4;
  282. //
  283. // insure power of two if not one.
  284. //
  285. return ( HashFinal & (SCHANNEL_USERLIST_COUNT-1) ) ;
  286. }
  287. ULONG
  288. __inline
  289. ListIndexToLockIndex(
  290. ULONG ListIndex
  291. )
  292. {
  293. ASSERT( (SCHANNEL_USERLIST_LOCK_COUNT) != 0 );
  294. ASSERT( (SCHANNEL_USERLIST_LOCK_COUNT & 1) == 0 );
  295. //
  296. // insure power of two if not one.
  297. //
  298. return ( ListIndex & (SCHANNEL_USERLIST_LOCK_COUNT-1) );
  299. }