@@ -193,6 +193,91 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
193
193
ossl_raise (rb_eArgError , "unknown SSL method `%" PRIsVALUE "'." , m );
194
194
}
195
195
196
+ static int
197
+ parse_proto_version (VALUE str )
198
+ {
199
+ int i ;
200
+ static const struct {
201
+ const char * name ;
202
+ int version ;
203
+ } map [] = {
204
+ { "SSL2" , SSL2_VERSION },
205
+ { "SSL3" , SSL3_VERSION },
206
+ { "TLS1" , TLS1_VERSION },
207
+ { "TLS1_1" , TLS1_1_VERSION },
208
+ { "TLS1_2" , TLS1_2_VERSION },
209
+ #ifdef TLS1_3_VERSION
210
+ { "TLS1_3" , TLS1_3_VERSION },
211
+ #endif
212
+ };
213
+
214
+ if (NIL_P (str ))
215
+ return 0 ;
216
+ if (RB_INTEGER_TYPE_P (str ))
217
+ return NUM2INT (str );
218
+
219
+ if (SYMBOL_P (str ))
220
+ str = rb_sym2str (str );
221
+ StringValue (str );
222
+ for (i = 0 ; i < numberof (map ); i ++ )
223
+ if (!strncmp (map [i ].name , RSTRING_PTR (str ), RSTRING_LEN (str )))
224
+ return map [i ].version ;
225
+ rb_raise (rb_eArgError , "unrecognized version %+" PRIsVALUE , str );
226
+ }
227
+
228
+ /*
229
+ * call-seq:
230
+ * ctx.set_minmax_proto_version(min, max) -> nil
231
+ *
232
+ * Sets the minimum and maximum supported protocol versions. See #min_version=
233
+ * and #max_version=.
234
+ */
235
+ static VALUE
236
+ ossl_sslctx_set_minmax_proto_version (VALUE self , VALUE min_v , VALUE max_v )
237
+ {
238
+ SSL_CTX * ctx ;
239
+ int min , max ;
240
+
241
+ GetSSLCTX (self , ctx );
242
+ min = parse_proto_version (min_v );
243
+ max = parse_proto_version (max_v );
244
+
245
+ #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
246
+ if (!SSL_CTX_set_min_proto_version (ctx , min ))
247
+ ossl_raise (eSSLError , "SSL_CTX_set_min_proto_version" );
248
+ if (!SSL_CTX_set_max_proto_version (ctx , max ))
249
+ ossl_raise (eSSLError , "SSL_CTX_set_max_proto_version" );
250
+ #else
251
+ {
252
+ unsigned long sum = 0 , opts = 0 ;
253
+ int i ;
254
+ static const struct {
255
+ int ver ;
256
+ unsigned long opts ;
257
+ } options_map [] = {
258
+ { SSL2_VERSION , SSL_OP_NO_SSLv2 },
259
+ { SSL3_VERSION , SSL_OP_NO_SSLv3 },
260
+ { TLS1_VERSION , SSL_OP_NO_TLSv1 },
261
+ { TLS1_1_VERSION , SSL_OP_NO_TLSv1_1 },
262
+ { TLS1_2_VERSION , SSL_OP_NO_TLSv1_2 },
263
+ # if defined(TLS1_3_VERSION )
264
+ { TLS1_3_VERSION , SSL_OP_NO_TLSv1_3 },
265
+ # endif
266
+ };
267
+
268
+ for (i = 0 ; i < numberof (options_map ); i ++ ) {
269
+ sum |= options_map [i ].opts ;
270
+ if (min && min > options_map [i ].ver || max && max < options_map [i ].ver )
271
+ opts |= options_map [i ].opts ;
272
+ }
273
+ SSL_CTX_clear_options (ctx , sum );
274
+ SSL_CTX_set_options (ctx , opts );
275
+ }
276
+ #endif
277
+
278
+ return Qnil ;
279
+ }
280
+
196
281
static VALUE
197
282
ossl_call_client_cert_cb (VALUE obj )
198
283
{
@@ -2548,6 +2633,8 @@ Init_ossl_ssl(void)
2548
2633
rb_define_alias (cSSLContext , "ssl_timeout" , "timeout" );
2549
2634
rb_define_alias (cSSLContext , "ssl_timeout=" , "timeout=" );
2550
2635
rb_define_method (cSSLContext , "ssl_version=" , ossl_sslctx_set_ssl_version , 1 );
2636
+ rb_define_private_method (cSSLContext , "set_minmax_proto_version" ,
2637
+ ossl_sslctx_set_minmax_proto_version , 2 );
2551
2638
rb_define_method (cSSLContext , "ciphers" , ossl_sslctx_get_ciphers , 0 );
2552
2639
rb_define_method (cSSLContext , "ciphers=" , ossl_sslctx_set_ciphers , 1 );
2553
2640
rb_define_method (cSSLContext , "ecdh_curves=" , ossl_sslctx_set_ecdh_curves , 1 );
@@ -2751,6 +2838,26 @@ Init_ossl_ssl(void)
2751
2838
rb_define_const (mSSL , "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG" , ULONG2NUM (SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG ));
2752
2839
2753
2840
2841
+ /*
2842
+ * SSL/TLS version constants. Used by SSLContext#min_version= and
2843
+ * #max_version=
2844
+ */
2845
+ /* SSL 2.0 */
2846
+ rb_define_const (mSSL , "SSL2_VERSION" , INT2NUM (SSL2_VERSION ));
2847
+ /* SSL 3.0 */
2848
+ rb_define_const (mSSL , "SSL3_VERSION" , INT2NUM (SSL3_VERSION ));
2849
+ /* TLS 1.0 */
2850
+ rb_define_const (mSSL , "TLS1_VERSION" , INT2NUM (TLS1_VERSION ));
2851
+ /* TLS 1.1 */
2852
+ rb_define_const (mSSL , "TLS1_1_VERSION" , INT2NUM (TLS1_1_VERSION ));
2853
+ /* TLS 1.2 */
2854
+ rb_define_const (mSSL , "TLS1_2_VERSION" , INT2NUM (TLS1_2_VERSION ));
2855
+ #ifdef TLS1_3_VERSION /* OpenSSL 1.1.1 */
2856
+ /* TLS 1.3 */
2857
+ rb_define_const (mSSL , "TLS1_3_VERSION" , INT2NUM (TLS1_3_VERSION ));
2858
+ #endif
2859
+
2860
+
2754
2861
sym_exception = ID2SYM (rb_intern ("exception" ));
2755
2862
sym_wait_readable = ID2SYM (rb_intern ("wait_readable" ));
2756
2863
sym_wait_writable = ID2SYM (rb_intern ("wait_writable" ));
0 commit comments