mirror of https://github.com/tongzx/nt5src
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
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);
|
|
}
|