case DTLS_CTRL_HANDLE_TIMEOUT: /* DTLSv1_handle_timeout */
/* For legacy compatibility with DTLS calls. */
return ossl_quic_handle_events(s) == 1 ? 1 : -1;
+
+ /* Mask ctrls we shouldn't support for QUIC. */
+ case SSL_CTRL_GET_READ_AHEAD:
+ case SSL_CTRL_SET_READ_AHEAD:
+ case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+ case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
+ case SSL_CTRL_SET_MAX_PIPELINES:
+ return 0;
+
default:
- /* Probably a TLS related ctrl. Defer to our internal SSL object */
- return SSL_ctrl(ctx.qc->tls, cmd, larg, parg);
+ /*
+ * Probably a TLS related ctrl. Send back to the frontend SSL_ctrl
+ * implementation. Either SSL_ctrl will handle it itself by direct
+ * access into handshake layer state, or failing that, it will be passed
+ * to the handshake layer via the SSL_METHOD vtable. If the ctrl is not
+ * supported by anything, the handshake layer's ctrl method will finally
+ * return 0.
+ */
+ return ossl_ctrl_internal(&ctx.qc->ssl, cmd, larg, parg, /*no_quic=*/1);
}
}
}
long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
+{
+ return ossl_ctrl_internal(s, cmd, larg, parg, /*no_quic=*/0);
+}
+
+long ossl_ctrl_internal(SSL *s, int cmd, long larg, void *parg, int no_quic)
{
long l;
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
- /* TODO(QUIC FUTURE): Special handling for some ctrls will be needed */
- if (sc == NULL)
- return 0;
+ /*
+ * Routing of ctrl calls for QUIC is a little counterintuitive:
+ *
+ * - Firstly (no_quic=0), we pass the ctrl directly to our QUIC
+ * implementation in case it wants to handle the ctrl specially.
+ *
+ * - If our QUIC implementation does not care about the ctrl, it
+ * will reenter this function with no_quic=1 and we will try to handle
+ * it directly using the QCSO SSL object stub (not the handshake layer
+ * SSL object). This is important for e.g. the version configuration
+ * ctrls below, which must use s->defltmeth (and not sc->defltmeth).
+ *
+ * - If we don't handle a ctrl here specially, then processing is
+ * redirected to the handshake layer SSL object.
+ */
+ if (!no_quic && IS_QUIC(s))
+ return s->method->ssl_ctrl(s, cmd, larg, parg);
switch (cmd) {
case SSL_CTRL_GET_READ_AHEAD:
- if (IS_QUIC(s))
- return 0;
return RECORD_LAYER_get_read_ahead(&sc->rlayer);
case SSL_CTRL_SET_READ_AHEAD:
- if (IS_QUIC(s))
- return 0;
l = RECORD_LAYER_get_read_ahead(&sc->rlayer);
RECORD_LAYER_set_read_ahead(&sc->rlayer, larg);
return l;
sc->max_cert_list = (size_t)larg;
return l;
case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
- if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH || IS_QUIC(s))
+ if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;
#ifndef OPENSSL_NO_KTLS
if (sc->wbio != NULL && BIO_get_ktls_send(sc->wbio))
sc->rlayer.wrlmethod->set_max_frag_len(sc->rlayer.wrl, larg);
return 1;
case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
- if ((size_t)larg > sc->max_send_fragment || larg == 0 || IS_QUIC(s))
+ if ((size_t)larg > sc->max_send_fragment || larg == 0)
return 0;
sc->split_send_fragment = larg;
return 1;
case SSL_CTRL_SET_MAX_PIPELINES:
- if (larg < 1 || larg > SSL_MAX_PIPELINES || IS_QUIC(s))
+ if (larg < 1 || larg > SSL_MAX_PIPELINES)
return 0;
sc->max_pipelines = larg;
if (sc->rlayer.rrlmethod->set_max_pipelines != NULL)
case SSL_CTRL_GET_MAX_PROTO_VERSION:
return sc->max_proto_version;
default:
- return s->method->ssl_ctrl(s, cmd, larg, parg);
+ if (IS_QUIC(s))
+ return SSL_ctrl((SSL *)sc, cmd, larg, parg);
+ else
+ return s->method->ssl_ctrl(s, cmd, larg, parg);
}
}