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 potentialParent) {
902 if candidate.cert.PublicKey == nil || alreadyInChain(candidate.cert, 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.cert); err != nil {
916 if hintErr == nil {
917 hintErr = err
918 hintCert = candidate.cert
919 }
920 return
921 }
922
923 err = candidate.cert.isValid(certType, currentChain, opts)
924 if err != nil {
925 if hintErr == nil {
926 hintErr = err
927 hintCert = candidate.cert
928 }
929 return
930 }
931
932 if candidate.constraint != nil {
933 if err := candidate.constraint(currentChain); err != nil {
934 if hintErr == nil {
935 hintErr = err
936 hintCert = candidate.cert
937 }
938 return
939 }
940 }
941
942 switch certType {
943 case rootCertificate:
944 chains = append(chains, appendToFreshChain(currentChain, candidate.cert))
945 case intermediateCertificate:
946 var childChains [][]*Certificate
947 childChains, err = candidate.cert.buildChains(appendToFreshChain(currentChain, candidate.cert), sigChecks, opts)
948 chains = append(chains, childChains...)
949 }
950 }
951
952 for _, root := range opts.Roots.findPotentialParents(c) {
953 considerCandidate(rootCertificate, root)
954 }
955 for _, intermediate := range opts.Intermediates.findPotentialParents(c) {
956 considerCandidate(intermediateCertificate, intermediate)
957 }
958
959 if len(chains) > 0 {
960 err = nil
961 }
962 if len(chains) == 0 && err == nil {
963 err = UnknownAuthorityError{c, hintErr, hintCert}
964 }
965
966 return
967 }
968
969 func validHostnamePattern(host string) bool { return validHostname(host, true) }
970 func validHostnameInput(host string) bool { return validHostname(host, false) }
971
972
973
974
975 func validHostname(host string, isPattern bool) bool {
976 if !isPattern {
977 host = strings.TrimSuffix(host, ".")
978 }
979 if len(host) == 0 {
980 return false
981 }
982
983 for i, part := range strings.Split(host, ".") {
984 if part == "" {
985
986 return false
987 }
988 if isPattern && i == 0 && part == "*" {
989
990
991
992 continue
993 }
994 for j, c := range part {
995 if 'a' <= c && c <= 'z' {
996 continue
997 }
998 if '0' <= c && c <= '9' {
999 continue
1000 }
1001 if 'A' <= c && c <= 'Z' {
1002 continue
1003 }
1004 if c == '-' && j != 0 {
1005 continue
1006 }
1007 if c == '_' {
1008
1009
1010 continue
1011 }
1012 return false
1013 }
1014 }
1015
1016 return true
1017 }
1018
1019 func matchExactly(hostA, hostB string) bool {
1020 if hostA == "" || hostA == "." || hostB == "" || hostB == "." {
1021 return false
1022 }
1023 return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB)
1024 }
1025
1026 func matchHostnames(pattern, host string) bool {
1027 pattern = toLowerCaseASCII(pattern)
1028 host = toLowerCaseASCII(strings.TrimSuffix(host, "."))
1029
1030 if len(pattern) == 0 || len(host) == 0 {
1031 return false
1032 }
1033
1034 patternParts := strings.Split(pattern, ".")
1035 hostParts := strings.Split(host, ".")
1036
1037 if len(patternParts) != len(hostParts) {
1038 return false
1039 }
1040
1041 for i, patternPart := range patternParts {
1042 if i == 0 && patternPart == "*" {
1043 continue
1044 }
1045 if patternPart != hostParts[i] {
1046 return false
1047 }
1048 }
1049
1050 return true
1051 }
1052
1053
1054
1055
1056 func toLowerCaseASCII(in string) string {
1057
1058 isAlreadyLowerCase := true
1059 for _, c := range in {
1060 if c == utf8.RuneError {
1061
1062
1063 isAlreadyLowerCase = false
1064 break
1065 }
1066 if 'A' <= c && c <= 'Z' {
1067 isAlreadyLowerCase = false
1068 break
1069 }
1070 }
1071
1072 if isAlreadyLowerCase {
1073 return in
1074 }
1075
1076 out := []byte(in)
1077 for i, c := range out {
1078 if 'A' <= c && c <= 'Z' {
1079 out[i] += 'a' - 'A'
1080 }
1081 }
1082 return string(out)
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 func (c *Certificate) VerifyHostname(h string) error {
1095
1096 candidateIP := h
1097 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
1098 candidateIP = h[1 : len(h)-1]
1099 }
1100 if ip := net.ParseIP(candidateIP); ip != nil {
1101
1102
1103 for _, candidate := range c.IPAddresses {
1104 if ip.Equal(candidate) {
1105 return nil
1106 }
1107 }
1108 return HostnameError{c, candidateIP}
1109 }
1110
1111 candidateName := toLowerCaseASCII(h)
1112 validCandidateName := validHostnameInput(candidateName)
1113
1114 for _, match := range c.DNSNames {
1115
1116
1117
1118
1119
1120 if validCandidateName && validHostnamePattern(match) {
1121 if matchHostnames(match, candidateName) {
1122 return nil
1123 }
1124 } else {
1125 if matchExactly(match, candidateName) {
1126 return nil
1127 }
1128 }
1129 }
1130
1131 return HostnameError{c, h}
1132 }
1133
1134 func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
1135 usages := make([]ExtKeyUsage, len(keyUsages))
1136 copy(usages, keyUsages)
1137
1138 if len(chain) == 0 {
1139 return false
1140 }
1141
1142 usagesRemaining := len(usages)
1143
1144
1145
1146
1147
1148 NextCert:
1149 for i := len(chain) - 1; i >= 0; i-- {
1150 cert := chain[i]
1151 if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
1152
1153 continue
1154 }
1155
1156 for _, usage := range cert.ExtKeyUsage {
1157 if usage == ExtKeyUsageAny {
1158
1159 continue NextCert
1160 }
1161 }
1162
1163 const invalidUsage ExtKeyUsage = -1
1164
1165 NextRequestedUsage:
1166 for i, requestedUsage := range usages {
1167 if requestedUsage == invalidUsage {
1168 continue
1169 }
1170
1171 for _, usage := range cert.ExtKeyUsage {
1172 if requestedUsage == usage {
1173 continue NextRequestedUsage
1174 }
1175 }
1176
1177 usages[i] = invalidUsage
1178 usagesRemaining--
1179 if usagesRemaining == 0 {
1180 return false
1181 }
1182 }
1183 }
1184
1185 return true
1186 }
1187
View as plain text