+113
-15
lines changedFilter options
+113
-15
lines changed Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package gencert
3
3
import (
4
4
"io/ioutil"
5
5
"os"
6
+
"strings"
6
7
"testing"
7
8
8
9
"github.com/cloudflare/cfssl/cli"
@@ -215,3 +216,17 @@ func TestBadGencertMain(t *testing.T) {
215
216
}
216
217
217
218
}
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
+
}
Original file line number Diff line number Diff 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
+
}
Original file line number Diff line number Diff line change
@@ -13,7 +13,10 @@
13
13
"L": "San Francisco",
14
14
"O": "CloudFlare",
15
15
"OU": "Systems Engineering",
16
-
"ST": "California"
16
+
"ST": "California",
17
+
"OID": {
18
+
"1.2.3.4.5": "abc"
19
+
}
17
20
}
18
21
]
19
-
}
22
+
}
Original file line number Diff line number Diff line change
@@ -12,9 +12,11 @@ import (
12
12
"encoding/asn1"
13
13
"encoding/pem"
14
14
"errors"
15
+
"fmt"
15
16
"net"
16
17
"net/mail"
17
18
"net/url"
19
+
"strconv"
18
20
"strings"
19
21
20
22
cferr "github.com/cloudflare/cfssl/errors"
@@ -30,12 +32,13 @@ const (
30
32
31
33
// A Name contains the SubjectInfo fields.
32
34
type Name struct {
33
-
C string `json:"C,omitempty" yaml:"C,omitempty"` // Country
34
-
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"`
39
42
}
40
43
41
44
// A KeyRequest contains the algorithm and key size for a new private key.
@@ -157,8 +160,25 @@ func appendIf(s string, a *[]string) {
157
160
}
158
161
}
159
162
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
+
160
180
// Name returns the PKIX name for the request.
161
-
func (cr *CertificateRequest) Name() pkix.Name {
181
+
func (cr *CertificateRequest) Name() (pkix.Name, error) {
162
182
var name pkix.Name
163
183
name.CommonName = cr.CN
164
184
@@ -168,9 +188,16 @@ func (cr *CertificateRequest) Name() pkix.Name {
168
188
appendIf(n.L, &name.Locality)
169
189
appendIf(n.O, &name.Organization)
170
190
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
+
}
171
198
}
172
199
name.SerialNumber = cr.SerialNumber
173
-
return name
200
+
return name, nil
174
201
}
175
202
176
203
// BasicConstraints CSR information RFC 5280, 4.2.1.9
@@ -367,8 +394,13 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
367
394
return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
368
395
}
369
396
397
+
subj, err := req.Name()
398
+
if err != nil {
399
+
return nil, err
400
+
}
401
+
370
402
var tpl = x509.CertificateRequest{
371
-
Subject: req.Name(),
403
+
Subject: subj,
372
404
SignatureAlgorithm: sigAlgo,
373
405
}
374
406
Original file line number Diff line number Diff line change
@@ -72,7 +72,10 @@ func TestPKIXName(t *testing.T) {
72
72
KeyRequest: NewKeyRequest(),
73
73
}
74
74
75
-
name := cr.Name()
75
+
name, err := cr.Name()
76
+
if err != nil {
77
+
t.Fatalf("Error getting name: %s", err.Error())
78
+
}
76
79
if len(name.Country) != 2 {
77
80
t.Fatal("Expected two countries in SubjInfo.")
78
81
} else if len(name.Province) != 2 {
@@ -113,7 +116,7 @@ func TestParseRequest(t *testing.T) {
113
116
KeyRequest: NewKeyRequest(),
114
117
Extensions: []pkix.Extension{
115
118
pkix.Extension{
116
-
Id: asn1.ObjectIdentifier{1, 2, 3, 4, 5},
119
+
Id: asn1.ObjectIdentifier{1, 2, 3, 4, 5},
117
120
Value: []byte("AgEB"),
118
121
},
119
122
},
@@ -123,7 +126,7 @@ func TestParseRequest(t *testing.T) {
123
126
if err != nil {
124
127
t.Fatalf("%v", err)
125
128
}
126
-
129
+
127
130
block, _ := pem.Decode(csrBytes)
128
131
if block == nil {
129
132
t.Fatalf("%v", err)
Original file line number Diff line number Diff line change
@@ -172,6 +172,10 @@ func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
172
172
}
173
173
}
174
174
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
+
175
179
// ParseCertificateRequest takes an incoming certificate request and
176
180
// builds a certificate template from it.
177
181
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
181
185
return
182
186
}
183
187
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
+
184
207
err = csrv.CheckSignature()
185
208
if err != nil {
186
209
err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
187
210
return
188
211
}
189
212
190
213
template = &x509.Certificate{
191
-
Subject: csrv.Subject,
214
+
Subject: subject,
192
215
PublicKeyAlgorithm: csrv.PublicKeyAlgorithm,
193
216
PublicKey: csrv.PublicKey,
194
217
SignatureAlgorithm: s.SigAlgo(),
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4