Skip to content

Commit

Permalink
Merge pull request #42 from smallstep/fix-subject-names
Browse files Browse the repository at this point in the history
Populate ExtraNames from Names
  • Loading branch information
maraino authored May 17, 2022
2 parents a7692cc + 487ffed commit 06971bd
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 27 deletions.
1 change: 0 additions & 1 deletion x509util/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ func newExtensions(extensions []pkix.Extension) []Extension {
ret[i] = newExtension(e)
}
return ret

}

// Set adds the extension to the given X509 certificate.
Expand Down
64 changes: 51 additions & 13 deletions x509util/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ import (
"github.com/pkg/errors"
)

// attributeTypeNames are the subject attributes managed by Go and this package.
// newExtraNames will populate .Insecure.CR.ExtraNames with the attributes not
// present on this map.
var attributeTypeNames = map[string]string{
"2.5.4.6": "C",
"2.5.4.10": "O",
"2.5.4.11": "OU",
"2.5.4.3": "CN",
"2.5.4.5": "SERIALNUMBER",
"2.5.4.7": "L",
"2.5.4.8": "ST",
"2.5.4.9": "STREET",
"2.5.4.17": "POSTALCODE",
}

// oidEmailAddress is the oid of the deprecated emailAddress in the subject.
var oidEmailAddress = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}

// Name is the JSON representation of X.501 type Name, used in the X.509 subject
// and issuer fields.
type Name struct {
Expand All @@ -35,7 +53,7 @@ func newName(n pkix.Name) Name {
PostalCode: n.PostalCode,
SerialNumber: n.SerialNumber,
CommonName: n.CommonName,
ExtraNames: newDistinguisedNames(n.ExtraNames),
ExtraNames: newExtraNames(n.Names),
}
}

Expand Down Expand Up @@ -86,7 +104,7 @@ func (s Subject) Set(c *x509.Certificate) {
PostalCode: s.PostalCode,
SerialNumber: s.SerialNumber,
CommonName: s.CommonName,
ExtraNames: fromDistinguisedNames(s.ExtraNames),
ExtraNames: fromDistinguishedNames(s.ExtraNames),
}
}

Expand Down Expand Up @@ -120,7 +138,7 @@ func (i Issuer) Set(c *x509.Certificate) {
PostalCode: i.PostalCode,
SerialNumber: i.SerialNumber,
CommonName: i.CommonName,
ExtraNames: fromDistinguisedNames(i.ExtraNames),
ExtraNames: fromDistinguishedNames(i.ExtraNames),
}
}

Expand All @@ -131,24 +149,44 @@ type DistinguishedName struct {
Value interface{} `json:"value"`
}

