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