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