Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/main/java/org/jruby/ext/openssl/SSLContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -458,10 +458,10 @@ synchronized IRubyObject doSetup(final ThreadContext context) {

value = getInstanceVariable("@alpn_protocols");
if ( value != null && ! value.isNil() ) {
IRubyObject[] alpn_protocols = ((RubyArray) value).toJavaArrayMaybeUnsafe();
String[] protocols = new String[alpn_protocols.length];
final RubyArray alpnProtocolsAry = value.convertToArray();
final String[] protocols = new String[alpnProtocolsAry.size()];
for(int i = 0; i < protocols.length; i++) {
protocols[i] = alpn_protocols[i].convertToString().asJavaString();
protocols[i] = alpnProtocolsAry.eltInternal(i).convertToString().asJavaString();
}
alpnProtocols = protocols;
} else {
Expand Down
43 changes: 25 additions & 18 deletions src/main/java/org/jruby/ext/openssl/X509CRL.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import org.jruby.exceptions.RaiseException;
import org.jruby.ext.openssl.log.Logger;
import org.jruby.ext.openssl.shim.ASN1Shim;
import org.jruby.ext.openssl.util.RubySupport;
import org.jruby.ext.openssl.x509store.PEMInputOutput;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
Expand All @@ -88,7 +89,6 @@
import org.jruby.runtime.builtin.Variable;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.TypeConverter;

import static org.jruby.ext.openssl.OpenSSL.*;
import static org.jruby.ext.openssl.X509._X509;
Expand Down Expand Up @@ -250,7 +250,7 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
final X509CRLEntry[] revokedSorted = revokedCRLs.toArray(new X509CRLEntry[revokedCRLs.size()]);
Arrays.sort(revokedSorted, 0, revokedSorted.length, Comparator.comparing(X509CRLEntry::getRevocationDate));
for (X509CRLEntry entry : revokedSorted) {
revoked().append( X509Revoked.newInstance(context, entry) );
revokedInternal().append( X509Revoked.newInstance(context, entry) );
}
}

Expand Down Expand Up @@ -544,44 +544,56 @@ public IRubyObject set_next_update(final ThreadContext context, IRubyObject val)
}

