Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion iocore/net/P_QUICNetVConnection_quiche.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
#include "P_UDPNet.h"
#include "P_ALPNSupport.h"
#include "TLSBasicSupport.h"
#include "TLSSessionResumptionSupport.h"
#include "TLSSNISupport.h"
#include "TLSCertSwitchSupport.h"
#include "tscore/ink_apidefs.h"
#include "tscore/List.h"

Expand All @@ -57,6 +60,9 @@ class QUICNetVConnection : public UnixNetVConnection,
public QUICConnection,
public RefCountObj,
public ALPNSupport,
public TLSSNISupport,
public TLSSessionResumptionSupport,
public TLSCertSwitchSupport,
public TLSBasicSupport
{
using super = UnixNetVConnection; ///< Parent type.
Expand All @@ -66,7 +72,7 @@ class QUICNetVConnection : public UnixNetVConnection,
~QUICNetVConnection();
void init(QUICVersion version, QUICConnectionId peer_cid, QUICConnectionId original_cid, UDPConnection *, QUICPacketHandler *);
void init(QUICVersion version, QUICConnectionId peer_cid, QUICConnectionId original_cid, QUICConnectionId first_cid,
QUICConnectionId retry_cid, UDPConnection *, quiche_conn *, QUICPacketHandler *, QUICConnectionTable *ctable);
QUICConnectionId retry_cid, UDPConnection *, quiche_conn *, QUICPacketHandler *, QUICConnectionTable *ctable, SSL *);

// Event handlers
int acceptEvent(int event, Event *e);
Expand All @@ -88,13 +94,16 @@ class QUICNetVConnection : public UnixNetVConnection,
VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner = false) override;
int connectUp(EThread *t, int fd) override;
int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs) override;
bool getSSLHandShakeComplete() const override;

// NetEvent
virtual void net_read_io(NetHandler *nh, EThread *lthread) override;

// NetVConnection
int populate_protocol(std::string_view *results, int n) const override;
const char *protocol_contains(std::string_view tag) const override;
const char *get_server_name() const override;
bool support_sni() const override;

// QUICConnection
QUICStreamManager *stream_manager() override;
Expand Down Expand Up @@ -144,7 +153,19 @@ class QUICNetVConnection : public UnixNetVConnection,
SSL *_get_ssl_object() const override;
ssl_curve_id _get_tls_curve() const override;

// TLSSNISupport
void _fire_ssl_servername_event() override;

// TLSSessionResumptionSupport
const IpEndpoint &_getLocalEndpoint() override;

// TLSCertSwitchSupport
bool _isTryingRenegotiation() const override;
shared_SSL_CTX _lookupContextByName(const std::string &servername, SSLCertContextType ctxType) override;
shared_SSL_CTX _lookupContextByIP() override;

private:
SSL *_ssl;
QUICConfig::scoped_config _quic_config;

QUICConnectionId _peer_quic_connection_id; // dst cid in local
Expand All @@ -159,6 +180,9 @@ class QUICNetVConnection : public UnixNetVConnection,
quiche_conn *_quiche_con = nullptr;
QUICConnectionTable *_ctable = nullptr;

void _bindSSLObject();
void _unbindSSLObject();

void _schedule_packet_write_ready(bool delay = false);
void _unschedule_packet_write_ready();
void _close_packet_write_ready(Event *data);
Expand Down
71 changes: 0 additions & 71 deletions iocore/net/QUICMultiCertConfigLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,77 +109,6 @@ QUICMultiCertConfigLoader::_set_npn_callback(SSL_CTX *ctx)
return true;
}

void
QUICMultiCertConfigLoader::_set_handshake_callbacks(SSL_CTX *ssl_ctx)
{
SSL_CTX_set_cert_cb(ssl_ctx, QUICMultiCertConfigLoader::ssl_cert_cb, nullptr);
SSL_CTX_set_tlsext_servername_callback(ssl_ctx, QUICMultiCertConfigLoader::ssl_sni_cb);

// Set client hello callback if needed
// SSL_CTX_set_client_hello_cb(ctx, QUIC::ssl_client_hello_cb, nullptr);
}

