2 * Copyright 2008 Maarten Lankhorst
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define NONAMELESSUNION
33 #include "cryptuiapi.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg
);
38 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
40 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
44 case DLL_WINE_PREATTACH
:
45 return FALSE
; /* prefer native version */
46 case DLL_PROCESS_ATTACH
:
47 DisableThreadLibraryCalls(hinstDLL
);
49 case DLL_PROCESS_DETACH
:
57 /***********************************************************************
58 * GetFriendlyNameOfCertA (CRYPTDLG.@)
60 DWORD WINAPI
GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert
, LPSTR pchBuffer
,
63 return CertGetNameStringA(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
64 pchBuffer
, cchBuffer
);
67 /***********************************************************************
68 * GetFriendlyNameOfCertW (CRYPTDLG.@)
70 DWORD WINAPI
GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert
, LPWSTR pchBuffer
,
73 return CertGetNameStringW(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
74 pchBuffer
, cchBuffer
);
77 /***********************************************************************
78 * CertTrustInit (CRYPTDLG.@)
80 HRESULT WINAPI
CertTrustInit(CRYPT_PROVIDER_DATA
*pProvData
)
82 HRESULT ret
= S_FALSE
;
84 TRACE("(%p)\n", pProvData
);
86 if (pProvData
->padwTrustStepErrors
&&
87 !pProvData
->padwTrustStepErrors
[TRUSTERROR_STEP_FINAL_WVTINIT
])
89 TRACE("returning %08x\n", ret
);
93 /***********************************************************************
94 * CertTrustCertPolicy (CRYPTDLG.@)
96 BOOL WINAPI
CertTrustCertPolicy(CRYPT_PROVIDER_DATA
*pProvData
, DWORD idxSigner
, BOOL fCounterSignerChain
, DWORD idxCounterSigner
)
98 FIXME("(%p, %d, %s, %d)\n", pProvData
, idxSigner
, fCounterSignerChain
? "TRUE" : "FALSE", idxCounterSigner
);
102 /***********************************************************************
103 * CertTrustCleanup (CRYPTDLG.@)
105 HRESULT WINAPI
CertTrustCleanup(CRYPT_PROVIDER_DATA
*pProvData
)
107 FIXME("(%p)\n", pProvData
);
111 static BOOL
CRYPTDLG_CheckOnlineCRL(void)
113 static const WCHAR policyFlagsKey
[] = { 'S','o','f','t','w','a','r','e',
114 '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
115 'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
116 '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
117 '7','9','3','8','7','e','a','}',0 };
118 static const WCHAR policyFlags
[] = { 'P','o','l','i','c','y','F','l','a',
123 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE
, policyFlagsKey
, 0, KEY_READ
, &key
))
125 DWORD type
, flags
, size
= sizeof(flags
);
127 if (!RegQueryValueExW(key
, policyFlags
, NULL
, &type
, (BYTE
*)&flags
,
128 &size
) && type
== REG_DWORD
)
130 /* The flag values aren't defined in any header I'm aware of, but
131 * this value is well documented on the net.
133 if (flags
& 0x00010000)
141 /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
144 static BOOL
CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert
)
148 DWORD size
= sizeof(hash
);
150 if ((ret
= CertGetCertificateContextProperty(pCert
,
151 CERT_SIGNATURE_HASH_PROP_ID
, hash
, &size
)))
153 static const WCHAR disallowedW
[] =
154 { 'D','i','s','a','l','l','o','w','e','d',0 };
155 HCERTSTORE disallowed
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
,
156 X509_ASN_ENCODING
, 0, CERT_SYSTEM_STORE_CURRENT_USER
, disallowedW
);
160 PCCERT_CONTEXT found
= CertFindCertificateInStore(disallowed
,
161 X509_ASN_ENCODING
, 0, CERT_FIND_SIGNATURE_HASH
, hash
, NULL
);
166 CertFreeCertificateContext(found
);
168 CertCloseStore(disallowed
, 0);
174 static DWORD
CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus
)
176 DWORD confidence
= 0;
179 if (!(errorStatus
& CERT_TRUST_IS_NOT_SIGNATURE_VALID
))
180 confidence
|= CERT_CONFIDENCE_SIG
;
181 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_VALID
))
182 confidence
|= CERT_CONFIDENCE_TIME
;
183 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_NESTED
))
184 confidence
|= CERT_CONFIDENCE_TIMENEST
;
188 static BOOL
CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA
*data
,
189 PCCERT_CHAIN_CONTEXT chain
)
192 CRYPT_PROVIDER_SGNR signer
;
193 PCERT_SIMPLE_CHAIN simpleChain
= chain
->rgpChain
[0];
196 memset(&signer
, 0, sizeof(signer
));
197 signer
.cbStruct
= sizeof(signer
);
198 ret
= data
->psPfns
->pfnAddSgnr2Chain(data
, FALSE
, 0, &signer
);
201 CRYPT_PROVIDER_SGNR
*sgnr
= WTHelperGetProvSignerFromChain(data
, 0,
206 sgnr
->dwError
= simpleChain
->TrustStatus
.dwErrorStatus
;
207 sgnr
->pChainContext
= CertDuplicateCertificateChain(chain
);
211 for (i
= 0; ret
&& i
< simpleChain
->cElement
; i
++)
213 ret
= data
->psPfns
->pfnAddCert2Chain(data
, 0, FALSE
, 0,
214 simpleChain
->rgpElement
[i
]->pCertContext
);
217 CRYPT_PROVIDER_CERT
*cert
;
219 if ((cert
= WTHelperGetProvCertFromChain(sgnr
, i
)))
221 CERT_CHAIN_ELEMENT
*element
= simpleChain
->rgpElement
[i
];
223 cert
->dwConfidence
= CRYPTDLG_TrustStatusToConfidence(
224 element
->TrustStatus
.dwErrorStatus
);
225 cert
->dwError
= element
->TrustStatus
.dwErrorStatus
;
226 cert
->pChainElement
= element
;
236 static CERT_VERIFY_CERTIFICATE_TRUST
*CRYPTDLG_GetVerifyData(
237 CRYPT_PROVIDER_DATA
*data
)
239 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= NULL
;
241 /* This should always be true, but just in case the calling function is
244 if (data
->pWintrustData
->dwUnionChoice
== WTD_CHOICE_BLOB
&&
245 data
->pWintrustData
->u
.pBlob
&& data
->pWintrustData
->u
.pBlob
->cbMemObject
==
246 sizeof(CERT_VERIFY_CERTIFICATE_TRUST
) &&
247 data
->pWintrustData
->u
.pBlob
->pbMemObject
)
248 pCert
= (CERT_VERIFY_CERTIFICATE_TRUST
*)
249 data
->pWintrustData
->u
.pBlob
->pbMemObject
;
253 static HCERTCHAINENGINE
CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST
*cert
)
255 HCERTCHAINENGINE engine
= NULL
;
256 HCERTSTORE root
= NULL
, trust
= NULL
;
259 if (cert
->cRootStores
)
261 root
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
262 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
265 for (i
= 0; i
< cert
->cRootStores
; i
++)
266 CertAddStoreToCollection(root
, cert
->rghstoreRoots
[i
], 0, 0);
269 if (cert
->cTrustStores
)
271 trust
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
272 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
275 for (i
= 0; i
< cert
->cTrustStores
; i
++)
276 CertAddStoreToCollection(trust
, cert
->rghstoreTrust
[i
], 0, 0);
279 if (cert
->cRootStores
|| cert
->cStores
|| cert
->cTrustStores
)
281 CERT_CHAIN_ENGINE_CONFIG config
;
283 memset(&config
, 0, sizeof(config
));
284 config
.cbSize
= sizeof(config
);
285 config
.hRestrictedRoot
= root
;
286 config
.hRestrictedTrust
= trust
;
287 config
.cAdditionalStore
= cert
->cStores
;
288 config
.rghAdditionalStore
= cert
->rghstoreCAs
;
289 config
.hRestrictedRoot
= root
;
290 CertCreateCertificateChainEngine(&config
, &engine
);
291 CertCloseStore(root
, 0);
292 CertCloseStore(trust
, 0);
297 /***********************************************************************
298 * CertTrustFinalPolicy (CRYPTDLG.@)
300 HRESULT WINAPI
CertTrustFinalPolicy(CRYPT_PROVIDER_DATA
*data
)
304 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= CRYPTDLG_GetVerifyData(data
);
306 TRACE("(%p)\n", data
);
308 if (data
->pWintrustData
->dwUIChoice
!= WTD_UI_NONE
)
309 FIXME("unimplemented for UI choice %d\n",
310 data
->pWintrustData
->dwUIChoice
);
314 CERT_CHAIN_PARA chainPara
;
315 HCERTCHAINENGINE engine
;
317 memset(&chainPara
, 0, sizeof(chainPara
));
318 chainPara
.cbSize
= sizeof(chainPara
);
319 if (CRYPTDLG_CheckOnlineCRL())
320 flags
|= CERT_CHAIN_REVOCATION_CHECK_END_CERT
;
321 engine
= CRYPTDLG_MakeEngine(pCert
);
322 GetSystemTimeAsFileTime(&data
->sftSystemTime
);
323 ret
= CRYPTDLG_IsCertAllowed(pCert
->pccert
);
326 PCCERT_CHAIN_CONTEXT chain
;
328 ret
= CertGetCertificateChain(engine
, pCert
->pccert
,
329 &data
->sftSystemTime
, NULL
, &chainPara
, flags
, NULL
, &chain
);
332 if (chain
->cChain
!= 1)
334 FIXME("unimplemented for more than 1 simple chain\n");
335 err
= TRUST_E_SUBJECT_FORM_UNKNOWN
;
338 else if ((ret
= CRYPTDLG_CopyChain(data
, chain
)))
340 if (CertVerifyTimeValidity(&data
->sftSystemTime
,
341 pCert
->pccert
->pCertInfo
))
344 err
= CERT_E_EXPIRED
;
348 err
= TRUST_E_SYSTEM_ERROR
;
349 CertFreeCertificateChain(chain
);
352 err
= TRUST_E_SUBJECT_NOT_TRUSTED
;
354 CertFreeCertificateChainEngine(engine
);
359 err
= TRUST_E_NOSIGNATURE
;
361 /* Oddly, native doesn't set the error in the trust step error location,
362 * probably because this action is more advisory than anything else.
363 * Instead it stores it as the final error, but the function "succeeds" in
367 data
->dwFinalError
= err
;
368 TRACE("returning %d (%08x)\n", S_OK
, data
->dwFinalError
);
372 /***********************************************************************
373 * CertViewPropertiesA (CRYPTDLG.@)
375 BOOL WINAPI
CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A
*info
)
377 CERT_VIEWPROPERTIES_STRUCT_W infoW
;
381 TRACE("(%p)\n", info
);
383 memcpy(&infoW
, info
, sizeof(infoW
));
386 int len
= MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, NULL
, 0);
388 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
391 MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, title
, len
);
392 infoW
.szTitle
= title
;
400 ret
= CertViewPropertiesW(&infoW
);
401 HeapFree(GetProcessHeap(), 0, title
);
406 /***********************************************************************
407 * CertViewPropertiesW (CRYPTDLG.@)
409 BOOL WINAPI
CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W
*info
)
411 static GUID cert_action_verify
= CERT_CERTIFICATE_ACTION_VERIFY
;
412 CERT_VERIFY_CERTIFICATE_TRUST trust
;
413 WINTRUST_BLOB_INFO blob
;
418 TRACE("(%p)\n", info
);
420 memset(&trust
, 0, sizeof(trust
));
421 trust
.cbSize
= sizeof(trust
);
422 trust
.pccert
= info
->pCertContext
;
423 trust
.cRootStores
= info
->cRootStores
;
424 trust
.rghstoreRoots
= info
->rghstoreRoots
;
425 trust
.cStores
= info
->cStores
;
426 trust
.rghstoreCAs
= info
->rghstoreCAs
;
427 trust
.cTrustStores
= info
->cTrustStores
;
428 trust
.rghstoreTrust
= info
->rghstoreTrust
;
429 memset(&blob
, 0, sizeof(blob
));
430 blob
.cbStruct
= sizeof(blob
);
431 blob
.cbMemObject
= sizeof(trust
);
432 blob
.pbMemObject
= (BYTE
*)&trust
;
433 memset(&wtd
, 0, sizeof(wtd
));
434 wtd
.cbStruct
= sizeof(wtd
);
435 wtd
.dwUIChoice
= WTD_UI_NONE
;
436 wtd
.dwUnionChoice
= WTD_CHOICE_BLOB
;
438 wtd
.dwStateAction
= WTD_STATEACTION_VERIFY
;
439 err
= WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
440 if (err
== ERROR_SUCCESS
)
442 CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo
;
443 BOOL propsChanged
= FALSE
;
445 memset(&uiInfo
, 0, sizeof(uiInfo
));
446 uiInfo
.dwSize
= sizeof(uiInfo
);
447 uiInfo
.hwndParent
= info
->hwndParent
;
449 CRYPTUI_DISABLE_ADDTOSTORE
| CRYPTUI_ENABLE_EDITPROPERTIES
;
450 uiInfo
.szTitle
= info
->szTitle
;
451 uiInfo
.pCertContext
= info
->pCertContext
;
452 uiInfo
.cPurposes
= info
->cArrayPurposes
;
453 uiInfo
.rgszPurposes
= (LPCSTR
*)info
->arrayPurposes
;
454 uiInfo
.u
.hWVTStateData
= wtd
.hWVTStateData
;
455 uiInfo
.fpCryptProviderDataTrustedUsage
= TRUE
;
456 uiInfo
.cPropSheetPages
= info
->cArrayPropSheetPages
;
457 uiInfo
.rgPropSheetPages
= info
->arrayPropSheetPages
;
458 uiInfo
.nStartPage
= info
->nStartPage
;
459 ret
= CryptUIDlgViewCertificateW(&uiInfo
, &propsChanged
);
460 wtd
.dwStateAction
= WTD_STATEACTION_CLOSE
;
461 WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
468 /***********************************************************************
469 * DllRegisterServer (CRYPTDLG.@)
471 HRESULT WINAPI
DllRegisterServer(void)
473 static WCHAR cryptdlg
[] = { 'c','r','y','p','t','d','l','g','.',
475 static WCHAR wintrust
[] = { 'w','i','n','t','r','u','s','t','.',
477 static WCHAR certTrustInit
[] = { 'C','e','r','t','T','r','u','s','t',
479 static WCHAR wintrustCertificateTrust
[] = { 'W','i','n','t','r','u','s','t',
480 'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
481 static WCHAR certTrustCertPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
482 'C','e','r','t','P','o','l','i','c','y',0 };
483 static WCHAR certTrustFinalPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
484 'F','i','n','a','l','P','o','l','i','c','y',0 };
485 static WCHAR certTrustCleanup
[] = { 'C','e','r','t','T','r','u','s','t',
486 'C','l','e','a','n','u','p',0 };
487 CRYPT_REGISTER_ACTIONID reg
;
488 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
491 memset(®
, 0, sizeof(reg
));
492 reg
.cbStruct
= sizeof(reg
);
493 reg
.sInitProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
494 reg
.sInitProvider
.pwszDLLName
= cryptdlg
;
495 reg
.sInitProvider
.pwszFunctionName
= certTrustInit
;
496 reg
.sCertificateProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
497 reg
.sCertificateProvider
.pwszDLLName
= wintrust
;
498 reg
.sCertificateProvider
.pwszFunctionName
= wintrustCertificateTrust
;
499 reg
.sCertificatePolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
500 reg
.sCertificatePolicyProvider
.pwszDLLName
= cryptdlg
;
501 reg
.sCertificatePolicyProvider
.pwszFunctionName
= certTrustCertPolicy
;
502 reg
.sFinalPolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
503 reg
.sFinalPolicyProvider
.pwszDLLName
= cryptdlg
;
504 reg
.sFinalPolicyProvider
.pwszFunctionName
= certTrustFinalPolicy
;
505 reg
.sCleanupProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
506 reg
.sCleanupProvider
.pwszDLLName
= cryptdlg
;
507 reg
.sCleanupProvider
.pwszFunctionName
= certTrustCleanup
;
508 if (!WintrustAddActionID(&guid
, WT_ADD_ACTION_ID_RET_RESULT_FLAG
, ®
))
513 /***********************************************************************
514 * DllUnregisterServer (CRYPTDLG.@)
516 HRESULT WINAPI
DllUnregisterServer(void)
518 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
520 WintrustRemoveActionID(&guid
);