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.
414 lines
9.3 KiB
414 lines
9.3 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
certcach.hxx
|
|
|
|
Abstract:
|
|
|
|
Contains class definition for certificate cache object.
|
|
The class acts a container for common certificates.
|
|
|
|
Contents:
|
|
SECURITY_CACHE_LIST
|
|
SECURITY_CACHE_LIST_ENTRY
|
|
|
|
Author:
|
|
|
|
Arthur L Bierer (arthurbi) 20-Apr-1996
|
|
|
|
Revision History:
|
|
|
|
20-Apr-1996 arthurbi
|
|
Created
|
|
|
|
--*/
|
|
|
|
|
|
typedef struct _SEC_PROVIDER
|
|
{
|
|
CHAR *pszName; // security pkg name
|
|
CredHandle hCreds; // credential handle
|
|
DWORD dwFlags; // encryption capabilities
|
|
BOOL fEnabled; // enable flag indicator
|
|
DWORD dwProtocolFlags; // protocol flags that this provider supports.
|
|
PCCERT_CONTEXT pCertCtxt; // cert context to use when getting default credentials.
|
|
} SEC_PROVIDER, *PSEC_PROVIDER;
|
|
|
|
// Default list of security packages to enumerate
|
|
#define MAX_SEC_PROVIDERS 3
|
|
|
|
extern const SEC_PROVIDER g_cSecProviders[MAX_SEC_PROVIDERS];
|
|
|
|
enum SSL_IMPERSONATION_LEVEL
|
|
{
|
|
SSL_IMPERSONATION_DISABLED = 0,
|
|
SSL_IMPERSONATION_ENABLED = 1,
|
|
SSL_IMPERSONATION_UNINITIALIZED = 2
|
|
};
|
|
|
|
//
|
|
// SECURITY_INFO_LIST_ENTRY - contains all security info
|
|
// pertaining to all connections to a server.
|
|
//
|
|
|
|
class SECURITY_CACHE_LIST_ENTRY {
|
|
|
|
friend class SECURITY_CACHE_LIST;
|
|
|
|
private:
|
|
|
|
//
|
|
// _List - Generic List entry structure.
|
|
//
|
|
|
|
LIST_ENTRY _List;
|
|
|
|
//
|
|
// _cRef - Reference count for this element.
|
|
//
|
|
|
|
LONG _cRef;
|
|
|
|
//
|
|
// _CertInfo - Certificate and other security
|
|
// attributes for the connection to
|
|
// this machine.
|
|
//
|
|
|
|
INTERNET_SECURITY_INFO _CertInfo;
|
|
|
|
//
|
|
// _dwSecurityFlags - Overrides for warnings.
|
|
//
|
|
|
|
DWORD _dwSecurityFlags;
|
|
|
|
//
|
|
// _dwStatusFlags - Tracker for all secure connection failure flags.
|
|
//
|
|
|
|
DWORD _dwStatusFlags;
|
|
|
|
//
|
|
// _ServerName - The name of the server
|
|
//
|
|
|
|
ICSTRING _ServerName;
|
|
|
|
INTERNET_PORT _ServerPort;
|
|
|
|
//
|
|
// _pCertChainList - If there is Client Authentication do be done with this server,
|
|
// then we'll cache it and remeber it later.
|
|
//
|
|
|
|
CERT_CONTEXT_ARRAY *_pCertContextArray;
|
|
|
|
//
|
|
// _fInCache - indicates this element is held by the cache
|
|
//
|
|
|
|
BOOL _fInCache;
|
|
|
|
//
|
|
// _fNoRevert - indicates whether or not any potential impersonation
|
|
// should be reverted during SSL handling.
|
|
//
|
|
|
|
BOOL _fNoRevert;
|
|
|
|
#if INET_DEBUG
|
|
DWORD m_Signature;
|
|
#endif
|
|
|
|
public:
|
|
|
|
LONG AddRef(VOID);
|
|
LONG Release(VOID);
|
|
|
|
//
|
|
// Cleans up object, so it can be reused
|
|
//
|
|
|
|
BOOL InCache() { return _fInCache; }
|
|
|
|
const INTERNET_SECURITY_INFO& GetSecInfo() const { return _CertInfo; }
|
|
|
|
VOID
|
|
Clear();
|
|
|
|
SECURITY_CACHE_LIST_ENTRY(
|
|
IN BOOL fNoRevert,
|
|
IN LPSTR lpszHostName,
|
|
IN INTERNET_PORT ServerPort
|
|
);
|
|
|
|
~SECURITY_CACHE_LIST_ENTRY();
|
|
|
|
//
|
|
// Copy CERT_INFO IN Method -
|
|
// copies a structure into our object.
|
|
//
|
|
|
|
SECURITY_CACHE_LIST_ENTRY& operator=(LPINTERNET_SECURITY_INFO Cert)
|
|
{
|
|
|
|
if(_CertInfo.pCertificate)
|
|
{
|
|
WRAP_REVERT_USER_VOID((*g_pfnCertFreeCertificateContext),
|
|
_fNoRevert,
|
|
(_CertInfo.pCertificate));
|
|
}
|
|
_CertInfo.dwSize = sizeof(_CertInfo);
|
|
WRAP_REVERT_USER((*g_pfnCertDuplicateCertificateContext),
|
|
_fNoRevert,
|
|
(Cert->pCertificate),
|
|
_CertInfo.pCertificate);
|
|
_CertInfo.dwProtocol = Cert->dwProtocol;
|
|
|
|
_CertInfo.aiCipher = Cert->aiCipher;
|
|
_CertInfo.dwCipherStrength = Cert->dwCipherStrength;
|
|
_CertInfo.aiHash = Cert->aiHash;
|
|
_CertInfo.dwHashStrength = Cert->dwHashStrength;
|
|
_CertInfo.aiExch = Cert->aiExch;
|
|
_CertInfo.dwExchStrength = Cert->dwExchStrength;
|
|
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
// Copy CERT_INFO OUT Method -
|
|
// need to copy ourselves out.
|
|
//
|
|
|
|
VOID
|
|
CopyOut(INTERNET_SECURITY_INFO &Cert)
|
|
{
|
|
Cert.dwSize = sizeof(Cert);
|
|
WRAP_REVERT_USER((*g_pfnCertDuplicateCertificateContext),
|
|
_fNoRevert,
|
|
(_CertInfo.pCertificate),
|
|
Cert.pCertificate);
|
|
Cert.dwProtocol = _CertInfo.dwProtocol;
|
|
|
|
Cert.aiCipher = _CertInfo.aiCipher;
|
|
Cert.dwCipherStrength = _CertInfo.dwCipherStrength;
|
|
Cert.aiHash = _CertInfo.aiHash;
|
|
Cert.dwHashStrength = _CertInfo.dwHashStrength;
|
|
Cert.aiExch = _CertInfo.aiExch;
|
|
Cert.dwExchStrength = _CertInfo.dwExchStrength;
|
|
}
|
|
|
|
//
|
|
// Sets and Gets the Client Authentication CertChain -
|
|
// we piggy back this pointer into the cache so we can cache
|
|
// previously generated and selected client auth certs.
|
|
//
|
|
|
|
VOID SetCertContextArray(CERT_CONTEXT_ARRAY *pCertContextArray) {
|
|
if (_pCertContextArray) {
|
|
delete _pCertContextArray;
|
|
}
|
|
_pCertContextArray = pCertContextArray;
|
|
}
|
|
|
|
CERT_CONTEXT_ARRAY * GetCertContextArray() {
|
|
return _pCertContextArray;
|
|
}
|
|
|
|
DWORD GetSecureFlags() {
|
|
return _dwSecurityFlags;
|
|
}
|
|
|
|
VOID SetSecureFlags(DWORD dwFlags) {
|
|
_dwSecurityFlags |= dwFlags;
|
|
}
|
|
|
|
VOID ClearSecureFlags(DWORD dwFlags) {
|
|
_dwSecurityFlags &= (~dwFlags);
|
|
}
|
|
|
|
DWORD GetStatusFlags(VOID)
|
|
{
|
|
return _dwStatusFlags;
|
|
}
|
|
|
|
VOID SetStatusFlags(DWORD dwFlags)
|
|
{
|
|
_dwStatusFlags |= dwFlags;
|
|
}
|
|
|
|
VOID ClearStatusFlags(DWORD dwFlags)
|
|
{
|
|
_dwStatusFlags &= (~dwFlags);
|
|
}
|
|
|
|
LPSTR GetHostName(VOID) {
|
|
return _ServerName.StringAddress();
|
|
}
|
|
|
|
BOOL IsImpersonationEnabled() {
|
|
return _fNoRevert;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SECURITY_CACHE_LIST {
|
|
|
|
private:
|
|
|
|
//
|
|
// _List - serialized list of SECURITY_CACHE_LIST_ENTRY objects
|
|
//
|
|
|
|
SERIALIZED_LIST _List;
|
|
|
|
#if INET_DEBUG
|
|
DWORD m_Signature;
|
|
#endif
|
|
|
|
//
|
|
// Array of encryption providers
|
|
//
|
|
SEC_PROVIDER _SecProviders[MAX_SEC_PROVIDERS];
|
|
|
|
//
|
|
// EncProvider flag
|
|
//
|
|
|
|
DWORD _dwEncFlags;
|
|
|
|
// Enabled SSL protocols for the session
|
|
DWORD _dwSecureProtocols;
|
|
|
|
SSL_IMPERSONATION_LEVEL _eImpersonationLevel;
|
|
|
|
LONG _cRefs;
|
|
|
|
public:
|
|
|
|
SECURITY_CACHE_LIST()
|
|
{
|
|
_cRefs = 1;
|
|
_eImpersonationLevel = SSL_IMPERSONATION_UNINITIALIZED;
|
|
}
|
|
|
|
LONG AddRef(VOID)
|
|
{
|
|
return (InterlockedIncrement(&_cRefs));
|
|
}
|
|
|
|
LONG Release(VOID)
|
|
{
|
|
// We can get away with interlocked increment/decrement
|
|
// because we're guaranteed to always have a live WHO
|
|
// reference anytime this is addref'ed.
|
|
LONG cRefs = InterlockedDecrement(&_cRefs);
|
|
|
|
if (cRefs == 0)
|
|
{
|
|
Terminate();
|
|
delete this;
|
|
}
|
|
return cRefs;
|
|
}
|
|
|
|
SECURITY_CACHE_LIST_ENTRY *
|
|
Find(
|
|
IN LPSTR lpszHostname,
|
|
IN INTERNET_PORT HostPort
|
|
);
|
|
|
|
BOOL Initialize(
|
|
VOID
|
|
);
|
|
|
|
VOID Terminate(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
ClearList(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
Add(
|
|
IN SECURITY_CACHE_LIST_ENTRY * entry
|
|
);
|
|
|
|
#if 0
|
|
|
|
BOOL
|
|
IsCertInCache(
|
|
IN LPSTR lpszHostname
|
|
)
|
|
{
|
|
SECURITY_CACHE_LIST_ENTRY *entry =
|
|
Find(lpszHostname);
|
|
|
|
if ( entry )
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
VOID SetSecureProtocols(DWORD dwSecureProtocols)
|
|
{
|
|
_dwSecureProtocols = dwSecureProtocols;
|
|
}
|
|
|
|
DWORD GetSecureProtocols()
|
|
{
|
|
return _dwSecureProtocols;
|
|
}
|
|
|
|
VOID SetEncFlags(DWORD dwEncFlags)
|
|
{
|
|
_dwEncFlags = dwEncFlags;
|
|
}
|
|
|
|
DWORD GetEncFlags()
|
|
{
|
|
return _dwEncFlags;
|
|
}
|
|
|
|
SEC_PROVIDER *GetSecProviders()
|
|
{
|
|
return _SecProviders;
|
|
}
|
|
|
|
DWORD SetImpersonationLevel(BOOL fLeaveImpersonation)
|
|
{
|
|
if (_eImpersonationLevel == SSL_IMPERSONATION_UNINITIALIZED)
|
|
{
|
|
_eImpersonationLevel = (fLeaveImpersonation ?
|
|
SSL_IMPERSONATION_ENABLED : SSL_IMPERSONATION_DISABLED);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// Can only be set once. This must also be initialized
|
|
// upon creation of the first request handle if the
|
|
// client doesn't set prior the first send request.
|
|
return ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
|
|
}
|
|
}
|
|
|
|
BOOL IsImpersonationLevelInitialized()
|
|
{
|
|
return (_eImpersonationLevel == SSL_IMPERSONATION_UNINITIALIZED);
|
|
}
|
|
|
|
BOOL IsImpersonationEnabled()
|
|
{
|
|
return (_eImpersonationLevel == SSL_IMPERSONATION_ENABLED);
|
|
}
|
|
|
|
};
|