Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added support for general OID names in CSRs
  • Loading branch information
Andy Martin committed Jan 29, 2021
1 parent 23b638f commit 38b8240
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 10 deletions.
50 changes: 41 additions & 9 deletions csr/csr.go
Expand Up @@ -12,9 +12,11 @@ import (
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
"net"
"net/mail"
"net/url"
"strconv"
"strings"

cferr "github.com/cloudflare/cfssl/errors"
Expand All @@ -30,12 +32,13 @@ const (

// A Name contains the SubjectInfo fields.
type Name struct {
C string `json:"C,omitempty" yaml:"C,omitempty"` // Country
ST string `json:"ST,omitempty" yaml:"ST,omitempty"` // State
L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
C string `json:"C,omitempty" yaml:"C,omitempty"` // Country
ST string `json:"ST,omitempty" yaml:"ST,omitempty"` // State
L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
OID map[string]string `json:"OID,omitempty", yaml:"OID,omitempty"`
}

// A KeyRequest contains the algorithm and key size for a new private key.
Expand Down Expand Up @@ -157,8 +160,24 @@ func appendIf(s string, a *[]string) {
}
}

func OIDFromString(s string) (asn1.ObjectIdentifier, error) {
var oid []int
parts := strings.Split(s, ".")
if len(parts) < 1 {
return oid, fmt.Errorf("invalid OID string: %s", s)
}
for _, p := range parts {
i, err := strconv.Atoi(p)
if err != nil {
return nil, fmt.Errorf("invalid OID part %s", p)
}
oid = append(oid, i)
}
return oid, nil
}

// Name returns the PKIX name for the request.
func (cr *CertificateRequest) Name() pkix.Name {
func (cr *CertificateRequest) Name() (pkix.Name, error) {
var name pkix.Name
name.CommonName = cr.CN

Expand All @@ -168,9 +187,16 @@ func (cr *CertificateRequest) Name() pkix.Name {
appendIf(n.L, &name.Locality)
appendIf(n.O, &name.Organization)
appendIf(n.OU, &name.OrganizationalUnit)
for k, v := range n.OID {
oid, err := OIDFromString(k)
if err != nil {
return name, err
}
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: oid, Value: v})
}
}
name.SerialNumber = cr.SerialNumber
return name
return name, nil
}

// BasicConstraints CSR information RFC 5280, 4.2.1.9
Expand Down Expand Up @@ -234,6 +260,7 @@ func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
// from an existing certificate. For a root certificate, the CA expiry
// length is calculated as the duration between cert.NotAfter and cert.NotBefore.
func ExtractCertificateRequest(cert *x509.Certificate) *CertificateRequest {
fmt.Printf("ExctractCertificateRequest %+v\n", *cert)
req := New()
req.CN = cert.Subject.CommonName
req.Names = getNames(cert.Subject)
Expand Down Expand Up @@ -367,8 +394,13 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
}

subj, err := req.Name()
if err != nil {
return nil, err
}

var tpl = x509.CertificateRequest{
Subject: req.Name(),
Subject: subj,
SignatureAlgorithm: sigAlgo,
}

Expand Down
25 changes: 24 additions & 1 deletion signer/signer.go
Expand Up @@ -172,6 +172,10 @@ func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
}
}

func isCommonAttr(t []int) bool {
return (len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 && (t[3] == 3 || (t[3] >= 5 && t[3] <= 11) || t[3] == 17))
}

// ParseCertificateRequest takes an incoming certificate request and
// builds a certificate template from it.
func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte) (template *x509.Certificate, err error) {
Expand All @@ -181,14 +185,33 @@ func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte
return
}

var r pkix.RDNSequence
_, err = asn1.Unmarshal(csrv.RawSubject, &r)

if err != nil {
err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
return
}

var subject pkix.Name
subject.FillFromRDNSequence(&r)

for _, v := range r {
for _, vv := range v {
if !isCommonAttr(vv.Type) {
subject.ExtraNames = append(subject.ExtraNames, vv)
}
}
}

err = csrv.CheckSignature()
if err != nil {
err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
return
}

template = &x509.Certificate{
Subject: csrv.Subject,
Subject: subject,
PublicKeyAlgorithm: csrv.PublicKeyAlgorithm,
PublicKey: csrv.PublicKey,
SignatureAlgorithm: s.SigAlgo(),
Expand Down

0 comments on commit 38b8240

Please sign in to comment.