int
QUICMultiCertConfigLoader::ssl_sni_cb(SSL *ssl, int * /*ad*/, void * /*arg*/)
{
// XXX: add SNIConfig support ?
// XXX: add TRANSPORT_BLIND_TUNNEL support ?
return 1;
}

int
QUICMultiCertConfigLoader::ssl_cert_cb(SSL *ssl, void * /*arg*/)
{
shared_SSL_CTX ctx = nullptr;
SSLCertContext *cc = nullptr;
QUICCertConfig::scoped_config lookup;
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
QUICConnection *qc = static_cast<QUICConnection *>(SSL_get_ex_data(ssl, QUIC::ssl_quic_qc_index));

if (servername == nullptr) {
servername = "";
}
QUICGlobalQCDebug(qc, "SNI=%s", servername);

// The incoming SSL_CTX is either the one mapped from the inbound IP address or the default one. If we
// don't find a name-based match at this point, we *do not* want to mess with the context because we've
// already made a best effort to find the best match.
if (likely(servername)) {
cc = lookup->find(const_cast<char *>(servername));
if (cc && cc->getCtx()) {
ctx = cc->getCtx();
}
}

// If there's no match on the server name, try to match on the peer address.
if (ctx == nullptr) {
QUICFiveTuple five_tuple = qc->five_tuple();
IpEndpoint ip = five_tuple.destination();
cc = lookup->find(ip);

if (cc && cc->getCtx()) {
ctx = cc->getCtx();
}
}

bool found = true;
if (ctx != nullptr) {
SSL_set_SSL_CTX(ssl, ctx.get());
} else {
found = false;
}

SSL_CTX *verify_ctx = nullptr;
verify_ctx = SSL_get_SSL_CTX(ssl);
QUICGlobalQCDebug(qc, "%s SSL_CTX %p for requested name '%s'", found ? "found" : "using", verify_ctx, servername);

if (verify_ctx == nullptr) {
return 0;
}

return 1;
}

const char *
QUICMultiCertConfigLoader::_debug_tag() const
{
Expand Down
4 changes: 0 additions & 4 deletions iocore/net/QUICMultiCertConfigLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,8 @@ class QUICMultiCertConfigLoader : public SSLMultiCertConfigLoader

private:
const char *_debug_tag() const override;
virtual void _set_handshake_callbacks(SSL_CTX *ssl_ctx) override;
virtual bool _setup_session_cache(SSL_CTX *ctx) override;
virtual bool _set_cipher_suites_for_legacy_versions(SSL_CTX *ctx) override;
virtual bool _set_info_callback(SSL_CTX *ctx) override;
virtual bool _set_npn_callback(SSL_CTX *ctx) override;

static int ssl_cert_cb(SSL *ssl, void *arg);
static int ssl_sni_cb(SSL *ssl, int *ad, void *arg);
};
8 changes: 0 additions & 8 deletions iocore/net/QUICNetProcessor_quiche.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,11 @@ QUICNetProcessor::start(int, size_t stacksize)
// QUICInitializeLibrary();
QUICConfig::startup();
QUICCertConfig::startup();
QUICCertConfig::scoped_config certs;
QUICConfig::scoped_config params;
SSLCertContext *context = certs->get(0);

quiche_enable_debug_logging(debug_log, NULL);
this->_quiche_config = quiche_config_new(QUICHE_PROTOCOL_VERSION);
quiche_config_set_application_protos(this->_quiche_config, (uint8_t *)"\02h3\x05h3-29\x05hq-29\x05h3-27\x05hq-27", 27);
if (context->userconfig->cert != nullptr) {
quiche_config_load_cert_chain_from_pem_file(this->_quiche_config, context->userconfig->cert);
}
if (context->userconfig->key != nullptr) {
quiche_config_load_priv_key_from_pem_file(this->_quiche_config, context->userconfig->key);
}

