qc_cleanup(ctx.qc, /*have_lock=*/1);
/* Note: SSL_free calls OPENSSL_free(qc) for us */
- if (ctx.qc->listener != NULL)
+ /*
+ * Just because we have a listener doesn't mean we have a ref on it
+ * QUIC pre-creates user ssls to return to applications.
+ * Those don't hold a reference until they are accepted, so only drop
+ * the count if the application has accepted them
+ */
+ if (ctx.qc->accepted == 1 && ctx.qc->listener != NULL)
SSL_free(&ctx.qc->listener->obj.ssl);
if (ctx.qc->domain != NULL)
SSL_free(&ctx.qc->domain->obj.ssl);
qctx_unlock(&ctx);
+ qc->accepted = 1;
return &qc->obj.ssl;
err:
QCTX ctx;
SSL *conn_ssl = NULL;
QUIC_CHANNEL *new_ch = NULL;
+ QUIC_CONNECTION *qc;
int no_block = ((flags & SSL_ACCEPT_CONNECTION_NO_BLOCK) != 0);
if (!expect_quic_listener(ssl, &ctx))
*/
conn_ssl = ossl_quic_channel_get0_tls(new_ch);
conn_ssl = SSL_CONNECTION_GET_USER_SSL(SSL_CONNECTION_FROM_SSL(conn_ssl));
+ qc = (QUIC_CONNECTION *)conn_ssl;
+ qc->accepted = 1;
+
+ if (!SSL_up_ref(&ctx.ql->obj.ssl)) {
+ SSL_free(conn_ssl);
+ SSL_free(ossl_quic_channel_get0_tls(new_ch));
+ conn_ssl = NULL;
+ }
+
out:
qctx_unlock(&ctx);
return conn_ssl;
{
QUIC_CONNECTION *qc = NULL;
- if (!SSL_up_ref(&ql->obj.ssl)) {
- QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
- goto err;
- }
-
if ((qc = OPENSSL_zalloc(sizeof(*qc))) == NULL) {
QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
- SSL_free(&ql->obj.ssl);
goto err;
}
SSL_TYPE_QUIC_CONNECTION,
&ql->obj.ssl, NULL, NULL)) {
QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
- SSL_free(&ql->obj.ssl);
goto err;
}
ossl_quic_channel_get_peer_addr(ch, &qc->init_peer_addr); /* best effort */
+ qc->accepted = 0;
qc->listener = ql;
qc->engine = ql->engine;
qc->port = ql->port;
}
tls = ossl_ssl_connection_new_int(port->channel_ctx, user_ssl, TLS_method());
- if (tls == NULL || (tls_conn = SSL_CONNECTION_FROM_SSL(tls)) == NULL)
+ if (tls == NULL || (tls_conn = SSL_CONNECTION_FROM_SSL(tls)) == NULL) {
+ SSL_free(user_ssl);
return NULL;
+ }
/*
* If we got a user ssl, which will be embedded in a quic connection
if (!ql->obj.ssl.ctx->new_pending_conn_cb(ql->obj.ssl.ctx, user_ssl,
ql->obj.ssl.ctx->new_pending_conn_arg)) {
SSL_free(tls);
+ SSL_free(user_ssl);
+ qc->tls = NULL;
return NULL;
}
* And finally init the channel struct
*/
if (!ossl_quic_channel_init(ch)) {
- if (ch->tls == NULL)
- SSL_free(ch->tls);
+ SSL_free(ch->tls);
OPENSSL_free(ch);
return NULL;
}
{
QUIC_CHANNEL *ch;
SSL *tls;
+ SSL *user_ssl;
for (;;) {
ch = ossl_quic_port_pop_incoming(port);
break;
tls = ossl_quic_channel_get0_tls(ch);
- ossl_quic_channel_free(ch);
- SSL_free(tls);
+ /*
+ * The user ssl may or may not have been created via the
+ * get_conn_user_ssl callback in the QUIC stack. The
+ * differentiation being if the user_ssl pointer and tls pointer
+ * are different. If they are, then the user_ssl needs freeing here
+ * which sends us through ossl_quic_free, which then drops the actual
+ * ch->tls ref and frees the channel
+ */
+ user_ssl = SSL_CONNECTION_GET_USER_SSL(SSL_CONNECTION_FROM_SSL(tls));
+ if (user_ssl == tls) {
+ ossl_quic_channel_free(ch);
+ SSL_free(tls);
+ } else {
+ SSL_free(user_ssl);
+ }
}
}