From 42430d4712f4c8a59af2c900b324d365d7a67265 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 30 Jan 2022 05:55:01 +0000 Subject: [PATCH] Fix some misc memory leaks and a few other minor issues. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6176 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- CMakeLists.txt | 28 +- engine/client/cl_main.c | 5 + engine/client/m_download.c | 4 + engine/client/valid.c | 11 +- engine/common/com_mesh.c | 3 + engine/common/cvar.c | 5 + engine/common/fs.c | 1 + engine/common/net_ice.c | 43 +++- engine/common/net_ssl_gnutls.c | 453 ++++++++++++--------------------- engine/common/net_wins.c | 3 +- engine/common/netinc.h | 2 +- engine/common/plugin.c | 3 + engine/common/sys.h | 2 +- engine/gl/gl_rlight.c | 4 + engine/server/pr_cmds.c | 2 +- engine/server/sv_main.c | 4 + engine/server/sv_sys_unix.c | 29 ++- plugins/net_ssl_openssl.c | 58 +++-- 18 files changed, 341 insertions(+), 319 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cf55e3e7..86f1d3b20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1091,15 +1091,20 @@ IF(FTE_PLUG_QI) EMBED_PLUGIN_META(qi "Quaddicted Map Database" "Provides easy access to the quaddicted map database. Once installed you can use eg 'map qi_dopa:start' to begin playing dopa, or load it via the menus.") ENDIF() -SET(FTE_PLUG_OPENSSL false CACHE BOOL "Compile OpenSSL (beware license).") +SET(FTE_PLUG_OPENSSL false CACHE BOOL "Compile OpenSSL.") IF(FTE_PLUG_OPENSSL) #the openssl license is incompatible with the GPL, so while we have code to use it distributing the binaries built with it is not a (legal) option. #note that openssl 3.0.0 upwards are apache-2 licensed, which IS gpl-3 compatible (though not gpl-2). debian has not caught up with that yet, however. FIND_PACKAGE(OpenSSL) + IF(OPENSSL_VERSION_MAJOR LESS 3) + SET(FTE_PRIVATE_USE_ONLY false CACHE BOOL "Ignore license violations.") + ENDIF() IF(NOT OPENSSL_FOUND) MESSAGE(WARNING "openssl library NOT available. you'll have to use some other library.") + ELSEIF(OPENSSL_VERSION_MAJOR LESS 3 AND NOT FTE_PRIVATE_USE_ONLY) + MESSAGE(WARNING "openssl v3 required for GPL compliance. Enable FTE_PRIVATE_USE_ONLY to compile openssl plugin.") ELSE() - IF(OPENSSL_VERSION_MAJOR LESS 3 AND NOT FTE_PRIVATE_USE_ONLY) + IF(OPENSSL_VERSION_MAJOR LESS 3) MESSAGE(WARNING "openssl library version is not 3 or above. You may not distribute plugin binaries due to license conflict.") ELSE() MESSAGE(WARNING "Using openssl. Resulting plugin must be licensed as GPLv3.") @@ -1117,6 +1122,25 @@ IF(FTE_PLUG_OPENSSL) ENDIF() ENDIF() +#SET(FTE_PLUG_GNUTLS true CACHE BOOL "Compile GnuTLS Library.") +#IF(FTE_PLUG_GNUTLS) +# FIND_PACKAGE(GnuTLS) +# IF(NOT GNUTLS_FOUND) +# MESSAGE(WARNING "openssl library NOT available. you'll have to use some other library.") +# ELSE() +# SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES}) +# +# ADD_LIBRARY(plug_gnutls MODULE +# plugins/plugin.c +# engine/common/net_ssl_gnutls.c +# ) +# SET_TARGET_PROPERTIES(plug_gnutls PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") +# TARGET_LINK_LIBRARIES(plug_gnutls ${SYS_LIBS} ${GNUTLS_LIBRARIES}) +# +# EMBED_PLUGIN_META(gnutls "GnuTLS" "Provides GnuTLS support for dtls/tls/https support. The crypto library that is actually used is controlled via the tls_provider cvar.") +# ENDIF() +#ENDIF() + #ODE Physics library plugin SET(FTE_PLUG_ODE true CACHE BOOL "Compile ODE rigid body physics plugin.") IF(FTE_PLUG_ODE) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index edc99a018..1ca48f971 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -35,6 +35,7 @@ void QDECL Name_Callback(struct cvar_s *var, char *oldvalue); #else #define Name_Callback NULL #endif +void GnuTLS_Shutdown(void); static void CL_ForceStopDownload (qboolean finish); @@ -7223,6 +7224,10 @@ void Host_Shutdown(void) Cvar_Shutdown(); Validation_FlushFileList(); +#ifdef HAVE_GNUTLS + GnuTLS_Shutdown(); +#endif + Cmd_Shutdown(); #ifdef PACKAGEMANAGER PM_Shutdown(false); diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 8f62b86ee..875d5299f 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -311,6 +311,10 @@ static void PM_FreePackage(package_t *p) Z_Free(p->previewimage); Z_Free(p->qhash); Z_Free(p->arch); + Z_Free(p->packprefix); + Z_Free(p->filesha1); + Z_Free(p->filesha512); + Z_Free(p->signature); Z_Free(p); } diff --git a/engine/client/valid.c b/engine/client/valid.c index 6de397cd4..6863340cf 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -913,9 +913,18 @@ void Ruleset_Shutdown(void) rs->rules--; Z_Free(rs->rule[rs->rules].rulename); Z_Free(rs->rule[rs->rules].rulevalue); + Z_Free(rs->rule[rs->rules].rulecond); } - Z_Free(rs->rule); + + while (rs->filehashes) + { + rs->filehashes--; + Z_Free(rs->filehash[rs->filehashes].filename); + Z_Free(rs->filehash[rs->filehashes].hash); + } + Z_Free(rs->filehash); + Z_Free(rs); } } diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 4a7ba8397..4f4b78967 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -6172,7 +6172,10 @@ static galiasinfo_t *Mod_LoadQ3ModelLod(model_t *mod, int *surfcount, void *buff if (i >= LittleLong(surf->numShaders)) Q_strncpyz(frames->shadername, "", sizeof(frames->shadername)); //this shouldn't be possible else + { Q_strncpyz(frames->shadername, inshader->name, sizeof(frames->shadername)); + Q_strncpyz(skin->name, inshader->name, sizeof(frames->shadername)); + } inshader++; skin++; diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 8db7025a8..266862f10 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -1714,6 +1714,11 @@ void Cvar_Shutdown(void) } Z_Free(var->latched_string); Z_Free(var->string); + + AHash_RemoveDataInsensitive(&cvar_hash, var->name, var); + if (var->name2) + AHash_RemoveDataInsensitive(&cvar_hash, var->name2, var); + if (var->flags & CVAR_POINTER) Z_Free(var); else diff --git a/engine/common/fs.c b/engine/common/fs.c index 9842ad735..282151401 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -223,6 +223,7 @@ void FS_Manifest_Free(ftemanifest_t *man) Z_Free(man->downloadsurl); Z_Free(man->installupd); #endif + Z_Free(man->mainconfig); Z_Free(man->schemes); Z_Free(man->protocolname); Z_Free(man->eula); diff --git a/engine/common/net_ice.c b/engine/common/net_ice.c index 9d0b4a0a4..a721c0ec3 100644 --- a/engine/common/net_ice.c +++ b/engine/common/net_ice.c @@ -407,7 +407,11 @@ static struct icestate_s *QDECL ICE_Create(void *module, const char *conname, co con->dtlsfuncs = DTLS_InitClient(); //credentials are a bit different, though fingerprints make it somewhat irrelevant. } if (con->dtlsfuncs && con->dtlsfuncs->GenTempCertificate && !con->cred.local.certsize) + { + Con_DPrintf("Generating dtls certificate...\n"); con->dtlsfuncs->GenTempCertificate(NULL, &con->cred.local); + Con_DPrintf("Done\n"); + } con->mysctpport = 27500; } @@ -931,9 +935,9 @@ static qboolean QDECL ICE_Set(struct icestate_s *con, const char *prop, const ch CL_Transfer(&con->qadr); //okay, the client should be using this ice connection now. #endif #ifndef CLIENTONLY - else if (con->proto == ICEP_QWSERVER) + else if (con->proto == ICEP_QWSERVER && con->mode != ICEM_WEBRTC) { - net_from = con->chosenpeer; + net_from = con->qadr; SVC_GetChallenge(false); } #endif @@ -1329,12 +1333,40 @@ void QDECL ICE_AddLCandidateConn(ftenet_connections_t *col, netadr_t *addr, int static void ICE_Destroy(struct icestate_s *con) { + struct icecandidate_s *c; + + if (con->sctp) + { + Z_Free(con->sctp->cookie); + Z_Free(con->sctp); + } + if (con->dtlsstate) + con->dtlsfuncs->DestroyContext(con->dtlsstate); if (con->connections) FTENET_CloseCollection(con->connections); if (con->cred.local.cert) Z_Free(con->cred.local.cert); if (con->cred.local.key) - Z_Free(con->cred.local.key); + Z_Free(con->cred.local.key); + while(con->rc) + { + c = con->rc; + con->rc = c->next; + Z_Free(c); + } + while(con->lc) + { + c = con->lc; + con->lc = c->next; + Z_Free(c); + } + Z_Free(con->stunserver); + Z_Free(con->lufrag); + Z_Free(con->lpwd); + Z_Free(con->rufrag); + Z_Free(con->rpwd); + Z_Free(con->friendlyname); + Z_Free(con->conname); //has already been unlinked Z_Free(con); } @@ -1406,7 +1438,7 @@ void ICE_Tick(void) { if (con->sctp) SCTP_Transmit(con->sctp, con, NULL,0); //try to keep it ticking... - if (con->dtlsfuncs) + if (con->dtlsstate) con->dtlsfuncs->Timeouts(con->dtlsstate); //FIXME: We should be sending a stun binding indication every 15 secs with a fingerprint attribute @@ -2154,6 +2186,8 @@ qboolean ICE_WasStun(ftenet_connections_t *col) if (net_from.type == NA_ICE) return false; //this stuff over an ICE connection doesn't make sense. #endif + if (net_from.prot != NP_DGRAM) + return false; #if defined(HAVE_CLIENT) && defined(VOICECHAT) if (col == cls.sockets) @@ -3110,7 +3144,6 @@ handleerror: } if (b->generic.islisten) { - Con_Printf("Client offered: %s\n", data); if (cl >= 0 && cl < b->numclients && b->clients[cl].ice) { iceapi.ICE_Set(b->clients[cl].ice, "sdpoffer", data); diff --git a/engine/common/net_ssl_gnutls.c b/engine/common/net_ssl_gnutls.c index a0d9a340a..99f1badb6 100644 --- a/engine/common/net_ssl_gnutls.c +++ b/engine/common/net_ssl_gnutls.c @@ -139,100 +139,125 @@ typedef int (VARGS gnutls_certificate_verify_function)(gnutls_session_t session) #endif -static int (VARGS *qgnutls_bye)(gnutls_session_t session, gnutls_close_request_t how); -static void (VARGS *qgnutls_perror)(int error); -static gnutls_alert_description_t (VARGS *qgnutls_alert_get)(gnutls_session_t session); -static const char *(VARGS *qgnutls_alert_get_name)(gnutls_alert_description_t alert); -static int (VARGS *qgnutls_handshake)(gnutls_session_t session); -static void (VARGS *qgnutls_transport_set_ptr)(gnutls_session_t session, gnutls_transport_ptr_t ptr); -static void (VARGS *qgnutls_transport_set_push_function)(gnutls_session_t session, gnutls_push_func push_func); -static void (VARGS *qgnutls_transport_set_pull_function)(gnutls_session_t session, gnutls_pull_func pull_func); -static void (VARGS *qgnutls_transport_set_errno)(gnutls_session_t session, int err); -static int (VARGS *qgnutls_error_is_fatal)(int error); -static int (VARGS *qgnutls_credentials_set)(gnutls_session_t, gnutls_credentials_type_t type, void* cred); -//static int (VARGS *qgnutls_kx_set_priority)(gnutls_session_t session, const int*); -static int (VARGS *qgnutls_init)(gnutls_session_t * session, gnutls_connection_end_t con_end); -static void (VARGS *qgnutls_deinit)(gnutls_session_t session); -static int (VARGS *qgnutls_set_default_priority)(gnutls_session_t session); -#ifdef HAVE_DTLS -static int (VARGS *qgnutls_set_default_priority_append)(gnutls_session_t session, const char *add_prio, const char **err_pos, unsigned flags); -#endif -static int (VARGS *qgnutls_certificate_allocate_credentials)(gnutls_certificate_credentials_t *sc); -static int (VARGS *qgnutls_anon_allocate_client_credentials)(gnutls_anon_client_credentials_t *sc); -static int (VARGS *qgnutls_global_init)(void); -static ssize_t (VARGS *qgnutls_record_send)(gnutls_session_t session, const void *data, size_t sizeofdata); -static ssize_t (VARGS *qgnutls_record_recv)(gnutls_session_t session, void *data, size_t sizeofdata); -static void (VARGS *qgnutls_certificate_set_verify_function)(gnutls_certificate_credentials_t cred, gnutls_certificate_verify_function *func); -static void *(VARGS *qgnutls_session_get_ptr)(gnutls_session_t session); -static void (VARGS *qgnutls_session_set_ptr)(gnutls_session_t session, void *ptr); -static int (VARGS *qgnutls_session_channel_binding)(gnutls_session_t session, gnutls_channel_binding_t cbtype, gnutls_datum_t * cb); #ifdef GNUTLS_HAVE_SYSTEMTRUST -static int (VARGS *qgnutls_certificate_set_x509_system_trust)(gnutls_certificate_credentials_t cred); + #define GNUTLS_TRUSTFUNCS GNUTLS_FUNC(gnutls_certificate_set_x509_system_trust,int,(gnutls_certificate_credentials_t cred)) #else -static int (VARGS *qgnutls_certificate_set_x509_trust_file)(gnutls_certificate_credentials_t cred, const char * cafile, gnutls_x509_crt_fmt_t type); + #define GNUTLS_TRUSTFUNCS GNUTLS_FUNC(gnutls_certificate_set_x509_trust_file,void,(void)) #endif -static int (VARGS *qgnutls_certificate_set_x509_key_file)(gnutls_certificate_credentials_t res, const char * certfile, const char * keyfile, gnutls_x509_crt_fmt_t type); #ifdef GNUTLS_HAVE_VERIFY3 -static int (VARGS *qgnutls_certificate_verify_peers3)(gnutls_session_t session, const char* hostname, unsigned int * status); -static int (VARGS *qgnutls_certificate_verification_status_print)(unsigned int status, gnutls_certificate_type_t type, gnutls_datum_t * out, unsigned int flags); + #define GNUTLS_VERIFYFUNCS \ + GNUTLS_FUNC(gnutls_certificate_verify_peers3,int,(gnutls_session_t session,const char *hostname,unsigned int *status)) \ + GNUTLS_FUNC(gnutls_certificate_verification_status_print,int,(unsigned int status, gnutls_certificate_type_t type, gnutls_datum_t * out, unsigned int flags)) \ + GNUTLS_FUNC(gnutls_certificate_type_get,gnutls_certificate_type_t,(gnutls_session_t session)) \ + GNUTLS_FUNC(gnutls_certificate_get_peers,const gnutls_datum_t *,(gnutls_session_t session, unsigned int *list_size)) #else -static int (VARGS *qgnutls_certificate_verify_peers2)(gnutls_session_t session, unsigned int * status); -static int (VARGS *qgnutls_x509_crt_check_hostname)(gnutls_x509_crt_t cert, const char * hostname); -static int (VARGS *qgnutls_x509_crt_init)(gnutls_x509_crt_t * cert); -static int (VARGS *qgnutls_x509_crt_import)(gnutls_x509_crt_t cert, const gnutls_datum_t *data, gnutls_x509_crt_fmt_t format); + #define GNUTLS_VERIFYFUNCS \ + GNUTLS_FUNC(gnutls_certificate_verify_peers2,int,(gnutls_session_t session, unsigned int *status)) \ + GNUTLS_FUNC(gnutls_x509_crt_check_hostname,unsigned,(gnutls_x509_crt_t cert, const char *hostname)) \ + GNUTLS_FUNC(gnutls_x509_crt_import,int,(gnutls_x509_crt_t cert, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format)) \ + GNUTLS_FUNC(gnutls_certificate_get_peers,const gnutls_datum_t *,(gnutls_session_t session, unsigned int *list_size)) #endif -static const gnutls_datum_t *(VARGS *qgnutls_certificate_get_peers)(gnutls_session_t session, unsigned int * list_size); -static gnutls_certificate_type_t (VARGS *qgnutls_certificate_type_get)(gnutls_session_t session); -static void *(VARGS **qgnutls_malloc)(size_t); -static void (VARGS **qgnutls_free)(void * ptr); -static int (VARGS *qgnutls_server_name_set)(gnutls_session_t session, gnutls_server_name_type_t type, const void * name, size_t name_length); #ifdef HAVE_DTLS -static int (VARGS *qgnutls_key_generate)(gnutls_datum_t * key, unsigned int key_size); -static void (VARGS *qgnutls_transport_set_pull_timeout_function)(gnutls_session_t session, gnutls_pull_timeout_func func); -static int (VARGS *qgnutls_dtls_cookie_verify)(gnutls_datum_t * key, void *client_data, size_t client_data_size, void *_msg, size_t msg_size, gnutls_dtls_prestate_st * prestate); -static int (VARGS *qgnutls_dtls_cookie_send)(gnutls_datum_t * key, void *client_data, size_t client_data_size, gnutls_dtls_prestate_st * prestate, gnutls_transport_ptr_t ptr, gnutls_push_func push_func); -static void (VARGS *qgnutls_dtls_prestate_set)(gnutls_session_t session, gnutls_dtls_prestate_st * prestate); -static void (VARGS *qgnutls_dtls_set_mtu)(gnutls_session_t session, unsigned int mtu); - -static int (VARGS *qgnutls_psk_allocate_server_credentials)(gnutls_psk_server_credentials_t *sc); -static void (VARGS *qgnutls_psk_set_server_credentials_function)(gnutls_psk_server_credentials_t cred, gnutls_psk_server_credentials_function *func); -static int (VARGS *qgnutls_psk_set_server_credentials_hint)(gnutls_psk_server_credentials_t res, const char *hint); -static const char *(VARGS *qgnutls_psk_client_get_hint)(gnutls_session_t session); -static int (VARGS *qgnutls_psk_allocate_client_credentials)(gnutls_psk_client_credentials_t *sc); -static void (VARGS *qgnutls_psk_set_client_credentials_function)(gnutls_psk_client_credentials_t cred, gnutls_psk_client_credentials_function *func); +#define GNUTLS_DTLS_STUFF \ + GNUTLS_FUNC(gnutls_key_generate,int,(gnutls_datum_t *key, unsigned int key_size)) \ + GNUTLS_FUNC(gnutls_privkey_sign_hash,int,(gnutls_privkey_t signer, gnutls_digest_algorithm_t hash_algo, unsigned int flags, const gnutls_datum_t * hash_data, gnutls_datum_t * signature)) \ + GNUTLS_FUNC(gnutls_certificate_get_x509_key,int,(gnutls_certificate_credentials_t res, unsigned index, gnutls_x509_privkey_t *key)) \ + GNUTLS_FUNC(gnutls_transport_set_pull_timeout_function,void,(gnutls_session_t session, gnutls_pull_timeout_func func)) \ + GNUTLS_FUNC(gnutls_dtls_cookie_verify,int,(gnutls_datum_t *key, void *client_data, size_t client_data_size, void *_msg, size_t msg_size, gnutls_dtls_prestate_st *prestate)) \ + GNUTLS_FUNC(gnutls_dtls_cookie_send,int,(gnutls_datum_t *key, void *client_data, size_t client_data_size, gnutls_dtls_prestate_st *prestate, gnutls_transport_ptr_t ptr, gnutls_push_func push_func)) \ + GNUTLS_FUNC(gnutls_dtls_prestate_set,void,(gnutls_session_t session, gnutls_dtls_prestate_st *prestate)) \ + GNUTLS_FUNC(gnutls_dtls_set_mtu,void,(gnutls_session_t session, unsigned int mtu)) \ + GNUTLS_FUNC(gnutls_psk_allocate_server_credentials,int,(gnutls_psk_server_credentials_t *sc)) \ + GNUTLS_FUNC(gnutls_psk_set_server_credentials_function,void,(gnutls_psk_server_credentials_t cred, gnutls_psk_server_credentials_function *func)) \ + GNUTLS_FUNC(gnutls_psk_set_server_credentials_hint,int,(gnutls_psk_server_credentials_t res, const char *hint)) \ + GNUTLS_FUNC(gnutls_psk_allocate_client_credentials,int,(gnutls_psk_client_credentials_t *sc)) \ + GNUTLS_FUNC(gnutls_psk_set_client_credentials_function,void,(gnutls_psk_client_credentials_t cred, gnutls_psk_client_credentials_function *func)) \ + GNUTLS_FUNC(gnutls_psk_client_get_hint,const char *,(gnutls_session_t session)) +#else + #define GNUTLS_DTLS_STUFF #endif -static unsigned int (VARGS *qgnutls_sec_param_to_pk_bits)(gnutls_pk_algorithm_t algo, gnutls_sec_param_t param); -static int (VARGS *qgnutls_x509_crt_init)(gnutls_x509_crt_t * cert); -static void (VARGS *qgnutls_x509_crt_deinit)(gnutls_x509_crt_t cert); -static int (VARGS *qgnutls_x509_crt_set_version)(gnutls_x509_crt_t crt, unsigned int version); -static int (VARGS *qgnutls_x509_crt_set_activation_time)(gnutls_x509_crt_t cert, time_t act_time); -static int (VARGS *qgnutls_x509_crt_set_expiration_time)(gnutls_x509_crt_t cert, time_t exp_time); -static int (VARGS *qgnutls_x509_crt_set_serial)(gnutls_x509_crt_t cert, const void *serial, size_t serial_size); -static int (VARGS *qgnutls_x509_crt_set_dn)(gnutls_x509_crt_t crt, const char *dn, const char **err); -static int (VARGS *qgnutls_x509_crt_set_issuer_dn)(gnutls_x509_crt_t crt, const char *dn, const char **err); -static int (VARGS *qgnutls_x509_crt_set_key)(gnutls_x509_crt_t crt, gnutls_x509_privkey_t key); -static int (VARGS *qgnutls_x509_crt_export2)(gnutls_x509_crt_t cert, gnutls_x509_crt_fmt_t format, gnutls_datum_t * out); -static int (VARGS *qgnutls_x509_crt_import)(gnutls_x509_crt_t cert, const gnutls_datum_t *data, gnutls_x509_crt_fmt_t format); -static int (VARGS *qgnutls_x509_privkey_init)(gnutls_x509_privkey_t * key); -static void (VARGS *qgnutls_x509_privkey_deinit)(gnutls_x509_privkey_t key); -static int (VARGS *qgnutls_x509_privkey_generate)(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags); -static int (VARGS *qgnutls_x509_privkey_export2)(gnutls_x509_privkey_t key, gnutls_x509_crt_fmt_t format, gnutls_datum_t * out); -static int (VARGS *qgnutls_x509_crt_privkey_sign)(gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, gnutls_privkey_t issuer_key, gnutls_digest_algorithm_t dig, unsigned int flags); -static int (VARGS *qgnutls_privkey_init)(gnutls_privkey_t * key); -static void (VARGS *qgnutls_privkey_deinit)(gnutls_privkey_t key); -static int (VARGS *qgnutls_privkey_import_x509)(gnutls_privkey_t pkey, gnutls_x509_privkey_t key, unsigned int flags); -//static int (VARGS *qgnutls_privkey_sign_hash2)(gnutls_privkey_t signer, gnutls_sign_algorithm_t algo, unsigned int flags, const gnutls_datum_t * hash_data, gnutls_datum_t * signature); -static int (VARGS *qgnutls_privkey_sign_hash)(gnutls_privkey_t signer, gnutls_digest_algorithm_t hash_algo, unsigned int flags, const gnutls_datum_t * hash_data, gnutls_datum_t * signature); -static int (VARGS *qgnutls_pubkey_init)(gnutls_pubkey_t * key); -static int (VARGS *qgnutls_pubkey_import_x509)(gnutls_pubkey_t key, gnutls_x509_crt_t crt, unsigned int flags); -static int (VARGS *qgnutls_pubkey_verify_hash2)(gnutls_pubkey_t key, gnutls_sign_algorithm_t algo, unsigned int flags, const gnutls_datum_t * hash, const gnutls_datum_t * signature); -static int (VARGS *qgnutls_certificate_set_x509_key_mem)(gnutls_certificate_credentials_t res, const gnutls_datum_t * cert, const gnutls_datum_t * key, gnutls_x509_crt_fmt_t type); -static int (VARGS *qgnutls_certificate_get_x509_key)(gnutls_certificate_credentials_t res, unsigned index, gnutls_x509_privkey_t *key); -static void (VARGS *qgnutls_certificate_free_credentials)(gnutls_certificate_credentials_t sc); + +#define GNUTLS_X509_STUFF \ + GNUTLS_FUNC(gnutls_sec_param_to_pk_bits,unsigned int,(gnutls_pk_algorithm_t algo, gnutls_sec_param_t param)) \ + GNUTLS_FUNC(gnutls_x509_crt_init,int,(gnutls_x509_crt_t * cert)) \ + GNUTLS_FUNC(gnutls_x509_crt_deinit,void,(gnutls_x509_crt_t cert)) \ + GNUTLS_FUNC(gnutls_x509_crt_import,int,(gnutls_x509_crt_t cert, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format)) \ + GNUTLS_FUNC(gnutls_x509_crt_set_version,int,(gnutls_x509_crt_t crt, unsigned int version)) \ + GNUTLS_FUNC(gnutls_x509_crt_set_activation_time,int,(gnutls_x509_crt_t cert, time_t act_time)) \ + GNUTLS_FUNC(gnutls_x509_crt_set_expiration_time,int,(gnutls_x509_crt_t cert, time_t exp_time)) \ + GNUTLS_FUNC(gnutls_x509_crt_set_serial,int,(gnutls_x509_crt_t cert, const void *serial, size_t serial_size)) \ + GNUTLS_FUNC(gnutls_x509_crt_set_dn,int,(gnutls_x509_crt_t crt, const char *dn, const char **err)) \ + GNUTLS_FUNC(gnutls_x509_crt_set_issuer_dn,int,(gnutls_x509_crt_t crt,const char *dn, const char **err)) \ + GNUTLS_FUNC(gnutls_x509_crt_set_key,int,(gnutls_x509_crt_t crt, gnutls_x509_privkey_t key)) \ + GNUTLS_FUNC(gnutls_x509_crt_export2,int,(gnutls_x509_crt_t cert, gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)) \ + GNUTLS_FUNC(gnutls_x509_privkey_init,int,(gnutls_x509_privkey_t * key)) \ + GNUTLS_FUNC(gnutls_x509_privkey_deinit,void,(gnutls_x509_privkey_t key)) \ + GNUTLS_FUNC(gnutls_x509_privkey_generate,int,(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags)) \ + GNUTLS_FUNC(gnutls_x509_privkey_export2,int,(gnutls_x509_privkey_t key, gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)) \ + GNUTLS_FUNC(gnutls_x509_crt_privkey_sign,int,(gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, gnutls_privkey_t issuer_key, gnutls_digest_algorithm_t dig, unsigned int flags)) \ + GNUTLS_FUNC(gnutls_privkey_init,int,(gnutls_privkey_t * key)) \ + GNUTLS_FUNC(gnutls_privkey_deinit,void,(gnutls_privkey_t key)) \ + GNUTLS_FUNC(gnutls_privkey_import_x509,int,(gnutls_privkey_t pkey, gnutls_x509_privkey_t key, unsigned int flags)) \ + GNUTLS_FUNC(gnutls_certificate_set_x509_key_mem,int,(gnutls_certificate_credentials_t res, const gnutls_datum_t * cert, const gnutls_datum_t * key, gnutls_x509_crt_fmt_t type)) \ + GNUTLS_FUNC(gnutls_pubkey_init,int,(gnutls_pubkey_t * key)) \ + GNUTLS_FUNC(gnutls_pubkey_deinit,void,(gnutls_pubkey_t key)) \ + GNUTLS_FUNC(gnutls_pubkey_import_x509,int,(gnutls_pubkey_t key, gnutls_x509_crt_t crt, unsigned int flags)) \ + GNUTLS_FUNC(gnutls_pubkey_verify_hash2,int,(gnutls_pubkey_t key, gnutls_sign_algorithm_t algo, unsigned int flags, const gnutls_datum_t * hash, const gnutls_datum_t * signature)) + + +#define GNUTLS_FUNCS \ + GNUTLS_FUNC(gnutls_bye,int,(gnutls_session_t session, gnutls_close_request_t how)) \ + GNUTLS_FUNC(gnutls_alert_get,gnutls_alert_description_t,(gnutls_session_t session)) \ + GNUTLS_FUNC(gnutls_alert_get_name,const char *,(gnutls_alert_description_t alert)) \ + GNUTLS_FUNC(gnutls_perror,void,(int error)) \ + GNUTLS_FUNC(gnutls_handshake,int,(gnutls_session_t session)) \ + GNUTLS_FUNC(gnutls_transport_set_ptr,void,(gnutls_session_t session, gnutls_transport_ptr_t ptr)) \ + GNUTLS_FUNC(gnutls_transport_set_push_function,void,(gnutls_session_t session, gnutls_push_func push_func)) \ + GNUTLS_FUNC(gnutls_transport_set_pull_function,void,(gnutls_session_t session, gnutls_pull_func pull_func)) \ + GNUTLS_FUNC(gnutls_transport_set_errno,void,(gnutls_session_t session, int err)) \ + GNUTLS_FUNC(gnutls_error_is_fatal,int,(int error)) \ + GNUTLS_FUNC(gnutls_credentials_set,int,(gnutls_session_t, gnutls_credentials_type_t type, void* cred)) \ + GNUTLS_FUNC(gnutls_init,int,(gnutls_session_t * session, gnutls_connection_end_t con_end)) \ + GNUTLS_FUNC(gnutls_deinit,void,(gnutls_session_t session)) \ + GNUTLS_FUNC(gnutls_set_default_priority,int,(gnutls_session_t session)) \ + GNUTLS_FUNC(gnutls_certificate_allocate_credentials,int,(gnutls_certificate_credentials_t *sc)) \ + GNUTLS_FUNC(gnutls_certificate_free_credentials,void,(gnutls_certificate_credentials_t sc)) \ + GNUTLS_FUNC(gnutls_session_channel_binding,int,(gnutls_session_t session, gnutls_channel_binding_t cbtype, gnutls_datum_t * cb)) \ + GNUTLS_FUNC(gnutls_global_init,int,(void)) \ + GNUTLS_FUNC(gnutls_global_deinit,void,(void)) \ + GNUTLS_FUNC(gnutls_record_send,ssize_t,(gnutls_session_t session, const void *data, size_t sizeofdata)) \ + GNUTLS_FUNC(gnutls_record_recv,ssize_t,(gnutls_session_t session, void *data, size_t sizeofdata)) \ + GNUTLS_FUNC(gnutls_certificate_set_verify_function,void,(gnutls_certificate_credentials_t cred, gnutls_certificate_verify_function *func)) \ + GNUTLS_FUNC(gnutls_session_get_ptr,void*,(gnutls_session_t session)) \ + GNUTLS_FUNC(gnutls_session_set_ptr,void,(gnutls_session_t session, void *ptr)) \ + GNUTLS_FUNCPTR(gnutls_malloc,void*,(size_t)) \ + GNUTLS_FUNCPTR(gnutls_free,void,(void * ptr)) \ + GNUTLS_FUNC(gnutls_server_name_set,int,(gnutls_session_t session, gnutls_server_name_type_t type, const void * name, size_t name_length)) \ + GNUTLS_TRUSTFUNCS \ + GNUTLS_VERIFYFUNCS \ + GNUTLS_DTLS_STUFF \ + GNUTLS_X509_STUFF + + +#ifdef GNUTLS_DYNAMIC + #define GNUTLS_FUNC(n,ret,args) static ret (VARGS *q##n)args; + #define GNUTLS_FUNCPTR(n,ret,args) static ret (VARGS **q##n)args; +#else + #define GNUTLS_FUNC(n,ret,args) static ret (VARGS *q##n)args = n; + #define GNUTLS_FUNCPTR(n,ret,args) static ret (VARGS **q##n)args = &n; +#endif + +#ifdef HAVE_DTLS + GNUTLS_FUNC(gnutls_set_default_priority_append,int,(gnutls_session_t session, const char *add_prio, const char **err_pos, unsigned flags)) +#endif +GNUTLS_FUNCS + +#undef GNUTLS_FUNC +#undef GNUTLS_FUNCPTR #if defined(GNUTLS_DYNAMIC) && defined(HAVE_DTLS) static int VARGS fallback_gnutls_set_default_priority_append(gnutls_session_t session, const char *add_prio, const char **err_pos, unsigned flags) @@ -241,226 +266,45 @@ static int VARGS fallback_gnutls_set_default_priority_append(gnutls_session_t se } #endif -static qboolean Init_GNUTLS(void) +static struct { -#ifdef GNUTLS_HAVE_SYSTEMTRUST - #define GNUTLS_TRUSTFUNCS GNUTLS_FUNC(gnutls_certificate_set_x509_system_trust) -#else - #define GNUTLS_TRUSTFUNCS GNUTLS_FUNC(gnutls_certificate_set_x509_trust_file) -#endif -#ifdef GNUTLS_HAVE_VERIFY3 - #define GNUTLS_VERIFYFUNCS \ - GNUTLS_FUNC(gnutls_certificate_verify_peers3) \ - GNUTLS_FUNC(gnutls_certificate_verification_status_print) \ - GNUTLS_FUNC(gnutls_certificate_get_peers) -#else - #define GNUTLS_VERIFYFUNCS \ - GNUTLS_FUNC(gnutls_certificate_verify_peers2) \ - GNUTLS_FUNC(gnutls_x509_crt_check_hostname) \ - GNUTLS_FUNC(gnutls_x509_crt_init) \ - GNUTLS_FUNC(gnutls_x509_crt_import) \ - GNUTLS_FUNC(gnutls_certificate_get_peers) -#endif - -#ifdef HAVE_DTLS -#define GNUTLS_DTLS_STUFF \ - GNUTLS_FUNC(gnutls_key_generate) \ - GNUTLS_FUNC(gnutls_transport_set_pull_timeout_function) \ - GNUTLS_FUNC(gnutls_dtls_cookie_verify) \ - GNUTLS_FUNC(gnutls_dtls_cookie_send) \ - GNUTLS_FUNC(gnutls_dtls_prestate_set) \ - GNUTLS_FUNC(gnutls_dtls_set_mtu) \ - GNUTLS_FUNC(gnutls_psk_allocate_server_credentials) \ - GNUTLS_FUNC(gnutls_psk_set_server_credentials_function) \ - GNUTLS_FUNC(gnutls_psk_set_server_credentials_hint) \ - GNUTLS_FUNC(gnutls_psk_allocate_client_credentials) \ - GNUTLS_FUNC(gnutls_psk_set_client_credentials_function) -#else - #define GNUTLS_DTLS_STUFF -#endif - - -#define GNUTLS_X509_STUFF \ - GNUTLS_FUNC(gnutls_sec_param_to_pk_bits) \ - GNUTLS_FUNC(gnutls_x509_crt_init) \ - GNUTLS_FUNC(gnutls_x509_crt_deinit) \ - GNUTLS_FUNC(gnutls_x509_crt_set_version) \ - GNUTLS_FUNC(gnutls_x509_crt_set_activation_time) \ - GNUTLS_FUNC(gnutls_x509_crt_set_expiration_time) \ - GNUTLS_FUNC(gnutls_x509_crt_set_serial) \ - GNUTLS_FUNC(gnutls_x509_crt_set_dn) \ - GNUTLS_FUNC(gnutls_x509_crt_set_issuer_dn) \ - GNUTLS_FUNC(gnutls_x509_crt_set_key) \ - GNUTLS_FUNC(gnutls_x509_crt_export2) \ - GNUTLS_FUNC(gnutls_x509_privkey_init) \ - GNUTLS_FUNC(gnutls_x509_privkey_deinit) \ - GNUTLS_FUNC(gnutls_x509_privkey_generate) \ - GNUTLS_FUNC(gnutls_x509_privkey_export2) \ - GNUTLS_FUNC(gnutls_x509_crt_privkey_sign) \ - GNUTLS_FUNC(gnutls_privkey_init) \ - GNUTLS_FUNC(gnutls_privkey_deinit) \ - GNUTLS_FUNC(gnutls_privkey_import_x509) \ - GNUTLS_FUNC(gnutls_certificate_set_x509_key_mem) - - - -#define GNUTLS_FUNCS \ - GNUTLS_FUNC(gnutls_bye) \ - GNUTLS_FUNC(gnutls_alert_get) \ - GNUTLS_FUNC(gnutls_alert_get_name) \ - GNUTLS_FUNC(gnutls_perror) \ - GNUTLS_FUNC(gnutls_handshake) \ - GNUTLS_FUNC(gnutls_transport_set_ptr) \ - GNUTLS_FUNC(gnutls_transport_set_push_function) \ - GNUTLS_FUNC(gnutls_transport_set_pull_function) \ - GNUTLS_FUNC(gnutls_transport_set_errno) \ - GNUTLS_FUNC(gnutls_error_is_fatal) \ - GNUTLS_FUNC(gnutls_credentials_set) \ - GNUTLS_FUNC(gnutls_init) \ - GNUTLS_FUNC(gnutls_deinit) \ - GNUTLS_FUNC(gnutls_set_default_priority) \ - GNUTLS_FUNC(gnutls_certificate_allocate_credentials) \ - GNUTLS_FUNC(gnutls_anon_allocate_client_credentials) \ - GNUTLS_FUNC(gnutls_global_init) \ - GNUTLS_FUNC(gnutls_record_send) \ - GNUTLS_FUNC(gnutls_record_recv) \ - GNUTLS_FUNC(gnutls_certificate_set_verify_function) \ - GNUTLS_FUNC(gnutls_session_get_ptr) \ - GNUTLS_FUNC(gnutls_session_set_ptr) \ - GNUTLS_TRUSTFUNCS \ - GNUTLS_FUNC(gnutls_certificate_set_x509_key_file) \ - GNUTLS_VERIFYFUNCS \ - GNUTLS_FUNC(gnutls_certificate_type_get) \ - GNUTLS_FUNCPTR(gnutls_malloc) \ - GNUTLS_FUNCPTR(gnutls_free) \ - GNUTLS_FUNC(gnutls_server_name_set) \ - GNUTLS_DTLS_STUFF \ - GNUTLS_X509_STUFF - #ifdef GNUTLS_DYNAMIC dllhandle_t *hmod; +#endif + int initstatus[2]; +} gnutls; + +static qboolean Init_GNUTLS(void) +{ +#ifdef GNUTLS_DYNAMIC dllfunction_t functable[] = { -//#define GNUTLS_FUNC(nam) {(void**)&q##nam, #nam}, -// GNUTLS_FUNCS -//#undef GNUTLS_FUNC - {(void**)&qgnutls_bye, "gnutls_bye"}, - {(void**)&qgnutls_perror, "gnutls_perror"}, - {(void**)&qgnutls_alert_get, "gnutls_alert_get"}, - {(void**)&qgnutls_alert_get_name, "gnutls_alert_get_name"}, - {(void**)&qgnutls_handshake, "gnutls_handshake"}, - {(void**)&qgnutls_transport_set_ptr, "gnutls_transport_set_ptr"}, - {(void**)&qgnutls_transport_set_push_function, "gnutls_transport_set_push_function"}, - {(void**)&qgnutls_transport_set_pull_function, "gnutls_transport_set_pull_function"}, - {(void**)&qgnutls_transport_set_errno, "gnutls_transport_set_errno"}, - {(void**)&qgnutls_error_is_fatal, "gnutls_error_is_fatal"}, - {(void**)&qgnutls_credentials_set, "gnutls_credentials_set"}, -// {(void**)&qgnutls_kx_set_priority, "gnutls_kx_set_priority"}, - {(void**)&qgnutls_init, "gnutls_init"}, - {(void**)&qgnutls_deinit, "gnutls_deinit"}, - {(void**)&qgnutls_set_default_priority, "gnutls_set_default_priority"}, - {(void**)&qgnutls_certificate_allocate_credentials, "gnutls_certificate_allocate_credentials"}, - {(void**)&qgnutls_anon_allocate_client_credentials, "gnutls_anon_allocate_client_credentials"}, - {(void**)&qgnutls_global_init, "gnutls_global_init"}, - {(void**)&qgnutls_record_send, "gnutls_record_send"}, - {(void**)&qgnutls_record_recv, "gnutls_record_recv"}, - - {(void**)&qgnutls_certificate_set_verify_function, "gnutls_certificate_set_verify_function"}, - {(void**)&qgnutls_session_get_ptr, "gnutls_session_get_ptr"}, - {(void**)&qgnutls_session_set_ptr, "gnutls_session_set_ptr"}, - {(void**)&qgnutls_session_channel_binding, "gnutls_session_channel_binding"}, -#ifdef GNUTLS_HAVE_SYSTEMTRUST - {(void**)&qgnutls_certificate_set_x509_system_trust, "gnutls_certificate_set_x509_system_trust"}, -#else - {(void**)&qgnutls_certificate_set_x509_trust_file, "gnutls_certificate_set_x509_trust_file"}, -#endif - {(void**)&qgnutls_certificate_set_x509_key_file, "gnutls_certificate_set_x509_key_file"}, -#ifdef GNUTLS_HAVE_VERIFY3 - {(void**)&qgnutls_certificate_verify_peers3, "gnutls_certificate_verify_peers3"}, - {(void**)&qgnutls_certificate_verification_status_print, "gnutls_certificate_verification_status_print"}, -#else - {(void**)&qgnutls_certificate_verify_peers2, "gnutls_certificate_verify_peers2"}, - {(void**)&qgnutls_x509_crt_init, "gnutls_x509_crt_init"}, - {(void**)&qgnutls_x509_crt_import, "gnutls_x509_crt_import"}, - {(void**)&qgnutls_x509_crt_check_hostname, "gnutls_x509_crt_check_hostname"}, -#endif - {(void**)&qgnutls_certificate_get_peers, "gnutls_certificate_get_peers"}, - {(void**)&qgnutls_certificate_type_get, "gnutls_certificate_type_get"}, - {(void**)&qgnutls_malloc, "gnutls_malloc"}, - {(void**)&qgnutls_free, "gnutls_free"}, - {(void**)&qgnutls_server_name_set, "gnutls_server_name_set"}, - -#ifdef HAVE_DTLS - {(void**)&qgnutls_key_generate, "gnutls_key_generate"}, - {(void**)&qgnutls_transport_set_pull_timeout_function, "gnutls_transport_set_pull_timeout_function"}, - {(void**)&qgnutls_dtls_cookie_verify, "gnutls_dtls_cookie_verify"}, - {(void**)&qgnutls_dtls_cookie_send, "gnutls_dtls_cookie_send"}, - {(void**)&qgnutls_dtls_prestate_set, "gnutls_dtls_prestate_set"}, - {(void**)&qgnutls_dtls_set_mtu, "gnutls_dtls_set_mtu"}, - - {(void**)&qgnutls_psk_allocate_server_credentials, "gnutls_psk_allocate_server_credentials"}, - {(void**)&qgnutls_psk_set_server_credentials_function, "gnutls_psk_set_server_credentials_function"}, - {(void**)&qgnutls_psk_set_server_credentials_hint, "gnutls_psk_set_server_credentials_hint"}, - {(void**)&qgnutls_psk_client_get_hint, "gnutls_psk_client_get_hint"}, - {(void**)&qgnutls_psk_allocate_client_credentials, "gnutls_psk_allocate_client_credentials"}, - {(void**)&qgnutls_psk_set_client_credentials_function, "gnutls_psk_set_client_credentials_function"}, -#endif - - {(void**)&qgnutls_sec_param_to_pk_bits, "gnutls_sec_param_to_pk_bits"}, - {(void**)&qgnutls_x509_crt_init, "gnutls_x509_crt_init"}, - {(void**)&qgnutls_x509_crt_deinit, "gnutls_x509_crt_deinit"}, - {(void**)&qgnutls_x509_crt_set_version, "gnutls_x509_crt_set_version"}, - {(void**)&qgnutls_x509_crt_set_activation_time, "gnutls_x509_crt_set_activation_time"}, - {(void**)&qgnutls_x509_crt_set_expiration_time, "gnutls_x509_crt_set_expiration_time"}, - {(void**)&qgnutls_x509_crt_set_serial, "gnutls_x509_crt_set_serial"}, - {(void**)&qgnutls_x509_crt_set_dn, "gnutls_x509_crt_set_dn"}, - {(void**)&qgnutls_x509_crt_set_issuer_dn, "gnutls_x509_crt_set_issuer_dn"}, - {(void**)&qgnutls_x509_crt_set_key, "gnutls_x509_crt_set_key"}, - {(void**)&qgnutls_x509_crt_export2, "gnutls_x509_crt_export2"}, - {(void**)&qgnutls_x509_privkey_init, "gnutls_x509_privkey_init"}, - {(void**)&qgnutls_x509_privkey_deinit, "gnutls_x509_privkey_deinit"}, - {(void**)&qgnutls_x509_privkey_generate, "gnutls_x509_privkey_generate"}, - {(void**)&qgnutls_x509_privkey_export2, "gnutls_x509_privkey_export2"}, - {(void**)&qgnutls_x509_crt_privkey_sign, "gnutls_x509_crt_privkey_sign"}, - {(void**)&qgnutls_privkey_init, "gnutls_privkey_init"}, - {(void**)&qgnutls_privkey_deinit, "gnutls_privkey_deinit"}, - {(void**)&qgnutls_privkey_import_x509, "gnutls_privkey_import_x509"}, - {(void**)&qgnutls_certificate_set_x509_key_mem, "gnutls_certificate_set_x509_key_mem"}, - - {(void**)&qgnutls_certificate_get_x509_key, "gnutls_certificate_get_x509_key"}, - {(void**)&qgnutls_certificate_free_credentials, "gnutls_certificate_free_credentials"}, - {(void**)&qgnutls_pubkey_init, "gnutls_pubkey_init"}, - {(void**)&qgnutls_pubkey_import_x509, "gnutls_pubkey_import_x509"}, - {(void**)&qgnutls_privkey_sign_hash, "gnutls_privkey_sign_hash"}, - {(void**)&qgnutls_pubkey_verify_hash2, "gnutls_pubkey_verify_hash2"}, - {(void**)&qgnutls_x509_crt_import, "gnutls_x509_crt_import"}, +#define GNUTLS_FUNC(nam,ret,args) {(void**)&q##nam, #nam}, +#define GNUTLS_FUNCPTR(nam,ret,args) {(void**)&q##nam, #nam}, + GNUTLS_FUNCS +#undef GNUTLS_FUNC +#undef GNUTLS_FUNCPTR {NULL, NULL} }; #ifdef GNUTLS_SONUM #ifdef __CYGWIN__ - hmod = Sys_LoadLibrary("cyggnutls"GNUTLS_SOPREFIX"-"STRINGIFY(GNUTLS_SONUM)".dll", functable); + gnutls.hmod = Sys_LoadLibrary("cyggnutls"GNUTLS_SOPREFIX"-"STRINGIFY(GNUTLS_SONUM)".dll", functable); #else - hmod = Sys_LoadLibrary("libgnutls"GNUTLS_SOPREFIX".so."STRINGIFY(GNUTLS_SONUM), functable); + gnutls.hmod = Sys_LoadLibrary("libgnutls"GNUTLS_SOPREFIX".so."STRINGIFY(GNUTLS_SONUM), functable); #endif #else - hmod = Sys_LoadLibrary("libgnutls"GNUTLS_SOPREFIX".so", functable); //hope and pray + gnutls.hmod = Sys_LoadLibrary("libgnutls"GNUTLS_SOPREFIX".so", functable); //hope and pray #endif - if (!hmod) + if (!gnutls.hmod) return false; #ifdef HAVE_DTLS - qgnutls_set_default_priority_append = Sys_GetAddressForName(hmod, "gnutls_set_default_priority_append"); + qgnutls_set_default_priority_append = Sys_GetAddressForName(gnutls.hmod, "gnutls_set_default_priority_append"); if (!qgnutls_set_default_priority_append) qgnutls_set_default_priority_append = fallback_gnutls_set_default_priority_append; #endif -#else - #define GNUTLS_FUNC(name) q##name = name; - #define GNUTLS_FUNCPTR(name) q##name = &name; - GNUTLS_FUNCS - #undef GNUTLS_FUNC - #undef GNUTLS_FUNCPTR #endif return true; } @@ -567,6 +411,12 @@ static void SSL_Close(vfsfile_t *vfs) qgnutls_deinit(file->session); file->session = NULL; } + + if (file->certcred) + { + qgnutls_certificate_free_credentials(file->certcred); + file->certcred = NULL; + } } static qboolean QDECL SSL_CloseFile(vfsfile_t *vfs) { @@ -1222,6 +1072,9 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred) if (pub.size != VFS_READ(pubf, pub.data, pub.size)) pub.size = 0; pub.data[pub.size] = 0; + + VFS_CLOSE(privf); + VFS_CLOSE(pubf); } //FIXME: extend the expiration time if its old? @@ -1247,7 +1100,6 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred) qboolean SSL_InitGlobal(qboolean isserver) { int err; - static int initstatus[2]; isserver = !!isserver; if (COM_CheckParm("-notls")) return false; @@ -1255,7 +1107,7 @@ qboolean SSL_InitGlobal(qboolean isserver) if (com_resourcemutex) Sys_LockMutex(com_resourcemutex); #endif - if (!initstatus[isserver]) + if (!gnutls.initstatus[isserver]) { if (!Init_GNUTLS()) { @@ -1266,7 +1118,7 @@ qboolean SSL_InitGlobal(qboolean isserver) Con_Printf("GnuTLS "GNUTLS_VERSION" library not available.\n"); return false; } - initstatus[isserver] = true; + gnutls.initstatus[isserver] = true; qgnutls_global_init (); #ifdef HAVE_DTLS @@ -1309,7 +1161,7 @@ qboolean SSL_InitGlobal(qboolean isserver) if (ret < 0) { Con_Printf(CON_ERROR"No certificate or key was found in %s and %s\n", certfile, keyfile); - initstatus[isserver] = -1; + gnutls.initstatus[isserver] = -1; } #endif } @@ -1325,10 +1177,31 @@ qboolean SSL_InitGlobal(qboolean isserver) #endif } - if (initstatus[isserver] < 0) + if (gnutls.initstatus[isserver] < 0) return false; return true; } + +void GnuTLS_Shutdown(void) +{ + int isserver; + for (isserver = 0; isserver < 2; isserver++) + if (gnutls.initstatus[isserver]) + { + qgnutls_certificate_free_credentials(xcred[isserver]); + xcred[isserver] = NULL; + gnutls.initstatus[isserver] = false; + + qgnutls_global_deinit(); //refcounted. + } +#ifdef GNUTLS_DYNAMIC + if (gnutls.hmod) + Sys_CloseLibrary(gnutls.hmod); + gnutls.hmod = NULL; +#endif +} + + #ifdef HAVE_DTLS static int GetPSKForUser(gnutls_session_t sess, const char *username, gnutls_datum_t * key) { //serverside. name must match what we expect (this isn't very secure), and we return the key we require for that user name. @@ -1506,6 +1379,7 @@ static int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bind } //crypto: generates a signed blob +#ifdef HAVE_DTLS static int GNUTLS_GenerateSignature(const qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax) { gnutls_datum_t hash = {(qbyte*)hashdata, hashsize}; @@ -1535,6 +1409,9 @@ static int GNUTLS_GenerateSignature(const qbyte *hashdata, size_t hashsize, qbyt memcpy(signdata, sign.data, sign.size); return sign.size; } +#else +#define GNUTLS_GenerateSignature NULL +#endif //crypto: verifies a signed blob matches an authority's public cert. windows equivelent https://docs.microsoft.com/en-us/windows/win32/seccrypto/example-c-program-signing-a-hash-and-verifying-the-hash-signature static enum hashvalidation_e GNUTLS_VerifyHash(const qbyte *hashdata, size_t hashsize, const qbyte *pubkeydata, size_t pubkeysize, const qbyte *signdata, size_t signsize) @@ -1563,6 +1440,8 @@ static enum hashvalidation_e GNUTLS_VerifyHash(const qbyte *hashdata, size_t has #endif r = qgnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA512, 0, &hash, &sign); + qgnutls_x509_crt_deinit(cert); + qgnutls_pubkey_deinit(pubkey); if (r < 0) { if (r == GNUTLS_E_PK_SIG_VERIFY_FAILED) @@ -1586,6 +1465,7 @@ static enum hashvalidation_e GNUTLS_VerifyHash(const qbyte *hashdata, size_t has static void GNUDTLS_DestroyContext(void *ctx) { SSL_Close(ctx); + Z_Free(ctx); } static void *GNUDTLS_CreateContext(const dtlscred_t *credinfo, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver) { @@ -1621,6 +1501,7 @@ static void *GNUDTLS_CreateContext(const dtlscred_t *credinfo, void *cbctx, nete if (!SSL_InitConnection(newf, isserver, true)) { SSL_Close(&newf->funcs); + Z_Free(newf); return NULL; } diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 9c1d59db7..6cacd3ec4 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -9240,7 +9240,8 @@ void NET_Shutdown (void) #ifdef HAVE_EPOLL - close(epoll_fd); + if (epoll_fd >= 0) + close(epoll_fd); epoll_fd = -1; stdin_epolling = false; #endif diff --git a/engine/common/netinc.h b/engine/common/netinc.h index 155f9be2f..c19aa9cc3 100644 --- a/engine/common/netinc.h +++ b/engine/common/netinc.h @@ -268,7 +268,7 @@ enum icemode_e { ICEM_RAW, //not actually interactive beyond a simple handshake. ICEM_ICE, //rfc5245. meant to be able to holepunch, but not implemented properly yet. - ICEM_WEBRTC, //IP+UDP+ICE+DTLS+SCTP... no more layers? :o + ICEM_WEBRTC, //IP+UDP+((ICE/STUN/SDP)+(DTLS+SCTP))... no more layers? :o }; enum icestate_e { diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 57c86d3ee..1bc61dbe0 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -190,6 +190,9 @@ static plugin_t *Plug_Load(const char *file) return newplug; } + if (COM_CheckParm("-noplugins")) + return NULL; + newplug = Z_Malloc(sizeof(plugin_t)+strlen(temp)+1); newplug->name = (char*)(newplug+1); strcpy(newplug->name, temp); diff --git a/engine/common/sys.h b/engine/common/sys.h index a7ed12921..867d91b08 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -105,7 +105,7 @@ qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refres #if defined(__GNUC__) #define qatomic32_t qint32_t #define FTE_Atomic32_Inc(ptr) __sync_add_and_fetch(ptr, 1) //returns the AFTER the operation. - #define FTE_Atomic32_Dec(ptr) __sync_add_and_fetch(ptr, 1) //returns the AFTER the operation. + #define FTE_Atomic32_Dec(ptr) __sync_add_and_fetch(ptr, -1) //returns the AFTER the operation. #elif defined(_WIN32) #define qatomic32_t long #define FTE_Atomic32_Inc(ptr) _InterlockedIncrement(ptr) diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 0a236e57e..28a289d40 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -872,7 +872,10 @@ qboolean R_ImportRTLights(const char *entlump, int importmode) } if (!importmode && !rerelease) + { + InfoBuf_Clear(&targets, true); return false; //don't make it up from legacy ents. + } for (entnum = 0; ;entnum++) { @@ -1119,6 +1122,7 @@ qboolean R_ImportRTLights(const char *entlump, int importmode) if (atoi(value)) { okay = true; + InfoBuf_Clear(&targets, true); return okay; } } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 65860ad25..4ee1b57fd 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -11880,7 +11880,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"log", PF_Logarithm, 0, 0, 0, 532, D("float(float v, optional float base)", "Determines the logarithm of the input value according to the specified base. This can be used to calculate how much something was shifted by.")}, {"soundupdate", PF_Fixme, 0, 0, 0, 0, D("float(entity e, float channel, string newsample, float volume, float attenuation, float pitchpct, float flags, float timeoffset)", "Changes the properties of the current sound being played on the given entity channel. newsample may be empty, and will be ignored in this case. timeoffset is relative to the current position (subtract the result of getsoundtime for absolute positions). Negative volume can be used to stop the sound. Return value is a fractional value based upon the number of audio devices that could be updated - test against TRUE rather than non-zero.")}, {"getsoundtime", PF_Ignore, 0, 0, 0, 533, D("float(entity e, float channel)", "Returns the current playback time of the sample on the given entity's channel. Beware CHAN_AUTO (in csqc, channels are not limited by network protocol).")}, - {"getchannellevel", PF_Ignore, 0, 0, 0, 0, D("float(entity e, float channel)", "")}, + {"getchannellevel", PF_Ignore, 0, 0, 0, 0, D("float(entity e, float channel)", "Reports how load the sound's sample is at its current offset.")}, {"soundlength", PF_Ignore, 0, 0, 0, 534, D("float(string sample)", "Provides a way to query the duration of a sound sample, allowing you to set up a timer to chain samples.")}, {"buf_loadfile", PF_buf_loadfile, 0, 0, 0, 535, D("float(string filename, strbuf bufhandle)", "Appends the named file into a string buffer (which must have been created in advance). The return value merely says whether the file was readable.")}, {"buf_writefile", PF_buf_writefile, 0, 0, 0, 536, D("float(filestream filehandle, strbuf bufhandle, optional float startpos, optional float numstrings)", "Writes the contents of a string buffer onto the end of the supplied filehandle (you must have already used fopen). Additional optional arguments permit you to constrain the writes to a subsection of the stringbuffer.")}, diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index b73de90c4..03a3f26ed 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -278,6 +278,10 @@ void SV_Shutdown (void) Z_Free(lp); } +#ifdef WEBCLIENT + HTTP_CL_Terminate(); +#endif + #ifdef HEXEN2 T_FreeStrings(); #endif diff --git a/engine/server/sv_sys_unix.c b/engine/server/sv_sys_unix.c index 4177c52a5..d817f6dd7 100644 --- a/engine/server/sv_sys_unix.c +++ b/engine/server/sv_sys_unix.c @@ -54,13 +54,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "netinc.h" #endif +#ifdef HAVE_GNUTLS +qboolean SSL_InitGlobal(qboolean isserver); +void GnuTLS_Shutdown(void); +#endif + // callbacks void Sys_Linebuffer_Callback (struct cvar_s *var, char *oldvalue); cvar_t sys_nostdout = CVAR("sys_nostdout","0"); cvar_t sys_extrasleep = CVAR("sys_extrasleep","0"); -cvar_t sys_colorconsole = CVAR("sys_colorconsole", "1"); +cvar_t sys_colorconsole = CVARD("sys_colorconsole", "1", "Parse colour escapes, with ansi colours on stdout."); +cvar_t sys_timestamps = CVARD("sys_timestamps", "0", "Show timesamps on stdout prints."); cvar_t sys_linebuffer = CVARC("sys_linebuffer", "1", Sys_Linebuffer_Callback); static qboolean stdin_ready; @@ -429,6 +435,7 @@ void Sys_Printf (char *fmt, ...) conchar_t *e, *c; conchar_t ctext[MAXPRINTMSG]; unsigned int codeflags, codepoint; + static qboolean wasnl = false; e = COM_ParseFunString(CON_WHITEMASK, msg, ctext, sizeof(ctext), false); for (c = ctext; c < e; ) { @@ -439,7 +446,17 @@ void Sys_Printf (char *fmt, ...) if ((codeflags&CON_RICHFORECOLOUR) || (codepoint == '\n' && (codeflags&CON_NONCLEARBG))) codeflags = CON_WHITEMASK; //make sure we don't get annoying backgrounds on other lines. ApplyColour(codeflags); + + if (wasnl && sys_timestamps.ival) + { + char buffer[64]; + time_t unixtime = time(NULL); + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S ", localtime(&unixtime)); + for (w = 0; w < buffer[w]; w++) + putc(buffer[w], stdout); + } w = codepoint; + wasnl = (w == '\n'); if (w >= 0xe000 && w < 0xe100) { /*not all quake chars are ascii compatible, so map those control chars to safe ones so we don't mess up anyone's xterm*/ @@ -567,6 +584,12 @@ Sys_Quit */ void Sys_Quit (void) { +#ifdef HAVE_SERVER + SV_Shutdown(); +#endif +#ifdef HAVE_GNUTLS + GnuTLS_Shutdown(); +#endif if (!noconinput) { tcsetattr(STDIN_FILENO, TCSADRAIN, &orig); @@ -742,6 +765,7 @@ void Sys_Init (void) Cvar_Register (&sys_extrasleep, "System configuration"); Cvar_Register (&sys_colorconsole, "System configuration"); + Cvar_Register (&sys_timestamps, "System configuration"); Cvar_Register (&sys_linebuffer, "System configuration"); } @@ -830,9 +854,6 @@ static void Friendly_Crash_Handler(int sig, siginfo_t *info, void *vcontext) } #endif -#ifdef HAVE_GNUTLS -qboolean SSL_InitGlobal(qboolean isserver); -#endif #ifdef SQL #include "sv_sql.h" #endif diff --git a/plugins/net_ssl_openssl.c b/plugins/net_ssl_openssl.c index f5b460c0f..3f97c2b64 100644 --- a/plugins/net_ssl_openssl.c +++ b/plugins/net_ssl_openssl.c @@ -264,14 +264,16 @@ static int OSSL_Verify_Peer(int preverify_ok, X509_STORE_CTX *x509_ctx) qbyte *blob; qbyte *end; blobsize = i2d_X509(cert, NULL); - if (blobsize != knownsize) - return 0; //fail if the size doesn't match. - blob = alloca(blobsize); - end = blob; - i2d_X509(cert, &end); - if (memcmp(blob, knowndata, blobsize)) - return 0; - return 1; //exact match to a known cert. yay. allow it. + if (blobsize == knownsize) + { //sizes must match. + blob = alloca(blobsize); + end = blob; + i2d_X509(cert, &end); + if (!memcmp(blob, knowndata, blobsize)) + preverify_ok = 1; //exact match to a known cert. yay. allow it. + } + plugfuncs->Free(knowndata); + return preverify_ok; } #ifdef HAVE_CLIENT @@ -1048,14 +1050,16 @@ static const dtlsfuncs_t *OSSL_InitServer(void) - +static struct +{ + qboolean inited; + qboolean init_success; +} ossl; static qboolean OSSL_Init(void) { - static qboolean inited; - static qboolean init_success; - if (inited) - return init_success; - inited = true; + if (ossl.inited) + return ossl.init_success; + ossl.inited = true; #if 0//def LOADERTHREAD Sys_LockMutex(com_resourcemutex); if (inited) //now check again, just in case @@ -1084,7 +1088,7 @@ static qboolean OSSL_Init(void) BIO_meth_set_create(biometh_vfs, OSSL_Bio_FCreate); BIO_meth_set_destroy(biometh_vfs, OSSL_Bio_FDestroy); BIO_meth_set_callback_ctrl(biometh_vfs, OSSL_Bio_FOtherCtrl); - init_success |= 1; + ossl.init_success |= 1; } biometh_dtls = BIO_meth_new(BIO_get_new_index()|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR, "fte_dtls"); @@ -1098,7 +1102,7 @@ static qboolean OSSL_Init(void) BIO_meth_set_create(biometh_dtls, OSSL_Bio_DCreate); BIO_meth_set_destroy(biometh_dtls, OSSL_Bio_DDestroy); BIO_meth_set_callback_ctrl(biometh_dtls, OSSL_Bio_DOtherCtrl); - init_success |= 2; + ossl.init_success |= 2; } ossl_fte_certctx = SSL_get_ex_new_index(0, "ossl_fte_certctx", NULL, NULL, NULL); @@ -1106,7 +1110,7 @@ static qboolean OSSL_Init(void) #if 0//def LOADERTHREAD Sys_UnlockMutex(com_resourcemutex); #endif - return init_success; + return ossl.init_success; } static enum hashvalidation_e OSSL_VerifyHash(const qbyte *hashdata, size_t hashsize, const qbyte *pubkeydata, size_t pubkeysize, const qbyte *signdata, size_t signsize) @@ -1151,12 +1155,32 @@ static ftecrypto_t crypto_openssl = NULL, }; +static void OSSL_PluginShutdown(void) +{ + ossl.inited = false; + ossl.init_success = false; + + X509_free(vhost.servercert); + EVP_PKEY_free(vhost.privatekey); + BIO_meth_free(biometh_vfs); + BIO_meth_free(biometh_dtls); +} +static qboolean OSSL_PluginMayShutdown(void) +{ + //the engine has a habit of holding on to handles without any refcounts, so don't allow it to die early. + return false; +} + qboolean Plug_Init(void) { fsfuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*fsfuncs)); netfuncs = plugfuncs->GetEngineInterface(plugnetfuncs_name, sizeof(*netfuncs)); if (!fsfuncs || !netfuncs) return false; + + plugfuncs->ExportFunction("Shutdown", OSSL_PluginShutdown); + plugfuncs->ExportFunction("MayUnload", OSSL_PluginMayShutdown); + pdtls_psk_hint = cvarfuncs->GetNVFDG("dtls_psk_hint", "", 0, NULL, "DTLS stuff"); pdtls_psk_user = cvarfuncs->GetNVFDG("dtls_psk_user", "", 0, NULL, "DTLS stuff"); pdtls_psk_key = cvarfuncs->GetNVFDG("dtls_psk_key", "", 0, NULL, "DTLS stuff");