Skip to content

Commit 37c6244

Browse files
jeremyrhenium
authored andcommitted
Look the SSLContext up from the SSL_CTX in the ALPN/NPN callbacks
ossl_sslctx_mark uses rb_gc_mark_movable, so the SSLContext relocates. Its VALUE is stored in four places: the SSL_CTX's ex_data, and the callback argument of the NPN advertise, NPN select and ALPN select callbacks. ossl_sslctx_compact updates the first. Nothing updates the other three, so after a compaction they hold the pre-move address. The three callbacks all receive the SSL, and the SSL_CTX's ex_data copy is already kept current -- so they can look the object up instead of carrying their own copy, which leaves exactly one stored copy and one place to maintain. Registration is one-shot (ossl_sslctx_setup returns early when self is frozen), so the stale address is captured at the first handshake and never refreshed. Fixes #1088.
1 parent 80959f8 commit 37c6244

1 file changed

Lines changed: 15 additions & 6 deletions

File tree

ext/openssl/ossl_ssl.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -579,12 +579,21 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
579579
return SSL_TLSEXT_ERR_OK;
580580
}
581581

582+
static VALUE
583+
ossl_sslctx_obj_from_ssl(const SSL *ssl)
584+
{
585+
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
586+
587+
return (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx);
588+
}
589+
582590
#ifdef OSSL_USE_NEXTPROTONEG
583591
static int
584592
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
585593
void *arg)
586594
{
587-
VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
595+
VALUE protocols = rb_attr_get(ossl_sslctx_obj_from_ssl(ssl),
596+
id_npn_protocols_encoded);
588597

589598
*out = (const unsigned char *) RSTRING_PTR(protocols);
590599
*outlen = RSTRING_LENINT(protocols);
@@ -598,7 +607,7 @@ ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
598607
{
599608
VALUE sslctx_obj, cb;
600609

601-
sslctx_obj = (VALUE) arg;
610+
sslctx_obj = ossl_sslctx_obj_from_ssl(ssl);
602611
cb = rb_attr_get(sslctx_obj, id_i_npn_select_cb);
603612

604613
return ssl_npn_select_cb_common(ssl, cb, (const unsigned char **)out,
@@ -612,7 +621,7 @@ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
612621
{
613622
VALUE sslctx_obj, cb;
614623

615-
sslctx_obj = (VALUE) arg;
624+
sslctx_obj = ossl_sslctx_obj_from_ssl(ssl);
616625
cb = rb_attr_get(sslctx_obj, id_i_alpn_select_cb);
617626

618627
return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen);
@@ -807,11 +816,11 @@ ossl_sslctx_setup(VALUE self)
807816
if (!NIL_P(val)) {
808817
VALUE encoded = ssl_encode_npn_protocols(val);
809818
rb_ivar_set(self, id_npn_protocols_encoded, encoded);
810-
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
819+
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, NULL);
811820
OSSL_Debug("SSL NPN advertise callback added");
812821
}
813822
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
814-
SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
823+
SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, NULL);
815824
OSSL_Debug("SSL NPN select callback added");
816825
}
817826
#endif
@@ -827,7 +836,7 @@ ossl_sslctx_setup(VALUE self)
827836
OSSL_Debug("SSL ALPN values added");
828837
}
829838
if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) {
830-
SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
839+
SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, NULL);
831840
OSSL_Debug("SSL ALPN select callback added");
832841
}
833842

0 commit comments

Comments
 (0)