@@ -193,6 +193,80 @@ 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
+ for (i = 0 ; i < numberof (map ); i ++ ) {
222
+ if (!strcmp (map [i ].name , StringValueCStr (str )))
223
+ return map [i ].version ;
224
+ }
225
+ rb_raise (rb_eArgError , "unrecognized version %+" PRIsVALUE , str );
226
+ }
227
+
228
+ static VALUE
229
+ ossl_sslctx_set_minmax_proto_version (VALUE self , VALUE min_v , VALUE max_v )
230
+ {
231
+ SSL_CTX * ctx ;
232
+ int min , max ;
233
+ #ifndef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
234
+ unsigned long sum = 0 , opts = 0 ;
235
+ int i ;
236
+ static const struct { int ver ; unsigned long opts ; } options_map [] = {
237
+ { SSL2_VERSION , SSL_OP_NO_SSLv2 },
238
+ { SSL3_VERSION , SSL_OP_NO_SSLv3 },
239
+ { TLS1_VERSION , SSL_OP_NO_TLSv1 },
240
+ { TLS1_1_VERSION , SSL_OP_NO_TLSv1_1 },
241
+ { TLS1_2_VERSION , SSL_OP_NO_TLSv1_2 },
242
+ #ifdef TLS1_3_VERSION
243
+ { TLS1_3_VERSION , SSL_OP_NO_TLSv1_3 },
244
+ #endif
245
+ };
246
+ #endif
247
+
248
+ GetSSLCTX (self , ctx );
249
+ min = parse_proto_version (min_v );
250
+ max = parse_proto_version (max_v );
251
+
252
+ #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
253
+ if (!SSL_CTX_set_min_proto_version (ctx , min ))
254
+ ossl_raise (eSSLError , "SSL_CTX_set_min_proto_version" );
255
+ if (!SSL_CTX_set_max_proto_version (ctx , max ))
256
+ ossl_raise (eSSLError , "SSL_CTX_set_max_proto_version" );
257
+ #else
258
+ for (i = 0 ; i < numberof (options_map ); i ++ ) {
259
+ sum |= options_map [i ].opts ;
260
+ if (min && min > options_map [i ].ver || max && max < options_map [i ].ver )
261
+ opts |= options_map [i ].opts ;
262
+ }
263
+ SSL_CTX_clear_options (ctx , sum );
264
+ SSL_CTX_set_options (ctx , opts );
265
+ #endif
266
+
267
+ return Qnil ;
268
+ }
269
+
196
270
static VALUE
197
271
ossl_call_client_cert_cb (VALUE obj )
198
272
{
@@ -2544,6 +2618,8 @@ Init_ossl_ssl(void)
2544
2618
rb_define_alias (cSSLContext , "ssl_timeout" , "timeout" );
2545
2619
rb_define_alias (cSSLContext , "ssl_timeout=" , "timeout=" );
2546
2620
rb_define_method (cSSLContext , "ssl_version=" , ossl_sslctx_set_ssl_version , 1 );
2621
+ rb_define_private_method (cSSLContext , "set_minmax_proto_version" ,
2622
+ ossl_sslctx_set_minmax_proto_version , 2 );
2547
2623
rb_define_method (cSSLContext , "ciphers" , ossl_sslctx_get_ciphers , 0 );
2548
2624
rb_define_method (cSSLContext , "ciphers=" , ossl_sslctx_set_ciphers , 1 );
2549
2625
rb_define_method (cSSLContext , "ecdh_curves=" , ossl_sslctx_set_ecdh_curves , 1 );
@@ -2747,6 +2823,26 @@ Init_ossl_ssl(void)
2747
2823
rb_define_const (mSSL , "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG" , ULONG2NUM (SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG ));
2748
2824
2749
2825
2826
+ /*
2827
+ * SSL/TLS version constants. Used by SSLContext#min_version= and
2828
+ * #max_version=
2829
+ */
2830
+ /* SSL 2 */
2831
+ rb_define_const (mSSL , "SSL2_VERSION" , INT2NUM (SSL2_VERSION ));
2832
+ /* SSL 3 */
2833
+ rb_define_const (mSSL , "SSL3_VERSION" , INT2NUM (SSL3_VERSION ));
2834
+ /* TLS 1.0 */
2835
+ rb_define_const (mSSL , "TLS1_VERSION" , INT2NUM (TLS1_VERSION ));
2836
+ /* TLS 1.1 */
2837
+ rb_define_const (mSSL , "TLS1_1_VERSION" , INT2NUM (TLS1_1_VERSION ));
2838
+ /* TLS 1.2 */
2839
+ rb_define_const (mSSL , "TLS1_2_VERSION" , INT2NUM (TLS1_2_VERSION ));
2840
+ #ifdef TLS1_3_VERSION /* OpenSSL 1.1.1 */
2841
+ /* TLS 1.3 */
2842
+ rb_define_const (mSSL , "TLS1_3_VERSION" , INT2NUM (TLS1_3_VERSION ));
2843
+ #endif
2844
+
2845
+
2750
2846
sym_exception = ID2SYM (rb_intern ("exception" ));
2751
2847
sym_wait_readable = ID2SYM (rb_intern ("wait_readable" ));
2752
2848
sym_wait_writable = ID2SYM (rb_intern ("wait_writable" ));
0 commit comments