ReactOS 0.4.15-dev-7788-g1ad9096
chain.c
Go to the documentation of this file.
1/*
2 * Copyright 2006 Juan Lang
3 *
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.
8 *
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.
13 *
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
17 *
18 */
19#include <stdarg.h>
20#define NONAMELESSUNION
21#include "windef.h"
22#include "winbase.h"
23#define CERT_CHAIN_PARA_HAS_EXTRA_FIELDS
24#define CERT_REVOCATION_PARA_HAS_EXTRA_FIELDS
25#include "wincrypt.h"
26#include "wininet.h"
27#include "wine/debug.h"
28#include "wine/unicode.h"
29#include "crypt32_private.h"
30
33
34#define DEFAULT_CYCLE_MODULUS 7
35
36/* This represents a subset of a certificate chain engine: it doesn't include
37 * the "hOther" store described by MSDN, because I'm not sure how that's used.
38 * It also doesn't include the "hTrust" store, because I don't yet implement
39 * CTLs or complex certificate chains.
40 */
42{
51
53 DWORD cStores, HCERTSTORE *stores)
54{
55 DWORD i;
56
57 for (i = 0; i < cStores; i++)
59}
60
61static inline void CRYPT_CloseStores(DWORD cStores, HCERTSTORE *stores)
62{
63 DWORD i;
64
65 for (i = 0; i < cStores; i++)
66 CertCloseStore(stores[i], 0);
67}
68
69static const WCHAR rootW[] = { 'R','o','o','t',0 };
70
71/* Finds cert in store by comparing the cert's hashes. */
74{
75 PCCERT_CONTEXT matching = NULL;
76 BYTE hash[20];
77 DWORD size = sizeof(hash);
78
80 {
81 CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
82
83 matching = CertFindCertificateInStore(store, cert->dwCertEncodingType,
85 }
86 return matching;
87}
88
90{
91 BOOL ret = TRUE;
92
93 if (store)
94 {
97
98 do {
100 if (cert)
101 {
102 if (!(check = CRYPT_FindCertInStore(rootStore, cert)))
103 ret = FALSE;
104 else
106 }
107 } while (ret && cert);
108 if (cert)
110 CertCloseStore(rootStore, 0);
111 }
112 return ret;
113}
114
116{
118 HCERTSTORE worldStores[4];
119
120 static const WCHAR caW[] = { 'C','A',0 };
121 static const WCHAR myW[] = { 'M','y',0 };
122 static const WCHAR trustW[] = { 'T','r','u','s','t',0 };
123
124 if(!root) {
125 if(config->cbSize >= sizeof(CERT_CHAIN_ENGINE_CONFIG) && config->hExclusiveRoot)
126 root = CertDuplicateStore(config->hExclusiveRoot);
127 else if (config->hRestrictedRoot)
128 root = CertDuplicateStore(config->hRestrictedRoot);
129 else
130 root = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, rootW);
131 if(!root)
132 return NULL;
133 }
134
135 engine = CryptMemAlloc(sizeof(CertificateChainEngine));
136 if(!engine) {
138 return NULL;
139 }
140
141 engine->ref = 1;
142 engine->hRoot = root;
144 worldStores[0] = CertDuplicateStore(engine->hRoot);
145 worldStores[1] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, caW);
146 worldStores[2] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, myW);
147 worldStores[3] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, trustW);
148
149 CRYPT_AddStoresToCollection(engine->hWorld, ARRAY_SIZE(worldStores), worldStores);
150 CRYPT_AddStoresToCollection(engine->hWorld, config->cAdditionalStore, config->rghAdditionalStore);
151 CRYPT_CloseStores(ARRAY_SIZE(worldStores), worldStores);
152
153 engine->dwFlags = config->dwFlags;
154 engine->dwUrlRetrievalTimeout = config->dwUrlRetrievalTimeout;
155 engine->MaximumCachedCertificates = config->MaximumCachedCertificates;
156 if(config->CycleDetectionModulus)
157 engine->CycleDetectionModulus = config->CycleDetectionModulus;
158 else
160
161 return engine;
162}
163
165
167{
168 const CERT_CHAIN_ENGINE_CONFIG config = { sizeof(config) };
169
171 if(!allow_default)
172 return NULL;
173
174 if(!default_cu_engine) {
179 }
180
181 return default_cu_engine;
182 }
183
185 if(!allow_default)
186 return NULL;
187
188 if(!default_lm_engine) {
193 }
194
195 return default_lm_engine;
196 }
197
199}
200
202{
203 if(!engine || InterlockedDecrement(&engine->ref))
204 return;
205
206 CertCloseStore(engine->hWorld, 0);
207 CertCloseStore(engine->hRoot, 0);
208 CryptMemFree(engine);
209}
210
212{
224
227{
228 BOOL ret;
229
230 TRACE("(%p, %p)\n", pConfig, phChainEngine);
231
233 && pConfig->cbSize != sizeof(CERT_CHAIN_ENGINE_CONFIG))
234 {
236 return FALSE;
237 }
239 if (!ret)
240 {
242 return FALSE;
243 }
244
246 return *phChainEngine != NULL;
247}
248
250{
251 TRACE("(%p)\n", hChainEngine);
253}
254
256{
259}
260
261typedef struct _CertificateChain
262{
267
269{
270 DWORD size, status = 0;
272 BOOL ret;
273
275 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
276 {
278
279 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
280 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData,
282 &info, &size);
283 if (ret)
284 {
285 if (info->AuthorityCertIssuer.cAltEntry &&
286 info->AuthorityCertSerialNumber.cbData)
287 {
288 PCERT_ALT_NAME_ENTRY directoryName = NULL;
289 DWORD i;
290
291 for (i = 0; !directoryName &&
292 i < info->AuthorityCertIssuer.cAltEntry; i++)
293 if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice
295 directoryName =
296 &info->AuthorityCertIssuer.rgAltEntry[i];
297 if (directoryName)
298 {
299 if (CertCompareCertificateName(cert->dwCertEncodingType, &directoryName->u.DirectoryName, &cert->pCertInfo->Issuer)
300 && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber, &cert->pCertInfo->SerialNumber))
302 }
303 else
304 {
305 FIXME("no supported name type in authority key id2\n");
306 ret = FALSE;
307 }
308 }
309 else if (info->KeyId.cbData)
310 {
313 if (ret && size == info->KeyId.cbData)
314 {
316
317 if (buf)
318 {
320 if (!memcmp(buf, info->KeyId.pbData, size))
323 }
324 }
325 }
327 }
328 }
330 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
331 {
333
334 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
335 X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData,
337 &info, &size);
338 if (ret)
339 {
340 if (info->CertIssuer.cbData && info->CertSerialNumber.cbData)
341 {
342 if (CertCompareCertificateName(cert->dwCertEncodingType, &info->CertIssuer, &cert->pCertInfo->Issuer)
343 && CertCompareIntegerBlob(&info->CertSerialNumber, &cert->pCertInfo->SerialNumber))
345 }
346 else if (info->KeyId.cbData)
347 {
350 if (ret && size == info->KeyId.cbData)
351 {
353
354 if (buf)
355 {
358 if (!memcmp(buf, info->KeyId.pbData, size))
361 }
362 }
363 }
365 }
366 }
367 else
368 if (CertCompareCertificateName(cert->dwCertEncodingType, &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer))
370
371 if (status)
373
374 return status;
375}
376
378{
379 CertFreeCertificateContext(element->pCertContext);
381}
382
384{
385 DWORD i, j, cyclicCertIndex = 0;
386
387 /* O(n^2) - I don't think there's a faster way */
388 for (i = 0; !cyclicCertIndex && i < chain->cElement; i++)
389 for (j = i + 1; !cyclicCertIndex && j < chain->cElement; j++)
391 chain->rgpElement[i]->pCertContext->pCertInfo,
392 chain->rgpElement[j]->pCertContext->pCertInfo))
393 cyclicCertIndex = j;
394 if (cyclicCertIndex)
395 {
396 chain->rgpElement[cyclicCertIndex]->TrustStatus.dwErrorStatus
398 /* Release remaining certs */
399 for (i = cyclicCertIndex + 1; i < chain->cElement; i++)
400 CRYPT_FreeChainElement(chain->rgpElement[i]);
401 /* Truncate chain */
402 chain->cElement = cyclicCertIndex + 1;
403 }
404}
405
406/* Checks whether the chain is cyclic by examining the last element's status */
408{
409 if (chain->cElement)
410 return chain->rgpElement[chain->cElement - 1]->TrustStatus.dwErrorStatus
412 else
413 return FALSE;
414}
415
416static inline void CRYPT_CombineTrustStatus(CERT_TRUST_STATUS *chainStatus,
417 const CERT_TRUST_STATUS *elementStatus)
418{
419 /* Any error that applies to an element also applies to a chain.. */
420 chainStatus->dwErrorStatus |= elementStatus->dwErrorStatus;
421 /* but the bottom nibble of an element's info status doesn't apply to the
422 * chain.
423 */
424 chainStatus->dwInfoStatus |= (elementStatus->dwInfoStatus & 0xfffffff0);
425}
426
429{
430 BOOL ret = FALSE;
432
433 if (element)
434 {
435 if (!chain->cElement)
436 chain->rgpElement = CryptMemAlloc(sizeof(PCERT_CHAIN_ELEMENT));
437 else
438 chain->rgpElement = CryptMemRealloc(chain->rgpElement,
439 (chain->cElement + 1) * sizeof(PCERT_CHAIN_ELEMENT));
440 if (chain->rgpElement)
441 {
442 chain->rgpElement[chain->cElement++] = element;
443 memset(element, 0, sizeof(CERT_CHAIN_ELEMENT));
444 element->cbSize = sizeof(CERT_CHAIN_ELEMENT);
446 if (chain->cElement > 1)
447 chain->rgpElement[chain->cElement - 2]->TrustStatus.dwInfoStatus
448 = subjectInfoStatus;
449 /* FIXME: initialize the rest of element */
450 if (!(chain->cElement % engine->CycleDetectionModulus))
451 {
453 /* Reinitialize the element pointer in case the chain is
454 * cyclic, in which case the chain is truncated.
455 */
456 element = chain->rgpElement[chain->cElement - 1];
457 }
458 CRYPT_CombineTrustStatus(&chain->TrustStatus,
459 &element->TrustStatus);
460 ret = TRUE;
461 }
462 else
464 }
465 return ret;
466}
467
469{
470 DWORD i;
471
472 for (i = 0; i < chain->cElement; i++)
473 CRYPT_FreeChainElement(chain->rgpElement[i]);
474 CryptMemFree(chain->rgpElement);
476}
477
479 PCERT_CHAIN_ELEMENT rootElement)
480{
482 rootElement->pCertContext);
483
484 if (!trustedRoot)
485 rootElement->TrustStatus.dwErrorStatus |=
487 else
488 CertFreeCertificateContext(trustedRoot);
489}
490
492 PCERT_CHAIN_ELEMENT rootElement)
493{
494 PCCERT_CONTEXT root = rootElement->pCertContext;
495
496 if (!CryptVerifyCertificateSignatureEx(0, root->dwCertEncodingType,
499 {
500 TRACE_(chain)("Last certificate's signature is invalid\n");
501 rootElement->TrustStatus.dwErrorStatus |=
503 }
504 CRYPT_CheckTrustedStatus(hRoot, rootElement);
505}
506
507/* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
508 * or szOID_BASIC_CONSTRAINTS2, whichever is present) into a
509 * CERT_BASIC_CONSTRAINTS2_INFO. If it neither extension is present, sets
510 * constraints->fCA to defaultIfNotSpecified.
511 * Returns FALSE if the extension is present but couldn't be decoded.
512 */
514 CERT_BASIC_CONSTRAINTS2_INFO *constraints, BOOL defaultIfNotSpecified)
515{
516 BOOL ret = TRUE;
518 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension);
519
520 constraints->fPathLenConstraint = FALSE;
521 if (ext)
522 {
524 DWORD size = 0;
525
527 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG,
528 NULL, &info, &size);
529 if (ret)
530 {
531 if (info->SubjectType.cbData == 1)
532 constraints->fCA =
533 info->SubjectType.pbData[0] & CERT_CA_SUBJECT_FLAG;
535 }
536 }
537 else
538 {
540 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension);
541 if (ext)
542 {
544
546 szOID_BASIC_CONSTRAINTS2, ext->Value.pbData, ext->Value.cbData,
547 0, NULL, constraints, &size);
548 }
549 else
550 constraints->fCA = defaultIfNotSpecified;
551 }
552 return ret;
553}
554
555/* Checks element's basic constraints to see if it can act as a CA, with
556 * remainingCAs CAs left in this chain. In general, a cert must include the
557 * basic constraints extension, with the CA flag asserted, in order to be
558 * allowed to be a CA. A V1 or V2 cert, which has no extensions, is also
559 * allowed to be a CA if it's installed locally (in the engine's world store.)
560 * This matches the expected usage in RFC 5280, section 4.2.1.9: a conforming
561 * CA MUST include the basic constraints extension in all certificates that are
562 * used to validate digital signatures on certificates. It also matches
563 * section 6.1.4(k): "If a certificate is a v1 or v2 certificate, then the
564 * application MUST either verify that the certificate is a CA certificate
565 * through out-of-band means or reject the certificate." Rejecting the
566 * certificate prohibits a large number of commonly used certificates, so
567 * accepting locally installed ones is a compromise.
568 * Root certificates are also allowed to be CAs even without a basic
569 * constraints extension. This is implied by RFC 5280, section 6.1: the
570 * root of a certificate chain's only requirement is that it was used to issue
571 * the next certificate in the chain.
572 * Updates chainConstraints with the element's constraints, if:
573 * 1. chainConstraints doesn't have a path length constraint, or
574 * 2. element's path length constraint is smaller than chainConstraints's
575 * Sets *pathLengthConstraintViolated to TRUE if a path length violation
576 * occurs.
577 * Returns TRUE if the element can be a CA, and the length of the remaining
578 * chain is valid.
579 */
582 DWORD remainingCAs, BOOL isRoot, BOOL *pathLengthConstraintViolated)
583{
584 BOOL validBasicConstraints, implicitCA = FALSE;
586
587 if (isRoot)
588 implicitCA = TRUE;
589 else if (cert->pCertInfo->dwVersion == CERT_V1 ||
590 cert->pCertInfo->dwVersion == CERT_V2)
591 {
592 BYTE hash[20];
593 DWORD size = sizeof(hash);
594
596 hash, &size))
597 {
598 CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
600 engine->hWorld, cert->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH,
601 &blob, NULL);
602
603 if (localCert)
604 {
606 implicitCA = TRUE;
607 }
608 }
609 }
610 if ((validBasicConstraints = CRYPT_DecodeBasicConstraints(cert,
611 &constraints, implicitCA)))
612 {
613 chainConstraints->fCA = constraints.fCA;
614 if (!constraints.fCA)
615 {
616 TRACE_(chain)("chain element %d can't be a CA\n", remainingCAs + 1);
617 validBasicConstraints = FALSE;
618 }
619 else if (constraints.fPathLenConstraint)
620 {
621 /* If the element has path length constraints, they apply to the
622 * entire remaining chain.
623 */
624 if (!chainConstraints->fPathLenConstraint ||
625 constraints.dwPathLenConstraint <
626 chainConstraints->dwPathLenConstraint)
627 {
628 TRACE_(chain)("setting path length constraint to %d\n",
629 chainConstraints->dwPathLenConstraint);
630 chainConstraints->fPathLenConstraint = TRUE;
631 chainConstraints->dwPathLenConstraint =
632 constraints.dwPathLenConstraint;
633 }
634 }
635 }
636 if (chainConstraints->fPathLenConstraint &&
637 remainingCAs > chainConstraints->dwPathLenConstraint)
638 {
639 TRACE_(chain)("remaining CAs %d exceed max path length %d\n",
640 remainingCAs, chainConstraints->dwPathLenConstraint);
641 validBasicConstraints = FALSE;
642 *pathLengthConstraintViolated = TRUE;
643 }
644 return validBasicConstraints;
645}
646
648{
649 BOOL match;
650
651 /* RFC 5280, section 4.2.1.10:
652 * "For URIs, the constraint applies to the host part of the name...
653 * When the constraint begins with a period, it MAY be expanded with one
654 * or more labels. That is, the constraint ".example.com" is satisfied by
655 * both host.example.com and my.host.example.com. However, the constraint
656 * ".example.com" is not satisfied by "example.com". When the constraint
657 * does not begin with a period, it specifies a host."
658 * and for email addresses,
659 * "To indicate all Internet mail addresses on a particular host, the
660 * constraint is specified as the host name. For example, the constraint
661 * "example.com" is satisfied by any mail address at the host
662 * "example.com". To specify any address within a domain, the constraint
663 * is specified with a leading period (as with URIs)."
664 */
665 if (constraint[0] == '.')
666 {
667 /* Must be strictly greater than, a name can't begin with '.' */
668 if (lstrlenW(name) > lstrlenW(constraint))
669 match = !lstrcmpiW(name + lstrlenW(name) - lstrlenW(constraint),
670 constraint);
671 else
672 {
673 /* name is too short, no match */
674 match = FALSE;
675 }
676 }
677 else
678 match = !lstrcmpiW(name, constraint);
679 return match;
680}
681
683 DWORD *trustErrorStatus)
684{
685 BOOL match = FALSE;
686
687 TRACE("%s, %s\n", debugstr_w(constraint), debugstr_w(name));
688
689 if (!constraint)
690 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
691 else if (!name)
692 ; /* no match */
693 else
694 {
695 LPCWSTR colon, authority_end, at, hostname = NULL;
696 /* The maximum length for a hostname is 254 in the DNS, see RFC 1034 */
697 WCHAR hostname_buf[255];
698
699 /* RFC 5280: only the hostname portion of the URL is compared. From
700 * section 4.2.1.10:
701 * "For URIs, the constraint applies to the host part of the name.
702 * The constraint MUST be specified as a fully qualified domain name
703 * and MAY specify a host or a domain."
704 * The format for URIs is in RFC 2396.
705 *
706 * First, remove any scheme that's present. */
707 colon = strchrW(name, ':');
708 if (colon && *(colon + 1) == '/' && *(colon + 2) == '/')
709 name = colon + 3;
710 /* Next, find the end of the authority component. (The authority is
711 * generally just the hostname, but it may contain a username or a port.
712 * Those are removed next.)
713 */
714 authority_end = strchrW(name, '/');
715 if (!authority_end)
716 authority_end = strchrW(name, '?');
717 if (!authority_end)
718 authority_end = name + strlenW(name);
719 /* Remove any port number from the authority. The userinfo portion
720 * of an authority may contain a colon, so stop if a userinfo portion
721 * is found (indicated by '@').
722 */
723 for (colon = authority_end; colon >= name && *colon != ':' &&
724 *colon != '@'; colon--)
725 ;
726 if (*colon == ':')
727 authority_end = colon;
728 /* Remove any username from the authority */
729 if ((at = strchrW(name, '@')))
730 name = at;
731 /* Ignore any path or query portion of the URL. */
732 if (*authority_end)
733 {
734 if (authority_end - name < ARRAY_SIZE(hostname_buf))
735 {
736 memcpy(hostname_buf, name,
737 (authority_end - name) * sizeof(WCHAR));
738 hostname_buf[authority_end - name] = 0;
739 hostname = hostname_buf;
740 }
741 /* else: Hostname is too long, not a match */
742 }
743 else
744 hostname = name;
745 if (hostname)
746 match = domain_name_matches(constraint, hostname);
747 }
748 return match;
749}
750
752 DWORD *trustErrorStatus)
753{
754 BOOL match = FALSE;
755 LPCWSTR at;
756
757 TRACE("%s, %s\n", debugstr_w(constraint), debugstr_w(name));
758
759 if (!constraint)
760 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
761 else if (!name)
762 ; /* no match */
763 else if (strchrW(constraint, '@'))
764 match = !lstrcmpiW(constraint, name);
765 else
766 {
767 if ((at = strchrW(name, '@')))
768 match = domain_name_matches(constraint, at + 1);
769 else
770 match = !lstrcmpiW(constraint, name);
771 }
772 return match;
773}
774
776 DWORD *trustErrorStatus)
777{
778 BOOL match = FALSE;
779
780 TRACE("%s, %s\n", debugstr_w(constraint), debugstr_w(name));
781
782 if (!constraint)
783 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
784 else if (!name)
785 ; /* no match */
786 /* RFC 5280, section 4.2.1.10:
787 * "DNS name restrictions are expressed as host.example.com. Any DNS name
788 * that can be constructed by simply adding zero or more labels to the
789 * left-hand side of the name satisfies the name constraint. For example,
790 * www.host.example.com would satisfy the constraint but host1.example.com
791 * would not."
792 */
793 else if (lstrlenW(name) == lstrlenW(constraint))
794 match = !lstrcmpiW(name, constraint);
795 else if (lstrlenW(name) > lstrlenW(constraint))
796 {
797 match = !lstrcmpiW(name + lstrlenW(name) - lstrlenW(constraint),
798 constraint);
799 if (match)
800 {
801 BOOL dot = FALSE;
802 LPCWSTR ptr;
803
804 /* This only matches if name is a subdomain of constraint, i.e.
805 * there's a '.' between the beginning of the name and the
806 * matching portion of the name.
807 */
808 for (ptr = name + lstrlenW(name) - lstrlenW(constraint);
809 !dot && ptr >= name; ptr--)
810 if (*ptr == '.')
811 dot = TRUE;
812 match = dot;
813 }
814 }
815 /* else: name is too short, no match */
816
817 return match;
818}
819
820static BOOL ip_address_matches(const CRYPT_DATA_BLOB *constraint,
821 const CRYPT_DATA_BLOB *name, DWORD *trustErrorStatus)
822{
823 BOOL match = FALSE;
824
825 TRACE("(%d, %p), (%d, %p)\n", constraint->cbData, constraint->pbData,
826 name->cbData, name->pbData);
827
828 /* RFC5280, section 4.2.1.10, iPAddress syntax: either 8 or 32 bytes, for
829 * IPv4 or IPv6 addresses, respectively.
830 */
831 if (constraint->cbData != sizeof(DWORD) * 2 && constraint->cbData != 32)
832 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
833 else if (name->cbData == sizeof(DWORD) &&
834 constraint->cbData == sizeof(DWORD) * 2)
835 {
836 DWORD subnet, mask, addr;
837
838 memcpy(&subnet, constraint->pbData, sizeof(subnet));
839 memcpy(&mask, constraint->pbData + sizeof(subnet), sizeof(mask));
840 memcpy(&addr, name->pbData, sizeof(addr));
841 /* These are really in big-endian order, but for equality matching we
842 * don't need to swap to host order
843 */
844 match = (subnet & mask) == (addr & mask);
845 }
846 else if (name->cbData == 16 && constraint->cbData == 32)
847 {
848 const BYTE *subnet, *mask, *addr;
849 DWORD i;
850
851 subnet = constraint->pbData;
852 mask = constraint->pbData + 16;
853 addr = name->pbData;
854 match = TRUE;
855 for (i = 0; match && i < 16; i++)
856 if ((subnet[i] & mask[i]) != (addr[i] & mask[i]))
857 match = FALSE;
858 }
859 /* else: name is wrong size, no match */
860
861 return match;
862}
863
865 const CERT_NAME_BLOB *name)
866{
867 CERT_NAME_INFO *constraintName;
868 DWORD size;
869 BOOL match = FALSE;
870
872 constraint->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &constraintName, &size))
873 {
874 DWORD i;
875
876 match = TRUE;
877 for (i = 0; match && i < constraintName->cRDN; i++)
880 (CERT_NAME_BLOB *)name, &constraintName->rgRDN[i]);
881 LocalFree(constraintName);
882 }
883 return match;
884}
885
887 const CERT_ALT_NAME_ENTRY *constraint, DWORD *trustErrorStatus, BOOL *present)
888{
889 BOOL match = FALSE;
890
891 if (name->dwAltNameChoice == constraint->dwAltNameChoice)
892 {
893 if (present)
894 *present = TRUE;
895 switch (constraint->dwAltNameChoice)
896 {
898 match = rfc822_name_matches(constraint->u.pwszURL,
899 name->u.pwszURL, trustErrorStatus);
900 break;
902 match = dns_name_matches(constraint->u.pwszURL,
903 name->u.pwszURL, trustErrorStatus);
904 break;
906 match = url_matches(constraint->u.pwszURL,
907 name->u.pwszURL, trustErrorStatus);
908 break;
910 match = ip_address_matches(&constraint->u.IPAddress,
911 &name->u.IPAddress, trustErrorStatus);
912 break;
915 &name->u.DirectoryName);
916 break;
917 default:
918 ERR("name choice %d unsupported in this context\n",
919 constraint->dwAltNameChoice);
920 *trustErrorStatus |=
922 }
923 }
924 else if (present)
925 *present = FALSE;
926 return match;
927}
928
930 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
931{
932 DWORD i;
933 BOOL match = FALSE;
934
935 for (i = 0; !match && i < nameConstraints->cExcludedSubtree; i++)
937 &nameConstraints->rgExcludedSubtree[i].Base, trustErrorStatus, NULL);
938 return match;
939}
940
942 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus,
943 BOOL *present)
944{
945 DWORD i;
946 BOOL match = FALSE;
947
948 for (i = 0; !match && i < nameConstraints->cPermittedSubtree; i++)
950 &nameConstraints->rgPermittedSubtree[i].Base, trustErrorStatus,
951 present);
952 return match;
953}
954
956{
958
960 cert->cExtension, cert->rgExtension);
961 if (!ext)
963 cert->cExtension, cert->rgExtension);
964 return ext;
965}
966
968 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
969{
970 CERT_ALT_NAME_INFO *subjectAltName;
971 DWORD size;
972
974 altNameExt->Value.pbData, altNameExt->Value.cbData,
976 &subjectAltName, &size))
977 {
978 DWORD i;
979
980 for (i = 0; i < subjectAltName->cAltEntry; i++)
981 {
982 BOOL nameFormPresent;
983
984 /* A name constraint only applies if the name form is present.
985 * From RFC 5280, section 4.2.1.10:
986 * "Restrictions apply only when the specified name form is
987 * present. If no name of the type is in the certificate,
988 * the certificate is acceptable."
989 */
991 &subjectAltName->rgAltEntry[i], nameConstraints,
992 trustErrorStatus))
993 {
994 TRACE_(chain)("subject alternate name form %d excluded\n",
995 subjectAltName->rgAltEntry[i].dwAltNameChoice);
996 *trustErrorStatus |=
998 }
999 nameFormPresent = FALSE;
1001 &subjectAltName->rgAltEntry[i], nameConstraints,
1002 trustErrorStatus, &nameFormPresent) && nameFormPresent)
1003 {
1004 TRACE_(chain)("subject alternate name form %d not permitted\n",
1005 subjectAltName->rgAltEntry[i].dwAltNameChoice);
1006 *trustErrorStatus |=
1008 }
1009 }
1010 LocalFree(subjectAltName);
1011 }
1012 else
1013 *trustErrorStatus |=
1015}
1016
1018 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
1019{
1020 DWORD i;
1021 BOOL match = FALSE;
1022
1023 for (i = 0; !match && i < nameConstraints->cExcludedSubtree; i++)
1024 {
1025 const CERT_ALT_NAME_ENTRY *constraint =
1026 &nameConstraints->rgExcludedSubtree[i].Base;
1027
1028 if (constraint->dwAltNameChoice == CERT_ALT_NAME_RFC822_NAME)
1030 (LPCWSTR)attr->Value.pbData, trustErrorStatus);
1031 }
1032 return match;
1033}
1034
1036 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus,
1037 BOOL *present)
1038{
1039 DWORD i;
1040 BOOL match = FALSE;
1041
1042 for (i = 0; !match && i < nameConstraints->cPermittedSubtree; i++)
1043 {
1044 const CERT_ALT_NAME_ENTRY *constraint =
1045 &nameConstraints->rgPermittedSubtree[i].Base;
1046
1047 if (constraint->dwAltNameChoice == CERT_ALT_NAME_RFC822_NAME)
1048 {
1049 *present = TRUE;
1051 (LPCWSTR)attr->Value.pbData, trustErrorStatus);
1052 }
1053 }
1054 return match;
1055}
1056
1059 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
1060{
1062 DWORD size;
1063
1065 subjectName->pbData, subjectName->cbData,
1067 {
1068 DWORD i, j;
1069
1070 for (i = 0; i < name->cRDN; i++)
1071 for (j = 0; j < name->rgRDN[i].cRDNAttr; j++)
1072 if (!strcmp(name->rgRDN[i].rgRDNAttr[j].pszObjId,
1074 {
1075 BOOL nameFormPresent;
1076
1077 /* A name constraint only applies if the name form is
1078 * present. From RFC 5280, section 4.2.1.10:
1079 * "Restrictions apply only when the specified name form is
1080 * present. If no name of the type is in the certificate,
1081 * the certificate is acceptable."
1082 */
1084 &name->rgRDN[i].rgRDNAttr[j], nameConstraints,
1085 trustErrorStatus))
1086 {
1087 TRACE_(chain)(
1088 "email address in subject name is excluded\n");
1089 *trustErrorStatus |=
1091 }
1092 nameFormPresent = FALSE;
1094 &name->rgRDN[i].rgRDNAttr[j], nameConstraints,
1095 trustErrorStatus, &nameFormPresent) && nameFormPresent)
1096 {
1097 TRACE_(chain)(
1098 "email address in subject name is not permitted\n");
1099 *trustErrorStatus |=
1101 }
1102 }
1103 LocalFree(name);
1104 }
1105 else
1106 *trustErrorStatus |=
1108}
1109
1111{
1112 BOOL empty;
1113
1114 if (!name->cbData)
1115 empty = TRUE;
1116 else if (name->cbData == 2 && name->pbData[1] == 0)
1117 {
1118 /* An empty sequence is also empty */
1119 empty = TRUE;
1120 }
1121 else
1122 empty = FALSE;
1123 return empty;
1124}
1125
1127 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
1128{
1129 BOOL hasEmailConstraint = FALSE;
1130 DWORD i;
1131
1132 /* In general, a subject distinguished name only matches a directory name
1133 * constraint. However, an exception exists for email addresses.
1134 * From RFC 5280, section 4.2.1.6:
1135 * "Legacy implementations exist where an electronic mail address is
1136 * embedded in the subject distinguished name as an emailAddress
1137 * attribute [RFC2985]."
1138 * If an email address constraint exists, check that constraint separately.
1139 */
1140 for (i = 0; !hasEmailConstraint && i < nameConstraints->cExcludedSubtree;
1141 i++)
1142 if (nameConstraints->rgExcludedSubtree[i].Base.dwAltNameChoice ==
1144 hasEmailConstraint = TRUE;
1145 for (i = 0; !hasEmailConstraint && i < nameConstraints->cPermittedSubtree;
1146 i++)
1147 if (nameConstraints->rgPermittedSubtree[i].Base.dwAltNameChoice ==
1149 hasEmailConstraint = TRUE;
1150 if (hasEmailConstraint)
1152 trustErrorStatus);
1153 for (i = 0; i < nameConstraints->cExcludedSubtree; i++)
1154 {
1155 CERT_ALT_NAME_ENTRY *constraint =
1156 &nameConstraints->rgExcludedSubtree[i].Base;
1157
1158 if (constraint->dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME &&
1160 {
1161 TRACE_(chain)("subject name is excluded\n");
1162 *trustErrorStatus |=
1164 }
1165 }
1166 /* RFC 5280, section 4.2.1.10:
1167 * "Restrictions apply only when the specified name form is present.
1168 * If no name of the type is in the certificate, the certificate is
1169 * acceptable."
1170 * An empty name can't have the name form present, so don't check it.
1171 */
1172 if (nameConstraints->cPermittedSubtree && !CRYPT_IsEmptyName(subjectName))
1173 {
1174 BOOL match = FALSE, hasDirectoryConstraint = FALSE;
1175
1176 for (i = 0; !match && i < nameConstraints->cPermittedSubtree; i++)
1177 {
1178 CERT_ALT_NAME_ENTRY *constraint =
1179 &nameConstraints->rgPermittedSubtree[i].Base;
1180
1182 {
1183 hasDirectoryConstraint = TRUE;
1185 subjectName);
1186 }
1187 }
1188 if (hasDirectoryConstraint && !match)
1189 {
1190 TRACE_(chain)("subject name is not permitted\n");
1192 }
1193 }
1194}
1195
1197 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, const CERT_INFO *cert,
1198 DWORD *trustErrorStatus)
1199{
1201
1202 if (ext)
1203 compare_alt_name_with_constraints(ext, nameConstraints,
1204 trustErrorStatus);
1205 /* Name constraints apply to the subject alternative name as well as the
1206 * subject name. From RFC 5280, section 4.2.1.10:
1207 * "Restrictions apply to the subject distinguished name and apply to
1208 * subject alternative names."
1209 */
1210 compare_subject_with_constraints(&cert->Subject, nameConstraints,
1211 trustErrorStatus);
1212}
1213
1214/* Gets cert's name constraints, if any. Free with LocalFree. */
1216{
1218
1220
1222 cert->rgExtension)))
1223 {
1224 DWORD size;
1225
1227 ext->Value.pbData, ext->Value.cbData,
1229 &size);
1230 }
1231 return info;
1232}
1233
1235{
1236 DWORD i;
1237 BOOL ret = TRUE;
1238
1239 /* Make sure at least one permitted or excluded subtree is present. From
1240 * RFC 5280, section 4.2.1.10:
1241 * "Conforming CAs MUST NOT issue certificates where name constraints is an
1242 * empty sequence. That is, either the permittedSubtrees field or the
1243 * excludedSubtrees MUST be present."
1244 */
1245 if (!info->cPermittedSubtree && !info->cExcludedSubtree)
1246 {
1247 WARN_(chain)("constraints contain no permitted nor excluded subtree\n");
1248 ret = FALSE;
1249 }
1250 /* Check that none of the constraints specifies a minimum or a maximum.
1251 * See RFC 5280, section 4.2.1.10:
1252 * "Within this profile, the minimum and maximum fields are not used with
1253 * any name forms, thus, the minimum MUST be zero, and maximum MUST be
1254 * absent. However, if an application encounters a critical name
1255 * constraints extension that specifies other values for minimum or
1256 * maximum for a name form that appears in a subsequent certificate, the
1257 * application MUST either process these fields or reject the
1258 * certificate."
1259 * Since it gives no guidance as to how to process these fields, we
1260 * reject any name constraint that contains them.
1261 */
1262 for (i = 0; ret && i < info->cPermittedSubtree; i++)
1263 if (info->rgPermittedSubtree[i].dwMinimum ||
1264 info->rgPermittedSubtree[i].fMaximum)
1265 {
1266 TRACE_(chain)("found a minimum or maximum in permitted subtrees\n");
1267 ret = FALSE;
1268 }
1269 for (i = 0; ret && i < info->cExcludedSubtree; i++)
1270 if (info->rgExcludedSubtree[i].dwMinimum ||
1271 info->rgExcludedSubtree[i].fMaximum)
1272 {
1273 TRACE_(chain)("found a minimum or maximum in excluded subtrees\n");
1274 ret = FALSE;
1275 }
1276 return ret;
1277}
1278
1280{
1281 int i, j;
1282
1283 /* Microsoft's implementation appears to violate RFC 3280: according to
1284 * MSDN, the various CERT_TRUST_*_NAME_CONSTRAINT errors are set if a CA's
1285 * name constraint is violated in the end cert. According to RFC 3280,
1286 * the constraints should be checked against every subsequent certificate
1287 * in the chain, not just the end cert.
1288 * Microsoft's implementation also sets the name constraint errors on the
1289 * certs whose constraints were violated, not on the certs that violated
1290 * them.
1291 * In order to be error-compatible with Microsoft's implementation, while
1292 * still adhering to RFC 3280, I use a O(n ^ 2) algorithm to check name
1293 * constraints.
1294 */
1295 for (i = chain->cElement - 1; i > 0; i--)
1296 {
1297 CERT_NAME_CONSTRAINTS_INFO *nameConstraints;
1298
1299 if ((nameConstraints = CRYPT_GetNameConstraints(
1300 chain->rgpElement[i]->pCertContext->pCertInfo)))
1301 {
1302 if (!CRYPT_IsValidNameConstraint(nameConstraints))
1303 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1305 else
1306 {
1307 for (j = i - 1; j >= 0; j--)
1308 {
1309 DWORD errorStatus = 0;
1310
1311 /* According to RFC 3280, self-signed certs don't have name
1312 * constraints checked unless they're the end cert.
1313 */
1314 if (j == 0 || !CRYPT_IsCertificateSelfSigned(
1315 chain->rgpElement[j]->pCertContext))
1316 {
1317 CRYPT_CheckNameConstraints(nameConstraints,
1318 chain->rgpElement[j]->pCertContext->pCertInfo,
1319 &errorStatus);
1320 if (errorStatus)
1321 {
1322 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1323 errorStatus;
1324 CRYPT_CombineTrustStatus(&chain->TrustStatus,
1325 &chain->rgpElement[i]->TrustStatus);
1326 }
1327 else
1328 chain->rgpElement[i]->TrustStatus.dwInfoStatus |=
1330 }
1331 }
1332 }
1333 LocalFree(nameConstraints);
1334 }
1335 }
1336}
1337
1338/* Gets cert's policies info, if any. Free with LocalFree. */
1340{
1342 CERT_POLICIES_INFO *policies = NULL;
1343
1344 ext = CertFindExtension(szOID_KEY_USAGE, cert->pCertInfo->cExtension,
1345 cert->pCertInfo->rgExtension);
1346 if (ext)
1347 {
1348 DWORD size;
1349
1351 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
1352 &policies, &size);
1353 }
1354 return policies;
1355}
1356
1358 DWORD *errorStatus)
1359{
1360 DWORD i;
1361
1362 for (i = 0; i < policies->cPolicyInfo; i++)
1363 {
1364 /* For now, the only accepted policy identifier is the anyPolicy
1365 * identifier.
1366 * FIXME: the policy identifiers should be compared against the
1367 * cert's certificate policies extension, subject to the policy
1368 * mappings extension, and the policy constraints extension.
1369 * See RFC 5280, sections 4.2.1.4, 4.2.1.5, and 4.2.1.11.
1370 */
1373 {
1374 FIXME("unsupported policy %s\n",
1377 }
1378 }
1379}
1380
1382{
1383 int i, j;
1384
1385 for (i = chain->cElement - 1; i > 0; i--)
1386 {
1387 CERT_POLICIES_INFO *policies;
1388
1389 if ((policies = CRYPT_GetPolicies(chain->rgpElement[i]->pCertContext)))
1390 {
1391 for (j = i - 1; j >= 0; j--)
1392 {
1393 DWORD errorStatus = 0;
1394
1395 CRYPT_CheckPolicies(policies,
1396 chain->rgpElement[j]->pCertContext->pCertInfo, &errorStatus);
1397 if (errorStatus)
1398 {
1399 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1400 errorStatus;
1401 CRYPT_CombineTrustStatus(&chain->TrustStatus,
1402 &chain->rgpElement[i]->TrustStatus);
1403 }
1404 }
1405 LocalFree(policies);
1406 }
1407 }
1408}
1409
1411{
1414 LPWSTR str = NULL;
1415
1416 if (len)
1417 {
1418 str = CryptMemAlloc(len * sizeof(WCHAR));
1419 if (str)
1422 }
1423 return str;
1424}
1425
1427{
1428 LPWSTR str;
1429
1430 switch (entry->dwAltNameChoice)
1431 {
1433 TRACE_(chain)("CERT_ALT_NAME_OTHER_NAME, oid = %s\n",
1434 debugstr_a(entry->u.pOtherName->pszObjId));
1435 break;
1437 TRACE_(chain)("CERT_ALT_NAME_RFC822_NAME: %s\n",
1438 debugstr_w(entry->u.pwszRfc822Name));
1439 break;
1441 TRACE_(chain)("CERT_ALT_NAME_DNS_NAME: %s\n",
1442 debugstr_w(entry->u.pwszDNSName));
1443 break;
1445 str = name_value_to_str(&entry->u.DirectoryName);
1446 TRACE_(chain)("CERT_ALT_NAME_DIRECTORY_NAME: %s\n", debugstr_w(str));
1448 break;
1449 case CERT_ALT_NAME_URL:
1450 TRACE_(chain)("CERT_ALT_NAME_URL: %s\n", debugstr_w(entry->u.pwszURL));
1451 break;
1453 TRACE_(chain)("CERT_ALT_NAME_IP_ADDRESS: %d bytes\n",
1454 entry->u.IPAddress.cbData);
1455 break;
1457 TRACE_(chain)("CERT_ALT_NAME_REGISTERED_ID: %s\n",
1458 debugstr_a(entry->u.pszRegisteredID));
1459 break;
1460 default:
1461 TRACE_(chain)("dwAltNameChoice = %d\n", entry->dwAltNameChoice);
1462 }
1463}
1464
1466{
1468 DWORD size;
1469
1470 TRACE_(chain)("%s:\n", type);
1472 ext->Value.pbData, ext->Value.cbData,
1474 {
1475 DWORD i;
1476
1477 TRACE_(chain)("%d alt name entries:\n", name->cAltEntry);
1478 for (i = 0; i < name->cAltEntry; i++)
1479 dump_alt_name_entry(&name->rgAltEntry[i]);
1480 LocalFree(name);
1481 }
1482}
1483
1485{
1487 DWORD size = 0;
1488
1490 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG,
1491 NULL, &info, &size))
1492 {
1493 TRACE_(chain)("SubjectType: %02x\n", info->SubjectType.pbData[0]);
1494 TRACE_(chain)("%s path length constraint\n",
1495 info->fPathLenConstraint ? "has" : "doesn't have");
1496 TRACE_(chain)("path length=%d\n", info->dwPathLenConstraint);
1497 LocalFree(info);
1498 }
1499}
1500
1502{
1503 CERT_BASIC_CONSTRAINTS2_INFO constraints;
1505
1507 szOID_BASIC_CONSTRAINTS2, ext->Value.pbData, ext->Value.cbData,
1508 0, NULL, &constraints, &size))
1509 {
1510 TRACE_(chain)("basic constraints:\n");
1511 TRACE_(chain)("can%s be a CA\n", constraints.fCA ? "" : "not");
1512 TRACE_(chain)("%s path length constraint\n",
1513 constraints.fPathLenConstraint ? "has" : "doesn't have");
1514 TRACE_(chain)("path length=%d\n", constraints.dwPathLenConstraint);
1515 }
1516}
1517
1519{
1521 DWORD size = sizeof(usage);
1522
1524 ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL, &usage, &size))
1525 {
1526#define trace_usage_bit(bits, bit) \
1527 if ((bits) & (bit)) TRACE_(chain)("%s\n", #bit)
1528 if (usage.cbData)
1529 {
1538 }
1539#undef trace_usage_bit
1540 if (usage.cbData > 1 && usage.pbData[1] & CERT_DECIPHER_ONLY_KEY_USAGE)
1541 TRACE_(chain)("CERT_DECIPHER_ONLY_KEY_USAGE\n");
1542 }
1543}
1544
1546{
1547 dump_alt_name_entry(&subtree->Base);
1548 TRACE_(chain)("dwMinimum = %d, fMaximum = %d, dwMaximum = %d\n",
1549 subtree->dwMinimum, subtree->fMaximum, subtree->dwMaximum);
1550}
1551
1553{
1554 CERT_NAME_CONSTRAINTS_INFO *nameConstraints;
1555 DWORD size;
1556
1558 ext->Value.pbData, ext->Value.cbData,
1560 &size))
1561 {
1562 DWORD i;
1563
1564 TRACE_(chain)("%d permitted subtrees:\n",
1565 nameConstraints->cPermittedSubtree);
1566 for (i = 0; i < nameConstraints->cPermittedSubtree; i++)
1567 dump_general_subtree(&nameConstraints->rgPermittedSubtree[i]);
1568 TRACE_(chain)("%d excluded subtrees:\n",
1569 nameConstraints->cExcludedSubtree);
1570 for (i = 0; i < nameConstraints->cExcludedSubtree; i++)
1571 dump_general_subtree(&nameConstraints->rgExcludedSubtree[i]);
1572 LocalFree(nameConstraints);
1573 }
1574}
1575
1577{
1578 CERT_POLICIES_INFO *policies;
1579 DWORD size;
1580
1582 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
1583 &policies, &size))
1584 {
1585 DWORD i, j;
1586
1587 TRACE_(chain)("%d policies:\n", policies->cPolicyInfo);
1588 for (i = 0; i < policies->cPolicyInfo; i++)
1589 {
1590 TRACE_(chain)("policy identifier: %s\n",
1592 TRACE_(chain)("%d policy qualifiers:\n",
1593 policies->rgPolicyInfo[i].cPolicyQualifier);
1594 for (j = 0; j < policies->rgPolicyInfo[i].cPolicyQualifier; j++)
1595 TRACE_(chain)("%s\n", debugstr_a(
1596 policies->rgPolicyInfo[i].rgPolicyQualifier[j].
1597 pszPolicyQualifierId));
1598 }
1599 LocalFree(policies);
1600 }
1601}
1602
1604{
1606 DWORD size;
1607
1609 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
1610 &usage, &size))
1611 {
1612 DWORD i;
1613
1614 TRACE_(chain)("%d usages:\n", usage->cUsageIdentifier);
1615 for (i = 0; i < usage->cUsageIdentifier; i++)
1616 TRACE_(chain)("%s\n", usage->rgpszUsageIdentifier[i]);
1618 }
1619}
1620
1622{
1624 DWORD size = sizeof(usage);
1625
1627 ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL, &usage, &size))
1628 {
1629#define trace_cert_type_bit(bits, bit) \
1630 if ((bits) & (bit)) TRACE_(chain)("%s\n", #bit)
1631 if (usage.cbData)
1632 {
1633 trace_cert_type_bit(usage.pbData[0],
1635 trace_cert_type_bit(usage.pbData[0],
1642 }
1643#undef trace_cert_type_bit
1644 }
1645}
1646
1648{
1649 TRACE_(chain)("%s (%scritical)\n", debugstr_a(ext->pszObjId),
1650 ext->fCritical ? "" : "not ");
1651 if (!strcmp(ext->pszObjId, szOID_SUBJECT_ALT_NAME))
1652 dump_alt_name("subject alt name", ext);
1653 else if (!strcmp(ext->pszObjId, szOID_ISSUER_ALT_NAME))
1654 dump_alt_name("issuer alt name", ext);
1655 else if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS))
1657 else if (!strcmp(ext->pszObjId, szOID_KEY_USAGE))
1659 else if (!strcmp(ext->pszObjId, szOID_SUBJECT_ALT_NAME2))
1660 dump_alt_name("subject alt name 2", ext);
1661 else if (!strcmp(ext->pszObjId, szOID_ISSUER_ALT_NAME2))
1662 dump_alt_name("issuer alt name 2", ext);
1663 else if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS2))
1665 else if (!strcmp(ext->pszObjId, szOID_NAME_CONSTRAINTS))
1667 else if (!strcmp(ext->pszObjId, szOID_CERT_POLICIES))
1669 else if (!strcmp(ext->pszObjId, szOID_ENHANCED_KEY_USAGE))
1671 else if (!strcmp(ext->pszObjId, szOID_NETSCAPE_CERT_TYPE))
1673}
1674
1676{
1677 char date[80];
1678 char dateFmt[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
1679 SYSTEMTIME sysTime;
1680
1681 if (!time) return "(null)";
1682
1684 FileTimeToSystemTime(time, &sysTime);
1685 GetDateFormatA(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, dateFmt, date, ARRAY_SIZE(date));
1686 return wine_dbg_sprintf("%s", date);
1687}
1688
1690{
1691 LPWSTR name = NULL;
1692 DWORD len, i;
1693
1694 TRACE_(chain)("%p: version %d\n", cert, cert->pCertInfo->dwVersion);
1697 name = CryptMemAlloc(len * sizeof(WCHAR));
1698 if (name)
1699 {
1702 TRACE_(chain)("issued by %s\n", debugstr_w(name));
1704 }
1706 NULL, 0);
1707 name = CryptMemAlloc(len * sizeof(WCHAR));
1708 if (name)
1709 {
1711 name, len);
1712 TRACE_(chain)("issued to %s\n", debugstr_w(name));
1714 }
1715 TRACE_(chain)("valid from %s to %s\n",
1716 filetime_to_str(&cert->pCertInfo->NotBefore),
1717 filetime_to_str(&cert->pCertInfo->NotAfter));
1718 TRACE_(chain)("%d extensions\n", cert->pCertInfo->cExtension);
1719 for (i = 0; i < cert->pCertInfo->cExtension; i++)
1720 dump_extension(&cert->pCertInfo->rgExtension[i]);
1721}
1722
1724 PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA, DWORD index)
1725{
1727 BOOL ret;
1728 BYTE usageBits = 0;
1729
1730 ext = CertFindExtension(szOID_KEY_USAGE, cert->pCertInfo->cExtension,
1731 cert->pCertInfo->rgExtension);
1732 if (ext)
1733 {
1735 DWORD size = sizeof(usage);
1736
1737 ret = CryptDecodeObjectEx(cert->dwCertEncodingType, X509_BITS,
1738 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL,
1739 &usage, &size);
1740 if (!ret)
1741 return FALSE;
1742 else if (usage.cbData > 2)
1743 {
1744 /* The key usage extension only defines 9 bits => no more than 2
1745 * bytes are needed to encode all known usages.
1746 */
1747 return FALSE;
1748 }
1749 else
1750 {
1751 /* The only bit relevant to chain validation is the keyCertSign
1752 * bit, which is always in the least significant byte of the
1753 * key usage bits.
1754 */
1755 usageBits = usage.pbData[usage.cbData - 1];
1756 }
1757 }
1758 if (isCA)
1759 {
1760 if (!ext)
1761 {
1762 /* MS appears to violate RFC 5280, section 4.2.1.3 (Key Usage)
1763 * here. Quoting the RFC:
1764 * "This [key usage] extension MUST appear in certificates that
1765 * contain public keys that are used to validate digital signatures
1766 * on other public key certificates or CRLs."
1767 * MS appears to accept certs that do not contain key usage
1768 * extensions as CA certs. V1 and V2 certificates did not have
1769 * extensions, and many root certificates are V1 certificates, so
1770 * perhaps this is prudent. On the other hand, MS also accepts V3
1771 * certs without key usage extensions. Because some CAs, e.g.
1772 * Certum, also do not include key usage extensions in their
1773 * intermediate certificates, we are forced to accept V3
1774 * certificates without key usage extensions as well.
1775 */
1776 ret = TRUE;
1777 }
1778 else
1779 {
1780 if (!(usageBits & CERT_KEY_CERT_SIGN_KEY_USAGE))
1781 {
1782 WARN_(chain)("keyCertSign not asserted on a CA cert\n");
1783 ret = FALSE;
1784 }
1785 else
1786 ret = TRUE;
1787 }
1788 }
1789 else
1790 {
1791 if (ext && (usageBits & CERT_KEY_CERT_SIGN_KEY_USAGE))
1792 {
1793 WARN_(chain)("keyCertSign asserted on a non-CA cert\n");
1794 ret = FALSE;
1795 }
1796 else
1797 ret = TRUE;
1798 }
1799 return ret;
1800}
1801
1803{
1804 BOOL ret = TRUE;
1805 DWORD i;
1806
1807 for (i = 0; ret && i < cert->pCertInfo->cExtension; i++)
1808 {
1809 if (cert->pCertInfo->rgExtension[i].fCritical)
1810 {
1811 LPCSTR oid = cert->pCertInfo->rgExtension[i].pszObjId;
1812
1814 ret = TRUE;
1815 else if (!strcmp(oid, szOID_BASIC_CONSTRAINTS2))
1816 ret = TRUE;
1817 else if (!strcmp(oid, szOID_NAME_CONSTRAINTS))
1818 ret = TRUE;
1819 else if (!strcmp(oid, szOID_KEY_USAGE))
1820 ret = TRUE;
1821 else if (!strcmp(oid, szOID_SUBJECT_ALT_NAME))
1822 ret = TRUE;
1823 else if (!strcmp(oid, szOID_SUBJECT_ALT_NAME2))
1824 ret = TRUE;
1825 else if (!strcmp(oid, szOID_CERT_POLICIES))
1826 ret = TRUE;
1827 else if (!strcmp(oid, szOID_ENHANCED_KEY_USAGE))
1828 ret = TRUE;
1829 else
1830 {
1831 FIXME("unsupported critical extension %s\n",
1832 debugstr_a(oid));
1833 ret = FALSE;
1834 }
1835 }
1836 }
1837 return ret;
1838}
1839
1841{
1842 BOOL ret = TRUE;
1843
1844 /* Checks whether the contents of the cert match the cert's version. */
1845 switch (cert->pCertInfo->dwVersion)
1846 {
1847 case CERT_V1:
1848 /* A V1 cert may not contain unique identifiers. See RFC 5280,
1849 * section 4.1.2.8:
1850 * "These fields MUST only appear if the version is 2 or 3 (Section
1851 * 4.1.2.1). These fields MUST NOT appear if the version is 1."
1852 */
1853 if (cert->pCertInfo->IssuerUniqueId.cbData ||
1854 cert->pCertInfo->SubjectUniqueId.cbData)
1855 ret = FALSE;
1856 /* A V1 cert may not contain extensions. See RFC 5280, section 4.1.2.9:
1857 * "This field MUST only appear if the version is 3 (Section 4.1.2.1)."
1858 */
1859 if (cert->pCertInfo->cExtension)
1860 ret = FALSE;
1861 break;
1862 case CERT_V2:
1863 /* A V2 cert may not contain extensions. See RFC 5280, section 4.1.2.9:
1864 * "This field MUST only appear if the version is 3 (Section 4.1.2.1)."
1865 */
1866 if (cert->pCertInfo->cExtension)
1867 ret = FALSE;
1868 break;
1869 case CERT_V3:
1870 /* Do nothing, all fields are allowed for V3 certs */
1871 break;
1872 default:
1873 WARN_(chain)("invalid cert version %d\n", cert->pCertInfo->dwVersion);
1874 ret = FALSE;
1875 }
1876 return ret;
1877}
1878
1881{
1882 PCERT_CHAIN_ELEMENT rootElement = chain->rgpElement[chain->cElement - 1];
1883 int i;
1884 BOOL pathLengthConstraintViolated = FALSE;
1885 CERT_BASIC_CONSTRAINTS2_INFO constraints = { FALSE, FALSE, 0 };
1886 DWORD status;
1887
1888 TRACE_(chain)("checking chain with %d elements for time %s\n",
1889 chain->cElement, filetime_to_str(time));
1890 for (i = chain->cElement - 1; i >= 0; i--)
1891 {
1892 BOOL isRoot;
1893
1894 if (TRACE_ON(chain))
1895 dump_element(chain->rgpElement[i]->pCertContext);
1896 if (i == chain->cElement - 1)
1898 chain->rgpElement[i]->pCertContext);
1899 else
1900 isRoot = FALSE;
1901 if (!CRYPT_IsCertVersionValid(chain->rgpElement[i]->pCertContext))
1902 {
1903 /* MS appears to accept certs whose versions don't match their
1904 * contents, so there isn't an appropriate error code.
1905 */
1906 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1908 }
1910 chain->rgpElement[i]->pCertContext->pCertInfo) != 0)
1911 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1913 if (i != 0)
1914 {
1915 /* Check the signature of the cert this issued */
1918 (void *)chain->rgpElement[i - 1]->pCertContext,
1920 (void *)chain->rgpElement[i]->pCertContext, 0, NULL))
1921 chain->rgpElement[i - 1]->TrustStatus.dwErrorStatus |=
1923 /* Once a path length constraint has been violated, every remaining
1924 * CA cert's basic constraints is considered invalid.
1925 */
1926 if (pathLengthConstraintViolated)
1927 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1929 else if (!CRYPT_CheckBasicConstraintsForCA(engine,
1930 chain->rgpElement[i]->pCertContext, &constraints, i - 1, isRoot,
1931 &pathLengthConstraintViolated))
1932 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1934 else if (constraints.fPathLenConstraint &&
1935 constraints.dwPathLenConstraint)
1936 {
1937 /* This one's valid - decrement max length */
1938 constraints.dwPathLenConstraint--;
1939 }
1940 }
1941 else
1942 {
1943 /* Check whether end cert has a basic constraints extension */
1945 chain->rgpElement[i]->pCertContext, &constraints, FALSE))
1946 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1948 }
1949 if (!CRYPT_KeyUsageValid(engine, chain->rgpElement[i]->pCertContext,
1950 isRoot, constraints.fCA, i))
1951 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1954 {
1955 /* If the chain is cyclic, then the path length constraints
1956 * are violated, because the chain is infinitely long.
1957 */
1958 pathLengthConstraintViolated = TRUE;
1959 chain->TrustStatus.dwErrorStatus |=
1962 }
1963 /* Check whether every critical extension is supported */
1965 chain->rgpElement[i]->pCertContext))
1966 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1969 CRYPT_CombineTrustStatus(&chain->TrustStatus,
1970 &chain->rgpElement[i]->TrustStatus);
1971 }
1975 {
1976 rootElement->TrustStatus.dwInfoStatus |= status;
1977 CRYPT_CheckRootCert(engine->hRoot, rootElement);
1978 }
1979 CRYPT_CombineTrustStatus(&chain->TrustStatus, &rootElement->TrustStatus);
1980}
1981
1983 HCERTSTORE store, DWORD type, void *para, DWORD flags, PCCERT_CONTEXT prev_issuer)
1984{
1985 CRYPT_URL_ARRAY *urls;
1987 DWORD size;
1988 BOOL res;
1989
1990 issuer = CertFindCertificateInStore(store, cert->dwCertEncodingType, 0, type, para, prev_issuer);
1991 if(issuer) {
1992 TRACE("Found in store %p\n", issuer);
1993 return issuer;
1994 }
1995
1996 /* FIXME: For alternate issuers, we don't search world store nor try to retrieve issuer from URL.
1997 * This needs more tests.
1998 */
1999 if(prev_issuer)
2000 return NULL;
2001
2002 if(engine->hWorld) {
2003 issuer = CertFindCertificateInStore(engine->hWorld, cert->dwCertEncodingType, 0, type, para, NULL);
2004 if(issuer) {
2005 TRACE("Found in world %p\n", issuer);
2006 return issuer;
2007 }
2008 }
2009
2011 if(!res)
2012 return NULL;
2013
2014 urls = HeapAlloc(GetProcessHeap(), 0, size);
2015 if(!urls)
2016 return NULL;
2017
2019 if(res)
2020 {
2021 CERT_CONTEXT *new_cert;
2022 HCERTSTORE new_store;
2023 unsigned i;
2024
2025 for(i=0; i < urls->cUrl; i++)
2026 {
2027 TRACE("Trying URL %s\n", debugstr_w(urls->rgwszUrl[i]));
2028
2031 0, (void**)&new_cert, NULL, NULL, NULL, NULL);
2032 if(!res)
2033 {
2034 TRACE("CryptRetrieveObjectByUrlW failed: %u\n", GetLastError());
2035 continue;
2036 }
2037
2038 /* FIXME: Use new_cert->hCertStore once cert ref count bug is fixed. */
2041 issuer = CertFindCertificateInStore(new_store, cert->dwCertEncodingType, 0, type, para, NULL);
2043 CertCloseStore(new_store, 0);
2044 if(issuer)
2045 {
2046 TRACE("Found downloaded issuer %p\n", issuer);
2047 break;
2048 }
2049 }
2050 }
2051
2052 HeapFree(GetProcessHeap(), 0, urls);
2053 return issuer;
2054}
2055
2057 HCERTSTORE store, PCCERT_CONTEXT subject, PCCERT_CONTEXT prevIssuer,
2058 DWORD flags, DWORD *infoStatus)
2059{
2062 DWORD size;
2063
2064 *infoStatus = 0;
2066 subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension)))
2067 {
2069 BOOL ret;
2070
2072 X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData,
2074 &info, &size);
2075 if (ret)
2076 {
2077 CERT_ID id;
2078
2079 if (info->CertIssuer.cbData && info->CertSerialNumber.cbData)
2080 {
2081 id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
2082 memcpy(&id.u.IssuerSerialNumber.Issuer, &info->CertIssuer,
2083 sizeof(CERT_NAME_BLOB));
2084 memcpy(&id.u.IssuerSerialNumber.SerialNumber,
2085 &info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB));
2086
2087 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2088 if (issuer)
2089 {
2090 TRACE_(chain)("issuer found by issuer/serial number\n");
2092 }
2093 }
2094 else if (info->KeyId.cbData)
2095 {
2096 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
2097
2098 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
2099 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2100 if (issuer)
2101 {
2102 TRACE_(chain)("issuer found by key id\n");
2103 *infoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER;
2104 }
2105 }
2106 LocalFree(info);
2107 }
2108 }
2110 subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension)))
2111 {
2113 BOOL ret;
2114
2116 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData,
2118 &info, &size);
2119 if (ret)
2120 {
2121 CERT_ID id;
2122
2123 if (info->AuthorityCertIssuer.cAltEntry &&
2124 info->AuthorityCertSerialNumber.cbData)
2125 {
2126 PCERT_ALT_NAME_ENTRY directoryName = NULL;
2127 DWORD i;
2128
2129 for (i = 0; !directoryName &&
2130 i < info->AuthorityCertIssuer.cAltEntry; i++)
2131 if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice
2133 directoryName =
2134 &info->AuthorityCertIssuer.rgAltEntry[i];
2135 if (directoryName)
2136 {
2137 id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
2138 memcpy(&id.u.IssuerSerialNumber.Issuer,
2139 &directoryName->u.DirectoryName, sizeof(CERT_NAME_BLOB));
2140 memcpy(&id.u.IssuerSerialNumber.SerialNumber,
2141 &info->AuthorityCertSerialNumber,
2142 sizeof(CRYPT_INTEGER_BLOB));
2143
2144 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2145 if (issuer)
2146 {
2147 TRACE_(chain)("issuer found by directory name\n");
2149 }
2150 }
2151 else
2152 FIXME("no supported name type in authority key id2\n");
2153 }
2154 else if (info->KeyId.cbData)
2155 {
2156 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
2157 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
2158 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2159 if (issuer)
2160 {
2161 TRACE_(chain)("issuer found by key id\n");
2162 *infoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER;
2163 }
2164 }
2165 LocalFree(info);
2166 }
2167 }
2168 else
2169 {
2170 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_SUBJECT_NAME,
2171 &subject->pCertInfo->Issuer, flags, prevIssuer);
2172 TRACE_(chain)("issuer found by name\n");
2174 }
2175 return issuer;
2176}
2177
2178/* Builds a simple chain by finding an issuer for the last cert in the chain,
2179 * until reaching a self-signed cert, or until no issuer can be found.
2180 */
2183{
2184 BOOL ret = TRUE;
2185 PCCERT_CONTEXT cert = chain->rgpElement[chain->cElement - 1]->pCertContext;
2186
2187 while (ret && !CRYPT_IsSimpleChainCyclic(chain) &&
2189 {
2191 &chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
2192
2193 if (issuer)
2194 {
2196 chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
2197 /* CRYPT_AddCertToSimpleChain add-ref's the issuer, so free it to
2198 * close the enumeration that found it
2199 */
2201 cert = issuer;
2202 }
2203 else
2204 {
2205 TRACE_(chain)("Couldn't find issuer, halting chain creation\n");
2206 chain->TrustStatus.dwErrorStatus |= CERT_TRUST_IS_PARTIAL_CHAIN;
2207 break;
2208 }
2209 }
2210 return ret;
2211}
2212
2214{
2215 if (!pTime)
2216 return "(nil)";
2217 return wine_dbg_sprintf("%p (%s)", pTime, filetime_to_str(pTime));
2218}
2219
2222 PCERT_SIMPLE_CHAIN *ppChain)
2223{
2224 BOOL ret = FALSE;
2226
2227 TRACE("(%p, %p, %p, %s)\n", engine, world, cert, debugstr_filetime(pTime));
2228
2230 if (chain)
2231 {
2232 memset(chain, 0, sizeof(CERT_SIMPLE_CHAIN));
2233 chain->cbSize = sizeof(CERT_SIMPLE_CHAIN);
2235 if (ret)
2236 {
2237 ret = CRYPT_BuildSimpleChain(engine, world, flags, chain);
2238 if (ret)
2240 }
2241 if (!ret)
2242 {
2244 chain = NULL;
2245 }
2246 *ppChain = chain;
2247 }
2248 return ret;
2249}
2250
2253 CertificateChain **ppChain)
2254{
2255 PCERT_SIMPLE_CHAIN simpleChain = NULL;
2256 HCERTSTORE world;
2257 BOOL ret;
2258
2261 CertAddStoreToCollection(world, engine->hWorld, 0, 0);
2262 if (hAdditionalStore)
2264 /* FIXME: only simple chains are supported for now, as CTLs aren't
2265 * supported yet.
2266 */
2267 if ((ret = CRYPT_GetSimpleChainForCert(engine, world, cert, pTime, flags, &simpleChain)))
2268 {
2270
2271 if (chain)
2272 {
2273 chain->ref = 1;
2274 chain->world = world;
2275 chain->context.cbSize = sizeof(CERT_CHAIN_CONTEXT);
2276 chain->context.TrustStatus = simpleChain->TrustStatus;
2277 chain->context.cChain = 1;
2278 chain->context.rgpChain = CryptMemAlloc(sizeof(PCERT_SIMPLE_CHAIN));
2279 chain->context.rgpChain[0] = simpleChain;
2280 chain->context.cLowerQualityChainContext = 0;
2281 chain->context.rgpLowerQualityChainContext = NULL;
2282 chain->context.fHasRevocationFreshnessTime = FALSE;
2283 chain->context.dwRevocationFreshnessTime = 0;
2284 }
2285 else
2286 {
2287 CRYPT_FreeSimpleChain(simpleChain);
2288 ret = FALSE;
2289 }
2290 *ppChain = chain;
2291 }
2292 return ret;
2293}
2294
2295/* Makes and returns a copy of chain, up to and including element iElement. */
2297 const CERT_SIMPLE_CHAIN *chain, DWORD iElement)
2298{
2300
2301 if (copy)
2302 {
2303 memset(copy, 0, sizeof(CERT_SIMPLE_CHAIN));
2304 copy->cbSize = sizeof(CERT_SIMPLE_CHAIN);
2305 copy->rgpElement =
2306 CryptMemAlloc((iElement + 1) * sizeof(PCERT_CHAIN_ELEMENT));
2307 if (copy->rgpElement)
2308 {
2309 DWORD i;
2310 BOOL ret = TRUE;
2311
2312 memset(copy->rgpElement, 0,
2313 (iElement + 1) * sizeof(PCERT_CHAIN_ELEMENT));
2314 for (i = 0; ret && i <= iElement; i++)
2315 {
2318
2319 if (element)
2320 {
2321 *element = *chain->rgpElement[i];
2323 chain->rgpElement[i]->pCertContext);
2324 /* Reset the trust status of the copied element, it'll get
2325 * rechecked after the new chain is done.
2326 */
2327 memset(&element->TrustStatus, 0, sizeof(CERT_TRUST_STATUS));
2328 copy->rgpElement[copy->cElement++] = element;
2329 }
2330 else
2331 ret = FALSE;
2332 }
2333 if (!ret)
2334 {
2335 for (i = 0; i <= iElement; i++)
2336 CryptMemFree(copy->rgpElement[i]);
2337 CryptMemFree(copy->rgpElement);
2339 copy = NULL;
2340 }
2341 }
2342 else
2343 {
2345 copy = NULL;
2346 }
2347 }
2348 return copy;
2349}
2350
2352{
2353 DWORD i;
2354
2355 for (i = 0; i < chain->context.cLowerQualityChainContext; i++)
2356 CertFreeCertificateChain(chain->context.rgpLowerQualityChainContext[i]);
2357 CryptMemFree(chain->context.rgpLowerQualityChainContext);
2358 chain->context.cLowerQualityChainContext = 0;
2359 chain->context.rgpLowerQualityChainContext = NULL;
2360}
2361
2363{
2364 DWORD i;
2365
2367 for (i = 0; i < chain->context.cChain; i++)
2368 CRYPT_FreeSimpleChain(chain->context.rgpChain[i]);
2369 CryptMemFree(chain->context.rgpChain);
2370 CertCloseStore(chain->world, 0);
2372}
2373
2374/* Makes and returns a copy of chain, up to and including element iElement of
2375 * simple chain iChain.
2376 */
2378 DWORD iChain, DWORD iElement)
2379{
2381
2382 if (copy)
2383 {
2384 copy->ref = 1;
2385 copy->world = CertDuplicateStore(chain->world);
2386 copy->context.cbSize = sizeof(CERT_CHAIN_CONTEXT);
2387 /* Leave the trust status of the copied chain unset, it'll get
2388 * rechecked after the new chain is done.
2389 */
2390 memset(&copy->context.TrustStatus, 0, sizeof(CERT_TRUST_STATUS));
2391 copy->context.cLowerQualityChainContext = 0;
2392 copy->context.rgpLowerQualityChainContext = NULL;
2393 copy->context.fHasRevocationFreshnessTime = FALSE;
2394 copy->context.dwRevocationFreshnessTime = 0;
2395 copy->context.rgpChain = CryptMemAlloc(
2396 (iChain + 1) * sizeof(PCERT_SIMPLE_CHAIN));
2397 if (copy->context.rgpChain)
2398 {
2399 BOOL ret = TRUE;
2400 DWORD i;
2401
2402 memset(copy->context.rgpChain, 0,
2403 (iChain + 1) * sizeof(PCERT_SIMPLE_CHAIN));
2404 if (iChain)
2405 {
2406 for (i = 0; ret && iChain && i < iChain - 1; i++)
2407 {
2408 copy->context.rgpChain[i] =
2409 CRYPT_CopySimpleChainToElement(chain->context.rgpChain[i],
2410 chain->context.rgpChain[i]->cElement - 1);
2411 if (!copy->context.rgpChain[i])
2412 ret = FALSE;
2413 }
2414 }
2415 else
2416 i = 0;
2417 if (ret)
2418 {
2419 copy->context.rgpChain[i] =
2420 CRYPT_CopySimpleChainToElement(chain->context.rgpChain[i],
2421 iElement);
2422 if (!copy->context.rgpChain[i])
2423 ret = FALSE;
2424 }
2425 if (!ret)
2426 {
2428 copy = NULL;
2429 }
2430 else
2431 copy->context.cChain = iChain + 1;
2432 }
2433 else
2434 {
2436 copy = NULL;
2437 }
2438 }
2439 return copy;
2440}
2441
2445{
2446 CertificateChain *alternate;
2447
2448 TRACE("(%p, %s, %p, %p)\n", engine, debugstr_filetime(pTime),
2450
2451 /* Always start with the last "lower quality" chain to ensure a consistent
2452 * order of alternate creation:
2453 */
2454 if (chain->context.cLowerQualityChainContext)
2455 chain = (CertificateChain*)chain->context.rgpLowerQualityChainContext[
2456 chain->context.cLowerQualityChainContext - 1];
2457 /* A chain with only one element can't have any alternates */
2458 if (chain->context.cChain <= 1 && chain->context.rgpChain[0]->cElement <= 1)
2459 alternate = NULL;
2460 else
2461 {
2462 DWORD i, j, infoStatus;
2463 PCCERT_CONTEXT alternateIssuer = NULL;
2464
2465 alternate = NULL;
2466 for (i = 0; !alternateIssuer && i < chain->context.cChain; i++)
2467 for (j = 0; !alternateIssuer &&
2468 j < chain->context.rgpChain[i]->cElement - 1; j++)
2469 {
2470 PCCERT_CONTEXT subject =
2471 chain->context.rgpChain[i]->rgpElement[j]->pCertContext;
2473 chain->context.rgpChain[i]->rgpElement[j + 1]->pCertContext);
2474
2475 alternateIssuer = CRYPT_GetIssuer(engine, prevIssuer->hCertStore,
2476 subject, prevIssuer, flags, &infoStatus);
2477 }
2478 if (alternateIssuer)
2479 {
2480 i--;
2481 j--;
2482 alternate = CRYPT_CopyChainToElement(chain, i, j);
2483 if (alternate)
2484 {
2486 alternate->context.rgpChain[i], alternateIssuer, infoStatus);
2487
2488 /* CRYPT_AddCertToSimpleChain add-ref's the issuer, so free it
2489 * to close the enumeration that found it
2490 */
2491 CertFreeCertificateContext(alternateIssuer);
2492 if (ret)
2493 {
2494 ret = CRYPT_BuildSimpleChain(engine, alternate->world,
2495 flags, alternate->context.rgpChain[i]);
2496 if (ret)
2498 alternate->context.rgpChain[i], pTime);
2500 &alternate->context.rgpChain[i]->TrustStatus);
2501 }
2502 if (!ret)
2503 {
2504 CRYPT_FreeChainContext(alternate);
2505 alternate = NULL;
2506 }
2507 }
2508 }
2509 }
2510 TRACE("%p\n", alternate);
2511 return alternate;
2512}
2513
2514#define CHAIN_QUALITY_SIGNATURE_VALID 0x16
2515#define CHAIN_QUALITY_TIME_VALID 8
2516#define CHAIN_QUALITY_COMPLETE_CHAIN 4
2517#define CHAIN_QUALITY_BASIC_CONSTRAINTS 2
2518#define CHAIN_QUALITY_TRUSTED_ROOT 1
2519
2520#define CHAIN_QUALITY_HIGHEST \
2521 CHAIN_QUALITY_SIGNATURE_VALID | CHAIN_QUALITY_TIME_VALID | \
2522 CHAIN_QUALITY_COMPLETE_CHAIN | CHAIN_QUALITY_BASIC_CONSTRAINTS | \
2523 CHAIN_QUALITY_TRUSTED_ROOT
2524
2525#define IS_TRUST_ERROR_SET(TrustStatus, bits) \
2526 (TrustStatus)->dwErrorStatus & (bits)
2527
2529{
2531
2532 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2534 quality &= ~CHAIN_QUALITY_TRUSTED_ROOT;
2535 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2537 quality &= ~CHAIN_QUALITY_BASIC_CONSTRAINTS;
2538 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2540 quality &= ~CHAIN_QUALITY_COMPLETE_CHAIN;
2541 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2543 quality &= ~CHAIN_QUALITY_TIME_VALID;
2544 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2546 quality &= ~CHAIN_QUALITY_SIGNATURE_VALID;
2547 return quality;
2548}
2549
2550/* Chooses the highest quality chain among chain and its "lower quality"
2551 * alternate chains. Returns the highest quality chain, with all other
2552 * chains as lower quality chains of it.
2553 */
2556{
2557 DWORD i;
2558
2559 /* There are always only two chains being considered: chain, and an
2560 * alternate at chain->rgpLowerQualityChainContext[i]. If the alternate
2561 * has a higher quality than chain, the alternate gets assigned the lower
2562 * quality contexts, with chain taking the alternate's place among the
2563 * lower quality contexts.
2564 */
2565 for (i = 0; i < chain->context.cLowerQualityChainContext; i++)
2566 {
2567 CertificateChain *alternate =
2568 (CertificateChain*)chain->context.rgpLowerQualityChainContext[i];
2569
2571 {
2573 chain->context.cLowerQualityChainContext;
2575 chain->context.rgpLowerQualityChainContext;
2578 chain->context.cLowerQualityChainContext = 0;
2579 chain->context.rgpLowerQualityChainContext = NULL;
2580 chain = alternate;
2581 }
2582 }
2583 return chain;
2584}
2585
2587 const CertificateChain *alternate)
2588{
2589 BOOL ret;
2590
2591 if (chain->context.cLowerQualityChainContext)
2592 chain->context.rgpLowerQualityChainContext =
2593 CryptMemRealloc(chain->context.rgpLowerQualityChainContext,
2594 (chain->context.cLowerQualityChainContext + 1) *
2595 sizeof(PCCERT_CHAIN_CONTEXT));
2596 else
2597 chain->context.rgpLowerQualityChainContext =
2599 if (chain->context.rgpLowerQualityChainContext)
2600 {
2601 chain->context.rgpLowerQualityChainContext[
2602 chain->context.cLowerQualityChainContext++] =
2603 (PCCERT_CHAIN_CONTEXT)alternate;
2604 ret = TRUE;
2605 }
2606 else
2607 ret = FALSE;
2608 return ret;
2609}
2610
2613{
2614 DWORD j, iElement;
2616
2617 for (j = 0, iElement = 0; !element && j < chain->cChain; j++)
2618 {
2619 if (iElement + chain->rgpChain[j]->cElement < i)
2620 iElement += chain->rgpChain[j]->cElement;
2621 else
2622 element = chain->rgpChain[j]->rgpElement[i - iElement];
2623 }
2624 return element;
2625}
2626
2631
2634 const CERT_CHAIN_PARA *pChainPara, DWORD chainFlags)
2635{
2636 DWORD cContext;
2637
2638 if (chainFlags & CERT_CHAIN_REVOCATION_CHECK_END_CERT)
2639 cContext = 1;
2640 else if ((chainFlags & CERT_CHAIN_REVOCATION_CHECK_CHAIN) ||
2642 {
2643 DWORD i;
2644
2645 for (i = 0, cContext = 0; i < chain->cChain; i++)
2646 {
2647 if (i < chain->cChain - 1 ||
2649 cContext += chain->rgpChain[i]->cElement;
2650 else
2651 cContext += chain->rgpChain[i]->cElement - 1;
2652 }
2653 }
2654 else
2655 cContext = 0;
2656 if (cContext)
2657 {
2658 DWORD i, j, iContext, revocationFlags;
2659 CERT_REVOCATION_PARA revocationPara = { sizeof(revocationPara), 0 };
2660 CERT_REVOCATION_STATUS revocationStatus =
2661 { sizeof(revocationStatus), 0 };
2662 BOOL ret;
2663
2664 revocationFlags = CERT_VERIFY_REV_CHAIN_FLAG;
2666 revocationFlags |= CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION;
2669 revocationPara.pftTimeToUse = pTime;
2670 if (hAdditionalStore)
2671 {
2672 revocationPara.cCertStore = 1;
2673 revocationPara.rgCertStore = &hAdditionalStore;
2674 revocationPara.hCrlStore = hAdditionalStore;
2675 }
2676 if (pChainPara->cbSize == sizeof(CERT_CHAIN_PARA))
2677 {
2678 revocationPara.dwUrlRetrievalTimeout =
2679 pChainPara->dwUrlRetrievalTimeout;
2680 revocationPara.fCheckFreshnessTime =
2681 pChainPara->fCheckRevocationFreshnessTime;
2682 revocationPara.dwFreshnessTime =
2683 pChainPara->dwRevocationFreshnessTime;
2684 }
2685 for (i = 0, iContext = 0; iContext < cContext && i < chain->cChain; i++)
2686 {
2687 for (j = 0; iContext < cContext &&
2688 j < chain->rgpChain[i]->cElement; j++, iContext++)
2689 {
2690 PCCERT_CONTEXT certToCheck =
2691 chain->rgpChain[i]->rgpElement[j]->pCertContext;
2692
2693 if (j < chain->rgpChain[i]->cElement - 1)
2694 revocationPara.pIssuerCert =
2695 chain->rgpChain[i]->rgpElement[j + 1]->pCertContext;
2696 else
2697 revocationPara.pIssuerCert = NULL;
2699 CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certToCheck,
2700 revocationFlags, &revocationPara, &revocationStatus);
2701
2702 if (!ret && chainFlags & CERT_CHAIN_REVOCATION_CHECK_CHAIN
2703 && revocationStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK && revocationPara.pIssuerCert == NULL)
2704 ret = TRUE;
2705
2706 if (!ret)
2707 {
2709 chain, iContext);
2710 DWORD error;
2711
2712 switch (revocationStatus.dwError)
2713 {
2717 /* If the revocation status is unknown, it's assumed
2718 * to be offline too.
2719 */
2722 break;
2725 break;
2726 case CRYPT_E_REVOKED:
2728 break;
2729 default:
2730 WARN("unmapped error %08x\n", revocationStatus.dwError);
2731 error = 0;
2732 }
2733 if (element)
2734 {
2735 /* FIXME: set element's pRevocationInfo member */
2736 element->TrustStatus.dwErrorStatus |= error;
2737 }
2738 chain->TrustStatus.dwErrorStatus |= error;
2739 }
2740 }
2741 }
2742 }
2743}
2744
2747{
2748 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA_NO_EXTRA_FIELDS) &&
2749 pChainPara->RequestedUsage.Usage.cUsageIdentifier)
2750 {
2751 PCCERT_CONTEXT endCert;
2753 BOOL validForUsage;
2754
2755 /* A chain, if created, always includes the end certificate */
2756 endCert = chain->rgpChain[0]->rgpElement[0]->pCertContext;
2757 /* The extended key usage extension specifies how a certificate's
2758 * public key may be used. From RFC 5280, section 4.2.1.12:
2759 * "This extension indicates one or more purposes for which the
2760 * certified public key may be used, in addition to or in place of the
2761 * basic purposes indicated in the key usage extension."
2762 * If the extension is present, it only satisfies the requested usage
2763 * if that usage is included in the extension:
2764 * "If the extension is present, then the certificate MUST only be used
2765 * for one of the purposes indicated."
2766 * There is also the special anyExtendedKeyUsage OID, but it doesn't
2767 * have to be respected:
2768 * "Applications that require the presence of a particular purpose
2769 * MAY reject certificates that include the anyExtendedKeyUsage OID
2770 * but not the particular OID expected for the application."
2771 * For now, I'm being more conservative and ignoring the presence of
2772 * the anyExtendedKeyUsage OID.
2773 */
2775 endCert->pCertInfo->cExtension, endCert->pCertInfo->rgExtension)))
2776 {
2777 const CERT_ENHKEY_USAGE *requestedUsage =
2778 &pChainPara->RequestedUsage.Usage;
2780 DWORD size;
2781
2783 X509_ENHANCED_KEY_USAGE, ext->Value.pbData, ext->Value.cbData,
2785 {
2786 if (pChainPara->RequestedUsage.dwType == USAGE_MATCH_TYPE_AND)
2787 {
2788 DWORD i, j;
2789
2790 /* For AND matches, all usages must be present */
2791 validForUsage = TRUE;
2792 for (i = 0; validForUsage &&
2793 i < requestedUsage->cUsageIdentifier; i++)
2794 {
2795 BOOL match = FALSE;
2796
2797 for (j = 0; !match && j < usage->cUsageIdentifier; j++)
2798 match = !strcmp(usage->rgpszUsageIdentifier[j],
2799 requestedUsage->rgpszUsageIdentifier[i]);
2800 if (!match)
2801 validForUsage = FALSE;
2802 }
2803 }
2804 else
2805 {
2806 DWORD i, j;
2807
2808 /* For OR matches, any matching usage suffices */
2809 validForUsage = FALSE;
2810 for (i = 0; !validForUsage &&
2811 i < requestedUsage->cUsageIdentifier; i++)
2812 {
2813 for (j = 0; !validForUsage &&
2814 j < usage->cUsageIdentifier; j++)
2815 validForUsage =
2816 !strcmp(usage->rgpszUsageIdentifier[j],
2817 requestedUsage->rgpszUsageIdentifier[i]);
2818 }
2819 }
2821 }
2822 else
2823 validForUsage = FALSE;
2824 }
2825 else
2826 {
2827 /* If the extension isn't present, any interpretation is valid:
2828 * "Certificate using applications MAY require that the extended
2829 * key usage extension be present and that a particular purpose
2830 * be indicated in order for the certificate to be acceptable to
2831 * that application."
2832 * Not all web sites include the extended key usage extension, so
2833 * accept chains without it.
2834 */
2835 TRACE_(chain)("requested usage from certificate with no usages\n");
2836 validForUsage = TRUE;
2837 }
2838 if (!validForUsage)
2839 {
2840 chain->TrustStatus.dwErrorStatus |=
2842 chain->rgpChain[0]->rgpElement[0]->TrustStatus.dwErrorStatus |=
2844 }
2845 }
2846 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA) &&
2847 pChainPara->RequestedIssuancePolicy.Usage.cUsageIdentifier)
2848 FIXME("unimplemented for RequestedIssuancePolicy\n");
2849}
2850
2851static void dump_usage_match(LPCSTR name, const CERT_USAGE_MATCH *usageMatch)
2852{
2853 if (usageMatch->Usage.cUsageIdentifier)
2854 {
2855 DWORD i;
2856
2857 TRACE_(chain)("%s: %s\n", name,
2858 usageMatch->dwType == USAGE_MATCH_TYPE_AND ? "AND" : "OR");
2859 for (i = 0; i < usageMatch->Usage.cUsageIdentifier; i++)
2860 TRACE_(chain)("%s\n", usageMatch->Usage.rgpszUsageIdentifier[i]);
2861 }
2862}
2863
2865{
2866 TRACE_(chain)("%d\n", pChainPara->cbSize);
2867 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA_NO_EXTRA_FIELDS))
2868 dump_usage_match("RequestedUsage", &pChainPara->RequestedUsage);
2869 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA))
2870 {
2871 dump_usage_match("RequestedIssuancePolicy",
2872 &pChainPara->RequestedIssuancePolicy);
2873 TRACE_(chain)("%d\n", pChainPara->dwUrlRetrievalTimeout);
2874 TRACE_(chain)("%d\n", pChainPara->fCheckRevocationFreshnessTime);
2875 TRACE_(chain)("%d\n", pChainPara->dwRevocationFreshnessTime);
2876 }
2877}
2878
2883{
2884 CertificateChainEngine *engine;
2885 BOOL ret;
2887
2888 TRACE("(%p, %p, %s, %p, %p, %08x, %p, %p)\n", hChainEngine, pCertContext,
2891
2892 engine = get_chain_engine(hChainEngine, TRUE);
2893 if (!engine)
2894 return FALSE;
2895
2896 if (ppChainContext)
2898 if (!pChainPara)
2899 {
2901 return FALSE;
2902 }
2904 {
2906 return FALSE;
2907 }
2908
2909 if (TRACE_ON(chain))
2911 /* FIXME: what about HCCE_LOCAL_MACHINE? */
2914 if (ret)
2915 {
2916 CertificateChain *alternate = NULL;
2917 PCERT_CHAIN_CONTEXT pChain;
2918
2919 do {
2920 alternate = CRYPT_BuildAlternateContextFromChain(engine,
2922
2923 /* Alternate contexts are added as "lower quality" contexts of
2924 * chain, to avoid loops in alternate chain creation.
2925 * The highest-quality chain is chosen at the end.
2926 */
2927 if (alternate)
2929 } while (ret && alternate);
2933 pChain = (PCERT_CHAIN_CONTEXT)chain;
2937 TRACE_(chain)("error status: %08x\n",
2938 pChain->TrustStatus.dwErrorStatus);
2939 if (ppChainContext)
2940 *ppChainContext = pChain;
2941 else
2943 }
2944 TRACE("returning %d\n", ret);
2945 return ret;
2946}
2947
2949 PCCERT_CHAIN_CONTEXT pChainContext)
2950{
2951 CertificateChain *chain = (CertificateChain*)pChainContext;
2952
2953 TRACE("(%p)\n", pChainContext);
2954
2955 if (chain)
2957 return pChainContext;
2958}
2959
2961{
2962 CertificateChain *chain = (CertificateChain*)pChainContext;
2963
2964 TRACE("(%p)\n", pChainContext);
2965
2966 if (chain)
2967 {
2968 if (InterlockedDecrement(&chain->ref) == 0)
2970 }
2971}
2972
2974 DWORD certEncodingType, DWORD findFlags, DWORD findType,
2975 const void *findPara, PCCERT_CHAIN_CONTEXT prevChainContext)
2976{
2977 FIXME("(%p, %08x, %08x, %d, %p, %p): stub\n", store, certEncodingType,
2978 findFlags, findType, findPara, prevChainContext);
2979 return NULL;
2980}
2981
2983 LONG *iChain, LONG *iElement)
2984{
2985 DWORD i, j;
2986
2987 for (i = 0; i < chain->cChain; i++)
2988 for (j = 0; j < chain->rgpChain[i]->cElement; j++)
2989 if (chain->rgpChain[i]->rgpElement[j]->TrustStatus.dwErrorStatus &
2990 error)
2991 {
2992 *iChain = i;
2993 *iElement = j;
2994 return;
2995 }
2996}
2997
2999 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3000 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3001{
3002 DWORD checks = 0;
3003
3004 if (pPolicyPara)
3005 checks = pPolicyPara->dwFlags;
3006 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = -1;
3007 pPolicyStatus->dwError = NO_ERROR;
3008 if (pChainContext->TrustStatus.dwErrorStatus &
3010 {
3011 pPolicyStatus->dwError = TRUST_E_CERT_SIGNATURE;
3012 find_element_with_error(pChainContext,
3014 &pPolicyStatus->lElementIndex);
3015 }
3016 else if (pChainContext->TrustStatus.dwErrorStatus & CERT_TRUST_IS_CYCLIC)
3017 {
3018 pPolicyStatus->dwError = CERT_E_CHAINING;
3020 &pPolicyStatus->lChainIndex, &pPolicyStatus->lElementIndex);
3021 /* For a cyclic chain, which element is a cycle isn't meaningful */
3022 pPolicyStatus->lElementIndex = -1;
3023 }
3024 if (!pPolicyStatus->dwError &&
3027 {
3028 pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
3029 find_element_with_error(pChainContext,
3031 &pPolicyStatus->lElementIndex);
3032 }
3033 if (!pPolicyStatus->dwError &&
3035 {
3036 pPolicyStatus->dwError = CERT_E_EXPIRED;
3037 find_element_with_error(pChainContext,
3039 &pPolicyStatus->lElementIndex);
3040 }
3041 if (!pPolicyStatus->dwError &&
3042 pChainContext->TrustStatus.dwErrorStatus &
3045 {
3046 pPolicyStatus->dwError = CERT_E_WRONG_USAGE;
3047 find_element_with_error(pChainContext,
3049 &pPolicyStatus->lElementIndex);
3050 }
3051 if (!pPolicyStatus->dwError &&
3052 pChainContext->TrustStatus.dwErrorStatus &
3055 {
3056 pPolicyStatus->dwError = CERT_E_CRITICAL;
3057 find_element_with_error(pChainContext,
3059 &pPolicyStatus->lElementIndex);
3060 }
3061 return TRUE;
3062}
3063
30650x30,0x47,0x02,0x40,0x81,0x55,0x22,0xb9,0x8a,0xa4,0x6f,0xed,0xd6,0xe7,0xd9,
30660x66,0x0f,0x55,0xbc,0xd7,0xcd,0xd5,0xbc,0x4e,0x40,0x02,0x21,0xa2,0xb1,0xf7,
30670x87,0x30,0x85,0x5e,0xd2,0xf2,0x44,0xb9,0xdc,0x9b,0x75,0xb6,0xfb,0x46,0x5f,
30680x42,0xb6,0x9d,0x23,0x36,0x0b,0xde,0x54,0x0f,0xcd,0xbd,0x1f,0x99,0x2a,0x10,
30690x58,0x11,0xcb,0x40,0xcb,0xb5,0xa7,0x41,0x02,0x03,0x01,0x00,0x01 };
30710x30,0x47,0x02,0x40,0x9c,0x50,0x05,0x1d,0xe2,0x0e,0x4c,0x53,0xd8,0xd9,0xb5,
30720xe5,0xfd,0xe9,0xe3,0xad,0x83,0x4b,0x80,0x08,0xd9,0xdc,0xe8,0xe8,0x35,0xf8,
30730x11,0xf1,0xe9,0x9b,0x03,0x7a,0x65,0x64,0x76,0x35,0xce,0x38,0x2c,0xf2,0xb6,
30740x71,0x9e,0x06,0xd9,0xbf,0xbb,0x31,0x69,0xa3,0xf6,0x30,0xa0,0x78,0x7b,0x18,
30750xdd,0x50,0x4d,0x79,0x1e,0xeb,0x61,0xc1,0x02,0x03,0x01,0x00,0x01 };
3076
3079{
3080 if (extraPara)
3081 {
3082 TRACE_(chain)("cbSize = %d\n", extraPara->cbSize);
3083 TRACE_(chain)("dwRegPolicySettings = %08x\n",
3084 extraPara->dwRegPolicySettings);
3085 TRACE_(chain)("pSignerInfo = %p\n", extraPara->pSignerInfo);
3086 }
3087}
3088
3090 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3091 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3092{
3093 BOOL ret = verify_base_policy(szPolicyOID, pChainContext, pPolicyPara,
3094 pPolicyStatus);
3096
3097 if (pPolicyPara)
3098 extraPara = pPolicyPara->pvExtraPolicyPara;
3099 if (TRACE_ON(chain))
3101 if (ret && pPolicyStatus->dwError == CERT_E_UNTRUSTEDROOT)
3102 {
3103 CERT_PUBLIC_KEY_INFO msPubKey = { { 0 } };
3104 BOOL isMSTestRoot = FALSE;
3105 PCCERT_CONTEXT failingCert =
3106 pChainContext->rgpChain[pPolicyStatus->lChainIndex]->
3107 rgpElement[pPolicyStatus->lElementIndex]->pCertContext;
3108 DWORD i;
3109 CRYPT_DATA_BLOB keyBlobs[] = {
3110 { sizeof(msTestPubKey1), msTestPubKey1 },
3111 { sizeof(msTestPubKey2), msTestPubKey2 },
3112 };
3113
3114 /* Check whether the root is an MS test root */
3115 for (i = 0; !isMSTestRoot && i < ARRAY_SIZE(keyBlobs); i++)
3116 {
3117 msPubKey.PublicKey.cbData = keyBlobs[i].cbData;
3118 msPubKey.PublicKey.pbData = keyBlobs[i].pbData;
3121 &failingCert->pCertInfo->SubjectPublicKeyInfo, &msPubKey))
3122 isMSTestRoot = TRUE;
3123 }
3124 if (isMSTestRoot)
3125 pPolicyStatus->dwError = CERT_E_UNTRUSTEDTESTROOT;
3126 }
3127 return ret;
3128}
3129
3131 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3132 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3133{
3134 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = -1;
3135 if (pChainContext->TrustStatus.dwErrorStatus &
3137 {
3138 pPolicyStatus->dwError = TRUST_E_BASIC_CONSTRAINTS;
3139 find_element_with_error(pChainContext,
3141 &pPolicyStatus->lElementIndex);
3142 }
3143 else
3144 pPolicyStatus->dwError = NO_ERROR;
3145 return TRUE;
3146}
3147
3150{
3151 BOOL matches = FALSE;
3153 DWORD size;
3154
3156 /* This could be spoofed by the embedded NULL vulnerability, since the
3157 * returned CERT_ALT_NAME_INFO doesn't have a way to indicate the
3158 * encoded length of a name. Fortunately CryptDecodeObjectEx fails if
3159 * the encoded form of the name contains a NULL.
3160 */
3162 ext->Value.pbData, ext->Value.cbData,
3164 &subjectName, &size))
3165 {
3166 DWORD i;
3167
3168 /* RFC 5280 states that multiple instances of each name type may exist,
3169 * in section 4.2.1.6:
3170 * "Multiple name forms, and multiple instances of each name form,
3171 * MAY be included."
3172 * It doesn't specify the behavior in such cases, but both RFC 2818
3173 * and RFC 2595 explicitly accept a certificate if any name matches.
3174 */
3175 for (i = 0; !matches && i < subjectName->cAltEntry; i++)
3176 {
3177 if (subjectName->rgAltEntry[i].dwAltNameChoice ==
3179 {
3180 TRACE_(chain)("dNSName: %s\n", debugstr_w(
3181 subjectName->rgAltEntry[i].u.pwszDNSName));
3182 if (subjectName->rgAltEntry[i].u.pwszDNSName[0] == '*')
3183 {
3184 LPCWSTR server_name_dot;
3185
3186 /* Matching a wildcard: a wildcard matches a single name
3187 * component, which is terminated by a dot. RFC 1034
3188 * doesn't define whether multiple wildcards are allowed,
3189 * but I will assume that they are not until proven
3190 * otherwise. RFC 1034 also states that 'the "*" label
3191 * always matches at least one whole label and sometimes
3192 * more, but always whole labels.' Native crypt32 does not
3193 * match more than one label with a wildcard, so I do the
3194 * same here. Thus, a wildcard only accepts the first
3195 * label, then requires an exact match of the remaining
3196 * string.
3197 */
3198 server_name_dot = strchrW(server_name, '.');
3199 if (server_name_dot)
3200 {
3201 if (!strcmpiW(server_name_dot,
3202 subjectName->rgAltEntry[i].u.pwszDNSName + 1))
3203 matches = TRUE;
3204 }
3205 }
3206 else if (!strcmpiW(server_name,
3207 subjectName->rgAltEntry[i].u.pwszDNSName))
3208 matches = TRUE;
3209 }
3210 }
3212 }
3213 return matches;
3214}
3215
3217 LPCWSTR component)
3218{
3219 BOOL matches = FALSE;
3220 DWORD i, j;
3221
3222 for (i = 0; !matches && i < name->cRDN; i++)
3223 for (j = 0; j < name->rgRDN[i].cRDNAttr; j++)
3225 name->rgRDN[i].rgRDNAttr[j].pszObjId))
3226 {
3227 const CERT_RDN_ATTR *attr;
3228
3229 attr = &name->rgRDN[i].rgRDNAttr[j];
3230 /* Compare with memicmpW rather than strcmpiW in order to avoid
3231 * a match with a string with an embedded NULL. The component
3232 * must match one domain component attribute's entire string
3233 * value with a case-insensitive match.
3234 */
3235 matches = !memicmpW(component, (LPCWSTR)attr->Value.pbData,
3236 attr->Value.cbData / sizeof(WCHAR));
3237 }
3238 return matches;
3239}
3240
3241static BOOL match_domain_component(LPCWSTR allowed_component, DWORD allowed_len,
3242 LPCWSTR server_component, DWORD server_len, BOOL allow_wildcards,
3243 BOOL *see_wildcard)
3244{
3245 LPCWSTR allowed_ptr, server_ptr;
3246 BOOL matches = TRUE;
3247
3248 *see_wildcard = FALSE;
3249
3250 if (server_len < allowed_len)
3251 {
3252 WARN_(chain)("domain component %s too short for %s\n",
3253 debugstr_wn(server_component, server_len),
3254 debugstr_wn(allowed_component, allowed_len));
3255 /* A domain component can't contain a wildcard character, so a domain
3256 * component shorter than the allowed string can't produce a match.
3257 */
3258 return FALSE;
3259 }
3260 for (allowed_ptr = allowed_component, server_ptr = server_component;
3261 matches && allowed_ptr - allowed_component < allowed_len;
3262 allowed_ptr++, server_ptr++)
3263 {
3264 if (*allowed_ptr == '*')
3265 {
3266 if (allowed_ptr - allowed_component < allowed_len - 1)
3267 {
3268 WARN_(chain)("non-wildcard characters after wildcard not supported\n");
3269 matches = FALSE;
3270 }
3271 else if (!allow_wildcards)
3272 {
3273 WARN_(chain)("wildcard after non-wildcard component\n");
3274 matches = FALSE;
3275 }
3276 else
3277 {
3278 /* the preceding characters must have matched, so the rest of
3279 * the component also matches.
3280 */
3281 *see_wildcard = TRUE;
3282 break;
3283 }
3284 }
3285 if (matches)
3286 matches = tolowerW(*allowed_ptr) == tolowerW(*server_ptr);
3287 }
3288 if (matches && server_ptr - server_component < server_len)
3289 {
3290 /* If there are unmatched characters in the server domain component,
3291 * the server domain only matches if the allowed string ended in a '*'.
3292 */
3293 matches = *allowed_ptr == '*';
3294 }
3295 return matches;
3296}
3297
3299{
3300 LPCWSTR allowed = (LPCWSTR)nameAttr->Value.pbData;
3301 LPCWSTR allowed_component = allowed;
3302 DWORD allowed_len = nameAttr->Value.cbData / sizeof(WCHAR);
3303 LPCWSTR server_component = server_name;
3304 DWORD server_len = strlenW(server_name);
3305 BOOL matches = TRUE, allow_wildcards = TRUE;
3306
3307 TRACE_(chain)("CN = %s\n", debugstr_wn(allowed_component, allowed_len));
3308
3309 /* Remove trailing NULLs from the allowed name; while they shouldn't appear
3310 * in a certificate in the first place, they sometimes do, and they should
3311 * be ignored.
3312 */
3313 while (allowed_len && allowed_component[allowed_len - 1] == 0)
3314 allowed_len--;
3315
3316 /* From RFC 2818 (HTTP over TLS), section 3.1:
3317 * "Names may contain the wildcard character * which is considered to match
3318 * any single domain name component or component fragment. E.g.,
3319 * *.a.com matches foo.a.com but not bar.foo.a.com. f*.com matches foo.com
3320 * but not bar.com."
3321 *
3322 * And from RFC 2595 (Using TLS with IMAP, POP3 and ACAP), section 2.4:
3323 * "A "*" wildcard character MAY be used as the left-most name component in
3324 * the certificate. For example, *.example.com would match a.example.com,
3325 * foo.example.com, etc. but would not match example.com."
3326 *
3327 * There are other protocols which use TLS, and none of them is
3328 * authoritative. This accepts certificates in common usage, e.g.
3329 * *.domain.com matches www.domain.com but not domain.com, and
3330 * www*.domain.com matches www1.domain.com but not mail.domain.com.
3331 */
3332 do {
3333 LPCWSTR allowed_dot, server_dot;
3334
3335 allowed_dot = memchrW(allowed_component, '.',
3336 allowed_len - (allowed_component - allowed));
3337 server_dot = memchrW(server_component, '.',
3338 server_len - (server_component - server_name));
3339 /* The number of components must match */
3340 if ((!allowed_dot && server_dot) || (allowed_dot && !server_dot))
3341 {
3342 if (!allowed_dot)
3343 WARN_(chain)("%s: too many components for CN=%s\n",
3344 debugstr_w(server_name), debugstr_wn(allowed, allowed_len));
3345 else
3346 WARN_(chain)("%s: not enough components for CN=%s\n",
3347 debugstr_w(server_name), debugstr_wn(allowed, allowed_len));
3348 matches = FALSE;
3349 }
3350 else
3351 {
3352 LPCWSTR allowed_end, server_end;
3353 BOOL has_wildcard;
3354
3355 allowed_end = allowed_dot ? allowed_dot : allowed + allowed_len;
3356 server_end = server_dot ? server_dot : server_name + server_len;
3357 matches = match_domain_component(allowed_component,
3358 allowed_end - allowed_component, server_component,
3359 server_end - server_component, allow_wildcards, &has_wildcard);
3360 /* Once a non-wildcard component is seen, no wildcard components
3361 * may follow
3362 */
3363 if (!has_wildcard)
3364 allow_wildcards = FALSE;
3365 if (matches)
3366 {
3367 allowed_component = allowed_dot ? allowed_dot + 1 : allowed_end;
3368 server_component = server_dot ? server_dot + 1 : server_end;
3369 }
3370 }
3371 } while (matches && allowed_component &&
3372 allowed_component - allowed < allowed_len &&
3373 server_component && server_component - server_name < server_len);
3374 TRACE_(chain)("returning %d\n", matches);
3375 return matches;
3376}
3377
3379{
3380 BOOL matches = FALSE;
3382 DWORD size;
3383
3386 cert->pCertInfo->Subject.pbData, cert->pCertInfo->Subject.cbData,
3388 &name, &size))
3389 {
3390 /* If the subject distinguished name contains any name components,
3391 * make sure all of them are present.
3392 */
3394 {
3396
3397 do {
3398 LPCWSTR dot = strchrW(ptr, '.'), end;
3399 /* 254 is the maximum DNS label length, see RFC 1035 */
3400 WCHAR component[255];
3401 DWORD len;
3402
3403 end = dot ? dot : ptr + strlenW(ptr);
3404 len = end - ptr;
3405 if (len >= ARRAY_SIZE(component))
3406 {
3407 WARN_(chain)("domain component %s too long\n",
3408 debugstr_wn(ptr, len));
3409 matches = FALSE;
3410 }
3411 else
3412 {
3413 memcpy(component, ptr, len * sizeof(WCHAR));
3414 component[len] = 0;
3416 }
3417 ptr = dot ? dot + 1 : end;
3418 } while (matches && ptr && *ptr);
3419 }
3420 else
3421 {
3422 DWORD i, j;
3423
3424 /* If the certificate isn't using a DN attribute in the name, make
3425 * make sure at least one common name matches. From RFC 2818,
3426 * section 3.1:
3427 * "If more than one identity of a given type is present in the
3428 * certificate (e.g., more than one dNSName name, a match in any
3429 * one of the set is considered acceptable.)"
3430 */
3431 for (i = 0; !matches && i < name->cRDN; i++)
3432 for (j = 0; !matches && j < name->rgRDN[i].cRDNAttr; j++)
3433 {
3434 PCERT_RDN_ATTR attr = &name->rgRDN[i].rgRDNAttr[j];
3435
3436 if (attr->pszObjId && !strcmp(szOID_COMMON_NAME,
3437 attr->pszObjId))
3439 }
3440 }
3441 LocalFree(name);
3442 }
3443 return matches;
3444}
3445
3447{
3448 if (sslPara)
3449 {
3450 TRACE_(chain)("cbSize = %d\n", sslPara->u.cbSize);
3451 TRACE_(chain)("dwAuthType = %d\n", sslPara->dwAuthType);
3452 TRACE_(chain)("fdwChecks = %08x\n", sslPara->fdwChecks);
3453 TRACE_(chain)("pwszServerName = %s\n",
3454 debugstr_w(sslPara->pwszServerName));
3455 }
3456}
3457
3459 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3460 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3461{
3462 HTTPSPolicyCallbackData *sslPara = NULL;
3463 DWORD checks = 0;
3464
3465 if (pPolicyPara)
3466 sslPara = pPolicyPara->pvExtraPolicyPara;
3467 if (TRACE_ON(chain))
3469 if (sslPara && sslPara->u.cbSize >= sizeof(HTTPSPolicyCallbackData))
3470 checks = sslPara->fdwChecks;
3471 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = -1;
3472 if (pChainContext->TrustStatus.dwErrorStatus &
3474 {
3475 pPolicyStatus->dwError = TRUST_E_CERT_SIGNATURE;
3476 find_element_with_error(pChainContext,
3478 &pPolicyStatus->lElementIndex);
3479 }
3480 else if (pChainContext->TrustStatus.dwErrorStatus &
3483 {
3484 pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
3485 find_element_with_error(pChainContext,
3487 &pPolicyStatus->lElementIndex);
3488 }
3489 else if (pChainContext->TrustStatus.dwErrorStatus & CERT_TRUST_IS_CYCLIC)
3490 {
3491 pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
3492 find_element_with_error(pChainContext,
3493 CERT_TRUST_IS_CYCLIC, &pPolicyStatus->lChainIndex,
3494 &pPolicyStatus->lElementIndex);
3495 /* For a cyclic chain, which element is a cycle isn't meaningful */
3496 pPolicyStatus->lElementIndex = -1;
3497 }
3498 else if (pChainContext->TrustStatus.dwErrorStatus &
3501 {
3502 pPolicyStatus->dwError = CERT_E_EXPIRED;
3503 find_element_with_error(pChainContext,
3505 &pPolicyStatus->lElementIndex);
3506 }
3507 else if (pChainContext->TrustStatus.dwErrorStatus &
3510 {
3511 pPolicyStatus->dwError = CERT_E_WRONG_USAGE;
3512 find_element_with_error(pChainContext,
3514 &pPolicyStatus->lElementIndex);
3515 }
3516 else if (pChainContext->TrustStatus.dwErrorStatus &
3518 {
3519 pPolicyStatus->dwError = CERT_E_REVOKED;
3520 find_element_with_error(pChainContext,
3521 CERT_TRUST_IS_REVOKED, &pPolicyStatus->lChainIndex,
3522 &pPolicyStatus->lElementIndex);
3523 }
3524 else if (pChainContext->TrustStatus.dwErrorStatus &
3527 {
3528 pPolicyStatus->dwError = CERT_E_REVOCATION_FAILURE;
3529 find_element_with_error(pChainContext,
3531 &pPolicyStatus->lElementIndex);
3532 }
3533 else if (pChainContext->TrustStatus.dwErrorStatus &
3535 {
3536 pPolicyStatus->dwError = CERT_E_CRITICAL;
3537 find_element_with_error(pChainContext,
3539 &pPolicyStatus->lElementIndex);
3540 }
3541 else
3542 pPolicyStatus->dwError = NO_ERROR;
3543 /* We only need bother checking whether the name in the end certificate
3544 * matches if the chain is otherwise okay.
3545 */
3546 if (!pPolicyStatus->dwError && pPolicyPara &&
3547 pPolicyPara->cbSize >= sizeof(CERT_CHAIN_POLICY_PARA))
3548 {
3549 if (sslPara && sslPara->u.cbSize >= sizeof(HTTPSPolicyCallbackData))
3550 {
3551 if (sslPara->dwAuthType == AUTHTYPE_SERVER &&
3552 sslPara->pwszServerName &&
3554 {
3556 PCERT_EXTENSION altNameExt;
3557 BOOL matches;
3558
3559 cert = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
3560 altNameExt = get_subject_alt_name_ext(cert->pCertInfo);
3561 /* If the alternate name extension exists, the name it contains
3562 * is bound to the certificate, so make sure the name matches
3563 * it. Otherwise, look for the server name in the subject
3564 * distinguished name. RFC5280, section 4.2.1.6:
3565 * "Whenever such identities are to be bound into a
3566 * certificate, the subject alternative name (or issuer
3567 * alternative name) extension MUST be used; however, a DNS
3568 * name MAY also be represented in the subject field using the
3569 * domainComponent attribute."
3570 */
3571 if (altNameExt)
3573 sslPara->pwszServerName);
3574 else
3576 sslPara->pwszServerName);
3577 if (!matches)
3578 {
3579 pPolicyStatus->dwError = CERT_E_CN_NO_MATCH;
3580 pPolicyStatus->lChainIndex = 0;
3581 pPolicyStatus->lElementIndex = 0;
3582 }
3583 }
3584 }
3585 }
3586 return TRUE;
3587}
3588
3589static BYTE msPubKey1[] = {
35900x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xdf,0x08,0xba,0xe3,0x3f,0x6e,
35910x64,0x9b,0xf5,0x89,0xaf,0x28,0x96,0x4a,0x07,0x8f,0x1b,0x2e,0x8b,0x3e,0x1d,
35920xfc,0xb8,0x80,0x69,0xa3,0xa1,0xce,0xdb,0xdf,0xb0,0x8e,0x6c,0x89,0x76,0x29,
35930x4f,0xca,0x60,0x35,0x39,0xad,0x72,0x32,0xe0,0x0b,0xae,0x29,0x3d,0x4c,0x16,
35940xd9,0x4b,0x3c,0x9d,0xda,0xc5,0xd3,0xd1,0x09,0xc9,0x2c,0x6f,0xa6,0xc2,0x60,
35950x53,0x45,0xdd,0x4b,0xd1,0x55,0xcd,0x03,0x1c,0xd2,0x59,0x56,0x24,0xf3,0xe5,
35960x78,0xd8,0x07,0xcc,0xd8,0xb3,0x1f,0x90,0x3f,0xc0,0x1a,0x71,0x50,0x1d,0x2d,
35970xa7,0x12,0x08,0x6d,0x7c,0xb0,0x86,0x6c,0xc7,0xba,0x85,0x32,0x07,0xe1,0x61,
35980x6f,0xaf,0x03,0xc5,0x6d,0xe5,0xd6,0xa1,0x8f,0x36,0xf6,0xc1,0x0b,0xd1,0x3e,
35990x69,0x97,0x48,0x72,0xc9,0x7f,0xa4,0xc8,0xc2,0x4a,0x4c,0x7e,0xa1,0xd1,0x94,
36000xa6,0xd7,0xdc,0xeb,0x05,0x46,0x2e,0xb8,0x18,0xb4,0x57,0x1d,0x86,0x49,0xdb,
36010x69,0x4a,0x2c,0x21,0xf5,0x5e,0x0f,0x54,0x2d,0x5a,0x43,0xa9,0x7a,0x7e,0x6a,
36020x8e,0x50,0x4d,0x25,0x57,0xa1,0xbf,0x1b,0x15,0x05,0x43,0x7b,0x2c,0x05,0x8d,
36030xbd,0x3d,0x03,0x8c,0x93,0x22,0x7d,0x63,0xea,0x0a,0x57,0x05,0x06,0x0a,0xdb,
36040x61,0x98,0x65,0x2d,0x47,0x49,0xa8,0xe7,0xe6,0x56,0x75,0x5c,0xb8,0x64,0x08,
36050x63,0xa9,0x30,0x40,0x66,0xb2,0xf9,0xb6,0xe3,0x34,0xe8,0x67,0x30,0xe1,0x43,
36060x0b,0x87,0xff,0xc9,0xbe,0x72,0x10,0x5e,0x23,0xf0,0x9b,0xa7,0x48,0x65,0xbf,
36070x09,0x88,0x7b,0xcd,0x72,0xbc,0x2e,0x79,0x9b,0x7b,0x02,0x03,0x01,0x00,0x01 };
3608static BYTE msPubKey2[] = {
36090x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0x02,0xbd,0xc1,0x70,0xe6,
36100x3b,0xf2,0x4e,0x1b,0x28,0x9f,0x97,0x78,0x5e,0x30,0xea,0xa2,0xa9,0x8d,0x25,
36110x5f,0xf8,0xfe,0x95,0x4c,0xa3,0xb7,0xfe,0x9d,0xa2,0x20,0x3e,0x7c,0x51,0xa2,
36120x9b,0xa2,0x8f,0x60,0x32,0x6b,0xd1,0x42,0x64,0x79,0xee,0xac,0x76,0xc9,0x54,
36130xda,0xf2,0xeb,0x9c,0x86,0x1c,0x8f,0x9f,0x84,0x66,0xb3,0xc5,0x6b,0x7a,0x62,
36140x23,0xd6,0x1d,0x3c,0xde,0x0f,0x01,0x92,0xe8,0x96,0xc4,0xbf,0x2d,0x66,0x9a,
36150x9a,0x68,0x26,0x99,0xd0,0x3a,0x2c,0xbf,0x0c,0xb5,0x58,0x26,0xc1,0x46,0xe7,
36160x0a,0x3e,0x38,0x96,0x2c,0xa9,0x28,0x39,0xa8,0xec,0x49,0x83,0x42,0xe3,0x84,
36170x0f,0xbb,0x9a,0x6c,0x55,0x61,0xac,0x82,0x7c,0xa1,0x60,0x2d,0x77,0x4c,0xe9,
36180x99,0xb4,0x64,0x3b,0x9a,0x50,0x1c,0x31,0x08,0x24,0x14,0x9f,0xa9,0xe7,0x91,
36190x2b,0x18,0xe6,0x3d,0x98,0x63,0x14,0x60,0x58,0x05,0x65,0x9f,0x1d,0x37,0x52,
36200x87,0xf7,0xa7,0xef,0x94,0x02,0xc6,0x1b,0xd3,0xbf,0x55,0x45,0xb3,0x89,0x80,
36210xbf,0x3a,0xec,0x54,0x94,0x4e,0xae,0xfd,0xa7,0x7a,0x6d,0x74,0x4e,0xaf,0x18,
36220xcc,0x96,0x09,0x28,0x21,0x00,0x57,0x90,0x60,0x69,0x37,0xbb,0x4b,0x12,0x07,
36230x3c,0x56,0xff,0x5b,0xfb,0xa4,0x66,0x0a,0x08,0xa6,0xd2,0x81,0x56,0x57,0xef,
36240xb6,0x3b,0x5e,0x16,0x81,0x77,0x04,0xda,0xf6,0xbe,0xae,0x80,0x95,0xfe,0xb0,
36250xcd,0x7f,0xd6,0xa7,0x1a,0x72,0x5c,0x3c,0xca,0xbc,0xf0,0x08,0xa3,0x22,0x30,
36260xb3,0x06,0x85,0xc9,0xb3,0x20,0x77,0x13,0x85,0xdf,0x02,0x03,0x01,0x00,0x01 };
3627static BYTE msPubKey3[] = {
36280x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xf3,0x5d,0xfa,0x80,0x67,0xd4,
36290x5a,0xa7,0xa9,0x0c,0x2c,0x90,0x20,0xd0,0x35,0x08,0x3c,0x75,0x84,0xcd,0xb7,
36300x07,0x89,0x9c,0x89,0xda,0xde,0xce,0xc3,0x60,0xfa,0x91,0x68,0x5a,0x9e,0x94,
36310x71,0x29,0x18,0x76,0x7c,0xc2,0xe0,0xc8,0x25,0x76,0x94,0x0e,0x58,0xfa,0x04,
36320x34,0x36,0xe6,0xdf,0xaf,0xf7,0x80,0xba,0xe9,0x58,0x0b,0x2b,0x93,0xe5,0x9d,
36330x05,0xe3,0x77,0x22,0x91,0xf7,0x34,0x64,0x3c,0x22,0x91,0x1d,0x5e,0xe1,0x09,
36340x90,0xbc,0x14,0xfe,0xfc,0x75,0x58,0x19,0xe1,0x79,0xb7,0x07,0x92,0xa3,0xae,
36350x88,0x59,0x08,0xd8,0x9f,0x07,0xca,0x03,0x58,0xfc,0x68,0x29,0x6d,0x32,0xd7,
36360xd2,0xa8,0xcb,0x4b,0xfc,0xe1,0x0b,0x48,0x32,0x4f,0xe6,0xeb,0xb8,0xad,0x4f,
36370xe4,0x5c,0x6f,0x13,0x94,0x99,0xdb,0x95,0xd5,0x75,0xdb,0xa8,0x1a,0xb7,0x94,
36380x91,0xb4,0x77,0x5b,0xf5,0x48,0x0c,0x8f,0x6a,0x79,0x7d,0x14,0x70,0x04,0x7d,
36390x6d,0xaf,0x90,0xf5,0xda,0x70,0xd8,0x47,0xb7,0xbf,0x9b,0x2f,0x6c,0xe7,0x05,
36400xb7,0xe1,0x11,0x60,0xac,0x79,0x91,0x14,0x7c,0xc5,0xd6,0xa6,0xe4,0xe1,0x7e,
36410xd5,0xc3,0x7e,0xe5,0x92,0xd2,0x3c,0x00,0xb5,0x36,0x82,0xde,0x79,0xe1,0x6d,
36420xf3,0xb5,0x6e,0xf8,0x9f,0x33,0xc9,0xcb,0x52,0x7d,0x73,0x98,0x36,0xdb,0x8b,
36430xa1,0x6b,0xa2,0x95,0x97,0x9b,0xa3,0xde,0xc2,0x4d,0x26,0xff,0x06,0x96,0x67,
36440x25,0x06,0xc8,0xe7,0xac,0xe4,0xee,0x12,0x33,0x95,0x31,0x99,0xc8,0x35,0x08,
36450x4e,0x34,0xca,0x79,0x53,0xd5,0xb5,0xbe,0x63,0x32,0x59,0x40,0x36,0xc0,0xa5,
36460x4e,0x04,0x4d,0x3d,0xdb,0x5b,0x07,0x33,0xe4,0x58,0xbf,0xef,0x3f,0x53,0x64,
36470xd8,0x42,0x59,0x35,0x57,0xfd,0x0f,0x45,0x7c,0x24,0x04,0x4d,0x9e,0xd6,0x38,
36480x74,0x11,0x97,0x22,0x90,0xce,0x68,0x44,0x74,0x92,0x6f,0xd5,0x4b,0x6f,0xb0,
36490x86,0xe3,0xc7,0x36,0x42,0xa0,0xd0,0xfc,0xc1,0xc0,0x5a,0xf9,0xa3,0x61,0xb9,
36500x30,0x47,0x71,0x96,0x0a,0x16,0xb0,0x91,0xc0,0x42,0x95,0xef,0x10,0x7f,0x28,
36510x6a,0xe3,0x2a,0x1f,0xb1,0xe4,0xcd,0x03,0x3f,0x77,0x71,0x04,0xc7,0x20,0xfc,
36520x49,0x0f,0x1d,0x45,0x88,0xa4,0xd7,0xcb,0x7e,0x88,0xad,0x8e,0x2d,0xec,0x45,
36530xdb,0xc4,0x51,0x04,0xc9,0x2a,0xfc,0xec,0x86,0x9e,0x9a,0x11,0x97,0x5b,0xde,
36540xce,0x53,0x88,0xe6,0xe2,0xb7,0xfd,0xac,0x95,0xc2,0x28,0x40,0xdb,0xef,0x04,
36550x90,0xdf,0x81,0x33,0x39,0xd9,0xb2,0x45,0xa5,0x23,0x87,0x06,0xa5,0x55,0x89,
36560x31,0xbb,0x06,0x2d,0x60,0x0e,0x41,0x18,0x7d,0x1f,0x2e,0xb5,0x97,0xcb,0x11,
36570xeb,0x15,0xd5,0x24,0xa5,0x94,0xef,0x15,0x14,0x89,0xfd,0x4b,0x73,0xfa,0x32,
36580x5b,0xfc,0xd1,0x33,0x00,0xf9,0x59,0x62,0x70,0x07,0x32,0xea,0x2e,0xab,0x40,
36590x2d,0x7b,0xca,0xdd,0x21,0x67,0x1b,0x30,0x99,0x8f,0x16,0xaa,0x23,0xa8,0x41,
36600xd1,0xb0,0x6e,0x11,0x9b,0x36,0xc4,0xde,0x40,0x74,0x9c,0xe1,0x58,0x65,0xc1,
36610x60,0x1e,0x7a,0x5b,0x38,0xc8,0x8f,0xbb,0x04,0x26,0x7c,0xd4,0x16,0x40,0xe5,
36620xb6,0x6b,0x6c,0xaa,0x86,0xfd,0x00,0xbf,0xce,0xc1,0x35,0x02,0x03,0x01,0x00,
36630x01 };
3664
3666 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3667 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3668{
3669 BOOL ret = verify_base_policy(szPolicyOID, pChainContext, pPolicyPara,
3670 pPolicyStatus);
3671
3672 if (ret && !pPolicyStatus->dwError)
3673 {
3674 CERT_PUBLIC_KEY_INFO msPubKey = { { 0 } };
3675 BOOL isMSRoot = FALSE;
3676 DWORD i;
3677 CRYPT_DATA_BLOB keyBlobs[] = {
3678 { sizeof(msPubKey1), msPubKey1 },
3679 { sizeof(msPubKey2), msPubKey2 },
3680 { sizeof(msPubKey3), msPubKey3 },
3681 };
3682 PCERT_SIMPLE_CHAIN rootChain =
3683 pChainContext->rgpChain[pChainContext->cChain -1 ];
3685 rootChain->rgpElement[rootChain->cElement - 1]->pCertContext;
3686
3687 for (i = 0; !isMSRoot && i < ARRAY_SIZE(keyBlobs); i++)
3688 {
3689 msPubKey.PublicKey.cbData = keyBlobs[i].cbData;
3690 msPubKey.PublicKey.pbData = keyBlobs[i].pbData;
3693 &root->pCertInfo->SubjectPublicKeyInfo, &msPubKey))
3694 isMSRoot = TRUE;
3695 }
3696 if (isMSRoot)
3697 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = 0;
3698 }
3699 return ret;
3700}
3701
3703 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3704 PCERT_CHAIN_POLICY_STATUS pPolicyStatus);
3705
3707{
3708 if (para)
3709 {
3710 TRACE_(chain)("cbSize = %d\n", para->cbSize);
3711 TRACE_(chain)("dwFlags = %08x\n", para->dwFlags);
3712 TRACE_(chain)("pvExtraPolicyPara = %p\n", para->pvExtraPolicyPara);
3713 }
3714}
3715
3717 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3718 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3719{
3720 static HCRYPTOIDFUNCSET set = NULL;
3721 BOOL ret = FALSE;
3723 HCRYPTOIDFUNCADDR hFunc = NULL;
3724
3725 TRACE("(%s, %p, %p, %p)\n", debugstr_a(szPolicyOID), pChainContext,
3726 pPolicyPara, pPolicyStatus);
3727 if (TRACE_ON(chain))
3728 dump_policy_para(pPolicyPara);
3729
3730 if (IS_INTOID(szPolicyOID))
3731 {
3732 switch (LOWORD(szPolicyOID))
3733 {
3735 verifyPolicy = verify_base_policy;
3736 break;
3738 verifyPolicy = verify_authenticode_policy;
3739 break;
3741 verifyPolicy = verify_ssl_policy;
3742 break;
3744 verifyPolicy = verify_basic_constraints_policy;
3745 break;
3747 verifyPolicy = verify_ms_root_policy;
3748 break;
3749 default:
3750 FIXME("unimplemented for %d\n", LOWORD(szPolicyOID));
3751 }
3752 }
3753 if (!verifyPolicy)
3754 {
3755 if (!set)
3759 (void **)&verifyPolicy, &hFunc);
3760 }
3761 if (verifyPolicy)
3762 ret = verifyPolicy(szPolicyOID, pChainContext, pPolicyPara,
3763 pPolicyStatus);
3764 if (hFunc)
3766 TRACE("returning %d (%08x)\n", ret, pPolicyStatus->dwError);
3767 return ret;
3768}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
char * hostname
Definition: ftp.c:88
#define ARRAY_SIZE(A)
Definition: main.h:33
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
struct _root root
Definition: _set.h:50
BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore, HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
Definition: decode.c:6286
DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indent, const CERT_NAME_BLOB *pName, DWORD dwStrType, LPWSTR psz, DWORD csz) DECLSPEC_HIDDEN
Definition: str.c:576
#define IS_INTOID(x)
BOOL WINAPI CryptRetrieveObjectByUrlW(LPCWSTR pszURL, LPCSTR pszObjectOid, DWORD dwRetrievalFlags, DWORD dwTimeout, LPVOID *ppvObject, HCRYPTASYNC hAsyncRetrieve, PCRYPT_CREDENTIALS pCredentials, LPVOID pvVerify, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
BOOL WINAPI CryptGetObjectUrl(LPCSTR pszUrlOid, LPVOID pvPara, DWORD dwFlags, PCRYPT_URL_ARRAY pUrlArray, DWORD *pcbUrlArray, PCRYPT_URL_INFO pUrlInfo, DWORD *pcbUrlInfo, LPVOID pvReserved)
#define NO_ERROR
Definition: dderror.h:5
#define E_INVALIDARG
Definition: ddrawi.h:101
struct config_s config
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition, PCCERT_CONTEXT *ppStoreContext)
Definition: cert.c:286
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:371
BOOL WINAPI CertCompareCertificateName(DWORD dwCertEncodingType, PCERT_NAME_BLOB pCertName1, PCERT_NAME_BLOB pCertName2)
Definition: cert.c:1180
PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType, const void *pvPara, PCCERT_CONTEXT pPrevCertContext)
Definition: cert.c:1765
BOOL WINAPI CertVerifyRevocation(DWORD dwEncodingType, DWORD dwRevType, DWORD cContext, PVOID rgpvContext[], DWORD dwFlags, PCERT_REVOCATION_PARA pRevPara, PCERT_REVOCATION_STATUS pRevStatus)
Definition: cert.c:1934
BOOL WINAPI CertIsRDNAttrsInCertificateName(DWORD dwCertEncodingType, DWORD dwFlags, PCERT_NAME_BLOB pCertName, PCERT_RDN pRDN)
Definition: cert.c:2131
BOOL WINAPI CryptVerifyCertificateSignatureEx(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType, DWORD dwSubjectType, void *pvSubject, DWORD dwIssuerType, void *pvIssuer, DWORD dwFlags, void *pvReserved)
Definition: cert.c:2717
BOOL WINAPI CertCompareCertificate(DWORD dwCertEncodingType, PCERT_INFO pCertId1, PCERT_INFO pCertId2)
Definition: cert.c:1166
PCERT_EXTENSION WINAPI CertFindExtension(LPCSTR pszObjId, DWORD cExtensions, CERT_EXTENSION rgExtensions[])
Definition: cert.c:2028
BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, DWORD dwPropId, void *pvData, DWORD *pcbData)
Definition: cert.c:551
BOOL WINAPI CertComparePublicKeyInfo(DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pPublicKey1, PCERT_PUBLIC_KEY_INFO pPublicKey2)
Definition: cert.c:1244
PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:360
LONG WINAPI CertVerifyTimeValidity(LPFILETIME pTimeToVerify, PCERT_INFO pCertInfo)
Definition: cert.c:2158
BOOL WINAPI CertCompareIntegerBlob(PCRYPT_INTEGER_BLOB pInt1, PCRYPT_INTEGER_BLOB pInt2)
Definition: cert.c:1221
PCERT_RDN_ATTR WINAPI CertFindRDNAttr(LPCSTR pszObjId, PCERT_NAME_INFO pName)
Definition: cert.c:2051
BOOL WINAPI CertVerifyCertificateChainPolicy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3716
static void CRYPT_CheckChainPolicies(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:1381
static void dump_netscape_cert_type(const CERT_EXTENSION *ext)
Definition: chain.c:1621
BOOL WINAPI CertGetCertificateChain(HCERTCHAINENGINE hChainEngine, PCCERT_CONTEXT pCertContext, LPFILETIME pTime, HCERTSTORE hAdditionalStore, PCERT_CHAIN_PARA pChainPara, DWORD dwFlags, LPVOID pvReserved, PCCERT_CHAIN_CONTEXT *ppChainContext)
Definition: chain.c:2879
static void CRYPT_CheckSimpleChainForCycles(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:383
static void CRYPT_CheckChainNameConstraints(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:1279
static BOOL WINAPI verify_ms_root_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3665
static void CRYPT_CloseStores(DWORD cStores, HCERTSTORE *stores)
Definition: chain.c:61
static CertificateChainEngine * default_lm_engine
Definition: chain.c:164
static DWORD CRYPT_ChainQuality(const CertificateChain *chain)
Definition: chain.c:2528
static BOOL CRYPT_BuildCandidateChainFromCert(CertificateChainEngine *engine, PCCERT_CONTEXT cert, LPFILETIME pTime, HCERTSTORE hAdditionalStore, DWORD flags, CertificateChain **ppChain)
Definition: chain.c:2251
static void CRYPT_CheckPolicies(const CERT_POLICIES_INFO *policies, CERT_INFO *cert, DWORD *errorStatus)
Definition: chain.c:1357
static BOOL CRYPT_AddAlternateChainToChain(CertificateChain *chain, const CertificateChain *alternate)
Definition: chain.c:2586
static BOOL match_dns_to_subject_alt_name(const CERT_EXTENSION *ext, LPCWSTR server_name)
Definition: chain.c:3148
static CertificateChainEngine * get_chain_engine(HCERTCHAINENGINE handle, BOOL allow_default)
Definition: chain.c:166
static BOOL CRYPT_CheckRestrictedRoot(HCERTSTORE store)
Definition: chain.c:89
static BOOL WINAPI verify_ssl_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3458
static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain, LPFILETIME pTime, HCERTSTORE hAdditionalStore, const CERT_CHAIN_PARA *pChainPara, DWORD chainFlags)
Definition: chain.c:2632
struct _CERT_CHAIN_PARA_NO_EXTRA_FIELDS CERT_CHAIN_PARA_NO_EXTRA_FIELDS
static void free_chain_engine(CertificateChainEngine *engine)
Definition: chain.c:201
static BOOL WINAPI verify_basic_constraints_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3130
#define CHAIN_QUALITY_HIGHEST
Definition: chain.c:2520
static void dump_policy_para(PCERT_CHAIN_POLICY_PARA para)
Definition: chain.c:3706
static void dump_extension(const CERT_EXTENSION *ext)
Definition: chain.c:1647
static BOOL CRYPT_AddCertToSimpleChain(const CertificateChainEngine *engine, PCERT_SIMPLE_CHAIN chain, PCCERT_CONTEXT cert, DWORD subjectInfoStatus)
Definition: chain.c:427
void default_chain_engine_free(void)
Definition: chain.c:255
static BYTE msPubKey3[]
Definition: chain.c:3627
static void CRYPT_FreeChainElement(PCERT_CHAIN_ELEMENT element)
Definition: chain.c:377
static BOOL url_matches(LPCWSTR constraint, LPCWSTR name, DWORD *trustErrorStatus)
Definition: chain.c:682
static BOOL ip_address_matches(const CRYPT_DATA_BLOB *constraint, const CRYPT_DATA_BLOB *name, DWORD *trustErrorStatus)
Definition: chain.c:820
static BYTE msTestPubKey2[]
Definition: chain.c:3070
static BOOL find_matching_domain_component(const CERT_NAME_INFO *name, LPCWSTR component)
Definition: chain.c:3216
static void dump_basic_constraints(const CERT_EXTENSION *ext)
Definition: chain.c:1484
static void dump_key_usage(const CERT_EXTENSION *ext)
Definition: chain.c:1518
static BOOL CRYPT_KeyUsageValid(CertificateChainEngine *engine, PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA, DWORD index)
Definition: chain.c:1723
#define IS_TRUST_ERROR_SET(TrustStatus, bits)
Definition: chain.c:2525
struct _CertificateChain CertificateChain
VOID WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
Definition: chain.c:2960
static BOOL WINAPI verify_base_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:2998
static void CRYPT_FreeLowerQualityChains(CertificateChain *chain)
Definition: chain.c:2351
void WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine)
Definition: chain.c:249
static BOOL rfc822_attr_matches_excluded_name(const CERT_RDN_ATTR *attr, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:1017
static void dump_enhanced_key_usage(const CERT_EXTENSION *ext)
Definition: chain.c:1603
struct _CERT_CHAIN_ENGINE_CONFIG_NO_EXCLUSIVE_ROOT CERT_CHAIN_ENGINE_CONFIG_NO_EXCLUSIVE_ROOT
static BOOL dns_name_matches(LPCWSTR constraint, LPCWSTR name, DWORD *trustErrorStatus)
Definition: chain.c:775
static BOOL domain_name_matches(LPCWSTR constraint, LPCWSTR name)
Definition: chain.c:647
BOOL WINAPI CertCreateCertificateChainEngine(PCERT_CHAIN_ENGINE_CONFIG pConfig, HCERTCHAINENGINE *phChainEngine)
Definition: chain.c:225
static void dump_basic_constraints2(const CERT_EXTENSION *ext)
Definition: chain.c:1501
static void find_element_with_error(PCCERT_CHAIN_CONTEXT chain, DWORD error, LONG *iChain, LONG *iElement)
Definition: chain.c:2982
static CertificateChain * CRYPT_CopyChainToElement(CertificateChain *chain, DWORD iChain, DWORD iElement)
Definition: chain.c:2377
static BOOL CRYPT_IsValidNameConstraint(const CERT_NAME_CONSTRAINTS_INFO *info)
Definition: chain.c:1234
static void dump_alt_name(LPCSTR type, const CERT_EXTENSION *ext)
Definition: chain.c:1465
static void dump_ssl_extra_chain_policy_para(HTTPSPolicyCallbackData *sslPara)
Definition: chain.c:3446
static CERT_POLICIES_INFO * CRYPT_GetPolicies(PCCERT_CONTEXT cert)
Definition: chain.c:1339
static void compare_alt_name_with_constraints(const CERT_EXTENSION *altNameExt, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:967
static BOOL rfc822_attr_matches_permitted_name(const CERT_RDN_ATTR *attr, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus, BOOL *present)
Definition: chain.c:1035
#define DEFAULT_CYCLE_MODULUS
Definition: chain.c:34
static void compare_subject_with_constraints(const CERT_NAME_BLOB *subjectName, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:1126
static PCCERT_CONTEXT CRYPT_FindCertInStore(HCERTSTORE store, PCCERT_CONTEXT cert)
Definition: chain.c:72
static BYTE msPubKey2[]
Definition: chain.c:3608
PCCERT_CHAIN_CONTEXT WINAPI CertFindChainInStore(HCERTSTORE store, DWORD certEncodingType, DWORD findFlags, DWORD findType, const void *findPara, PCCERT_CHAIN_CONTEXT prevChainContext)
Definition: chain.c:2973
static void CRYPT_CheckUsages(PCERT_CHAIN_CONTEXT chain, const CERT_CHAIN_PARA *pChainPara)
Definition: chain.c:2745
static void dump_usage_match(LPCSTR name, const CERT_USAGE_MATCH *usageMatch)
Definition: chain.c:2851
static BOOL CRYPT_IsCertVersionValid(PCCERT_CONTEXT cert)
Definition: chain.c:1840
static void CRYPT_CheckSimpleChain(CertificateChainEngine *engine, PCERT_SIMPLE_CHAIN chain, LPFILETIME time)
Definition: chain.c:1879
static LPCSTR debugstr_filetime(LPFILETIME pTime)
Definition: chain.c:2213
static void CRYPT_CheckTrustedStatus(HCERTSTORE hRoot, PCERT_CHAIN_ELEMENT rootElement)
Definition: chain.c:478
static BOOL CRYPT_CheckBasicConstraintsForCA(CertificateChainEngine *engine, PCCERT_CONTEXT cert, CERT_BASIC_CONSTRAINTS2_INFO *chainConstraints, DWORD remainingCAs, BOOL isRoot, BOOL *pathLengthConstraintViolated)
Definition: chain.c:580
static BOOL match_dns_to_subject_dn(PCCERT_CONTEXT cert, LPCWSTR server_name)
Definition: chain.c:3378
PCCERT_CHAIN_CONTEXT WINAPI CertDuplicateCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
Definition: chain.c:2948
#define trace_cert_type_bit(bits, bit)
static BOOL alt_name_matches_excluded_name(const CERT_ALT_NAME_ENTRY *name, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:929
static PCERT_EXTENSION get_subject_alt_name_ext(const CERT_INFO *cert)
Definition: chain.c:955
static CertificateChain * CRYPT_BuildAlternateContextFromChain(CertificateChainEngine *engine, LPFILETIME pTime, HCERTSTORE hAdditionalStore, DWORD flags, CertificateChain *chain)
Definition: chain.c:2442
static PCCERT_CONTEXT CRYPT_GetIssuer(const CertificateChainEngine *engine, HCERTSTORE store, PCCERT_CONTEXT subject, PCCERT_CONTEXT prevIssuer, DWORD flags, DWORD *infoStatus)
Definition: chain.c:2056
static CertificateChain * CRYPT_ChooseHighestQualityChain(CertificateChain *chain)
Definition: chain.c:2554
static BOOL CRYPT_CriticalExtensionsSupported(PCCERT_CONTEXT cert)
Definition: chain.c:1802
static PCERT_CHAIN_ELEMENT CRYPT_FindIthElementInChain(const CERT_CHAIN_CONTEXT *chain, DWORD i)
Definition: chain.c:2611
static LPWSTR name_value_to_str(const CERT_NAME_BLOB *name)
Definition: chain.c:1410
static void CRYPT_CheckNameConstraints(const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, const CERT_INFO *cert, DWORD *trustErrorStatus)
Definition: chain.c:1196
static BOOL rfc822_name_matches(LPCWSTR constraint, LPCWSTR name, DWORD *trustErrorStatus)
Definition: chain.c:751
static BOOL CRYPT_IsEmptyName(const CERT_NAME_BLOB *name)
Definition: chain.c:1110
static const WCHAR rootW[]
Definition: chain.c:69
#define trace_usage_bit(bits, bit)
static void dump_alt_name_entry(const CERT_ALT_NAME_ENTRY *entry)
Definition: chain.c:1426
static BOOL match_common_name(LPCWSTR server_name, const CERT_RDN_ATTR *nameAttr)
Definition: chain.c:3298
static PCERT_SIMPLE_CHAIN CRYPT_CopySimpleChainToElement(const CERT_SIMPLE_CHAIN *chain, DWORD iElement)
Definition: chain.c:2296
static LPCSTR filetime_to_str(const FILETIME *time)
Definition: chain.c:1675
HCERTCHAINENGINE CRYPT_CreateChainEngine(HCERTSTORE root, DWORD system_store, const CERT_CHAIN_ENGINE_CONFIG *config)
Definition: chain.c:115
static void CRYPT_CheckRootCert(HCERTSTORE hRoot, PCERT_CHAIN_ELEMENT rootElement)
Definition: chain.c:491
static void dump_name_constraints(const CERT_EXTENSION *ext)
Definition: chain.c:1552
static CERT_NAME_CONSTRAINTS_INFO * CRYPT_GetNameConstraints(CERT_INFO *cert)
Definition: chain.c:1215
static BOOL CRYPT_DecodeBasicConstraints(PCCERT_CONTEXT cert, CERT_BASIC_CONSTRAINTS2_INFO *constraints, BOOL defaultIfNotSpecified)
Definition: chain.c:513
static BOOL alt_name_matches(const CERT_ALT_NAME_ENTRY *name, const CERT_ALT_NAME_ENTRY *constraint, DWORD *trustErrorStatus, BOOL *present)
Definition: chain.c:886
static BOOL directory_name_matches(const CERT_NAME_BLOB *constraint, const CERT_NAME_BLOB *name)
Definition: chain.c:864
static void dump_authenticode_extra_chain_policy_para(AUTHENTICODE_EXTRA_CERT_CHAIN_POLICY_PARA *extraPara)
Definition: chain.c:3077
static void CRYPT_FreeSimpleChain(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:468
static void CRYPT_AddStoresToCollection(HCERTSTORE collection, DWORD cStores, HCERTSTORE *stores)
Definition: chain.c:52
static CertificateChainEngine * default_cu_engine
Definition: chain.c:164
static BOOL CRYPT_IsSimpleChainCyclic(const CERT_SIMPLE_CHAIN *chain)
Definition: chain.c:407
static void dump_general_subtree(const CERT_GENERAL_SUBTREE *subtree)
Definition: chain.c:1545
static void CRYPT_FreeChainContext(CertificateChain *chain)
Definition: chain.c:2362
static BOOL WINAPI verify_authenticode_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3089
static BYTE msTestPubKey1[]
Definition: chain.c:3064
struct _CertificateChainEngine CertificateChainEngine
static BOOL CRYPT_BuildSimpleChain(const CertificateChainEngine *engine, HCERTSTORE world, DWORD flags, PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:2181
static BOOL match_domain_component(LPCWSTR allowed_component, DWORD allowed_len, LPCWSTR server_component, DWORD server_len, BOOL allow_wildcards, BOOL *see_wildcard)
Definition: chain.c:3241
static void compare_subject_with_email_constraints(const CERT_NAME_BLOB *subjectName, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:1057
static BYTE msPubKey1[]
Definition: chain.c:3589
DWORD CRYPT_IsCertificateSelfSigned(const CERT_CONTEXT *cert)
Definition: chain.c:268
static void dump_cert_policies(const CERT_EXTENSION *ext)
Definition: chain.c:1576
static void dump_chain_para(const CERT_CHAIN_PARA *pChainPara)
Definition: chain.c:2864
static void dump_element(PCCERT_CONTEXT cert)
Definition: chain.c:1689
static BOOL alt_name_matches_permitted_name(const CERT_ALT_NAME_ENTRY *name, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus, BOOL *present)
Definition: chain.c:941
static BOOL CRYPT_GetSimpleChainForCert(CertificateChainEngine *engine, HCERTSTORE world, PCCERT_CONTEXT cert, LPFILETIME pTime, DWORD flags, PCERT_SIMPLE_CHAIN *ppChain)
Definition: chain.c:2220
BOOL(WINAPI * CertVerifyCertificateChainPolicyFunc)(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3702
static PCCERT_CONTEXT CRYPT_FindIssuer(const CertificateChainEngine *engine, const CERT_CONTEXT *cert, HCERTSTORE store, DWORD type, void *para, DWORD flags, PCCERT_CONTEXT prev_issuer)
Definition: chain.c:1982
static void CRYPT_CombineTrustStatus(CERT_TRUST_STATUS *chainStatus, const CERT_TRUST_STATUS *elementStatus)
Definition: chain.c:416
LPVOID WINAPI CryptMemAlloc(ULONG cbSize)
Definition: main.c:131
LPVOID WINAPI CryptMemRealloc(LPVOID pv, ULONG cbSize)
Definition: main.c:136
VOID WINAPI CryptMemFree(LPVOID pv)
Definition: main.c:141
static WCHAR issuer[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1905
HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName, DWORD dwFlags)
Definition: oid.c:114
BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet, DWORD dwEncodingType, LPCSTR pszOID, DWORD dwFlags, void **ppvFuncAddr, HCRYPTOIDFUNCADDR *phFuncAddr)
Definition: oid.c:387
BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr, DWORD dwFlags)
Definition: oid.c:468
HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const void *pvPara)
Definition: store.c:815
HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
Definition: store.c:1116
PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
Definition: store.c:928
BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
Definition: store.c:1127
HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubSystemProtocol)
Definition: store.c:916
DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
Definition: str.c:1228
static const WCHAR empty[]
Definition: main.c:47
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define GetProcessHeap()
Definition: compat.h:736
#define TRACE_(x)
Definition: compat.h:76
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define TRACE_ON(x)
Definition: compat.h:75
#define HeapFree(x, y, z)
Definition: compat.h:735
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
#define lstrlenW
Definition: compat.h:750
static const WCHAR *const ext[]
Definition: module.c:53
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
#define check(expected, result)
Definition: dplayx.c:32
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
WINE_UNICODE_INLINE WCHAR * memchrW(const WCHAR *ptr, WCHAR ch, size_t n)
Definition: unicode.h:295
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
uint32_t entry
Definition: isohybrid.c:63
int quality
Definition: jpeglib.h:992
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: lang.c:1028
INT WINAPI GetDateFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpDateStr, INT cchOut)
Definition: lcformat.c:936
if(dx< 0)
Definition: linetemp.h:194
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
__u16 date
Definition: mkdosfs.c:8
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
#define matches(FN)
Definition: match.h:70
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static HTREEITEM hRoot
Definition: treeview.c:381
static BYTE subjectName[]
Definition: cert.c:63
static BYTE cert[]
Definition: msg.c:1437
static LPCSTR DWORD void * pvReserved
Definition: str.c:196
static ICollection collection
Definition: typelib.c:184
#define BOOL
Definition: nt_native.h:43
#define LOCALE_SYSTEM_DEFAULT
#define LOWORD(l)
Definition: pedump.c:82
long LONG
Definition: pedump.c:60
#define strchrW(s, c)
Definition: unicode.h:34
#define memicmpW(s1, s2, n)
Definition: unicode.h:27
#define strcmpiW(s1, s2)
Definition: unicode.h:39
#define tolowerW(n)
Definition: unicode.h:44
#define strlenW(s)
Definition: unicode.h:28
const WCHAR * str
#define WARN_(ch,...)
Definition: debug.h:157
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
Definition: wincrypt.h:332
LPWSTR pwszRfc822Name
Definition: wincrypt.h:336
LPWSTR pwszURL
Definition: wincrypt.h:339
DWORD dwAltNameChoice
Definition: wincrypt.h:333
CRYPT_DATA_BLOB IPAddress
Definition: wincrypt.h:340
CERT_NAME_BLOB DirectoryName
Definition: wincrypt.h:338
PCERT_ALT_NAME_ENTRY rgAltEntry
Definition: wincrypt.h:357
PCERT_SIMPLE_CHAIN * rgpChain
Definition: wincrypt.h:941
DWORD cLowerQualityChainContext
Definition: wincrypt.h:942
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:939
PCCERT_CHAIN_CONTEXT * rgpLowerQualityChainContext
Definition: wincrypt.h:943
PCCERT_CONTEXT pCertContext
Definition: wincrypt.h:916
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:917
HCERTSTORE hRestrictedRoot
Definition: wincrypt.h:3626
CERT_USAGE_MATCH RequestedUsage
Definition: chain.c:2629
DWORD dwCertEncodingType
Definition: wincrypt.h:479
HCERTSTORE hCertStore
Definition: wincrypt.h:483
PCERT_INFO pCertInfo
Definition: wincrypt.h:482
CRYPT_OBJID_BLOB Value
Definition: wincrypt.h:232
CERT_ALT_NAME_ENTRY Base
Definition: wincrypt.h:571
PCERT_EXTENSION rgExtension
Definition: wincrypt.h:252
CERT_NAME_BLOB Issuer
Definition: wincrypt.h:244
CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo
Definition: wincrypt.h:248
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm
Definition: wincrypt.h:243
DWORD cExtension
Definition: wincrypt.h:251
PCERT_GENERAL_SUBTREE rgPermittedSubtree
Definition: wincrypt.h:579
PCERT_GENERAL_SUBTREE rgExcludedSubtree
Definition: wincrypt.h:581
PCERT_RDN rgRDN
Definition: wincrypt.h:268
CERT_POLICY_INFO * rgPolicyInfo
Definition: wincrypt.h:400
CERT_POLICY_QUALIFIER_INFO * rgPolicyQualifier
Definition: wincrypt.h:395
LPSTR pszPolicyIdentifier
Definition: wincrypt.h:393
DWORD cPolicyQualifier
Definition: wincrypt.h:394
CRYPT_BIT_BLOB PublicKey
Definition: wincrypt.h:226
CERT_RDN_VALUE_BLOB Value
Definition: wincrypt.h:258
LPFILETIME pftTimeToUse
Definition: wincrypt.h:808
HCERTSTORE hCrlStore
Definition: wincrypt.h:807
PCCERT_CONTEXT pIssuerCert
Definition: wincrypt.h:804
HCERTSTORE * rgCertStore
Definition: wincrypt.h:806
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:926
PCERT_CHAIN_ELEMENT * rgpElement
Definition: wincrypt.h:928
CERT_ENHKEY_USAGE Usage
Definition: wincrypt.h:1048
BYTE * pbData
Definition: wincrypt.h:103
BYTE * pbData
Definition: wincrypt.h:197
LPWSTR * rgwszUrl
Definition: wincrypt.h:1514
DWORD cUsageIdentifier
Definition: wincrypt.h:719
LPSTR * rgpszUsageIdentifier
Definition: wincrypt.h:720
DWORD MaximumCachedCertificates
Definition: chain.c:48
DWORD dwUrlRetrievalTimeout
Definition: chain.c:47
HCERTSTORE hRoot
Definition: chain.c:44
DWORD CycleDetectionModulus
Definition: chain.c:49
HCERTSTORE hWorld
Definition: chain.c:45
CERT_CHAIN_CONTEXT context
Definition: chain.c:263
HCERTSTORE world
Definition: chain.c:264
Definition: cookie.c:202
Definition: image.c:134
Definition: _hash_fun.h:40
Definition: match.c:28
Definition: name.c:39
Definition: ps.c:97
struct sock * chain
Definition: tcpcore.h:1
unsigned char * LPBYTE
Definition: typedefs.h:53
int ret
char * server_name
Definition: widl.c:145
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
struct _CERT_CHAIN_ELEMENT CERT_CHAIN_ELEMENT
#define CERT_FIND_CERT_ID
Definition: wincrypt.h:2907
#define CERT_CHAIN_POLICY_MICROSOFT_ROOT
Definition: wincrypt.h:968
#define X509_AUTHORITY_KEY_ID2
Definition: wincrypt.h:3398
#define szOID_AUTHORITY_KEY_IDENTIFIER
Definition: wincrypt.h:3175
#define CERT_ID_ISSUER_SERIAL_NUMBER
Definition: wincrypt.h:3673
#define CONTEXT_OID_CERTIFICATE
Definition: wincrypt.h:1627
#define USAGE_MATCH_TYPE_AND
Definition: wincrypt.h:1043
struct _CERT_SIMPLE_CHAIN CERT_SIMPLE_CHAIN
#define CERT_KEY_ENCIPHERMENT_KEY_USAGE
Definition: wincrypt.h:306
#define CERT_CHAIN_POLICY_BASE
Definition: wincrypt.h:962
#define CRYPT_DECODE_NOCOPY_FLAG
Definition: wincrypt.h:3450
#define CERT_KEY_IDENTIFIER_PROP_ID
Definition: wincrypt.h:2706
#define NETSCAPE_SSL_CA_CERT_TYPE
Definition: wincrypt.h:3360
#define CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS
Definition: wincrypt.h:1064
#define X509_NAME
Definition: wincrypt.h:3372
#define CERT_NON_REPUDIATION_KEY_USAGE
Definition: wincrypt.h:305
const CERT_CHAIN_CONTEXT * PCCERT_CHAIN_CONTEXT
Definition: wincrypt.h:935
#define URL_OID_CERTIFICATE_ISSUER
Definition: wincrypt.h:1524
#define CERT_TRUST_IS_REVOKED
Definition: wincrypt.h:872
#define X509_UNICODE_NAME
Definition: wincrypt.h:3385
#define CERT_TRUST_INVALID_POLICY_CONSTRAINTS
Definition: wincrypt.h:879
#define CERT_NAME_SIMPLE_DISPLAY_TYPE
Definition: wincrypt.h:3500
#define CERT_STORE_PROV_COLLECTION
Definition: wincrypt.h:2261
#define CERT_V3
Definition: wincrypt.h:2658
#define HCCE_CURRENT_USER
Definition: wincrypt.h:3613
#define CERT_TRUST_REVOCATION_STATUS_UNKNOWN
Definition: wincrypt.h:876
#define CERT_CHAIN_REVOCATION_CHECK_CHAIN
Definition: wincrypt.h:1057
#define CERT_ALT_NAME_URL
Definition: wincrypt.h:351
#define NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE
Definition: wincrypt.h:3357
#define CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT
Definition: wincrypt.h:889
_In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_opt_ HCERTSTORE _In_ PCERT_CHAIN_PARA pChainPara
Definition: wincrypt.h:4839
#define CERT_CHAIN_POLICY_BASIC_CONSTRAINTS
Definition: wincrypt.h:966
#define szOID_BASIC_CONSTRAINTS2
Definition: wincrypt.h:3189
#define CERT_ALT_NAME_DIRECTORY_NAME
Definition: wincrypt.h:349
#define CERT_TRUST_IS_CYCLIC
Definition: wincrypt.h:877
#define NETSCAPE_SIGN_CERT_TYPE
Definition: wincrypt.h:3359
#define CERT_CHAIN_REVOCATION_CHECK_END_CERT
Definition: wincrypt.h:1056
#define CERT_ID_KEY_IDENTIFIER
Definition: wincrypt.h:3674
#define CERT_ALT_NAME_IP_ADDRESS
Definition: wincrypt.h:352
#define szOID_NAME_CONSTRAINTS
Definition: wincrypt.h:3195
#define CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS
Definition: wincrypt.h:903
#define CERT_STORE_CREATE_NEW_FLAG
Definition: wincrypt.h:2464
#define NETSCAPE_SIGN_CA_CERT_TYPE
Definition: wincrypt.h:3362
#define CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL
Definition: wincrypt.h:3618
#define CERT_TRUST_INVALID_EXTENSION
Definition: wincrypt.h:878
#define szOID_ISSUER_ALT_NAME2
Definition: wincrypt.h:3188
#define CERT_TRUST_INVALID_BASIC_CONSTRAINTS
Definition: wincrypt.h:880
_In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_opt_ HCERTSTORE _In_ PCERT_CHAIN_PARA _In_ DWORD _Reserved_ LPVOID _Out_ PCCERT_CHAIN_CONTEXT * ppChainContext
Definition: wincrypt.h:4842
#define CERT_ALT_NAME_RFC822_NAME
Definition: wincrypt.h:346
#define CERT_ALT_NAME_OTHER_NAME
Definition: wincrypt.h:345
#define CERT_TRUST_HAS_EXACT_MATCH_ISSUER
Definition: wincrypt.h:896
#define CERT_CRL_SIGN_KEY_USAGE
Definition: wincrypt.h:311
#define HCCE_LOCAL_MACHINE
Definition: wincrypt.h:3614
#define CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG
Definition: wincrypt.h:2807
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT
Definition: wincrypt.h:3474
#define CERT_DIGITAL_SIGNATURE_KEY_USAGE
Definition: wincrypt.h:304
#define CERT_V1
Definition: wincrypt.h:2656
#define szOID_KEY_USAGE
Definition: wincrypt.h:3185
#define CERT_TRUST_IS_NOT_TIME_NESTED
Definition: wincrypt.h:871
#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT
Definition: wincrypt.h:3469
#define X509_ASN_ENCODING
Definition: wincrypt.h:2297
#define szOID_ANY_CERT_POLICY
Definition: wincrypt.h:3198
_In_ PCCERT_CONTEXT _In_opt_ LPFILETIME pTime
Definition: wincrypt.h:4837
#define szOID_BASIC_CONSTRAINTS
Definition: wincrypt.h:3183
#define CERT_CHAIN_POLICY_AUTHENTICODE
Definition: wincrypt.h:963
#define CRYPT_AIA_RETRIEVAL
Definition: wincrypt.h:1645
#define CERT_TRUST_IS_SELF_SIGNED
Definition: wincrypt.h:899
_Out_ HCERTCHAINENGINE * phChainEngine
Definition: wincrypt.h:4825
#define CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT
Definition: wincrypt.h:1061
#define CRYPT_DECODE_ALLOC_FLAG
Definition: wincrypt.h:3454
#define CERT_STORE_PROV_MEMORY
Definition: wincrypt.h:2251
#define CERT_TRUST_IS_OFFLINE_REVOCATION
Definition: wincrypt.h:886
#define CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION
Definition: wincrypt.h:820
#define CERT_TRUST_HAS_KEY_MATCH_ISSUER
Definition: wincrypt.h:897
#define X509_AUTHORITY_KEY_ID
Definition: wincrypt.h:3374
#define CERT_ENCIPHER_ONLY_KEY_USAGE
Definition: wincrypt.h:312
#define CERT_SIMPLE_NAME_STR
Definition: wincrypt.h:3484
#define CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT
Definition: wincrypt.h:884
#define szOID_RSA_emailAddr
Definition: wincrypt.h:3035
#define NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE
Definition: wincrypt.h:3356
#define X509_CERT_POLICIES
Definition: wincrypt.h:3381
#define CERT_CA_SUBJECT_FLAG
Definition: wincrypt.h:378
#define AUTHTYPE_SERVER
Definition: wincrypt.h:1035
#define szOID_NETSCAPE_CERT_TYPE
Definition: wincrypt.h:3340
#define CERT_DECIPHER_ONLY_KEY_USAGE
Definition: wincrypt.h:314
#define CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG
Definition: wincrypt.h:980
#define NETSCAPE_SMIME_CERT_TYPE
Definition: wincrypt.h:3358
struct _CERT_CHAIN_CONTEXT CERT_CHAIN_CONTEXT
Definition: wincrypt.h:934
#define CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG
Definition: wincrypt.h:981
#define szOID_SUBJECT_ALT_NAME
Definition: wincrypt.h:3180
#define szOID_CERT_POLICIES
Definition: wincrypt.h:3197
#define CERT_SYSTEM_STORE_LOCAL_MACHINE
Definition: wincrypt.h:2326
#define CERT_CHAIN_POLICY_SSL
Definition: wincrypt.h:965
#define CERT_ALT_NAME_DNS_NAME
Definition: wincrypt.h:347
#define X509_BITS
Definition: wincrypt.h:3392
#define szOID_ENHANCED_KEY_USAGE
Definition: wincrypt.h:3202
#define CERT_STORE_ADD_NEW
Definition: wincrypt.h:2482
#define CERT_TRUST_INVALID_NAME_CONSTRAINTS
Definition: wincrypt.h:881
#define szOID_SUBJECT_ALT_NAME2
Definition: wincrypt.h:3187
#define CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
Definition: wincrypt.h:1058
_In_ PCCERT_CONTEXT pCertContext
Definition: wincrypt.h:4836
#define CERT_HASH_PROP_ID
Definition: wincrypt.h:2688
#define CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG
Definition: wincrypt.h:821
#define CERT_CHAIN_POLICY_IGNORE_NOT_SUPPORTED_CRITICAL_EXT_FLAG
Definition: wincrypt.h:997
#define CERT_NAME_ISSUER_FLAG
Definition: wincrypt.h:3506
#define CERT_CONTEXT_REVOCATION_TYPE
Definition: wincrypt.h:818
#define CERT_TRUST_HAS_NAME_MATCH_ISSUER
Definition: wincrypt.h:898
#define CERT_STORE_PROV_SYSTEM_W
Definition: wincrypt.h:2259
#define CERT_FIND_SUBJECT_NAME
Definition: wincrypt.h:2878
#define CERT_FIND_SHA1_HASH
Definition: wincrypt.h:2865
#define CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT
Definition: wincrypt.h:885
#define CRYPT_OID_VERIFY_CERTIFICATE_CHAIN_POLICY_FUNC
Definition: wincrypt.h:2506
#define CERT_TRUST_IS_PARTIAL_CHAIN
Definition: wincrypt.h:891
#define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY
Definition: wincrypt.h:1059
#define CERT_KEY_AGREEMENT_KEY_USAGE
Definition: wincrypt.h:308
#define CERT_SYSTEM_STORE_CURRENT_USER
Definition: wincrypt.h:2324
#define X509_ALTERNATE_NAME
Definition: wincrypt.h:3377
#define szOID_AUTHORITY_KEY_IDENTIFIER2
Definition: wincrypt.h:3200
#define szOID_COMMON_NAME
Definition: wincrypt.h:3134
#define PKCS_7_ASN_ENCODING
Definition: wincrypt.h:2299
#define NETSCAPE_SMIME_CA_CERT_TYPE
Definition: wincrypt.h:3361
#define X509_NAME_CONSTRAINTS
Definition: wincrypt.h:3425
#define CERT_TRUST_IS_NOT_VALID_FOR_USAGE
Definition: wincrypt.h:874
#define CERT_KEY_CERT_SIGN_KEY_USAGE
Definition: wincrypt.h:309
#define CERT_TRUST_IS_NOT_SIGNATURE_VALID
Definition: wincrypt.h:873
#define szOID_DOMAIN_COMPONENT
Definition: wincrypt.h:3205
#define CERT_DATA_ENCIPHERMENT_KEY_USAGE
Definition: wincrypt.h:307
#define CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT
Definition: wincrypt.h:882
struct _CERT_CHAIN_CONTEXT * PCERT_CHAIN_CONTEXT
Definition: wincrypt.h:934
#define CERT_VERIFY_REV_CHAIN_FLAG
Definition: wincrypt.h:819
struct _CERT_BASIC_CONSTRAINTS2_INFO CERT_BASIC_CONSTRAINTS2_INFO
#define CERT_ALT_NAME_REGISTERED_ID
Definition: wincrypt.h:353
_In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_opt_ HCERTSTORE hAdditionalStore
Definition: wincrypt.h:4838
#define X509_ENHANCED_KEY_USAGE
Definition: wincrypt.h:3403
#define CRYPT_CACHE_ONLY_RETRIEVAL
Definition: wincrypt.h:1634
#define CERT_TRUST_IS_UNTRUSTED_ROOT
Definition: wincrypt.h:875
#define CERT_TRUST_IS_NOT_TIME_VALID
Definition: wincrypt.h:870
#define szOID_ISSUER_ALT_NAME
Definition: wincrypt.h:3181
#define CERT_V2
Definition: wincrypt.h:2657
#define WINAPI
Definition: msvc.h:6
#define CRYPT_E_REVOKED
Definition: winerror.h:3019
#define CERT_E_REVOCATION_FAILURE
Definition: winerror.h:3130
#define CERT_E_CHAINING
Definition: winerror.h:3126
#define CERT_E_UNTRUSTEDROOT
Definition: winerror.h:3125
#define CERT_E_UNTRUSTEDTESTROOT
Definition: winerror.h:3129
#define CERT_E_REVOKED
Definition: winerror.h:3128
#define CRYPT_E_NO_REVOCATION_DLL
Definition: winerror.h:3020
#define CRYPT_E_NOT_IN_REVOCATION_DATABASE
Definition: winerror.h:3023
#define CERT_E_WRONG_USAGE
Definition: winerror.h:3132
#define TRUST_E_CERT_SIGNATURE
Definition: winerror.h:3107
#define CERT_E_CRITICAL
Definition: winerror.h:3121
#define TRUST_E_BASIC_CONSTRAINTS
Definition: winerror.h:3110
#define CRYPT_E_NO_REVOCATION_CHECK
Definition: winerror.h:3021
#define CERT_E_CN_NO_MATCH
Definition: winerror.h:3131
#define CRYPT_E_REVOCATION_OFFLINE
Definition: winerror.h:3022
#define CERT_E_EXPIRED
Definition: winerror.h:3117
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
Definition: winhttp.h:282
#define SECURITY_FLAG_IGNORE_UNKNOWN_CA
Definition: winhttp.h:281
#define SECURITY_FLAG_IGNORE_CERT_CN_INVALID
Definition: winhttp.h:283
#define SECURITY_FLAG_IGNORE_WRONG_USAGE
Definition: wininet.h:831
#define SECURITY_FLAG_IGNORE_REVOCATION
Definition: wininet.h:829
#define LOCALE_SSHORTDATE
Definition: winnls.h:60
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193