From 12869039080ac756e5e7e73cc545a2f9d880e0f2 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 4 Jun 2023 19:21:59 -0500 Subject: [PATCH] ioquake3 resync to commit 47c96419 from 4610a240 Document USE_INTERNAL_VORBIS in README Update CI to Ubuntu 20.04 Add protocol handler support Fix bad client reliableAcknowledge DOS exploit --- .github/workflows/build.yml | 2 +- engine/Makefile | 2 +- engine/code/qcommon/q_shared.h | 2 + engine/code/server/sv_client.c | 2 +- engine/code/sys/sys_local.h | 5 ++ engine/code/sys/sys_main.c | 120 ++++++++++++++++++++++++++++++++- engine/code/sys/sys_osx.m | 43 ++++++++++++ engine/docs/README.md | 1 + engine/make-macosx-app.sh | 16 +++++ 9 files changed, 189 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8a626e8d..cc716a46 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: [push, pull_request] jobs: linux: name: Linux - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Install Dependencies diff --git a/engine/Makefile b/engine/Makefile index 7fbd66a3..6e240187 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -52,7 +52,7 @@ ifndef BUILD_DEFINES endif # ioquake3 git commit that this is based on -IOQ3_REVISION = 4610a240 +IOQ3_REVISION = 47c96419 ############################################################################# # diff --git a/engine/code/qcommon/q_shared.h b/engine/code/qcommon/q_shared.h index 11fce00d..91ff14ac 100644 --- a/engine/code/qcommon/q_shared.h +++ b/engine/code/qcommon/q_shared.h @@ -39,6 +39,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define CINEMATICS_LOGO "idlogo.roq" #define CINEMATICS_INTRO "intro.roq" // #define LEGACY_PROTOCOL // You probably don't need this for your standalone game +// #define PROTOCOL_HANDLER "foobar" #else #define PRODUCT_NAME "ioq3" #define BASEGAME "baseq3" @@ -55,6 +56,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define CINEMATICS_LOGO "idlogo.RoQ" #define CINEMATICS_INTRO "intro.RoQ" #define LEGACY_PROTOCOL + #define PROTOCOL_HANDLER "quake3" #endif // Heartbeat for dpmaster protocol. You shouldn't change this unless you know what you're doing diff --git a/engine/code/server/sv_client.c b/engine/code/server/sv_client.c index 62d6456e..1d230c07 100644 --- a/engine/code/server/sv_client.c +++ b/engine/code/server/sv_client.c @@ -1917,7 +1917,7 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) { // NOTE: when the client message is fux0red the acknowledgement numbers // can be out of range, this could cause the server to send thousands of server // commands which the server thinks are not yet acknowledged in SV_UpdateServerCommandsToClient - if (cl->reliableAcknowledge < cl->reliableSequence - MAX_RELIABLE_COMMANDS) { + if ((cl->reliableSequence - cl->reliableAcknowledge >= MAX_RELIABLE_COMMANDS) || (cl->reliableSequence - cl->reliableAcknowledge < 0)) { // usually only hackers create messages like this // it is more annoying for them to let them hanging #ifndef NDEBUG diff --git a/engine/code/sys/sys_local.h b/engine/code/sys/sys_local.h index cd7fbe7f..cc660a71 100644 --- a/engine/code/sys/sys_local.h +++ b/engine/code/sys/sys_local.h @@ -64,3 +64,8 @@ void Sys_AnsiColorPrint( const char *msg ); int Sys_PID( void ); qboolean Sys_PIDIsRunning( int pid ); + +#ifdef PROTOCOL_HANDLER +char *Sys_InitProtocolHandler( void ); +char *Sys_ParseProtocolUri( const char *uri ); +#endif diff --git a/engine/code/sys/sys_main.c b/engine/code/sys/sys_main.c index ae46c705..41bb54bd 100644 --- a/engine/code/sys/sys_main.c +++ b/engine/code/sys/sys_main.c @@ -642,6 +642,94 @@ void Sys_ParseArgs( int argc, char **argv ) } } +#ifdef PROTOCOL_HANDLER +/* +================= +Sys_InitProtocolHandler + +See sys_osx.m for macOS implementation. +================= +*/ +#ifndef __APPLE__ +char *Sys_InitProtocolHandler( void ) +{ + return NULL; +} +#endif + +/* +================= +Sys_ParseProtocolUri + +This parses a protocol URI, e.g. "quake3://connect/example.com:27950" +to a string that can be run in the console, or a null pointer if the +operation is invalid or unsupported. +At the moment only the "connect" command is supported. +================= +*/ +char *Sys_ParseProtocolUri( const char *uri ) +{ + // Both "quake3://" and "quake3:" can be used + if ( Q_strncmp( uri, PROTOCOL_HANDLER ":", strlen( PROTOCOL_HANDLER ":" ) ) ) + { + Com_Printf( "Sys_ParseProtocolUri: unsupported protocol.\n" ); + return NULL; + } + uri += strlen( PROTOCOL_HANDLER ":" ); + if ( !Q_strncmp( uri, "//", strlen( "//" ) ) ) + { + uri += strlen( "//" ); + } + Com_Printf( "Sys_ParseProtocolUri: %s\n", uri ); + + // At the moment, only "connect/hostname:port" is supported + if ( !Q_strncmp( uri, "connect/", strlen( "connect/" ) ) ) + { + int i, bufsize; + char *out; + + uri += strlen( "connect/" ); + if ( *uri == '\0' || *uri == '?' ) + { + Com_Printf( "Sys_ParseProtocolUri: missing argument.\n" ); + return NULL; + } + + // Check for any unsupported characters + // For safety reasons, the "hostname:port" part can only + // contain characters from: a-zA-Z0-9.:-[] + for ( i=0; uri[i] != '\0'; i++ ) + { + if ( uri[i] == '?' ) + { + // For forwards compatibility, any query string parameters are ignored (e.g. "?password=abcd") + // However, these are not passed on macOS, so it may be a bad idea to add them. + break; + } + + if ( isalpha( uri[i] ) == 0 && isdigit( uri[i] ) == 0 + && uri[i] != '.' && uri[i] != ':' && uri[i] != '-' + && uri[i] != '[' && uri[i] != ']' ) + { + Com_Printf( "Sys_ParseProtocolUri: hostname contains unsupported character.\n" ); + return NULL; + } + } + + bufsize = strlen( "+connect " ) + i + 1; + out = malloc( bufsize ); + strcpy( out, "+connect " ); + strncat( out, uri, i ); + return out; + } + else + { + Com_Printf( "Sys_ParseProtocolUri: unsupported command.\n" ); + return NULL; + } +} +#endif + #ifndef DEFAULT_BASEDIR # ifdef __APPLE__ # define DEFAULT_BASEDIR Sys_StripAppBundle(Sys_BinaryPath()) @@ -690,6 +778,9 @@ int main( int argc, char **argv ) { int i; char commandLine[ MAX_STRING_CHARS ] = { 0 }; +#ifdef PROTOCOL_HANDLER + char *protocolCommand = NULL; +#endif extern void Sys_LaunchAutoupdater(int argc, char **argv); Sys_LaunchAutoupdater(argc, argv); @@ -724,6 +815,10 @@ int main( int argc, char **argv ) Sys_PlatformInit( ); +#ifdef PROTOCOL_HANDLER + protocolCommand = Sys_InitProtocolHandler( ); +#endif + // Set the initial time base Sys_Milliseconds( ); @@ -740,7 +835,22 @@ int main( int argc, char **argv ) // Concatenate the command line for passing to Com_Init for( i = 1; i < argc; i++ ) { - const qboolean containsSpaces = strchr(argv[i], ' ') != NULL; + qboolean containsSpaces; + + // For security reasons we always detect --uri, even when PROTOCOL_HANDLER is undefined + // Any arguments after "--uri quake3://..." is ignored + if ( !strcmp( argv[i], "--uri" ) ) + { +#ifdef PROTOCOL_HANDLER + if ( argc > i+1 ) + { + protocolCommand = Sys_ParseProtocolUri( argv[i+1] ); + } +#endif + break; + } + + containsSpaces = strchr(argv[i], ' ') != NULL; if (containsSpaces) Q_strcat( commandLine, sizeof( commandLine ), "\"" ); @@ -752,6 +862,14 @@ int main( int argc, char **argv ) Q_strcat( commandLine, sizeof( commandLine ), " " ); } +#ifdef PROTOCOL_HANDLER + if ( protocolCommand != NULL ) + { + Q_strcat( commandLine, sizeof( commandLine ), protocolCommand ); + free( protocolCommand ); + } +#endif + CON_Init( ); Com_Init( commandLine ); NET_Init( ); diff --git a/engine/code/sys/sys_osx.m b/engine/code/sys/sys_osx.m index b0ecf6a5..d7415d32 100644 --- a/engine/code/sys/sys_osx.m +++ b/engine/code/sys/sys_osx.m @@ -34,6 +34,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #import #import +#ifdef PROTOCOL_HANDLER +char *protocolCommand = NULL; +#endif + /* ============== Sys_Dialog @@ -115,3 +119,42 @@ char *Sys_StripAppBundle( char *dir ) Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd)); return cwd; } + +#ifdef PROTOCOL_HANDLER + +@interface AppDelegate : NSObject +@end + +@implementation AppDelegate + +- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent +{ + NSString *input = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; + protocolCommand = Sys_ParseProtocolUri( input.UTF8String ); +} + +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + [NSApp stop:nil]; +} + +@end + +char *Sys_InitProtocolHandler( void ) +{ + [NSApplication sharedApplication]; + + AppDelegate *appDelegate = [AppDelegate new]; + NSAppleEventManager *sharedAppleEventManager = [NSAppleEventManager new]; + [sharedAppleEventManager setEventHandler:appDelegate + andSelector:@selector(handleAppleEvent:withReplyEvent:) + forEventClass:kInternetEventClass + andEventID:kAEGetURL]; + + [NSApp setDelegate:appDelegate]; + [NSApp run]; + + return protocolCommand; +} + +#endif diff --git a/engine/docs/README.md b/engine/docs/README.md index 3b013e6c..ce2999cb 100644 --- a/engine/docs/README.md +++ b/engine/docs/README.md @@ -150,6 +150,7 @@ Makefile.local: USE_INTERNAL_JPEG - build and link against internal JPEG library USE_INTERNAL_OGG - build and link against internal ogg library USE_INTERNAL_OPUS - build and link against internal opus/opusfile libraries + USE_INTERNAL_VORBIS - build and link against internal Vorbis library USE_LOCAL_HEADERS - use headers local to ioq3 instead of system ones DEBUG_CFLAGS - C compiler flags to use for building debug version COPYDIR - the target installation directory diff --git a/engine/make-macosx-app.sh b/engine/make-macosx-app.sh index c583bb4a..672effc1 100755 --- a/engine/make-macosx-app.sh +++ b/engine/make-macosx-app.sh @@ -192,6 +192,7 @@ WRAPPER_NAME="${PRODUCT_NAME}.${WRAPPER_EXTENSION}" CONTENTS_FOLDER_PATH="${WRAPPER_NAME}/Contents" UNLOCALIZED_RESOURCES_FOLDER_PATH="${CONTENTS_FOLDER_PATH}/Resources" EXECUTABLE_FOLDER_PATH="${CONTENTS_FOLDER_PATH}/MacOS" +PROTOCOL_HANDLER="quake3" # loop through the architectures to build string lists for each universal binary for ARCH in $SEARCH_ARCHS; do @@ -362,6 +363,21 @@ if [ -n "${MACOSX_DEPLOYMENT_TARGET_PPC}" ] || [ -n "${MACOSX_DEPLOYMENT_TARGET_ " fi + if [ -n "${PROTOCOL_HANDLER}" ]; then + PLIST="${PLIST} + CFBundleURLTypes + + + CFBundleURLName + ${PRODUCT_NAME} + CFBundleURLSchemes + + ${PROTOCOL_HANDLER} + + + " + fi + PLIST="${PLIST} NSHumanReadableCopyright QUAKE III ARENA Copyright © 1999-2000 id Software, Inc. All rights reserved.