From b21a648a4b0ec823b90a10d57a5eacbc70187ea0 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 16 Jan 2022 18:41:53 +0000 Subject: [PATCH] Set up the openssl(3) plugin to statically link for windows, so people can actually host properly with dtls on windows. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6163 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/common/net_wins.c | 16 ++++++++++++++++ engine/server/pr_q1qvm.c | 22 +++++++++++++--------- plugins/Makefile | 37 +++++++++++++++++++++++++++++++++---- plugins/net_ssl_openssl.c | 22 +++++++++++----------- 4 files changed, 73 insertions(+), 24 deletions(-) diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index f81ee2bad..0ac8e3413 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -154,6 +154,7 @@ extern cvar_t net_ice_exchangeprivateips; #if defined(HAVE_DTLS) && defined(HAVE_SERVER) static void QDECL NET_Enable_DTLS_Changed(struct cvar_s *var, char *oldvalue) { + var->ival = var->value; //set up the default value if (!*var->string) var->ival = 0; //FIXME: change to 1 then 2 when better tested. @@ -250,6 +251,10 @@ static void NET_TLS_Provider_Changed(struct cvar_s *var, char *oldvalue) Con_Printf(" %s", cryptolib[i]->drivername); Con_Printf("\n"); } + +#if defined(HAVE_DTLS) && defined(HAVE_SERVER) + Cvar_ForceCallback(&net_enable_dtls); +#endif } #endif qboolean NET_RegisterCrypto(void *module, ftecrypto_t *driver) @@ -2973,13 +2978,24 @@ const dtlsfuncs_t *DTLS_InitServer(void) { const dtlsfuncs_t *f = NULL; int i; + const char *provname; if (tls_provider.ival>0 && tls_provider.ival <= cryptolib_count && cryptolib[tls_provider.ival-1]) + { f = !cryptolib[tls_provider.ival-1]->DTLS_InitServer?NULL:cryptolib[tls_provider.ival-1]->DTLS_InitServer(); + provname = cryptolib[tls_provider.ival-1]->drivername; + } else for (i = 0; !f && i < cryptolib_count; i++) { if (cryptolib[i] && cryptolib[i]->DTLS_InitServer) + { f = cryptolib[i]->DTLS_InitServer(); + provname = cryptolib[i]->drivername; + if (!f) + Con_Printf("DTLS provider %s failed\n", cryptolib[i]->drivername); + } } + if (f) + Con_DPrintf("Using DTLS provider %s\n", provname); return f; } const dtlsfuncs_t *DTLS_InitClient(void) diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 160a96730..ac4137dd2 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -1789,23 +1789,27 @@ svextqcfields } static qintptr_t QVM_SetExtField (void *offset, quintptr_t mask, const qintptr_t *arg) { - edict_t *e = VM_POINTER(arg[0]); + unsigned int entnum = ((char*)VM_POINTER(arg[0]) - (char*)evars)/sv.world.edict_size; int i = QVM_FindExtField(VM_POINTER(arg[1])); int value = VM_LONG(arg[2]); - if (i < 0) - return 0; - ((int*)e->xv)[i] = value; - return value; + if (i >= 0 && entnum < q1qvmprogfuncs.edicttable_length && q1qvmprogfuncs.edicttable[entnum]) + { + ((int*)q1qvmprogfuncs.edicttable[entnum]->xv)[i] = value; + return value; + } + return 0; } static qintptr_t QVM_GetExtField (void *offset, quintptr_t mask, const qintptr_t *arg) { - edict_t *e = VM_POINTER(arg[0]); + unsigned int entnum = ((char*)VM_POINTER(arg[0]) - (char*)evars)/sv.world.edict_size; int i = QVM_FindExtField(VM_POINTER(arg[1])); - if (i < 0) - return 0; - return ((int*)e->xv)[i]; + if (i >= 0 && entnum < q1qvmprogfuncs.edicttable_length && q1qvmprogfuncs.edicttable[entnum]) + { + return ((int*)q1qvmprogfuncs.edicttable[entnum]->xv)[i]; + } + return 0; } #ifdef WEBCLIENT diff --git a/plugins/Makefile b/plugins/Makefile index b9a012fcc..3a350a650 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -405,13 +405,42 @@ $(PLUG_PREFIX)models$(PLUG_NATIVE_EXT): models/gltf.c models/exportiqm.c models/ $(call EMBEDMETA,models,$@,Models Plugin,Kinda redundant now that the engine has gltf2 loading) #NATIVE_PLUGINS+=models +##################### #Openssl crypto plugin, to replace microsoft's shoddy dtls implementation. could also be useful on the BSDs, yay system components? + +ifeq ($(FTE_TARGET),win32) + OSSL_ARCH=mingw32 +endif +ifeq ($(FTE_TARGET),win64) + OSSL_ARCH=mingw64 +endif +#statically link openssl on the above systems (instead of depending on system libs) +ifneq ($(OSSL_ARCH),) +OSSL_VERSION=3.0.1 +ARCHLIBS=../engine/libs-$(ARCH) +#../engine/libs-$(ARCH)/openssl-$(OSSL_VERSION).tar.gz: +../engine/openssl-$(OSSL_VERSION).tar.gz: + wget -O $@ -N https://github.com/openssl/openssl/archive/refs/tags/openssl-$(OSSL_VERSION).tar.gz +$(ARCHLIBS)/openssl-openssl-$(OSSL_VERSION)/libssl.a: ../engine/openssl-$(OSSL_VERSION).tar.gz + (cd $(ARCHLIBS) && tar xvfz ../openssl-$(OSSL_VERSION).tar.gz) + (cd $(ARCHLIBS)/openssl-openssl-$(OSSL_VERSION) && CFLAGS=-Os ./Configure --release no-filenames no-legacy no-shared no-stdio no-asm $(OSSL_ARCH) --cross-compile-prefix=$(ARCH)- && $(MAKE)) +net_ssl_openssl.c: $(ARCHLIBS)/openssl-openssl-$(OSSL_VERSION)/libssl.a $(ARCHLIBS)/openssl-openssl-$(OSSL_VERSION)/libcrypt.a + +#we should be using openssl's no-sock option, but that also disables core dtls functionality (despite us using our own BIOs). +OPENSSL_LDCFLAGS=-I$(ARCHLIBS)/openssl-openssl-$(OSSL_VERSION)/include -L$(ARCHLIBS)/openssl-openssl-$(OSSL_VERSION) -lssl -lcrypto -lws2_32 +OPENSSL_AVAILABLE=1 +endif + +OPENSSL_LDCFLAGS?=`$(PKGCONFIG) --libs --cflags openssl` +OPENSSL_AVAILABLE?=$(shell $(OPENSSLPKGPATH) $(PKGCONFIG) --atleast-version=3.0.0 openssl && echo 1) $(PLUG_PREFIX)openssl$(PLUG_NATIVE_EXT): net_ssl_openssl.c plugin.c - $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) `$(PKGCONFIG) --libs --cflags openssl` + $(CC) -s $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(OPENSSL_LDCFLAGS) $(call EMBEDMETA,openssl,$@,OpenSSL,Provides OpenSSL support for dtls/tls/https support. The crypto library that is actually used is controlled via the tls_provider cvar.) -#ifeq ($(shell $(PKGCONFIG) --exists openssl && echo 1),1) -#Disabled due to licensing issues #NATIVE_PLUGINS+=openssl -#endif +#OpenSSL 3.0.0 is apache2 and thus GPL3-compatible, earlier versions are NOT GPL-compatible at all, so only enable it if its okay. +#(you can still force it, but don't distribute) +ifeq ($(OPENSSL_AVAILABLE),1) +NATIVE_PLUGINS+=openssl +endif ##################### #for compat with half-life 2's file formats diff --git a/plugins/net_ssl_openssl.c b/plugins/net_ssl_openssl.c index 0a9bc42d3..ace8f4f29 100644 --- a/plugins/net_ssl_openssl.c +++ b/plugins/net_ssl_openssl.c @@ -770,18 +770,16 @@ static void *OSSL_CreateContext(const char *remotehost, void *cbctx, neterr_t(*p return NULL; } -static char dtlscookiekey[16]; +static qbyte dtlscookiekey[16]; static int OSSL_GenCookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) { ossldtls_t *f = SSL_get_app_data(ssl); + qbyte *blurgh = alloca(sizeof(dtlscookiekey) + f->peeraddrsize); - SHA_CTX ctx; + memcpy(blurgh, dtlscookiekey, sizeof(dtlscookiekey)); + memcpy(blurgh+sizeof(dtlscookiekey), f->peeraddr, f->peeraddrsize); - SHA1_Init(&ctx); - SHA1_Update(&ctx, dtlscookiekey, sizeof(dtlscookiekey)); - SHA1_Update(&ctx, "somethinghashy", 15); - SHA1_Update(&ctx, f->peeraddr, f->peeraddrsize); - SHA1_Final(cookie, &ctx); + SHA1(blurgh, sizeof(dtlscookiekey) + f->peeraddrsize, cookie); *cookie_len = SHA_DIGEST_LENGTH; return 1; @@ -949,7 +947,8 @@ static qboolean OSSL_Init(void) static qboolean init_success; if (inited) return init_success; -#ifdef LOADERTHREAD + inited = true; +#if 0//def LOADERTHREAD Sys_LockMutex(com_resourcemutex); if (inited) //now check again, just in case { @@ -960,7 +959,6 @@ static qboolean OSSL_Init(void) SSL_library_init(); SSL_load_error_strings(); - ERR_load_BIO_strings(); // OPENSSL_config(NULL); ERR_print_errors_cb(OSSL_PrintError_CB, NULL); @@ -997,8 +995,7 @@ static qboolean OSSL_Init(void) ossl_fte_certctx = SSL_get_ex_new_index(0, "ossl_fte_certctx", NULL, NULL, NULL); - inited = true; -#ifdef LOADERTHREAD +#if 0//def LOADERTHREAD Sys_UnlockMutex(com_resourcemutex); #endif return init_success; @@ -1056,5 +1053,8 @@ qboolean Plug_Init(void) pdtls_psk_user = cvarfuncs->GetNVFDG("dtls_psk_user", "", 0, NULL, "DTLS stuff"); pdtls_psk_key = cvarfuncs->GetNVFDG("dtls_psk_key", "", 0, NULL, "DTLS stuff"); netfuncs->RandomBytes(dtlscookiekey, sizeof(dtlscookiekey)); //something random so people can't guess cookies for arbitrary victim IPs. + + OSSL_Init(); //shoving this here solves threading issues (eg two loader threads racing to open an https image url) + return plugfuncs->ExportInterface("Crypto", &crypto_openssl, sizeof(crypto_openssl)); //export a named interface struct to the engine } \ No newline at end of file