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