aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2017-09-03 18:59:33 +0900
committerGitHub <noreply@github.com>2017-09-03 18:59:33 +0900
commita91c6b054288aabeea441f57117f83c70b50abde (patch)
treed70bc4f625b415fb32cb39b070d53df09074abe3
parente96d9c02c4d4788083360fa49d3afcba9ffef289 (diff)
parent3b6cdf121cf541c39df217b1e9068cabf537e475 (diff)
downloadruby-openssl-a91c6b054288aabeea441f57117f83c70b50abde.tar.gz
Merge pull request #143 from rhenium/ky/x509name-to-utf-8
Add X509::Name#to_utf8 and #inspect
-rw-r--r--ext/openssl/ossl_x509name.c61
-rw-r--r--test/test_x509name.rb39
2 files changed, 83 insertions, 17 deletions
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index ccb2541f..b2063954 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -260,6 +260,23 @@ ossl_x509name_to_s_old(VALUE self)
return str;
}
+static VALUE
+x509name_print(VALUE self, unsigned long iflag)
+{
+ X509_NAME *name;
+ BIO *out;
+
+ GetX509Name(self, name);
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ ossl_raise(eX509NameError, NULL);
+ if (!X509_NAME_print_ex(out, name, 0, iflag)) {
+ BIO_free(out);
+ ossl_raise(eX509NameError, "X509_NAME_print_ex");
+ }
+ return ossl_membio2str(out);
+}
+
/*
* call-seq:
* name.to_s -> string
@@ -279,27 +296,37 @@ ossl_x509name_to_s_old(VALUE self)
static VALUE
ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
{
- X509_NAME *name;
- VALUE flag, str;
- BIO *out;
- unsigned long iflag;
-
- rb_scan_args(argc, argv, "01", &flag);
- if (NIL_P(flag))
+ rb_check_arity(argc, 0, 1);
+ /* name.to_s(nil) was allowed */
+ if (!argc || NIL_P(argv[0]))
return ossl_x509name_to_s_old(self);
- else iflag = NUM2ULONG(flag);
- if (!(out = BIO_new(BIO_s_mem())))
- ossl_raise(eX509NameError, NULL);
- GetX509Name(self, name);
- if (!X509_NAME_print_ex(out, name, 0, iflag)){
- BIO_free(out);
- ossl_raise(eX509NameError, NULL);
- }
- str = ossl_membio2str(out);
+ else
+ return x509name_print(self, NUM2ULONG(argv[0]));
+}
+/*
+ * call-seq;
+ * name.to_utf8 -> string
+ *
+ * Returns an UTF-8 representation of the distinguished name, as specified
+ * in {RFC 2253}[https://www.ietf.org/rfc/rfc2253.txt].
+ */
+static VALUE
+ossl_x509name_to_utf8(VALUE self)
+{
+ VALUE str = x509name_print(self, XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
+ rb_enc_associate_index(str, rb_utf8_encindex());
return str;
}
+/* :nodoc: */
+static VALUE
+ossl_x509name_inspect(VALUE self)
+{
+ return rb_enc_sprintf(rb_utf8_encoding(), "#<%"PRIsVALUE" %"PRIsVALUE">",
+ rb_obj_class(self), ossl_x509name_to_utf8(self));
+}
+
/*
* call-seq:
* name.to_a => [[name, data, type], ...]
@@ -494,6 +521,8 @@ Init_ossl_x509name(void)
rb_define_method(cX509Name, "initialize_copy", ossl_x509name_initialize_copy, 1);
rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1);
rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1);
+ rb_define_method(cX509Name, "to_utf8", ossl_x509name_to_utf8, 0);
+ rb_define_method(cX509Name, "inspect", ossl_x509name_inspect, 0);
rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0);
rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1);
rb_define_alias(cX509Name, "<=>", "cmp");
diff --git a/test/test_x509name.rb b/test/test_x509name.rb
index 2f77f20b..ce370415 100644
--- a/test/test_x509name.rb
+++ b/test/test_x509name.rb
@@ -1,4 +1,4 @@
-# coding: US-ASCII
+# coding: ASCII-8BIT
# frozen_string_literal: false
require_relative 'utils'
@@ -356,6 +356,43 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
assert_equal("CN=unya,OU=b+OU=a,O=ruby-lang", dn.dup.to_s(OpenSSL::X509::Name::RFC2253))
end
+ def test_to_s
+ dn = [
+ ["DC", "org"],
+ ["DC", "ruby-lang"],
+ ["CN", "フー, バー"],
+ ]
+ name = OpenSSL::X509::Name.new
+ dn.each { |x| name.add_entry(*x) }
+
+ assert_equal "/DC=org/DC=ruby-lang/" \
+ "CN=\\xE3\\x83\\x95\\xE3\\x83\\xBC, \\xE3\\x83\\x90\\xE3\\x83\\xBC",
+ name.to_s
+ # OpenSSL escapes characters with MSB by default
+ assert_equal \
+ "CN=\\E3\\83\\95\\E3\\83\\BC\\, \\E3\\83\\90\\E3\\83\\BC," \
+ "DC=ruby-lang,DC=org",
+ name.to_s(OpenSSL::X509::Name::RFC2253)
+ assert_equal "DC = org, DC = ruby-lang, " \
+ "CN = \"\\E3\\83\\95\\E3\\83\\BC, \\E3\\83\\90\\E3\\83\\BC\"",
+ name.to_s(OpenSSL::X509::Name::ONELINE)
+ end
+
+ def test_to_utf8
+ dn = [
+ ["DC", "org"],
+ ["DC", "ruby-lang"],
+ ["CN", "フー, バー"],
+ ]
+ name = OpenSSL::X509::Name.new
+ dn.each { |x| name.add_entry(*x) }
+
+ str = name.to_utf8
+ expected = "CN=フー\\, バー,DC=ruby-lang,DC=org".force_encoding("UTF-8")
+ assert_equal expected, str
+ assert_equal Encoding.find("UTF-8"), str.encoding
+ end
+
def test_equals2
n1 = OpenSSL::X509::Name.parse 'CN=a'
n2 = OpenSSL::X509::Name.parse 'CN=a'