Skip to content

Commit d4ded26

Browse files
committed
Merge branch 'ky/x509name-add-entry-options'
* ky/x509name-add-entry-options: x509name: add 'loc' and 'set' kwargs to OpenSSL::X509::Name#add_entry
2 parents f745503 + 47bc35c commit d4ded26

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

ext/openssl/ossl_x509name.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other)
198198

199199
/*
200200
* call-seq:
201-
* name.add_entry(oid, value [, type]) => self
201+
* name.add_entry(oid, value [, type], loc: -1, set: 0) => self
202202
*
203203
* Adds a new entry with the given _oid_ and _value_ to this name. The _oid_
204204
* is an object identifier defined in ASN.1. Some common OIDs are:
@@ -209,24 +209,39 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other)
209209
* O:: Organization Name
210210
* OU:: Organizational Unit Name
211211
* ST:: State or Province Name
212+
*
213+
* The optional keyword parameters _loc_ and _set_ specify where to insert the
214+
* new attribute. Refer to the manpage of X509_NAME_add_entry(3) for details.
215+
* _loc_ defaults to -1 and _set_ defaults to 0. This appends a single-valued
216+
* RDN to the end.
212217
*/
213218
static
214219
VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
215220
{
216221
X509_NAME *name;
217-
VALUE oid, value, type;
222+
VALUE oid, value, type, opts, kwargs[2];
223+
static ID kwargs_ids[2];
218224
const char *oid_name;
225+
int loc = -1, set = 0;
219226

220-
rb_scan_args(argc, argv, "21", &oid, &value, &type);
227+
if (!kwargs_ids[0]) {
228+
kwargs_ids[0] = rb_intern_const("loc");
229+
kwargs_ids[1] = rb_intern_const("set");
230+
}
231+
rb_scan_args(argc, argv, "21:", &oid, &value, &type, &opts);
232+
rb_get_kwargs(opts, kwargs_ids, 0, 2, kwargs);
221233
oid_name = StringValueCStr(oid);
222234
StringValue(value);
223235
if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
236+
if (kwargs[0] != Qundef)
237+
loc = NUM2INT(kwargs[0]);
238+
if (kwargs[1] != Qundef)
239+
set = NUM2INT(kwargs[1]);
224240
GetX509Name(self, name);
225241
if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type),
226-
(const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) {
227-
ossl_raise(eX509NameError, NULL);
228-
}
229-
242+
(unsigned char *)RSTRING_PTR(value),
243+
RSTRING_LENINT(value), loc, set))
244+
ossl_raise(eX509NameError, "X509_NAME_add_entry_by_txt");
230245
return self;
231246
}
232247

test/test_x509name.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,40 @@ def test_add_entry_street
320320
assert_equal("Namiki", ary[5][1])
321321
end
322322

323+
def test_add_entry_placing
324+
der = %w{ 30 2A
325+
31 12
326+
30 10 06 03 55 04 0A 0C 09 72 75 62 79 2D 6C 61 6E 67
327+
31 14
328+
30 08 06 03 55 04 0B 0C 01 61
329+
30 08 06 03 55 04 0B 0C 01 62 }
330+
orig = OpenSSL::X509::Name.new([der.join].pack("H*"))
331+
assert_equal("OU=b+OU=a,O=ruby-lang", orig.to_s(OpenSSL::X509::Name::RFC2253))
332+
# Skip for now; they do not work
333+
#
334+
# dn = orig.dup
335+
# dn.add_entry("CN", "unya", loc: 0, set: 0)
336+
# assert_equal("OU=b+OU=a,O=ruby-lang,CN=unya", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
337+
# dn = orig.dup
338+
# dn.add_entry("CN", "unya", loc: 0, set: 1)
339+
# assert_equal("OU=b+OU=a,O=ruby-lang+CN=unya", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
340+
dn = orig.dup
341+
dn.add_entry("CN", "unya", loc: 1, set: -1)
342+
assert_equal("OU=b+OU=a,O=ruby-lang+CN=unya", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
343+
# dn = orig.dup
344+
# dn.add_entry("CN", "unya", loc: 1, set: 0)
345+
# assert_equal("OU=b+OU=a,CN=unya,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
346+
dn = orig.dup
347+
dn.add_entry("CN", "unya", loc: 1, set: 1)
348+
assert_equal("CN=unya+OU=b+OU=a,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
349+
dn = orig.dup
350+
dn.add_entry("CN", "unya", loc: -1, set: -1)
351+
assert_equal("CN=unya+OU=b+OU=a,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
352+
dn = orig.dup
353+
dn.add_entry("CN", "unya", loc: -1, set: 0)
354+
assert_equal("CN=unya,OU=b+OU=a,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
355+
end
356+
323357
def test_equals2
324358
n1 = OpenSSL::X509::Name.parse 'CN=a'
325359
n2 = OpenSSL::X509::Name.parse 'CN=a'

0 commit comments

Comments
 (0)