Browse Source

Ruby OpenSSL extension patch to support multiple certificates

new-scoring
aeris 2 years ago
parent
commit
b296750db0
2 changed files with 153 additions and 2 deletions
  1. 3
    2
      Makefile
  2. 150
    0
      multiple_certs.patch

+ 3
- 2
Makefile View File

@@ -64,7 +64,7 @@ libs: $(LIBS)
64 64
 build/$(RUBY_VERSION)-cryptcheck: $(RBENV_ROOT)/plugins/ruby-build/share/ruby-build/$(RUBY_VERSION)
65 65
 	cp $< $@
66 66
 install-ruby: build/$(RUBY_VERSION)-cryptcheck $(LIBS) | $(OPENSSL_DIR)/
67
-	cat tmp_key.patch set_ecdh_curves.patch fallback_scsv.patch | \
67
+	cat tmp_key.patch set_ecdh_curves.patch fallback_scsv.patch multiple_certs.patch | \
68 68
 	RUBY_BUILD_CACHE_PATH=$(PWD)/build \
69 69
 	RUBY_BUILD_DEFINITIONS=$(PWD)/build \
70 70
 	rbenv install -fp $(RUBY_VERSION)-cryptcheck
@@ -88,9 +88,10 @@ $(RUBY_OPENSSL_EXT_DIR)/Makefile: libs | $(RUBY_DIR)/
88 88
 	patch -d $(RUBY_DIR)/ -p1 < tmp_key.patch
89 89
 	patch -d $(RUBY_DIR)/ -p1 < set_ecdh_curves.patch
90 90
 	patch -d $(RUBY_DIR)/ -p1 < fallback_scsv.patch
91
+	patch -d $(RUBY_DIR)/ -p1 < multiple_certs.patch
91 92
 	cd $(RUBY_OPENSSL_EXT_DIR) && ruby extconf.rb
92 93
 
93
-$(RUBY_OPENSSL_EXT_DIR)/openssl.so: $(LIBS) $(RUBY_OPENSSL_EXT_DIR)/Makefile
94
+$(RUBY_OPENSSL_EXT_DIR)/openssl.so: $(LIBS) #$(RUBY_OPENSSL_EXT_DIR)/Makefile
94 95
 	top_srcdir=../.. $(MAKE) -C $(RUBY_OPENSSL_EXT_DIR)
95 96
 
96 97
 lib/openssl.so: $(RUBY_OPENSSL_EXT_DIR)/openssl.so

+ 150
- 0
multiple_certs.patch View File

