Windows2003-3790/inetcore/outlookexpress/inetcomm/mimeole/smime.h
2020-09-30 16:53:55 +02:00

349 lines
13 KiB
C++

/*
** s m i m e . h
**
** Purpose: class for cryptographically enhanced mail.
**
** Owner: t-erikne
** Created: 8/27/96
**
** Copyright (C) Microsoft Corp. 1996-1998
*/
#ifndef __SMIME_H
#define __SMIME_H
#include <mimeole.h>
#ifndef __WINCRYPT_H__
#include "wincrypt.h"
#endif
#ifdef SMIME_V3
// #include "..\ess\essout.h"
#endif // SMIME_V3
#define szOID_INFOSEC_keyExchangeAlgorithm "2.16.840.1.101.2.1.1.22"
#include "capitype.h"
#include "cryptdbg.h"
// WinCrypt.h helper
#define DOUTL_SMIME CRYPT_LEVEL
class CCAPIStm;
extern CRYPT_ENCODE_PARA CryptEncodeAlloc;
extern CRYPT_DECODE_PARA CryptDecodeAlloc;
#ifdef MAC
/*
** An array of function pointers, needed because we dynalink to
** CRYPT32.DLL. Note that not all of the crypto functions come
** from this DLL. I also use functions from ADVAPI32: the CAPI 1
** functions. These are not represented in this table and do not
** need to use GetProcAddress.
** Typedefs come from capitype.h, local to our project.
*/
typedef struct tagCAPIfuncs {
CERTENUMCERTIFICATESINSTORE *EnumCerts;
CERTNAMETOSTRA *CertNameToStr;
} CAPIfuncs, *PCAPIfuncs;
#endif // MAC
/////////////////////////////////////////////////////////////////////////////
//
// Structure definitions
//
typedef enum {
ENCRYPT_ITEM_TRANSPORT = 1,
ENCRYPT_ITEM_AGREEMENT = 2,
ENCRYPT_ITEM_MAILLIST = 3
} ENCRYPT_ITEM_TYPE;
typedef struct tagEncryptItem {
DWORD dwTagType;
union {
struct {
BLOB blobAlg;
DWORD cCert;
PCCERT_CONTEXT * rgpccert;
} Transport;
struct {
BLOB blobAlg;
DWORD cCert;
PCCERT_CONTEXT * rgpccert;
PCCERT_CONTEXT pccertSender;
} Agreement;
struct {
BLOB blobAlg; // AlgId + AuxInfo
BLOB blobKeyId; // Data_Blob KeyID
FILETIME date; // Date
BLOB blobOctet; // Other attribute (oid, any)
#ifdef SMIME_V3
HCRYPTPROV hprov; // hprov
HCRYPTKEY hkey; // hkey
#else // !SMIME_V3
BLOB blobKeyMaterial;
#endif // SMIME_V3
} MailList;
};
} EncryptItem;
typedef struct tagEncryptItems {
DWORD cItems;
EncryptItem * rgItems;
} EncryptItems;
//
// Notes about the [directions]
// [sgn] - signing -- in for sign ops
// [ver] - verification -- out for sign ops
// [enc] - encryption -- in for encrypt ops
// [dec] - decryption -- out for encrypt ops
// [in] = [sgn,enc]
// [out] = [ver,dec]
//
typedef struct {
DWORD ulValidity; // Validity bits for each signature
PCCERT_CONTEXT pccert; // Signer certificate
BLOB blobHashAlg; // Hash algorithm for signer
BLOB blobAuth; // authenticated attributes
BLOB blobUnauth; // unauthenticated attributes
#ifdef SMIME_V3
BLOB blobReceipt; // Receipt to be returned
BLOB blobHash; // Hash of message
#endif // SMIME_V3
} SignerData;
class CSECURITY_LAYER_DATA : public IUnknown
{
friend class CSMime; // Allow CSMime access to our private data
friend class CCAPIStm; // Allow CCAPIStm access to our private data
public:
CSECURITY_LAYER_DATA(void);
~CSECURITY_LAYER_DATA(void);
// --------------------------------------------------------------------
// IUnknown
// --------------------------------------------------------------------
STDMETHODIMP QueryInterface(REFIID, LPVOID *);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
//private: // private data
DWORD m_cRef;
DWORD m_dwMsgEnhancement; // sign? encrypt?
BOOL m_fCertInLayer; // TRUE if there is a cert included in this layer
// The following elements exist one for each signer on the current layer
DWORD m_cSigners; // Count of signers
SignerData * m_rgSigners; // Signer Data
// The following items exist to encrypt the current layer
DWORD m_cEncryptItems; // Encrypt Item count
#ifdef SMIME_V3
CRYPT_ALGORITHM_IDENTIFIER m_ContentEncryptAlgorithm; // Content AlgId
void * m_pvEncryptAuxInfo; // Aux info
CMSG_RECIPIENT_ENCODE_INFO * m_rgRecipientInfo; // Array of Recpient Infos
CRYPT_DATA_BLOB m_blobUnprotectAttrs; // Unprotected attributes
HCERTSTORE m_hstoreEncrypt; // Encrypt cert store
#else // !SMIME_V3
EncryptItem * m_rgEncryptItems; // count of Encrypt Items
#endif // SMIME_V3
// The following items exists for a decrypted message
DWORD m_ulDecValidity;
BLOB m_blobDecAlg; // Decryption Algorithm
PCCERT_CONTEXT m_pccertDecrypt; // Decryption Certificate
// These are items common to both encryption and signing
HCERTSTORE m_hcertstor; // message cert store
// Cert Bag for signing
// Originator Info for encryption
//
CSECURITY_LAYER_DATA * m_psldInner; // down link
CSECURITY_LAYER_DATA * m_psldOuter; // up link
};
typedef class CSECURITY_LAYER_DATA SECURITY_LAYER_DATA;
typedef SECURITY_LAYER_DATA * PSECURITY_LAYER_DATA;
// -------------------------------------------------------------------
// SMIMEINFO:
// bidirectional communication struct for passing parameter
// info to/from the en/decode functions
//
// dwMsgEnhancement [inout]
// fCertWithMsg [ver]
// ulMsgValidity [out]
// ietRequested [in]
// -------------------------------------------------------------------
struct SMIMEINFOtag { // si
DWORD dwMsgEnhancement;
PSECURITY_LAYER_DATA psldLayers; // outermost layer
PSECURITY_LAYER_DATA psldEncrypt; // encryption layer
PSECURITY_LAYER_DATA psldInner; // innermost layer
ULONG cStores; // size of rgStores
HCERTSTORE * rgStores; // array of cert stores
BOOL fCertWithMsg;
ULONG ulMsgValidity;
ENCODINGTYPE ietRequested;
HCRYPTPROV hProv;
#ifdef SMIME_V3
LPSTR pszInnerContent; // Inner content (NULL ->> id-data)
DWORD cbInnerContent; // Inner content size if != id-data
LPWSTR pwszKeyPrompt; // Key password prompt
#endif // SMIME_V3
};
typedef struct SMIMEINFOtag SMIMEINFO;
typedef SMIMEINFO *PSMIMEINFO;
typedef const SMIMEINFO *PCSMIMEINFO;
/////////////////////////////////////////////////////////////////////////////
//
// Class begins
//
class CSMime :
public IMimeSecurity
{
public:
//
// ctor and dtor
//
CSMime(void);
~CSMime();
//
// IUnknown methods
//
STDMETHODIMP QueryInterface(REFIID, LPVOID *);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
//
// IMimeSecurity methods
//
STDMETHODIMP InitNew();
STDMETHODIMP CheckInit();
STDMETHODIMP EncodeMessage(IMimeMessageTree *const pTree, DWORD dwFlags);
STDMETHODIMP DecodeMessage(IMimeMessageTree *const pTree, DWORD dwFlags);
STDMETHODIMP EncodeBody(IMimeMessageTree *const pTree, HBODY hEncodeRoot, DWORD dwFlags);
STDMETHODIMP DecodeBody(IMimeMessageTree *const pTree, HBODY hDecodeRoot, DWORD dwFlags);
STDMETHODIMP EnumCertificates(HCAPICERTSTORE hc, DWORD dwUsage, PCX509CERT pPrev, PCX509CERT *pCert);
STDMETHODIMP GetCertificateName(const PCX509CERT pX509Cert, const CERTNAMETYPE cn, LPSTR *ppszName);
STDMETHODIMP GetMessageType(const HWND hwndParent, IMimeBody *const pBody, DWORD *const pdwSecType);
STDMETHODIMP GetCertData(const PCX509CERT pX509Cert, const CERTDATAID dataid, LPPROPVARIANT pValue);
// Other methods
HRESULT EncodeMessage2(IMimeMessageTree * const pTree, DWORD dwFlags,
HWND hwnd);
HRESULT DecodeMessage2(IMimeMessageTree * const pTree, DWORD dwFlags,
HWND hwnd, IMimeSecurityCallback * pCallback);
HRESULT EncodeBody2(IMimeMessageTree *const pTree, HBODY hEncodeRoot,
DWORD dwFlags, HWND hwnd);
HRESULT DecodeBody2(IMimeMessageTree *const pTree, HBODY hDecodeRoot,
DWORD dwFlags, SMIMEINFO * psiOuterOp, HWND hwnd,
IMimeSecurityCallback * pCallback);
//
// Implementation methods
//
static void UnloadAll(void);
static HRESULT HrGetCertsFromThumbprints(THUMBBLOB *const rgThumbprint, X509CERTRESULT *const pResults);
static HRESULT StaticGetMessageType(HWND hwndParent, IMimeBody *const pBody, DWORD *const pdwSecType);
protected:
static HRESULT StaticCheckInit();
struct CERTARRAY {
DWORD cCerts;
PCCERT_CONTEXT *rgpCerts;
};
typedef CERTARRAY *PCERTARRAY;
typedef const CERTARRAY *PCCERTARRAY;
HRESULT DecodeBody (IMimeMessageTree *const pTree, HBODY hDecodeRoot, DWORD dwFlags, SMIMEINFO * psiOuterOp);
HRESULT HrEncodeOpaque (SMIMEINFO *const psi, IMimeMessageTree *pTree, HBODY hEncodeRoot, IMimeBody *pEncodeRoot, LPSTREAM lpstmOut, HWND hwnd);
HRESULT HrDecodeOpaque (DWORD dwFlags, SMIMEINFO *const psi, IMimeBody *const pBody, IStream *const pstmOut, HWND hwnd, IMimeSecurityCallback * pCallback);
HRESULT HrEncodeClearSigned (SMIMEINFO *const psi, IMimeMessageTree *const pTree, const HBODY hEncodeRoot, IMimeBody *const pEncodeRoot, LPSTREAM lpstmOut, BOOL fCommit, HWND hwnd);
HRESULT HrDecodeClearSigned (DWORD dwFlags, SMIMEINFO *const psi, IMimeMessageTree *const pTree, const HBODY hData, const HBODY hSig, HWND hwnd, IMimeSecurityCallback * pCallback);
static BOOL FSign(const DWORD dwAction)
{ return BOOL(dwAction & MST_SIGN_MASK); }
static BOOL FClearSign(const DWORD dwAction)
{ return (FSign(dwAction) && !(dwAction & MST_BLOB_FLAG)); }
static BOOL FEncrypt(const DWORD dwAction)
{ return BOOL(dwAction & MST_ENCRYPT_MASK); }
static HRESULT HrGetNeededAddresses(const DWORD dwTypes, IMimeMessageTree *pTree, IMimeAddressTable **ppAdrTable, IMimeEnumAddressTypes **ppEnum);
static HRESULT HrGetCertificates(IMimeAddressTable *const pAdrTable, IMimeEnumAddressTypes *pEnum, const DWORD dwType, const BOOL fAlreadyHaveSendersCert, CERTARRAY *rgCerts);
static HRESULT HrGetThumbprints(IMimeEnumAddressTypes *pEnum, const ITHUMBPRINTTYPE ittType, THUMBBLOB *const rgThumbprint);
static HRESULT HrGenerateCertsStatus(X509CERTRESULT *pResults, IMimeAddressTable *const pAdrTable, IMimeEnumAddressTypes *const pEnum, const BOOL fIgnoreSenderError);
HRESULT HrFindUsableCert(HCERTSTORE hCertStore, BYTE dwKeySpec, PCCERT_CONTEXT pPrevCert, PCCERT_CONTEXT *ppCert);
static HRESULT OptionsToSMIMEINFO(BOOL fEncode, IMimeMessageTree *const pmm, IMimeBody *pBody, SMIMEINFO *psi);
static HRESULT SMIMEINFOToOptions(IMimeMessageTree *const pTree, const SMIMEINFO *psi, HBODY hBody);
static HRESULT MergeSMIMEINFO( SMIMEINFO * psiOut, SMIMEINFO * psiInner);
static void FreeSMIMEINFO(SMIMEINFO *psi);
#ifdef DEBUG
void DumpAlgorithms();
#endif
private:
static HRESULT HrInitCAPI();
static void UnloadCAPI();
static HRESULT CAPISTMtoSMIMEINFO(CCAPIStm *pcapistm, SMIMEINFO *psi);
static void MergeSMIMEINFOs(const SMIMEINFO *const psiOuter, SMIMEINFO *const psiInner);
UINT m_cRef;
CRITICAL_SECTION m_cs;
#ifdef MAC
static CAPIfuncs ms_CAPI;
static LPCSTR ms_rgszFuncNames[];
#endif // MAC
};
inline BOOL IsOpaqueSecureContentType(IMimePropertySet *pSet)
{
return (
S_OK == pSet->IsContentType(STR_CNT_APPLICATION, STR_SUB_XPKCS7MIME) ||
S_OK == pSet->IsContentType(STR_CNT_APPLICATION, STR_SUB_PKCS7MIME));
}
inline BOOL IsSecureContentType(IMimePropertySet *pSet)
{
return (
S_OK == pSet->IsContentType(STR_CNT_MULTIPART, STR_SUB_SIGNED) ||
IsOpaqueSecureContentType(pSet));
}
BOOL IsSMimeProtocol(LPMIMEPROPERTYSET lpPropSet);
#ifdef SMIME_V3
void FreeRecipientInfoContent(PCMS_RECIPIENT_INFO pRecipInfo);
HRESULT HrCopyOID(LPCSTR psz, LPSTR * ppsz);
HRESULT HrCopyCryptDataBlob(const CRYPT_DATA_BLOB * pblobSrc, PCRYPT_DATA_BLOB pblobDst);
HRESULT HrCopyCryptBitBlob(const CRYPT_BIT_BLOB * pblobSrc, PCRYPT_BIT_BLOB pblobDst);
HRESULT HrCopyCryptAlgorithm(const CRYPT_ALGORITHM_IDENTIFIER * pAlgSrc,
PCRYPT_ALGORITHM_IDENTIFIER pAlgDst);
HRESULT HrCopyCertId(const CERT_ID * pcertidSrc, PCERT_ID pcertidDst);
#endif // SMIME_V3
#endif // _SMIME_H