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
31 #include "cryptuiapi.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg
);
36 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
38 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
42 case DLL_WINE_PREATTACH
:
43 return FALSE
; /* prefer native version */
44 case DLL_PROCESS_ATTACH
:
45 DisableThreadLibraryCalls(hinstDLL
);
47 case DLL_PROCESS_DETACH
:
55 /***********************************************************************
56 * GetFriendlyNameOfCertA (CRYPTDLG.@)
58 DWORD WINAPI
GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert
, LPSTR pchBuffer
,
61 return CertGetNameStringA(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
62 pchBuffer
, cchBuffer
);
65 /***********************************************************************
66 * GetFriendlyNameOfCertW (CRYPTDLG.@)
68 DWORD WINAPI
GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert
, LPWSTR pchBuffer
,
71 return CertGetNameStringW(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
72 pchBuffer
, cchBuffer
);
75 /***********************************************************************
76 * CertTrustInit (CRYPTDLG.@)
78 HRESULT WINAPI
CertTrustInit(CRYPT_PROVIDER_DATA
*pProvData
)
80 HRESULT ret
= S_FALSE
;
82 TRACE("(%p)\n", pProvData
);
84 if (pProvData
->padwTrustStepErrors
&&
85 !pProvData
->padwTrustStepErrors
[TRUSTERROR_STEP_FINAL_WVTINIT
])
87 TRACE("returning %08x\n", ret
);
91 /***********************************************************************
92 * CertTrustCertPolicy (CRYPTDLG.@)
94 BOOL WINAPI
CertTrustCertPolicy(CRYPT_PROVIDER_DATA
*pProvData
, DWORD idxSigner
, BOOL fCounterSignerChain
, DWORD idxCounterSigner
)
96 FIXME("(%p, %d, %s, %d)\n", pProvData
, idxSigner
, fCounterSignerChain
? "TRUE" : "FALSE", idxCounterSigner
);
100 /***********************************************************************
101 * CertTrustCleanup (CRYPTDLG.@)
103 HRESULT WINAPI
CertTrustCleanup(CRYPT_PROVIDER_DATA
*pProvData
)
105 FIXME("(%p)\n", pProvData
);
109 static BOOL
CRYPTDLG_CheckOnlineCRL(void)
111 static const WCHAR policyFlagsKey
[] = { 'S','o','f','t','w','a','r','e',
112 '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
113 'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
114 '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
115 '7','9','3','8','7','e','a','}',0 };
116 static const WCHAR policyFlags
[] = { 'P','o','l','i','c','y','F','l','a',
121 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE
, policyFlagsKey
, 0, KEY_READ
, &key
))
123 DWORD type
, flags
, size
= sizeof(flags
);
125 if (!RegQueryValueExW(key
, policyFlags
, NULL
, &type
, (BYTE
*)&flags
,
126 &size
) && type
== REG_DWORD
)
128 /* The flag values aren't defined in any header I'm aware of, but
129 * this value is well documented on the net.
131 if (flags
& 0x00010000)
139 /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
142 static BOOL
CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert
)
146 DWORD size
= sizeof(hash
);
148 if ((ret
= CertGetCertificateContextProperty(pCert
,
149 CERT_SIGNATURE_HASH_PROP_ID
, hash
, &size
)))
151 static const WCHAR disallowedW
[] =
152 { 'D','i','s','a','l','l','o','w','e','d',0 };
153 HCERTSTORE disallowed
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
,
154 X509_ASN_ENCODING
, 0, CERT_SYSTEM_STORE_CURRENT_USER
, disallowedW
);
158 PCCERT_CONTEXT found
= CertFindCertificateInStore(disallowed
,
159 X509_ASN_ENCODING
, 0, CERT_FIND_SIGNATURE_HASH
, hash
, NULL
);
164 CertFreeCertificateContext(found
);
166 CertCloseStore(disallowed
, 0);
172 static DWORD
CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus
)
174 DWORD confidence
= 0;
177 if (!(errorStatus
& CERT_TRUST_IS_NOT_SIGNATURE_VALID
))
178 confidence
|= CERT_CONFIDENCE_SIG
;
179 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_VALID
))
180 confidence
|= CERT_CONFIDENCE_TIME
;
181 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_NESTED
))
182 confidence
|= CERT_CONFIDENCE_TIMENEST
;
186 static BOOL
CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA
*data
,
187 PCCERT_CHAIN_CONTEXT chain
)
190 CRYPT_PROVIDER_SGNR signer
;
191 PCERT_SIMPLE_CHAIN simpleChain
= chain
->rgpChain
[0];
194 memset(&signer
, 0, sizeof(signer
));
195 signer
.cbStruct
= sizeof(signer
);
196 ret
= data
->psPfns
->pfnAddSgnr2Chain(data
, FALSE
, 0, &signer
);
199 CRYPT_PROVIDER_SGNR
*sgnr
= WTHelperGetProvSignerFromChain(data
, 0,
204 sgnr
->dwError
= simpleChain
->TrustStatus
.dwErrorStatus
;
205 sgnr
->pChainContext
= CertDuplicateCertificateChain(chain
);
209 for (i
= 0; ret
&& i
< simpleChain
->cElement
; i
++)
211 ret
= data
->psPfns
->pfnAddCert2Chain(data
, 0, FALSE
, 0,
212 simpleChain
->rgpElement
[i
]->pCertContext
);
215 CRYPT_PROVIDER_CERT
*cert
;
217 if ((cert
= WTHelperGetProvCertFromChain(sgnr
, i
)))
219 CERT_CHAIN_ELEMENT
*element
= simpleChain
->rgpElement
[i
];
221 cert
->dwConfidence
= CRYPTDLG_TrustStatusToConfidence(
222 element
->TrustStatus
.dwErrorStatus
);
223 cert
->dwError
= element
->TrustStatus
.dwErrorStatus
;
224 cert
->pChainElement
= element
;
234 static CERT_VERIFY_CERTIFICATE_TRUST
*CRYPTDLG_GetVerifyData(
235 CRYPT_PROVIDER_DATA
*data
)
237 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= NULL
;
239 /* This should always be true, but just in case the calling function is
242 if (data
->pWintrustData
->dwUnionChoice
== WTD_CHOICE_BLOB
&&
243 data
->pWintrustData
->pBlob
&& data
->pWintrustData
->pBlob
->cbMemObject
==
244 sizeof(CERT_VERIFY_CERTIFICATE_TRUST
) &&
245 data
->pWintrustData
->pBlob
->pbMemObject
)
246 pCert
= (CERT_VERIFY_CERTIFICATE_TRUST
*)
247 data
->pWintrustData
->pBlob
->pbMemObject
;
251 static HCERTCHAINENGINE
CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST
*cert
)
253 HCERTCHAINENGINE engine
= NULL
;
254 HCERTSTORE root
= NULL
, trust
= NULL
;
257 if (cert
->cRootStores
)
259 root
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
260 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
263 for (i
= 0; i
< cert
->cRootStores
; i
++)
264 CertAddStoreToCollection(root
, cert
->rghstoreRoots
[i
], 0, 0);
267 if (cert
->cTrustStores
)
269 trust
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
270 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
273 for (i
= 0; i
< cert
->cTrustStores
; i
++)
274 CertAddStoreToCollection(trust
, cert
->rghstoreTrust
[i
], 0, 0);
277 if (cert
->cRootStores
|| cert
->cStores
|| cert
->cTrustStores
)
279 CERT_CHAIN_ENGINE_CONFIG config
;
281 memset(&config
, 0, sizeof(config
));
282 config
.cbSize
= sizeof(config
);
283 config
.hRestrictedRoot
= root
;
284 config
.hRestrictedTrust
= trust
;
285 config
.cAdditionalStore
= cert
->cStores
;
286 config
.rghAdditionalStore
= cert
->rghstoreCAs
;
287 config
.hRestrictedRoot
= root
;
288 CertCreateCertificateChainEngine(&config
, &engine
);
289 CertCloseStore(root
, 0);
290 CertCloseStore(trust
, 0);
295 /***********************************************************************
296 * CertTrustFinalPolicy (CRYPTDLG.@)
298 HRESULT WINAPI
CertTrustFinalPolicy(CRYPT_PROVIDER_DATA
*data
)
302 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= CRYPTDLG_GetVerifyData(data
);
304 TRACE("(%p)\n", data
);
306 if (data
->pWintrustData
->dwUIChoice
!= WTD_UI_NONE
)
307 FIXME("unimplemented for UI choice %d\n",
308 data
->pWintrustData
->dwUIChoice
);
312 CERT_CHAIN_PARA chainPara
;
313 HCERTCHAINENGINE engine
;
315 memset(&chainPara
, 0, sizeof(chainPara
));
316 chainPara
.cbSize
= sizeof(chainPara
);
317 if (CRYPTDLG_CheckOnlineCRL())
318 flags
|= CERT_CHAIN_REVOCATION_CHECK_END_CERT
;
319 engine
= CRYPTDLG_MakeEngine(pCert
);
320 GetSystemTimeAsFileTime(&data
->sftSystemTime
);
321 ret
= CRYPTDLG_IsCertAllowed(pCert
->pccert
);
324 PCCERT_CHAIN_CONTEXT chain
;
326 ret
= CertGetCertificateChain(engine
, pCert
->pccert
,
327 &data
->sftSystemTime
, NULL
, &chainPara
, flags
, NULL
, &chain
);
330 if (chain
->cChain
!= 1)
332 FIXME("unimplemented for more than 1 simple chain\n");
333 err
= TRUST_E_SUBJECT_FORM_UNKNOWN
;
336 else if ((ret
= CRYPTDLG_CopyChain(data
, chain
)))
338 if (CertVerifyTimeValidity(&data
->sftSystemTime
,
339 pCert
->pccert
->pCertInfo
))
342 err
= CERT_E_EXPIRED
;
346 err
= TRUST_E_SYSTEM_ERROR
;
347 CertFreeCertificateChain(chain
);
350 err
= TRUST_E_SUBJECT_NOT_TRUSTED
;
352 CertFreeCertificateChainEngine(engine
);
357 err
= TRUST_E_NOSIGNATURE
;
359 /* Oddly, native doesn't set the error in the trust step error location,
360 * probably because this action is more advisory than anything else.
361 * Instead it stores it as the final error, but the function "succeeds" in
365 data
->dwFinalError
= err
;
366 TRACE("returning %d (%08x)\n", S_OK
, data
->dwFinalError
);
370 /***********************************************************************
371 * CertViewPropertiesA (CRYPTDLG.@)
373 BOOL WINAPI
CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A
*info
)
375 CERT_VIEWPROPERTIES_STRUCT_W infoW
;
379 TRACE("(%p)\n", info
);
381 memcpy(&infoW
, info
, sizeof(infoW
));
384 int len
= MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, NULL
, 0);
386 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
389 MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, title
, len
);
390 infoW
.szTitle
= title
;
398 ret
= CertViewPropertiesW(&infoW
);
399 HeapFree(GetProcessHeap(), 0, title
);
404 /***********************************************************************
405 * CertViewPropertiesW (CRYPTDLG.@)
407 BOOL WINAPI
CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W
*info
)
409 static GUID cert_action_verify
= CERT_CERTIFICATE_ACTION_VERIFY
;
410 CERT_VERIFY_CERTIFICATE_TRUST trust
;
411 WINTRUST_BLOB_INFO blob
;
416 TRACE("(%p)\n", info
);
418 memset(&trust
, 0, sizeof(trust
));
419 trust
.cbSize
= sizeof(trust
);
420 trust
.pccert
= info
->pCertContext
;
421 trust
.cRootStores
= info
->cRootStores
;
422 trust
.rghstoreRoots
= info
->rghstoreRoots
;
423 trust
.cStores
= info
->cStores
;
424 trust
.rghstoreCAs
= info
->rghstoreCAs
;
425 trust
.cTrustStores
= info
->cTrustStores
;
426 trust
.rghstoreTrust
= info
->rghstoreTrust
;
427 memset(&blob
, 0, sizeof(blob
));
428 blob
.cbStruct
= sizeof(blob
);
429 blob
.cbMemObject
= sizeof(trust
);
430 blob
.pbMemObject
= (BYTE
*)&trust
;
431 memset(&wtd
, 0, sizeof(wtd
));
432 wtd
.cbStruct
= sizeof(wtd
);
433 wtd
.dwUIChoice
= WTD_UI_NONE
;
434 wtd
.dwUnionChoice
= WTD_CHOICE_BLOB
;
436 wtd
.dwStateAction
= WTD_STATEACTION_VERIFY
;
437 err
= WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
438 if (err
== ERROR_SUCCESS
)
440 CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo
;
441 BOOL propsChanged
= FALSE
;
443 memset(&uiInfo
, 0, sizeof(uiInfo
));
444 uiInfo
.dwSize
= sizeof(uiInfo
);
445 uiInfo
.hwndParent
= info
->hwndParent
;
447 CRYPTUI_DISABLE_ADDTOSTORE
| CRYPTUI_ENABLE_EDITPROPERTIES
;
448 uiInfo
.szTitle
= info
->szTitle
;
449 uiInfo
.pCertContext
= info
->pCertContext
;
450 uiInfo
.cPurposes
= info
->cArrayPurposes
;
451 uiInfo
.rgszPurposes
= (LPCSTR
*)info
->arrayPurposes
;
452 uiInfo
.hWVTStateData
= wtd
.hWVTStateData
;
453 uiInfo
.fpCryptProviderDataTrustedUsage
= TRUE
;
454 uiInfo
.cPropSheetPages
= info
->cArrayPropSheetPages
;
455 uiInfo
.rgPropSheetPages
= info
->arrayPropSheetPages
;
456 uiInfo
.nStartPage
= info
->nStartPage
;
457 ret
= CryptUIDlgViewCertificateW(&uiInfo
, &propsChanged
);
458 wtd
.dwStateAction
= WTD_STATEACTION_CLOSE
;
459 WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
466 /***********************************************************************
467 * DllRegisterServer (CRYPTDLG.@)
469 HRESULT WINAPI
DllRegisterServer(void)
471 static WCHAR cryptdlg
[] = { 'c','r','y','p','t','d','l','g','.',
473 static WCHAR wintrust
[] = { 'w','i','n','t','r','u','s','t','.',
475 static WCHAR certTrustInit
[] = { 'C','e','r','t','T','r','u','s','t',
477 static WCHAR wintrustCertificateTrust
[] = { 'W','i','n','t','r','u','s','t',
478 'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
479 static WCHAR certTrustCertPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
480 'C','e','r','t','P','o','l','i','c','y',0 };
481 static WCHAR certTrustFinalPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
482 'F','i','n','a','l','P','o','l','i','c','y',0 };
483 static WCHAR certTrustCleanup
[] = { 'C','e','r','t','T','r','u','s','t',
484 'C','l','e','a','n','u','p',0 };
485 CRYPT_REGISTER_ACTIONID reg
;
486 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
489 memset(®
, 0, sizeof(reg
));
490 reg
.cbStruct
= sizeof(reg
);
491 reg
.sInitProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
492 reg
.sInitProvider
.pwszDLLName
= cryptdlg
;
493 reg
.sInitProvider
.pwszFunctionName
= certTrustInit
;
494 reg
.sCertificateProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
495 reg
.sCertificateProvider
.pwszDLLName
= wintrust
;
496 reg
.sCertificateProvider
.pwszFunctionName
= wintrustCertificateTrust
;
497 reg
.sCertificatePolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
498 reg
.sCertificatePolicyProvider
.pwszDLLName
= cryptdlg
;
499 reg
.sCertificatePolicyProvider
.pwszFunctionName
= certTrustCertPolicy
;
500 reg
.sFinalPolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
501 reg
.sFinalPolicyProvider
.pwszDLLName
= cryptdlg
;
502 reg
.sFinalPolicyProvider
.pwszFunctionName
= certTrustFinalPolicy
;
503 reg
.sCleanupProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
504 reg
.sCleanupProvider
.pwszDLLName
= cryptdlg
;
505 reg
.sCleanupProvider
.pwszFunctionName
= certTrustCleanup
;
506 if (!WintrustAddActionID(&guid
, WT_ADD_ACTION_ID_RET_RESULT_FLAG
, ®
))
511 /***********************************************************************
512 * DllUnregisterServer (CRYPTDLG.@)
514 HRESULT WINAPI
DllUnregisterServer(void)
516 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
518 WintrustRemoveActionID(&guid
);