1
2
3
4
5 package x509
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "net"
12 "net/url"
13 "reflect"
14 "runtime"
15 "strings"
16 "time"
17 "unicode/utf8"
18 )
19
20 type InvalidReason int
21
22 const (
23
24
25 NotAuthorizedToSign InvalidReason = iota
26
27
28 Expired
29
30
31
32 CANotAuthorizedForThisName
33
34
35 TooManyIntermediates
36
37
38 IncompatibleUsage
39
40
41 NameMismatch
42
43 NameConstraintsWithoutSANs
44
45
46
47 UnconstrainedName
48
49
50
51
52
53 TooManyConstraints
54
55
56 CANotAuthorizedForExtKeyUsage
57 )
58
59
60
61 type CertificateInvalidError struct {
62 Cert *Certificate
63 Reason InvalidReason
64 Detail string
65 }
66
67 func (e CertificateInvalidError) Error() string {
68 switch e.Reason {
69 case NotAuthorizedToSign:
70 return "x509: certificate is not authorized to sign other certificates"
71 case Expired:
72 return "x509: certificate has expired or is not yet valid: " + e.Detail
73 case CANotAuthorizedForThisName:
74 return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e.Detail
75 case CANotAuthorizedForExtKeyUsage:
76 return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e.Detail
77 case TooManyIntermediates:
78 return "x509: too many intermediates for path length constraint"
79 case IncompatibleUsage:
80 return "x509: certificate specifies an incompatible key usage"
81 case NameMismatch:
82 return "x509: issuer name does not match subject from issuing certificate"
83 case NameConstraintsWithoutSANs:
84 return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
85 case UnconstrainedName:
86 return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail
87 }
88 return "x509: unknown error"
89 }
90
91
92
93 type HostnameError struct {
94 Certificate *Certificate
95 Host string
96 }
97
98 func (h HostnameError) Error() string {
99 c := h.Certificate
100
101 if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
102 return "x509: certificate relies on legacy Common Name field, use SANs instead"
103 }
104
105 var valid string
106 if ip := net.ParseIP(h.Host); ip != nil {
107
108 if len(c.IPAddresses) == 0 {
109 return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
110 }
111 for _, san := range c.IPAddresses {
112 if len(valid) > 0 {
113 valid += ", "
114 }
115 valid += san.String()
116 }
117 } else {
118 valid = strings.Join(c.DNSNames, ", ")
119 }
120
121 if len(valid) == 0 {
122 return "x509: certificate is not valid for any names, but wanted to match " + h.Host
123 }
124 return "x509: certificate is valid for " + valid + ", not " + h.Host
125 }
126
127
128 type UnknownAuthorityError struct {
129 Cert *Certificate
130
131
132 hintErr error
133
134
135 hintCert *Certificate
136 }
137
138 func (e UnknownAuthorityError) Error() string {
139 s := "x509: certificate signed by unknown authority"
140 if e.hintErr != nil {
141 certName := e.hintCert.Subject.CommonName
142 if len(certName) == 0 {
143 if len(e.hintCert.Subject.Organization) > 0 {
144 certName = e.hintCert.Subject.Organization[0]
145 } else {
146 certName = "serial:" + e.hintCert.SerialNumber.String()
147 }
148 }
149 s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
150 }
151 return s
152 }
153
154
155 type SystemRootsError struct {
156 Err error
157 }
158
159 func (se SystemRootsError) Error() string {
160 msg := "x509: failed to load system roots and no roots provided"
161 if se.Err != nil {
162 return msg + "; " + se.Err.Error()
163 }
164 return msg
165 }
166
167 func (se SystemRootsError) Unwrap() error { return se.Err }
168
169
170
171 var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
172
173
174 type VerifyOptions struct {
175
176
177 DNSName string
178
179
180
181
182 Intermediates *CertPool
183
184
185 Roots *CertPool
186
187
188
189 CurrentTime time.Time
190
191
192
193
194 KeyUsages []ExtKeyUsage
195
196
197
198
199
200
201 MaxConstraintComparisions int
202 }
203
204 const (
205 leafCertificate = iota
206 intermediateCertificate
207 rootCertificate
208 )
209
210
211
212
213 type rfc2821Mailbox struct {
214 local, domain string
215 }
216
217
218
219
220
221 func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) {
222 if len(in) == 0 {
223 return mailbox, false
224 }
225
226 localPartBytes := make([]byte, 0, len(in)/2)
227
228 if in[0] == '"' {
229
230
231
232
233
234
235
236
237
238
239 in = in[1:]
240 QuotedString:
241 for {
242 if len(in) == 0 {
243 return mailbox, false
244 }
245 c := in[0]
246 in = in[1:]
247
248 switch {
249 case c == '"':
250 break QuotedString
251
252 case c == '\\':
253
254 if len(in) == 0 {
255 return mailbox, false
256 }
257 if in[0] == 11 ||
258 in[0] == 12 ||
259 (1 <= in[0] && in[0] <= 9) ||
260 (14 <= in[0] && in[0] <= 127) {
261 localPartBytes = append(localPartBytes, in[0])
262 in = in[1:]
263 } else {
264 return mailbox, false
265 }
266
267 case c == 11 ||
268 c == 12 ||
269
270
271
272
273
274 c == 32 ||
275 c == 33 ||
276 c == 127 ||
277 (1 <= c && c <= 8) ||
278 (14 <= c && c <= 31) ||
279 (35 <= c && c <= 91) ||
280 (93 <= c && c <= 126):
281
282 localPartBytes = append(localPartBytes, c)
283
284 default:
285 return mailbox, false
286 }
287 }
288 } else {
289
290 NextChar:
291 for len(in) > 0 {
292
293 c := in[0]
294
295 switch {
296 case c == '\\':
297
298
299
300
301
302 in = in[1:]
303 if len(in) == 0 {
304 return mailbox, false
305 }
306 fallthrough
307
308 case ('0' <= c && c <= '9') ||
309 ('a' <= c && c <= 'z') ||
310 ('A' <= c && c <= 'Z') ||
311 c == '!' || c == '#' || c == '$' || c == '%' ||
312 c == '&' || c == '\'' || c == '*' || c == '+' ||
313 c == '-' || c == '/' || c == '=' || c == '?' ||
314 c == '^' || c == '_' || c == '`' || c == '{' ||
315 c == '|' || c == '}' || c == '~' || c == '.':
316 localPartBytes = append(localPartBytes, in[0])
317 in = in[1:]
318
319 default:
320 break NextChar
321 }
322 }
323
324 if len(localPartBytes) == 0 {
325 return mailbox, false
326 }
327
328
329
330
331
332 twoDots := []byte{'.', '.'}
333 if localPartBytes[0] == '.' ||
334 localPartBytes[len(localPartBytes)-1] == '.' ||
335 bytes.Contains(localPartBytes, twoDots) {
336 return mailbox, false
337 }
338 }
339
340 if len(in) == 0 || in[0] != '@' {
341 return mailbox, false
342 }
343 in = in[1:]
344
345
346
347
348 if _, ok := domainToReverseLabels(in); !ok {
349 return mailbox, false
350 }
351
352 mailbox.local = string(localPartBytes)
353 mailbox.domain = in
354 return mailbox, true
355 }
356
357
358
359 func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {
360 for len(domain) > 0 {
361 if i := strings.LastIndexByte(domain, '.'); i == -1 {
362 reverseLabels = append(reverseLabels, domain)
363 domain = ""
364 } else {
365 reverseLabels = append(reverseLabels, domain[i+1:])
366 domain = domain[:i]
367 }
368 }
369
370 if len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 {
371
372 return nil, false
373 }
374
375 for _, label := range reverseLabels {
376 if len(label) == 0 {
377
378 return nil, false
379 }
380
381 for _, c := range label {
382 if c < 33 || c > 126 {
383
384 return nil, false
385 }
386 }
387 }
388
389 return reverseLabels, true
390 }
391
392 func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) {
393
394
395 if strings.Contains(constraint, "@") {
396 constraintMailbox, ok := parseRFC2821Mailbox(constraint)
397 if !ok {
398 return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", constraint)
399 }
400 return mailbox.local == constraintMailbox.local && strings.EqualFold(mailbox.domain, constraintMailbox.domain), nil
401 }
402
403
404
405 return matchDomainConstraint(mailbox.domain, constraint)
406 }
407
408 func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
409
410
411
412
413
414
415
416
417 host := uri.Host
418 if len(host) == 0 {
419 return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", uri.String())
420 }
421
422 if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") {
423 var err error
424 host, _, err = net.SplitHostPort(uri.Host)
425 if err != nil {
426 return false, err
427 }
428 }
429
430 if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") ||
431 net.ParseIP(host) != nil {
432 return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
433 }
434
435 return matchDomainConstraint(host, constraint)
436 }
437
438 func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
439 if len(ip) != len(constraint.IP) {
440 return false, nil
441 }
442
443 for i := range ip {
444 if mask := constraint.Mask[i]; ip[i]&mask != constraint.IP[i]&mask {
445 return false, nil
446 }
447 }
448
449 return true, nil
450 }
451
452 func matchDomainConstraint(domain, constraint string) (bool, error) {
453
454
455 if len(constraint) == 0 {
456 return true, nil
457 }
458
459 domainLabels, ok := domainToReverseLabels(domain)
460 if !ok {
461 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain)
462 }
463
464
465
466
467
468
469 mustHaveSubdomains := false
470 if constraint[0] == '.' {
471 mustHaveSubdomains = true
472 constraint = constraint[1:]
473 }
474
475 constraintLabels, ok := domainToReverseLabels(constraint)
476 if !ok {
477 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint)
478 }
479
480 if len(domainLabels) < len(constraintLabels) ||
481 (mustHaveSubdomains && len(domainLabels) == len(constraintLabels)) {
482 return false, nil
483 }
484
485 for i, constraintLabel := range constraintLabels {
486 if !strings.EqualFold(constraintLabel, domainLabels[i]) {
487 return false, nil
488 }
489 }
490
491 return true, nil
492 }
493
494
495
496
497
498
499 func (c *Certificate) checkNameConstraints(count *int,
500 maxConstraintComparisons int,
501 nameType string,
502 name string,
503 parsedName any,
504 match func(parsedName, constraint any) (match bool, err error),
505 permitted, excluded any) error {
506
507 excludedValue := reflect.ValueOf(excluded)
508
509 *count += excludedValue.Len()
510 if *count > maxConstraintComparisons {
511 return CertificateInvalidError{c, TooManyConstraints, ""}
512 }
513
514 for i := 0; i < excludedValue.Len(); i++ {
515 constraint := excludedValue.Index(i).Interface()
516 match, err := match(parsedName, constraint)
517 if err != nil {
518 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
519 }
520
521 if match {
522 return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", nameType, name, constraint)}
523 }
524 }
525
526 permittedValue := reflect.ValueOf(permitted)
527
528 *count += permittedValue.Len()
529 if *count > maxConstraintComparisons {
530 return CertificateInvalidError{c, TooManyConstraints, ""}
531 }
532
533 ok := true
534 for i := 0; i < permittedValue.Len(); i++ {
535 constraint := permittedValue.Index(i).Interface()
536
537 var err error
538 if ok, err = match(parsedName, constraint); err != nil {
539 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
540 }
541
542 if ok {
543 break
544 }
545 }
546
547 if !ok {
548 return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", nameType, name)}
549 }
550
551 return nil
552 }
553
554
555
556 func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
557 if len(c.UnhandledCriticalExtensions) > 0 {
558 return UnhandledCriticalExtension{}
559 }
560
561 if len(currentChain) > 0 {
562 child := currentChain[len(currentChain)-1]
563 if !bytes.Equal(child.RawIssuer, c.RawSubject) {
564 return CertificateInvalidError{c, NameMismatch, ""}
565 }
566 }
567
568 now := opts.CurrentTime
569 if now.IsZero() {
570 now = time.Now()
571 }
572 if now.Before(c.NotBefore) {
573 return CertificateInvalidError{
574 Cert: c,
575 Reason: Expired,
576 Detail: fmt.Sprintf("current time %s is before %s", now.Format(time.RFC3339), c.NotBefore.Format(time.RFC3339)),
577 }
578 } else if now.After(c.NotAfter) {
579 return CertificateInvalidError{
580 Cert: c,
581 Reason: Expired,
582 Detail: fmt.Sprintf("current time %s is after %s", now.Format(time.RFC3339), c.NotAfter.Format(time.RFC3339)),
583 }
584 }
585
586 maxConstraintComparisons := opts.MaxConstraintComparisions
587 if maxConstraintComparisons == 0 {
588 maxConstraintComparisons = 250000
589 }
590 comparisonCount := 0
591
592 var leaf *Certificate
593 if certType == intermediateCertificate || certType == rootCertificate {
594 if len(currentChain) == 0 {
595 return errors.New("x509: internal error: empty chain when appending CA cert")
596 }
597 leaf = currentChain[0]
598 }
599
600 if (certType == intermediateCertificate || certType == rootCertificate) &&
601 c.hasNameConstraints() && leaf.hasSANExtension() {
602 err := forEachSAN(leaf.getSANExtension(), func(tag int, data []byte) error {
603 switch tag {
604 case nameTypeEmail:
605 name := string(data)
606 mailbox, ok := parseRFC2821Mailbox(name)
607 if !ok {
608 return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox)
609 }
610
611 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
612 func(parsedName, constraint any) (bool, error) {
613 return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string))
614 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
615 return err
616 }
617
618 case nameTypeDNS:
619 name := string(data)
620 if _, ok := domainToReverseLabels(name); !ok {
621 return fmt.Errorf("x509: cannot parse dnsName %q", name)
622 }
623
624 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
625 func(parsedName, constraint any) (bool, error) {
626 return matchDomainConstraint(parsedName.(string), constraint.(string))
627 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
628 return err
629 }
630
631 case nameTypeURI:
632 name := string(data)
633 uri, err := url.Parse(name)
634 if err != nil {
635 return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name)
636 }
637
638 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
639 func(parsedName, constraint any) (bool, error) {
640 return matchURIConstraint(parsedName.(*url.URL), constraint.(string))
641 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
642 return err
643 }
644
645 case nameTypeIP:
646 ip := net.IP(data)
647 if l := len(ip); l != net.IPv4len && l != net.IPv6len {
648 return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data)
649 }
650
651 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip,
652 func(parsedName, constraint any) (bool, error) {
653 return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet))
654 }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil {
655 return err
656 }
657
658 default:
659
660 }
661
662 return nil
663 })
664
665 if err != nil {
666 return err
667 }
668 }
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687 if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
688 return CertificateInvalidError{c, NotAuthorizedToSign, ""}
689 }
690
691 if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
692 numIntermediates := len(currentChain) - 1
693 if numIntermediates > c.MaxPathLen {
694 return CertificateInvalidError{c, TooManyIntermediates, ""}
695 }
696 }
697
698 return nil
699 }
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
732
733
734 if len(c.Raw) == 0 {
735 return nil, errNotParsed
736 }
737 for i := 0; i < opts.Intermediates.len(); i++ {
738 c, err := opts.Intermediates.cert(i)
739 if err != nil {
740 return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", err)
741 }
742 if len(c.Raw) == 0 {
743 return nil, errNotParsed
744 }
745 }
746
747
748 if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
749 if opts.Roots == nil {
750 return c.systemVerify(&opts)
751 }
752 if opts.Roots != nil && opts.Roots.systemPool {
753 platformChains, err := c.systemVerify(&opts)
754
755
756
757 if err == nil || opts.Roots.len() == 0 {
758 return platformChains, err
759 }
760 }
761 }
762
763 if opts.Roots == nil {
764 opts.Roots = systemRootsPool()
765 if opts.Roots == nil {
766 return nil, SystemRootsError{systemRootsErr}
767 }
768 }
769
770 err = c.isValid(leafCertificate, nil, &opts)
771 if err != nil {
772 return
773 }
774
775 if len(opts.DNSName) > 0 {
776 err = c.VerifyHostname(opts.DNSName)
777 if err != nil {
778 return
779 }
780 }
781
782 var candidateChains [][]*Certificate
783 if opts.Roots.contains(c) {
784 candidateChains = append(candidateChains, []*Certificate{c})
785 } else {
786 if candidateChains, err = c.buildChains(nil, []*Certificate{c}, nil, &opts); err != nil {
787 return nil, err
788 }
789 }
790
791 keyUsages := opts.KeyUsages
792 if len(keyUsages) == 0 {
793 keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
794 }
795
796
797 for _, usage := range keyUsages {
798 if usage == ExtKeyUsageAny {
799 return candidateChains, nil
800 }
801 }
802
803 for _, candidate := range candidateChains {
804 if checkChainForKeyUsage(candidate, keyUsages) {
805 chains = append(chains, candidate)
806 }
807 }
808
809 if len(chains) == 0 {
810 return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
811 }
812
813 return chains, nil
814 }
815
816 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
817 n := make([]*Certificate, len(chain)+1)
818 copy(n, chain)
819 n[len(chain)] = cert
820 return n
821 }
822
823
824
825
826
827 const maxChainSignatureChecks = 100
828
829 func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) {
830 var (
831 hintErr error
832 hintCert *Certificate
833 )
834
835 considerCandidate := func(certType int, candidate *Certificate) {
836 for _, cert := range currentChain {
837 if cert.Equal(candidate) {
838 return
839 }
840 }
841
842 if sigChecks == nil {
843 sigChecks = new(int)
844 }
845 *sigChecks++
846 if *sigChecks > maxChainSignatureChecks {
847 err = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
848 return
849 }
850
851 if err := c.CheckSignatureFrom(candidate); err != nil {
852 if hintErr == nil {
853 hintErr = err
854 hintCert = candidate
855 }
856 return
857 }
858
859 err = candidate.isValid(certType, currentChain, opts)
860 if err != nil {
861 return
862 }
863
864 switch certType {
865 case rootCertificate:
866 chains = append(chains, appendToFreshChain(currentChain, candidate))
867 case intermediateCertificate:
868 if cache == nil {
869 cache = make(map[*Certificate][][]*Certificate)
870 }
871 childChains, ok := cache[candidate]
872 if !ok {
873 childChains, err = candidate.buildChains(cache, appendToFreshChain(currentChain, candidate), sigChecks, opts)
874 cache[candidate] = childChains
875 }
876 chains = append(chains, childChains...)
877 }
878 }
879
880 for _, root := range opts.Roots.findPotentialParents(c) {
881 considerCandidate(rootCertificate, root)
882 }
883 for _, intermediate := range opts.Intermediates.findPotentialParents(c) {
884 considerCandidate(intermediateCertificate, intermediate)
885 }
886
887 if len(chains) > 0 {
888 err = nil
889 }
890 if len(chains) == 0 && err == nil {
891 err = UnknownAuthorityError{c, hintErr, hintCert}
892 }
893
894 return
895 }
896
897 func validHostnamePattern(host string) bool { return validHostname(host, true) }
898 func validHostnameInput(host string) bool { return validHostname(host, false) }
899
900
901
902
903 func validHostname(host string, isPattern bool) bool {
904 if !isPattern {
905 host = strings.TrimSuffix(host, ".")
906 }
907 if len(host) == 0 {
908 return false
909 }
910
911 for i, part := range strings.Split(host, ".") {
912 if part == "" {
913
914 return false
915 }
916 if isPattern && i == 0 && part == "*" {
917
918
919
920 continue
921 }
922 for j, c := range part {
923 if 'a' <= c && c <= 'z' {
924 continue
925 }
926 if '0' <= c && c <= '9' {
927 continue
928 }
929 if 'A' <= c && c <= 'Z' {
930 continue
931 }
932 if c == '-' && j != 0 {
933 continue
934 }
935 if c == '_' {
936
937
938 continue
939 }
940 return false
941 }
942 }
943
944 return true
945 }
946
947 func matchExactly(hostA, hostB string) bool {
948 if hostA == "" || hostA == "." || hostB == "" || hostB == "." {
949 return false
950 }
951 return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB)
952 }
953
954 func matchHostnames(pattern, host string) bool {
955 pattern = toLowerCaseASCII(pattern)
956 host = toLowerCaseASCII(strings.TrimSuffix(host, "."))
957
958 if len(pattern) == 0 || len(host) == 0 {
959 return false
960 }
961
962 patternParts := strings.Split(pattern, ".")
963 hostParts := strings.Split(host, ".")
964
965 if len(patternParts) != len(hostParts) {
966 return false
967 }
968
969 for i, patternPart := range patternParts {
970 if i == 0 && patternPart == "*" {
971 continue
972 }
973 if patternPart != hostParts[i] {
974 return false
975 }
976 }
977
978 return true
979 }
980
981
982
983
984 func toLowerCaseASCII(in string) string {
985
986 isAlreadyLowerCase := true
987 for _, c := range in {
988 if c == utf8.RuneError {
989
990
991 isAlreadyLowerCase = false
992 break
993 }
994 if 'A' <= c && c <= 'Z' {
995 isAlreadyLowerCase = false
996 break
997 }
998 }
999
1000 if isAlreadyLowerCase {
1001 return in
1002 }
1003
1004 out := []byte(in)
1005 for i, c := range out {
1006 if 'A' <= c && c <= 'Z' {
1007 out[i] += 'a' - 'A'
1008 }
1009 }
1010 return string(out)
1011 }
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 func (c *Certificate) VerifyHostname(h string) error {
1023
1024 candidateIP := h
1025 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
1026 candidateIP = h[1 : len(h)-1]
1027 }
1028 if ip := net.ParseIP(candidateIP); ip != nil {
1029
1030
1031 for _, candidate := range c.IPAddresses {
1032 if ip.Equal(candidate) {
1033 return nil
1034 }
1035 }
1036 return HostnameError{c, candidateIP}
1037 }
1038
1039 candidateName := toLowerCaseASCII(h)
1040 validCandidateName := validHostnameInput(candidateName)
1041
1042 for _, match := range c.DNSNames {
1043
1044
1045
1046
1047
1048 if validCandidateName && validHostnamePattern(match) {
1049 if matchHostnames(match, candidateName) {
1050 return nil
1051 }
1052 } else {
1053 if matchExactly(match, candidateName) {
1054 return nil
1055 }
1056 }
1057 }
1058
1059 return HostnameError{c, h}
1060 }
1061
1062 func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
1063 usages := make([]ExtKeyUsage, len(keyUsages))
1064 copy(usages, keyUsages)
1065
1066 if len(chain) == 0 {
1067 return false
1068 }
1069
1070 usagesRemaining := len(usages)
1071
1072
1073
1074
1075
1076 NextCert:
1077 for i := len(chain) - 1; i >= 0; i-- {
1078 cert := chain[i]
1079 if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
1080
1081 continue
1082 }
1083
1084 for _, usage := range cert.ExtKeyUsage {
1085 if usage == ExtKeyUsageAny {
1086
1087 continue NextCert
1088 }
1089 }
1090
1091 const invalidUsage ExtKeyUsage = -1
1092
1093 NextRequestedUsage:
1094 for i, requestedUsage := range usages {
1095 if requestedUsage == invalidUsage {
1096 continue
1097 }
1098
1099 for _, usage := range cert.ExtKeyUsage {
1100 if requestedUsage == usage {
1101 continue NextRequestedUsage
1102 }
1103 }
1104
1105 usages[i] = invalidUsage
1106 usagesRemaining--
1107 if usagesRemaining == 0 {
1108 return false
1109 }
1110 }
1111 }
1112
1113 return true
1114 }
1115
View as plain text