mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-12 14:57:20 +00:00
[client/idd] network: allow unencrypted 1-RTT payloads
Expose the insecure MsQuic draft API and add an opt-in setting on both peers. Query the negotiated state after connection establishment so one-sided opt-in remains encrypted and is logged accurately.
This commit is contained in:
@@ -37,6 +37,10 @@ endif()
|
||||
|
||||
add_library(transport_Network STATIC ${TRANSPORT_NETWORK_SOURCES})
|
||||
|
||||
target_compile_definitions(transport_Network PRIVATE
|
||||
QUIC_API_ENABLE_INSECURE_FEATURES=1
|
||||
)
|
||||
|
||||
target_include_directories(transport_Network PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src
|
||||
)
|
||||
|
||||
@@ -213,6 +213,7 @@ struct NetworkConnection
|
||||
uint16_t port;
|
||||
char * password;
|
||||
char * endpoint;
|
||||
bool allowUnencrypted;
|
||||
|
||||
NetworkKnownHosts * knownHosts;
|
||||
NetworkTrustPromptFn trustPrompt;
|
||||
@@ -2922,8 +2923,28 @@ static QUIC_STATUS QUIC_API networkConnectionCallback(HQUIC handle,
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
HQUIC stream = NULL;
|
||||
QUIC_STATUS status = this->api->StreamOpen(handle,
|
||||
BOOLEAN encryptionDisabled = FALSE;
|
||||
uint32_t encryptionDisabledLength = sizeof(encryptionDisabled);
|
||||
QUIC_STATUS status = this->api->GetParam(handle,
|
||||
QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION,
|
||||
&encryptionDisabledLength, &encryptionDisabled);
|
||||
if (QUIC_FAILED(status))
|
||||
{
|
||||
DEBUG_ERROR("Failed to query 1-RTT encryption for %s: 0x%08x",
|
||||
this->endpoint, (unsigned)status);
|
||||
networkConnectionFail(this, LG_TRANSPORT_ERROR);
|
||||
this->api->ConnectionShutdown(handle,
|
||||
QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT, 0);
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DEBUG_INFO("Network connection to %s established in %s mode "
|
||||
"(%s 1-RTT payloads)", this->endpoint,
|
||||
encryptionDisabled ? "insecure" : "secure",
|
||||
encryptionDisabled ? "unencrypted" : "encrypted");
|
||||
|
||||
HQUIC stream = NULL;
|
||||
status = this->api->StreamOpen(handle,
|
||||
QUIC_STREAM_OPEN_FLAG_NONE, networkStreamCallback, this, &stream);
|
||||
if (QUIC_FAILED(status))
|
||||
{
|
||||
@@ -3585,15 +3606,16 @@ bool networkConnectionCreate(NetworkConnection ** result,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
this->port = params->port;
|
||||
this->knownHosts = params->knownHosts;
|
||||
this->trustPrompt = params->trustPrompt;
|
||||
this->trustCancel = params->trustCancel;
|
||||
this->packet = params->packet;
|
||||
this->state = params->state;
|
||||
this->sendReady = params->sendReady;
|
||||
this->datagramLost = params->datagramLost;
|
||||
this->opaque = params->opaque;
|
||||
this->port = params->port;
|
||||
this->allowUnencrypted = params->allowUnencrypted;
|
||||
this->knownHosts = params->knownHosts;
|
||||
this->trustPrompt = params->trustPrompt;
|
||||
this->trustCancel = params->trustCancel;
|
||||
this->packet = params->packet;
|
||||
this->state = params->state;
|
||||
this->sendReady = params->sendReady;
|
||||
this->datagramLost = params->datagramLost;
|
||||
this->opaque = params->opaque;
|
||||
|
||||
this->connectEvent = lgCreateEvent(false, 0);
|
||||
this->closeEvent = lgCreateEvent(false, 0);
|
||||
@@ -3863,6 +3885,26 @@ LG_TransportStatus networkConnectionConnect(NetworkConnection * this,
|
||||
return LG_TRANSPORT_ERROR;
|
||||
}
|
||||
|
||||
if (this->allowUnencrypted)
|
||||
{
|
||||
const BOOLEAN disableEncryption = TRUE;
|
||||
status = this->api->SetParam(this->connection,
|
||||
QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION,
|
||||
sizeof(disableEncryption), &disableEncryption);
|
||||
if (QUIC_FAILED(status))
|
||||
{
|
||||
DEBUG_ERROR("Failed to allow unencrypted 1-RTT payloads for %s: "
|
||||
"0x%08x", this->endpoint, (unsigned)status);
|
||||
this->api->ConnectionClose(this->connection);
|
||||
this->connection = NULL;
|
||||
LG_LOCK(this->lock);
|
||||
this->connecting = false;
|
||||
this->connectStatus = LG_TRANSPORT_ERROR;
|
||||
LG_UNLOCK(this->lock);
|
||||
return LG_TRANSPORT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
status = this->api->ConnectionStart(this->connection, this->configuration,
|
||||
QUIC_ADDRESS_FAMILY_UNSPEC, this->address, this->port);
|
||||
if (QUIC_FAILED(status))
|
||||
|
||||
@@ -59,6 +59,7 @@ typedef struct NetworkConnectionParams
|
||||
const char * address;
|
||||
uint16_t port;
|
||||
const char * password;
|
||||
bool allowUnencrypted;
|
||||
NetworkKnownHosts * knownHosts;
|
||||
NetworkTrustPromptFn trustPrompt;
|
||||
NetworkTrustCancelFn trustCancel;
|
||||
|
||||
@@ -246,6 +246,13 @@ static void networkSetup(void)
|
||||
.sensitive = true,
|
||||
.value.x_string = NULL,
|
||||
},
|
||||
{
|
||||
.module = "network",
|
||||
.name = "allowUnencrypted",
|
||||
.description = "Allow unencrypted 1-RTT network payloads",
|
||||
.type = OPTION_TYPE_BOOL,
|
||||
.value.x_bool = false,
|
||||
},
|
||||
{
|
||||
.module = "network",
|
||||
.name = "forgetCertificate",
|
||||
@@ -555,20 +562,21 @@ static bool networkCreate(LG_Transport ** result)
|
||||
|
||||
const NetworkConnectionParams params =
|
||||
{
|
||||
.address = address,
|
||||
.port = port,
|
||||
.password = option_get_string("network", "password"),
|
||||
.knownHosts = &this->knownHosts,
|
||||
.trustPrompt = networkTrustPrompt,
|
||||
.trustCancel = networkCancelTrustPrompt,
|
||||
.packet = networkPacket,
|
||||
.state = networkConnectionState,
|
||||
.sendReady = networkSendReady,
|
||||
.datagramLost = networkDatagramLost,
|
||||
.capabilities = NETWORK_CAPABILITIES,
|
||||
.capabilityCount = sizeof(NETWORK_CAPABILITIES) /
|
||||
.address = address,
|
||||
.port = port,
|
||||
.password = option_get_string("network", "password"),
|
||||
.allowUnencrypted = option_get_bool("network", "allowUnencrypted"),
|
||||
.knownHosts = &this->knownHosts,
|
||||
.trustPrompt = networkTrustPrompt,
|
||||
.trustCancel = networkCancelTrustPrompt,
|
||||
.packet = networkPacket,
|
||||
.state = networkConnectionState,
|
||||
.sendReady = networkSendReady,
|
||||
.datagramLost = networkDatagramLost,
|
||||
.capabilities = NETWORK_CAPABILITIES,
|
||||
.capabilityCount = sizeof(NETWORK_CAPABILITIES) /
|
||||
sizeof(NETWORK_CAPABILITIES[0]),
|
||||
.opaque = this,
|
||||
.opaque = this,
|
||||
};
|
||||
if (!networkConnectionCreate(&this->connection, ¶ms))
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(LGMsQuicSourceDir)src\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>QUIC_BUILD_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>QUIC_BUILD_STATIC;QUIC_API_ENABLE_INSECURE_FEATURES=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(LGMsQuicStaticLibrary);$(LGMsQuicCoreLibrary);$(LGMsQuicPlatformLibrary);ws2_32.lib;schannel.lib;secur32.lib;OneCore.lib;wbemuuid.lib;winmm.lib;ntdll.lib;bcrypt.lib;ncrypt.lib;crypt32.lib;iphlpapi.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@@ -34,7 +34,7 @@
|
||||
<!-- NormalizeDirectory adds a trailing slash. The dot prevents that slash
|
||||
from escaping the closing quote in the command line. -->
|
||||
<Exec
|
||||
Command="cmake -S "$(LGMsQuicSourceDir)." -B "$(LGMsQuicBuildDir)." -G "Visual Studio 17 2022" -A "$(LGMsQuicArchitecture)" -T v143 -DCMAKE_SYSTEM_VERSION="$(WindowsTargetPlatformVersion)" -DQUIC_BUILD_SHARED=OFF -DQUIC_BUILD_TOOLS=OFF -DQUIC_BUILD_TEST=OFF -DQUIC_BUILD_PERF=OFF -DQUIC_TLS_LIB=schannel -DQUIC_ENABLE_LOGGING=OFF -DQUIC_STATIC_LINK_CRT=OFF -DQUIC_STATIC_LINK_PARTIAL_CRT=OFF -DQUIC_SOURCE_LINK=OFF -DQUIC_PDBALTPATH=OFF -DQUIC_EMBED_GIT_HASH=OFF -DCMAKE_PROJECT_INCLUDE="$(MSBuildThisFileDirectory)MsQuic.cmake" -DLG_MSQUIC_DISABLE_CODE_ANALYSIS=ON" />
|
||||
Command="cmake -S "$(LGMsQuicSourceDir)." -B "$(LGMsQuicBuildDir)." -G "Visual Studio 17 2022" -A "$(LGMsQuicArchitecture)" -T v143 -DCMAKE_SYSTEM_VERSION="$(WindowsTargetPlatformVersion)" -DQUIC_BUILD_SHARED=OFF -DQUIC_BUILD_TOOLS=OFF -DQUIC_BUILD_TEST=OFF -DQUIC_BUILD_PERF=OFF -DQUIC_TLS_LIB=schannel -DQUIC_ENABLE_LOGGING=OFF -DQUIC_STATIC_LINK_CRT=OFF -DQUIC_STATIC_LINK_PARTIAL_CRT=OFF -DQUIC_SOURCE_LINK=OFF -DQUIC_PDBALTPATH=OFF -DQUIC_EMBED_GIT_HASH=OFF -DCMAKE_PROJECT_INCLUDE="$(MSBuildThisFileDirectory)MsQuic.cmake" -DLG_MSQUIC_DISABLE_CODE_ANALYSIS=ON -DLG_MSQUIC_ENABLE_INSECURE_FEATURES=ON" />
|
||||
</Target>
|
||||
<Target
|
||||
Name="BuildLGMsQuic"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
include(ExternalProject)
|
||||
|
||||
if(LG_MSQUIC_ENABLE_INSECURE_FEATURES)
|
||||
add_compile_definitions(QUIC_API_ENABLE_INSECURE_FEATURES=1)
|
||||
endif()
|
||||
|
||||
# MsQuic's static archive flattener must be able to see this imported target
|
||||
# from outside the directory where FindOpenSSL is invoked.
|
||||
if(LG_MSQUIC_OPENSSL_CRYPTO_LIBRARY AND NOT TARGET OpenSSL::Crypto)
|
||||
@@ -125,6 +129,7 @@ function(lg_add_static_msquic)
|
||||
"-DQUIC_SOURCE_LINK=OFF"
|
||||
"-DQUIC_PDBALTPATH=OFF"
|
||||
"-DQUIC_EMBED_GIT_HASH=OFF"
|
||||
"-DLG_MSQUIC_ENABLE_INSECURE_FEATURES=ON"
|
||||
)
|
||||
|
||||
if(NOT EXISTS "${LG_MSQUIC_SOURCE_DIR}/CMakeLists.txt")
|
||||
@@ -495,7 +500,7 @@ function(lg_add_static_msquic)
|
||||
IMPORTED_LOCATION_RELEASE "${LG_MSQUIC_RELEASE_LIBRARY}"
|
||||
IMPORTED_LOCATION_RELWITHDEBINFO "${LG_MSQUIC_RELEASE_LIBRARY}"
|
||||
IMPORTED_LOCATION_MINSIZEREL "${LG_MSQUIC_RELEASE_LIBRARY}"
|
||||
INTERFACE_COMPILE_DEFINITIONS QUIC_BUILD_STATIC
|
||||
INTERFACE_COMPILE_DEFINITIONS "QUIC_BUILD_STATIC;QUIC_API_ENABLE_INSECURE_FEATURES=1"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LG_MSQUIC_SOURCE_DIR}/src/inc"
|
||||
INTERFACE_LINK_LIBRARIES "${LG_MSQUIC_LINK_LIBRARIES}"
|
||||
)
|
||||
|
||||
@@ -5695,10 +5695,26 @@ retry:
|
||||
ResetEvent(owner.drainedEvent);
|
||||
}
|
||||
|
||||
owner.api->SetCallbackHandler(event->NEW_CONNECTION.Connection,
|
||||
reinterpret_cast<void *>(ConnectionCallback), connection);
|
||||
const QUIC_STATUS status = owner.api->ConnectionSetConfiguration(
|
||||
event->NEW_CONNECTION.Connection, owner.configuration);
|
||||
QUIC_STATUS status = QUIC_STATUS_SUCCESS;
|
||||
if (owner.settings.allowUnencrypted)
|
||||
{
|
||||
const BOOLEAN disableEncryption = TRUE;
|
||||
status = owner.api->SetParam(event->NEW_CONNECTION.Connection,
|
||||
QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION,
|
||||
sizeof(disableEncryption), &disableEncryption);
|
||||
if (QUIC_FAILED(status))
|
||||
DEBUG_ERROR("Failed to allow unencrypted 1-RTT payloads for "
|
||||
"network client %u: 0x%x", connection->client,
|
||||
static_cast<unsigned>(status));
|
||||
}
|
||||
|
||||
if (QUIC_SUCCEEDED(status))
|
||||
{
|
||||
owner.api->SetCallbackHandler(event->NEW_CONNECTION.Connection,
|
||||
reinterpret_cast<void *>(ConnectionCallback), connection);
|
||||
status = owner.api->ConnectionSetConfiguration(
|
||||
event->NEW_CONNECTION.Connection, owner.configuration);
|
||||
}
|
||||
if (QUIC_FAILED(status))
|
||||
{
|
||||
{
|
||||
@@ -5723,8 +5739,28 @@ retry:
|
||||
switch (event->Type)
|
||||
{
|
||||
case QUIC_CONNECTION_EVENT_CONNECTED:
|
||||
DEBUG_INFO("Network client %u connected", connection.client);
|
||||
{
|
||||
BOOLEAN encryptionDisabled = FALSE;
|
||||
uint32_t encryptionDisabledLength = sizeof(encryptionDisabled);
|
||||
const QUIC_STATUS status = owner.api->GetParam(handle,
|
||||
QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION,
|
||||
&encryptionDisabledLength, &encryptionDisabled);
|
||||
if (QUIC_FAILED(status))
|
||||
{
|
||||
DEBUG_ERROR("Failed to query 1-RTT encryption for network "
|
||||
"client %u: 0x%x", connection.client,
|
||||
static_cast<unsigned>(status));
|
||||
owner.Shutdown(connection, NETWORK_ERROR_PROTOCOL);
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DEBUG_INFO("Network client %u connected in %s mode "
|
||||
"(%s 1-RTT payloads)",
|
||||
connection.client,
|
||||
encryptionDisabled ? "insecure" : "secure",
|
||||
encryptionDisabled ? "unencrypted" : "encrypted");
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED:
|
||||
{
|
||||
|
||||
@@ -29,13 +29,14 @@ namespace
|
||||
{
|
||||
enum Field : unsigned
|
||||
{
|
||||
FIELD_BIND = 1U << 0,
|
||||
FIELD_PORT = 1U << 1,
|
||||
FIELD_MAX_CLIENTS = 1U << 2,
|
||||
FIELD_AUTH = 1U << 3,
|
||||
FIELD_PASSWORD = 1U << 4,
|
||||
FIELD_VIDEO_CHROMA = 1U << 5,
|
||||
FIELD_VIDEO_BITRATE = 1U << 6,
|
||||
FIELD_BIND = 1U << 0,
|
||||
FIELD_PORT = 1U << 1,
|
||||
FIELD_MAX_CLIENTS = 1U << 2,
|
||||
FIELD_AUTH = 1U << 3,
|
||||
FIELD_PASSWORD = 1U << 4,
|
||||
FIELD_VIDEO_CHROMA = 1U << 5,
|
||||
FIELD_VIDEO_BITRATE = 1U << 6,
|
||||
FIELD_ALLOW_UNENCRYPTED = 1U << 7,
|
||||
};
|
||||
|
||||
std::wstring Trim(const std::wstring& value)
|
||||
@@ -93,6 +94,23 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseBoolean(const std::wstring& value, bool& result)
|
||||
{
|
||||
if (Equal(value, L"true") || Equal(value, L"yes") ||
|
||||
Equal(value, L"1"))
|
||||
{
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
if (Equal(value, L"false") || Equal(value, L"no") ||
|
||||
Equal(value, L"0"))
|
||||
{
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SetField(const std::wstring& key, const std::wstring& rawValue,
|
||||
NetworkSettings& settings, unsigned& fields,
|
||||
std::wstring * error)
|
||||
@@ -139,6 +157,12 @@ namespace
|
||||
return Fail(error, L"invalid password");
|
||||
settings.password = value;
|
||||
}
|
||||
else if (Equal(key, L"allowUnencrypted"))
|
||||
{
|
||||
field = FIELD_ALLOW_UNENCRYPTED;
|
||||
if (!ParseBoolean(value, settings.allowUnencrypted))
|
||||
return Fail(error, L"invalid allowUnencrypted value");
|
||||
}
|
||||
else if (Equal(key, L"videoChroma"))
|
||||
{
|
||||
field = FIELD_VIDEO_CHROMA;
|
||||
|
||||
@@ -40,6 +40,7 @@ struct NetworkSettings
|
||||
uint16_t maxClients = NETWORK_DEFAULT_MAX_CLIENTS;
|
||||
LGNetAuthMode auth = LG_NET_AUTH_MODE_DEFAULT;
|
||||
std::wstring password;
|
||||
bool allowUnencrypted = false;
|
||||
uint32_t videoBitrateMbps =
|
||||
NETWORK_DEFAULT_VIDEO_BITRATE_MBPS;
|
||||
LGNetVideoChromaSubsampling videoChroma =
|
||||
@@ -47,10 +48,11 @@ struct NetworkSettings
|
||||
};
|
||||
|
||||
// Settings use a semicolon-separated key=value list. Supported keys are
|
||||
// bind, port, maxClients, auth, password, videoBitrateMbps, and videoChroma.
|
||||
// videoBitrateMbps uses decimal Mbit/s and defaults to 200. videoChroma accepts
|
||||
// 420 or 444 and defaults to 444. Password authentication requires a non-empty
|
||||
// password. The default address requests a dual-stack wildcard listener from
|
||||
// the eventual QUIC provider.
|
||||
// bind, port, maxClients, auth, password, allowUnencrypted, videoBitrateMbps,
|
||||
// and videoChroma. allowUnencrypted accepts true, false, yes, no, 1, or 0 and
|
||||
// defaults to false. videoBitrateMbps uses decimal Mbit/s and defaults to 200.
|
||||
// videoChroma accepts 420 or 444 and defaults to 444. Password authentication
|
||||
// requires a non-empty password. The default address requests a dual-stack
|
||||
// wildcard listener from the eventual QUIC provider.
|
||||
bool ParseNetworkSettings(const std::wstring& source,
|
||||
NetworkSettings& settings, std::wstring * error = nullptr);
|
||||
|
||||
Reference in New Issue
Block a user