Merge pull request #1014 from smallstep/max/dns-id

Check for DNS name validity
pull/1024/head
Max 2 years ago committed by GitHub
commit 8f88740a5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,6 +13,7 @@ import (
"github.com/go-chi/chi" "github.com/go-chi/chi"
"go.step.sm/crypto/randutil" "go.step.sm/crypto/randutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/acme" "github.com/smallstep/certificates/acme"
"github.com/smallstep/certificates/api/render" "github.com/smallstep/certificates/api/render"
@ -33,12 +34,20 @@ func (n *NewOrderRequest) Validate() error {
return acme.NewError(acme.ErrorMalformedType, "identifiers list cannot be empty") return acme.NewError(acme.ErrorMalformedType, "identifiers list cannot be empty")
} }
for _, id := range n.Identifiers { for _, id := range n.Identifiers {
if !(id.Type == acme.DNS || id.Type == acme.IP) { switch id.Type {
case acme.IP:
if net.ParseIP(id.Value) == nil {
return acme.NewError(acme.ErrorMalformedType, "invalid IP address: %s", id.Value)
}
case acme.DNS:
value, _ := trimIfWildcard(id.Value)
if _, err := x509util.SanitizeName(value); err != nil {
return acme.NewError(acme.ErrorMalformedType, "invalid DNS name: %s", id.Value)
}
default:
return acme.NewError(acme.ErrorMalformedType, "identifier type unsupported: %s", id.Type) return acme.NewError(acme.ErrorMalformedType, "identifier type unsupported: %s", id.Type)
} }
if id.Type == acme.IP && net.ParseIP(id.Value) == nil {
return acme.NewError(acme.ErrorMalformedType, "invalid IP address: %s", id.Value)
}
// TODO(hs): add some validations for DNS domains? // TODO(hs): add some validations for DNS domains?
// TODO(hs): combine the errors from this with allow/deny policy, like example error in https://datatracker.ietf.org/doc/html/rfc8555#section-6.7.1 // TODO(hs): combine the errors from this with allow/deny policy, like example error in https://datatracker.ietf.org/doc/html/rfc8555#section-6.7.1
} }
@ -218,13 +227,19 @@ func newACMEPolicyEngine(eak *acme.ExternalAccountKey) (policy.X509Policy, error
return policy.NewX509PolicyEngine(eak.Policy) return policy.NewX509PolicyEngine(eak.Policy)
} }
func trimIfWildcard(value string) (string, bool) {
if strings.HasPrefix(value, "*.") {
return strings.TrimPrefix(value, "*."), true
}
return value, false
}
func newAuthorization(ctx context.Context, az *acme.Authorization) error { func newAuthorization(ctx context.Context, az *acme.Authorization) error {
if strings.HasPrefix(az.Identifier.Value, "*.") { value, isWildcard := trimIfWildcard(az.Identifier.Value)
az.Wildcard = true az.Wildcard = isWildcard
az.Identifier = acme.Identifier{ az.Identifier = acme.Identifier{
Value: strings.TrimPrefix(az.Identifier.Value, "*."), Value: value,
Type: az.Identifier.Type, Type: az.Identifier.Type,
}
} }
chTypes := challengeTypes(az) chTypes := challengeTypes(az)

@ -49,6 +49,36 @@ func TestNewOrderRequest_Validate(t *testing.T) {
err: acme.NewError(acme.ErrorMalformedType, "identifier type unsupported: foo"), err: acme.NewError(acme.ErrorMalformedType, "identifier type unsupported: foo"),
} }
}, },
"fail/bad-identifier/bad-dns": func(t *testing.T) test {
return test{
nor: &NewOrderRequest{
Identifiers: []acme.Identifier{
{Type: "dns", Value: "xn--bücher.example.com"},
},
},
err: acme.NewError(acme.ErrorMalformedType, "invalid DNS name: xn--bücher.example.com"),
}
},
"fail/bad-identifier/dns-port": func(t *testing.T) test {
return test{
nor: &NewOrderRequest{
Identifiers: []acme.Identifier{
{Type: "dns", Value: "example.com:8080"},
},
},
err: acme.NewError(acme.ErrorMalformedType, "invalid DNS name: example.com:8080"),
}
},
"fail/bad-identifier/dns-wildcard-port": func(t *testing.T) test {
return test{
nor: &NewOrderRequest{
Identifiers: []acme.Identifier{
{Type: "dns", Value: "*.example.com:8080"},
},
},
err: acme.NewError(acme.ErrorMalformedType, "invalid DNS name: *.example.com:8080"),
}
},
"fail/bad-ip": func(t *testing.T) test { "fail/bad-ip": func(t *testing.T) test {
nbf := time.Now().UTC().Add(time.Minute) nbf := time.Now().UTC().Add(time.Minute)
naf := time.Now().UTC().Add(5 * time.Minute) naf := time.Now().UTC().Add(5 * time.Minute)
@ -72,7 +102,7 @@ func TestNewOrderRequest_Validate(t *testing.T) {
nor: &NewOrderRequest{ nor: &NewOrderRequest{
Identifiers: []acme.Identifier{ Identifiers: []acme.Identifier{
{Type: "dns", Value: "example.com"}, {Type: "dns", Value: "example.com"},
{Type: "dns", Value: "bar.com"}, {Type: "dns", Value: "*.bar.com"},
}, },
NotAfter: naf, NotAfter: naf,
NotBefore: nbf, NotBefore: nbf,
@ -2097,3 +2127,32 @@ func TestHandler_challengeTypes(t *testing.T) {
}) })
} }
} }
func TestTrimIfWildcard(t *testing.T) {
tests := []struct {
name string
arg string
wantValue string
wantBool bool
}{
{
name: "no trim",
arg: "smallstep.com",
wantValue: "smallstep.com",
wantBool: false,
},
{
name: "trim",
arg: "*.smallstep.com",
wantValue: "smallstep.com",
wantBool: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
v, ok := trimIfWildcard(tt.arg)
assert.Equals(t, v, tt.wantValue)
assert.Equals(t, ok, tt.wantBool)
})
}
}

Loading…
Cancel
Save