@@ -0,0 +1,150 @@
1
+diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
2
+index bcb167e..5f688db 100644
3
+--- a/ext/openssl/lib/openssl/ssl.rb
4
++++ b/ext/openssl/lib/openssl/ssl.rb
5
+@@ -70,7 +70,7 @@ class SSLContext
6
+         DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
7
+       end
8
+ 
9
+-      INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path",
10
++      INIT_VARS = ["client_ca", "ca_file", "ca_path",
11
+         "timeout", "verify_mode", "verify_depth", "renegotiation_cb",
12
+         "verify_callback", "cert_store", "extra_chain_cert",
13
+         "client_cert_cb", "session_id_context", "tmp_dh_callback",
14
+@@ -106,6 +106,7 @@ class SSLContext
15
+       #
16
+       # You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
17
+       def initialize(version = nil, fallback_scsv: false)
18
++        @certs = @keys = []
19
+         INIT_VARS.each { |v| instance_variable_set v, nil }
20
+         self.options = self.options | OpenSSL::SSL::OP_ALL
21
+         return unless version
22
+@@ -131,6 +132,22 @@ def set_params(params={})
23
+         end
24
+         return params
25
+       end
26
++
27
++      # Compatibility with previous version supporting a single certificate
28
++      def cert=(cert)
29
++        self.certs = [cert]
30
++      end
31
++      def cert
32
++
33
++        self.certs.first
34
++      end
35
++
36
++      def key=(key)
37
++        self.keys = [key]
38
++      end
39
++      def key
40
++        self.keys.first
41
++      end
42
+     end
43
+ 
44
+     module SocketForwarder
45
+diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
46
+index 9f7ee0b..9437793 100644
47
+--- a/ext/openssl/ossl_ssl.c
48
++++ b/ext/openssl/ossl_ssl.c
49
+@@ -36,8 +36,8 @@ VALUE cSSLSocket;
50
+ static VALUE eSSLErrorWaitReadable;
51
+ static VALUE eSSLErrorWaitWritable;
52
+ 
53
+-#define ossl_sslctx_set_cert(o,v)        	rb_iv_set((o),"@cert",(v))
54
+-#define ossl_sslctx_set_key(o,v)         	rb_iv_set((o),"@key",(v))
55
++#define ossl_sslctx_set_certs(o,v)        	rb_iv_set((o),"@certs",(v))
56
++#define ossl_sslctx_set_keys(o,v)         	rb_iv_set((o),"@keys",(v))
57
+ #define ossl_sslctx_set_client_ca(o,v)   	rb_iv_set((o),"@client_ca",(v))
58
+ #define ossl_sslctx_set_ca_file(o,v)     	rb_iv_set((o),"@ca_file",(v))
59
+ #define ossl_sslctx_set_ca_path(o,v)     	rb_iv_set((o),"@ca_path",(v))
60
+@@ -50,8 +50,8 @@ static VALUE eSSLErrorWaitWritable;
61
+ #define ossl_sslctx_set_client_cert_cb(o,v) 	rb_iv_set((o),"@client_cert_cb",(v))
62
+ #define ossl_sslctx_set_sess_id_ctx(o, v) 	rb_iv_set((o),"@session_id_context",(v))
63
+ 
64
+-#define ossl_sslctx_get_cert(o)          	rb_iv_get((o),"@cert")
65
+-#define ossl_sslctx_get_key(o)           	rb_iv_get((o),"@key")
66
++#define ossl_sslctx_get_certs(o)          	rb_iv_get((o),"@certs")
67
++#define ossl_sslctx_get_keys(o)           	rb_iv_get((o),"@keys")
68
+ #define ossl_sslctx_get_client_ca(o)     	rb_iv_get((o),"@client_ca")
69
+ #define ossl_sslctx_get_ca_file(o)       	rb_iv_get((o),"@ca_file")
70
+ #define ossl_sslctx_get_ca_path(o)       	rb_iv_get((o),"@ca_path")
71
+@@ -713,7 +713,8 @@ ossl_sslctx_setup(VALUE self)
72
+     char *ca_path = NULL, *ca_file = NULL;
73
+     int verify_mode;
74
+     long i;
75
+-    VALUE val;
76
++    VALUE val, val2;
77
++    int cert_defined = 0, key_defined = 0;
78
+ 
79
+     if(OBJ_FROZEN(self)) return Qnil;
80
+     GetSSLCTX(self, ctx);
81
+@@ -761,19 +762,39 @@ ossl_sslctx_setup(VALUE self)
82
+     }
83
+ 
84
+     /* private key may be bundled in certificate file. */
85
+-    val = ossl_sslctx_get_cert(self);
86
+-    cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
87
+-    val = ossl_sslctx_get_key(self);
88
+-    key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
89
+-    if (cert && key) {
90
+-        if (!SSL_CTX_use_certificate(ctx, cert)) {
91
+-            /* Adds a ref => Safe to FREE */
92
+-            ossl_raise(eSSLError, "SSL_CTX_use_certificate");
93
++    val = ossl_sslctx_get_certs(self);
94
++    if (!NIL_P(val)) {
95
++        Check_Type(val, T_ARRAY);
96
++        for (i = 0; i < RARRAY_LEN(val); i++) {
97
++            val2 = rb_ary_entry(val, i);
98
++            cert = NIL_P(val2) ? NULL : GetX509CertPtr(val2); /* NO DUP NEEDED */
99
++            if (cert) {
100
++                cert_defined = 1;
101
++                if (!SSL_CTX_use_certificate(ctx, cert)) {
102
++                    /* Adds a ref => Safe to FREE */
103
++                    ossl_raise(eSSLError, "SSL_CTX_use_certificate");
104
++                }
105
++            }
106
+         }
107
+-        if (!SSL_CTX_use_PrivateKey(ctx, key)) {
108
+-            /* Adds a ref => Safe to FREE */
109
+-            ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
110
++    }
111
++
112
++    val = ossl_sslctx_get_keys(self);
113
++    if (!NIL_P(val)) {
114
++        Check_Type(val, T_ARRAY);
115
++        for (i = 0; i < RARRAY_LEN(val); i++) {
116
++            val2 = rb_ary_entry(val, i);
117
++            key = NIL_P(val2) ? NULL : GetPKeyPtr(val2); /* NO DUP NEEDED */
118
++            if (cert) {
119
++                key_defined = 1;
120
++                if (!SSL_CTX_use_PrivateKey(ctx, key)) {
121
++                    /* Adds a ref => Safe to FREE */
122
++                    ossl_raise(eSSLError, "SSL_CTX_use_certificate");
123
++                }
124
++            }
125
+         }
126
++    }
127
++
128
++    if (cert_defined && key_defined) {
129
+         if (!SSL_CTX_check_private_key(ctx)) {
130
+             ossl_raise(eSSLError, "SSL_CTX_check_private_key");
131
+         }
132
+@@ -2128,14 +2149,14 @@ Init_ossl_ssl(void)
133
+     rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
134
+ 
135
+     /*
136
+-     * Context certificate
137
++     * Context certificates
138
+      */
139
+-    rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
140
++    rb_attr(cSSLContext, rb_intern("certs"), 1, 1, Qfalse);
141
+ 
142
+     /*
143
+-     * Context private key
144
++     * Context private keys
145
+      */
146
+-    rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
147
++    rb_attr(cSSLContext, rb_intern("keys"), 1, 1, Qfalse);
148
+ 
149
+     /*
150
+      * A certificate or Array of certificates that will be sent to the client.

Loading…
Cancel
Save