Leaked source code of windows server 2003
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.

499 lines
17 KiB

  1. #define INITGUID
  2. #define DEFINE_STRCONST
  3. #include <windows.h>
  4. #include <ole2.h>
  5. #include <initguid.h>
  6. #include <mimeole.h>
  7. #include "encode.h"
  8. #define CORg(command) \
  9. if (FAILED(command)) { \
  10. goto Error; \
  11. }
  12. #define CPRg(command) \
  13. if (! (command)) { \
  14. goto Error; \
  15. }
  16. static LPWSTR s_rgwszValues[] = { NULL };
  17. #define DEBUGFILE 1
  18. #define MAX_LAYERS 3
  19. //------------------------------------------------------------------
  20. //------------------------------------------------------------------
  21. HRESULT WriteBSTRToMultibyteToStream( const BSTR bstrStr, IStream** ppStream )
  22. {
  23. HRESULT hr = S_OK;
  24. LARGE_INTEGER liZero = {0}; // for ->Seek()
  25. char* pszMessage = NULL;
  26. int len = 0;
  27. if (!ppStream) return E_INVALIDARG;
  28. len = wcslen(bstrStr);
  29. CPRg(pszMessage = new char[len + 1]);
  30. WideCharToMultiByte(CP_ACP, 0, bstrStr, len,
  31. pszMessage, len + 1,
  32. NULL, NULL );
  33. pszMessage[len] = '\0';
  34. CORg(CreateStreamOnHGlobal(NULL, TRUE, ppStream));
  35. CORg((*ppStream)->Seek(liZero, STREAM_SEEK_SET, NULL));
  36. CORg((*ppStream)->Write(pszMessage, len, NULL));
  37. CORg((*ppStream)->Seek(liZero, STREAM_SEEK_SET, NULL));
  38. Error:
  39. if (pszMessage) delete[] pszMessage;
  40. return hr;
  41. }
  42. //------------------------------------------------------------------
  43. SMimeEncode::SMimeEncode() :
  44. m_dwFlags(0),
  45. m_stmOutput(NULL),
  46. m_szSignAlg(NULL),
  47. m_szEncryptAlg(NULL),
  48. m_szBody(NULL),
  49. m_SigningCertInner(NULL),
  50. m_SigningCertOuter(NULL),
  51. m_EncryptionCert(NULL),
  52. m_hCryptProv(NULL),
  53. m_hMYCertStore(NULL),
  54. m_hCACertStore(NULL),
  55. m_hABCertStore(NULL),
  56. m_szSenderEmail(NULL),
  57. m_szSenderName(NULL),
  58. m_szRecipientEmail(NULL),
  59. m_szRecipientName(NULL),
  60. m_szOutputFile(NULL)
  61. {
  62. }
  63. #define APPEND_SEPERATOR(subject) \
  64. if (lstrlen(subject)) { \
  65. lstrcat(subject, " | "); \
  66. }
  67. //------------------------------------------------------------------
  68. SMimeEncode::~SMimeEncode()
  69. {
  70. // BUGBUG: Should clean up any allocated members
  71. }
  72. //------------------------------------------------------------------
  73. HRESULT SMimeEncode::HrConfig(
  74. DWORD dwFlags,
  75. LPTSTR lpszBody,
  76. HCRYPTPROV hCryptProv,
  77. HCERTSTORE hMYCertStore,
  78. HCERTSTORE hCACertStore,
  79. HCERTSTORE hABCertStore,
  80. PCCERT_CONTEXT lpSigningCertInner,
  81. PCCERT_CONTEXT lpSigningCertOuter,
  82. PCCERT_CONTEXT lpEncryptionCert,
  83. LPTSTR lpszSenderEmail,
  84. LPTSTR lpszSenderName,
  85. LPTSTR lpszRecipientEmail,
  86. LPTSTR lpszRecipientName,
  87. LPTSTR lpszOutputFile
  88. )
  89. {
  90. HRESULT hr = S_OK;
  91. static char szSubject[257] = "";
  92. if (dwFlags & encode_Encrypt) {
  93. // specify an encryption algorithm
  94. // BUGBUG: Hardcoded in Encode
  95. }
  96. if (dwFlags & encode_InnerSign) {
  97. // specify a signing algorithm
  98. // BUGBUG: Hardcoded in Encode
  99. }
  100. if (dwFlags & encode_OuterSign) {
  101. // specify a signing algorithm
  102. // BUGBUG: Hardcoded in Encode
  103. }
  104. m_dwFlags = dwFlags;
  105. m_szBody = lpszBody;
  106. m_hCryptProv = hCryptProv;
  107. m_hMYCertStore = hMYCertStore;
  108. m_hCACertStore = hCACertStore;
  109. m_hABCertStore = hABCertStore;
  110. m_SigningCertInner = (PCERT_CONTEXT)lpSigningCertInner;
  111. m_SigningCertOuter = (PCERT_CONTEXT)lpSigningCertOuter;
  112. m_EncryptionCert = (PCERT_CONTEXT)lpEncryptionCert;
  113. m_szSenderEmail = lpszSenderEmail;
  114. m_szRecipientEmail = lpszRecipientEmail;
  115. m_szOutputFile = lpszOutputFile;
  116. // Set a meaningful subject
  117. lstrcpy(szSubject, "");
  118. if (dwFlags & encode_InnerSign) {
  119. APPEND_SEPERATOR(szSubject);
  120. if (dwFlags & encode_InnerClear) {
  121. lstrcat(szSubject, "Clear Sign");
  122. } else {
  123. lstrcat(szSubject, "Opaque Sign");
  124. }
  125. }
  126. if (dwFlags & encode_Encrypt) {
  127. APPEND_SEPERATOR(szSubject);
  128. lstrcat(szSubject, "Encrypt");
  129. }
  130. if (dwFlags & encode_OuterSign) {
  131. APPEND_SEPERATOR(szSubject);
  132. if (dwFlags & encode_OuterClear) {
  133. lstrcat(szSubject, "Clear Sign");
  134. } else {
  135. lstrcat(szSubject, "Opaque Sign");
  136. }
  137. }
  138. m_szSubject = szSubject;
  139. return(hr);
  140. }
  141. //------------------------------------------------------------------
  142. HRESULT SMimeEncode::HrExecute(void) {
  143. // Using the SMIME engine:
  144. //
  145. // Build the message tree (attach the body)
  146. // CoCreateInstance( CLSID_IMimeSecurity )
  147. // InitNew()
  148. // pSMIMEEngine->EncodeBody( IMimeMessageTree*,
  149. // hRoot,
  150. // SEF_??? | EBF_RECURSE ) OR ???
  151. // HrEncodeOpaque( psi, pTree, hbody, pencoderoot, pstmOut ) ????
  152. //
  153. HRESULT hr = S_OK;
  154. LARGE_INTEGER liZero = {0}; // for ->Seek()
  155. IStream* pBuildStream = NULL; // scratch stream
  156. IStream* pResultStream = NULL; // scratch stream
  157. IMimeMessage* pMimeRoot = NULL; // message in process
  158. IMimeBody* pMimeRootBody = NULL; // another version
  159. IMimeInternational* pCharSet = NULL;
  160. HCHARSET HCharset = 0;
  161. SYSTEMTIME stNow;
  162. PROPVARIANT var;
  163. HBODY hbBody;
  164. IMimeSecurity* pMimeSecurity = NULL;
  165. ULONG dwSecurityType = MST_NONE;
  166. IPersistFile* pIPFFileStore = NULL;
  167. HRESULT hrLocal = S_OK;
  168. WCHAR szwFileName[MAX_PATH + 1];
  169. CHAR szFrom[2 * (MAX_PATH + 1) + 1];
  170. // Multilayer stuff
  171. BOOL fTripleWrap = m_dwFlags & encode_OuterSign;
  172. ULONG ulSecurityLayers = 0;
  173. ULONG iEncryptLayer = (ULONG)-1;
  174. ULONG iInnerSignLayer = (ULONG)-1;
  175. ULONG iOuterSignLayer = (ULONG)-1;
  176. // Arrays of option values to set
  177. DWORD rgdwSecurityType[MAX_LAYERS] = {0};
  178. PCCERT_CONTEXT rgdwCertSigning[MAX_LAYERS] = {0};
  179. HCERTSTORE rgdwhCertStore[MAX_LAYERS] = {0}; // optional
  180. DWORD rgdwUserValidity[MAX_LAYERS] = {0}; // decode only
  181. DWORD rgdwROMsgValidity[MAX_LAYERS] = {0}; // decode only
  182. FILETIME rgftSigntime[MAX_LAYERS] = {0}; // optional
  183. PROPVARIANT rgpvAlgHash[MAX_LAYERS] = {0};
  184. PROPVARIANT rgpvSymcaps[MAX_LAYERS] = {0};
  185. PROPVARIANT rgpvAuthattr[MAX_LAYERS] = {0}; // optional
  186. PROPVARIANT rgpvUnauthattr[MAX_LAYERS] = {0}; // optional
  187. // This is the ALOGORITHM ID for SHA1, default supported signing alg
  188. const BYTE c_SHA1_ALGORITHM_ID[] =
  189. {0x30, 0x09, 0x30, 0x07, 0x06, 0x05, 0x2B, 0x0E,
  190. 0x03, 0x02, 0x1A};
  191. // This is the ALOGORITHM ID for RC2 -- 40 bit, the default encrypt
  192. const BYTE c_RC2_40_ALGORITHM_ID[] =
  193. {0x30, 0x0F, 0x30, 0x0D, 0x06, 0x08, 0x2A, 0x86,
  194. 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x02, 0x02, 0x01,
  195. 0x28};
  196. // get the signing cert from my store
  197. if (! m_hCryptProv || ! m_hMYCertStore || ! m_hCACertStore || ! m_hABCertStore) {
  198. hr = E_FAIL;
  199. goto Error;
  200. }
  201. // Create the Message object
  202. //
  203. CORg(CoCreateInstance(CLSID_IMimeMessage, NULL, CLSCTX_INPROC_SERVER,
  204. IID_IMimeMessage, (LPVOID*)&pMimeRoot));
  205. CORg(pMimeRoot->InitNew());
  206. CORg(CreateStreamOnHGlobal( NULL, TRUE, &pBuildStream));
  207. CORg(pBuildStream->Seek(liZero, STREAM_SEEK_SET, NULL));
  208. CORg(pBuildStream->Write(m_szBody, lstrlen(m_szBody), NULL));
  209. CORg(pBuildStream->Seek(liZero, STREAM_SEEK_SET, NULL));
  210. CORg(pMimeRoot->SetTextBody(TXT_PLAIN, IET_8BIT, NULL, pBuildStream, &hbBody));
  211. // Create the formatted From address
  212. if (m_szSenderName) {
  213. lstrcpy(szFrom, "\"");
  214. lstrcat(szFrom, m_szSenderName);
  215. lstrcat(szFrom, "\" ");
  216. } else {
  217. lstrcpy(szFrom, "");
  218. }
  219. lstrcat(szFrom, "<");
  220. lstrcat(szFrom, m_szSenderEmail);
  221. lstrcat(szFrom, ">");
  222. var.vt = VT_LPSTR;
  223. var.pszVal = szFrom; // From Email
  224. CORg(hr = pMimeRoot->SetProp(PIDTOSTR(PID_HDR_FROM), 0, &var));
  225. var.vt = VT_LPSTR; // ignored?
  226. var.pszVal = (LPSTR) STR_MIME_TEXT_PLAIN;
  227. CORg(pMimeRoot->SetBodyProp(hbBody, STR_HDR_CNTTYPE, 0, &var));
  228. var.vt = VT_LPSTR; // ignored?
  229. var.pszVal = (LPSTR) STR_ENC_QP;
  230. CORg(pMimeRoot->SetBodyProp(hbBody, STR_HDR_CNTXFER, 0, &var));
  231. // Set subject
  232. var.vt = VT_LPSTR;
  233. var.pszVal = (LPSTR) m_szSubject;
  234. CORg(pMimeRoot->SetBodyProp(hbBody, STR_HDR_SUBJECT, 0, &var));
  235. CORg(pMimeRoot->BindToObject(HBODY_ROOT, IID_IMimeBody, (LPVOID*)&pMimeRootBody));
  236. //
  237. // Set the security options
  238. //
  239. // How many layers?
  240. if (m_dwFlags & encode_InnerSign) {
  241. iInnerSignLayer = ulSecurityLayers;
  242. ulSecurityLayers++;
  243. }
  244. if (m_dwFlags & encode_Encrypt) {
  245. iEncryptLayer = ulSecurityLayers; // index in arrays
  246. ulSecurityLayers++;
  247. }
  248. if (m_dwFlags & encode_OuterSign) {
  249. iOuterSignLayer = ulSecurityLayers;
  250. ulSecurityLayers++;
  251. }
  252. // Set up for Inner Signing
  253. if (m_dwFlags & encode_InnerSign) {
  254. // specifiy the Security Type for this layer
  255. rgdwSecurityType[iInnerSignLayer] = m_dwFlags & encode_InnerClear ? MST_THIS_SIGN : MST_THIS_BLOBSIGN;
  256. dwSecurityType |= m_dwFlags & encode_InnerClear ? MST_THIS_SIGN : MST_THIS_BLOBSIGN;
  257. // Specify the Signing Time for this layer
  258. GetSystemTime(&stNow);
  259. SystemTimeToFileTime(&stNow, &rgftSigntime[iInnerSignLayer]);
  260. // specify the signature alg for this layer
  261. rgpvAlgHash[iInnerSignLayer].vt = VT_BLOB;
  262. rgpvAlgHash[iInnerSignLayer].blob.cbSize = sizeof(c_SHA1_ALGORITHM_ID);
  263. rgpvAlgHash[iInnerSignLayer].blob.pBlobData = (BYTE*)c_SHA1_ALGORITHM_ID;
  264. // Specify the signing cert for this layer
  265. rgdwCertSigning[iInnerSignLayer] = m_SigningCertInner;
  266. // HCERTSTORE rgdwhCertStore[MAX_LAYERS] = {0}; // optional
  267. // PROPVARIANT rgpvSymcaps[MAX_LAYERS] = {0};
  268. // PROPVARIANT rgpvAuthattr[MAX_LAYERS] = {0}; // optional
  269. // PROPVARIANT rgpvUnauthattr[MAX_LAYERS] = {0}; // optional
  270. }
  271. // Set up for Outer Signing
  272. if (m_dwFlags & encode_OuterSign) {
  273. // specifiy the Security Type for this layer
  274. rgdwSecurityType[iOuterSignLayer] = m_dwFlags & encode_InnerClear ? MST_THIS_SIGN : MST_THIS_BLOBSIGN;
  275. dwSecurityType |= m_dwFlags & encode_OuterClear ? MST_THIS_SIGN : MST_THIS_BLOBSIGN;
  276. // Specify the Signing Time for this layer
  277. GetSystemTime(&stNow);
  278. SystemTimeToFileTime(&stNow, &rgftSigntime[iOuterSignLayer]);
  279. // specify the signature alg for this layer
  280. rgpvAlgHash[iOuterSignLayer].vt = VT_BLOB;
  281. rgpvAlgHash[iOuterSignLayer].blob.cbSize = sizeof(c_SHA1_ALGORITHM_ID);
  282. rgpvAlgHash[iOuterSignLayer].blob.pBlobData = (BYTE*)c_SHA1_ALGORITHM_ID;
  283. // Specify the signing cert for this layer
  284. rgdwCertSigning[iOuterSignLayer] = m_SigningCertOuter;
  285. // HCERTSTORE rgdwhCertStore[MAX_LAYERS] = {0}; // optional
  286. // PROPVARIANT rgpvSymcaps[MAX_LAYERS] = {0};
  287. // PROPVARIANT rgpvAuthattr[MAX_LAYERS] = {0}; // optional
  288. // PROPVARIANT rgpvUnauthattr[MAX_LAYERS] = {0}; // optional
  289. }
  290. // Set up for Encrypting
  291. if (m_dwFlags & encode_Encrypt) {
  292. HCERTSTORE aCertStores[3];
  293. //
  294. // BUGBUG: Hardcoded to RC2 40-bit
  295. var.vt = VT_BLOB;
  296. var.blob.cbSize = sizeof( c_RC2_40_ALGORITHM_ID );
  297. var.blob.pBlobData = (BYTE*) c_RC2_40_ALGORITHM_ID;
  298. CORg(hr = pMimeRootBody->SetOption(OID_SECURITY_ALG_BULK, &var));
  299. // for encryption, get to the right cert store....
  300. //
  301. var.caul.cElems = 3;
  302. aCertStores[0] = CertDuplicateStore(m_hCACertStore);
  303. aCertStores[1] = CertDuplicateStore(m_hMYCertStore);
  304. aCertStores[2] = CertDuplicateStore(m_hABCertStore);
  305. var.caul.pElems = (ULONG*)aCertStores;
  306. CORg(hr = pMimeRootBody->SetOption(OID_SECURITY_SEARCHSTORES, &var));
  307. var.vt = VT_VECTOR | VT_UI4;
  308. var.caul.cElems = 1;
  309. var.caul.pElems = (ULONG*)&m_EncryptionCert;
  310. CORg(pMimeRootBody->SetOption(OID_SECURITY_RG_CERT_ENCRYPT, &var));
  311. #ifdef BUGBUG // This isn't right, is it?
  312. // include the cert...
  313. var.vt = VT_VECTOR | VT_UI4;
  314. var.caul.cElems = 1;
  315. var.caul.pElems = (ULONG*)&m_EncryptionCert;
  316. CORg(pMimeRootBody->SetOption(OID_SECURITY_RG_CERT_BAG, &var));
  317. #endif // OLD_STUFF
  318. dwSecurityType |= MST_THIS_ENCRYPT;
  319. rgdwSecurityType[iEncryptLayer] = MST_THIS_ENCRYPT;
  320. }
  321. // Set the OID_SECURITY_TYPE
  322. if (fTripleWrap) {
  323. var.vt = VT_VECTOR | VT_UI4;
  324. var.caul.cElems = ulSecurityLayers;
  325. var.caul.pElems = rgdwSecurityType;
  326. CORg(pMimeRootBody->SetOption(OID_SECURITY_TYPE_RG, &var));
  327. var.vt = VT_VECTOR | VT_FILETIME;
  328. var.cafiletime.cElems = ulSecurityLayers;
  329. var.cafiletime.pElems = rgftSigntime;
  330. CORg(pMimeRootBody->SetOption(OID_SECURITY_SIGNTIME_RG, &var));
  331. var.vt = VT_VECTOR | VT_UI4;
  332. var.caul.cElems = ulSecurityLayers;
  333. var.caul.pElems = (DWORD *)rgdwCertSigning;
  334. CORg(pMimeRootBody->SetOption(OID_SECURITY_CERT_SIGNING_RG, &var));
  335. var.vt = VT_VECTOR | VT_VARIANT;
  336. var.capropvar.cElems = ulSecurityLayers;
  337. var.capropvar.pElems = rgpvAlgHash;
  338. CORg(pMimeRootBody->SetOption(OID_SECURITY_ALG_HASH_RG, &var));
  339. var.vt = VT_VECTOR | VT_VARIANT;
  340. var.capropvar.cElems = ulSecurityLayers;
  341. var.capropvar.pElems = rgpvAlgHash;
  342. CORg(pMimeRootBody->SetOption(OID_SECURITY_ALG_HASH_RG, &var));
  343. } else {
  344. // Security Type
  345. var.vt = VT_UI4;
  346. var.ulVal = dwSecurityType;
  347. CORg(pMimeRootBody->SetOption(OID_SECURITY_TYPE, &var));
  348. if (dwSecurityType & MST_SIGN_MASK) {
  349. // Signing Time
  350. var.vt = VT_FILETIME;
  351. memcpy(&var.filetime, &rgftSigntime[iInnerSignLayer], sizeof(FILETIME));
  352. CORg(pMimeRootBody->SetOption(OID_SECURITY_SIGNTIME, &var));
  353. // Hash Algorithm
  354. var.vt = VT_BLOB;
  355. memcpy(&var.blob, &rgpvAlgHash[iInnerSignLayer].blob, sizeof(BLOB));
  356. CORg(hr = pMimeRootBody->SetOption(OID_SECURITY_ALG_HASH, &var));
  357. // Signing Cert
  358. var.vt = VT_UI4;
  359. var.ulVal = (ULONG)m_SigningCertInner;
  360. CORg(pMimeRootBody->SetOption(OID_SECURITY_CERT_SIGNING, &var));
  361. }
  362. }
  363. // Set the HWND for CAPI calls
  364. var.vt = VT_UI4;
  365. var.ulVal = 0;
  366. CORg(pMimeRootBody->SetOption(OID_SECURITY_HWND_OWNER, &var));
  367. // all built, get rid of the shadow pointer we are holding
  368. //
  369. pMimeRootBody->Release();
  370. pMimeRootBody = NULL;
  371. pMimeRoot->Commit(0);
  372. // SMIME Engine
  373. //
  374. CORg(CoCreateInstance(CLSID_IMimeSecurity, NULL, CLSCTX_INPROC_SERVER,
  375. IID_IMimeSecurity, (LPVOID*) &pMimeSecurity));
  376. CORg(pMimeSecurity->InitNew());
  377. // ERRORMESSAGE( Unable to encrypt/encode string )
  378. CORg(pMimeSecurity->EncodeBody(pMimeRoot, HBODY_ROOT,
  379. EBF_RECURSE | SEF_SENDERSCERTPROVIDED | SEF_ENCRYPTWITHNOSENDERCERT |
  380. EBF_COMMITIFDIRTY));
  381. // Get an Hcharset to force the encoding correctly
  382. //
  383. CORg(CoCreateInstance(CLSID_IMimeInternational, NULL, CLSCTX_INPROC_SERVER,
  384. IID_IMimeInternational, (LPVOID*)&pCharSet));
  385. CORg(pCharSet->FindCharset("UTF-8", &HCharset));
  386. CORg(pMimeRoot->SetCharset(HCharset, // HCharset
  387. CSET_APPLY_ALL)); // Applytype
  388. // dump it to a file
  389. //
  390. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, m_szOutputFile, -1, szwFileName, MAX_PATH);
  391. CORg(pMimeRoot->QueryInterface(IID_IPersistFile, (LPVOID*)&pIPFFileStore));
  392. CORg(pIPFFileStore->Save(szwFileName, FALSE));
  393. // extract the whole message into a stream
  394. //
  395. CORg(CreateStreamOnHGlobal(NULL, TRUE, &pResultStream));
  396. CORg(pMimeRoot->Save(pResultStream, FALSE));
  397. Error:
  398. if (pBuildStream) pBuildStream->Release();
  399. if (pResultStream) pResultStream->Release();
  400. if (pMimeRoot) pMimeRoot->Release();
  401. if (pMimeRootBody) pMimeRootBody->Release();
  402. if (pCharSet) pCharSet->Release();
  403. if (pMimeSecurity) pMimeSecurity->Release();
  404. if (pIPFFileStore) pIPFFileStore->Release();
  405. return(hr);
  406. }