Reject all CSRs with an IP in the CN (#8282)
Although https://github.com/letsencrypt/boulder/pull/8231 fixed csr.CNFromCSR to ignore Common Names that are valid IPs, that didn't fully solve our issue: identifier.FromCSR still extracts the CN and assumes that it is a dnsName, leading to a mismatch between the CSR's identifiers and the Order's identifiers. Instead, let's outright reject all CSRs which carry an IP in their Subject Common Name. Although this doesn't have the elegance of rejecting such CNs on a profile-by-profile basis, it matches our ongoing effort to do away with CNs entirely.
This commit is contained in:
parent
5493682a19
commit
a1a7a7f7e6
13
csr/csr.go
13
csr/csr.go
|
@ -37,6 +37,7 @@ var (
|
|||
invalidEmailPresent = berrors.BadCSRError("CSR contains one or more email address fields")
|
||||
invalidURIPresent = berrors.BadCSRError("CSR contains one or more URI fields")
|
||||
invalidNoIdent = berrors.BadCSRError("at least one identifier is required")
|
||||
invalidIPCN = berrors.BadCSRError("CSR contains IP address in Common Name")
|
||||
)
|
||||
|
||||
// VerifyCSR checks the validity of a x509.CertificateRequest. It uses
|
||||
|
@ -69,6 +70,16 @@ func VerifyCSR(ctx context.Context, csr *x509.CertificateRequest, maxNames int,
|
|||
return invalidURIPresent
|
||||
}
|
||||
|
||||
// Reject all CSRs which have an IP address in the CN. We want to get rid of
|
||||
// CNs entirely anyway, and IP addresses are a new feature, so don't let
|
||||
// clients get in the habit of including them in the CN. We don't use
|
||||
// CNFromCSR here because that also filters out IP address CNs, for defense
|
||||
// in depth.
|
||||
_, err = netip.ParseAddr(csr.Subject.CommonName)
|
||||
if err == nil { // Inverted! Successful parsing is a bad thing in this case.
|
||||
return invalidIPCN
|
||||
}
|
||||
|
||||
// FromCSR also performs normalization, returning values that may not match
|
||||
// the literal CSR contents.
|
||||
idents := identifier.FromCSR(csr)
|
||||
|
@ -98,7 +109,7 @@ func CNFromCSR(csr *x509.CertificateRequest) string {
|
|||
|
||||
if csr.Subject.CommonName != "" {
|
||||
_, err := netip.ParseAddr(csr.Subject.CommonName)
|
||||
if err == nil { // inverted; we're looking for successful parsing here
|
||||
if err == nil { // Inverted! Successful parsing is a bad thing in this case.
|
||||
return ""
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,9 @@ func TestVerifyCSR(t *testing.T) {
|
|||
signedReqWithIPAddress := new(x509.CertificateRequest)
|
||||
*signedReqWithIPAddress = *signedReq
|
||||
signedReqWithIPAddress.IPAddresses = []net.IP{net.IPv4(1, 2, 3, 4)}
|
||||
signedReqWithIPCN := new(x509.CertificateRequest)
|
||||
*signedReqWithIPCN = *signedReq
|
||||
signedReqWithIPCN.Subject.CommonName = "1.2.3.4"
|
||||
signedReqWithURI := new(x509.CertificateRequest)
|
||||
*signedReqWithURI = *signedReq
|
||||
testURI, _ := url.ParseRequestURI("https://example.com/")
|
||||
|
@ -141,6 +144,12 @@ func TestVerifyCSR(t *testing.T) {
|
|||
&mockPA{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
signedReqWithIPCN,
|
||||
100,
|
||||
&mockPA{},
|
||||
invalidIPCN,
|
||||
},
|
||||
{
|
||||
signedReqWithURI,
|
||||
100,
|
||||
|
|
Loading…
Reference in New Issue