//+------------------------------------------------------------------------- // // 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 #include #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); }