Ruby OpenSSL extension patch to support multiple certificates
parent
48cd65e6e2
commit
b296750db0
5
Makefile
5
Makefile
|
@ -64,7 +64,7 @@ libs: $(LIBS)
|
|||
build/$(RUBY_VERSION)-cryptcheck: $(RBENV_ROOT)/plugins/ruby-build/share/ruby-build/$(RUBY_VERSION)
|
||||
cp $< $@
|
||||
install-ruby: build/$(RUBY_VERSION)-cryptcheck $(LIBS) | $(OPENSSL_DIR)/
|
||||
cat tmp_key.patch set_ecdh_curves.patch fallback_scsv.patch | \
|
||||
cat tmp_key.patch set_ecdh_curves.patch fallback_scsv.patch multiple_certs.patch | \
|
||||
RUBY_BUILD_CACHE_PATH=$(PWD)/build \
|
||||
RUBY_BUILD_DEFINITIONS=$(PWD)/build \
|
||||
rbenv install -fp $(RUBY_VERSION)-cryptcheck
|
||||
|
@ -88,9 +88,10 @@ $(RUBY_OPENSSL_EXT_DIR)/Makefile: libs | $(RUBY_DIR)/
|
|||
patch -d $(RUBY_DIR)/ -p1 < tmp_key.patch
|
||||
patch -d $(RUBY_DIR)/ -p1 < set_ecdh_curves.patch
|
||||
patch -d $(RUBY_DIR)/ -p1 < fallback_scsv.patch
|
||||
patch -d $(RUBY_DIR)/ -p1 < multiple_certs.patch
|
||||
cd $(RUBY_OPENSSL_EXT_DIR) && ruby extconf.rb
|
||||
|
||||
$(RUBY_OPENSSL_EXT_DIR)/openssl.so: $(LIBS) $(RUBY_OPENSSL_EXT_DIR)/Makefile
|
||||
$(RUBY_OPENSSL_EXT_DIR)/openssl.so: $(LIBS) #$(RUBY_OPENSSL_EXT_DIR)/Makefile
|
||||
top_srcdir=../.. $(MAKE) -C $(RUBY_OPENSSL_EXT_DIR)
|
||||
|
||||
lib/openssl.so: $(RUBY_OPENSSL_EXT_DIR)/openssl.so
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
|
||||
index bcb167e..5f688db 100644
|
||||
--- a/ext/openssl/lib/openssl/ssl.rb
|
||||
+++ b/ext/openssl/lib/openssl/ssl.rb
|
||||
@@ -70,7 +70,7 @@ class SSLContext
|
||||
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
|
||||
end
|
||||
|
||||
- INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path",
|
||||
+ INIT_VARS = ["client_ca", "ca_file", "ca_path",
|
||||
"timeout", "verify_mode", "verify_depth", "renegotiation_cb",
|
||||
"verify_callback", "cert_store", "extra_chain_cert",
|
||||
"client_cert_cb", "session_id_context", "tmp_dh_callback",
|
||||
@@ -106,6 +106,7 @@ class SSLContext
|
||||
#
|
||||
# You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
|
||||
def initialize(version = nil, fallback_scsv: false)
|
||||
+ @certs = @keys = []
|
||||
INIT_VARS.each { |v| instance_variable_set v, nil }
|
||||
self.options = self.options | OpenSSL::SSL::OP_ALL
|
||||
return unless version
|
||||
@@ -131,6 +132,22 @@ def set_params(params={})
|
||||
end
|
||||
return params
|
||||
end
|
||||
+
|
||||
+ # Compatibility with previous version supporting a single certificate
|
||||
+ def cert=(cert)
|
||||
+ self.certs = [cert]
|
||||
+ end
|
||||
+ def cert
|
||||
+
|
||||
+ self.certs.first
|
||||
+ end
|
||||
+
|
||||
+ def key=(key)
|
||||
+ self.keys = [key]
|
||||
+ end
|
||||
+ def key
|
||||
+ self.keys.first
|
||||
+ end
|
||||
end
|
||||
|
||||
module SocketForwarder
|
||||
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
|
||||
index 9f7ee0b..9437793 100644
|
||||
--- a/ext/openssl/ossl_ssl.c
|
||||
+++ b/ext/openssl/ossl_ssl.c
|
||||
@@ -36,8 +36,8 @@ VALUE cSSLSocket;
|
||||
static VALUE eSSLErrorWaitReadable;
|
||||
static VALUE eSSLErrorWaitWritable;
|
||||
|
||||
-#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
|
||||
-#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
|
||||
+#define ossl_sslctx_set_certs(o,v) rb_iv_set((o),"@certs",(v))
|
||||
+#define ossl_sslctx_set_keys(o,v) rb_iv_set((o),"@keys",(v))
|
||||
#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
|
||||
#define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
|
||||
#define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
|
||||
@@ -50,8 +50,8 @@ static VALUE eSSLErrorWaitWritable;
|
||||
#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
|
||||
#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_set((o),"@session_id_context",(v))
|
||||
|
||||
-#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
|
||||
-#define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
|
||||
+#define ossl_sslctx_get_certs(o) rb_iv_get((o),"@certs")
|
||||
+#define ossl_sslctx_get_keys(o) rb_iv_get((o),"@keys")
|
||||
#define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
|
||||
#define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
|
||||
#define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
|
||||
@@ -713,7 +713,8 @@ ossl_sslctx_setup(VALUE self)
|
||||
char *ca_path = NULL, *ca_file = NULL;
|
||||
int verify_mode;
|
||||
long i;
|
||||
- VALUE val;
|
||||
+ VALUE val, val2;
|
||||
+ int cert_defined = 0, key_defined = 0;
|
||||
|
||||
if(OBJ_FROZEN(self)) return Qnil;
|
||||
GetSSLCTX(self, ctx);
|
||||
@@ -761,19 +762,39 @@ ossl_sslctx_setup(VALUE self)
|
||||
}
|
||||
|
||||
/* private key may be bundled in certificate file. */
|
||||
- val = ossl_sslctx_get_cert(self);
|
||||
- cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
|
||||
- val = ossl_sslctx_get_key(self);
|
||||
- key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
|
||||
- if (cert && key) {
|
||||
- if (!SSL_CTX_use_certificate(ctx, cert)) {
|
||||
- /* Adds a ref => Safe to FREE */
|
||||
- ossl_raise(eSSLError, "SSL_CTX_use_certificate");
|
||||
+ val = ossl_sslctx_get_certs(self);
|
||||
+ if (!NIL_P(val)) {
|
||||
+ Check_Type(val, T_ARRAY);
|
||||
+ for (i = 0; i < RARRAY_LEN(val); i++) {
|
||||
+ val2 = rb_ary_entry(val, i);
|
||||
+ cert = NIL_P(val2) ? NULL : GetX509CertPtr(val2); /* NO DUP NEEDED */
|
||||
+ if (cert) {
|
||||
+ cert_defined = 1;
|
||||
+ if (!SSL_CTX_use_certificate(ctx, cert)) {
|
||||
+ /* Adds a ref => Safe to FREE */
|
||||
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
- if (!SSL_CTX_use_PrivateKey(ctx, key)) {
|
||||
- /* Adds a ref => Safe to FREE */
|
||||
- ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
|
||||
+ }
|
||||
+
|
||||
+ val = ossl_sslctx_get_keys(self);
|
||||
+ if (!NIL_P(val)) {
|
||||
+ Check_Type(val, T_ARRAY);
|
||||
+ for (i = 0; i < RARRAY_LEN(val); i++) {
|
||||
+ val2 = rb_ary_entry(val, i);
|
||||
+ key = NIL_P(val2) ? NULL : GetPKeyPtr(val2); /* NO DUP NEEDED */
|
||||
+ if (cert) {
|
||||
+ key_defined = 1;
|
||||
+ if (!SSL_CTX_use_PrivateKey(ctx, key)) {
|
||||
+ /* Adds a ref => Safe to FREE */
|
||||
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ if (cert_defined && key_defined) {
|
||||
if (!SSL_CTX_check_private_key(ctx)) {
|
||||
ossl_raise(eSSLError, "SSL_CTX_check_private_key");
|
||||
}
|
||||
@@ -2128,14 +2149,14 @@ Init_ossl_ssl(void)
|
||||
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
|
||||
|
||||
/*
|
||||
- * Context certificate
|
||||
+ * Context certificates
|
||||
*/
|
||||
- rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
|
||||
+ rb_attr(cSSLContext, rb_intern("certs"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
- * Context private key
|
||||
+ * Context private keys
|
||||
*/
|
||||
- rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
|
||||
+ rb_attr(cSSLContext, rb_intern("keys"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* A certificate or Array of certificates that will be sent to the client.
|
Loading…
Reference in New Issue