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.

2836 lines
80 KiB

  1. /*
  2. ** s e c l a b e l. c p p
  3. **
  4. ** Purpose: Security labels interface
  5. **
  6. ** Ported from O2K fed release by YST
  7. **
  8. ** Copyright (C) Microsoft Corp. 1996-1999
  9. */
  10. #include "pch.hxx"
  11. #include "ipab.h"
  12. #include "secutil.h"
  13. #include "wchar.h"
  14. #include "goptions.h"
  15. #include "SecLabel.h"
  16. #include "mailnews.h"
  17. #include "shlwapip.h"
  18. #include "util.h"
  19. #include "demand.h"
  20. // #include "_digsigx.h"
  21. // #include "..\_secext\SecExt.h"
  22. // --------------------------------------------------------------------------------
  23. // GUIDS
  24. // --------------------------------------------------------------------------------
  25. // {5073B6B4-AA66-11d2-9841-0060B0EC2DF3}
  26. EXTERN_C const GUID DECLSPEC_SELECTANY IID_ISMimePolicySimpleEdit ={0x5073b6b4, 0xaa66, 0x11d2, { 0x98, 0x41, 0x0, 0x60, 0xb0, 0xec, 0x2d, 0xf3} };
  27. // {5073B6B5-AA66-11d2-9841-0060B0EC2DF3}
  28. EXTERN_C const GUID DECLSPEC_SELECTANY IID_ISMimePolicyFullEdit = {0x5073b6b5, 0xaa66, 0x11d2, { 0x98, 0x41, 0x0, 0x60, 0xb0, 0xec, 0x2d, 0xf3} };
  29. // {5073B6B6-AA66-11d2-9841-0060B0EC2DF3}
  30. EXTERN_C const GUID DECLSPEC_SELECTANY IID_ISMimePolicyCheckAccess = {0x5073b6b6, 0xaa66, 0x11d2, { 0x98, 0x41, 0x0, 0x60, 0xb0, 0xec, 0x2d, 0xf3} };
  31. // {5073B6B7-AA66-11d2-9841-0060B0EC2DF3}
  32. EXTERN_C const GUID DECLSPEC_SELECTANY IID_ISMimePolicyLabelInfo = {0x5073b6b7, 0xaa66, 0x11d2, { 0x98, 0x41, 0x0, 0x60, 0xb0, 0xec, 0x2d, 0xf3} };
  33. // {5073B6B8-AA66-11d2-9841-0060B0EC2DF3}
  34. EXTERN_C const GUID DECLSPEC_SELECTANY IID_ISMimePolicyValidateSend = {0x5073b6b8, 0xaa66, 0x11d2, { 0x98, 0x41, 0x0, 0x60, 0xb0, 0xec, 0x2d, 0xf3} };
  35. //
  36. // constant local data.
  37. //
  38. //$ M00Bug : GautamV Use the CryptoReg helper Api's to get the base crypto regkey.
  39. const TCHAR c_szSecurityPoliciesRegKey[] =
  40. TEXT("Software\\Microsoft\\Cryptography\\OID\\EncodingType 1\\SMIMESecurityLabel");
  41. const TCHAR c_szSecurityPolicyDllPath[] = TEXT("DllPath"); // string.
  42. const WCHAR c_wszSecurityPolicyCommonName[] = L"CommonName"; // string
  43. const TCHAR c_szSecurityPolicyFuncName[] = TEXT("FuncName"); // string.
  44. const TCHAR c_szSecurityPolicyOtherInfo[] = TEXT("OtherInfo"); // dword
  45. const TCHAR SzRegSecurity[] = "Software\\Microsoft\\Office\\9.0\\Outlook\\Security";
  46. // other constant strings.
  47. const CHAR c_szDefaultPolicyOid[] = "default"; // The default policy
  48. static const WCHAR c_PolwszEmpty[] = L""; //
  49. const WCHAR c_wszPolicyNone[] = L"<None>"; //$ M00BUG: GautamV. This needs to be localized.
  50. #define KEY_USAGE_SIGNING (CERT_DIGITAL_SIGNATURE_KEY_USAGE|CERT_NON_REPUDIATION_KEY_USAGE)
  51. #define KEY_USAGE_ENCRYPTION (CERT_KEY_ENCIPHERMENT_KEY_USAGE|CERT_KEY_AGREEMENT_KEY_USAGE)
  52. #define KEY_USAGE_SIGNENCRYPT (KEY_USAGE_SIGNING|KEY_USAGE_ENCRYPTION)
  53. //
  54. // static local data.
  55. //
  56. // The cached information about the security policies.
  57. enum EPolicyRegInfoState {
  58. ePolicyRegInfoNOTLOADED = 0,
  59. ePolicyRegInfoPRESENT = 1,
  60. ePolicyRegInfoABSENT = 2
  61. };
  62. const static HELPMAP g_rgCtxSecLabel[] =
  63. {
  64. {IDC_POLICY_COMBO, IDH_SECURITY_POLICY_MODULE},
  65. {IDC_CLASSIF_COMB, IDH_SECURITY_CLASSIFICATION},
  66. {IDC_PRIVACY_EDIT, IDH_SECURITY_PRIVACY},
  67. {IDC_CONFIGURE, IDH_SECURITY_CONFIGURE},
  68. {IDC_STATIC, IDH_NEWS_COMM_GROUPBOX},
  69. {0, 0}
  70. };
  71. static EPolicyRegInfoState s_ePolicyRegInfoState = ePolicyRegInfoNOTLOADED;
  72. static SMIME_SECURITY_POLICY *s_rgSsp = NULL; // array of Ssp's.
  73. static ULONG s_cSsp = 0;
  74. // local fn prototypes.
  75. VOID _IncrPolicyUsage(PSMIME_SECURITY_POLICY pSsp);
  76. HRESULT _HrFindLeastUsedPolicy(PSMIME_SECURITY_POLICY *ppSsp);
  77. HRESULT _EnsureNewPolicyLoadable();
  78. BOOL _FLoadedPolicyRegInfo();
  79. // BOOL _FPresentPolicyRegInfo();
  80. HRESULT _HrEnsurePolicyRegInfoLoaded(DWORD dwFlags);
  81. HRESULT _HrLoadPolicyRegInfo(DWORD dwFlags);
  82. HRESULT _HrReloadPolicyRegInfo(DWORD dwFlags);
  83. BOOL _FFindPolicy(LPCSTR szPolicyOid, PSMIME_SECURITY_POLICY *ppSsp);
  84. BOOL _FIsPolicyLoaded(PSMIME_SECURITY_POLICY pSsp);
  85. HRESULT _HrUnloadPolicy(PSMIME_SECURITY_POLICY pSsp);
  86. HRESULT _HrLoadPolicy(PSMIME_SECURITY_POLICY pSsp);
  87. HRESULT _HrEnsurePolicyLoaded(PSMIME_SECURITY_POLICY pSsp);
  88. HRESULT _HrGetPolicy(LPCSTR szPolicyOid, PSMIME_SECURITY_POLICY *ppSsp);
  89. // Registry access functions
  90. const int QRV_Suppress_HKLM = 1;
  91. const int QRV_Suppress_HKCU = 2;
  92. HRESULT HrQueryRegValue(DWORD dwFlags, LPSTR szRegKey, LPDWORD pdwType,
  93. LPBYTE * ppbData, LPDWORD pcbData, DWORD dwDefaultType,
  94. LPBYTE pbDefault, DWORD cbDefault);
  95. HRESULT CategoriesToBinary(PSMIME_SECURITY_LABEL plabel, BYTE * *ppArray, int *cbSize);
  96. HRESULT BinaryToCategories(CRYPT_ATTRIBUTE_TYPE_VALUE ** ppCategories, DWORD *cCat, BYTE * pArray);
  97. //
  98. // Increase the usage count of the given policy.
  99. //
  100. VOID _IncrPolicyUsage(PSMIME_SECURITY_POLICY pSsp)
  101. {
  102. if (!FPresentPolicyRegInfo()) return;
  103. if ((pSsp->dwUsage + 1) < pSsp->dwUsage) {
  104. // prevent overflow.
  105. Assert(s_rgSsp);
  106. for (ULONG iSsp = 0; iSsp<s_cSsp; iSsp++) {
  107. s_rgSsp[iSsp].dwUsage /= 2; // Just halve each usage count.
  108. }
  109. }
  110. pSsp->dwUsage ++;
  111. }
  112. //
  113. // Find the least used policy.
  114. //
  115. HRESULT _HrFindLeastUsedPolicy(PSMIME_SECURITY_POLICY *ppSsp)
  116. {
  117. ULONG iSsp;
  118. HRESULT hr = E_FAIL;
  119. PSMIME_SECURITY_POLICY pSspFound = NULL;
  120. // validate i/p params.
  121. if (NULL == ppSsp) {
  122. hr = E_INVALIDARG;
  123. goto Error;
  124. }
  125. *ppSsp = NULL;
  126. // find the least used policy.
  127. for (iSsp=0; iSsp < s_cSsp; iSsp++) {
  128. if (_FIsPolicyLoaded(& (s_rgSsp[iSsp]) )) {
  129. // if we haven't found a ssp earlier,
  130. // OR if this one is less used that the currently found one.
  131. if ((NULL == pSspFound) ||
  132. (s_rgSsp[iSsp].dwUsage < pSspFound->dwUsage)) {
  133. pSspFound = & (s_rgSsp[iSsp]);
  134. }
  135. }
  136. }
  137. // have we found the result.
  138. if (NULL == pSspFound) {
  139. hr = E_FAIL;
  140. goto Error;
  141. }
  142. // success.
  143. *ppSsp = pSspFound;
  144. hr = S_OK;
  145. // Exit:
  146. Error:
  147. return hr;
  148. }
  149. //
  150. // Unloads one or more policies from memory and ensures that there
  151. // is room for a new policy to be loaded.
  152. //
  153. HRESULT _EnsureNewPolicyLoadable()
  154. {
  155. ULONG cSspLoaded = 0;
  156. HRESULT hr = E_FAIL;
  157. ULONG iSsp;
  158. // count the number of policies loaded into memory.
  159. for (iSsp=0; iSsp < s_cSsp; iSsp++) {
  160. if (_FIsPolicyLoaded( &(s_rgSsp[iSsp]) )) {
  161. cSspLoaded ++;
  162. }
  163. }
  164. // If we have room for one more policy, then we don't need to do anything.
  165. if (cSspLoaded < MAX_SECURITY_POLICIES_CACHED) {
  166. hr = S_OK;
  167. goto Exit;
  168. }
  169. // Assert that this isn't a "bad" condition, but we will handle it anyway.
  170. Assert(cSspLoaded == MAX_SECURITY_POLICIES_CACHED);
  171. // unload one or more policies.
  172. while (cSspLoaded >= MAX_SECURITY_POLICIES_CACHED) {
  173. PSMIME_SECURITY_POLICY pSsp = NULL;
  174. if (FAILED(_HrFindLeastUsedPolicy(&pSsp))) {
  175. goto Error;
  176. }
  177. if (FAILED(_HrUnloadPolicy(pSsp))) {
  178. goto Error;
  179. }
  180. cSspLoaded --;
  181. }
  182. // success.
  183. hr = S_OK;
  184. Exit:
  185. return hr;
  186. Error:
  187. AssertSz(FALSE, "_EnsureNewPolicyLoadable failed");
  188. goto Exit;
  189. }
  190. //
  191. // Return true if the info about the installed policies
  192. // has been read in from the windows registry.
  193. //
  194. BOOL _FLoadedPolicyRegInfo()
  195. {
  196. return ( ! ( ePolicyRegInfoNOTLOADED == s_ePolicyRegInfoState ) );
  197. }
  198. //
  199. // Ensure that the policy registration info has been read in.
  200. //
  201. HRESULT _HrEnsurePolicyRegInfoLoaded(DWORD dwFlags)
  202. {
  203. HRESULT hr = S_OK;
  204. if ( !_FLoadedPolicyRegInfo() ) hr = _HrLoadPolicyRegInfo(dwFlags);
  205. return hr;
  206. }
  207. //
  208. // Are any policies installed(registered) ?
  209. //
  210. BOOL FPresentPolicyRegInfo()
  211. {
  212. HRESULT hr = S_OK;
  213. BOOL fRegistered = FALSE;
  214. // No label support without SMIME3 bits
  215. if(!IsSMIME3Supported())
  216. return FALSE;
  217. hr = _HrEnsurePolicyRegInfoLoaded(0);
  218. if (SUCCEEDED(hr)) {
  219. fRegistered = (ePolicyRegInfoPRESENT == s_ePolicyRegInfoState);
  220. Assert(!fRegistered || s_rgSsp); // ie ((registered_policies) => (NULL!=s_rgSsp)).
  221. }
  222. return fRegistered;
  223. }
  224. //
  225. // Internal function.
  226. // Load Policy Registration information.
  227. //
  228. // Returns:
  229. // S_OK or E_FAIL.
  230. //
  231. // The format of the security policy registration info is assumed to be:
  232. // HKLM\Software\Microsoft\Cryptography\SMIME\SecurityPolicies\
  233. // szPolicyOid_1
  234. // DLLPATH REG_SZ
  235. // CommonName REG_SZ
  236. // FuncName REG_SZ
  237. // OtherInfo REG_SZ
  238. // szPolicyOid_2
  239. // Default
  240. // ...
  241. //
  242. //
  243. HRESULT _HrLoadPolicyRegInfo(DWORD dwFlags)
  244. {
  245. HRESULT hr = E_FAIL;
  246. LONG lRes = 0;
  247. HKEY hkey = NULL;
  248. HKEY hkeySub = NULL;
  249. ULONG cb = 0;
  250. LPBYTE pb = NULL;
  251. DWORD cSubKeys = 0;
  252. ULONG iSubKey = 0;
  253. if (_FLoadedPolicyRegInfo()) {
  254. AssertSz(FALSE, "PolicyRegInfo is already loaded");
  255. hr = S_OK;
  256. goto Cleanup;
  257. }
  258. // Open the security policies key.
  259. lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szSecurityPoliciesRegKey, 0,
  260. KEY_READ, &hkey);
  261. if ( (ERROR_SUCCESS != lRes) || (NULL == hkey) ) {
  262. // we couldn't open the regkey, bail out.
  263. hr = E_FAIL;
  264. goto Error;
  265. }
  266. // find the number of security policies. (ie number of subkeys).
  267. lRes = RegQueryInfoKey(hkey, NULL, NULL, NULL, &cSubKeys,
  268. NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  269. if ( (ERROR_SUCCESS != lRes) || (0 == cSubKeys) ) {
  270. // we counldn't get num of subkeys, or there are no subkeys.
  271. hr = E_FAIL;
  272. goto Error;
  273. }
  274. // Allocate enough memory to retrieve and store info about
  275. // the registered security policies.
  276. cb = sizeof(SMIME_SECURITY_POLICY) * cSubKeys;
  277. pb = (LPBYTE) malloc(cb);
  278. if (NULL == pb) {
  279. hr = E_OUTOFMEMORY;
  280. goto Error;
  281. }
  282. memset(pb, 0, cb); // initialize the whole blob to zeros.
  283. Assert(NULL == s_rgSsp);
  284. s_rgSsp = (PSMIME_SECURITY_POLICY) pb;
  285. s_cSsp = 0;
  286. //
  287. // Enumerate over the subkeys and retrieve reqd info.
  288. //
  289. for (iSubKey=0; iSubKey<cSubKeys; iSubKey++) {
  290. ULONG cbData;
  291. DWORD dwType;
  292. TCHAR szPolicyOid[MAX_OID_LENGTH];
  293. TCHAR szDllPath[MAX_PATH];
  294. TCHAR szExpanded[MAX_PATH];
  295. TCHAR szFuncName[MAX_FUNC_NAME];
  296. WCHAR wszPolicyName[MAX_POLICY_NAME];
  297. DWORD dwOtherInfo;
  298. // release previously opened subkeys.
  299. if (NULL != hkeySub) {
  300. RegCloseKey(hkeySub);
  301. hkeySub = NULL;
  302. }
  303. // Get the subkey name. (ie policy oid).
  304. lRes = RegEnumKey(hkey, iSubKey, szPolicyOid, DimensionOf(szPolicyOid));
  305. if (ERROR_SUCCESS != lRes) {
  306. goto NextSsp;
  307. }
  308. szPolicyOid[ DimensionOf(szPolicyOid) - 1 ] = '\0';
  309. // Open the subkey. (ie the policy subkey).
  310. lRes = RegOpenKeyEx(hkey, szPolicyOid, 0, KEY_READ, &hkeySub);
  311. if (ERROR_SUCCESS != lRes) {
  312. goto NextSsp;
  313. }
  314. //
  315. // query the szOid policy values.
  316. //
  317. // get the path to the policy dll.
  318. cbData = sizeof(szDllPath);
  319. lRes = RegQueryValueEx(hkeySub, c_szSecurityPolicyDllPath, NULL,
  320. &dwType, (LPBYTE)szDllPath, &cbData);
  321. if (ERROR_SUCCESS != lRes) {
  322. goto NextSsp;
  323. }
  324. else if (REG_EXPAND_SZ == dwType)
  325. {
  326. ExpandEnvironmentStrings(szDllPath, szExpanded, ARRAYSIZE(szExpanded));
  327. StrCpyN(szDllPath, szExpanded, ARRAYSIZE(szDllPath));
  328. }
  329. else
  330. szDllPath[ DimensionOf(szDllPath) - 1 ] = '\0';
  331. // get the common name.
  332. cbData = DimensionOf(wszPolicyName);
  333. lRes = RegQueryValueExWrapW(hkeySub, c_wszSecurityPolicyCommonName, NULL,
  334. &dwType, (LPBYTE)wszPolicyName, &cbData);
  335. if (ERROR_SUCCESS != lRes) {
  336. goto NextSsp;
  337. }
  338. wszPolicyName[ DimensionOf(wszPolicyName) - 1 ] = '\0';
  339. // get the entry func name.
  340. cbData = sizeof(szFuncName);
  341. lRes = RegQueryValueEx(hkeySub, c_szSecurityPolicyFuncName, NULL,
  342. &dwType, (LPBYTE)szFuncName, &cbData);
  343. if (ERROR_SUCCESS != lRes) {
  344. goto NextSsp;
  345. }
  346. szFuncName[ DimensionOf(szFuncName) - 1] = '\0';
  347. // get other policy info.
  348. cbData = sizeof(dwOtherInfo);
  349. lRes = RegQueryValueEx(hkeySub, c_szSecurityPolicyOtherInfo, NULL,
  350. &dwType, (LPBYTE)&dwOtherInfo, &cbData);
  351. if (ERROR_SUCCESS != lRes) {
  352. dwOtherInfo = 0; // ignore the absence of this value.
  353. }
  354. //
  355. // Great: we were able to open subkey, and get all required info.
  356. // Now we store all the info we retrieved.
  357. //
  358. s_rgSsp[s_cSsp].fValid = TRUE;
  359. s_rgSsp[s_cSsp].fDefault = (0 == lstrcmpi(c_szDefaultPolicyOid, szPolicyOid));
  360. StrCpyNA(s_rgSsp[s_cSsp].szPolicyOid, szPolicyOid, ARRAYSIZE(s_rgSsp[s_cSsp].szPolicyOid));
  361. StrCpyNW(s_rgSsp[s_cSsp].wszPolicyName, wszPolicyName, ARRAYSIZE(s_rgSsp[s_cSsp].wszPolicyName));
  362. StrCpyNA(s_rgSsp[s_cSsp].szDllPath, szDllPath, ARRAYSIZE(s_rgSsp[s_cSsp].szDllPath));
  363. s_rgSsp[s_cSsp].dwOtherInfo = dwOtherInfo;
  364. s_rgSsp[s_cSsp].dwUsage = 0;
  365. s_rgSsp[s_cSsp].hinstDll = NULL;
  366. StrCpyNA(s_rgSsp[s_cSsp].szFuncName, szFuncName, ARRAYSIZE(s_rgSsp[s_cSsp].szFuncName));
  367. s_rgSsp[s_cSsp].punk = NULL;
  368. s_cSsp++;
  369. continue;
  370. NextSsp:
  371. AssertSz(FALSE, "Ignoring incorrectly registered Ssp");
  372. }
  373. // success.
  374. if (0 == s_cSsp) {
  375. AssertSz(FALSE, "There isn't even one correctly registered Ssp");
  376. goto Error;
  377. }
  378. s_ePolicyRegInfoState = ePolicyRegInfoPRESENT;
  379. hr = S_OK;
  380. goto Cleanup;
  381. Error:
  382. // Any error is treated as if no security policies are registered.
  383. s_ePolicyRegInfoState = ePolicyRegInfoABSENT;
  384. free(pb); //ie free(s_rgSsp);
  385. s_cSsp = 0;
  386. s_rgSsp = NULL;
  387. Cleanup:
  388. if (NULL != hkeySub) RegCloseKey(hkeySub);
  389. if (NULL != hkey) RegCloseKey(hkey);
  390. return hr;
  391. }
  392. //
  393. // Unload Policy Registration Information.
  394. //
  395. HRESULT HrUnloadPolicyRegInfo(DWORD dwFlags)
  396. {
  397. HRESULT hr = S_OK;
  398. ULONG iSsp;
  399. // If the policy reg info isn't loaded
  400. if ( ! _FLoadedPolicyRegInfo() ) {
  401. return S_OK;
  402. }
  403. // unload all policy modules.
  404. if (FPresentPolicyRegInfo()) {
  405. Assert(s_rgSsp && s_cSsp);
  406. for (iSsp=0; iSsp<s_cSsp; iSsp++) {
  407. SideAssert(SUCCEEDED(_HrUnloadPolicy(&s_rgSsp[iSsp])));
  408. // if this fails, we don't have to abort.
  409. }
  410. }
  411. // free memory, reset cache info and exit.
  412. free(s_rgSsp);
  413. s_rgSsp = NULL;
  414. s_ePolicyRegInfoState = ePolicyRegInfoNOTLOADED;
  415. s_cSsp = 0;
  416. hr = S_OK;
  417. return hr;
  418. }
  419. //
  420. // Reload all the policy registration information.
  421. //
  422. HRESULT _HrReloadPolicyRegInfo(DWORD dwFlags)
  423. {
  424. HRESULT hr = S_OK;
  425. hr = HrUnloadPolicyRegInfo(dwFlags);
  426. Assert(SUCCEEDED(hr));
  427. if (SUCCEEDED(hr)) {
  428. hr = _HrLoadPolicyRegInfo(dwFlags);
  429. }
  430. return hr;
  431. }
  432. //
  433. // Find a given policy, and return its reg info struct.
  434. //
  435. // Input:
  436. // szPolicyOid [in]
  437. // ppSsp [out]
  438. //
  439. // Output:
  440. // TRUE/FALSE. (if true, *ppSsp contains the reqd info).
  441. //
  442. BOOL _FFindPolicy(LPCSTR szPolicyOid, PSMIME_SECURITY_POLICY *ppSsp)
  443. {
  444. BOOL fFound = FALSE;
  445. HRESULT hr = E_FAIL;
  446. ULONG iSsp;
  447. // Validate i/p params and init o/p params.
  448. if ( (NULL == szPolicyOid) || (NULL == ppSsp) ) {
  449. hr = E_INVALIDARG;
  450. goto Error;
  451. }
  452. *ppSsp = NULL;
  453. // Load the info from the registry if reqd.
  454. hr = _HrEnsurePolicyRegInfoLoaded(0);
  455. if (FAILED(hr)) {
  456. goto Error;
  457. }
  458. // If we haven any installed policies, search for the one we want.
  459. if (FPresentPolicyRegInfo()) {
  460. for (iSsp=0; iSsp<s_cSsp; iSsp++) {
  461. if (0 == lstrcmpi(s_rgSsp[iSsp].szPolicyOid, szPolicyOid)) {
  462. // found the policy.
  463. *ppSsp = & (s_rgSsp[iSsp]);
  464. fFound = TRUE;
  465. break;
  466. }
  467. }
  468. }
  469. Error:
  470. // Cleanup:
  471. return fFound;
  472. }
  473. //
  474. // Finds out if a given policy module is loaded.
  475. //
  476. // Input: pSsp [in].
  477. // Output: true/false if policy is loaded or notloaded.
  478. //
  479. BOOL _FIsPolicyLoaded(PSMIME_SECURITY_POLICY pSsp)
  480. {
  481. BOOL fIsLoaded = FALSE;
  482. HRESULT hr = E_FAIL;
  483. // validate i/p params.
  484. if (NULL == pSsp) {
  485. hr = E_INVALIDARG;
  486. goto Error;
  487. }
  488. // Find out if hinstDll, pfn, and punk are loaded and ok.
  489. if ( (NULL != pSsp->hinstDll) &&
  490. (NULL != pSsp->pfnGetSMimePolicy) &&
  491. (NULL != pSsp->punk) ) {
  492. fIsLoaded = TRUE;
  493. }
  494. Error:
  495. return fIsLoaded;
  496. }
  497. //
  498. // Unload a specified policy.
  499. //
  500. // Input : pSsp
  501. // Output: hr.
  502. //
  503. HRESULT _HrUnloadPolicy(PSMIME_SECURITY_POLICY pSsp)
  504. {
  505. HRESULT hr;
  506. // validate i/p params.
  507. if (NULL == pSsp) {
  508. hr = E_INVALIDARG;
  509. goto Error;
  510. }
  511. // release the object.
  512. if (NULL != pSsp->punk) {
  513. if (! IsBadReadPtr(pSsp->punk, sizeof(IUnknown)) ) {
  514. pSsp->punk->Release();
  515. }
  516. pSsp->punk = NULL;
  517. }
  518. // forget the proc address.
  519. if (NULL != pSsp->pfnGetSMimePolicy) {
  520. pSsp->pfnGetSMimePolicy = NULL;
  521. }
  522. // unload the library.
  523. if (NULL != pSsp->hinstDll) {
  524. FreeLibrary(pSsp->hinstDll);
  525. // there's no point in aborting to error here.
  526. pSsp->hinstDll = NULL;
  527. }
  528. hr = S_OK;
  529. Error:
  530. return hr;
  531. }
  532. //
  533. // (Force) Load a specified policy.
  534. //
  535. // Input: pSsp
  536. // Output: hr
  537. //
  538. HRESULT _HrLoadPolicy(PSMIME_SECURITY_POLICY pSsp)
  539. {
  540. HRESULT hr = E_FAIL;
  541. // validate i/p params.
  542. if (NULL == pSsp) {
  543. hr = E_INVALIDARG;
  544. goto Error;
  545. }
  546. // Unload any partial info we might have.
  547. SideAssert(SUCCEEDED(_HrUnloadPolicy(pSsp)));
  548. // Unload policies (if reqd) to make room for the new one.
  549. hr = _EnsureNewPolicyLoadable();
  550. if (FAILED(hr)) {
  551. goto Error;
  552. }
  553. // Load the dll, get its proc address and get the interface ptr.
  554. Assert(NULL != pSsp->szDllPath);
  555. pSsp->hinstDll = LoadLibraryEx(pSsp->szDllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  556. if (NULL == pSsp->hinstDll) {
  557. hr = E_FAIL;
  558. goto Error;
  559. }
  560. Assert(NULL != pSsp->szFuncName);
  561. pSsp->pfnGetSMimePolicy = (PFNGetSMimePolicy)
  562. GetProcAddress(pSsp->hinstDll, pSsp->szFuncName);
  563. if (NULL == pSsp->pfnGetSMimePolicy) {
  564. hr = E_FAIL;
  565. goto Error;
  566. }
  567. //$ M00BUG: GautamV. Need to pass in an appropriate lcid.
  568. hr = (pSsp->pfnGetSMimePolicy) (0, pSsp->szPolicyOid, GetACP(),
  569. IID_IUnknown, &(pSsp->punk) );
  570. if (FAILED(hr)) {
  571. goto Error;
  572. }
  573. if (NULL == pSsp->punk) {
  574. hr = E_FAIL;
  575. goto Error;
  576. }
  577. // Success.
  578. hr = S_OK;
  579. goto Cleanup;
  580. Error:
  581. // unload the policy module (since we may have partially loaded it).
  582. SideAssert(SUCCEEDED(_HrUnloadPolicy(pSsp)));
  583. Cleanup:
  584. return hr;
  585. }
  586. //
  587. // Ensure that the given policy is loaded.
  588. // Input: pSsp
  589. // Output: pSsp
  590. //
  591. HRESULT _HrEnsurePolicyLoaded(PSMIME_SECURITY_POLICY pSsp)
  592. {
  593. HRESULT hr = E_FAIL;
  594. // validate i/p params.
  595. if (NULL == pSsp) {
  596. hr = E_INVALIDARG;
  597. goto Error;
  598. }
  599. // if it is already loaded, then we are done.
  600. if (_FIsPolicyLoaded(pSsp)) {
  601. hr = S_OK;
  602. goto Cleanup;
  603. }
  604. // else, load the policy.
  605. hr = _HrLoadPolicy(pSsp);
  606. if (FAILED(hr)) {
  607. goto Error;
  608. }
  609. Assert(_FIsPolicyLoaded(pSsp));
  610. hr = S_OK;
  611. goto Cleanup;
  612. Error:
  613. Cleanup:
  614. return hr;
  615. }
  616. //
  617. // Given a oid, find it, ensure that it is loaded and
  618. // return the structure contain its registration info.
  619. //
  620. // Returns:
  621. // S_OK and a valid pSsp
  622. // OR E_INVALIDARG, E_FAIL, etc.
  623. //
  624. HRESULT _HrGetPolicy(LPCSTR szPolicyOid, PSMIME_SECURITY_POLICY *ppSsp)
  625. {
  626. HRESULT hr = E_FAIL;
  627. PSMIME_SECURITY_POLICY pSsp = NULL;
  628. // Validate i/p params and initialize o/p params.
  629. if ( (NULL == szPolicyOid) || (NULL == ppSsp) ) {
  630. hr = E_INVALIDARG;
  631. goto Error;
  632. }
  633. *ppSsp = NULL;
  634. // Load all the registration information for all installed policies.
  635. hr = _HrEnsurePolicyRegInfoLoaded(0);
  636. if (FAILED(hr)) {
  637. goto Error;
  638. }
  639. // find the policy we want.
  640. if (! _FFindPolicy(szPolicyOid, &pSsp)) {
  641. hr = NTE_NOT_FOUND;
  642. goto Error; // not found.
  643. }
  644. // If needed, load the policy.
  645. hr = _HrEnsurePolicyLoaded(pSsp);
  646. if (FAILED(hr)) {
  647. goto Error;
  648. }
  649. // success
  650. *ppSsp = pSsp;
  651. // We increment the usage count, each time someone "gets" a policy.
  652. _IncrPolicyUsage(pSsp);
  653. hr = S_OK;
  654. Error:
  655. return hr;
  656. // Cleanup:
  657. }
  658. //
  659. // SecurityPolicy - QI clone.
  660. // Given a policy oid, finds and loads it, does a
  661. // qi and returns the reqd interface to the policy module.
  662. //
  663. HRESULT HrQueryPolicyInterface(DWORD dwFlags, LPCSTR szPolicyOid, REFIID riid, LPVOID * ppv)
  664. {
  665. HRESULT hr = E_FAIL;
  666. PSMIME_SECURITY_POLICY pSsp = NULL;
  667. // Validate i/p params, initialize o/p params.
  668. if ((NULL == szPolicyOid) || (NULL == ppv)) {
  669. hr = E_INVALIDARG;
  670. goto Error;
  671. }
  672. *ppv = NULL;
  673. // Get the policy.
  674. hr = _HrGetPolicy(szPolicyOid, &pSsp);
  675. if (FAILED(hr)) {
  676. goto Error;
  677. }
  678. Assert(NULL != pSsp->punk);
  679. hr = pSsp->punk->QueryInterface(riid, ppv);
  680. // fall through to Error.
  681. // Cleanup:
  682. Error:
  683. return hr;
  684. }
  685. //
  686. // The allocators we pass in to the Crypto Api's.
  687. //
  688. LPVOID WINAPI SecLabelAlloc(size_t cbSize)
  689. {
  690. return SecPolicyAlloc(cbSize);
  691. }
  692. VOID WINAPI SecLabelFree(LPVOID pv)
  693. {
  694. SecPolicyFree(pv);
  695. }
  696. CRYPT_DECODE_PARA SecLabelDecode = {
  697. sizeof(SecLabelDecode), SecLabelAlloc, SecLabelFree
  698. };
  699. CRYPT_ENCODE_PARA SecLabelEncode = {
  700. sizeof(SecLabelEncode), SecLabelAlloc, SecLabelFree
  701. };
  702. //
  703. // Decode and allocate a label.
  704. //
  705. HRESULT HrDecodeAndAllocLabel(LPBYTE pbLabel, DWORD cbLabel, PSMIME_SECURITY_LABEL *pplabel, DWORD *pcbLabel)
  706. {
  707. BOOL f;
  708. f = CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_SMIME_Security_Label, pbLabel, cbLabel,
  709. CRYPT_ENCODE_ALLOC_FLAG, &SecLabelDecode,
  710. pplabel, pcbLabel);
  711. if (!f) {
  712. return E_FAIL; // HrCryptError();
  713. }
  714. return S_OK;
  715. }
  716. //
  717. // Encode and Allocate a label.
  718. //
  719. HRESULT HrEncodeAndAllocLabel(const PSMIME_SECURITY_LABEL plabel, BYTE ** ppbLabel, DWORD * pcbLabel)
  720. {
  721. BOOL f;
  722. f = CryptEncodeObjectEx(X509_ASN_ENCODING, szOID_SMIME_Security_Label, plabel,
  723. CRYPT_ENCODE_ALLOC_FLAG, &SecLabelEncode,
  724. ppbLabel, pcbLabel);
  725. if (!f) {
  726. return E_FAIL; // HrCryptError();
  727. }
  728. return S_OK;
  729. }
  730. // HrDupLabel
  731. // Duplicate a given label.
  732. //
  733. // Parameters:
  734. // plabel [in]
  735. // pplabel [out]
  736. //
  737. // Returns:
  738. // on success, returns S_OK with a valid label *pplabelOut.
  739. // else returns failure code, (as well as frees *pplabelOut).
  740. //
  741. HRESULT HrDupLabel(PSMIME_SECURITY_LABEL *pplabelOut, const PSMIME_SECURITY_LABEL plabelIn)
  742. {
  743. HRESULT hr = E_FAIL;
  744. ULONG cbLabel = 0;
  745. LPBYTE pbLabel = NULL;
  746. ULONG cbLabel2 = 0;
  747. PSMIME_SECURITY_LABEL plabel = NULL;
  748. // validate i/p parameters.
  749. if ((NULL == plabelIn) || (NULL == pplabelOut)) {
  750. hr = E_INVALIDARG;
  751. goto Error;
  752. }
  753. SecPolicyFree(*pplabelOut);
  754. // encode it.
  755. hr = HrEncodeAndAllocLabel(plabelIn, &pbLabel, &cbLabel);
  756. if (FAILED(hr)) {
  757. goto Error;
  758. }
  759. Assert( (NULL != pbLabel) && (0 < cbLabel) );
  760. // decode it.
  761. hr = HrDecodeAndAllocLabel(pbLabel, cbLabel, &plabel, &cbLabel2);
  762. if (FAILED(hr)) {
  763. goto Error;
  764. }
  765. Assert( (NULL != plabel) && (0 < cbLabel2) );
  766. // succcess.
  767. *pplabelOut = plabel;
  768. hr = S_OK;
  769. Exit:
  770. SecLabelEncode.pfnFree(pbLabel);
  771. return hr;
  772. Error:
  773. SecLabelDecode.pfnFree(plabel);
  774. goto Exit;
  775. }
  776. // FSafeCompareString
  777. // Given two strings, compare them and return TRUE if they are equivalent
  778. // (safe for NULL pointers)
  779. //
  780. // Parameters:
  781. // pwz1 - wide string 1
  782. // pwz2 - wide string 2
  783. //
  784. // Returns:
  785. // TRUE if the strings are equivalent
  786. // FALSE otherwise
  787. //
  788. BOOL FSafeCompareStringW(LPCWSTR pwz1, LPCWSTR pwz2)
  789. {
  790. if (pwz1 == pwz2) {
  791. return TRUE;
  792. }
  793. else if ((NULL == pwz1)||(NULL == pwz2)) {
  794. return FALSE;
  795. }
  796. return (0 == wcscmp(pwz1, pwz2));
  797. }
  798. BOOL FSafeCompareStringA(LPCSTR psz1, LPCSTR psz2)
  799. {
  800. if (psz1 == psz2) {
  801. return TRUE;
  802. }
  803. else if ((NULL == psz1)||(NULL == psz2)) {
  804. return FALSE;
  805. }
  806. return (0 == strcmp(psz1, psz2));
  807. }
  808. // FCompareLabels
  809. // Given the label, return TRUE if the labels are equivalent
  810. //
  811. // Parameters:
  812. // plabel1 [in]
  813. // plabel2 [in]
  814. //
  815. // Returns:
  816. // TRUE if the labels are equivalent
  817. // FALSE otherwise
  818. //
  819. BOOL FCompareLabels(PSMIME_SECURITY_LABEL plabel1, PSMIME_SECURITY_LABEL plabel2)
  820. {
  821. BOOL fEqual = FALSE;
  822. UINT i;
  823. if (plabel1 == plabel2) {
  824. fEqual = TRUE;
  825. goto Exit;
  826. }
  827. if ((NULL == plabel1)||(NULL == plabel2)) {
  828. goto Exit;
  829. }
  830. if ((plabel1->fHasClassification != plabel2->fHasClassification)||
  831. (plabel1->dwClassification != plabel2->dwClassification)||
  832. (plabel1->cCategories != plabel2->cCategories)) {
  833. goto Exit;
  834. }
  835. if (!FSafeCompareStringA(plabel1->pszObjIdSecurityPolicy,
  836. plabel2->pszObjIdSecurityPolicy)||
  837. !FSafeCompareStringW(plabel1->wszPrivacyMark, plabel2->wszPrivacyMark)) {
  838. goto Exit;
  839. }
  840. //$M00REVIEW: What if the categories are in different order???
  841. for (i=0; i<plabel1->cCategories; ++i) {
  842. if ((plabel1->rgCategories[i].Value.cbData !=
  843. plabel2->rgCategories[i].Value.cbData)||
  844. (0 != memcmp(plabel1->rgCategories[i].Value.pbData,
  845. plabel2->rgCategories[i].Value.pbData,
  846. plabel2->rgCategories[i].Value.cbData))) {
  847. goto Exit;
  848. }
  849. }
  850. fEqual = TRUE;
  851. Exit:
  852. return fEqual;
  853. }
  854. // HrGetLabelFromData
  855. // Given the label data, allocate and store the info in a label struct.
  856. //
  857. // Parameters:
  858. // pplabel [out]
  859. // others [in]
  860. //
  861. // Returns:
  862. // on success, returns S_OK with a valid label *pplabel.
  863. // else returns failure code, (as well as frees *pplabel).
  864. //
  865. HRESULT HrGetLabelFromData(PSMIME_SECURITY_LABEL *pplabel, LPCSTR szPolicyOid,
  866. DWORD fHasClassification, DWORD dwClassification, LPCWSTR wszPrivacyMark,
  867. DWORD cCategories, CRYPT_ATTRIBUTE_TYPE_VALUE *rgCategories)
  868. {
  869. HRESULT hr = E_FAIL;
  870. SMIME_SECURITY_LABEL label = {0};
  871. PSMIME_SECURITY_LABEL plabel = NULL;
  872. // validate i/p parameters.
  873. if ((NULL == pplabel) || (NULL == szPolicyOid)) {
  874. hr = E_INVALIDARG;
  875. goto Error;
  876. }
  877. SecPolicyFree(*pplabel);
  878. // set up our temporary label structure.
  879. label.pszObjIdSecurityPolicy = const_cast<LPSTR> (szPolicyOid);
  880. label.fHasClassification = fHasClassification;
  881. if (fHasClassification) {
  882. label.dwClassification = dwClassification;
  883. }
  884. label.wszPrivacyMark = const_cast<LPWSTR> (wszPrivacyMark);
  885. label.cCategories = cCategories;
  886. if (label.cCategories) {
  887. label.rgCategories = rgCategories;
  888. }
  889. // dupe and get a contiguous label structure.
  890. hr = HrDupLabel(&plabel, &label);
  891. if (FAILED(hr)) {
  892. goto Error;
  893. }
  894. // success. set return value.
  895. *pplabel = plabel;
  896. hr = S_OK;
  897. Exit:
  898. return hr;
  899. Error:
  900. SecPolicyFree(plabel);
  901. goto Exit;
  902. }
  903. //
  904. // Utility fn to "Select NO label".
  905. //
  906. // Input: hwndDlg, idc's of controls.
  907. // Output: hr
  908. //
  909. HRESULT HrSetLabelNone(HWND hwndDlg, INT idcPolicyModule, INT idcClassification,
  910. INT idcPrivacyMark, INT idcConfigure)
  911. {
  912. HRESULT hr = E_FAIL;
  913. LONG_PTR iEntry;
  914. // Make sure the policy Module name is <none> and that it is selected.
  915. // First try to select the <none> policy module.
  916. iEntry = SendDlgItemMessageW(hwndDlg, idcPolicyModule,
  917. CB_SELECTSTRING, (WPARAM) (-1),
  918. (LPARAM) (c_wszPolicyNone));
  919. if (CB_ERR == iEntry) {
  920. // Otherwise, add the <none>policy module and select it.
  921. iEntry = SendDlgItemMessageW(hwndDlg, idcPolicyModule,
  922. CB_ADDSTRING, (WPARAM) 0,
  923. (LPARAM) c_wszPolicyNone);
  924. Assert(NULL == SendDlgItemMessage(hwndDlg, idcPolicyModule, CB_GETITEMDATA, iEntry, 0));
  925. iEntry = SendDlgItemMessageW(hwndDlg, idcPolicyModule,
  926. CB_SETCURSEL, (WPARAM) iEntry, 0);
  927. Assert(CB_ERR != iEntry);
  928. }
  929. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LPARAM)iEntry);
  930. // Reset and disable the other controls.
  931. SendDlgItemMessage(hwndDlg, idcClassification, CB_RESETCONTENT, 0, 0);
  932. EnableWindow(GetDlgItem(hwndDlg, idcClassification), FALSE);
  933. EnableWindow(GetDlgItem(hwndDlg, idcClassification+1), FALSE);
  934. SetDlgItemTextW(hwndDlg, idcPrivacyMark, c_PolwszEmpty);
  935. EnableWindow(GetDlgItem(hwndDlg, idcPrivacyMark), FALSE);
  936. EnableWindow(GetDlgItem(hwndDlg, idcPrivacyMark+1), FALSE);
  937. EnableWindow(GetDlgItem(hwndDlg, idcConfigure), FALSE);
  938. hr = S_OK;
  939. return hr;
  940. }
  941. //
  942. // Select a label in the dlg.
  943. //
  944. // Given pssl, sets that label.
  945. // Given pSsp, sets that policy's default info.
  946. // If neither is given, sets label to none.
  947. //
  948. // Input:
  949. // hwndDlg, idc's of the various controls [in].
  950. // pSsp [in, optional] smime security policy.
  951. // plabel [in, optional] security label.
  952. //
  953. // Returns:
  954. // returns either S_OK or an error code.
  955. //
  956. HRESULT HrSetLabel(HWND hwndDlg, INT idcPolicyModule, INT idcClassification,
  957. INT idcPrivacyMark, INT idcConfigure,
  958. PSMIME_SECURITY_POLICY pSsp, PSMIME_SECURITY_LABEL plabel)
  959. {
  960. HRESULT hr = E_FAIL;
  961. ULONG iClassification;
  962. LONG_PTR iEntry;
  963. LPCWSTR wszT = NULL;
  964. DWORD dwPolicyFlags = 0;
  965. ULONG cClassifications = 0;
  966. LPWSTR *pwszClassifications = NULL;
  967. LPDWORD pdwClassifications = NULL;
  968. DWORD dwDefaultClassification = 0;
  969. DWORD dwT = 0;
  970. WCHAR *pwchPrivacyMark = NULL;
  971. BOOL fPrivMarkReadOnly = FALSE;
  972. SpISMimePolicySimpleEdit spspse = NULL;
  973. // Validate the i/p parameters.
  974. if ( ! IsWindow(hwndDlg) ) {
  975. hr = E_INVALIDARG;
  976. goto Exit;
  977. }
  978. // If we are neither given a policy nor a ssl, set the label to <none>.
  979. if ((NULL == pSsp) && (NULL == plabel)) {
  980. hr = S_OK;
  981. goto Error;
  982. }
  983. // if given a label, but not a policy, try to locate & load the policy.
  984. if ((NULL == pSsp) && (NULL != plabel)) {
  985. if (NULL != plabel->pszObjIdSecurityPolicy) {
  986. hr = _HrGetPolicy(plabel->pszObjIdSecurityPolicy, &pSsp);
  987. // if unable to locate/load the policy, set the label to <none>
  988. if (FAILED(hr)) {
  989. goto PolicyNotFoundError;
  990. }
  991. }
  992. else {
  993. hr = S_OK;
  994. goto Error;
  995. }
  996. }
  997. // ensure that the policy is loaded.
  998. hr = _HrEnsurePolicyLoaded(pSsp);
  999. if (FAILED(hr)) {
  1000. goto PolicyNotFoundError;
  1001. }
  1002. Assert(_FIsPolicyLoaded(pSsp) && pSsp->punk);
  1003. hr = pSsp->punk->QueryInterface(IID_ISMimePolicySimpleEdit,
  1004. (LPVOID *) & spspse);
  1005. if (FAILED(hr)) {
  1006. goto PolicyNotFoundError;
  1007. }
  1008. // get the policy flags
  1009. hr = spspse->GetPolicyInfo(0, &dwPolicyFlags);
  1010. if (FAILED(hr)) {
  1011. goto PolicyError;
  1012. }
  1013. // get the classification information.
  1014. hr = spspse->GetClassifications(0, &cClassifications, &pwszClassifications,
  1015. &pdwClassifications,
  1016. &dwDefaultClassification);
  1017. if (FAILED(hr)) {
  1018. goto PolicyError;
  1019. }
  1020. // get the default policy info.
  1021. hr = spspse->GetDefaultPolicyInfo(0, &dwT, &pwchPrivacyMark);
  1022. if (FAILED(hr)) {
  1023. goto PolicyError;
  1024. }
  1025. Assert(dwT == dwDefaultClassification);
  1026. // initialize the classification and privacy strings.
  1027. Assert((NULL == plabel) || (plabel->fHasClassification)); // UI currently doesn't allow one to not specify one.
  1028. SendDlgItemMessage(hwndDlg, idcClassification, CB_RESETCONTENT, 0, 0);
  1029. for (iClassification=0; iClassification<cClassifications; iClassification++) {
  1030. // add the classification strings to the listbox.
  1031. iEntry = SendDlgItemMessageW(hwndDlg, idcClassification, CB_ADDSTRING,
  1032. (WPARAM) 0,
  1033. (LPARAM) pwszClassifications[iClassification]);
  1034. if ((CB_ERR == iEntry) || (CB_ERRSPACE == iEntry)) {
  1035. AssertSz(FALSE, "Unable to add classification string");
  1036. hr = E_OUTOFMEMORY;
  1037. goto Error;
  1038. }
  1039. SendDlgItemMessageW(hwndDlg, idcClassification, CB_SETITEMDATA,
  1040. iEntry, (LPARAM) pdwClassifications[iClassification]);
  1041. // If this classification is the one in the label, remember it.
  1042. if ((NULL != plabel) &&
  1043. (pdwClassifications[iClassification] == plabel->dwClassification)) {
  1044. wszT = pwszClassifications[iClassification];
  1045. }
  1046. // if needed, pick up the default classification string.
  1047. if ((NULL == wszT) && (pdwClassifications[iClassification] == dwDefaultClassification)) {
  1048. wszT = pwszClassifications[iClassification];
  1049. }
  1050. }
  1051. if (NULL == wszT) {
  1052. Assert(FALSE);
  1053. wszT = pwszClassifications[0];
  1054. }
  1055. // select the classification specified in the security label or the default one.
  1056. Assert(wszT != NULL);
  1057. iEntry = SendDlgItemMessageW(hwndDlg, idcClassification, CB_SELECTSTRING,
  1058. (WPARAM) ((int) -1), (LPARAM) wszT);
  1059. Assert(CB_ERR != iEntry);
  1060. // Set the privacy mark string.
  1061. // if given label has one, use it, else if policy provided one, use it,
  1062. wszT = const_cast<LPWSTR>(c_PolwszEmpty);
  1063. if (NULL != plabel) {
  1064. if (NULL != plabel->wszPrivacyMark) {
  1065. wszT = plabel->wszPrivacyMark;
  1066. }
  1067. }
  1068. else if (NULL != pwchPrivacyMark) {
  1069. wszT = pwchPrivacyMark;
  1070. }
  1071. SendDlgItemMessageW(hwndDlg, idcPrivacyMark, WM_SETTEXT, 0,
  1072. (LPARAM)(LPWSTR)wszT);
  1073. #if 0
  1074. iEntry = SelectCBItemWithData(hwndDlg, idcPolicyModule, (DWORD) pSsp);
  1075. iEntry = SendDlgItemMessageW(hwndDlg, idcPolicyModule, CB_SELECTSTRING,
  1076. (WPARAM) ((int) -1), (LPARAM) pSsp);
  1077. AssertSz(CB_ERR != iEntry, "Hey why is this policy module missing from the listbox");
  1078. #else
  1079. iEntry = SendDlgItemMessageW(hwndDlg, idcPolicyModule,
  1080. CB_SELECTSTRING,
  1081. (WPARAM) (-1),
  1082. (LPARAM) pSsp->wszPolicyName);
  1083. AssertSz(CB_ERR != iEntry, "Hey why is this policy module missing from the listbox");
  1084. // SetWindowLongPtr(hwndDlg, GWLP_USERDATA, iEntry);
  1085. #endif
  1086. // enable the controls.
  1087. EnableWindow(GetDlgItem(hwndDlg, idcPolicyModule), TRUE);
  1088. EnableWindow(GetDlgItem(hwndDlg, idcClassification), TRUE);
  1089. EnableWindow(GetDlgItem(hwndDlg, idcClassification+1), TRUE);
  1090. EnableWindow(GetDlgItem(hwndDlg, idcPrivacyMark), TRUE);
  1091. EnableWindow(GetDlgItem(hwndDlg, idcPrivacyMark+1), TRUE);
  1092. // the configure button is enabled if the policy module supports adv config.
  1093. EnableWindow(GetDlgItem(hwndDlg, idcConfigure),
  1094. (dwPolicyFlags & SMIME_POLICY_MODULE_SUPPORTS_ADV_CONFIG));
  1095. // Set the privacy mark as read-only if the policy says so.
  1096. if (dwPolicyFlags & SMIME_POLICY_MODULE_PRIVACYMARK_READONLY) {
  1097. fPrivMarkReadOnly = TRUE;
  1098. }
  1099. SendDlgItemMessage(hwndDlg, idcPrivacyMark, EM_SETREADONLY,
  1100. (WPARAM) fPrivMarkReadOnly, 0);
  1101. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, iEntry);
  1102. hr = S_OK;
  1103. // fall through to Exit;
  1104. Exit:
  1105. SecPolicyFree(pwszClassifications);
  1106. SecPolicyFree(pdwClassifications);
  1107. SecPolicyFree(pwchPrivacyMark);
  1108. return hr;
  1109. Error:
  1110. // Set <none> as the security label.
  1111. SideAssert(SUCCEEDED(HrSetLabelNone(hwndDlg, idcPolicyModule,
  1112. idcClassification, idcPrivacyMark, idcConfigure)));
  1113. goto Exit;
  1114. PolicyError:
  1115. AthMessageBoxW(hwndDlg, MAKEINTRESOURCEW(idsAthenaMail),
  1116. MAKEINTRESOURCEW(idsSecPolicyErr), NULL, MB_OK | MB_ICONSTOP);
  1117. goto Error;
  1118. PolicyNotFoundError:
  1119. AthMessageBoxW(hwndDlg, MAKEINTRESOURCEW(idsAthenaMail),
  1120. MAKEINTRESOURCEW(idsSecPolicyNotFound), NULL, MB_OK | MB_ICONSTOP);
  1121. goto Error;
  1122. }
  1123. //
  1124. // Initialize the Security Labels info.
  1125. // Input:
  1126. // hwndDlg, idc's of controls. [in]
  1127. // LPSEditSecLabelHelper. [in].
  1128. // Returns: TRUE/FALSE
  1129. //
  1130. BOOL SecurityLabelsOnInitDialog(HWND hwndDlg, PSMIME_SECURITY_LABEL plabel,
  1131. INT idcPolicyModule, INT idcClassification,
  1132. INT idcPrivacyMark, INT idcConfigure)
  1133. {
  1134. BOOL fRet = FALSE;
  1135. HRESULT hr = E_FAIL;
  1136. PSMIME_SECURITY_POLICY pSsp = NULL;
  1137. ULONG iSsp;
  1138. LONG_PTR iEntry;
  1139. // Validate i/p params.
  1140. if ( ! IsWindow(hwndDlg) ) {
  1141. fRet = FALSE;
  1142. hr = E_INVALIDARG;
  1143. goto Error;
  1144. }
  1145. SendDlgItemMessage(hwndDlg, idcPrivacyMark, EM_LIMITTEXT,
  1146. (WPARAM)(MAX_PRIVACYMARK_LENGTH-1), 0);
  1147. // Check if any policies are registered.
  1148. if (! FPresentPolicyRegInfo()) {
  1149. // Just set label to none and return.
  1150. hr = S_OK;
  1151. fRet = TRUE;
  1152. goto SetLabelNone;
  1153. }
  1154. // Load the common names in the policy module listbox.
  1155. Assert(s_cSsp && s_rgSsp);
  1156. for (iSsp=0; iSsp<s_cSsp; iSsp++) {
  1157. // Add the policy module string to the lbox. (skip the default policy).
  1158. if (0 == lstrcmpi(s_rgSsp[iSsp].szPolicyOid, c_szDefaultPolicyOid)) {
  1159. continue;
  1160. }
  1161. iEntry = SendDlgItemMessageW(hwndDlg, idcPolicyModule,
  1162. CB_ADDSTRING, (WPARAM) 0,
  1163. (LPARAM) s_rgSsp[iSsp].wszPolicyName);
  1164. Assert(iEntry != CB_ERR);
  1165. SendDlgItemMessage(hwndDlg, idcPolicyModule, CB_SETITEMDATA,
  1166. (WPARAM) iEntry, (LPARAM) &s_rgSsp[iSsp]);
  1167. }
  1168. // If we already have a label in the security profile.
  1169. // then try to initialize that policy and that label.
  1170. if ((NULL != plabel) && (NULL != plabel->pszObjIdSecurityPolicy)) {
  1171. // Next 3 lines for O2KFed
  1172. // Set the label if the function fails it sets the label to None so ignore return
  1173. hr = HrSetLabel(hwndDlg, idcPolicyModule, idcClassification,
  1174. idcPrivacyMark, idcConfigure, pSsp, plabel);
  1175. if (FAILED(hr)) {
  1176. goto Error;
  1177. }
  1178. }
  1179. else {
  1180. // if we aren't given a label to initialize with, then set <none>
  1181. fRet = TRUE;
  1182. goto SetLabelNone;
  1183. }
  1184. fRet = TRUE;
  1185. goto Cleanup;
  1186. Error:
  1187. SetLabelNone:
  1188. hr = HrSetLabelNone(hwndDlg, idcPolicyModule, idcClassification,
  1189. idcPrivacyMark, idcConfigure);
  1190. Assert(SUCCEEDED(hr));
  1191. Cleanup:
  1192. return fRet;
  1193. }
  1194. //
  1195. // Given a null-terminated wide string, returns TRUE if it
  1196. // consists of only white wchars.
  1197. //
  1198. BOOL FIsWhiteStringW(LPWSTR wsz)
  1199. {
  1200. BOOL fRet = TRUE;
  1201. if (NULL != wsz) {
  1202. while (*wsz) {
  1203. if (! iswspace(*wsz) ) {
  1204. fRet = FALSE;
  1205. break;
  1206. }
  1207. wsz++;
  1208. }
  1209. }
  1210. return fRet;
  1211. }
  1212. //
  1213. // HrUpdateLabel
  1214. //
  1215. // Input:
  1216. // hwndDlg, idc's of various controls. [in]
  1217. // PSMIME_SECURITY_LABEL *pplabel [in/out].
  1218. //
  1219. // Updates pplabel with the information in the seclabel dlg.
  1220. //
  1221. HRESULT HrUpdateLabel(HWND hwndDlg, INT idcPolicyModule,
  1222. INT idcClassification, INT idcPrivacyMark,
  1223. INT idcConfigure, PSMIME_SECURITY_LABEL *pplabel)
  1224. {
  1225. HRESULT hr = E_FAIL;
  1226. LONG_PTR iEntry = 0;
  1227. LONG cwchT = 0;
  1228. WCHAR rgwchPrivacyMark[MAX_PRIVACYMARK_LENGTH];
  1229. PSMIME_SECURITY_LABEL plabelT = NULL;
  1230. PSMIME_SECURITY_POLICY pSsp = NULL;
  1231. BOOL fPolicyNotChanged = FALSE;
  1232. LPSTR szPolicyOid = NULL;
  1233. DWORD fHasClassification = FALSE;
  1234. DWORD dwClassification = 0;
  1235. LPWSTR wszPrivacyMark = NULL;
  1236. // validate i/p params.
  1237. if ( ! (hwndDlg && idcPolicyModule && idcClassification &&
  1238. idcPrivacyMark && idcConfigure && pplabel) ) {
  1239. AssertSz(FALSE, "HrUpdateLabel : Invalid args.");
  1240. hr = E_INVALIDARG;
  1241. goto Error;
  1242. }
  1243. if (NULL != *pplabel) {
  1244. hr = HrDupLabel(&plabelT, *pplabel);
  1245. if (FAILED(hr)) {
  1246. goto Error;
  1247. }
  1248. }
  1249. SecPolicyFree(*pplabel);
  1250. // Update with the new information.
  1251. // Get the policy and retrieve its oid.
  1252. iEntry = SendMessage(GetDlgItem(hwndDlg, idcPolicyModule),
  1253. CB_GETCURSEL, 0, 0);
  1254. if (iEntry == CB_ERR) {
  1255. AssertSz(FALSE, "HrUpdateLabel : No label selected");
  1256. goto Error;
  1257. }
  1258. pSsp = (PSMIME_SECURITY_POLICY)
  1259. SendDlgItemMessage(hwndDlg, idcPolicyModule,
  1260. CB_GETITEMDATA, iEntry, 0);
  1261. if (NULL == pSsp) {
  1262. hr = S_OK;
  1263. goto Exit;
  1264. }
  1265. if (NULL == pSsp->szPolicyOid) {
  1266. AssertSz(FALSE, "HrUpdateLabel : Invalid policy oid");
  1267. hr = E_FAIL;
  1268. goto Error;
  1269. }
  1270. szPolicyOid = pSsp->szPolicyOid;
  1271. // set the classification.
  1272. iEntry = SendMessage(GetDlgItem(hwndDlg, idcClassification),
  1273. CB_GETCURSEL, 0, 0);
  1274. if (CB_ERR != iEntry) {
  1275. dwClassification = (DWORD) SendDlgItemMessage(hwndDlg,
  1276. idcClassification, CB_GETITEMDATA, iEntry, 0);
  1277. fHasClassification = TRUE;
  1278. }
  1279. // set the privacy mark.
  1280. cwchT = GetDlgItemTextW(hwndDlg, idcPrivacyMark,
  1281. rgwchPrivacyMark, DimensionOf(rgwchPrivacyMark) - 1);
  1282. rgwchPrivacyMark[DimensionOf(rgwchPrivacyMark) - 1] = '\0'; // null terminate the string.
  1283. if ((0 < cwchT) && !FIsWhiteStringW(rgwchPrivacyMark)) {
  1284. wszPrivacyMark = rgwchPrivacyMark;
  1285. }
  1286. if ( (NULL != plabelT) && (NULL != plabelT->pszObjIdSecurityPolicy) ) {
  1287. fPolicyNotChanged = (0 == lstrcmpi(plabelT->pszObjIdSecurityPolicy, szPolicyOid));
  1288. }
  1289. hr = HrGetLabelFromData(pplabel, szPolicyOid, fHasClassification,
  1290. dwClassification, wszPrivacyMark,
  1291. (fPolicyNotChanged ? plabelT->cCategories : 0),
  1292. (fPolicyNotChanged ? plabelT->rgCategories : NULL) );
  1293. if (FAILED(hr)) {
  1294. goto Error;
  1295. }
  1296. hr = S_OK;
  1297. // fall through to Exit.
  1298. Exit:
  1299. SecLabelDecode.pfnFree(plabelT);
  1300. return hr;
  1301. Error:
  1302. SecPolicyFree(*pplabel);
  1303. goto Exit;
  1304. }
  1305. //
  1306. // OnChangePolicy.
  1307. //
  1308. // Input:
  1309. // hwndDlg. idc's for various controls. [in]
  1310. // iEntry. index of newly selected policy [in]
  1311. // PSMIME_SECURITY_LABEL pplabel [in/out]
  1312. //
  1313. //
  1314. //
  1315. BOOL OnChangePolicy(HWND hwndDlg, LONG_PTR iEntry, INT idcPolicyModule,
  1316. INT idcClassification, INT idcPrivacyMark,
  1317. INT idcConfigure, PSMIME_SECURITY_LABEL *pplabel)
  1318. {
  1319. BOOL fRet = FALSE;
  1320. HRESULT hr = E_FAIL;
  1321. PSMIME_SECURITY_POLICY pSsp = NULL;
  1322. // validate i/p params.
  1323. if (! (hwndDlg && idcPolicyModule && idcClassification &&
  1324. idcPrivacyMark && idcConfigure && pplabel) ) {
  1325. AssertSz(FALSE, "OnChangePolicy : Invalid args");
  1326. hr = E_INVALIDARG;
  1327. goto Error;
  1328. }
  1329. pSsp = (PSMIME_SECURITY_POLICY) SendDlgItemMessage(hwndDlg,
  1330. idcPolicyModule, CB_GETITEMDATA, iEntry, 0);
  1331. hr = HrSetLabel(hwndDlg, idcPolicyModule, idcClassification,
  1332. idcPrivacyMark, idcConfigure, pSsp, NULL);
  1333. if (FAILED(hr)) {
  1334. goto Error;
  1335. }
  1336. // update the label.
  1337. hr = HrUpdateLabel(hwndDlg, idcPolicyModule, idcClassification,
  1338. idcPrivacyMark, idcConfigure, pplabel);
  1339. if (FAILED(hr)) {
  1340. goto Error;
  1341. }
  1342. hr = S_OK;
  1343. // fall through to exit;
  1344. Exit:
  1345. return fRet;
  1346. Error:
  1347. SecPolicyFree(*pplabel);
  1348. goto Exit;
  1349. }
  1350. //
  1351. // Security Labels Dialog Proc.
  1352. //
  1353. // IN/OUT pplabel.
  1354. //
  1355. // Note: The caller is responsible for freeing the *pplabel.
  1356. //
  1357. INT_PTR CALLBACK SecurityLabelsDlgProc(HWND hwndDlg, UINT msg,
  1358. WPARAM wParam, LPARAM lParam)
  1359. {
  1360. HRESULT hr;
  1361. LONG_PTR iEntry;
  1362. LONG_PTR iPrevEntry;
  1363. PSMIME_SECURITY_LABEL *pplabel;
  1364. switch ( msg) {
  1365. case WM_INITDIALOG:
  1366. // Remember the pselh we were handed.
  1367. pplabel = (PSMIME_SECURITY_LABEL *) lParam;
  1368. Assert(NULL !=pplabel);
  1369. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pplabel);
  1370. CenterDialog(hwndDlg);
  1371. return SecurityLabelsOnInitDialog(hwndDlg, *pplabel,
  1372. IDC_POLICY_COMBO /*IDC_SL_POLICYMODULE*/, IDC_CLASSIF_COMB/* IDC_SL_CLASSIFICATION*/,
  1373. IDC_PRIVACY_EDIT/*IDC_SL_PRIVACYMARK*/, IDC_CONFIGURE/*IDC_SL_CONFIGURE*/);
  1374. break;
  1375. case WM_COMMAND:
  1376. pplabel = (PSMIME_SECURITY_LABEL *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  1377. Assert(NULL != pplabel);
  1378. switch (LOWORD(wParam)) {
  1379. case IDC_POLICY_COMBO:
  1380. switch (HIWORD(wParam)) {
  1381. case CBN_SELENDOK:
  1382. case CBN_SELCHANGE:
  1383. iEntry = SendMessage(GetDlgItem(hwndDlg, IDC_POLICY_COMBO),
  1384. CB_GETCURSEL, 0, 0);
  1385. iPrevEntry = GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  1386. if ((iEntry != CB_ERR) && (iEntry != iPrevEntry)) {
  1387. return OnChangePolicy(hwndDlg, iEntry, IDC_POLICY_COMBO,
  1388. IDC_CLASSIF_COMB, IDC_PRIVACY_EDIT,
  1389. IDC_CONFIGURE, pplabel);
  1390. }
  1391. break;
  1392. default:
  1393. return FALSE;
  1394. break;
  1395. }
  1396. break;
  1397. case IDC_CONFIGURE:
  1398. if ((NULL != *pplabel) && (NULL != (*pplabel)->pszObjIdSecurityPolicy)) {
  1399. SpISMimePolicyFullEdit spspfe;
  1400. hr = HrQueryPolicyInterface(0, (*pplabel)->pszObjIdSecurityPolicy,
  1401. IID_ISMimePolicyFullEdit,
  1402. (LPVOID *) &spspfe);
  1403. if (SUCCEEDED(hr)) {
  1404. hr = spspfe->DoAdvancedEdit(0, hwndDlg, pplabel);
  1405. if (SUCCEEDED(hr)) {
  1406. Assert(NULL != *pplabel);
  1407. hr = HrSetLabel(hwndDlg, IDC_POLICY_COMBO,
  1408. IDC_CLASSIF_COMB, IDC_PRIVACY_EDIT,
  1409. IDC_CONFIGURE, NULL, *pplabel);
  1410. Assert(SUCCEEDED(hr));
  1411. }
  1412. }
  1413. }
  1414. break;
  1415. case IDC_CLASSIF_COMB:
  1416. break;
  1417. case IDC_PRIVACY_EDIT:
  1418. break;
  1419. case IDOK:
  1420. hr = HrUpdateLabel(hwndDlg, IDC_POLICY_COMBO,
  1421. IDC_CLASSIF_COMB, IDC_PRIVACY_EDIT,
  1422. IDC_CONFIGURE, pplabel);
  1423. EndDialog(hwndDlg, IDOK);
  1424. break;
  1425. case IDCANCEL:
  1426. EndDialog(hwndDlg, IDCANCEL);
  1427. break;
  1428. default:
  1429. return FALSE;
  1430. break;
  1431. }
  1432. break;
  1433. case WM_CONTEXTMENU:
  1434. case WM_HELP:
  1435. return OnContextHelp(hwndDlg, msg, wParam, lParam, g_rgCtxSecLabel);
  1436. break;
  1437. default:
  1438. return FALSE;
  1439. break;
  1440. }
  1441. return TRUE;
  1442. }
  1443. /////////////////////////////////
  1444. // Misc Label Utility fns.
  1445. /////////////////////////////////
  1446. //
  1447. // "Stringize" a given security label.
  1448. // Note: The caller must free the returned buffer pwszLabel with SecPolicyFree().
  1449. //
  1450. HRESULT HrGetStringizedLabel(PSMIME_SECURITY_LABEL plabel, LPWSTR *pwszLabel)
  1451. {
  1452. HRESULT hr = E_FAIL;
  1453. SpISMimePolicyLabelInfo spspli;
  1454. if ((NULL == plabel) || (NULL == pwszLabel) || (NULL == plabel->pszObjIdSecurityPolicy)) {
  1455. hr = E_INVALIDARG;
  1456. goto Error;
  1457. }
  1458. // Get the required interface to the policy module.
  1459. hr = HrQueryPolicyInterface(0, plabel->pszObjIdSecurityPolicy, IID_ISMimePolicyLabelInfo,
  1460. (LPVOID *) &spspli);
  1461. if (FAILED(hr) || !(spspli)) {
  1462. goto Error;
  1463. }
  1464. // Get the stringized label.
  1465. hr = spspli->GetStringizedLabel(0, plabel, pwszLabel);
  1466. if (FAILED(hr)) {
  1467. goto Error;
  1468. }
  1469. // fall through to ExitHere.
  1470. ExitHere:
  1471. return hr;
  1472. Error:
  1473. goto ExitHere;
  1474. }
  1475. // mbcs version of above fn.
  1476. HRESULT HrGetStringizedLabelA(PSMIME_SECURITY_LABEL plabel, LPSTR *pszLabel)
  1477. {
  1478. HRESULT hr;
  1479. LPSTR pchLabel = NULL;
  1480. LPWSTR pwchLabel = NULL;
  1481. int cch, cchT;
  1482. // validate i/p params.
  1483. if ((NULL == plabel) || (NULL == pszLabel)) {
  1484. hr = E_INVALIDARG;
  1485. goto Error;
  1486. }
  1487. *pszLabel = NULL;
  1488. // get the wide-stringized label.
  1489. hr = HrGetStringizedLabel(plabel, &pwchLabel);
  1490. if (FAILED(hr)) {
  1491. goto Error;
  1492. }
  1493. // conver to an mbcs string.
  1494. cch = WideCharToMultiByte(CP_ACP, 0, pwchLabel, -1, NULL, 0, NULL, NULL);
  1495. if (0 == cch) {
  1496. hr = E_FAIL;
  1497. goto Error;
  1498. }
  1499. pchLabel = (LPSTR) SecPolicyAlloc(cch);
  1500. if (NULL == pchLabel) {
  1501. hr = E_OUTOFMEMORY;
  1502. goto Error;
  1503. }
  1504. cchT = WideCharToMultiByte(CP_ACP, 0, pwchLabel, -1, pchLabel, cch, NULL, NULL);
  1505. Assert(cch == cchT);
  1506. if (0 == cchT) {
  1507. Assert(FALSE);
  1508. hr = E_FAIL;
  1509. goto Error;
  1510. }
  1511. // success.
  1512. *pszLabel = pchLabel;
  1513. hr = S_OK;
  1514. ExitHere:
  1515. SecPolicyFree(pwchLabel);
  1516. return hr;
  1517. Error:
  1518. SecPolicyFree(pchLabel);
  1519. goto ExitHere;
  1520. }
  1521. //
  1522. // Given a policy oid, return its policy flags.
  1523. //
  1524. HRESULT HrGetPolicyFlags(LPSTR szPolicyOid, LPDWORD pdwFlags)
  1525. {
  1526. HRESULT hr = S_OK;
  1527. DWORD dwFlags;
  1528. SpISMimePolicySimpleEdit spspse;
  1529. // validate i/p parameters.
  1530. if ((NULL == szPolicyOid) || (NULL == pdwFlags)) {
  1531. hr = E_INVALIDARG;
  1532. goto Error;
  1533. }
  1534. *pdwFlags = 0;
  1535. // Get the reqd interface.
  1536. hr = HrQueryPolicyInterface(0, szPolicyOid, IID_ISMimePolicySimpleEdit,
  1537. (LPVOID *) &spspse);
  1538. if (FAILED(hr) || !(spspse)) {
  1539. goto Error;
  1540. }
  1541. // Get the policy flags.
  1542. hr = spspse->GetPolicyInfo(0, &dwFlags);
  1543. if (FAILED(hr)) {
  1544. goto Error;
  1545. }
  1546. // success, set return values.
  1547. *pdwFlags = dwFlags;
  1548. Exit:
  1549. return hr;
  1550. Error:
  1551. goto Exit;
  1552. }
  1553. //
  1554. // "Validate" a given security label and sender cert on Edit.
  1555. // The pplabel MAY be modified by the security policy.
  1556. //
  1557. HRESULT HrValidateLabelOnEdit(PSMIME_SECURITY_LABEL *pplabel, HWND hwndParent,
  1558. PCCERT_CONTEXT pccertSign, PCCERT_CONTEXT pccertKeyEx)
  1559. {
  1560. HRESULT hr = E_FAIL;
  1561. DWORD dwFlags = 0;
  1562. SpISMimePolicySimpleEdit spspse;
  1563. SpISMimePolicyValidateSend spspvs;
  1564. // Validate i/p parameters.
  1565. if ((NULL == pplabel) || (NULL == hwndParent) ||
  1566. (NULL == pccertSign) || (NULL == pccertKeyEx)) {
  1567. hr = E_INVALIDARG;
  1568. goto Error;
  1569. }
  1570. if (NULL == *pplabel) {
  1571. hr = S_OK;
  1572. goto Exit;
  1573. }
  1574. // Find out if the policy requires sender/recipient cert validation.
  1575. hr = HrQueryPolicyInterface(0, (*pplabel)->pszObjIdSecurityPolicy,
  1576. IID_ISMimePolicySimpleEdit, (LPVOID *) &spspse);
  1577. if (FAILED(hr) || !(spspse)) {
  1578. goto Error;
  1579. }
  1580. // Query the policy to see if the label is valid.
  1581. hr = spspse->IsLabelValid(0, hwndParent, pplabel);
  1582. if (FAILED(hr) || (NULL == *pplabel)) {
  1583. goto Error;
  1584. }
  1585. // get the policy flags.
  1586. hr = HrGetPolicyFlags((*pplabel)->pszObjIdSecurityPolicy, &dwFlags);
  1587. if (FAILED(hr)) {
  1588. goto Error;
  1589. }
  1590. // Get the required interface to the policy module.
  1591. hr = HrQueryPolicyInterface(0, (*pplabel)->pszObjIdSecurityPolicy, IID_ISMimePolicyValidateSend,
  1592. (LPVOID *) &spspvs);
  1593. if (FAILED(hr) || !(spspvs)) {
  1594. goto Error;
  1595. }
  1596. // verify that the signing cert is allowed by the security policy.
  1597. if ((dwFlags & SMIME_POLICY_MODULE_VALIDATE_SENDER) && (NULL != pccertSign)) {
  1598. hr = spspvs->IsValidLabelSignerCert(0, hwndParent, *pplabel, pccertSign);
  1599. if (FAILED(hr)) {
  1600. goto Error;
  1601. }
  1602. }
  1603. // verify that the recipient certs are allowed by the security policy.
  1604. if ( (dwFlags & SMIME_POLICY_MODULE_VALIDATE_RECIPIENT) &&
  1605. (NULL != pccertKeyEx) ) {
  1606. //$ M00Bug:
  1607. // ValidateRecipient && !pccertKeyEx should probably be an error.
  1608. hr = spspvs->IsValidLabelRecipientCert(0, hwndParent, *pplabel, pccertKeyEx);
  1609. if (FAILED(hr)) {
  1610. goto Error;
  1611. }
  1612. }
  1613. // success. fall through to exit.
  1614. Exit:
  1615. Error:
  1616. return hr;
  1617. }
  1618. //
  1619. // "Validate" a given security label and recipient cert.
  1620. //
  1621. HRESULT HrValidateLabelRecipCert(PSMIME_SECURITY_LABEL plabel, HWND hwndParent,
  1622. PCCERT_CONTEXT pccertRecip)
  1623. {
  1624. HRESULT hr = S_OK;
  1625. DWORD dwFlags;
  1626. SpISMimePolicyValidateSend spspvs;
  1627. // Validate i/p parameters.
  1628. if ((NULL == plabel) || (NULL == pccertRecip)) {
  1629. hr = E_INVALIDARG;
  1630. goto Error;
  1631. }
  1632. // get the policy flags.
  1633. hr = HrGetPolicyFlags(plabel->pszObjIdSecurityPolicy, &dwFlags);
  1634. if (FAILED(hr)) {
  1635. goto Error;
  1636. }
  1637. // see if we need to validate sender.
  1638. if (! (dwFlags & SMIME_POLICY_MODULE_VALIDATE_RECIPIENT) ) {
  1639. // No Recipient validation is required.
  1640. hr = S_OK;
  1641. goto ExitHere;
  1642. }
  1643. // Get the required interface to the policy module.
  1644. hr = HrQueryPolicyInterface(0, plabel->pszObjIdSecurityPolicy, IID_ISMimePolicyValidateSend,
  1645. (LPVOID *) &spspvs);
  1646. if (FAILED(hr) || !(spspvs)) {
  1647. goto Error;
  1648. }
  1649. // verify that the recipient certs are allowed by the security policy.
  1650. hr = spspvs->IsValidLabelRecipientCert(0, hwndParent, plabel, pccertRecip);
  1651. if (FAILED(hr)) {
  1652. goto Error;
  1653. }
  1654. // fall through to ExitHere.
  1655. ExitHere:
  1656. return hr;
  1657. Error:
  1658. goto ExitHere;
  1659. }
  1660. //
  1661. // "Validate" a given security label and signer cert.
  1662. //
  1663. HRESULT HrValidateLabelSignerCert(PSMIME_SECURITY_LABEL plabel, HWND hwndParent,
  1664. PCCERT_CONTEXT pccertSigner)
  1665. {
  1666. HRESULT hr = S_OK;
  1667. DWORD dwFlags;
  1668. SpISMimePolicyValidateSend spspvs;
  1669. // Validate i/p parameters.
  1670. if ((NULL == plabel) || (NULL == pccertSigner)) {
  1671. hr = E_INVALIDARG;
  1672. goto Error;
  1673. }
  1674. // get the policy flags.
  1675. hr = HrGetPolicyFlags(plabel->pszObjIdSecurityPolicy, &dwFlags);
  1676. if (FAILED(hr)) {
  1677. goto Error;
  1678. }
  1679. // see if we need to validate sender.
  1680. if (! (dwFlags & SMIME_POLICY_MODULE_VALIDATE_SENDER) ) {
  1681. // No Recipient validation is required.
  1682. hr = S_OK;
  1683. goto ExitHere;
  1684. }
  1685. // Get the required interface to the policy module.
  1686. hr = HrQueryPolicyInterface(0, plabel->pszObjIdSecurityPolicy, IID_ISMimePolicyValidateSend,
  1687. (LPVOID *) &spspvs);
  1688. if (FAILED(hr) || !(spspvs)) {
  1689. goto Error;
  1690. }
  1691. // verify that the signer certs are allowed by the security policy.
  1692. hr = spspvs->IsValidLabelSignerCert(0, hwndParent, plabel, pccertSigner);
  1693. if (FAILED(hr)) {
  1694. goto Error;
  1695. }
  1696. // fall through to ExitHere.
  1697. ExitHere:
  1698. return hr;
  1699. Error:
  1700. goto ExitHere;
  1701. }
  1702. //
  1703. // "Validate" a given security label and certs.
  1704. //
  1705. HRESULT HrValidateLabelOnSend(PSMIME_SECURITY_LABEL plabel, HWND hwndParent,
  1706. PCCERT_CONTEXT pccertSign,
  1707. ULONG ccertRecip, PCCERT_CONTEXT *rgccertRecip)
  1708. {
  1709. HRESULT hr = S_OK;
  1710. DWORD dwFlags;
  1711. ULONG icert;
  1712. SpISMimePolicyValidateSend spspvs;
  1713. // Validate i/p parameters.
  1714. if ((NULL == plabel) || (NULL == pccertSign)) {
  1715. hr = E_INVALIDARG;
  1716. goto Error;
  1717. }
  1718. // get the policy flags.
  1719. hr = HrGetPolicyFlags(plabel->pszObjIdSecurityPolicy, &dwFlags);
  1720. if (FAILED(hr)) {
  1721. goto Error;
  1722. }
  1723. // see if we need to validate sender and/or recipient(s).
  1724. if (! (dwFlags &
  1725. (SMIME_POLICY_MODULE_VALIDATE_SENDER | SMIME_POLICY_MODULE_VALIDATE_RECIPIENT)) ) {
  1726. // No Sender/Recipient validation is required.
  1727. hr = S_OK;
  1728. goto ExitHere;
  1729. }
  1730. // Get the required interface to the policy module.
  1731. hr = HrQueryPolicyInterface(0, plabel->pszObjIdSecurityPolicy, IID_ISMimePolicyValidateSend,
  1732. (LPVOID *) &spspvs);
  1733. if (FAILED(hr) || !(spspvs)) {
  1734. goto Error;
  1735. }
  1736. // verify that the signing cert is allowed by the security policy.
  1737. if ((dwFlags & SMIME_POLICY_MODULE_VALIDATE_SENDER) && (NULL != pccertSign)) {
  1738. hr = spspvs->IsValidLabelSignerCert(0, hwndParent, plabel, pccertSign);
  1739. if (FAILED(hr)) {
  1740. goto Error;
  1741. }
  1742. }
  1743. // verify that the recipient certs are allowed by the security policy.
  1744. if ( (dwFlags & SMIME_POLICY_MODULE_VALIDATE_RECIPIENT) &&
  1745. (0 < ccertRecip) && (NULL != rgccertRecip) ) {
  1746. for (icert=0; icert<ccertRecip; icert++) {
  1747. hr = spspvs->IsValidLabelRecipientCert(0, hwndParent, plabel, rgccertRecip[icert]);
  1748. if (FAILED(hr)) {
  1749. goto Error;
  1750. }
  1751. }
  1752. }
  1753. // fall through to ExitHere.
  1754. ExitHere:
  1755. return hr;
  1756. Error:
  1757. goto ExitHere;
  1758. }
  1759. //
  1760. // Does the admin force a security label on all S/MIME signed messages?
  1761. //
  1762. BOOL FForceSecurityLabel(void)
  1763. {
  1764. enum EForceLabel {
  1765. FORCELABEL_UNINIT = 0,
  1766. FORCELABEL_YES = 1,
  1767. FORCELABEL_NO = 2 };
  1768. static EForceLabel eForceLabel = FORCELABEL_UNINIT; // uninitialized.
  1769. if (!IsSMIME3Supported()) {
  1770. return FALSE;
  1771. }
  1772. if (eForceLabel == FORCELABEL_UNINIT) {
  1773. DWORD dwDefault = 0;
  1774. DWORD dwForceLabel = 0;
  1775. DWORD dwType;
  1776. LPBYTE pb = (LPBYTE) &dwForceLabel;
  1777. ULONG cb = sizeof(dwForceLabel);
  1778. static const CHAR SzForceSecurityLabel[] = "ForceSecurityLabel";
  1779. // Get our Admin key and check if we should enable Fed Features.
  1780. if (FAILED(HrQueryRegValue(0, (LPSTR) SzForceSecurityLabel, &dwType,
  1781. &pb, &cb, REG_DWORD, (LPBYTE) &dwDefault,
  1782. sizeof(dwDefault))) ||
  1783. (dwType != REG_DWORD) ) {
  1784. dwForceLabel = dwDefault;
  1785. }
  1786. if (dwForceLabel != 0) {
  1787. eForceLabel = FORCELABEL_YES;
  1788. }
  1789. else {
  1790. eForceLabel = FORCELABEL_NO;
  1791. }
  1792. }
  1793. return (eForceLabel == FORCELABEL_YES);
  1794. }
  1795. //
  1796. // Get the label we are forced to us by the admin
  1797. //
  1798. HRESULT HrGetForcedSecurityLabel(PSMIME_SECURITY_LABEL* ppLabel)
  1799. {
  1800. ULONG cb = 0;
  1801. DWORD dwType;
  1802. HRESULT hr = S_OK;
  1803. LPBYTE pbLabel = NULL;
  1804. PSMIME_SECURITY_LABEL pLabel = NULL;
  1805. static const CHAR SzForceSecurityLabelX[] = "ForceSecurityLabelX";
  1806. *ppLabel = NULL;
  1807. if (FForceSecurityLabel()) {
  1808. hr = HrQueryRegValue(0, (LPSTR) SzForceSecurityLabelX, &dwType,
  1809. &pbLabel, &cb, REG_BINARY, NULL, 0);
  1810. if (SUCCEEDED(hr) && (dwType == REG_BINARY)) {
  1811. DWORD cbLabel = 0;
  1812. hr = HrDecodeAndAllocLabel(pbLabel, cb,
  1813. &pLabel, &cbLabel);
  1814. if (SUCCEEDED(hr)) {
  1815. *ppLabel = pLabel;
  1816. pLabel = NULL;
  1817. }
  1818. }
  1819. }
  1820. if (pbLabel != NULL) free(pbLabel);
  1821. SecPolicyFree(pLabel);
  1822. return hr;
  1823. }
  1824. // Given a label, load its policy and show the read-only
  1825. // label info dialog.
  1826. HRESULT HrDisplayLabelInfo(HWND hwndParent, PSMIME_SECURITY_LABEL plabel)
  1827. {
  1828. HRESULT hr = E_FAIL;
  1829. SpISMimePolicyLabelInfo spspli;
  1830. // validate i/p params.
  1831. if ((NULL == plabel) || (NULL == plabel->pszObjIdSecurityPolicy)) {
  1832. hr = E_INVALIDARG;
  1833. goto Error;
  1834. }
  1835. // load the policy and get the reqd interface.
  1836. hr = HrQueryPolicyInterface(0, plabel->pszObjIdSecurityPolicy,
  1837. IID_ISMimePolicyLabelInfo, (LPVOID *) &spspli);
  1838. if (FAILED(hr)) {
  1839. // the policy OR the reqd intf wasn't found.
  1840. goto Error;
  1841. }
  1842. // Display the label-info dlg.
  1843. hr = spspli->DisplayAdvancedLabelProperties(0, hwndParent, plabel);
  1844. if (FAILED(hr)) {
  1845. goto Error;
  1846. }
  1847. // success.
  1848. hr = S_OK;
  1849. Exit:
  1850. return hr;
  1851. Error:
  1852. goto Exit;
  1853. }
  1854. DWORD DetermineCertUsageWithLabel(PCCERT_CONTEXT pccert, PSMIME_SECURITY_LABEL pLabel)
  1855. {
  1856. DWORD dwUsage = 0;
  1857. HRESULT hr;
  1858. Assert(NULL != pccert);
  1859. Assert(NULL != pLabel);
  1860. hr = HrGetCertKeyUsage(pccert, &dwUsage);
  1861. if (S_OK != hr) {
  1862. goto Exit;
  1863. }
  1864. if (0 != (KEY_USAGE_SIGNING & dwUsage)) {
  1865. hr = HrValidateLabelSignerCert(pLabel, NULL, pccert);
  1866. if (FAILED(hr)) {
  1867. dwUsage &= (~KEY_USAGE_SIGNING);
  1868. }
  1869. }
  1870. if (0 != (KEY_USAGE_ENCRYPTION & dwUsage)) {
  1871. hr = HrValidateLabelRecipCert(pLabel, NULL, pccert);
  1872. if (FAILED(hr)) {
  1873. dwUsage &= (~KEY_USAGE_ENCRYPTION);
  1874. }
  1875. }
  1876. Exit:
  1877. return dwUsage;
  1878. }
  1879. // Create default label, if it's not exist
  1880. HRESULT HrGetDefaultLabel(PSMIME_SECURITY_LABEL *pplabel)
  1881. {
  1882. SpISMimePolicySimpleEdit spspse = NULL;
  1883. WCHAR *pwchPrivacyMark = NULL;
  1884. DWORD dwT = 0;
  1885. // Load the info from the registry if reqd.
  1886. HRESULT hr = _HrEnsurePolicyRegInfoLoaded(0);
  1887. if (FAILED(hr)) {
  1888. goto Error;
  1889. }
  1890. // If we haven any installed policies, search for the one we want.
  1891. if (FPresentPolicyRegInfo())
  1892. {
  1893. if(s_cSsp > 0)
  1894. {
  1895. // if it is already loaded, then we are done.
  1896. hr = HrQueryPolicyInterface(0, s_rgSsp[0].szPolicyOid, IID_ISMimePolicySimpleEdit,
  1897. (LPVOID *) & spspse);
  1898. if (FAILED(hr))
  1899. {
  1900. goto Error;
  1901. }
  1902. hr = spspse->GetDefaultPolicyInfo(0, &dwT, &pwchPrivacyMark);
  1903. if (FAILED(hr))
  1904. {
  1905. goto Error;
  1906. }
  1907. hr = HrGetLabelFromData(pplabel,
  1908. s_rgSsp[0].szPolicyOid,
  1909. TRUE, // fHasClassification,
  1910. dwT, // dwClassification,
  1911. pwchPrivacyMark, // wszPrivacyMark,
  1912. 0, NULL);
  1913. }
  1914. }
  1915. Error:
  1916. // Cleanup:
  1917. if(pwchPrivacyMark)
  1918. SecPolicyFree(pwchPrivacyMark);
  1919. #ifdef YST // We don't need to relase spspse, because we use SpISMIME...(ATL does ecerything)
  1920. if(spspse)
  1921. {
  1922. spspse->Release();
  1923. }
  1924. #endif //YST
  1925. return hr;
  1926. }
  1927. // Check label in registry, is not exist then return default label
  1928. HRESULT HrGetOELabel(PSMIME_SECURITY_LABEL *pplabel)
  1929. {
  1930. HRESULT hr = E_FAIL;
  1931. LPWSTR pwchPolicyName = NULL;
  1932. LPWSTR pwchPrivacyMark = NULL;
  1933. LPBYTE pbCategory = NULL;
  1934. CRYPT_ATTRIBUTE_TYPE_VALUE *pCategories = NULL;
  1935. DWORD cCat =0;
  1936. DWORD dwSize;
  1937. TCHAR *pchPolicyName = NULL;
  1938. DWORD dwT = 0;
  1939. if(NULL == pplabel)
  1940. {
  1941. hr = E_INVALIDARG;
  1942. goto Error;
  1943. }
  1944. dwSize = DwGetOption(OPT_POLICYNAME_SIZE);
  1945. // if policy name is not set
  1946. if(dwSize <= 0)
  1947. return(HrGetDefaultLabel(pplabel));
  1948. if(!MemAlloc((LPVOID *)&pchPolicyName, dwSize + 1))
  1949. return(HrGetDefaultLabel(pplabel));
  1950. if( GetOption(OPT_POLICYNAME_DATA, pchPolicyName, dwSize) != dwSize)
  1951. {
  1952. hr = HrGetDefaultLabel(pplabel);
  1953. goto Error;
  1954. }
  1955. // get privacy mark
  1956. dwSize = DwGetOption(OPT_PRIVACYMARK_SIZE);
  1957. if(dwSize > 0)
  1958. {
  1959. if(MemAlloc((LPVOID *)&pwchPrivacyMark, (dwSize * sizeof(WCHAR)) + 1))
  1960. GetOption(OPT_PRIVACYMARK_DATA, pwchPrivacyMark, (dwSize * sizeof(WCHAR)));
  1961. }
  1962. // get category
  1963. dwSize = DwGetOption(OPT_CATEGORY_SIZE);
  1964. if(dwSize > 0)
  1965. {
  1966. if(MemAlloc((LPVOID *)&pbCategory, (dwSize * sizeof(BYTE))))
  1967. {
  1968. if(GetOption(OPT_CATEGORY_DATA, pbCategory, (dwSize * sizeof(BYTE))))
  1969. {
  1970. hr = BinaryToCategories(&pCategories, &cCat, pbCategory);
  1971. if(FAILED(hr))
  1972. goto Error;
  1973. }
  1974. }
  1975. }
  1976. // get classification
  1977. dwSize = DwGetOption(OPT_HAS_CLASSIFICAT);
  1978. if(dwSize > 0)
  1979. dwT = DwGetOption(OPT_CLASSIFICAT_DATA);
  1980. hr = HrGetLabelFromData(pplabel,
  1981. pchPolicyName,
  1982. dwSize, // fHasClassification,
  1983. dwT, // dwClassification,
  1984. pwchPrivacyMark, // wszPrivacyMark,
  1985. cCat,
  1986. pCategories);
  1987. Error:
  1988. if(cCat > 0)
  1989. {
  1990. UINT i;
  1991. for(i = 0; i < cCat; i++)
  1992. {
  1993. MemFree(pCategories[i].pszObjId);
  1994. MemFree(pCategories[i].Value.pbData);
  1995. }
  1996. MemFree(pCategories);
  1997. }
  1998. MemFree(pwchPrivacyMark);
  1999. MemFree(pbCategory);
  2000. MemFree(pchPolicyName);
  2001. return hr;
  2002. }
  2003. // Save label in registry
  2004. HRESULT HrSetOELabel(PSMIME_SECURITY_LABEL plabel)
  2005. {
  2006. HRESULT hr = E_FAIL;
  2007. LPWSTR pwchPolicyName = NULL;
  2008. LPWSTR pwchClassification = NULL;
  2009. LPWSTR pwchPrivacyMark = NULL;
  2010. LPWSTR pwchCategory = NULL;
  2011. DWORD dwSize;
  2012. BYTE *pArray = NULL;
  2013. int Size = 0;
  2014. SpISMimePolicyLabelInfo spspli;
  2015. if ((NULL == plabel) || (NULL == plabel->pszObjIdSecurityPolicy))
  2016. {
  2017. hr = E_INVALIDARG;
  2018. goto Error;
  2019. }
  2020. // Get the required interface to the policy module.
  2021. hr = HrQueryPolicyInterface(0, plabel->pszObjIdSecurityPolicy, IID_ISMimePolicyLabelInfo,
  2022. (LPVOID *) &spspli);
  2023. if (FAILED(hr) || !(spspli))
  2024. {
  2025. goto Error;
  2026. }
  2027. // get label as strings
  2028. hr = spspli->GetLabelAsStrings(0, plabel, &pwchPolicyName, &pwchClassification, &pwchPrivacyMark, &pwchCategory);
  2029. if (FAILED(hr))
  2030. goto Error;
  2031. // save Policy name
  2032. if(pwchPolicyName == NULL)
  2033. {
  2034. Assert(FALSE);
  2035. goto Error;
  2036. }
  2037. dwSize = lstrlen(plabel->pszObjIdSecurityPolicy) + 1;
  2038. SetDwOption(OPT_POLICYNAME_SIZE, dwSize, NULL, 0);
  2039. SetOption(OPT_POLICYNAME_DATA, plabel->pszObjIdSecurityPolicy, dwSize, NULL, 0);
  2040. // Save Classification
  2041. SetDwOption(OPT_HAS_CLASSIFICAT, plabel->fHasClassification, NULL, 0);
  2042. if(plabel->fHasClassification)
  2043. SetDwOption(OPT_CLASSIFICAT_DATA, plabel->dwClassification, NULL, 0);
  2044. // Save Privacy mark
  2045. dwSize = pwchPrivacyMark ? (wcslen(pwchPrivacyMark) + 1) : 0;
  2046. SetDwOption(OPT_PRIVACYMARK_SIZE, dwSize, NULL, 0);
  2047. if(dwSize)
  2048. SetOption(OPT_PRIVACYMARK_DATA, pwchPrivacyMark, dwSize*sizeof(WCHAR), NULL, 0);
  2049. // Save Category
  2050. hr = CategoriesToBinary(plabel, &pArray, &Size);
  2051. if(FAILED(hr))
  2052. goto Error;
  2053. SetDwOption(OPT_CATEGORY_SIZE, Size, NULL, 0);
  2054. if(Size)
  2055. SetOption(OPT_CATEGORY_DATA, pArray, Size*sizeof(BYTE), NULL, 0);
  2056. Error:
  2057. MemFree(pArray);
  2058. SecPolicyFree(pwchPolicyName);
  2059. SecPolicyFree(pwchClassification);
  2060. SecPolicyFree(pwchPrivacyMark);
  2061. SecPolicyFree(pwchCategory);
  2062. return hr;
  2063. }
  2064. //// QueryRegistry
  2065. //
  2066. // Description:
  2067. // This is a common function which should be used to get information from the
  2068. // registry in most cases. It will look in both the HLKM and HKCU registries
  2069. // as requested.
  2070. //
  2071. // M00TODO -- Should check for errors and distinguish between denied and
  2072. // non-existance.
  2073. //
  2074. HRESULT HrQueryRegValue(DWORD dwFlags, LPSTR szRegKey, LPDWORD pdwType,
  2075. LPBYTE * ppbData, LPDWORD pcbData, DWORD dwDefaultType,
  2076. LPBYTE pbDefault, DWORD cbDefault)
  2077. {
  2078. DWORD cbData;
  2079. HKEY hKey;
  2080. DWORD l;
  2081. LPBYTE pbData;
  2082. //
  2083. // Start by getting the Local Machine first if possible
  2084. //
  2085. if (!(dwFlags & QRV_Suppress_HKLM)) {
  2086. //
  2087. // Open the key if it exists
  2088. //
  2089. l = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SzRegSecurity, 0, KEY_QUERY_VALUE,
  2090. &hKey);
  2091. //
  2092. // If we succeed in opening the key, then we will look for the value
  2093. //
  2094. if (l == ERROR_SUCCESS) {
  2095. //
  2096. // If they passed in a size, then we use that as the size, otherwise
  2097. // we need to find the size of the object to be used
  2098. //
  2099. if ((pcbData != NULL) && (*pcbData != 0)) {
  2100. cbData = *pcbData;
  2101. pbData = *ppbData;
  2102. }
  2103. else {
  2104. cbData = 0;
  2105. pbData = NULL;
  2106. }
  2107. //
  2108. // Query for the actual value.
  2109. //
  2110. l = RegQueryValueEx(hKey, szRegKey, NULL, pdwType, pbData, &cbData);
  2111. //
  2112. // On success -- return the value
  2113. //
  2114. if (l == ERROR_SUCCESS) {
  2115. if ((pcbData == NULL) || (*pcbData == 0)) {
  2116. pbData = (LPBYTE) malloc(cbData);
  2117. if (pbData == NULL) {
  2118. RegCloseKey(hKey);
  2119. return E_OUTOFMEMORY;
  2120. }
  2121. l = RegQueryValueEx(hKey, szRegKey, NULL, pdwType, pbData, &cbData);
  2122. RegCloseKey(hKey);
  2123. if (l == ERROR_SUCCESS) {
  2124. if (pcbData != NULL) {
  2125. *pcbData = cbData;
  2126. }
  2127. *ppbData = pbData;
  2128. return S_OK;
  2129. }
  2130. free(pbData);
  2131. return 0x80070000 | l;
  2132. }
  2133. if (pcbData != NULL) {
  2134. *pcbData = cbData;
  2135. }
  2136. RegCloseKey(hKey);
  2137. return S_OK;
  2138. }
  2139. else if (l != ERROR_FILE_NOT_FOUND) {
  2140. RegCloseKey(hKey);
  2141. return 0x80070000 | l;
  2142. }
  2143. RegCloseKey(hKey);
  2144. }
  2145. //
  2146. // If we failed to open the key for some reason other than non-presence,
  2147. // return that error
  2148. //
  2149. else if (l != ERROR_FILE_NOT_FOUND) {
  2150. return 0x80070000 | l;
  2151. }
  2152. //
  2153. // Not found error -- try the next registry object
  2154. //
  2155. }
  2156. //
  2157. // Start by getting the Local Machine first if possible
  2158. //
  2159. if (!(dwFlags & QRV_Suppress_HKCU)) {
  2160. //
  2161. // Open the key if it exists
  2162. //
  2163. l = RegOpenKeyEx(HKEY_CURRENT_USER, SzRegSecurity, 0, KEY_QUERY_VALUE, &hKey);
  2164. //
  2165. // If we succeed in opening the key, then we will look for the value
  2166. //
  2167. if (l == ERROR_SUCCESS) {
  2168. //
  2169. // If they passed in a size, then we use that as the size, otherwise
  2170. // we need to find the size of the object to be used
  2171. //
  2172. if ((pcbData != NULL) && (*pcbData != 0)) {
  2173. cbData = *pcbData;
  2174. pbData = *ppbData;
  2175. }
  2176. else {
  2177. cbData = 0;
  2178. pbData = NULL;
  2179. }
  2180. //
  2181. // Query for the actual value.
  2182. //
  2183. l = RegQueryValueEx(hKey, szRegKey, NULL, pdwType, pbData, &cbData);
  2184. //
  2185. // On success -- return the value
  2186. //
  2187. if (l == ERROR_SUCCESS) {
  2188. if ((pcbData == NULL) || (*pcbData == 0)) {
  2189. pbData = (LPBYTE) malloc(cbData);
  2190. if (pbData == NULL) {
  2191. RegCloseKey(hKey);
  2192. return E_OUTOFMEMORY;
  2193. }
  2194. l = RegQueryValueEx(hKey, szRegKey, NULL, pdwType, pbData, &cbData);
  2195. RegCloseKey(hKey);
  2196. if (l == ERROR_SUCCESS) {
  2197. if (pcbData != NULL) {
  2198. *pcbData = cbData;
  2199. }
  2200. *ppbData = pbData;
  2201. return S_OK;
  2202. }
  2203. free(pbData);
  2204. return 0x80070000 | l;
  2205. }
  2206. if (pcbData != NULL) {
  2207. *pcbData = cbData;
  2208. }
  2209. RegCloseKey(hKey);
  2210. return S_OK;
  2211. }
  2212. else if (l != ERROR_FILE_NOT_FOUND) {
  2213. RegCloseKey(hKey);
  2214. return 0x80070000 | l;
  2215. }
  2216. RegCloseKey(hKey);
  2217. }
  2218. //
  2219. // If we failed to open the key for some reason other than non-presence,
  2220. // return that error
  2221. //
  2222. else if (l != ERROR_FILE_NOT_FOUND) {
  2223. return 0x80070000 | l;
  2224. }
  2225. //
  2226. // Not found error -- try the next registry object
  2227. //
  2228. }
  2229. //
  2230. // No value found, return the default value if it is present
  2231. //
  2232. if (pbDefault == NULL) {
  2233. return 0x80070000 | ERROR_FILE_NOT_FOUND; // Not found
  2234. }
  2235. if ((pcbData != NULL) && (*pcbData != 0) && (cbDefault > *pcbData)) {
  2236. return 0x80070000 | ERROR_MORE_DATA;
  2237. }
  2238. if ((pcbData != NULL) && (*pcbData == 0)) {
  2239. *ppbData = (LPBYTE) malloc(cbDefault);
  2240. if (*ppbData == NULL) {
  2241. return E_OUTOFMEMORY;
  2242. }
  2243. }
  2244. memcpy(*ppbData, pbDefault, cbDefault);
  2245. if (pcbData != NULL) *pcbData = cbDefault;
  2246. if (pdwType != NULL) *pdwType = dwDefaultType;
  2247. return S_OK;
  2248. }
  2249. HRESULT CategoriesToBinary(PSMIME_SECURITY_LABEL plabel, BYTE * *ppArray, int *cbSize)
  2250. {
  2251. HRESULT hr = S_OK;
  2252. int i = 0;
  2253. PCRYPT_ATTRIBUTE_TYPE_VALUE pcatv = NULL;
  2254. LPBYTE pv = NULL;
  2255. int size;
  2256. // pArray = NULL;
  2257. *cbSize = 0;
  2258. if(plabel->cCategories == 0)
  2259. return S_OK;
  2260. // Find size of memory that we need
  2261. size = sizeof(int);
  2262. for (i = 0; i < ((int) plabel->cCategories); i++)
  2263. {
  2264. pcatv = & (plabel->rgCategories[i]);
  2265. size += sizeof(int);
  2266. size += lstrlen(pcatv->pszObjId) + 1;
  2267. size += sizeof(DWORD);
  2268. size += pcatv->Value.cbData;
  2269. }
  2270. Assert(size > sizeof(int));
  2271. // allocate the required memory.
  2272. if(!MemAlloc((LPVOID *)ppArray, size*sizeof(BYTE)))
  2273. return E_OUTOFMEMORY;
  2274. *cbSize = size;
  2275. // construct array
  2276. pv = *ppArray;
  2277. memcpy(pv, &(plabel->cCategories), sizeof(DWORD));
  2278. pv += sizeof(DWORD);
  2279. for (i = 0; i < ((int) plabel->cCategories); i++)
  2280. {
  2281. pcatv = & (plabel->rgCategories[i]);
  2282. size = lstrlen(pcatv->pszObjId);
  2283. memcpy(pv, &size, sizeof(int));
  2284. pv += sizeof(int);
  2285. memcpy(pv, pcatv->pszObjId, size);
  2286. pv += size;
  2287. memcpy(pv, &(pcatv->Value.cbData), sizeof(DWORD));
  2288. pv += sizeof(DWORD);
  2289. memcpy(pv, pcatv->Value.pbData, pcatv->Value.cbData);
  2290. pv += pcatv->Value.cbData;
  2291. }
  2292. return(S_OK);
  2293. }
  2294. HRESULT BinaryToCategories(CRYPT_ATTRIBUTE_TYPE_VALUE ** ppCategories, DWORD *cCat, BYTE * pArray)
  2295. {
  2296. HRESULT hr = S_OK;
  2297. int i = 0;
  2298. PCRYPT_ATTRIBUTE_TYPE_VALUE pcatv = NULL;
  2299. LPBYTE pv = pArray;
  2300. int size;
  2301. DWORD dwVal = 0;
  2302. // Number of elements in array
  2303. memcpy(&dwVal, pv, sizeof(DWORD));
  2304. pv += sizeof(DWORD);
  2305. Assert(dwVal > 0);
  2306. // Allocate memory for array of categories
  2307. if(!MemAlloc((LPVOID *)ppCategories, dwVal*sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE)))
  2308. return E_OUTOFMEMORY;
  2309. *cCat = dwVal;
  2310. // construct array
  2311. for (i = 0; i < ((int) *cCat); i++)
  2312. {
  2313. pcatv = &((*ppCategories)[i]);
  2314. // pszObjId is ANSI string
  2315. memcpy(&size, pv, sizeof(int));
  2316. pv += sizeof(int);
  2317. if(!MemAlloc((LPVOID *)&(pcatv->pszObjId), size*sizeof(CHAR)+1))
  2318. return E_OUTOFMEMORY;
  2319. memcpy(pcatv->pszObjId, pv, size);
  2320. pcatv->pszObjId[size] = '\0';
  2321. pv += size;
  2322. // Value
  2323. memcpy(&dwVal, pv, sizeof(DWORD));
  2324. pv += sizeof(DWORD);
  2325. pcatv->Value.cbData = dwVal;
  2326. if(!MemAlloc((LPVOID *)&(pcatv->Value.pbData), dwVal*sizeof(BYTE)))
  2327. return E_OUTOFMEMORY;
  2328. memcpy(pcatv->Value.pbData, pv, dwVal);
  2329. pv += dwVal;
  2330. }
  2331. return(S_OK);
  2332. }