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