From 7a8c41333b21e34a66543371817ee23a58b6cdcb Mon Sep 17 00:00:00 2001 From: Martin Ott Date: Tue, 23 Oct 2012 18:23:41 +0200 Subject: [PATCH] Implemented OpenSSL::PKCS7#type= and OpenSSL::PKCS7#add_data Methods are required to create a PKCS#7 degenerate structure which contains only certificates. This is basically the same that 'openssl crl2pkcs7' [http://www.openssl.org/docs/apps/crl2pkcs7.html] does. --- src/java/org/jruby/ext/openssl/PKCS7.java | 65 ++++++++++++++++-- .../org/jruby/ext/openssl/impl/PKCS7.java | 7 +- test/test_pkcs7.rb | 67 +++++++++++++++++++ 3 files changed, 134 insertions(+), 5 deletions(-) diff --git a/src/java/org/jruby/ext/openssl/PKCS7.java b/src/java/org/jruby/ext/openssl/PKCS7.java index c5dc2b0..af92e6e 100644 --- a/src/java/org/jruby/ext/openssl/PKCS7.java +++ b/src/java/org/jruby/ext/openssl/PKCS7.java @@ -299,8 +299,29 @@ public IRubyObject initialize_copy(IRubyObject obj) { @JRubyMethod(name="type=") public IRubyObject set_type(IRubyObject obj) { - System.err.println("WARNING: unimplemented method called PKCS7#type="); - return getRuntime().getNil(); + int typeId = ASN1Registry.NID_undef; + + String type = obj.convertToString().asJavaString(); + + if ("signed".equals(type)) { + typeId = ASN1Registry.NID_pkcs7_signed; + } else if ("data".equals(type)) { + typeId = ASN1Registry.NID_pkcs7_data; + } else if ("signedAndEnveloped".equals(type)) { + typeId = ASN1Registry.NID_pkcs7_signedAndEnveloped; + } else if ("enveloped".equals(type)) { + typeId = ASN1Registry.NID_pkcs7_enveloped; + } else if ("encrypted".equals(type)) { + typeId = ASN1Registry.NID_pkcs7_encrypted; + } + + try { + p7.setType(typeId); + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(getRuntime(), pkcs7e); + } + + return obj; } @JRubyMethod(name="type") @@ -478,8 +499,44 @@ public IRubyObject crls() { @JRubyMethod(name={"add_data", "data="}) public IRubyObject add_data(IRubyObject obj) { - System.err.println("WARNING: unimplemented method called PKCS7#add_data"); - return getRuntime().getNil(); + if (p7.isSigned()) { + try { + p7.contentNew(ASN1Registry.NID_pkcs7_data); + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(getRuntime(), pkcs7e); + } + } + + BIO in = obj2bio(obj); + BIO out = null; + try { + out = p7.dataInit(null); + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(getRuntime(), pkcs7e); + } + byte[] buf = new byte[4096]; + for(;;) { + try { + int i = in.read(buf, 0, buf.length); + if(i <= 0) { + break; + } + if(out != null) { + out.write(buf, 0, i); + } + } catch(IOException e) { + throw getRuntime().newIOErrorFromException(e); + } + } + + try { + p7.dataFinal(out); + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(getRuntime(), pkcs7e); + } + setData(getRuntime().getNil()); + + return obj; } @JRubyMethod(rest=true) diff --git a/src/java/org/jruby/ext/openssl/impl/PKCS7.java b/src/java/org/jruby/ext/openssl/impl/PKCS7.java index 82132fe..7815ae6 100644 --- a/src/java/org/jruby/ext/openssl/impl/PKCS7.java +++ b/src/java/org/jruby/ext/openssl/impl/PKCS7.java @@ -935,7 +935,12 @@ public BIO dataInit(BIO bio) throws PKCS7Exception { bio.setMemEofReturn(0); } } - out.push(bio); + + if (out != null) { + out.push(bio); + } else { + out = bio; + } bio = null; return out; } diff --git a/test/test_pkcs7.rb b/test/test_pkcs7.rb index 93b62ce..708b992 100644 --- a/test/test_pkcs7.rb +++ b/test/test_pkcs7.rb @@ -53,4 +53,71 @@ def test_load_empty_pkcs7 p7 = OpenSSL::PKCS7.new(EMPTY_PEM) assert_equal(EMPTY_PEM, p7.to_pem) end + + def test_set_type_signed + p7 = OpenSSL::PKCS7.new + p7.type = "signed" + assert_equal(p7.type, :signed) + end + + def test_set_type_data + p7 = OpenSSL::PKCS7.new + p7.type = "data" + assert_equal(p7.type, :data) + end + + def test_set_type_signed_and_enveloped + p7 = OpenSSL::PKCS7.new + p7.type = "signedAndEnveloped" + assert_equal(p7.type, :signedAndEnveloped) + end + + def test_set_type_enveloped + p7 = OpenSSL::PKCS7.new + p7.type = "enveloped" + assert_equal(p7.type, :enveloped) + end + + def test_set_type_encrypted + p7 = OpenSSL::PKCS7.new + p7.type = "encrypted" + assert_equal(p7.type, :encrypted) + end + + def test_degenerate_pkcs7 + ca_cert_pem = <