Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

698 lines
16 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
trust.c
Abstract:
This module implements WinVerifyTrust and related API
Author:
Robert Reichel (RobertRe) 3-18-96
Revision History:
--*/
#ifdef _DEBUG
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#endif
#include <windows.h>
#include <wintrust.h>
#include "provider.h"
#include "sip.h"
#include "trust.h"
#include <wtypes.h>
#ifdef _DEBUG
DWORD OwningThread = 0;
#endif
//
// Private data
//
LIST_LOCK ListLock;
HANDLE ListEvent;
//
// Exported routines: prototypes
//
DWORD
WinTrustServerPing(
IN LPWSTR lpProviderName,
IN DWORD dwParameter,
OUT LPDWORD lpdwResult
);
BOOL
WinTrustCheckSubjectContentInfo(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject, // pointer to subject info
IN LPWIN_CERTIFICATE lpSignedData // PKCS #7 Signed Data
);
BOOL
WinTrustEnumSubjectCertificates(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject, // pointer to subject info
IN DWORD dwTypeFilter, // 0 or WIN_CERT_TYPE_xxx
OUT LPDWORD lpCertificateCount,
IN OUT LPDWORD lpIndices, // Rcvs WIN_CERT_TYPE_
IN DWORD dwIndexCount
);
BOOL
WinTrustGetSubjectCertificate(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject,
IN DWORD dwCertificateIndex,
OUT LPWIN_CERTIFICATE lpCertificate,
IN OUT LPDWORD lpRequiredLength
);
BOOL
WinTrustGetSubjectCertHeader(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject,
IN DWORD dwCertificateIndex,
OUT LPWIN_CERTIFICATE lpCertificateHeader
);
BOOL
WinTrustGetSubjectName(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject,
IN LPWIN_CERTIFICATE lpSignedData,
IN OUT LPWSTR lpBuffer,
IN OUT LPDWORD lpRequiredLength
);
//
// WinTrustClientTPDispatchTable - Table of function pointers passed
// to trust providers during their initialization routines.
//
WINTRUST_CLIENT_TP_DISPATCH_TABLE WinTrustClientTPDispatchTable = {
WinTrustServerPing,
WinTrustCheckSubjectContentInfo,
WinTrustEnumSubjectCertificates,
WinTrustGetSubjectCertificate,
WinTrustGetSubjectCertHeader,
WinTrustGetSubjectName
};
//
// WinTrustClientTPInfo - Structure passed to trust providers via their
// initialization routine.
//
WINTRUST_CLIENT_TP_INFO WinTrustClientTPInfo = {
WIN_TRUST_REVISION_1_0,
&WinTrustClientTPDispatchTable
};
LONG
WinVerifyTrust(
HWND hwnd,
GUID * ActionID,
LPVOID ActionData
)
/*++
Routine Description:
Top level routine for WinVerifyTrust. This routine will attempt to
find a trust provider that supports the passed ActionID, and if successful,
will pass the passed ActionData to the loaded trust provider.
Arguments:
hwnd - Optionally supplies the handle to a parent window to allow
trust providers to display a UI.
ActionID - Supplies the action to be performed.
ActionData - Supplies subject information for the passed ActionID.
Return Value:
Returns TRUE for success, FALSE for failure. Extended error status
is available using GetLastError.
--*/
{
PLOADED_PROVIDER Provider;
LONG rc;
//
// First, find a trust provider that supports
// the passed action ID
//
Provider = WinTrustFindActionID(
ActionID
);
if (NULL == Provider) {
return( TRUST_E_PROVIDER_UNKNOWN );
}
rc = (*Provider->ClientInfo->lpServices->VerifyTrust)( hwnd,
ActionID,
ActionData
);
return( rc );
}
DWORD
WinTrustServerPing(
IN LPWSTR lpProviderName,
IN DWORD dwParameter,
OUT LPDWORD lpdwResult
)
/*++
Routine Description:
Not currently implemented.
Implements server ping functionality. See WinTrust Developer's Guide
for more information.
Arguments:
lpProviderName - Supplies the name that was passed to the provider when
it was initialized.
dwParameter - Unexamined parameter, passed to server side.
lpdwResult - Unexamined return code from server side.
Return Value:
Returns TRUE for success, FALSE for failure. Extended error status
is available using GetLastError.
--*/
{
return( (DWORD)0 );
}
BOOL
WinTrustCheckSubjectContentInfo(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject, // pointer to subject info
IN LPWIN_CERTIFICATE lpSignedData // PKCS #7 Signed Data
)
/*++
Routine Description:
Attempts to find a SIP that supports the passed subject form. If
successful, calls the SIP asking it to verify the subject based on
the contents of the passed WIN_CERTIFICATE.
Arguments:
lpSubject - Supplies the subject information, where the subject is the
data item (e.g., file) being examined.
lpSignedData - Supplies the signature data to be verified.
Return Value:
Returns TRUE for success, FALSE for failure. Extended error status
is available using GetLastError.
--*/
{
GUID * SubjectForm;
PLOADED_SIP Sip;
BOOL bool;
SubjectForm = lpSubject->SubjectType;
//
// Find a SIP that supports
// the passed subject type.
//
Sip = WinTrustFindSubjectForm(
SubjectForm
);
if (NULL == Sip) {
SetLastError( (DWORD)TRUST_E_SUBJECT_FORM_UNKNOWN );
return( FALSE );
}
bool = (*Sip->SipInfo->lpServices->CheckSubjectContentInfo)( lpSubject,
lpSignedData
);
return( bool );
}
BOOL
WinTrustEnumSubjectCertificates(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject, // pointer to subject info
IN DWORD dwTypeFilter, // 0 or WIN_CERT_TYPE_xxx
OUT LPDWORD lpCertificateCount,
IN OUT LPDWORD lpIndices, // Rcvs WIN_CERT_TYPE_
IN DWORD dwIndexCount
)
/*++
Routine Description:
Attempts to find a SIP that supports the passed subject form. If
successful, calls the SIP asking it to enumerate the certificates
in the subject based on the passed TypeFilter.
Arguments:
lpSubject - Supplies the subject information, where the subject is the
data item (e.g., file) being examined.
dwTypeFilter
lpCertificateCount
lpIndices
dwIndexCount
Return Value:
Returns TRUE for success, FALSE for failure. Extended error status
is available using GetLastError.
--*/
{
GUID * SubjectForm;
PLOADED_SIP Sip;
BOOL bool;
SubjectForm = lpSubject->SubjectType;
//
// Find a SIP that supports
// the passed subject type.
//
Sip = WinTrustFindSubjectForm(
SubjectForm
);
if (NULL == Sip) {
SetLastError( (DWORD)TRUST_E_SUBJECT_FORM_UNKNOWN );
return( FALSE );
}
bool = (*Sip->SipInfo->lpServices->EnumSubjectCertificates)( lpSubject,
dwTypeFilter,
lpCertificateCount,
lpIndices,
dwIndexCount
);
return( bool );
}
BOOL
WinTrustGetSubjectName(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject,
IN LPWIN_CERTIFICATE lpSignedData,
IN OUT LPWSTR lpBuffer,
IN OUT LPDWORD lpRequiredLength
)
{
GUID * SubjectForm;
PLOADED_SIP Sip;
BOOL bool;
SubjectForm = lpSubject->SubjectType;
//
// Find a SIP that supports
// the passed subject type.
//
Sip = WinTrustFindSubjectForm(
SubjectForm
);
if (NULL == Sip) {
SetLastError( (DWORD)TRUST_E_SUBJECT_FORM_UNKNOWN );
return( FALSE );
}
bool = (*Sip->SipInfo->lpServices->GetSubjectName)( lpSubject,
lpSignedData,
lpBuffer,
lpRequiredLength
);
return( bool );
}
BOOL
WinTrustGetSubjectCertificate(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject,
IN DWORD dwCertificateIndex,
OUT LPWIN_CERTIFICATE lpCertificate,
IN OUT LPDWORD lpRequiredLength
)
{
GUID * SubjectForm;
PLOADED_SIP Sip;
BOOL bool;
SubjectForm = lpSubject->SubjectType;
//
// Find a SIP that supports
// the passed subject type.
//
Sip = WinTrustFindSubjectForm(
SubjectForm
);
if (NULL == Sip) {
SetLastError( (DWORD)TRUST_E_SUBJECT_FORM_UNKNOWN );
return( FALSE );
}
bool = (*Sip->SipInfo->lpServices->GetSubjectCertificate)( lpSubject,
dwCertificateIndex,
lpCertificate,
lpRequiredLength
);
return( bool );
}
BOOL
WinTrustGetSubjectCertHeader(
IN LPWIN_TRUST_SIP_SUBJECT lpSubject,
IN DWORD dwCertificateIndex,
OUT LPWIN_CERTIFICATE lpCertificateHeader
)
{
GUID * SubjectForm;
PLOADED_SIP Sip;
BOOL bool;
SubjectForm = lpSubject->SubjectType;
//
// Find a SIP that supports
// the passed subject type.
//
Sip = WinTrustFindSubjectForm(
SubjectForm
);
if (NULL == Sip) {
SetLastError( (DWORD)TRUST_E_SUBJECT_FORM_UNKNOWN );
return( FALSE );
}
bool = (*Sip->SipInfo->lpServices->GetSubjectCertHeader)( lpSubject,
dwCertificateIndex,
lpCertificateHeader
);
return( bool );
}
BOOLEAN
WinTrustInit(
IN PVOID hmod,
IN ULONG Reason,
IN PCONTEXT Context
)
{
BOOL b;
if (Reason == DLL_PROCESS_ATTACH) {
//
// Initialize critical section to protect lists.
//
b = LockInitialize( &ListLock );
if (b == FALSE) {
return( FALSE );
}
//
// Initialize the event that gates the list.
//
ListEvent = CreateEvent( NULL, // no security
TRUE, // manual reset
TRUE, // initially signalled
NULL // unnamed
);
if (ListEvent != NULL) {
return( TRUE );
} else {
return( FALSE );
}
}
return( TRUE );
}
BOOL
LockInitialize(
PLIST_LOCK ListLock
)
{
//
// Initialize the variable that indicates the number of
// reader threads that are reading.
// Initially no reader threads are reading.
//
ListLock->NumReaders = 0;
ListLock->hMutexNoWriter = CreateMutex(NULL, FALSE, NULL);
if (ListLock->hMutexNoWriter == NULL) {
return( FALSE );
}
//
// Create the manual-reset event that is signalled when
// no reader threads are reading. Initially no reader
// threads are reading.
//
ListLock->hEventNoReaders = CreateEvent(NULL, TRUE, TRUE, NULL);
if (ListLock->hEventNoReaders != NULL) {
return( TRUE );
} else {
CloseHandle( ListLock->hMutexNoWriter );
return( FALSE );
}
}
VOID LockWaitToWrite(
PLIST_LOCK ListLock
)
{
HANDLE aHandles[2];
DWORD rc;
//
// We can write if the following are true:
//
// 1. The mutex guard is available and no
// other threads are writing.
//
// 2. No threads are reading.
//
// Note that, unlike an rtl resource, this attempt
// to write does not lock out other readers. We
// just have to wait patiently for our turn.
//
aHandles[0] = ListLock->hMutexNoWriter;
aHandles[1] = ListLock->hEventNoReaders;
rc = WaitForMultipleObjects(2, aHandles, TRUE, INFINITE);
#ifdef _DEBUG
ASSERT( OwningThread == 0 );
OwningThread = GetCurrentThreadId();
DbgPrint("Thread %x has Write lock\n",GetCurrentThreadId());
#endif
//
// Exit with the mutex, so as to prevent any more readers or writers
// from coming in.
//
return;
}
VOID
LockDoneWriting(
PLIST_LOCK ListLock
)
{
//
// We're done writing, release the mutex so that
// readers or other writers may come in.
//
#ifdef _DEBUG
volatile DWORD Tid;
Tid = GetCurrentThreadId();
ASSERT( OwningThread == Tid );
OwningThread = 0;
DbgPrint("Thread %x releasing Write lock\n",Tid);
#endif
ReleaseMutex(ListLock->hMutexNoWriter);
return;
}
VOID
LockWaitToRead(
PLIST_LOCK ListLock
)
{
//
// Acquire the mutex that protects the list data.
//
WaitForSingleObject(ListLock->hMutexNoWriter, INFINITE);
#ifdef _DEBUG
DbgPrint("Thread %x has Read lock\n",GetCurrentThreadId());
#endif
//
// Now that we have the mutex, we can modify list data without
// fear of corrupting anyone.
//
//
// Increment the number of reader threads.
//
if (++ListLock->NumReaders == 1) {
//
// If this is the first reader thread, set our event to
// reflect this. This is so that anyone waiting to write
// will block until we're done.
//
ResetEvent(ListLock->hEventNoReaders);
}
//
// Allow other writer/reader threads to use
// the lock object.
//
ReleaseMutex( ListLock->hMutexNoWriter );
}
VOID LockDoneReading(
PLIST_LOCK ListLock
)
{
//
// Acquire the mutex that guards the list data so we can
// decrement the number of readers safely.
//
WaitForSingleObject( ListLock->hMutexNoWriter, INFINITE );
#ifdef _DEBUG
DbgPrint("Thread %x releasing Read lock\n",GetCurrentThreadId());
#endif
if (--ListLock->NumReaders == 0) {
//
// We were the last reader. Wake up any potential
// writers.
//
SetEvent(ListLock->hEventNoReaders);
}
//
// Allow other writer/reader threads to use
// the lock object.
//
ReleaseMutex( ListLock->hMutexNoWriter);
return;
}