diff --git a/src/main/java/org/jruby/ext/openssl/X509Extension.java b/src/main/java/org/jruby/ext/openssl/X509Extension.java index d8f708bf..3c9c3fa2 100644 --- a/src/main/java/org/jruby/ext/openssl/X509Extension.java +++ b/src/main/java/org/jruby/ext/openssl/X509Extension.java @@ -207,7 +207,7 @@ final byte[] getRealValueEncoded() throws IOException { if ( value instanceof byte[] ) return (byte[]) value; if ( value instanceof RubyString ) return ((RubyString) value).getBytes(); if ( value instanceof String ) return ByteList.plain((String) value); - + if ( value instanceof ASN1OctetString ) { // initialize return ((ASN1OctetString) value).getOctets(); } @@ -536,7 +536,7 @@ public RubyString value(final ThreadContext context) { for ( int i = 0; i < names.length; i++ ) { boolean other = formatGeneralName(names[i], val, false); if ( i < names.length - 1 ) { - if ( other ) val.append(';'); else val.append(','); + if ( other ) val.append(';'); else val.append(',').append(' '); } } return runtime.newString( val ); diff --git a/src/main/java/org/jruby/ext/openssl/X509ExtensionFactory.java b/src/main/java/org/jruby/ext/openssl/X509ExtensionFactory.java index 5c5daf7f..cf691704 100644 --- a/src/main/java/org/jruby/ext/openssl/X509ExtensionFactory.java +++ b/src/main/java/org/jruby/ext/openssl/X509ExtensionFactory.java @@ -209,6 +209,7 @@ else if (id.equals("2.5.29.37")) { // extendedKeyUsage } } catch (IOException e) { + OpenSSL.debugStackTrace(e); throw newExtensionError(runtime, "Unable to create extension: " + e.getMessage()); } return newExtension(runtime, objectId, value, critical.isNil() ? null : critical.isTrue()); @@ -518,8 +519,19 @@ private static ASN1Encodable parseSubjectAltName(final String valuex) throws IOE return new GeneralName(GeneralName.registeredID, rid); } if ( valuex.startsWith(email_) ) { - final String mail = valuex.substring(email_.length()); - return new GeneralName(GeneralName.rfc822Name, mail); + final String[] vals = valuex.split(","); + final GeneralName[] names = new GeneralName[vals.length]; + for ( int i = 0; i < vals.length; i++ ) { + if (vals[i].startsWith(email_)) { + String mail = vals[i].substring(email_.length()); + names[i] = new GeneralName(GeneralName.rfc822Name, mail); + } + else { + ASN1Encodable name = parseSubjectAltName(vals[i]); + names[i] = name instanceof GeneralNames ? ((GeneralNames) name).getNames()[0] : (GeneralName) name; + } + } + return new GeneralNames(names); } if ( valuex.startsWith("IP:") || valuex.startsWith("IP Address:") ) { final int idx = valuex.charAt(2) == ':' ? 3 : 11; diff --git a/src/test/ruby/x509/test_x509ext.rb b/src/test/ruby/x509/test_x509ext.rb index afadda84..8b1812af 100644 --- a/src/test/ruby/x509/test_x509ext.rb +++ b/src/test/ruby/x509/test_x509ext.rb @@ -150,6 +150,15 @@ def test_subject_alt_name_sign_to_pem assert dns =~ /test.example.com.*?test2.example.com.*?example.com.*?www.example.com/ end + def test_subject_alt_name_sequence + extensions = OpenSSL::X509::ExtensionFactory.new + ext = extensions.create_extension("subjectAltName", "email:foo@bar.com,DNS:a.b.com,email:baz@bar.com") + assert_equal 'subjectAltName', ext.oid + assert_equal 'email:foo@bar.com, DNS:a.b.com, email:baz@bar.com', ext.value + mri_der = "0,\x06\x03U\x1D\x11\x04%0#\x81\vfoo@bar.com\x82\aa.b.com\x81\vbaz@bar.com" + assert_equal mri_der, ext.to_der + end + def subject_alt_name(domains) ef = OpenSSL::X509::ExtensionFactory.new ef.create_extension("subjectAltName", domains.split(',').map { |d| "DNS: #{d}" }.join(','))