//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1992. // // File: cred.cxx // // Contents: Credential class used to store common security credential // for NTLM and Kerberos // // Classes: CCredential // // Functions: CCredential::CCredential() // CCredential::~CCredential() // // // History: 12-Jan-94 MikeSw Created // //-------------------------------------------------------------------------- #include #pragma hdrstop // NT Headers #include #include "debug.hxx" // // Global Data // //+------------------------------------------------------------------------- // // Function: CCredential::Credential() // // Synopsis: Constructor. // // Effects: // //-------------------------------------------------------------------------- CCredential::CCredential(CCredentialList *pOwningList) { DebugOut((CRED_FUNC, "CCredential()\n")); _Check = CRED_CHECK_VALUE; _dwCredID = 0; _dwProcessID = 0; _pOwningList = pOwningList; _pLock = NULL; } //+------------------------------------------------------------------------- // // Function: CCredential::~CCredential() // // Synopsis: Destructor. // // Notes: Credential should be locked to delete it. An implemenation // should write a real destructor that cleans up all the // other data, such as user name. // // //-------------------------------------------------------------------------- CCredential::~CCredential() { // DsysAssert(_pLock); DebugOut((DEB_TRACE,"Deleting credential %p\n",this)); _Check = 0; if (_pLock != NULL) { if (!_pOwningList->FreeCredLock(_pLock,TRUE)) { DebugOut((DEB_ERROR,"Lock conflict in freed credential - thread still waiting\n")); } } _pOwningList = NULL; } //+------------------------------------------------------------------------- // // Function: CCredential::Lock() // // Synopsis: // // Effects: // // Arguments: // // Requires: // // Returns: // // Notes: // // //-------------------------------------------------------------------------- BOOLEAN CCredential::Lock() { DWORD checkvalue; HRESULT hrRet; BOOLEAN fLockedList = FALSE; BOOLEAN bRet = TRUE; CCredentialList * pCredList = NULL; // // Verify that this credential is valid: // __try { hrRet = SEC_E_INVALID_HANDLE; if (_pOwningList) { // // First check the _Check value. This isn't sufficient, since // by the time we lock the list it may change, so we check // again afterwards. // if (_Check == CRED_CHECK_VALUE) { // // Copy on pCredList just in case it gets changed on us // so we can still unlock it. // pCredList = _pOwningList; pCredList->rCredentials.GetWrite(); fLockedList = TRUE; checkvalue = _Check; // // Now check the check value. // if (checkvalue == CRED_CHECK_VALUE) { hrRet = S_OK; } } } } __except(EXCEPTION_EXECUTE_HANDLER) { hrRet = SEC_E_INVALID_HANDLE; } if (FAILED(hrRet)) { if (fLockedList) { pCredList->rCredentials.Release(); } DebugOut((DEB_WARN,"Invalid cred passed to lock: %p\n",this)); return(FALSE); } DebugOut((DEB_TRACE,"Going to lock creds for 0x%x:%wS\n", _dwCredID,&_Name)); // If the pLock field is non-null, then there is an active user of // the credentials. if (_pLock) { // If we already own this lock, bump the recursion count: if (_pLock->dwThread == GetCurrentThreadId()) { // Null body } else { // // Otherwise, we block on the CredLock. // // Note: BlockOnCredLock will release the CredList exclusive lock // for the duration of its wait, and re-obtain it before it // returns. // bRet = pCredList->BlockOnCredLock(_pLock); } } else { _pLock = _pOwningList->AllocateCredLock(); if (!_pLock) DebugOut((DEB_ERROR, "AllocateCredLock failed\n")); } if (bRet) { _pLock->dwThread = GetCurrentThreadId(); _pLock->cRecursion++; DebugOut((DEB_TRACE,"Locked creds for %wS\n", &_Name)); } #if DBG else { DebugOut((DEB_WARN,"Failed to lock creds, cred was freed while waiting\n")); } #endif pCredList->rCredentials.Release(); return(bRet); } //+------------------------------------------------------------------------- // // Function: CCredentials::Release // // Synopsis: // // Effects: // // Arguments: // // Requires: // // Returns: // // Notes: // // //-------------------------------------------------------------------------- BOOLEAN CCredential::Release() { #if DBG if (!_pLock) { DebugOut((DEB_WARN, "UnlockCredentials - Creds for %wS aren't locked\n", &_Name)); return(TRUE); } #endif if (_pLock->dwThread != GetCurrentThreadId()) { DebugOut((DEB_ERROR, "UnlockCredentials: Not owner of creds for %wS\n", &_Name)); return(FALSE); } _pOwningList->rCredentials.GetWrite(); DebugOut((DEB_TRACE, "Unlocking credentials of 0x%x:%wS(%d,%d)\n", _dwCredID, &_Name, _pLock->cRecursion, _pLock->cWaiters)); // // First, decrement the recusion count. If it is not zero, then // this thread has multiple locks on this credential. So, this unlock // is successful, but the credentials are still locked. // if (--_pLock->cRecursion) { _pOwningList->rCredentials.Release(); return(TRUE); } if (_pOwningList->FreeCredLock(_pLock,FALSE)) { _pLock = NULL; } DebugOut((DEB_TRACE,"Released creds for %wS\n", &_Name)); _pOwningList->rCredentials.Release(); return(TRUE); }