@@ -273,80 +273,87 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
273273 return ossl_verify_cb_call (cb , preverify_ok , ctx );
274274}
275275
276+ struct sess_get_cb_args {
277+ VALUE ssl_obj ;
278+ const unsigned char * data ;
279+ int len ;
280+ };
281+
276282static VALUE
277- ossl_call_session_get_cb (VALUE ary )
283+ ossl_call_sess_get_cb (VALUE args_ )
278284{
279- VALUE ssl_obj , sslctx_obj , cb ;
285+ struct sess_get_cb_args * args = (struct sess_get_cb_args * )args_ ;
286+ VALUE ssl_obj = args -> ssl_obj , sslctx_obj , cb ;
280287
281- Check_Type (ary , T_ARRAY );
282- ssl_obj = rb_ary_entry (ary , 0 );
283288 sslctx_obj = rb_attr_get (ssl_obj , id_i_context );
284289 cb = rb_attr_get (sslctx_obj , id_i_session_get_cb );
285290 if (NIL_P (cb )) return Qnil ;
286291
287- return rb_funcallv (cb , id_call , 1 , & ary );
292+ VALUE session_id = rb_str_new ((const char * )args -> data , args -> len );
293+ VALUE ret_obj = rb_funcall (cb , id_call , 1 , rb_assoc_new (ssl_obj , session_id ));
294+ // XXX: Should we raise if ret is neither SSLSession nor nil?
295+ if (!rb_obj_is_instance_of (ret_obj , cSSLSession ))
296+ return (VALUE )NULL ;
297+
298+ SSL_SESSION * sess ;
299+ GetSSLSession (ret_obj , sess );
300+ return (VALUE )sess ;
288301}
289302
290303static SSL_SESSION *
291304ossl_sslctx_session_get_cb (SSL * ssl , const unsigned char * buf , int len , int * copy )
292305{
293306 struct ossl_ssl_data * p = ssl_data (ssl );
294- VALUE ary , ret_obj ;
295- SSL_SESSION * sess ;
296- int state = 0 ;
307+ if (p -> cb_state )
308+ return NULL ;
297309
298310 OSSL_Debug ("SSL SESSION get callback entered" );
299- ary = rb_ary_new2 (2 );
300- rb_ary_push (ary , p -> self );
301- rb_ary_push (ary , rb_str_new ((const char * )buf , len ));
302-
303- ret_obj = rb_protect (ossl_call_session_get_cb , ary , & state );
311+ struct sess_get_cb_args args = { p -> self , buf , len };
312+ int state ;
313+ VALUE ret = rb_protect (ossl_call_sess_get_cb , (VALUE )& args , & state );
304314 if (state ) {
305315 p -> cb_state = state ;
306316 return NULL ;
307317 }
308- if (!rb_obj_is_instance_of (ret_obj , cSSLSession ))
309- return NULL ;
310-
311- GetSSLSession (ret_obj , sess );
312318 * copy = 1 ;
313-
314- return sess ;
319+ return (SSL_SESSION * )ret ;
315320}
316321
322+ struct sess_new_cb_args {
323+ VALUE ssl_obj ;
324+ SSL_SESSION * sess ;
325+ };
326+
317327static VALUE
318- ossl_call_session_new_cb (VALUE ary )
328+ ossl_call_session_new_cb (VALUE args_ )
319329{
320- VALUE ssl_obj , sslctx_obj , cb ;
330+ struct sess_new_cb_args * args = (struct sess_new_cb_args * )args_ ;
331+ VALUE ssl_obj = args -> ssl_obj , sslctx_obj , cb ;
321332
322- Check_Type (ary , T_ARRAY );
323- ssl_obj = rb_ary_entry (ary , 0 );
324333 sslctx_obj = rb_attr_get (ssl_obj , id_i_context );
325334 cb = rb_attr_get (sslctx_obj , id_i_session_new_cb );
326335 if (NIL_P (cb )) return Qnil ;
327336
328- return rb_funcallv (cb , id_call , 1 , & ary );
337+ VALUE sess_obj = rb_obj_alloc (cSSLSession );
338+ if (!SSL_SESSION_up_ref (args -> sess ))
339+ ossl_raise (eSSLError , "SSL_SESSION_up_ref" );
340+ RTYPEDDATA_DATA (sess_obj ) = args -> sess ;
341+
342+ return rb_funcall (cb , id_call , 1 , rb_assoc_new (ssl_obj , sess_obj ));
329343}
330344
331345/* return 1 normal. return 0 removes the session */
332346static int
333347ossl_sslctx_session_new_cb (SSL * ssl , SSL_SESSION * sess )
334348{
335349 struct ossl_ssl_data * p = ssl_data (ssl );
336- VALUE ary , sess_obj ;
337- int state = 0 ;
350+ if ( p -> cb_state )
351+ return 0 ;
338352
339353 OSSL_Debug ("SSL SESSION new callback entered" );
340-
341- sess_obj = rb_obj_alloc (cSSLSession );
342- SSL_SESSION_up_ref (sess );
343- DATA_PTR (sess_obj ) = sess ;
344-
345- ary = rb_ary_new2 (2 );
346- rb_ary_push (ary , p -> self );
347- rb_ary_push (ary , sess_obj );
348-
349- rb_protect (ossl_call_session_new_cb , ary , & state );
354+ struct sess_new_cb_args args = { p -> self , sess };
355+ int state ;
356+ rb_protect (ossl_call_session_new_cb , (VALUE )& args , & state );
350357 if (state ) {
351358 p -> cb_state = state ;
352359 }
@@ -407,26 +414,32 @@ ossl_sslctx_keylog_cb(const SSL *ssl, const char *line)
407414}
408415#endif
409416
417+ struct sess_remove_cb_args {
418+ SSL_CTX * ctx ;
419+ SSL_SESSION * sess ;
420+ };
421+
410422static VALUE
411- ossl_call_session_remove_cb (VALUE ary )
423+ ossl_call_session_remove_cb (VALUE args_ )
412424{
425+ struct sess_remove_cb_args * args = (struct sess_remove_cb_args * )args_ ;
413426 VALUE sslctx_obj , cb ;
414427
415- Check_Type (ary , T_ARRAY );
416- sslctx_obj = rb_ary_entry (ary , 0 );
417-
428+ sslctx_obj = (VALUE )SSL_CTX_get_ex_data (args -> ctx , ossl_sslctx_ex_ptr_idx );
418429 cb = rb_attr_get (sslctx_obj , id_i_session_remove_cb );
419430 if (NIL_P (cb )) return Qnil ;
420431
421- return rb_funcallv (cb , id_call , 1 , & ary );
432+ VALUE sess_obj = rb_obj_alloc (cSSLSession );
433+ if (!SSL_SESSION_up_ref (args -> sess ))
434+ ossl_raise (eSSLError , "SSL_SESSION_up_ref" );
435+ RTYPEDDATA_DATA (sess_obj ) = args -> sess ;
436+
437+ return rb_funcall (cb , id_call , 1 , rb_assoc_new (sslctx_obj , sess_obj ));
422438}
423439
424440static void
425441ossl_sslctx_session_remove_cb (SSL_CTX * ctx , SSL_SESSION * sess )
426442{
427- VALUE ary , sslctx_obj , sess_obj ;
428- int state = 0 ;
429-
430443 /*
431444 * This callback is also called for all sessions in the internal store
432445 * when SSL_CTX_free() is called.
@@ -435,23 +448,16 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
435448 return ;
436449
437450 OSSL_Debug ("SSL SESSION remove callback entered" );
438-
439- sslctx_obj = (VALUE )SSL_CTX_get_ex_data (ctx , ossl_sslctx_ex_ptr_idx );
440- sess_obj = rb_obj_alloc (cSSLSession );
441- SSL_SESSION_up_ref (sess );
442- DATA_PTR (sess_obj ) = sess ;
443-
444- ary = rb_ary_new2 (2 );
445- rb_ary_push (ary , sslctx_obj );
446- rb_ary_push (ary , sess_obj );
447-
448- rb_protect (ossl_call_session_remove_cb , ary , & state );
451+ struct sess_remove_cb_args args = { ctx , sess };
452+ int state ;
453+ rb_protect (ossl_call_session_remove_cb , (VALUE )& args , & state );
449454 if (state ) {
450- /*
451- the SSL_CTX is frozen, nowhere to save state.
452- there is no common accessor method to check it either.
453- rb_ivar_set(sslctx_obj, ID_callback_state, INT2NUM(state));
454- */
455+ /*
456+ * the SSL_CTX is frozen, nowhere to save state.
457+ * there is no common accessor method to check it either.
458+ */
459+ rb_warn ("exception in session_remove_cb is ignored" );
460+ rb_set_errinfo (Qnil );
455461 }
456462}
457463
0 commit comments