From 75bff055fcf639e7358dc9743828915b8ece5cec Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 20 Sep 2022 14:45:47 -0700 Subject: [PATCH] Add StatusCoder to ConstraintError --- authority/internal/constraints/constraints.go | 46 +++++++++++-------- .../internal/constraints/constraints_test.go | 12 ++--- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/authority/internal/constraints/constraints.go b/authority/internal/constraints/constraints.go index 327379b7..29b5be56 100644 --- a/authority/internal/constraints/constraints.go +++ b/authority/internal/constraints/constraints.go @@ -4,6 +4,7 @@ import ( "crypto/x509" "fmt" "net" + "net/http" "net/url" ) @@ -22,6 +23,11 @@ func (e ConstraintError) Error() string { return e.Detail } +// StatusCode implements an status coder interface. +func (e ConstraintError) StatusCode() int { + return http.StatusForbidden +} + // Engine implements a constraint validator for DNS names, IP addresses, Email // addresses and URIs. type Engine struct { @@ -39,38 +45,38 @@ type Engine struct { // New creates a constraint validation engine that contains the given chain of // certificates. func New(chain ...*x509.Certificate) *Engine { - s := new(Engine) + e := new(Engine) for _, crt := range chain { - s.permittedDNSDomains = append(s.permittedDNSDomains, crt.PermittedDNSDomains...) - s.excludedDNSDomains = append(s.excludedDNSDomains, crt.ExcludedDNSDomains...) - s.permittedIPRanges = append(s.permittedIPRanges, crt.PermittedIPRanges...) - s.excludedIPRanges = append(s.excludedIPRanges, crt.ExcludedIPRanges...) - s.permittedEmailAddresses = append(s.permittedEmailAddresses, crt.PermittedEmailAddresses...) - s.excludedEmailAddresses = append(s.excludedEmailAddresses, crt.ExcludedEmailAddresses...) - s.permittedURIDomains = append(s.permittedURIDomains, crt.PermittedURIDomains...) - s.excludedURIDomains = append(s.excludedURIDomains, crt.ExcludedURIDomains...) + e.permittedDNSDomains = append(e.permittedDNSDomains, crt.PermittedDNSDomains...) + e.excludedDNSDomains = append(e.excludedDNSDomains, crt.ExcludedDNSDomains...) + e.permittedIPRanges = append(e.permittedIPRanges, crt.PermittedIPRanges...) + e.excludedIPRanges = append(e.excludedIPRanges, crt.ExcludedIPRanges...) + e.permittedEmailAddresses = append(e.permittedEmailAddresses, crt.PermittedEmailAddresses...) + e.excludedEmailAddresses = append(e.excludedEmailAddresses, crt.ExcludedEmailAddresses...) + e.permittedURIDomains = append(e.permittedURIDomains, crt.PermittedURIDomains...) + e.excludedURIDomains = append(e.excludedURIDomains, crt.ExcludedURIDomains...) - if !s.hasNameConstraints { + if !e.hasNameConstraints { for _, ext := range crt.Extensions { if ext.Id.Equal(oidExtensionNameConstraints) { - s.hasNameConstraints = true + e.hasNameConstraints = true break } } } } - return s + return e } // Validate checks the given names with the name constraints defined in the // service. -func (s *Engine) Validate(dnsNames []string, ipAddresses []net.IP, emailAddresses []string, uris []*url.URL) error { - if s == nil || !s.hasNameConstraints { +func (e *Engine) Validate(dnsNames []string, ipAddresses []net.IP, emailAddresses []string, uris []*url.URL) error { + if e == nil || !e.hasNameConstraints { return nil } for _, name := range dnsNames { - if err := checkNameConstraints("DNS name", name, name, s.permittedDNSDomains, s.excludedDNSDomains, + if err := checkNameConstraints("DNS name", name, name, e.permittedDNSDomains, e.excludedDNSDomains, func(parsedName, constraint any) (bool, error) { return matchDomainConstraint(parsedName.(string), constraint.(string)) }, @@ -80,7 +86,7 @@ func (s *Engine) Validate(dnsNames []string, ipAddresses []net.IP, emailAddresse } for _, ip := range ipAddresses { - if err := checkNameConstraints("IP address", ip.String(), ip, s.permittedIPRanges, s.excludedIPRanges, + if err := checkNameConstraints("IP address", ip.String(), ip, e.permittedIPRanges, e.excludedIPRanges, func(parsedName, constraint any) (bool, error) { return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet)) }, @@ -94,7 +100,7 @@ func (s *Engine) Validate(dnsNames []string, ipAddresses []net.IP, emailAddresse if !ok { return fmt.Errorf("cannot parse rfc822Name %q", email) } - if err := checkNameConstraints("Email address", email, mailbox, s.permittedEmailAddresses, s.excludedEmailAddresses, + if err := checkNameConstraints("Email address", email, mailbox, e.permittedEmailAddresses, e.excludedEmailAddresses, func(parsedName, constraint any) (bool, error) { return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string)) }, @@ -104,7 +110,7 @@ func (s *Engine) Validate(dnsNames []string, ipAddresses []net.IP, emailAddresse } for _, uri := range uris { - if err := checkNameConstraints("URI", uri.String(), uri, s.permittedURIDomains, s.excludedURIDomains, + if err := checkNameConstraints("URI", uri.String(), uri, e.permittedURIDomains, e.excludedURIDomains, func(parsedName, constraint any) (bool, error) { return matchURIConstraint(parsedName.(*url.URL), constraint.(string)) }, @@ -118,6 +124,6 @@ func (s *Engine) Validate(dnsNames []string, ipAddresses []net.IP, emailAddresse // ValidateCertificate validates the DNS names, IP addresses, Email address and // URIs present in the given certificate. -func (s *Engine) ValidateCertificate(cert *x509.Certificate) error { - return s.Validate(cert.DNSNames, cert.IPAddresses, cert.EmailAddresses, cert.URIs) +func (e *Engine) ValidateCertificate(cert *x509.Certificate) error { + return e.Validate(cert.DNSNames, cert.IPAddresses, cert.EmailAddresses, cert.URIs) } diff --git a/authority/internal/constraints/constraints_test.go b/authority/internal/constraints/constraints_test.go index f4f909bf..dff8d043 100644 --- a/authority/internal/constraints/constraints_test.go +++ b/authority/internal/constraints/constraints_test.go @@ -205,7 +205,7 @@ func Test_service_Validate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := &Engine{ + e := &Engine{ hasNameConstraints: tt.fields.hasNameConstraints, permittedDNSDomains: tt.fields.permittedDNSDomains, excludedDNSDomains: tt.fields.excludedDNSDomains, @@ -216,7 +216,7 @@ func Test_service_Validate(t *testing.T) { permittedURIDomains: tt.fields.permittedURIDomains, excludedURIDomains: tt.fields.excludedURIDomains, } - if err := s.Validate(tt.args.dnsNames, tt.args.ipAddresses, tt.args.emailAddresses, tt.args.uris); (err != nil) != tt.wantErr { + if err := e.Validate(tt.args.dnsNames, tt.args.ipAddresses, tt.args.emailAddresses, tt.args.uris); (err != nil) != tt.wantErr { t.Errorf("service.Validate() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -224,8 +224,8 @@ func Test_service_Validate(t *testing.T) { } func Test_service_Validate_nil(t *testing.T) { - var s *Engine - if err := s.Validate([]string{"www.example.com"}, nil, nil, nil); err != nil { + var e *Engine + if err := e.Validate([]string{"www.example.com"}, nil, nil, nil); err != nil { t.Errorf("service.Validate() error = %v, wantErr false", err) } } @@ -284,7 +284,7 @@ func TestEngine_ValidateCertificate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := &Engine{ + e := &Engine{ hasNameConstraints: tt.fields.hasNameConstraints, permittedDNSDomains: tt.fields.permittedDNSDomains, excludedDNSDomains: tt.fields.excludedDNSDomains, @@ -295,7 +295,7 @@ func TestEngine_ValidateCertificate(t *testing.T) { permittedURIDomains: tt.fields.permittedURIDomains, excludedURIDomains: tt.fields.excludedURIDomains, } - if err := s.ValidateCertificate(tt.args.cert); (err != nil) != tt.wantErr { + if err := e.ValidateCertificate(tt.args.cert); (err != nil) != tt.wantErr { t.Errorf("Engine.ValidateCertificate() error = %v, wantErr %v", err, tt.wantErr) } })