Skip to content

Commit

Permalink
x509name: add 'loc' and 'set' kwargs to OpenSSL::X509::Name#add_entry
Browse files Browse the repository at this point in the history
Add a way to specify these arguments for X509_NAME_add_entry_by_txt().
We currently always use -1 and 0 respectively, which will result in
appending a new single-valued RDN to the end.

Fixes: #94
  • Loading branch information
rhenium committed Jul 25, 2017
1 parent 576eff6 commit 47bc35c
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 7 deletions.
29 changes: 22 additions & 7 deletions ext/openssl/ossl_x509name.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other)

/*
* call-seq:
* name.add_entry(oid, value [, type]) => self
* name.add_entry(oid, value [, type], loc: -1, set: 0) => self
*
* Adds a new entry with the given _oid_ and _value_ to this name. The _oid_
* is an object identifier defined in ASN.1. Some common OIDs are:
Expand All @@ -209,24 +209,39 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other)
* O:: Organization Name
* OU:: Organizational Unit Name
* ST:: State or Province Name
*
* The optional keyword parameters _loc_ and _set_ specify where to insert the
* new attribute. Refer to the manpage of X509_NAME_add_entry(3) for details.
* _loc_ defaults to -1 and _set_ defaults to 0. This appends a single-valued
* RDN to the end.
*/
static
VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
{
X509_NAME *name;
VALUE oid, value, type;
VALUE oid, value, type, opts, kwargs[2];
static ID kwargs_ids[2];
const char *oid_name;
int loc = -1, set = 0;

rb_scan_args(argc, argv, "21", &oid, &value, &type);
if (!kwargs_ids[0]) {
kwargs_ids[0] = rb_intern_const("loc");
kwargs_ids[1] = rb_intern_const("set");
}
rb_scan_args(argc, argv, "21:", &oid, &value, &type, &opts);
rb_get_kwargs(opts, kwargs_ids, 0, 2, kwargs);
oid_name = StringValueCStr(oid);
StringValue(value);
if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
if (kwargs[0] != Qundef)
loc = NUM2INT(kwargs[0]);
if (kwargs[1] != Qundef)
set = NUM2INT(kwargs[1]);
GetX509Name(self, name);
if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type),
(const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) {
ossl_raise(eX509NameError, NULL);
}

(unsigned char *)RSTRING_PTR(value),
RSTRING_LENINT(value), loc, set))
ossl_raise(eX509NameError, "X509_NAME_add_entry_by_txt");
return self;
}

Expand Down
34 changes: 34 additions & 0 deletions test/test_x509name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,40 @@ def test_add_entry_street
assert_equal("Namiki", ary[5][1])
end

def test_add_entry_placing
der = %w{ 30 2A
31 12
30 10 06 03 55 04 0A 0C 09 72 75 62 79 2D 6C 61 6E 67
31 14
30 08 06 03 55 04 0B 0C 01 61
30 08 06 03 55 04 0B 0C 01 62 }
orig = OpenSSL::X509::Name.new([der.join].pack("H*"))
assert_equal("OU=b+OU=a,O=ruby-lang", orig.to_s(OpenSSL::X509::Name::RFC2253))
# Skip for now; they do not work
#
# dn = orig.dup
# dn.add_entry("CN", "unya", loc: 0, set: 0)
# assert_equal("OU=b+OU=a,O=ruby-lang,CN=unya", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
# dn = orig.dup
# dn.add_entry("CN", "unya", loc: 0, set: 1)
# assert_equal("OU=b+OU=a,O=ruby-lang+CN=unya", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
dn = orig.dup
dn.add_entry("CN", "unya", loc: 1, set: -1)
assert_equal("OU=b+OU=a,O=ruby-lang+CN=unya", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
# dn = orig.dup
# dn.add_entry("CN", "unya", loc: 1, set: 0)
# assert_equal("OU=b+OU=a,CN=unya,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
dn = orig.dup
dn.add_entry("CN", "unya", loc: 1, set: 1)
assert_equal("CN=unya+OU=b+OU=a,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
dn = orig.dup
dn.add_entry("CN", "unya", loc: -1, set: -1)
assert_equal("CN=unya+OU=b+OU=a,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
dn = orig.dup
dn.add_entry("CN", "unya", loc: -1, set: 0)
assert_equal("CN=unya,OU=b+OU=a,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
end

def test_equals2
n1 = OpenSSL::X509::Name.parse 'CN=a'
n2 = OpenSSL::X509::Name.parse 'CN=a'
Expand Down

0 comments on commit 47bc35c

Please sign in to comment.