quiche_config_set_max_idle_timeout(this->_quiche_config, params->no_activity_timeout_in());
quiche_config_set_max_recv_udp_payload_size(this->_quiche_config, params->get_max_recv_udp_payload_size_in());
Expand Down
104 changes: 101 additions & 3 deletions iocore/net/QUICNetVConnection_quiche.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@

#include "P_QUICNetVConnection_quiche.h"
#include "P_QUICPacketHandler_quiche.h"
#include "QUICMultiCertConfigLoader.h"
#include "quic/QUICStream_quiche.h"
#include "quic/QUICGlobals.h"
#include <quiche.h>

static constexpr ink_hrtime WRITE_READY_INTERVAL = HRTIME_MSECONDS(2);
Expand All @@ -46,7 +48,7 @@ QUICNetVConnection::init(QUICVersion version, QUICConnectionId peer_cid, QUICCon
void
QUICNetVConnection::init(QUICVersion version, QUICConnectionId peer_cid, QUICConnectionId original_cid, QUICConnectionId first_cid,
QUICConnectionId retry_cid, UDPConnection *udp_con, quiche_conn *quiche_con,
QUICPacketHandler *packet_handler, QUICConnectionTable *ctable)
QUICPacketHandler *packet_handler, QUICConnectionTable *ctable, SSL *ssl)
{
SET_HANDLER((NetVConnHandler)&QUICNetVConnection::acceptEvent);
this->_udp_con = udp_con;
Expand All @@ -61,6 +63,10 @@ QUICNetVConnection::init(QUICVersion version, QUICConnectionId peer_cid, QUICCon
this->_ctable->insert(this->_quic_connection_id, this);
this->_ctable->insert(this->_original_quic_connection_id, this);
}

this->_ssl = ssl;
SSL_set_ex_data(ssl, QUIC::ssl_quic_qc_index, static_cast<QUICConnection *>(this));
this->_bindSSLObject();
}

void
Expand Down Expand Up @@ -114,6 +120,7 @@ QUICNetVConnection::free(EThread *t)
this->_context->trigger(QUICContext::CallbackEvent::CONNECTION_CLOSE);
ALPNSupport::clear();
TLSBasicSupport::clear();
TLSCertSwitchSupport::_clear();

this->_packet_handler->close_connection(this);
this->_packet_handler = nullptr;
Expand Down Expand Up @@ -489,6 +496,32 @@ QUICNetVConnection::load_buffer_and_write(int64_t towrite, MIOBufferAccessor &bu
return 0;
}

bool
QUICNetVConnection::getSSLHandShakeComplete() const
{
return quiche_conn_is_established(this->_quiche_con);
}

void
QUICNetVConnection::_bindSSLObject()
{
TLSBasicSupport::bind(this->_ssl, this);
ALPNSupport::bind(this->_ssl, this);
TLSSessionResumptionSupport::bind(this->_ssl, this);
TLSSNISupport::bind(this->_ssl, this);
TLSCertSwitchSupport::bind(this->_ssl, this);
}

void
QUICNetVConnection::_unbindSSLObject()
{
TLSBasicSupport::unbind(this->_ssl);
ALPNSupport::unbind(this->_ssl);
TLSSessionResumptionSupport::unbind(this->_ssl);
TLSSNISupport::unbind(this->_ssl);
TLSCertSwitchSupport::unbind(this->_ssl);
}

void
QUICNetVConnection::_schedule_packet_write_ready(bool delay)
{
Expand Down Expand Up @@ -632,14 +665,79 @@ QUICNetVConnection::protocol_contains(std::string_view tag) const
return "";
}

const char *
QUICNetVConnection::get_server_name() const
{
return get_sni_server_name();
}

bool
QUICNetVConnection::support_sni() const
{
return true;
}

SSL *
QUICNetVConnection::_get_ssl_object() const
{
return nullptr;
return this->_ssl;
}

ssl_curve_id
QUICNetVConnection::_get_tls_curve() const
{
return 0;
if (getSSLSessionCacheHit()) {
return getSSLCurveNID();
} else {
return SSLGetCurveNID(this->_ssl);
}
}

void
QUICNetVConnection::_fire_ssl_servername_event()
{
}

