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.

309 lines
6.4 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: cred.cxx
  7. //
  8. // Contents: Credential class used to store common security credential
  9. // for NTLM and Kerberos
  10. //
  11. // Classes: CCredential
  12. //
  13. // Functions: CCredential::CCredential()
  14. // CCredential::~CCredential()
  15. //
  16. //
  17. // History: 12-Jan-94 MikeSw Created
  18. //
  19. //--------------------------------------------------------------------------
  20. #include <secpch2.hxx>
  21. #pragma hdrstop
  22. // NT Headers
  23. #include <credlist.hxx>
  24. #include "debug.hxx"
  25. //
  26. // Global Data
  27. //
  28. //+-------------------------------------------------------------------------
  29. //
  30. // Function: CCredential::Credential()
  31. //
  32. // Synopsis: Constructor.
  33. //
  34. // Effects:
  35. //
  36. //--------------------------------------------------------------------------
  37. CCredential::CCredential(CCredentialList *pOwningList)
  38. {
  39. DebugOut((CRED_FUNC, "CCredential()\n"));
  40. _Check = CRED_CHECK_VALUE;
  41. _dwCredID = 0;
  42. _dwProcessID = 0;
  43. _pOwningList = pOwningList;
  44. _pLock = NULL;
  45. }
  46. //+-------------------------------------------------------------------------
  47. //
  48. // Function: CCredential::~CCredential()
  49. //
  50. // Synopsis: Destructor.
  51. //
  52. // Notes: Credential should be locked to delete it. An implemenation
  53. // should write a real destructor that cleans up all the
  54. // other data, such as user name.
  55. //
  56. //
  57. //--------------------------------------------------------------------------
  58. CCredential::~CCredential()
  59. {
  60. // DsysAssert(_pLock);
  61. DebugOut((DEB_TRACE,"Deleting credential %p\n",this));
  62. _Check = 0;
  63. if (_pLock != NULL)
  64. {
  65. if (!_pOwningList->FreeCredLock(_pLock,TRUE))
  66. {
  67. DebugOut((DEB_ERROR,"Lock conflict in freed credential - thread still waiting\n"));
  68. }
  69. }
  70. _pOwningList = NULL;
  71. }
  72. //+-------------------------------------------------------------------------
  73. //
  74. // Function: CCredential::Lock()
  75. //
  76. // Synopsis:
  77. //
  78. // Effects:
  79. //
  80. // Arguments:
  81. //
  82. // Requires:
  83. //
  84. // Returns:
  85. //
  86. // Notes:
  87. //
  88. //
  89. //--------------------------------------------------------------------------
  90. BOOLEAN
  91. CCredential::Lock()
  92. {
  93. DWORD checkvalue;
  94. HRESULT hrRet;
  95. BOOLEAN fLockedList = FALSE;
  96. BOOLEAN bRet = TRUE;
  97. CCredentialList * pCredList = NULL;
  98. //
  99. // Verify that this credential is valid:
  100. //
  101. __try
  102. {
  103. hrRet = SEC_E_INVALID_HANDLE;
  104. if (_pOwningList)
  105. {
  106. //
  107. // First check the _Check value. This isn't sufficient, since
  108. // by the time we lock the list it may change, so we check
  109. // again afterwards.
  110. //
  111. if (_Check == CRED_CHECK_VALUE)
  112. {
  113. //
  114. // Copy on pCredList just in case it gets changed on us
  115. // so we can still unlock it.
  116. //
  117. pCredList = _pOwningList;
  118. pCredList->rCredentials.GetWrite();
  119. fLockedList = TRUE;
  120. checkvalue = _Check;
  121. //
  122. // Now check the check value.
  123. //
  124. if (checkvalue == CRED_CHECK_VALUE)
  125. {
  126. hrRet = S_OK;
  127. }
  128. }
  129. }
  130. }
  131. __except(EXCEPTION_EXECUTE_HANDLER)
  132. {
  133. hrRet = SEC_E_INVALID_HANDLE;
  134. }
  135. if (FAILED(hrRet))
  136. {
  137. if (fLockedList)
  138. {
  139. pCredList->rCredentials.Release();
  140. }
  141. DebugOut((DEB_WARN,"Invalid cred passed to lock: %p\n",this));
  142. return(FALSE);
  143. }
  144. DebugOut((DEB_TRACE,"Going to lock creds for 0x%x:%wS\n",
  145. _dwCredID,&_Name));
  146. // If the pLock field is non-null, then there is an active user of
  147. // the credentials.
  148. if (_pLock)
  149. {
  150. // If we already own this lock, bump the recursion count:
  151. if (_pLock->dwThread == GetCurrentThreadId())
  152. {
  153. // Null body
  154. }
  155. else
  156. {
  157. //
  158. // Otherwise, we block on the CredLock.
  159. //
  160. // Note: BlockOnCredLock will release the CredList exclusive lock
  161. // for the duration of its wait, and re-obtain it before it
  162. // returns.
  163. //
  164. bRet = pCredList->BlockOnCredLock(_pLock);
  165. }
  166. }
  167. else
  168. {
  169. _pLock = _pOwningList->AllocateCredLock();
  170. if (!_pLock)
  171. DebugOut((DEB_ERROR, "AllocateCredLock failed\n"));
  172. }
  173. if (bRet)
  174. {
  175. _pLock->dwThread = GetCurrentThreadId();
  176. _pLock->cRecursion++;
  177. DebugOut((DEB_TRACE,"Locked creds for %wS\n",
  178. &_Name));
  179. }
  180. #if DBG
  181. else
  182. {
  183. DebugOut((DEB_WARN,"Failed to lock creds, cred was freed while waiting\n"));
  184. }
  185. #endif
  186. pCredList->rCredentials.Release();
  187. return(bRet);
  188. }
  189. //+-------------------------------------------------------------------------
  190. //
  191. // Function: CCredentials::Release
  192. //
  193. // Synopsis:
  194. //
  195. // Effects:
  196. //
  197. // Arguments:
  198. //
  199. // Requires:
  200. //
  201. // Returns:
  202. //
  203. // Notes:
  204. //
  205. //
  206. //--------------------------------------------------------------------------
  207. BOOLEAN
  208. CCredential::Release()
  209. {
  210. #if DBG
  211. if (!_pLock)
  212. {
  213. DebugOut((DEB_WARN, "UnlockCredentials - Creds for %wS aren't locked\n",
  214. &_Name));
  215. return(TRUE);
  216. }
  217. #endif
  218. if (_pLock->dwThread != GetCurrentThreadId())
  219. {
  220. DebugOut((DEB_ERROR, "UnlockCredentials: Not owner of creds for %wS\n",
  221. &_Name));
  222. return(FALSE);
  223. }
  224. _pOwningList->rCredentials.GetWrite();
  225. DebugOut((DEB_TRACE, "Unlocking credentials of 0x%x:%wS(%d,%d)\n",
  226. _dwCredID,
  227. &_Name,
  228. _pLock->cRecursion,
  229. _pLock->cWaiters));
  230. //
  231. // First, decrement the recusion count. If it is not zero, then
  232. // this thread has multiple locks on this credential. So, this unlock
  233. // is successful, but the credentials are still locked.
  234. //
  235. if (--_pLock->cRecursion)
  236. {
  237. _pOwningList->rCredentials.Release();
  238. return(TRUE);
  239. }
  240. if (_pOwningList->FreeCredLock(_pLock,FALSE))
  241. {
  242. _pLock = NULL;
  243. }
  244. DebugOut((DEB_TRACE,"Released creds for %wS\n",
  245. &_Name));
  246. _pOwningList->rCredentials.Release();
  247. return(TRUE);
  248. }