func newDistinguisedNames(atvs []pkix.AttributeTypeAndValue) []DistinguishedName {
// newExtraNames returns a list of DistinguishedName with the attributes not
// present in attributeTypeNames.
func newExtraNames(atvs []pkix.AttributeTypeAndValue) []DistinguishedName {
var extraNames []DistinguishedName
for _, atv := range atvs {
extraNames = append(extraNames, DistinguishedName{
Type: ObjectIdentifier(atv.Type),
Value: atv.Value,
})
if _, ok := attributeTypeNames[atv.Type.String()]; !ok {
extraNames = append(extraNames, DistinguishedName{
Type: ObjectIdentifier(atv.Type),
Value: atv.Value,
})
}
}
return extraNames
}

func fromDistinguisedNames(dns []DistinguishedName) []pkix.AttributeTypeAndValue {
// fromDistinguishedNames converts a list of DistinguishedName to
// []pkix.AttributeTypeAndValue. Note that this method has a special case to
// encode the deprecated emailAddress field (1.2.840.113549.1.9.1).
func fromDistinguishedNames(dns []DistinguishedName) []pkix.AttributeTypeAndValue {
var atvs []pkix.AttributeTypeAndValue
for _, dn := range dns {
atvs = append(atvs, pkix.AttributeTypeAndValue{
Type: asn1.ObjectIdentifier(dn.Type),
Value: dn.Value,
})
typ := asn1.ObjectIdentifier(dn.Type)
v, isString := dn.Value.(string)
if typ.Equal(oidEmailAddress) && isString {
atvs = append(atvs, pkix.AttributeTypeAndValue{
Type: typ,
Value: asn1.RawValue{
Class: asn1.ClassUniversal,
Tag: asn1.TagIA5String,
Bytes: []byte(v),
},
})
} else {
atvs = append(atvs, pkix.AttributeTypeAndValue{
Type: typ,
Value: dn.Value,
})
}
}
return atvs
}
44 changes: 31 additions & 13 deletions x509util/name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,19 @@ func Test_newName(t *testing.T) {
PostalCode: []string{"The postalCode"},
SerialNumber: "The serialNumber",
CommonName: "The commonName",
ExtraNames: []pkix.AttributeTypeAndValue{
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
Names: []pkix.AttributeTypeAndValue{
{Type: asn1.ObjectIdentifier{2, 5, 4, 6}, Value: "The country"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 10}, Value: "The organization"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 11}, Value: "The organizationalUnit 1"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 11}, Value: "The organizationalUnit 2"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 3}, Value: "The commonName"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 5}, Value: "The serialNumber"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 7}, Value: "The locality 1"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 7}, Value: "The locality 2"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 8}, Value: "The province"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 9}, Value: "The streetAddress"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 17}, Value: "The postalCode"},
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
},
}}, Name{
Country: []string{"The country"},
Expand All @@ -41,7 +52,7 @@ func Test_newName(t *testing.T) {
SerialNumber: "The serialNumber",
CommonName: "The commonName",
ExtraNames: []DistinguishedName{
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
},
}},
}
Expand Down Expand Up @@ -127,8 +138,8 @@ func Test_newSubject(t *testing.T) {
PostalCode: []string{"The postalCode"},
SerialNumber: "The serialNumber",
CommonName: "The commonName",
ExtraNames: []pkix.AttributeTypeAndValue{
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
Names: []pkix.AttributeTypeAndValue{
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
},
}}, Subject{
Country: []string{"The country"},
Expand All @@ -141,7 +152,7 @@ func Test_newSubject(t *testing.T) {
SerialNumber: "The serialNumber",
CommonName: "The commonName",
ExtraNames: []DistinguishedName{
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
},
}},
}
Expand Down Expand Up @@ -405,6 +416,7 @@ func TestIssuer_Set(t *testing.T) {
CommonName: "The commonName",
ExtraNames: []DistinguishedName{
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: ObjectIdentifier{1, 2, 3, 4}, Value: "[email protected]"},
},
}, args{&x509.Certificate{}}, &x509.Certificate{
Issuer: pkix.Name{
Expand All @@ -418,7 +430,8 @@ func TestIssuer_Set(t *testing.T) {
SerialNumber: "The serialNumber",
CommonName: "The commonName",
ExtraNames: []pkix.AttributeTypeAndValue{
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
{Type: asn1.ObjectIdentifier{1, 2, 3, 4}, Value: "[email protected]"},
},
},
}},
Expand Down Expand Up @@ -452,7 +465,7 @@ func TestIssuer_Set(t *testing.T) {
}
}

func Test_newDistinguisedNames(t *testing.T) {
func Test_newExtraNames(t *testing.T) {
type args struct {
atvs []pkix.AttributeTypeAndValue
}
Expand All @@ -462,15 +475,18 @@ func Test_newDistinguisedNames(t *testing.T) {
want []DistinguishedName
}{
{"ok", args{[]pkix.AttributeTypeAndValue{
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: asn1.ObjectIdentifier{2, 5, 4, 3}, Value: "The commonName"},
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
{Type: asn1.ObjectIdentifier{1, 2, 3, 4}, Value: "[email protected]"},
}}, []DistinguishedName{
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
{Type: ObjectIdentifier{1, 2, 3, 4}, Value: "[email protected]"},
}},
{"ok nil", args{nil}, nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := newDistinguisedNames(tt.args.atvs); !reflect.DeepEqual(got, tt.want) {
if got := newExtraNames(tt.args.atvs); !reflect.DeepEqual(got, tt.want) {
t.Errorf("newDistinguisedNames() = %v, want %v", got, tt.want)
}
})
Expand All @@ -488,14 +504,16 @@ func Test_fromDistinguisedNames(t *testing.T) {
}{
{"ok", args{[]DistinguishedName{
{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: ObjectIdentifier{1, 2, 3, 4}, Value: "[email protected]"},
}}, []pkix.AttributeTypeAndValue{
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "[email protected]"},
{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: asn1.RawValue{Class: asn1.ClassUniversal, Tag: asn1.TagIA5String, Bytes: []byte("[email protected]")}},
{Type: asn1.ObjectIdentifier{1, 2, 3, 4}, Value: "[email protected]"},
}},
{"ok nil", args{nil}, nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := fromDistinguisedNames(tt.args.dns); !reflect.DeepEqual(got, tt.want) {
if got := fromDistinguishedNames(tt.args.dns); !reflect.DeepEqual(got, tt.want) {
t.Errorf("fromDistinguisedNames() = %v, want %v", got, tt.want)
}
})
Expand Down

0 comments on commit 06971bd

Please sign in to comment.