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.
 
 
 
 
 
 

587 lines
13 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: SIPObjSS.cpp
//
// Contents: Microsoft SIP Provider - Structured Storage
//
// History: 07-Aug-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "sipobjss.hxx"
#include <objidl.h>
#include <objbase.h>
#define SIG_AUTHOR 0
#define SIG_NOTARY 1
#define SIG_MAX 1
typedef struct StreamIds_
{
DWORD dwSigIndex;
WCHAR *pwszName;
} StreamIds;
static StreamIds Ids[] =
{
SIG_AUTHOR, L"\001MSDigSig(Author)",
SIG_NOTARY, L"\001MSDigSig(Notary)",
0xffffffff, NULL
};
////////////////////////////////////////////////////////////////////////////
//
// construct/destruct:
//
SIPObjectSS_::SIPObjectSS_(DWORD id) : SIPObject_(id)
{
GUID gSS = CRYPT_SUBJTYPE_SS_IMAGE;
memset(&SpcSigInfo,0x00,sizeof(SPC_SIGINFO));
SpcSigInfo.dwSipVersion = MSSIP_CURRENT_VERSION;
memcpy(&SpcSigInfo.gSIPGuid, &gSS, sizeof(GUID));
pTopStg = NULL;
this->fUseFileMap = FALSE;
}
SIPObjectSS_::~SIPObjectSS_(void)
{
if (pTopStg)
{
pTopStg->Commit(STGC_DEFAULT);
pTopStg->Release();
}
}
////////////////////////////////////////////////////////////////////////////
//
// public:
//
BOOL SIPObjectSS_::RemoveSignedDataMsg(SIP_SUBJECTINFO *pSI,DWORD dwIdx)
{
if (dwIdx > SIG_MAX)
{
SetLastError((DWORD)TRUST_E_NOSIGNATURE);
return(FALSE);
}
if (this->FileHandleFromSubject(pSI, GENERIC_READ | GENERIC_WRITE))
{
if (pTopStg->DestroyElement(Ids[dwIdx].pwszName) != S_OK)
{
SetLastError((DWORD)TRUST_E_NOSIGNATURE);
return(FALSE);
}
return(TRUE);
}
return(FALSE);
}
////////////////////////////////////////////////////////////////////////////
//
// protected:
//
BOOL SIPObjectSS_::GetMessageFromFile(SIP_SUBJECTINFO *pSI,
WIN_CERTIFICATE *pWinCert,
DWORD dwIndex,DWORD *pcbCert)
{
if (!(pTopStg))
{
return(FALSE);
}
if (dwIndex > SIG_MAX)
{
SetLastError((DWORD)TRUST_E_NOSIGNATURE);
return(FALSE);
}
STATSTG sStatStg;
IStream *pStream;
DWORD cbCert;
pStream = NULL;
if ((pTopStg->OpenStream(Ids[dwIndex].pwszName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
0, &pStream) != S_OK) ||
!(pStream))
{
SetLastError(TRUST_E_NOSIGNATURE);
return(FALSE);
}
if (pStream->Stat(&sStatStg, STATFLAG_NONAME) != S_OK)
{
pStream->Release();
SetLastError(ERROR_BAD_FORMAT);
return(FALSE);
}
cbCert = sStatStg.cbSize.LowPart;
if (cbCert == 0)
{
pStream->Release();
SetLastError(TRUST_E_NOSIGNATURE);
return(FALSE);
}
cbCert += WVT_OFFSETOF(WIN_CERTIFICATE, bCertificate);
if (*pcbCert < cbCert)
{
pStream->Release();
*pcbCert = cbCert;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return(FALSE);
}
if (pWinCert)
{
DWORD cbRead;
pWinCert->dwLength = cbCert;
pWinCert->wRevision = WIN_CERT_REVISION_2_0;
pWinCert->wCertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
cbRead = 0;
cbCert -= WVT_OFFSETOF(WIN_CERTIFICATE, bCertificate);
if ((pStream->Read(pWinCert->bCertificate, cbCert, &cbRead) != S_OK) ||
(cbRead != cbCert))
{
SetLastError(ERROR_BAD_FORMAT);
pStream->Release();
return(FALSE);
}
}
pStream->Release();
return(TRUE);
}
BOOL SIPObjectSS_::PutMessageInFile(SIP_SUBJECTINFO *pSI,
WIN_CERTIFICATE *pWinCert,DWORD *pdwIndex)
{
if ((pWinCert->dwLength <= OFFSETOF(WIN_CERTIFICATE,bCertificate)) ||
(pWinCert->wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (*pdwIndex > SIG_MAX)
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
IStream *pStream;
pStream = NULL;
if ((pTopStg->CreateStream(Ids[*pdwIndex].pwszName,
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
0, 0, &pStream) != S_OK) ||
!(pStream))
{
SetLastError(ERROR_BAD_FORMAT);
return(FALSE);
}
if (pStream->Write(pWinCert->bCertificate,
pWinCert->dwLength - WVT_OFFSETOF(WIN_CERTIFICATE, bCertificate),
NULL) != S_OK)
{
pStream->Release();
SetLastError(ERROR_BAD_FORMAT);
return(FALSE);
}
pStream->Release();
return(TRUE);
}
BOOL SIPObjectSS_::GetDigestStream(DIGEST_DATA *pDigestData,
DIGEST_FUNCTION pfnCallBack, DWORD dwFlags)
{
return(this->IStorageDigest(pTopStg, pDigestData, pfnCallBack));
}
BOOL SIPObjectSS_::IStorageDigest(IStorage *pStg, DIGEST_DATA *pDigestData, DIGEST_FUNCTION pfnCallBack)
{
STATSTG *pSortStg;
STATSTG sStatStg;
DWORD cSortStg;
BOOL fRet;
cSortStg = 0;
pSortStg = NULL;
if (!(this->SortElements(pStg, &cSortStg, &pSortStg)))
{
return(FALSE);
}
if (cSortStg == 0)
{
return(TRUE);
}
if (!(pSortStg))
{
return(FALSE);
}
for (int i = 0; i < (int)cSortStg; i++)
{
switch (pSortStg[i].type)
{
case STGTY_STORAGE:
IStorage *pInnerStg;
pInnerStg = NULL;
if ((pStg->OpenStorage(pSortStg[i].pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
0, 0, &pInnerStg) != S_OK) ||
!(pInnerStg))
{
this->FreeElements(&cSortStg, &pSortStg);
SetLastError(ERROR_BAD_FORMAT);
return(FALSE);
}
//
// WARNING: recursive!
//
fRet = this->IStorageDigest(pInnerStg, pDigestData, pfnCallBack);
pInnerStg->Release();
if (!(fRet))
{
this->FreeElements(&cSortStg, &pSortStg);
return(FALSE);
}
break;
case STGTY_STREAM:
IStream *pInnerStm;
StreamIds *pIds;
BOOL fSigEntry;
BYTE rgb[512];
ULONG cbRead;
fSigEntry = FALSE;
pIds = &Ids[0];
while (pIds->dwSigIndex != 0xffffffff)
{
if (_wcsicmp(pSortStg[i].pwcsName, pIds->pwszName) == 0)
{
fSigEntry = TRUE;
break;
}
pIds++;
}
if (fSigEntry)
{
break;
}
pInnerStm = NULL;
if ((pStg->OpenStream(pSortStg[i].pwcsName,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&pInnerStm) != S_OK) ||
!(pInnerStm))
{
this->FreeElements(&cSortStg, &pSortStg);
SetLastError(ERROR_BAD_FORMAT);
return(FALSE);
}
for EVER
{
cbRead = 0;
if (pInnerStm->Read(rgb, 512, &cbRead) != S_OK)
{
break;
}
if (cbRead == 0)
{
break;
}
if (!(pfnCallBack(pDigestData, rgb, cbRead)))
{
this->FreeElements(&cSortStg, &pSortStg);
pInnerStm->Release();
return(FALSE);
}
}
pInnerStm->Release();
break;
case STGTY_LOCKBYTES:
break;
case STGTY_PROPERTY:
break;
default:
break;
}
}
memset(&sStatStg, 0x00, sizeof(STATSTG));
if (pStg->Stat(&sStatStg, STATFLAG_NONAME) != S_OK)
{
this->FreeElements(&cSortStg, &pSortStg);
SetLastError(ERROR_BAD_FORMAT);
return(FALSE);
}
// the ctime member is changed if the file is copied....
// !(pfnCallBack(pDigestData, (BYTE *)&sStatStg.ctime, sizeof(FILETIME))) ||
//
if (!(pfnCallBack(pDigestData, (BYTE *)&sStatStg.type, sizeof(DWORD))) ||
!(pfnCallBack(pDigestData, (BYTE *)&sStatStg.cbSize, sizeof(ULARGE_INTEGER))) ||
!(pfnCallBack(pDigestData, (BYTE *)&sStatStg.clsid, sizeof(CLSID))) ||
!(pfnCallBack(pDigestData, (BYTE *)&sStatStg.grfStateBits, sizeof(DWORD))))
{
this->FreeElements(&cSortStg, &pSortStg);
return(FALSE);
}
this->FreeElements(&cSortStg, &pSortStg);
return(TRUE);
}
BOOL SIPObjectSS_::FileHandleFromSubject(SIP_SUBJECTINFO *pSubject, DWORD dwAccess, DWORD dwShared)
{
/* if ((dwAccess & GENERIC_WRITE) &&
(pSubject->hFile != NULL) &&
(pSubject->hFile != INVALID_HANDLE_VALUE))
{
CloseHandle(pSubject->hFile);
pSubject->hFile = NULL;
} */
HRESULT hr;
pTopStg = NULL;
/* if ((hr = StgOpenStorage((const WCHAR *)pSubject->pwsFileName,
NULL,
(dwAccess & GENERIC_WRITE) ?
(STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT) :
(STGM_READ | STGM_SHARE_DENY_NONE | STGM_TRANSACTED),
NULL,
0,
&pTopStg)) != S_OK)
{
pTopStg = NULL;
return(FALSE);
} */
if ((hr = StgOpenStorage((const WCHAR *)pSubject->pwsFileName,
NULL,
(dwAccess & GENERIC_WRITE) ?
(STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT) :
(STGM_READ | STGM_SHARE_DENY_WRITE | STGM_DIRECT),
NULL,
0,
&pTopStg)) != S_OK)
{
pTopStg = NULL;
return(FALSE);
}
return(TRUE);
}
////////////////////////////////////////////////////////////////////////////
//
// private:
//
BOOL WINAPI IsStructuredStorageFile(WCHAR *pwszFileName, GUID *pgSubject)
{
GUID gSS = CRYPT_SUBJTYPE_SS_IMAGE;
if (!(pwszFileName) ||
!(pgSubject))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (StgIsStorageFile(pwszFileName) == S_OK)
{
memcpy(pgSubject, &gSS, sizeof(GUID));
return(TRUE);
}
return(FALSE);
}
static int __cdecl CompareSTATSTG(const void *p1, const void *p2)
{
return(wcscmp(((STATSTG *)p1)->pwcsName, ((STATSTG *)p2)->pwcsName));
}
void SIPObjectSS_::FreeElements(DWORD *pcStg, STATSTG **ppStg)
{
if (*ppStg)
{
STATSTG *pStg;
pStg = *ppStg;
for (int i = 0; i < (int)*pcStg; i++)
{
if (pStg[i].pwcsName)
{
CoTaskMemFree(pStg[i].pwcsName);
}
}
DELETE_OBJECT(*ppStg);
}
*pcStg = 0;
}
BOOL SIPObjectSS_::SortElements(IStorage *pStg, DWORD *pcSortStg, STATSTG **ppSortStg)
{
DWORD cb;
IEnumSTATSTG *pEnum;
pEnum = NULL;
*pcSortStg = 0;
*ppSortStg = NULL;
if (pStg->EnumElements(0, NULL, 0, &pEnum) != S_OK)
{
return(FALSE);
}
DWORD celtFetched;
STATSTG rgCntStatStg[10];
for EVER
{
celtFetched = 0;
pEnum->Next(10, rgCntStatStg, &celtFetched);
if (celtFetched == 0)
{
break;
}
*pcSortStg += celtFetched;
while (celtFetched--)
{
CoTaskMemFree(rgCntStatStg[celtFetched].pwcsName);
}
}
if (*pcSortStg > 0)
{
cb = sizeof(STATSTG) * *pcSortStg;
if (!(*ppSortStg = (STATSTG *)this->SIPNew(cb)))
{
pEnum->Release();
return(FALSE);
}
memset(*ppSortStg, 0x00, cb);
pEnum->Reset();
celtFetched = 0;
if ((pEnum->Next(*pcSortStg, *ppSortStg, &celtFetched) != S_OK) ||
(celtFetched != *pcSortStg))
{
this->FreeElements(pcSortStg, ppSortStg);
pEnum->Release();
SetLastError(ERROR_BAD_FORMAT);
return(FALSE);
}
qsort(*ppSortStg, *pcSortStg, sizeof(STATSTG), CompareSTATSTG);
}
pEnum->Release();
return(TRUE);
}