* a QCSO with a default stream was passed);
* - whether a QSSO was passed (xso == NULL must not be used to determine this
* because it may be non-NULL when a QCSO is passed if that QCSO has a
- * default stream).
+ * default stream);
+ * - whether we are in "I/O context", meaning that non-normal errors can
+ * be reported via SSL_get_error() as well as via ERR. Functions such as
+ * SSL_read(), SSL_write() and SSL_do_handshake() are "I/O context"
+ * functions which are allowed to change the value returned by
+ * SSL_get_error. However, other functions (including functions which call
+ * SSL_do_handshake() implicitly) are not allowed to change the return value
+ * of SSL_get_error.
*/
struct qctx_st {
QUIC_CONNECTION *qc;
QUIC_XSO *xso;
- int is_stream;
+ int is_stream, in_io;
};
/*
*
* ctx should be NULL if the connection lock is not held.
*/
-static int quic_raise_non_normal_error(QCTX *ctx, int set_last_error,
+static int quic_raise_non_normal_error(QCTX *ctx,
const char *file,
int line,
const char *func,
va_list args;
if (ctx != NULL) {
- if (set_last_error && ctx->is_stream && ctx->xso != NULL)
+ if (ctx->in_io && ctx->is_stream && ctx->xso != NULL)
ctx->xso->last_error = SSL_ERROR_SSL;
- else if (set_last_error && !ctx->is_stream && ctx->qc != NULL)
+ else if (ctx->in_io && !ctx->is_stream && ctx->qc != NULL)
ctx->qc->last_error = SSL_ERROR_SSL;
if (reason == SSL_R_PROTOCOL_IS_SHUTDOWN && ctx->qc != NULL)
quic_raise_normal_error((ctx), (err))
#define QUIC_RAISE_NON_NORMAL_ERROR(ctx, reason, msg) \
- quic_raise_non_normal_error((ctx), 1, \
- OPENSSL_FILE, OPENSSL_LINE, \
- OPENSSL_FUNC, \
- (reason), \
- (msg))
-
-#define QUIC_RAISE_NON_IO_ERROR(ctx, reason, msg) \
- quic_raise_non_normal_error((ctx), 0, \
+ quic_raise_non_normal_error((ctx), \
OPENSSL_FILE, OPENSSL_LINE, \
OPENSSL_FUNC, \
(reason), \
ctx->is_stream = 0;
if (s == NULL)
- return QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_PASSED_NULL_PARAMETER, NULL);
+ return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_PASSED_NULL_PARAMETER, NULL);
switch (s->type) {
case SSL_TYPE_QUIC_CONNECTION:
ctx->qc = qc;
ctx->xso = qc->default_xso;
ctx->is_stream = 0;
+ ctx->in_io = 0;
return 1;
case SSL_TYPE_QUIC_XSO:
ctx->qc = xso->conn;
ctx->xso = xso;
ctx->is_stream = 1;
+ ctx->in_io = 0;
return 1;
default:
- return QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
+ return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
}
}
*/
QUIC_ACQUIRES_LOCK
static int ossl_unused expect_quic_with_stream_lock(const SSL *s, int remote_init,
- QCTX *ctx)
+ int in_io, QCTX *ctx)
{
if (!expect_quic(s, ctx))
return 0;
+ ctx->in_io = in_io;
quic_lock(ctx->qc);
if (ctx->xso == NULL && remote_init >= 0) {
}
if (ctx->xso == NULL) {
- QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_NO_STREAM, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_NO_STREAM, NULL);
goto err;
}
* Like expect_quic(), but fails if called on a QUIC_XSO. ctx->xso may still
* be non-NULL if the QCSO has a default stream.
*/
-static int ossl_unused expect_quic_conn_only(const SSL *s, QCTX *ctx)
+static int ossl_unused expect_quic_conn_only(const SSL *s, int in_io, QCTX *ctx)
{
if (!expect_quic(s, ctx))
return 0;
+ ctx->in_io = in_io;
if (ctx->is_stream)
- return QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_CONN_USE_ONLY, NULL);
+ return QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_CONN_USE_ONLY, NULL);
return 1;
}
qc = OPENSSL_zalloc(sizeof(*qc));
if (qc == NULL) {
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
goto err;
}
ssl_base = &qc->ssl;
if (!ossl_ssl_init(ssl_base, ctx, ctx->method, SSL_TYPE_QUIC_CONNECTION)) {
ssl_base = NULL;
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
goto err;
}
qc->tls = ossl_ssl_connection_new_int(ctx, TLS_method());
if (qc->tls == NULL || (sc = SSL_CONNECTION_FROM_SSL(qc->tls)) == NULL) {
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
goto err;
}
#if defined(OPENSSL_THREADS)
if ((qc->mutex = ossl_crypto_mutex_new()) == NULL) {
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
goto err;
}
#endif
/* Cannot enable blocking mode if we do not have pollable FDs. */
if (blocking != 0 &&
(!ctx.qc->can_poll_net_rbio || !ctx.qc->can_poll_net_wbio))
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_UNSUPPORTED, NULL);
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_UNSUPPORTED, NULL);
if (!ctx.is_stream) {
/*
return 0;
if (ctx.qc->started)
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
NULL);
if (peer_addr == NULL) {
return 0;
if (desc == NULL || ctx.qc->net_rbio == NULL)
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
NULL);
return BIO_get_rpoll_descriptor(ctx.qc->net_rbio, desc);
return 0;
if (desc == NULL || ctx.qc->net_wbio == NULL)
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
NULL);
return BIO_get_wpoll_descriptor(ctx.qc->net_wbio, desc);
return -1;
if (ctx.is_stream) {
- QUIC_RAISE_NON_IO_ERROR(&ctx, SSL_R_CONN_USE_ONLY, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, SSL_R_CONN_USE_ONLY, NULL);
return -1;
}
qc->ch = ossl_quic_channel_new(&args);
if (qc->ch == NULL) {
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
return 0;
}
if (BIO_ADDR_family(&qc->init_peer_addr) == AF_UNSPEC) {
/* Peer address must have been set. */
- QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET, NULL);
return -1; /* Non-protocol error */
}
if (qc->as_server != qc->as_server_state) {
- QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL);
return -1; /* Non-protocol error */
}
if (qc->net_rbio == NULL || qc->net_wbio == NULL) {
/* Need read and write BIOs. */
- QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_BIO_NOT_SET, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_BIO_NOT_SET, NULL);
return -1; /* Non-protocol error */
}
* non-blocking mode, which is fine.
*/
if (!ensure_channel_started(qc)) {
- QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
return -1; /* Non-protocol error */
}
QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
return 0; /* Shutdown before completion */
} else if (ret <= 0) {
- QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
return -1; /* Non-protocol error */
}
if (!expect_quic(s, &ctx))
return 0;
+ ctx.in_io = 1;
quic_lock(ctx.qc);
ret = quic_do_handshake(&ctx);
*/
qc_set_default_xso(qc, create_xso_from_stream(qc, qs), /*touch=*/0);
if (qc->default_xso == NULL)
- return QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
+ return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
qc_touch_default_xso(qc); /* inhibits default XSO */
return 1;
QUIC_XSO *xso = NULL;
if ((xso = OPENSSL_zalloc(sizeof(*xso))) == NULL) {
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_CRYPTO_LIB, NULL);
goto err;
}
if (!ossl_ssl_init(&xso->ssl, qc->ssl.ctx, qc->ssl.method, SSL_TYPE_QUIC_XSO)) {
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
goto err;
}
/* XSO refs QC */
if (!SSL_up_ref(&qc->ssl)) {
- QUIC_RAISE_NON_IO_ERROR(NULL, ERR_R_SSL_LIB, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_SSL_LIB, NULL);
goto err;
}
quic_lock(qc);
if (!quic_mutation_allowed(qc, /*req_active=*/0)) {
- QUIC_RAISE_NON_IO_ERROR(ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
goto err;
}
qs = ossl_quic_channel_new_stream_local(qc->ch, is_uni);
if (qs == NULL) {
- QUIC_RAISE_NON_IO_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
goto err;
}
{
QCTX ctx;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return NULL;
return quic_conn_stream_new(&ctx, flags, /*need_lock=*/1);
*written = 0;
- if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, &ctx))
+ if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, /*io=*/1, &ctx))
return 0;
partial_write = ((ctx.xso->ssl_mode & SSL_MODE_ENABLE_PARTIAL_WRITE) != 0);
if (!expect_quic(s, &ctx))
return 0;
+ ctx.in_io = 1;
quic_lock(ctx.qc);
if (!quic_mutation_allowed(ctx.qc, /*req_active=*/0)) {
quic_lock(ctx.qc);
if (ctx.xso == NULL) {
- QUIC_RAISE_NON_IO_ERROR(&ctx, SSL_R_NO_STREAM, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, SSL_R_NO_STREAM, NULL);
goto out;
}
if (ctx.xso->stream == NULL
|| !ossl_quic_stream_has_recv_buffer(ctx.xso->stream)) {
- QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_INTERNAL_ERROR, NULL);
goto out;
}
QUIC_STREAM *qs;
int err;
- if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, &ctx))
+ if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, /*io=*/0, &ctx))
return 0;
qs = ctx.xso->stream;
QCTX ctx;
uint64_t id;
- if (!expect_quic_with_stream_lock(s, /*remote_init=*/-1, &ctx))
+ if (!expect_quic_with_stream_lock(s, /*remote_init=*/-1, /*io=*/0, &ctx))
return UINT64_MAX;
id = ctx.xso->stream->id;
{
QCTX ctx;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return 0;
quic_lock(ctx.qc);
if (ctx.qc->default_xso_created) {
quic_unlock(ctx.qc);
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
"too late to change default stream mode");
}
break;
default:
quic_unlock(ctx.qc);
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
"bad default stream type");
}
QCTX ctx;
QUIC_XSO *xso = NULL;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return NULL;
quic_lock(ctx.qc);
QUIC_XSO *xso;
int nref;
- if (!expect_quic_conn_only(conn, &ctx))
+ if (!expect_quic_conn_only(conn, /*io=*/0, &ctx))
return 0;
if (stream == NULL || stream->type != SSL_TYPE_QUIC_XSO)
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_NULL_PARAMETER,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_NULL_PARAMETER,
"stream to attach must be a valid QUIC stream");
xso = (QUIC_XSO *)stream;
if (ctx.qc->default_xso != NULL) {
quic_unlock(ctx.qc);
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
"connection already has a default stream");
}
*/
if (!CRYPTO_GET_REF(&xso->ssl.references, &nref)) {
quic_unlock(ctx.qc);
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_INTERNAL_ERROR,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_INTERNAL_ERROR,
"ref");
}
if (nref != 1) {
quic_unlock(ctx.qc);
- return QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
+ return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT,
"stream being attached must have "
"only 1 reference");
}
int ret = 1;
QCTX ctx;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return 0;
quic_lock(ctx.qc);
break;
default:
- QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL);
ret = 0;
break;
}
QUIC_XSO *xso;
OSSL_RTT_INFO rtt_info;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return NULL;
quic_lock(ctx.qc);
if (qc_get_effective_incoming_stream_policy(ctx.qc)
== SSL_INCOMING_STREAM_POLICY_REJECT) {
- QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, NULL);
goto out;
}
QCTX ctx;
size_t v;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return 0;
quic_lock(ctx.qc);
uint64_t error_code;
int ok, err;
- if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/0, &ctx))
+ if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/0, /*io=*/0, &ctx))
return 0;
qsm = ossl_quic_channel_get_qsm(ctx.qc->ch);
QCTX ctx;
int state;
- if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, &ctx))
+ if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, /*io=*/0, &ctx))
return SSL_STREAM_STATE_NONE;
quic_classify_stream(ctx.qc, ctx.xso->stream, is_write, &state, NULL);
QCTX ctx;
int state;
- if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, &ctx))
+ if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, /*io=*/0, &ctx))
return -1;
quic_classify_stream(ctx.qc, ctx.xso->stream, /*is_write=*/0,
int ret = 0;
QCTX ctx;
- if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, &ctx))
+ if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, /*io=*/0, &ctx))
return 0;
if (!ossl_quic_stream_has_send(ctx.xso->stream)) {
/* Called on a unidirectional receive-only stream - error. */
- QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, NULL);
goto out;
}
}
if (!ossl_quic_sstream_set_buffer_size(ctx.xso->stream->sstream, size)) {
- QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_INTERNAL_ERROR, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_INTERNAL_ERROR, NULL);
goto out;
}
QCTX ctx;
const QUIC_TERMINATE_CAUSE *tc;
- if (!expect_quic_conn_only(ssl, &ctx))
+ if (!expect_quic_conn_only(ssl, /*io=*/0, &ctx))
return -1;
tc = ossl_quic_channel_get_terminate_cause(ctx.qc->ch);
{
QCTX ctx;
- if (!expect_quic_conn_only(ssl, &ctx))
+ if (!expect_quic_conn_only(ssl, /*io=*/0, &ctx))
return 0;
switch (update_type) {
break;
default:
- QUIC_RAISE_NON_IO_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL);
return 0;
}
/* Attempt to perform a TXKU. */
if (!ossl_quic_channel_trigger_txku(ctx.qc->ch)) {
- QUIC_RAISE_NON_IO_ERROR(&ctx, SSL_R_TOO_MANY_KEY_UPDATES, NULL);
+ QUIC_RAISE_NON_NORMAL_ERROR(&ctx, SSL_R_TOO_MANY_KEY_UPDATES, NULL);
quic_unlock(ctx.qc);
return 0;
}
{
QCTX ctx;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return 0;
switch (cmd) {
{
QCTX ctx;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_conn_only(s, /*io=*/0, &ctx))
return NULL;
return ctx.qc->ch;