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