349 lines
13 KiB
C++
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
|