8000 Merge pull request #1163 from akgmartin/master · cloudflare/cfssl@9f7129a · GitHub
[go: up one dir, main page]

Skip to content

Commit 9f7129a

Browse files
authored
Merge pull request #1163 from akgmartin/master
2 parents 57882e0 + 5628e97 commit 9f7129a

File tree

6 files changed

+113
-15
lines changed

6 files changed

+113
-15
lines changed

cli/gencert/gencert_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package gencert
33
import (
44
"io/ioutil"
55
"os"
6+
"strings"
67
"testing"
78

89
"github.com/cloudflare/cfssl/cli"
@@ -215,3 +216,17 @@ func TestBadGencertMain(t *testing.T) {
215216
}
216217

217218
}
219+
220+
func TestOidMain(t *testing.T) {
221+
c := cli.Config{
222+
CAFile: "../testdata/ca.pem",
223+
CAKeyFile: "../testdata/ca-key.pem",
224+
}
225+
err := gencertMain([]string{"../testdata/bad_oid_csr.json"}, c)
226+
if err == nil {
227+
t.Fatal("Expected error")
228+
}
229+
if !strings.Contains(err.Error(), "invalid OID part abc") {
230+
t.Fatalf("Unexpected error: %s", err.Error())
231+
}
232+
}

cli/testdata/bad_oid_csr.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"hosts": [
3+
"cloudflare.com",
4+
"www.cloudflare.com"
5+
],
6+
"key": {
7+
"algo": "rsa",
8+
"size": 2048
9+
},
10+
"names": [
11+
{
12+
"C": "US",
13+
"L": "San Francisco",
14+
"O": "CloudFlare",
15+
"OU": "Systems Engineering",
16+
"ST": "California",
17+
"OID": {
18+
"abc": "abc"
19+
}
20+
}
21+
]
22+
}

cli/testdata/csr.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
"L": "San Francisco",
1414
"O": "CloudFlare",
1515
"OU": "Systems Engineering",
16-
"ST": "California"
16+
"ST": "California",
17+
"OID": {
18+
"1.2.3.4.5": "abc"
19+
}
1720
}
1821
]
19-
}
22+
}

csr/csr.go

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import (
1212
"encoding/asn1"
1313
"encoding/pem"
1414
"errors"
15+
"fmt"
1516
"net"
1617
"net/mail"
1718
"net/url"
19+
"strconv"
1820
"strings"
1921

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

3133
// A Name contains the SubjectInfo fields.
3234
type Name struct {
33-
C string `json:"C,omitempty" yaml:"C,omitempty"` // Country
34-< 9E88 div class="diff-text-inner"> ST string `json:"ST,omitempty" yaml:"ST,omitempty"` // State
35-
L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
36-
O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
37-
OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
38-
SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
35+
C string `json:"C,omitempty" yaml:"C,omitempty"` // Country
36+
ST string `json:"ST,omitempty" yaml:"ST,omitempty"` // State
37+
L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
38+
O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
39+
OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
40+
SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
41+
OID map[string]string `json:"OID,omitempty", yaml:"OID,omitempty"`
3942
}
4043

4144
// A KeyRequest contains the algorithm and key size for a new private key.
@@ -157,8 +160,25 @@ func appendIf(s string, a *[]string) {
157160
}
158161
}
159162

