From 88cb52d42d712c6633cfba657b89487e5748c731 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 12 Jun 2017 15:32:32 +0900 Subject: [PATCH 1/3] test/test_x509name: change script encoding to ASCII-8BIT Allow string literals containing UTF-8 characters. (cherry picked from commit 98945c7ce8706309a6d358007f1fdb2a73711662) --- test/test_x509name.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_x509name.rb b/test/test_x509name.rb index c1dacf4fa..f7a60c3a9 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' From 49c9d3f473d9b12583e67971a20639170c0db95f Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 3 Sep 2017 12:27:16 +0900 Subject: [PATCH 2/3] x509name: refactor OpenSSL::X509::Name#to_s Extract the body into a function in preparation for adding #to_utf8. Also a potential memory leak is fixed: the GetX509Name() macro can raise TypeError. (cherry picked from commit 58964733f7d1f9646ecc344d127150aa7115760e) --- ext/openssl/ossl_x509name.c | 40 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c index e3e39e714..16a1b2573 100644 --- a/ext/openssl/ossl_x509name.c +++ b/ext/openssl/ossl_x509name.c @@ -249,6 +249,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 @@ -264,25 +281,12 @@ 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); - - return str; + else + return x509name_print(self, NUM2ULONG(argv[0])); } /* From 7b2fdb8d136c580a7d1849a888516b698a979931 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 8 Aug 2018 18:34:47 +0900 Subject: [PATCH 3/3] x509name: fix handling of X509_NAME_{oneline,print_ex}() return value X509_NAME_print_ex() behaves differently depending on the passed flags. When XN_FLAG_COMPAT is specified, it returns either 1 on success or 0 on error. Otherwise, it returns the byte size written or -1 on error. This means 0 return is not necessarily an error. Also, X509_NAME_oneline() return value needs to be checked as it may fail with a NULL return. Fixes: https://github.com/ruby/openssl/issues/200 --- ext/openssl/ossl_x509name.c | 12 ++++++------ test/test_x509name.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c index 16a1b2573..f064cf65d 100644 --- a/ext/openssl/ossl_x509name.c +++ b/ext/openssl/ossl_x509name.c @@ -239,14 +239,12 @@ ossl_x509name_to_s_old(VALUE self) { X509_NAME *name; char *buf; - VALUE str; GetX509Name(self, name); buf = X509_NAME_oneline(name, NULL, 0); - str = rb_str_new2(buf); - OPENSSL_free(buf); - - return str; + if (!buf) + ossl_raise(eX509NameError, "X509_NAME_oneline"); + return ossl_buf2str(buf, rb_long2int(strlen(buf))); } static VALUE @@ -254,12 +252,14 @@ x509name_print(VALUE self, unsigned long iflag) { X509_NAME *name; BIO *out; + int ret; GetX509Name(self, name); out = BIO_new(BIO_s_mem()); if (!out) ossl_raise(eX509NameError, NULL); - if (!X509_NAME_print_ex(out, name, 0, iflag)) { + ret = X509_NAME_print_ex(out, name, 0, iflag); + if (ret < 0 || iflag == XN_FLAG_COMPAT && ret == 0) { BIO_free(out); ossl_raise(eX509NameError, "X509_NAME_print_ex"); } diff --git a/test/test_x509name.rb b/test/test_x509name.rb index f7a60c3a9..f8fabafea 100644 --- a/test/test_x509name.rb +++ b/test/test_x509name.rb @@ -322,6 +322,34 @@ def test_add_entry_street assert_equal("Namiki", ary[5][1]) 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) + + empty = OpenSSL::X509::Name.new + assert_equal "", empty.to_s + assert_equal "", empty.to_s(OpenSSL::X509::Name::COMPAT) + assert_equal "", empty.to_s(OpenSSL::X509::Name::RFC2253) + assert_equal "", empty.to_s(OpenSSL::X509::Name::ONELINE) + end + def test_equals2 n1 = OpenSSL::X509::Name.parse 'CN=a' n2 = OpenSSL::X509::Name.parse 'CN=a'