@JRubyMethod
public RubyArray revoked() {
public RubyArray revoked(ThreadContext context) {
return revoked == null ? context.runtime.newEmptyArray() : RubySupport.copyArray(context.runtime, revoked);
}

private RubyArray revokedInternal() {
return revoked == null ? revoked = getRuntime().newArray(4) : revoked;
}

@JRubyMethod(name="revoked=")
public IRubyObject set_revoked(final IRubyObject revoked) {
if (!(revoked instanceof RubyArray)) throw getRuntime().newTypeError(revoked, getRuntime().getArray());
this.revoked = X509Revoked.copyRevoked(getRuntime(), (RubyArray) revoked);
this.changed = true;
return this.revoked = (RubyArray) revoked;
return revoked;
}

@JRubyMethod
public IRubyObject add_revoked(final ThreadContext context, IRubyObject val) {
final X509Revoked revoked = asRevoked(context.runtime, val);
final X509Revoked revoked = X509Revoked.asRevoked(context.runtime, val);
if (revoked.getTime() == null) throw X509Revoked.newRevokedError(context.runtime, "revocation time not set");
revokedInternal().append(X509Revoked.copy(context.runtime, revoked));
this.changed = true;
revoked().callMethod(context, "<<", val); return val;
return val;
}

@JRubyMethod
public RubyArray extensions() {
return this.extensions;
public RubyArray extensions(ThreadContext context) {
return extensions == null ? context.runtime.newEmptyArray() : RubySupport.copyArray(context.runtime, extensions);
}

private RubyArray extensionsInternal() {
return extensions == null ? extensions = getRuntime().newArray(4) : extensions;
}

@SuppressWarnings("unchecked")
@JRubyMethod(name="extensions=")
public IRubyObject set_extensions(final IRubyObject extensions) {
if (!(extensions instanceof RubyArray)) throw getRuntime().newTypeError(extensions, getRuntime().getArray());
this.extensions = X509Extension.copyExtensions(getRuntime(), (RubyArray) extensions);
this.changed = true;
return this.extensions = (RubyArray) extensions;
return extensions;
}

@JRubyMethod
public IRubyObject add_extension(final IRubyObject extension) {
if (!(extension instanceof X509Extension)) throw getRuntime().newTypeError(
extension, X509Extension._Extension(getRuntime()));
extensionsInternal().append(X509Extension.copy(getRuntime(), (X509Extension) extension));
this.changed = true;
extensions().append(extension); return extension;
return extension;
}

@JRubyMethod
Expand All @@ -598,13 +610,13 @@ public IRubyObject sign(final ThreadContext context, final IRubyObject key, IRub

if ( revoked != null ) {
for ( int i = 0; i < revoked.size(); i++ ) {
final X509Revoked rev = asRevoked(runtime, revoked.eltInternal(i));
final X509Revoked rev = X509Revoked.asRevoked(runtime, revoked.eltInternal(i));
final DateTime revTime = rev.getTime();
if (revTime == null) throw X509Revoked.newRevokedError(runtime, "revocation time not set");

final Extensions revExts;
if ( rev.hasExtensions() ) {
final RubyArray exts = rev.extensions();
final RubyArray exts = rev.extensions(context);
final ASN1Encodable[] array = new ASN1Encodable[ exts.size() ];
for ( int j = 0; j < exts.size(); j++ ) {
final X509Extension ext = (X509Extension) exts.entry(j);
Expand Down Expand Up @@ -754,7 +766,7 @@ private ASN1Sequence toASN1Sequence(final Ruby runtime) {
final ASN1EncodableVector revokedEntries = new ASN1EncodableVector(revoked.size());
try {
for (int i = 0; i < revoked.size(); i++) {
revokedEntries.add(asRevoked(runtime, revoked.eltInternal(i)).toASN1Sequence());
revokedEntries.add(X509Revoked.asRevoked(runtime, revoked.eltInternal(i)).toASN1Sequence());
}
} catch (IOException e) {
throw newCRLError(runtime, e);
Expand Down Expand Up @@ -782,11 +794,6 @@ private ASN1Sequence toASN1Sequence(final Ruby runtime) {
});
}

private static X509Revoked asRevoked(final Ruby runtime, final IRubyObject value) {
if (!(value instanceof X509Revoked)) throw runtime.newTypeError(value, X509Revoked._Revoked(runtime));
return (X509Revoked) value;
}

private ASN1Primitive readCRL(final Ruby runtime) {
try {
return ASN1.readObject(getEncodedOriginal());
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/org/jruby/ext/openssl/X509Extension.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,31 @@ static X509Extension newExtension(final Ruby runtime, ASN1ObjectIdentifier objec
return ext;
}

static X509Extension copy(final Ruby runtime, final X509Extension extension) {
final X509Extension copy = new X509Extension(runtime, _Extension(runtime));
copy.setRealObjectID(extension.getRealObjectID());
copy.setRealCritical(extension.isRealCritical());
try {
copy.value = extension.getRealValueEncoded().clone();
} catch (IOException e) {
throw newExtensionError(runtime, e);
}
return copy;
}

static RubyArray copyExtensions(final Ruby runtime, final RubyArray array) {
final int length = array.size();
final IRubyObject[] copy = new IRubyObject[length];
for (int i = 0; i < length; i++) {
final IRubyObject extension = array.eltInternal(i);
if (!(extension instanceof X509Extension)) {
throw runtime.newTypeError(extension, X509Extension._Extension(runtime));
}
copy[i] = copy(runtime, (X509Extension) extension);
}
return RubyArray.newArrayNoCopy(runtime, copy);
}

ASN1ObjectIdentifier getRealObjectID() {
return objectID;
}
Expand Down
72 changes: 43 additions & 29 deletions src/main/java/org/jruby/ext/openssl/X509ExtensionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,86 +161,95 @@ public IRubyObject set_config(IRubyObject arg) {
}

@JRubyMethod(rest = true)
public IRubyObject create_ext(final ThreadContext context, final IRubyObject[] args) {
public IRubyObject create_ext(final ThreadContext context, final IRubyObject... args) {
final Ruby runtime = context.runtime;
IRubyObject critical;
if (Arity.checkArgumentCount(runtime, args, 2, 3) == 3 && !args[2].isNil()) {
critical = args[2];
} else {
critical = runtime.getFalse();
}
final String oid = args[0].toString();
String valuex = args[1].toString();
return create_ext(context, args[0], args[1], critical);
}

private X509Extension create_ext(final ThreadContext context,
final IRubyObject oid,
final IRubyObject value,
IRubyObject critical) {
final Ruby runtime = context.runtime;
final String oidString = oid.toString();
String valuex = value.toString();
final ASN1ObjectIdentifier objectId;
try {
objectId = ASN1.getObjectID(runtime, oid);
objectId = ASN1.getObjectID(runtime, oidString);
} catch (IllegalArgumentException e) {
LOG.debug(runtime, "create_ext getObjectID failed", e);
throw newExtensionError(runtime, "unknown OID `" + oid + "'");
throw newExtensionError(runtime, "unknown OID `" + oidString + "'");
}
final String critical_ = "critical,";
if ( valuex.startsWith(critical_) ) {
critical = runtime.getTrue();
critical = context.tru;
valuex = valuex.substring(critical_.length()).trim();
}
final ASN1Encodable value;

final ASN1Encodable val;
try {
final String id = objectId.getId();
if (valuex.startsWith("ASN1:")) {
value = parseASN1ConfigValue(context, valuex);
val = parseASN1ConfigValue(context, valuex);
}
else if (id.equals("2.5.29.14")) { // subjectKeyIdentifier
value = new DEROctetString(parseSubjectKeyIdentifier(context, oid, valuex));
val = new DEROctetString(parseSubjectKeyIdentifier(context, oidString, valuex));
}
else if (id.equals("2.5.29.35")) { // authorityKeyIdentifier
value = parseAuthorityKeyIdentifier(context, valuex);
val = parseAuthorityKeyIdentifier(context, valuex);
}
else if (id.equals("2.5.29.17")) { // subjectAltName
value = parseSubjectAltName(valuex);
val = parseSubjectAltName(valuex);
}
else if (id.equals("2.5.29.18")) { // issuerAltName
value = parseIssuerAltName(context, valuex);
val = parseIssuerAltName(context, valuex);
}
else if (id.equals("2.5.29.19")) { // basicConstraints
value = parseBasicConstrains(valuex);
val = parseBasicConstrains(valuex);
}
else if (id.equals("2.5.29.15")) { // keyUsage
value = parseKeyUsage(oid, valuex);
val = parseKeyUsage(oidString, valuex);
}
else if (id.equals("2.16.840.1.113730.1.1")) { // nsCertType
value = parseNsCertType(oid, valuex);
val = parseNsCertType(oidString, valuex);
}
else if (id.equals("2.5.29.37")) { // extendedKeyUsage
value = parseExtendedKeyUsage(runtime, oid, valuex, critical.isTrue());
val = parseExtendedKeyUsage(runtime, oidString, valuex, critical.isTrue());
}
else if (id.equals("2.5.29.31")) { // crlDistributionPoints
value = parseCRLDistributionPoints(context, valuex);
val = parseCRLDistributionPoints(context, valuex);
}
else if (id.equals("1.3.6.1.5.5.7.1.1")) { // authorityInfoAccess
value = parseAuthorityInfoAccess(valuex);
val = parseAuthorityInfoAccess(valuex);
}
else if (isNetscapeIA5StringExtension(id)) {
value = new DEROctetString(new DERIA5String(valuex).getEncoded(ASN1Encoding.DER));
val = new DEROctetString(new DERIA5String(valuex).getEncoded(ASN1Encoding.DER));
}
else if (id.equals("2.5.29.30")) { // nameConstraints
value = parseNameConstraints(valuex);
val = parseNameConstraints(valuex);
}
else if (id.equals("2.5.29.32")) { // certificatePolicies
value = parseCertificatePolicies(context, valuex);
val = parseCertificatePolicies(context, valuex);
}
else {
value = new DEROctetString(new DEROctetString(ByteList.plain(valuex)).getEncoded(ASN1Encoding.DER));
val = new DEROctetString(new DEROctetString(ByteList.plain(valuex)).getEncoded(ASN1Encoding.DER));
}
}
catch (IOException e) {
LOG.debugStack(runtime, null, e);
throw newExtensionError(runtime, "Unable to create extension: " + e.getMessage());
}
catch (IllegalArgumentException e) {
throw newExtensionError(runtime, oid + " = " + valuex +
": error in extension (name=" + oid + ", value=" + valuex + ")");
throw newExtensionError(runtime, oidString + " = " + valuex +
": error in extension (name=" + oidString + ", value=" + valuex + ")");
}
return newExtension(runtime, objectId, value, critical.isNil() ? null : critical.isTrue());
return newExtension(runtime, objectId, val, critical.isNil() ? null : critical.isTrue());
}

private ASN1Encodable parseASN1ConfigValue(final ThreadContext context, final String value)
Expand Down Expand Up @@ -355,8 +364,13 @@ public IRubyObject create_extension(final ThreadContext context, final IRubyObje
@JRubyMethod
public IRubyObject create_ext_from_array(final ThreadContext context, final IRubyObject arg) {
final RubyArray ary = (RubyArray) arg;
if ( ary.size() > 3 ) throw newExtensionError(context.runtime, "unexpected array form");
return create_ext(context, ary.toJavaArrayUnsafe());
final int size = ary.size();
if ( size > 3 ) throw newExtensionError(context.runtime, "unexpected array form");
if ( size < 2 ) { // fail with appropriate ArgumentError
return size == 1 ? create_ext(context, ary.eltInternal(0)) : create_ext(context);
}
final IRubyObject critical = size == 3 ? ary.eltInternal(2) : context.fals;
return create_ext(context, ary.eltInternal(0), ary.eltInternal(1), critical);
}

@JRubyMethod
Expand All @@ -366,7 +380,7 @@ public IRubyObject create_ext_from_hash(final ThreadContext context, final IRuby
final IRubyObject oid = hash.op_aref(context, newStringFrozen(runtime, "oid"));
final IRubyObject value = hash.op_aref(context, newStringFrozen(runtime, "value"));
final IRubyObject critical = hash.op_aref(context, newStringFrozen(runtime, "critical"));
return create_ext(context, new IRubyObject[]{oid, value, critical});
return create_ext(context, oid, value, critical);
}

// "oid = critical, value"
Expand All @@ -387,7 +401,7 @@ public IRubyObject create_ext_from_string(final ThreadContext context, final IRu
value.op_aset19(context, runtime.newFixnum(0), runtime.newFixnum(critical__.length), RubyString.newEmptyString(runtime));
}
value.strip_bang19(context);
return create_ext(context, new IRubyObject[]{oid, value, critical});
return create_ext(context, oid, value, critical);
}

private DERBitString parseKeyUsage(final String oid, final String valuex) {
Expand Down
Loading
Loading