const IpEndpoint &
QUICNetVConnection::_getLocalEndpoint()
{
return this->local_addr;
}

bool
QUICNetVConnection::_isTryingRenegotiation() const
{
// Renegotiation is not allowed on QUIC (TLS 1.3) connections.
// If handshake is completed when this function is called, that should be unallowed attempt of renegotiation.
return this->getSSLHandShakeComplete();
}

shared_SSL_CTX
QUICNetVConnection::_lookupContextByName(const std::string &servername, SSLCertContextType ctxType)
{
shared_SSL_CTX ctx = nullptr;
QUICCertConfig::scoped_config lookup;
SSLCertContext *cc = lookup->find(servername, ctxType);

if (cc && cc->getCtx()) {
ctx = cc->getCtx();
}

return ctx;
}

shared_SSL_CTX
QUICNetVConnection::_lookupContextByIP()
{
shared_SSL_CTX ctx = nullptr;
QUICCertConfig::scoped_config lookup;
QUICFiveTuple five_tuple = this->five_tuple();
IpEndpoint ip = five_tuple.destination();
SSLCertContext *cc = lookup->find(ip);

if (cc && cc->getCtx()) {
ctx = cc->getCtx();
}

return ctx;
}
11 changes: 8 additions & 3 deletions iocore/net/QUICPacketHandler_quiche.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "P_QUICNetProcessor_quiche.h"
#include "P_QUICClosedConCollector.h"
#include "quic/QUICConnectionTable.h"
#include "QUICMultiCertConfigLoader.h"
#include <quiche.h>

static constexpr char debug_tag[] = "quic_sec";
Expand Down Expand Up @@ -274,10 +275,14 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet)
}

QUICConnectionId new_cid;
quiche_conn *quiche_con = quiche_accept(

QUICCertConfig::scoped_config server_cert;
SSL *ssl = SSL_new(server_cert->defaultContext());

quiche_conn *quiche_con = quiche_conn_new_with_tls(
new_cid, new_cid.length(), retry_token.original_dcid(), retry_token.original_dcid().length(), &udp_packet->to.sa,
udp_packet->to.isIp4() ? sizeof(udp_packet->to.sin) : sizeof(udp_packet->to.sin6), &udp_packet->from.sa,
udp_packet->from.isIp4() ? sizeof(udp_packet->from.sin) : sizeof(udp_packet->from.sin6), &this->_quiche_config);
udp_packet->from.isIp4() ? sizeof(udp_packet->from.sin) : sizeof(udp_packet->from.sin6), &this->_quiche_config, ssl, true);

if (params->get_qlog_file_base_name() != nullptr) {
char qlog_filepath[PATH_MAX];
Expand All @@ -296,7 +301,7 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet)
// vc->init(version, peer_cid, original_cid, ocid_in_retry_token, rcid_in_retry_token, udp_packet->getConnection(), this,
// &this->_ctable);
vc->init(version, peer_cid, new_cid, QUICConnectionId::ZERO(), QUICConnectionId::ZERO(), udp_packet->getConnection(),
quiche_con, this, &this->_ctable);
quiche_con, this, &this->_ctable, ssl);
vc->id = net_next_connection_number();
vc->con.move(con);
vc->submit_time = Thread::get_hrtime();
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/timeout/active_timeout.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
tr3.Processes.Default.Command = 'curl -k -i --http2 https://127.0.0.1:{0}/file'.format(ts.Variables.ssl_port)
tr3.Processes.Default.Streams.stdout = Testers.ContainsExpression("Activity Timeout", "Request should fail with active timeout")

if Condition.HasATSFeature('TS_USE_QUIC') and Condition.HasCurlFeature('http3'):
if Condition.HasATSFeature('TS_HAS_QUICHE') and Condition.HasCurlFeature('http3'):
tr4 = Test.AddTestRun("tr")
tr4.Processes.Default.Command = 'curl -k -i --http3 https://127.0.0.1:{0}/file'.format(ts.Variables.ssl_port)
tr4.Processes.Default.Streams.stdout = Testers.ContainsExpression("Activity Timeout", "Request should fail with active timeout")