163+
// OIDFromString creates an ASN1 ObjectIdentifier from its string representation
164+
func OIDFromString(s string) (asn1.ObjectIdentifier, error) {
165+
var oid []int
166+
parts := strings.Split(s, ".")
167+
if len(parts) < 1 {
168+
return oid, fmt.Errorf("invalid OID string: %s", s)
169+
}
170+
for _, p := range parts {
171+
i, err := strconv.Atoi(p)
172+
if err != nil {
173+
return nil, fmt.Errorf("invalid OID part %s", p)
174+
}
175+
oid = append(oid, i)
176+
}
177+
return oid, nil
178+
}
179+
160180
// Name returns the PKIX name for the request.
161-
func (cr *CertificateRequest) Name() pkix.Name {
181+
func (cr *CertificateRequest) Name() (pkix.Name, error) {
162182
var name pkix.Name
163183
name.CommonName = cr.CN
164184

@@ -168,9 +188,16 @@ func (cr *CertificateRequest) Name() pkix.Name {
168188
appendIf(n.L, &name.Locality)
169189
appendIf(n.O, &name.Organization)
170190
appendIf(n.OU, &name.OrganizationalUnit)
191+
for k, v := range n.OID {
192+
oid, err := OIDFromString(k)
193+
if err != nil {
194+
return name, err
195+
}
196+
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: oid, Value: v})
197+
}
171198
}
172199
name.SerialNumber = cr.SerialNumber
173-
return name
200+
return name, nil
174201
}
175202

176203
// BasicConstraints CSR information RFC 5280, 4.2.1.9
@@ -367,8 +394,13 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
367394
return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
368395
}
369396

397+
subj, err := req.Name()
398+
if err != nil {
399+
return nil, err
400+
}
401+
370402
var tpl = x509.CertificateRequest{
371-
Subject: req.Name(),
403+
Subject: subj,
372404
SignatureAlgorithm: sigAlgo,
373405
}
374406

csr/csr_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ func TestPKIXName(t *testing.T) {
7272
KeyRequest: NewKeyRequest(),
7373
}
7474

75-
name := cr.Name()
75+
name, err := cr.Name()
76+
if err != nil {
77+
t.Fatalf("Error getting name: %s", err.Error())
78+
}
7679
if len(name.Country) != 2 {
7780
t.Fatal("Expected two countries in SubjInfo.")
7881
} else if len(name.Province) != 2 {
@@ -113,7 +116,7 @@ func TestParseRequest(t *testing.T) {
113116
KeyRequest: NewKeyRequest(),
114117
Extensions: []pkix.Extension{
115118
pkix.Extension{
116-
Id: asn1.ObjectIdentifier{1, 2, 3, 4, 5},
119+
Id: asn1.ObjectIdentifier{1, 2, 3, 4, 5},
117120
Value: []byte("AgEB"),
118121
},
119122
},
@@ -123,7 +126,7 @@ func TestParseRequest(t *testing.T) {
123126
if err != nil {
124127
t.Fatalf("%v", err)
125128
}
126-
129+
127130
block, _ := pem.Decode(csrBytes)
128131
if block == nil {
129132
t.Fatalf("%v", err)

signer/signer.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
172172
}
173173
}
174174

175+
func isCommonAttr(t []int) bool {
176+
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))
177+
}
178+
175179
// ParseCertificateRequest takes an incoming certificate request and
176180
// builds a certificate template from it.
177181
func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte) (template *x509.Certificate, err error) {
@@ -181,14 +185,33 @@ func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte
181185
return
182186
}
183187

188+
var r pkix.RDNSequence
189+
_, err = asn1.Unmarshal(csrv.RawSubject, &r)
190+
191+
if err != nil {
192+
err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
193+
return
194+
}
195+
196+
var subject pkix.Name
197+
subject.FillFromRDNSequence(&r)
198+
199+
for _, v := range r {
200+
for _, vv := range v {
201+
if !isCommonAttr(vv.Type) {
202+
subject.ExtraNames = append(subject.ExtraNames, vv)
203+
}
204+
}
205+
}
206+
184207
err = csrv.CheckSignature()
185208
if err != nil {
186209
err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
187210
return
188211
}
189212

190213
template = &x509.Certificate{
191-
Subject: csrv.Subject,
214+
Subject: subject,
192215
PublicKeyAlgorithm: csrv.PublicKeyAlgorithm,
193216
PublicKey: csrv.PublicKey,
194217
SignatureAlgorithm: s.SigAlgo(),

0 commit comments

Comments
 (0)
0