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