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.

334 lines
11 KiB

  1. /*
  2. ** m i m e d e m . c p p
  3. **
  4. ** Purpose: implement the loader functions for defer/demand -loaded libraries
  5. **
  6. ** Creators: yst
  7. ** Created: 2/10/99
  8. **
  9. ** Copyright (C) Microsoft Corp. 1999
  10. */
  11. #include "pch.hxx"
  12. #include "imnact.h"
  13. #include <acctimp.h>
  14. #include "resource.h"
  15. // W4 stuff
  16. #pragma warning(disable: 4201) // nameless struct/union
  17. #pragma warning(disable: 4514) // unreferenced inline function removed
  18. #define IMPLEMENT_LOADER_FUNCTIONS
  19. #include "mimedem.h"
  20. // --------------------------------------------------------------------------------
  21. // CRIT_GET_PROC_ADDR
  22. // --------------------------------------------------------------------------------
  23. #define CRIT_GET_PROC_ADDR(h, fn, temp) \
  24. temp = (TYP_##fn) GetProcAddress(h, #fn); \
  25. if (temp) \
  26. VAR_##fn = temp; \
  27. else \
  28. { \
  29. AssertSz(0, VAR_##fn" failed to load"); \
  30. goto error; \
  31. }
  32. // --------------------------------------------------------------------------------
  33. // RESET
  34. // --------------------------------------------------------------------------------
  35. #define RESET(fn) VAR_##fn = LOADER_##fn;
  36. // --------------------------------------------------------------------------------
  37. // GET_PROC_ADDR
  38. // --------------------------------------------------------------------------------
  39. #define GET_PROC_ADDR(h, fn) \
  40. VAR_##fn = (TYP_##fn) GetProcAddress(h, #fn); \
  41. Assert(VAR_##fn != NULL); \
  42. if(NULL == VAR_##fn ) { \
  43. VAR_##fn = LOADER_##fn; \
  44. }
  45. // --------------------------------------------------------------------------------
  46. // GET_PROC_ADDR_ORDINAL
  47. // --------------------------------------------------------------------------------
  48. #define GET_PROC_ADDR_ORDINAL(h, fn, ord) \
  49. VAR_##fn = (TYP_##fn) GetProcAddress(h, MAKEINTRESOURCE(ord)); \
  50. Assert(VAR_##fn != NULL); \
  51. if(NULL == VAR_##fn ) { \
  52. VAR_##fn = LOADER_##fn; \
  53. }
  54. // --------------------------------------------------------------------------------
  55. // GET_PROC_ADDR3
  56. // --------------------------------------------------------------------------------
  57. #define GET_PROC_ADDR3(h, fn, varname) \
  58. VAR_##varname = (TYP_##varname) GetProcAddress(h, #fn); \
  59. Assert(VAR_##varname != NULL);
  60. ////////////////////////////////////////////////////////////////////////////
  61. //
  62. // Variables
  63. ////////////////////////////////////////////////////////////////////////////
  64. static HMODULE s_hMimeOle = 0;
  65. static CRITICAL_SECTION g_csDefMimeLoad = {0};
  66. // --------------------------------------------------------------------------------
  67. // InitDemandLoadedLibs
  68. // --------------------------------------------------------------------------------
  69. void InitDemandMimeole(void)
  70. {
  71. InitializeCriticalSection(&g_csDefMimeLoad);
  72. }
  73. // --------------------------------------------------------------------------------
  74. // FreeDemandLoadedLibs
  75. // --------------------------------------------------------------------------------
  76. void FreeDemandMimeOle(void)
  77. {
  78. EnterCriticalSection(&g_csDefMimeLoad);
  79. SafeFreeLibrary(s_hMimeOle);
  80. LeaveCriticalSection(&g_csDefMimeLoad);
  81. DeleteCriticalSection(&g_csDefMimeLoad);
  82. }
  83. // --------------------------------------------------------------------------------
  84. // DemandLoadCrypt32
  85. // --------------------------------------------------------------------------------
  86. BOOL DemandLoadMimeOle(void)
  87. {
  88. BOOL fRet = TRUE;
  89. EnterCriticalSection(&g_csDefMimeLoad);
  90. if (0 == s_hMimeOle)
  91. {
  92. s_hMimeOle = LoadLibrary("INETCOMM.DLL");
  93. AssertSz((NULL != s_hMimeOle), TEXT("LoadLibrary failed on INETCOMM.DLL"));
  94. if (0 == s_hMimeOle)
  95. fRet = FALSE;
  96. else
  97. {
  98. GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapsToDlg);
  99. GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapsFromDlg);
  100. GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapsFull);
  101. GET_PROC_ADDR(s_hMimeOle, MimeOleSMimeCapInit);
  102. }
  103. }
  104. LeaveCriticalSection(&g_csDefMimeLoad);
  105. return fRet;
  106. }
  107. HRESULT HrGetHighestSymcaps(LPBYTE * ppbSymcap, ULONG *pcbSymcap);
  108. const BYTE c_RC2_40_ALGORITHM_ID[] =
  109. {0x30, 0x0F, 0x30, 0x0D, 0x06, 0x08, 0x2A, 0x86,
  110. 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x02, 0x02, 0x01,
  111. 0x28};
  112. const ULONG cbRC2_40_ALGORITHM_ID = 0x11; // Must be 11 hex to match size!
  113. BOOL AdvSec_FillEncAlgCombo(HWND hwnd, IImnAccount *pAcct, PCCERT_CONTEXT * prgCerts)
  114. {
  115. HRESULT hr;
  116. THUMBBLOB tb = {0,0};
  117. // Get the default caps blob from the registry
  118. // hr = poi->pOpt->GetProperty(MAKEPROPSTRING(OPT_MAIL_DEFENCRYPTSYMCAPS), &var, 0);
  119. if (SUCCEEDED(hr = pAcct->GetProp(AP_SMTP_ENCRYPT_ALGTH, NULL, &tb.cbSize)))
  120. {
  121. if (!MemAlloc((void**)&tb.pBlobData, tb.cbSize))
  122. tb.pBlobData = NULL;
  123. else
  124. hr = pAcct->GetProp(AP_SMTP_ENCRYPT_ALGTH, tb.pBlobData, &tb.cbSize);
  125. }
  126. if (FAILED(hr) || ! tb.cbSize || ! tb.pBlobData)
  127. {
  128. HrGetHighestSymcaps(&tb.pBlobData, &tb.cbSize);
  129. }
  130. if (tb.pBlobData && tb.cbSize)
  131. {
  132. // Init the caps->dlg engine
  133. if (FAILED(hr = MimeOleSMimeCapsToDlg(
  134. tb.pBlobData,
  135. tb.cbSize,
  136. (prgCerts ? 1 : 0),
  137. prgCerts,
  138. hwnd,
  139. IDC_ALGCOMBO, // combo box for encryption algorithms
  140. 0, // combo box for signing algorithms (we combine encrypt and signing)
  141. 0))) // id of checkbox for pkcs7-opaque. We handle this elsewhere.
  142. {
  143. DOUTL(1024, "MimeOleSMimeCapsToDlg -> %x\n", hr);
  144. }
  145. SafeMemFree(tb.pBlobData);
  146. }
  147. return(SUCCEEDED(hr));
  148. }
  149. // Largest symcap is currently 0x4E with 3DES, RC2/128, RC2/64, DES, RC2/40 and SHA-1.
  150. // You may want to bump up the size when FORTEZZA algorithms are supported.
  151. #define CCH_BEST_SYMCAP 0x50
  152. HRESULT HrGetHighestSymcaps(LPBYTE * ppbSymcap, ULONG *pcbSymcap)
  153. {
  154. HRESULT hr=S_OK;
  155. LPVOID pvSymCapsCookie = NULL;
  156. LPBYTE pbEncode = NULL;
  157. ULONG cbEncode = 0;
  158. DWORD dwBits;
  159. // The MimeOleSMimeCapsFull call is quite expensive. The results are always
  160. // the same during a session. (They can only change with software upgrade.)
  161. // Cache the results here for better performance.
  162. static BYTE szSaveBestSymcap[CCH_BEST_SYMCAP];
  163. static ULONG cbSaveBestSymcap = 0;
  164. if (cbSaveBestSymcap == 0)
  165. {
  166. // Init with no symcap gives max allowed by providers
  167. hr = MimeOleSMimeCapInit(NULL, NULL, &pvSymCapsCookie);
  168. if (FAILED(hr))
  169. goto exit;
  170. if (pvSymCapsCookie)
  171. {
  172. // Finish up with SymCaps
  173. MimeOleSMimeCapsFull(pvSymCapsCookie, TRUE, FALSE, pbEncode, &cbEncode);
  174. if (cbEncode)
  175. {
  176. if (! MemAlloc((LPVOID *)&pbEncode, cbEncode))
  177. cbEncode = 0;
  178. else
  179. {
  180. hr = MimeOleSMimeCapsFull(pvSymCapsCookie, TRUE, FALSE, pbEncode, &cbEncode);
  181. if (SUCCEEDED(hr))
  182. {
  183. // Save this symcap in the static array for next time
  184. // Only if we have room!
  185. if (cbEncode <= CCH_BEST_SYMCAP)
  186. {
  187. memcpy(szSaveBestSymcap, pbEncode, cbEncode);
  188. cbSaveBestSymcap = cbEncode;
  189. }
  190. }
  191. }
  192. }
  193. SafeMemFree(pvSymCapsCookie);
  194. }
  195. }
  196. else
  197. {
  198. // We have saved the best in the static array. Avoid the time intensive
  199. // MimeOle query.
  200. cbEncode = cbSaveBestSymcap;
  201. if (! MemAlloc((LPVOID *)&pbEncode, cbEncode))
  202. cbEncode = 0;
  203. else
  204. memcpy(pbEncode, szSaveBestSymcap, cbEncode);
  205. }
  206. exit:
  207. if (! pbEncode)
  208. {
  209. // Hey, there should ALWAYS be at least RC2 (40 bit). What happened?
  210. AssertSz(cbEncode, "MimeOleSMimeCapGetEncAlg gave us no encoding algorithm");
  211. // Try to fix it up as best you can. Stick in the RC2 value.
  212. cbEncode = cbRC2_40_ALGORITHM_ID;
  213. if (MemAlloc((LPVOID *)&pbEncode, cbEncode))
  214. {
  215. memcpy(pbEncode, (LPBYTE)c_RC2_40_ALGORITHM_ID, cbEncode);
  216. hr = S_OK;
  217. }
  218. }
  219. if (cbEncode && pbEncode)
  220. {
  221. *pcbSymcap = cbEncode;
  222. *ppbSymcap = pbEncode;
  223. }
  224. return(hr);
  225. }
  226. BOOL AdvSec_GetEncryptAlgCombo(HWND hwnd, IImnAccount *pAcct)
  227. {
  228. HRESULT hr;
  229. LPBYTE pbSymCaps = NULL;
  230. ULONG cbSymCaps = 0;
  231. // How big a buffer do I need?
  232. hr = MimeOleSMimeCapsFromDlg(hwnd,
  233. IDC_ALGCOMBO, // idEncryptAlgs
  234. 0, // idSignAlgs,
  235. 0, // idBlob,
  236. NULL,
  237. &cbSymCaps);
  238. // Never mind the hr, it's screwy. Do we have a size?
  239. if (cbSymCaps)
  240. {
  241. if (MemAlloc((void **)&pbSymCaps, cbSymCaps))
  242. {
  243. if (hr = MimeOleSMimeCapsFromDlg(hwnd,
  244. IDC_ALGCOMBO, // idEncryptAlgs
  245. 0, // idSignAlgs,
  246. 0, // idBlob,
  247. pbSymCaps, &cbSymCaps))
  248. {
  249. DOUTL(1024, "MimeOleSMimeCapsFromDlg -> %x", hr);
  250. }
  251. else
  252. {
  253. LPBYTE pbBestSymcaps = NULL;
  254. ULONG cbBestSymcaps = 0;
  255. // Compare symcaps to highest available.
  256. if (SUCCEEDED(HrGetHighestSymcaps(&pbBestSymcaps, &cbBestSymcaps)) &&
  257. (cbBestSymcaps == cbSymCaps && (0 == memcmp(pbBestSymcaps, pbSymCaps, cbBestSymcaps)))) {
  258. // Best available symcaps. Set it to default value of NULL (which should delete the prop.)
  259. SafeMemFree(pbSymCaps);
  260. cbSymCaps = 0;
  261. pbSymCaps = NULL;
  262. }
  263. SafeMemFree(pbBestSymcaps);
  264. pAcct->SetProp(AP_SMTP_ENCRYPT_ALGTH, pbSymCaps, cbSymCaps);
  265. }
  266. }
  267. else
  268. {
  269. DOUTL(1024, "MemAlloc of SymCaps blob failed");
  270. hr = E_OUTOFMEMORY;
  271. }
  272. }
  273. else
  274. {
  275. DOUTL(1024, "BAD NEWS: First MimeOleSMimeCapsFromDlg didn't return size", hr);
  276. Assert(hr); // Weird, maybe there isn't a symcaps?
  277. hr = E_FAIL;
  278. }
  279. SafeMemFree(pbSymCaps);
  280. return(SUCCEEDED(hr));
  281. }