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 var leaf *Certificate
595 if certType == intermediateCertificate || certType == rootCertificate {
596 if len(currentChain) == 0 {
597 return errors.New("x509: internal error: empty chain when appending CA cert")
598 }
599 leaf = currentChain[0]
600 }
601
602 if (certType == intermediateCertificate || certType == rootCertificate) &&
603 c.hasNameConstraints() {
604 toCheck := []*Certificate{}
605 if leaf.hasSANExtension() {
606 toCheck = append(toCheck, leaf)
607 }
608 if c.hasSANExtension() {
609 toCheck = append(toCheck, c)
610 }
611 for _, sanCert := range toCheck {
612 err := forEachSAN(sanCert.getSANExtension(), func(tag int, data []byte) error {
613 switch tag {
614 case nameTypeEmail:
615 name := string(data)
616 mailbox, ok := parseRFC2821Mailbox(name)
617 if !ok {
618 return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox)
619 }
620
621 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
622 func(parsedName, constraint any) (bool, error) {
623 return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string))
624 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
625 return err
626 }
627
628 case nameTypeDNS:
629 name := string(data)
630 if _, ok := domainToReverseLabels(name); !ok {
631 return fmt.Errorf("x509: cannot parse dnsName %q", name)
632 }
633
634 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
635 func(parsedName, constraint any) (bool, error) {
636 return matchDomainConstraint(parsedName.(string), constraint.(string))
637 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
638 return err
639 }
640
641 case nameTypeURI:
642 name := string(data)
643 uri, err := url.Parse(name)
644 if err != nil {
645 return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name)
646 }
647
648 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
649 func(parsedName, constraint any) (bool, error) {
650 return matchURIConstraint(parsedName.(*url.URL), constraint.(string))
651 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
652 return err
653 }
654
655 case nameTypeIP:
656 ip := net.IP(data)
657 if l := len(ip); l != net.IPv4len && l != net.IPv6len {
658 return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data)
659 }
660
661 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip,
662 func(parsedName, constraint any) (bool, error) {
663 return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet))
664 }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil {
665 return err
666 }
667
668 default:
669
670 }
671
672 return nil
673 })
674
675 if err != nil {
676 return err
677 }
678 }
679 }
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698 if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
699 return CertificateInvalidError{c, NotAuthorizedToSign, ""}
700 }
701
702 if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
703 numIntermediates := len(currentChain) - 1
704 if numIntermediates > c.MaxPathLen {
705 return CertificateInvalidError{c, TooManyIntermediates, ""}
706 }
707 }
708
709 if !boringAllowCert(c) {
710
711
712
713 return CertificateInvalidError{c, IncompatibleUsage, ""}
714 }
715
716 return nil
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
749 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
750
751
752 if len(c.Raw) == 0 {
753 return nil, errNotParsed
754 }
755 for i := 0; i < opts.Intermediates.len(); i++ {
756 c, err := opts.Intermediates.cert(i)
757 if err != nil {
758 return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", err)
759 }
760 if len(c.Raw) == 0 {
761 return nil, errNotParsed
762 }
763 }
764
765
766 if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
767 if opts.Roots == nil {
768 return c.systemVerify(&opts)
769 }
770 if opts.Roots != nil && opts.Roots.systemPool {
771 platformChains, err := c.systemVerify(&opts)
772
773
774
775 if err == nil || opts.Roots.len() == 0 {
776 return platformChains, err
777 }
778 }
779 }
780
781 if opts.Roots == nil {
782 opts.Roots = systemRootsPool()
783 if opts.Roots == nil {
784 return nil, SystemRootsError{systemRootsErr}
785 }
786 }
787
788 err = c.isValid(leafCertificate, nil, &opts)
789 if err != nil {
790 return
791 }
792
793 if len(opts.DNSName) > 0 {
794 err = c.VerifyHostname(opts.DNSName)
795 if err != nil {
796 return
797 }
798 }
799
800 var candidateChains [][]*Certificate
801 if opts.Roots.contains(c) {
802 candidateChains = [][]*Certificate{{c}}
803 } else {
804 candidateChains, err = c.buildChains([]*Certificate{c}, nil, &opts)
805 if err != nil {
806 return nil, err
807 }
808 }
809
810 if len(opts.KeyUsages) == 0 {
811 opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
812 }
813
814 for _, eku := range opts.KeyUsages {
815 if eku == ExtKeyUsageAny {
816
817
818 return candidateChains, nil
819 }
820 }
821
822 chains = make([][]*Certificate, 0, len(candidateChains))
823 for _, candidate := range candidateChains {
824 if checkChainForKeyUsage(candidate, opts.KeyUsages) {
825 chains = append(chains, candidate)
826 }
827 }
828
829 if len(chains) == 0 {
830 return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
831 }
832
833 return chains, nil
834 }
835
836 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
837 n := make([]*Certificate, len(chain)+1)
838 copy(n, chain)
839 n[len(chain)] = cert
840 return n
841 }
842
843
844
845
846
847
848 func alreadyInChain(candidate *Certificate, chain []*Certificate) bool {
849 type pubKeyEqual interface {
850 Equal(crypto.PublicKey) bool
851 }
852
853 var candidateSAN *pkix.Extension
854 for _, ext := range candidate.Extensions {
855 if ext.Id.Equal(oidExtensionSubjectAltName) {
856 candidateSAN = &ext
857 break
858 }
859 }
860
861 for _, cert := range chain {
862 if !bytes.Equal(candidate.RawSubject, cert.RawSubject) {
863 continue
864 }
865 if !candidate.PublicKey.(pubKeyEqual).Equal(cert.PublicKey) {
866 continue
867 }
868 var certSAN *pkix.Extension
869 for _, ext := range cert.Extensions {
870 if ext.Id.Equal(oidExtensionSubjectAltName) {
871 certSAN = &ext
872 break
873 }
874 }
875 if candidateSAN == nil && certSAN == nil {
876 return true
877 } else if candidateSAN == nil || certSAN == nil {
878 return false
879 }
880 if bytes.Equal(candidateSAN.Value, certSAN.Value) {
881 return true
882 }
883 }
884 return false
885 }
886
887
888
889
890
891 const maxChainSignatureChecks = 100
892
893 func (c *Certificate) buildChains(currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) {
894 var (
895 hintErr error
896 hintCert *Certificate
897 )
898
899 considerCandidate := func(certType int, candidate *Certificate) {
900 if alreadyInChain(candidate, currentChain) {
901 return
902 }
903
904 if sigChecks == nil {
905 sigChecks = new(int)
906 }
907 *sigChecks++
908 if *sigChecks > maxChainSignatureChecks {
909 err = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
910 return
911 }
912
913 if err := c.CheckSignatureFrom(candidate); err != nil {
914 if hintErr == nil {
915 hintErr = err
916 hintCert = candidate
917 }
918 return
919 }
920
921 err = candidate.isValid(certType, currentChain, opts)
922 if err != nil {
923 return
924 }
925
926 switch certType {
927 case rootCertificate:
928 chains = append(chains, appendToFreshChain(currentChain, candidate))
929 case intermediateCertificate:
930 var childChains [][]*Certificate
931 childChains, err = candidate.buildChains(appendToFreshChain(currentChain, candidate), sigChecks, opts)
932 chains = append(chains, childChains...)
933 }
934 }
935
936 for _, root := range opts.Roots.findPotentialParents(c) {
937 considerCandidate(rootCertificate, root)
938 }
939 for _, intermediate := range opts.Intermediates.findPotentialParents(c) {
940 considerCandidate(intermediateCertificate, intermediate)
941 }
942
943 if len(chains) > 0 {
944 err = nil
945 }
946 if len(chains) == 0 && err == nil {
947 err = UnknownAuthorityError{c, hintErr, hintCert}
948 }
949
950 return
951 }
952
953 func validHostnamePattern(host string) bool { return validHostname(host, true) }
954 func validHostnameInput(host string) bool { return validHostname(host, false) }
955
956
957
958
959 func validHostname(host string, isPattern bool) bool {
960 if !isPattern {
961 host = strings.TrimSuffix(host, ".")
962 }
963 if len(host) == 0 {
964 return false
965 }
966
967 for i, part := range strings.Split(host, ".") {
968 if part == "" {
969
970 return false
971 }
972 if isPattern && i == 0 && part == "*" {
973
974
975
976 continue
977 }
978 for j, c := range part {
979 if 'a' <= c && c <= 'z' {
980 continue
981 }
982 if '0' <= c && c <= '9' {
983 continue
984 }
985 if 'A' <= c && c <= 'Z' {
986 continue
987 }
988 if c == '-' && j != 0 {
989 continue
990 }
991 if c == '_' {
992
993
994 continue
995 }
996 return false
997 }
998 }
999
1000 return true
1001 }
1002
1003 func matchExactly(hostA, hostB string) bool {
1004 if hostA == "" || hostA == "." || hostB == "" || hostB == "." {
1005 return false
1006 }
1007 return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB)
1008 }
1009
1010 func matchHostnames(pattern, host string) bool {
1011 pattern = toLowerCaseASCII(pattern)
1012 host = toLowerCaseASCII(strings.TrimSuffix(host, "."))
1013
1014 if len(pattern) == 0 || len(host) == 0 {
1015 return false
1016 }
1017
1018 patternParts := strings.Split(pattern, ".")
1019 hostParts := strings.Split(host, ".")
1020
1021 if len(patternParts) != len(hostParts) {
1022 return false
1023 }
1024
1025 for i, patternPart := range patternParts {
1026 if i == 0 && patternPart == "*" {
1027 continue
1028 }
1029 if patternPart != hostParts[i] {
1030 return false
1031 }
1032 }
1033
1034 return true
1035 }
1036
1037
1038
1039
1040 func toLowerCaseASCII(in string) string {
1041
1042 isAlreadyLowerCase := true
1043 for _, c := range in {
1044 if c == utf8.RuneError {
1045
1046
1047 isAlreadyLowerCase = false
1048 break
1049 }
1050 if 'A' <= c && c <= 'Z' {
1051 isAlreadyLowerCase = false
1052 break
1053 }
1054 }
1055
1056 if isAlreadyLowerCase {
1057 return in
1058 }
1059
1060 out := []byte(in)
1061 for i, c := range out {
1062 if 'A' <= c && c <= 'Z' {
1063 out[i] += 'a' - 'A'
1064 }
1065 }
1066 return string(out)
1067 }
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078 func (c *Certificate) VerifyHostname(h string) error {
1079
1080 candidateIP := h
1081 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
1082 candidateIP = h[1 : len(h)-1]
1083 }
1084 if ip := net.ParseIP(candidateIP); ip != nil {
1085
1086
1087 for _, candidate := range c.IPAddresses {
1088 if ip.Equal(candidate) {
1089 return nil
1090 }
1091 }
1092 return HostnameError{c, candidateIP}
1093 }
1094
1095 candidateName := toLowerCaseASCII(h)
1096 validCandidateName := validHostnameInput(candidateName)
1097
1098 for _, match := range c.DNSNames {
1099
1100
1101
1102
1103
1104 if validCandidateName && validHostnamePattern(match) {
1105 if matchHostnames(match, candidateName) {
1106 return nil
1107 }
1108 } else {
1109 if matchExactly(match, candidateName) {
1110 return nil
1111 }
1112 }
1113 }
1114
1115 return HostnameError{c, h}
1116 }
1117
1118 func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
1119 usages := make([]ExtKeyUsage, len(keyUsages))
1120 copy(usages, keyUsages)
1121
1122 if len(chain) == 0 {
1123 return false
1124 }
1125
1126 usagesRemaining := len(usages)
1127
1128
1129
1130
1131
1132 NextCert:
1133 for i := len(chain) - 1; i >= 0; i-- {
1134 cert := chain[i]
1135 if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
1136
1137 continue
1138 }
1139
1140 for _, usage := range cert.ExtKeyUsage {
1141 if usage == ExtKeyUsageAny {
1142
1143 continue NextCert
1144 }
1145 }
1146
1147 const invalidUsage ExtKeyUsage = -1
1148
1149 NextRequestedUsage:
1150 for i, requestedUsage := range usages {
1151 if requestedUsage == invalidUsage {
1152 continue
1153 }
1154
1155 for _, usage := range cert.ExtKeyUsage {
1156 if requestedUsage == usage {
1157 continue NextRequestedUsage
1158 }
1159 }
1160
1161 usages[i] = invalidUsage
1162 usagesRemaining--
1163 if usagesRemaining == 0 {
1164 return false
1165 }
1166 }
1167 }
1168
1169 return true
1170 }
1171
View as plain text