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.
625 lines
16 KiB
625 lines
16 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows NT Security
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: filesp.cpp
|
|
//
|
|
// Contents: File Scheme Provider
|
|
//
|
|
// History: 08-Aug-97 kirtd Created
|
|
// 01-Jan-02 philh Changed to internally use UNICODE Urls
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include <global.hxx>
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileRetrieveEncodedObject
|
|
//
|
|
// Synopsis: retrieve encoded object via Win32 File I/O
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI FileRetrieveEncodedObject (
|
|
IN LPCWSTR pwszUrl,
|
|
IN LPCSTR pszObjectOid,
|
|
IN DWORD dwRetrievalFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT PCRYPT_BLOB_ARRAY pObject,
|
|
OUT PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
|
|
OUT LPVOID* ppvFreeContext,
|
|
IN HCRYPTASYNC hAsyncRetrieve,
|
|
IN PCRYPT_CREDENTIALS pCredentials,
|
|
IN PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
IObjectRetriever* por = NULL;
|
|
|
|
if ( !( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL ) )
|
|
{
|
|
por = new CFileSynchronousRetriever;
|
|
}
|
|
|
|
if ( por == NULL )
|
|
{
|
|
SetLastError( (DWORD) E_OUTOFMEMORY );
|
|
return( FALSE );
|
|
}
|
|
|
|
fResult = por->RetrieveObjectByUrl(
|
|
pwszUrl,
|
|
pszObjectOid,
|
|
dwRetrievalFlags,
|
|
dwTimeout,
|
|
(LPVOID *)pObject,
|
|
ppfnFreeObject,
|
|
ppvFreeContext,
|
|
hAsyncRetrieve,
|
|
pCredentials,
|
|
NULL,
|
|
pAuxInfo
|
|
);
|
|
|
|
por->Release();
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileFreeEncodedObject
|
|
//
|
|
// Synopsis: free encoded object retrieved via FileRetrieveEncodedObject
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID WINAPI FileFreeEncodedObject (
|
|
IN LPCSTR pszObjectOid,
|
|
IN PCRYPT_BLOB_ARRAY pObject,
|
|
IN LPVOID pvFreeContext
|
|
)
|
|
{
|
|
BOOL fFreeBlobs = TRUE;
|
|
PFILE_BINDINGS pfb = (PFILE_BINDINGS)pvFreeContext;
|
|
|
|
//
|
|
// If no file bindings were given in the context then this
|
|
// must be a mapped file so we deal with it as such
|
|
//
|
|
|
|
if ( pfb != NULL )
|
|
{
|
|
fFreeBlobs = FALSE;
|
|
FileFreeBindings( pfb );
|
|
}
|
|
|
|
FileFreeCryptBlobArray( pObject, fFreeBlobs );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileCancelAsyncRetrieval
|
|
//
|
|
// Synopsis: cancel asynchronous object retrieval
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WINAPI FileCancelAsyncRetrieval (
|
|
IN HCRYPTASYNC hAsyncRetrieve
|
|
)
|
|
{
|
|
SetLastError( (DWORD) E_NOTIMPL );
|
|
return( FALSE );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileSynchronousRetriever::CFileSynchronousRetriever, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CFileSynchronousRetriever::CFileSynchronousRetriever ()
|
|
{
|
|
m_cRefs = 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileSynchronousRetriever::~CFileSynchronousRetriever, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CFileSynchronousRetriever::~CFileSynchronousRetriever ()
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileSynchronousRetriever::AddRef, public
|
|
//
|
|
// Synopsis: IRefCountedObject::AddRef
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CFileSynchronousRetriever::AddRef ()
|
|
{
|
|
InterlockedIncrement( (LONG *)&m_cRefs );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileSynchronousRetriever::Release, public
|
|
//
|
|
// Synopsis: IRefCountedObject::Release
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CFileSynchronousRetriever::Release ()
|
|
{
|
|
if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 )
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileSynchronousRetriever::RetrieveObjectByUrl, public
|
|
//
|
|
// Synopsis: IObjectRetriever::RetrieveObjectByUrl
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CFileSynchronousRetriever::RetrieveObjectByUrl (
|
|
LPCWSTR pwszUrl,
|
|
LPCSTR pszObjectOid,
|
|
DWORD dwRetrievalFlags,
|
|
DWORD dwTimeout,
|
|
LPVOID* ppvObject,
|
|
PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
|
|
LPVOID* ppvFreeContext,
|
|
HCRYPTASYNC hAsyncRetrieve,
|
|
PCRYPT_CREDENTIALS pCredentials,
|
|
LPVOID pvVerify,
|
|
PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
DWORD LastError = 0;
|
|
PFILE_BINDINGS pfb = NULL;
|
|
LPVOID pvFreeContext = NULL;
|
|
BOOL fIsUncUrl;
|
|
|
|
assert( hAsyncRetrieve == NULL );
|
|
|
|
fIsUncUrl = FileIsUncUrl( pwszUrl );
|
|
|
|
if ( ( dwRetrievalFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) &&
|
|
( fIsUncUrl == TRUE ) )
|
|
{
|
|
return( SchemeRetrieveCachedCryptBlobArray(
|
|
pwszUrl,
|
|
dwRetrievalFlags,
|
|
(PCRYPT_BLOB_ARRAY)ppvObject,
|
|
ppfnFreeObject,
|
|
ppvFreeContext,
|
|
pAuxInfo
|
|
) );
|
|
}
|
|
|
|
fResult = FileGetBindings(
|
|
pwszUrl,
|
|
dwRetrievalFlags,
|
|
pCredentials,
|
|
&pfb,
|
|
pAuxInfo
|
|
);
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
if ( pfb->fMapped == FALSE )
|
|
{
|
|
fResult = FileSendReceiveUrlRequest(
|
|
pfb,
|
|
(PCRYPT_BLOB_ARRAY)ppvObject
|
|
);
|
|
|
|
LastError = GetLastError();
|
|
FileFreeBindings( pfb );
|
|
}
|
|
else
|
|
{
|
|
fResult = FileConvertMappedBindings(
|
|
pfb,
|
|
(PCRYPT_BLOB_ARRAY)ppvObject
|
|
);
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
pvFreeContext = (LPVOID)pfb;
|
|
}
|
|
else
|
|
{
|
|
LastError = GetLastError();
|
|
FileFreeBindings( pfb );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
if ( !( dwRetrievalFlags & CRYPT_DONT_CACHE_RESULT ) &&
|
|
( fIsUncUrl == TRUE ) )
|
|
{
|
|
fResult = SchemeCacheCryptBlobArray(
|
|
pwszUrl,
|
|
dwRetrievalFlags,
|
|
(PCRYPT_BLOB_ARRAY)ppvObject,
|
|
pAuxInfo
|
|
);
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
FileFreeEncodedObject(
|
|
pszObjectOid,
|
|
(PCRYPT_BLOB_ARRAY)ppvObject,
|
|
pvFreeContext
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SchemeRetrieveUncachedAuxInfo( pAuxInfo );
|
|
}
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
|
|
*ppfnFreeObject = FileFreeEncodedObject;
|
|
*ppvFreeContext = pvFreeContext;
|
|
}
|
|
|
|
if ( LastError != 0 )
|
|
{
|
|
SetLastError( LastError );
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInetSynchronousRetriever::CancelAsyncRetrieval, public
|
|
//
|
|
// Synopsis: IObjectRetriever::CancelAsyncRetrieval
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CFileSynchronousRetriever::CancelAsyncRetrieval ()
|
|
{
|
|
SetLastError( (DWORD) E_NOTIMPL );
|
|
return( FALSE );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileGetBindings
|
|
//
|
|
// Synopsis: get the file bindings
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
FileGetBindings (
|
|
LPCWSTR pwszUrl,
|
|
DWORD dwRetrievalFlags,
|
|
PCRYPT_CREDENTIALS pCredentials,
|
|
PFILE_BINDINGS* ppfb,
|
|
PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
|
|
)
|
|
{
|
|
DWORD LastError;
|
|
LPWSTR pwszFile = (LPWSTR)pwszUrl;
|
|
HANDLE hFile;
|
|
HANDLE hFileMap;
|
|
LPVOID pvMap = NULL;
|
|
DWORD dwSize;
|
|
PFILE_BINDINGS pfb;
|
|
|
|
BOOL fResult;
|
|
WIN32_FILE_ATTRIBUTE_DATA FileAttr;
|
|
DWORD dwMaxUrlRetrievalByteCount = 0; // 0 => no max
|
|
|
|
|
|
if (pAuxInfo &&
|
|
offsetof(CRYPT_RETRIEVE_AUX_INFO, dwMaxUrlRetrievalByteCount) <
|
|
pAuxInfo->cbSize)
|
|
dwMaxUrlRetrievalByteCount = pAuxInfo->dwMaxUrlRetrievalByteCount;
|
|
|
|
if ( pCredentials != NULL )
|
|
{
|
|
SetLastError( (DWORD) E_NOTIMPL );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( wcsstr( pwszUrl, FILE_SCHEME_PLUSPLUS ) != NULL )
|
|
{
|
|
pwszFile += wcslen( FILE_SCHEME_PLUSPLUS );
|
|
}
|
|
|
|
fResult = GetFileAttributesExW(
|
|
pwszFile,
|
|
GetFileExInfoStandard,
|
|
&FileAttr
|
|
);
|
|
|
|
if (!fResult)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
dwSize = FileAttr.nFileSizeLow;
|
|
|
|
if ((FileAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
|
(0 != FileAttr.nFileSizeHigh) || (0 == dwSize)
|
|
||
|
|
((0 != dwMaxUrlRetrievalByteCount) &&
|
|
(dwSize > dwMaxUrlRetrievalByteCount)))
|
|
{
|
|
I_CryptNetDebugErrorPrintfA(
|
|
"CRYPTNET.DLL --> Invalid File(%S):: Attributes: 0x%x Size: %d\n",
|
|
pwszFile, FileAttr.dwFileAttributes, FileAttr.nFileSizeLow);
|
|
|
|
SetLastError(ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
pfb = new FILE_BINDINGS;
|
|
if ( pfb == NULL )
|
|
{
|
|
SetLastError( (DWORD) E_OUTOFMEMORY );
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
hFile = CreateFileW(
|
|
pwszFile,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
|
|
if ( hFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
delete pfb;
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( dwSize <= FILE_MAPPING_THRESHOLD )
|
|
{
|
|
pfb->hFile = hFile;
|
|
pfb->dwSize = dwSize;
|
|
pfb->fMapped = FALSE;
|
|
pfb->hFileMap = NULL;
|
|
pfb->pvMap = NULL;
|
|
|
|
*ppfb = pfb;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
hFileMap = CreateFileMappingA(
|
|
hFile,
|
|
NULL,
|
|
PAGE_READONLY,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if ( hFileMap != NULL )
|
|
{
|
|
pvMap = MapViewOfFile( hFileMap, FILE_MAP_READ, 0, 0, 0 );
|
|
}
|
|
|
|
if ( pvMap != NULL )
|
|
{
|
|
pfb->hFile = hFile;
|
|
pfb->dwSize = dwSize;
|
|
pfb->fMapped = TRUE;
|
|
pfb->hFileMap = hFileMap;
|
|
pfb->pvMap = pvMap;
|
|
|
|
*ppfb = pfb;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
LastError = GetLastError();
|
|
|
|
if ( hFileMap != NULL )
|
|
{
|
|
CloseHandle( hFileMap );
|
|
}
|
|
|
|
if ( hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle( hFile );
|
|
}
|
|
|
|
delete pfb;
|
|
|
|
SetLastError( LastError );
|
|
return( FALSE );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileFreeBindings
|
|
//
|
|
// Synopsis: free the file bindings
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
FileFreeBindings (
|
|
PFILE_BINDINGS pfb
|
|
)
|
|
{
|
|
if ( pfb->fMapped == TRUE )
|
|
{
|
|
UnmapViewOfFile( pfb->pvMap );
|
|
CloseHandle( pfb->hFileMap );
|
|
}
|
|
|
|
CloseHandle( pfb->hFile );
|
|
delete pfb;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileSendReceiveUrlRequest
|
|
//
|
|
// Synopsis: synchronously process the request for the file bits using
|
|
// Win32 File API. Note that this only works for non-mapped
|
|
// file bindings, for mapped file bindings use
|
|
// FileConvertMappedBindings
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
FileSendReceiveUrlRequest (
|
|
PFILE_BINDINGS pfb,
|
|
PCRYPT_BLOB_ARRAY pcba
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
LPBYTE pb;
|
|
DWORD dwRead;
|
|
|
|
assert( pfb->fMapped == FALSE );
|
|
|
|
pb = CCryptBlobArray::AllocBlob( pfb->dwSize );
|
|
if ( pb == NULL )
|
|
{
|
|
SetLastError( (DWORD) E_OUTOFMEMORY );
|
|
return( FALSE );
|
|
}
|
|
|
|
fResult = ReadFile( pfb->hFile, pb, pfb->dwSize, &dwRead, NULL );
|
|
if ( fResult == TRUE )
|
|
{
|
|
CCryptBlobArray cba( 1, 1, fResult );
|
|
|
|
if ( dwRead == pfb->dwSize )
|
|
{
|
|
fResult = cba.AddBlob( pfb->dwSize, pb, FALSE );
|
|
}
|
|
else
|
|
{
|
|
SetLastError( (DWORD) E_FAIL );
|
|
fResult = FALSE;
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
cba.GetArrayInNativeForm( pcba );
|
|
}
|
|
else
|
|
{
|
|
cba.FreeArray( FALSE );
|
|
}
|
|
}
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
CCryptBlobArray::FreeBlob( pb );
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileConvertMappedBindings
|
|
//
|
|
// Synopsis: convert mapped bindings to a CRYPT_BLOB_ARRAY
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
FileConvertMappedBindings (
|
|
PFILE_BINDINGS pfb,
|
|
PCRYPT_BLOB_ARRAY pcba
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
|
|
assert( pfb->fMapped == TRUE );
|
|
|
|
CCryptBlobArray cba( 1, 1, fResult );
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
fResult = cba.AddBlob( pfb->dwSize, (LPBYTE)pfb->pvMap, FALSE );
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
cba.GetArrayInNativeForm( pcba );
|
|
}
|
|
else
|
|
{
|
|
cba.FreeArray( FALSE );
|
|
}
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileFreeCryptBlobArray
|
|
//
|
|
// Synopsis: free the CRYPT_BLOB_ARRAY
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
FileFreeCryptBlobArray (
|
|
PCRYPT_BLOB_ARRAY pcba,
|
|
BOOL fFreeBlobs
|
|
)
|
|
{
|
|
CCryptBlobArray cba( pcba, 0 );
|
|
|
|
cba.FreeArray( fFreeBlobs );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileIsUncUrl
|
|
//
|
|
// Synopsis: is this a UNC path URL?
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
FileIsUncUrl (
|
|
LPCWSTR pwszUrl
|
|
)
|
|
{
|
|
DWORD cch = 0;
|
|
|
|
if ( wcsstr( pwszUrl, FILE_SCHEME_PLUSPLUS ) != NULL )
|
|
{
|
|
cch += wcslen( FILE_SCHEME_PLUSPLUS );
|
|
}
|
|
|
|
if ( ( pwszUrl[ cch ] == L'\\' ) && ( pwszUrl[ cch + 1 ] == L'\\' ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|