Rework tls/dtls stuff into a more formal crypto interface instead of lots of ifdefs all over the place.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5891 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
1057453158
commit
d4714cab52
17 changed files with 229 additions and 246 deletions
|
@ -274,25 +274,6 @@ ELSEIF(${WIN32})
|
||||||
ELSEIF(${UNIX} AND NOT FTE_USE_SDL) #linux(ish)
|
ELSEIF(${UNIX} AND NOT FTE_USE_SDL) #linux(ish)
|
||||||
#openbsd will have issues with snd_linux.c
|
#openbsd will have issues with snd_linux.c
|
||||||
|
|
||||||
IF(FTE_PRIVATE_USE_ONLY)
|
|
||||||
#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. debian has not caught up with that yet, however.
|
|
||||||
FIND_PACKAGE(OpenSSL)
|
|
||||||
IF(NOT OPENSSL_FOUND)
|
|
||||||
MESSAGE(WARNING "openssl library NOT available. HTTPS/DTLS will not be available.")
|
|
||||||
ELSEIF(OPENSSL_VERSION_MAJOR LESS 3 AND NOT FTE_PRIVATE_USE_ONLY)
|
|
||||||
MESSAGE(WARNING "openssl library version is not 3 or above. Ignoring due to incompatible license.")
|
|
||||||
ELSE()
|
|
||||||
MESSAGE(WARNING "Using openssl.")
|
|
||||||
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};HAVE_OPENSSL)
|
|
||||||
|
|
||||||
SET(FTE_ARCH_FILES ${FTE_ARCH_FILES} engine/common/net_ssl_openssl.c)
|
|
||||||
SET(FTE_LIBS ${FTE_LIBS} ${OPENSSL_LIBRARIES})
|
|
||||||
SET(FTESV_ARCH_FILES ${FTESV_ARCH_FILES} engine/common/net_ssl_openssl.c)
|
|
||||||
SET(FTESV_LIBS ${FTESV_LIBS} ${OPENSSL_LIBRARIES})
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PACKAGE(GnuTLS)
|
FIND_PACKAGE(GnuTLS)
|
||||||
IF(NOT GNUTLS_FOUND)
|
IF(NOT GNUTLS_FOUND)
|
||||||
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
|
MESSAGE(WARNING "gnutls library NOT available. HTTPS/DTLS will not be available.")
|
||||||
|
@ -328,7 +309,6 @@ ELSEIF(${UNIX} AND NOT FTE_USE_SDL) #linux(ish)
|
||||||
engine/client/sys_linux.c
|
engine/client/sys_linux.c
|
||||||
engine/common/sys_linux_threads.c
|
engine/common/sys_linux_threads.c
|
||||||
engine/common/net_ssl_gnutls.c
|
engine/common/net_ssl_gnutls.c
|
||||||
# engine/common/net_ssl_openssl.c
|
|
||||||
|
|
||||||
engine/client/snd_al.c
|
engine/client/snd_al.c
|
||||||
engine/client/snd_alsa.c
|
engine/client/snd_alsa.c
|
||||||
|
@ -391,14 +371,9 @@ ELSEIF(${UNIX} AND NOT FTE_USE_SDL) #linux(ish)
|
||||||
engine/server/sv_sys_unix.c
|
engine/server/sv_sys_unix.c
|
||||||
engine/common/sys_linux_threads.c
|
engine/common/sys_linux_threads.c
|
||||||
engine/common/net_ssl_gnutls.c
|
engine/common/net_ssl_gnutls.c
|
||||||
# engine/common/net_ssl_openssl.c
|
|
||||||
)
|
)
|
||||||
SET(FTESV_LIBS ${FTESV_LIBS} ${SYS_LIBS} ${CMAKE_DL_LIBS} pthread)
|
SET(FTESV_LIBS ${FTESV_LIBS} ${SYS_LIBS} ${CMAKE_DL_LIBS} pthread)
|
||||||
|
|
||||||
# SET(FTE_DEFINES ${FTE_DEFINES};HAVE_OPENSSL)
|
|
||||||
# SET(FTESV_DEFINES ${FTESV_DEFINES};HAVE_OPENSSL)
|
|
||||||
# SET(FTE_LIBS ${FTE_LIBS} ssl crypto)
|
|
||||||
# SET(FTESV_LIBS ${FTE_LIBS} ssl crypto)
|
|
||||||
ELSEIF(1) #SDL
|
ELSEIF(1) #SDL
|
||||||
# FIND_PACKAGE(Freetype REQUIRED)
|
# FIND_PACKAGE(Freetype REQUIRED)
|
||||||
# INCLUDE_DIRECTORIES(engine/libs engine/libs/freetype2/include)
|
# INCLUDE_DIRECTORIES(engine/libs engine/libs/freetype2/include)
|
||||||
|
|
|
@ -361,9 +361,12 @@ void PM_ValidateAuthenticity(package_t *p, enum hashvalidation_e validated)
|
||||||
size_t hashsize = 0;
|
size_t hashsize = 0;
|
||||||
qbyte signdata[1024];
|
qbyte signdata[1024];
|
||||||
size_t signsize = 0;
|
size_t signsize = 0;
|
||||||
int r;
|
int r, i;
|
||||||
char authority[MAX_QPATH], *sig;
|
char authority[MAX_QPATH], *sig;
|
||||||
|
|
||||||
|
const qbyte *pubkey;
|
||||||
|
size_t pubkeysize;
|
||||||
|
|
||||||
#ifndef _DEBUG
|
#ifndef _DEBUG
|
||||||
#pragma message("Temporary code.")
|
#pragma message("Temporary code.")
|
||||||
//this is temporary code and should be removed once everything else has been fixed.
|
//this is temporary code and should be removed once everything else has been fixed.
|
||||||
|
@ -412,28 +415,25 @@ void PM_ValidateAuthenticity(package_t *p, enum hashvalidation_e validated)
|
||||||
sig++;
|
sig++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
strcpy(authority, "Spike"); //legacy bollocks
|
||||||
sig = p->signature;
|
sig = p->signature;
|
||||||
|
}
|
||||||
hashsize = Base16_DecodeBlock(p->filesha512, hashdata, sizeof(hashdata));
|
hashsize = Base16_DecodeBlock(p->filesha512, hashdata, sizeof(hashdata));
|
||||||
signsize = Base64_DecodeBlock(sig, NULL, signdata, sizeof(signdata));
|
signsize = Base64_DecodeBlock(sig, NULL, signdata, sizeof(signdata));
|
||||||
r = VH_UNSUPPORTED;//preliminary
|
r = VH_UNSUPPORTED;//preliminary
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)signsize;
|
pubkey = Auth_GetKnownCertificate(authority, &pubkeysize);
|
||||||
(void)hashsize;
|
if (!pubkey)
|
||||||
|
r = VH_AUTHORITY_UNKNOWN;
|
||||||
|
|
||||||
//try and get one of our providers to verify it...
|
//try and get one of our providers to verify it...
|
||||||
#ifdef HAVE_WINSSPI
|
for (i = 0; r==VH_UNSUPPORTED && i < cryptolib_count; i++)
|
||||||
if (r == VH_UNSUPPORTED)
|
{
|
||||||
r = SSPI_VerifyHash(hashdata, hashsize, authority, signdata, signsize);
|
if (cryptolib[i] && cryptolib[i]->VerifyHash)
|
||||||
#endif
|
r = cryptolib[i]->VerifyHash(hashdata, hashsize, pubkey, pubkeysize, signdata, signsize);
|
||||||
#ifdef HAVE_GNUTLS
|
}
|
||||||
if (r == VH_UNSUPPORTED)
|
|
||||||
r = GNUTLS_VerifyHash(hashdata, hashsize, authority, signdata, signsize);
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_OPENSSL
|
|
||||||
if (r == VH_UNSUPPORTED)
|
|
||||||
r = OSSL_VerifyHash(hashdata, hashsize, authority, signdata, signsize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p->flags &= ~(DPF_SIGNATUREACCEPTED|DPF_SIGNATUREREJECTED|DPF_SIGNATUREUNKNOWN);
|
p->flags &= ~(DPF_SIGNATUREACCEPTED|DPF_SIGNATUREREJECTED|DPF_SIGNATUREUNKNOWN);
|
||||||
if (r == VH_CORRECT)
|
if (r == VH_CORRECT)
|
||||||
|
@ -1379,8 +1379,11 @@ static qboolean PM_ParsePackageList(const char *f, unsigned int parseflags, cons
|
||||||
char authority[MAX_OSPATH];
|
char authority[MAX_OSPATH];
|
||||||
char signdata[MAX_OSPATH];
|
char signdata[MAX_OSPATH];
|
||||||
char signature_base64[MAX_OSPATH];
|
char signature_base64[MAX_OSPATH];
|
||||||
|
qbyte *pubkey;
|
||||||
|
size_t pubkeysize;
|
||||||
size_t signsize;
|
size_t signsize;
|
||||||
enum hashvalidation_e r;
|
enum hashvalidation_e r;
|
||||||
|
int i;
|
||||||
hashfunc_t *hf = &hash_sha512;
|
hashfunc_t *hf = &hash_sha512;
|
||||||
void *hashdata = Z_Malloc(hf->digestsize);
|
void *hashdata = Z_Malloc(hf->digestsize);
|
||||||
void *hashctx = Z_Malloc(hf->contextsize);
|
void *hashctx = Z_Malloc(hf->contextsize);
|
||||||
|
@ -1395,20 +1398,16 @@ static qboolean PM_ParsePackageList(const char *f, unsigned int parseflags, cons
|
||||||
Z_Free(hashctx);
|
Z_Free(hashctx);
|
||||||
r = VH_UNSUPPORTED;//preliminary
|
r = VH_UNSUPPORTED;//preliminary
|
||||||
|
|
||||||
(void)signsize;
|
pubkey = Auth_GetKnownCertificate(authority, &pubkeysize);
|
||||||
|
if (!pubkey)
|
||||||
|
r = VH_AUTHORITY_UNKNOWN;
|
||||||
|
|
||||||
//try and get one of our providers to verify it...
|
//try and get one of our providers to verify it...
|
||||||
#ifdef HAVE_WINSSPI
|
for (i = 0; r==VH_UNSUPPORTED && i < cryptolib_count; i++)
|
||||||
if (r == VH_UNSUPPORTED)
|
{
|
||||||
r = SSPI_VerifyHash(hashdata, hf->digestsize, authority, signdata, signsize);
|
if (cryptolib[i] && cryptolib[i]->VerifyHash)
|
||||||
#endif
|
r = cryptolib[i]->VerifyHash(hashdata, hf->digestsize, pubkey, pubkeysize, signdata, signsize);
|
||||||
#ifdef HAVE_GNUTLS
|
}
|
||||||
if (r == VH_UNSUPPORTED)
|
|
||||||
r = GNUTLS_VerifyHash(hashdata, hf->digestsize, authority, signdata, signsize);
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_OPENSSL
|
|
||||||
if (r == VH_UNSUPPORTED)
|
|
||||||
r = OSSL_VerifyHash(hashdata, hf->digestsize, authority, signdata, signsize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Z_Free(hashdata);
|
Z_Free(hashdata);
|
||||||
source.validated = r;
|
source.validated = r;
|
||||||
|
|
|
@ -1076,7 +1076,19 @@ char *Sys_ConsoleInput(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GNUTLS
|
//begin meta generation helper
|
||||||
|
#include "fs.h"
|
||||||
|
static int Crypto_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int sigsize = -1;
|
||||||
|
for (i = 0; sigsize==-1 && i<cryptolib_count; i++)
|
||||||
|
{
|
||||||
|
if (cryptolib[i] && cryptolib[i]->GenerateSignature)
|
||||||
|
sigsize = cryptolib[i]->GenerateSignature(hashdata, hashsize, signdata, signsizemax);
|
||||||
|
}
|
||||||
|
return sigsize;
|
||||||
|
}
|
||||||
static void DoSign(const char *fname, int signtype)
|
static void DoSign(const char *fname, int signtype)
|
||||||
{
|
{
|
||||||
qbyte digest[1024];
|
qbyte digest[1024];
|
||||||
|
@ -1112,25 +1124,20 @@ static void DoSign(const char *fname, int signtype)
|
||||||
Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
|
Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
|
||||||
printf(" \\\"sha512=%s\\\"", base64);
|
printf(" \\\"sha512=%s\\\"", base64);
|
||||||
|
|
||||||
sigsize = GNUTLS_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
|
sigsize = Crypto_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
|
||||||
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
|
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
|
||||||
printf(" \\\"sign=%s:%s\\\"\n", auth, base64);
|
printf(" \\\"sign=%s:%s\\\"\n", auth, base64);
|
||||||
}
|
}
|
||||||
else if (signtype == 2)
|
else if (signtype == 2)
|
||||||
{ //signature "auth" "signdata"
|
{ //spits out the raw signature.
|
||||||
//printf(" \\\"dlsize=%zu\\\"", ts);
|
sigsize = Crypto_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
|
||||||
|
|
||||||
//Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
|
|
||||||
//printf(" \\\"sha512=%s\\\"", base64);
|
|
||||||
|
|
||||||
sigsize = GNUTLS_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
|
|
||||||
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
|
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
|
||||||
|
|
||||||
printf("%s\n", base64);
|
printf("%s\n", base64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
//end meta helpers
|
||||||
|
|
||||||
#ifdef _POSIX_C_SOURCE
|
#ifdef _POSIX_C_SOURCE
|
||||||
static void SigCont(int code)
|
static void SigCont(int code)
|
||||||
|
@ -1285,7 +1292,7 @@ int main (int c, const char **v)
|
||||||
if (COM_CheckParm("-nostdout"))
|
if (COM_CheckParm("-nostdout"))
|
||||||
nostdout = 1;
|
nostdout = 1;
|
||||||
|
|
||||||
#ifdef HAVE_GNUTLS
|
//begin meta generation helpers
|
||||||
//fteqw -privcert privcert.key -pubcert pubcert.key -sign binaryfile.pk3
|
//fteqw -privcert privcert.key -pubcert pubcert.key -sign binaryfile.pk3
|
||||||
i = COM_CheckParm("-sign");
|
i = COM_CheckParm("-sign");
|
||||||
if (!i)
|
if (!i)
|
||||||
|
@ -1301,7 +1308,7 @@ int main (int c, const char **v)
|
||||||
DoSign(com_argv[i+1], atoi(com_argv[i+0]+5));
|
DoSign(com_argv[i+1], atoi(com_argv[i+0]+5));
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif
|
//end
|
||||||
|
|
||||||
if (parms.binarydir)
|
if (parms.binarydir)
|
||||||
Sys_Printf("Binary is located at \"%s\"\n", parms.binarydir);
|
Sys_Printf("Binary is located at \"%s\"\n", parms.binarydir);
|
||||||
|
|
|
@ -419,10 +419,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#undef USE_EGL
|
#undef USE_EGL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) || defined(HAVE_WINSSPI)
|
#if defined(HAVE_GNUTLS) || defined(HAVE_WINSSPI)
|
||||||
#define HAVE_SSL
|
#define HAVE_SSL
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) || defined(HAVE_WINSSPI)
|
#if defined(HAVE_GNUTLS) || defined(HAVE_WINSSPI)
|
||||||
//FIXME: HAVE_WINSSPI does not work as a server.
|
//FIXME: HAVE_WINSSPI does not work as a server.
|
||||||
//FIXME: advertising dtls without a valid certificate will probably bug out if a client tries to auto-upgrade.
|
//FIXME: advertising dtls without a valid certificate will probably bug out if a client tries to auto-upgrade.
|
||||||
//FIXME: we don't cache server certs
|
//FIXME: we don't cache server certs
|
||||||
|
|
|
@ -5566,9 +5566,6 @@ static void COM_Version_f (void)
|
||||||
#ifdef HAVE_GNUTLS //on linux
|
#ifdef HAVE_GNUTLS //on linux
|
||||||
Con_Printf(" GnuTLS");
|
Con_Printf(" GnuTLS");
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_OPENSSL //on linux. hardlinked, so typically set only via the makefile.
|
|
||||||
Con_Printf(" OpenSSL");
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_WINSSPI //on windows
|
#ifdef HAVE_WINSSPI //on windows
|
||||||
Con_Printf(" WINSSPI");
|
Con_Printf(" WINSSPI");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -159,7 +159,6 @@
|
||||||
//FIXME: Stuff that Spike has added that Eukara needs to decide whether to keep or not.
|
//FIXME: Stuff that Spike has added that Eukara needs to decide whether to keep or not.
|
||||||
#define HAVE_OPUS
|
#define HAVE_OPUS
|
||||||
//#define HAVE_SPEEX
|
//#define HAVE_SPEEX
|
||||||
//#define HAVE_OPENSSL
|
|
||||||
//#define IMAGEFMT_HDR
|
//#define IMAGEFMT_HDR
|
||||||
//#define IMAGEFMT_PBM
|
//#define IMAGEFMT_PBM
|
||||||
//#define IMAGEFMT_PSD
|
//#define IMAGEFMT_PSD
|
||||||
|
|
|
@ -147,7 +147,6 @@
|
||||||
#define HAVE_PACKET //we can send unreliable messages!
|
#define HAVE_PACKET //we can send unreliable messages!
|
||||||
#define HAVE_TCP //we can create/accept TCP connections.
|
#define HAVE_TCP //we can create/accept TCP connections.
|
||||||
#define HAVE_GNUTLS //on linux
|
#define HAVE_GNUTLS //on linux
|
||||||
//#define HAVE_OPENSSL //on linux. hardlinked, so typically set only via the makefile.
|
|
||||||
#define HAVE_WINSSPI //on windows
|
#define HAVE_WINSSPI //on windows
|
||||||
#define FTPSERVER //sv_ftp cvar.
|
#define FTPSERVER //sv_ftp cvar.
|
||||||
#define WEBCLIENT //uri_get+any internal downloads etc
|
#define WEBCLIENT //uri_get+any internal downloads etc
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#undef FTPSERVER
|
#undef FTPSERVER
|
||||||
#undef HAVE_TCP
|
#undef HAVE_TCP
|
||||||
#undef HAVE_GNUTLS
|
#undef HAVE_GNUTLS
|
||||||
#undef HAVE_OPENSSL
|
|
||||||
#undef HAVE_WINSSPI
|
#undef HAVE_WINSSPI
|
||||||
#undef SUPPORT_ICE
|
#undef SUPPORT_ICE
|
||||||
#undef SUBSERVERS
|
#undef SUBSERVERS
|
||||||
|
|
|
@ -149,7 +149,6 @@
|
||||||
#define HAVE_PACKET //we can send unreliable messages!
|
#define HAVE_PACKET //we can send unreliable messages!
|
||||||
//#define HAVE_TCP //we can create/accept TCP connections.
|
//#define HAVE_TCP //we can create/accept TCP connections.
|
||||||
//#define HAVE_GNUTLS //on linux
|
//#define HAVE_GNUTLS //on linux
|
||||||
//#define HAVE_OPENSSL //on linux. hardlinked, so typically set only via the makefile.
|
|
||||||
//#define HAVE_WINSSPI //on windows
|
//#define HAVE_WINSSPI //on windows
|
||||||
//#define FTPSERVER //sv_ftp cvar.
|
//#define FTPSERVER //sv_ftp cvar.
|
||||||
//#define WEBCLIENT //uri_get+any internal downloads etc
|
//#define WEBCLIENT //uri_get+any internal downloads etc
|
||||||
|
|
|
@ -147,7 +147,6 @@
|
||||||
#define HAVE_PACKET //we can send unreliable messages!
|
#define HAVE_PACKET //we can send unreliable messages!
|
||||||
#define HAVE_TCP //we can create/accept TCP connections.
|
#define HAVE_TCP //we can create/accept TCP connections.
|
||||||
#define HAVE_GNUTLS //on linux
|
#define HAVE_GNUTLS //on linux
|
||||||
//#define HAVE_OPENSSL //on linux. hardlinked, so typically set only via the makefile.
|
|
||||||
#define HAVE_WINSSPI //on windows
|
#define HAVE_WINSSPI //on windows
|
||||||
//#define FTPSERVER //sv_ftp cvar.
|
//#define FTPSERVER //sv_ftp cvar.
|
||||||
#define WEBCLIENT //uri_get+any internal downloads etc
|
#define WEBCLIENT //uri_get+any internal downloads etc
|
||||||
|
|
|
@ -179,7 +179,6 @@
|
||||||
#undef WAYLANDQUAKE
|
#undef WAYLANDQUAKE
|
||||||
#undef SERVER_DEMO_PLAYBACK /* deprecated */
|
#undef SERVER_DEMO_PLAYBACK /* deprecated */
|
||||||
#undef DECOMPRESS_BPTC
|
#undef DECOMPRESS_BPTC
|
||||||
#undef HAVE_OPENSSL /* incomplete */
|
|
||||||
#undef IMAGEFMT_HDR
|
#undef IMAGEFMT_HDR
|
||||||
#undef IMAGEFMT_PBM
|
#undef IMAGEFMT_PBM
|
||||||
#undef IMAGEFMT_PSD
|
#undef IMAGEFMT_PSD
|
||||||
|
|
|
@ -194,6 +194,8 @@ void NET_DTLS_Timeouts(struct ftenet_connections_s *col);
|
||||||
#endif
|
#endif
|
||||||
extern cvar_t timeout;
|
extern cvar_t timeout;
|
||||||
extern cvar_t tls_ignorecertificateerrors; //evil evil evil.
|
extern cvar_t tls_ignorecertificateerrors; //evil evil evil.
|
||||||
|
struct ftecrypto_s;
|
||||||
|
qboolean NET_RegisterCrypto(void *module, struct ftecrypto_s *driver);
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
|
|
@ -903,7 +903,7 @@ static gnutls_certificate_credentials_t xcred[2];
|
||||||
static gnutls_datum_t cookie_key;
|
static gnutls_datum_t cookie_key;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vfsfile_t *SSL_OpenPrivKey(char *nativename, size_t nativesize)
|
static vfsfile_t *SSL_OpenPrivKey(char *nativename, size_t nativesize)
|
||||||
{
|
{
|
||||||
#define privname "privkey.pem"
|
#define privname "privkey.pem"
|
||||||
vfsfile_t *privf;
|
vfsfile_t *privf;
|
||||||
|
@ -926,7 +926,7 @@ vfsfile_t *SSL_OpenPrivKey(char *nativename, size_t nativesize)
|
||||||
return privf;
|
return privf;
|
||||||
#undef privname
|
#undef privname
|
||||||
}
|
}
|
||||||
vfsfile_t *SSL_OpenPubKey(char *nativename, size_t nativesize)
|
static vfsfile_t *SSL_OpenPubKey(char *nativename, size_t nativesize)
|
||||||
{
|
{
|
||||||
#define fullchainname "fullchain.pem"
|
#define fullchainname "fullchain.pem"
|
||||||
#define pubname "cert.pem"
|
#define pubname "cert.pem"
|
||||||
|
@ -1231,7 +1231,7 @@ static qboolean SSL_InitConnection(gnutlsfile_t *newf, qboolean isserver, qboole
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfsfile_t *GNUTLS_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver)
|
static vfsfile_t *GNUTLS_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver)
|
||||||
{
|
{
|
||||||
gnutlsfile_t *newf;
|
gnutlsfile_t *newf;
|
||||||
|
|
||||||
|
@ -1270,7 +1270,7 @@ vfsfile_t *GNUTLS_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isse
|
||||||
return &newf->funcs;
|
return &newf->funcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
|
static int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
|
||||||
{
|
{
|
||||||
gnutls_datum_t cb;
|
gnutls_datum_t cb;
|
||||||
gnutlsfile_t *f = (gnutlsfile_t*)vf;
|
gnutlsfile_t *f = (gnutlsfile_t*)vf;
|
||||||
|
@ -1293,9 +1293,9 @@ int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
//crypto: generates a signed blob
|
//crypto: generates a signed blob
|
||||||
int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax)
|
static int GNUTLS_GenerateSignature(const qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax)
|
||||||
{
|
{
|
||||||
gnutls_datum_t hash = {hashdata, hashsize};
|
gnutls_datum_t hash = {(qbyte*)hashdata, hashsize};
|
||||||
gnutls_datum_t sign = {NULL, 0};
|
gnutls_datum_t sign = {NULL, 0};
|
||||||
|
|
||||||
gnutls_certificate_credentials_t cred;
|
gnutls_certificate_credentials_t cred;
|
||||||
|
@ -1324,24 +1324,21 @@ int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
//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
|
//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
|
||||||
enum hashvalidation_e GNUTLS_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize)
|
static enum hashvalidation_e GNUTLS_VerifyHash(const qbyte *hashdata, size_t hashsize, const qbyte *pubkeydata, size_t pubkeysize, const qbyte *signdata, size_t signsize)
|
||||||
{
|
{
|
||||||
gnutls_datum_t hash = {hashdata, hashsize};
|
gnutls_datum_t hash = {(qbyte*)hashdata, hashsize};
|
||||||
gnutls_datum_t sign = {signdata, signsize};
|
gnutls_datum_t sign = {(qbyte*)signdata, signsize};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
gnutls_datum_t rawcert;
|
gnutls_datum_t rawcert = {(qbyte*)pubkeydata, pubkeysize};
|
||||||
#if 1
|
#if 1
|
||||||
size_t sz;
|
|
||||||
gnutls_pubkey_t pubkey;
|
gnutls_pubkey_t pubkey;
|
||||||
gnutls_x509_crt_t cert;
|
gnutls_x509_crt_t cert;
|
||||||
|
|
||||||
rawcert.data = Auth_GetKnownCertificate(authority, &sz);
|
|
||||||
if (!rawcert.data)
|
if (!rawcert.data)
|
||||||
return VH_AUTHORITY_UNKNOWN;
|
return VH_AUTHORITY_UNKNOWN;
|
||||||
if (!Init_GNUTLS())
|
if (!Init_GNUTLS())
|
||||||
return VH_UNSUPPORTED;
|
return VH_UNSUPPORTED;
|
||||||
rawcert.size = sz;
|
|
||||||
|
|
||||||
qgnutls_pubkey_init(&pubkey);
|
qgnutls_pubkey_init(&pubkey);
|
||||||
qgnutls_x509_crt_init(&cert);
|
qgnutls_x509_crt_init(&cert);
|
||||||
|
@ -1437,7 +1434,7 @@ static neterr_t GNUDTLS_Transmit(void *ctx, const qbyte *data, size_t datasize)
|
||||||
return NETERR_SENT;
|
return NETERR_SENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static neterr_t GNUDTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
static neterr_t GNUDTLS_Received(void *ctx, sizebuf_t *message)
|
||||||
{
|
{
|
||||||
int cli_addr = 0xdeadbeef;
|
int cli_addr = 0xdeadbeef;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1450,7 +1447,7 @@ static neterr_t GNUDTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
||||||
memset(&f->prestate, 0, sizeof(f->prestate));
|
memset(&f->prestate, 0, sizeof(f->prestate));
|
||||||
ret = qgnutls_dtls_cookie_verify(&cookie_key,
|
ret = qgnutls_dtls_cookie_verify(&cookie_key,
|
||||||
&cli_addr, sizeof(cli_addr),
|
&cli_addr, sizeof(cli_addr),
|
||||||
data, datasize,
|
message->data, message->cursize,
|
||||||
&f->prestate);
|
&f->prestate);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -1473,8 +1470,8 @@ static neterr_t GNUDTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
||||||
f->handshaking = true;
|
f->handshaking = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->readdata = data;
|
f->readdata = message->data;
|
||||||
f->readsize = datasize;
|
f->readsize = message->cursize;
|
||||||
|
|
||||||
if (f->handshaking)
|
if (f->handshaking)
|
||||||
{
|
{
|
||||||
|
@ -1487,7 +1484,7 @@ static neterr_t GNUDTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
||||||
return NETERR_DISCONNECTED;
|
return NETERR_DISCONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qgnutls_record_recv(f->session, net_message_buffer, sizeof(net_message_buffer));
|
ret = qgnutls_record_recv(f->session, message->data, message->maxsize);
|
||||||
//Sys_Printf("DTLS_Received returned %i of %i\n", ret, f->readsize);
|
//Sys_Printf("DTLS_Received returned %i of %i\n", ret, f->readsize);
|
||||||
f->readsize = 0;
|
f->readsize = 0;
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
|
@ -1505,8 +1502,8 @@ static neterr_t GNUDTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
||||||
// Sys_Printf("DTLS_Received temp error\n");
|
// Sys_Printf("DTLS_Received temp error\n");
|
||||||
return NETERR_CLOGGED;
|
return NETERR_CLOGGED;
|
||||||
}
|
}
|
||||||
net_message.cursize = ret;
|
message->cursize = ret;
|
||||||
data[ret] = 0;
|
message->data[ret] = 0;
|
||||||
// Sys_Printf("DTLS_Received returned %s\n", data);
|
// Sys_Printf("DTLS_Received returned %s\n", data);
|
||||||
return NETERR_SENT;
|
return NETERR_SENT;
|
||||||
}
|
}
|
||||||
|
@ -1540,26 +1537,37 @@ static const dtlsfuncs_t dtlsfuncs_gnutls =
|
||||||
GNUDTLS_Received,
|
GNUDTLS_Received,
|
||||||
GNUDTLS_Timeouts,
|
GNUDTLS_Timeouts,
|
||||||
};
|
};
|
||||||
const dtlsfuncs_t *GNUDTLS_InitServer(void)
|
static const dtlsfuncs_t *GNUDTLS_InitServer(void)
|
||||||
{
|
{
|
||||||
if (!SSL_InitGlobal(true))
|
if (!SSL_InitGlobal(true))
|
||||||
return NULL; //unable to init a server certificate. don't allow dtls to init.
|
return NULL; //unable to init a server certificate. don't allow dtls to init.
|
||||||
return &dtlsfuncs_gnutls;
|
return &dtlsfuncs_gnutls;
|
||||||
}
|
}
|
||||||
const dtlsfuncs_t *GNUDTLS_InitClient(void)
|
static const dtlsfuncs_t *GNUDTLS_InitClient(void)
|
||||||
{
|
{
|
||||||
return &dtlsfuncs_gnutls;
|
return &dtlsfuncs_gnutls;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define GNUDTLS_InitServer NULL
|
||||||
|
#define GNUDTLS_InitClient NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ftecrypto_t crypto_gnutls =
|
||||||
|
{
|
||||||
|
"GNUTLS",
|
||||||
|
GNUTLS_OpenVFS,
|
||||||
|
GNUTLS_GetChannelBinding,
|
||||||
|
GNUDTLS_InitClient,
|
||||||
|
GNUDTLS_InitServer,
|
||||||
|
GNUTLS_VerifyHash,
|
||||||
|
GNUTLS_GenerateSignature,
|
||||||
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#warning "GNUTLS version is too old (3.0+ required). Please clean and then recompile with CFLAGS=-DNO_GNUTLS"
|
#warning "GNUTLS version is too old (3.0+ required). Please clean and then recompile with CFLAGS=-DNO_GNUTLS"
|
||||||
|
|
||||||
|
ftecrypto_t crypto_gnutls;
|
||||||
qboolean SSL_InitGlobal(qboolean isserver) {return false;}
|
qboolean SSL_InitGlobal(qboolean isserver) {return false;}
|
||||||
vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean isserver) {return NULL;}
|
|
||||||
int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize) {return -1;}
|
|
||||||
const dtlsfuncs_t *GNUDTLS_InitClient(void) {return NULL;}
|
|
||||||
const dtlsfuncs_t *GNUDTLS_InitServer(void) {return NULL;}
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -996,7 +996,7 @@ static qboolean QDECL SSPI_Close (struct vfsfile_s *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
vfsfile_t *SSPI_OpenVFS(const char *servername, vfsfile_t *source, qboolean server)
|
static vfsfile_t *SSPI_OpenVFS(const char *servername, vfsfile_t *source, qboolean server)
|
||||||
{
|
{
|
||||||
sslfile_t *newf;
|
sslfile_t *newf;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -1071,7 +1071,7 @@ typedef struct _SecPkgContext_Bindings
|
||||||
SEC_CHANNEL_BINDINGS *Bindings;
|
SEC_CHANNEL_BINDINGS *Bindings;
|
||||||
} SecPkgContext_Bindings, *PSecPkgContext_Bindings;
|
} SecPkgContext_Bindings, *PSecPkgContext_Bindings;
|
||||||
#endif
|
#endif
|
||||||
int SSPI_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
|
static int SSPI_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
sslfile_t *f = (sslfile_t*)vf;
|
sslfile_t *f = (sslfile_t*)vf;
|
||||||
|
@ -1105,59 +1105,7 @@ int SSPI_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "netinc.h"
|
#include "netinc.h"
|
||||||
#if 0
|
#if defined(HAVE_DTLS)
|
||||||
struct fakedtls_s
|
|
||||||
{
|
|
||||||
void *cbctx;
|
|
||||||
neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize);
|
|
||||||
};
|
|
||||||
static void *FAKEDTLS_CreateContext(const char *remotehost, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver)
|
|
||||||
{
|
|
||||||
struct fakedtls_s *ctx = Z_Malloc(sizeof(*ctx));
|
|
||||||
ctx->cbctx = cbctx;
|
|
||||||
ctx->push = push;
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
static void FAKEDTLS_DestroyContext(void *vctx)
|
|
||||||
{
|
|
||||||
Z_Free(vctx);
|
|
||||||
}
|
|
||||||
static neterr_t FAKEDTLS_Transmit(void *vctx, const qbyte *data, size_t datasize)
|
|
||||||
{
|
|
||||||
struct fakedtls_s *ctx = vctx;
|
|
||||||
neterr_t r;
|
|
||||||
*(int*)data ^= 0xdeadbeef;
|
|
||||||
r = ctx->push(ctx->cbctx, data, datasize);
|
|
||||||
*(int*)data ^= 0xdeadbeef;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
static neterr_t FAKEDTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
|
||||||
{
|
|
||||||
*(int*)data ^= 0xdeadbeef;
|
|
||||||
return NETERR_SENT;
|
|
||||||
}
|
|
||||||
static neterr_t FAKEDTLS_Timeouts(void *ctx)
|
|
||||||
{
|
|
||||||
// fakedtls_s *f = (fakedtls_s *)ctx;
|
|
||||||
return NETERR_SENT;
|
|
||||||
}
|
|
||||||
static const dtlsfuncs_t dtlsfuncs_fakedtls =
|
|
||||||
{
|
|
||||||
FAKEDTLS_CreateContext,
|
|
||||||
FAKEDTLS_DestroyContext,
|
|
||||||
FAKEDTLS_Transmit,
|
|
||||||
FAKEDTLS_Received,
|
|
||||||
FAKEDTLS_Timeouts,
|
|
||||||
};
|
|
||||||
const dtlsfuncs_t *FAKEDTLS_InitServer(void)
|
|
||||||
{
|
|
||||||
return &dtlsfuncs_fakedtls;
|
|
||||||
}
|
|
||||||
const dtlsfuncs_t *FAKEDTLS_InitClient(void)
|
|
||||||
{
|
|
||||||
return &dtlsfuncs_fakedtls;
|
|
||||||
}
|
|
||||||
#elif defined(HAVE_DTLS)
|
|
||||||
static void *SSPI_DTLS_CreateContext(const char *remotehost, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver)
|
static void *SSPI_DTLS_CreateContext(const char *remotehost, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -1236,15 +1184,15 @@ static neterr_t SSPI_DTLS_Transmit(void *ctx, const qbyte *data, size_t datasize
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static neterr_t SSPI_DTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
static neterr_t SSPI_DTLS_Received(void *ctx, sizebuf_t *msg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
sslfile_t *f = (sslfile_t *)ctx;
|
sslfile_t *f = (sslfile_t *)ctx;
|
||||||
|
|
||||||
//Con_Printf("DTLS_Received: %i\n", datasize);
|
//Con_Printf("DTLS_Received: %i\n", datasize);
|
||||||
|
|
||||||
f->incrypt.data = data;
|
f->incrypt.data = msg->data;
|
||||||
f->incrypt.avail = f->incrypt.datasize = datasize;
|
f->incrypt.avail = f->incrypt.datasize = msg->cursize;
|
||||||
|
|
||||||
if (f->handshaking)
|
if (f->handshaking)
|
||||||
{
|
{
|
||||||
|
@ -1259,12 +1207,12 @@ static neterr_t SSPI_DTLS_Received(void *ctx, qbyte *data, size_t datasize)
|
||||||
SSPI_Decode(f);
|
SSPI_Decode(f);
|
||||||
ret = NETERR_SENT;
|
ret = NETERR_SENT;
|
||||||
|
|
||||||
memcpy(net_message_buffer, f->inraw.data, f->inraw.avail);
|
if (f->inraw.avail > msg->maxsize)
|
||||||
net_message.cursize = f->inraw.avail;
|
msg->cursize = f->inraw.avail;
|
||||||
|
else
|
||||||
|
msg->cursize = msg->maxsize;
|
||||||
|
memcpy(msg->data, f->inraw.data, msg->cursize);
|
||||||
f->inraw.avail = 0;
|
f->inraw.avail = 0;
|
||||||
|
|
||||||
net_message_buffer[net_message.cursize] = 0;
|
|
||||||
// Con_Printf("returning %i bytes: %s\n", net_message.cursize, net_message_buffer);
|
|
||||||
}
|
}
|
||||||
f->incrypt.data = NULL;
|
f->incrypt.data = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1288,14 +1236,14 @@ static const dtlsfuncs_t dtlsfuncs_schannel =
|
||||||
SSPI_DTLS_Received,
|
SSPI_DTLS_Received,
|
||||||
SSPI_DTLS_Timeouts,
|
SSPI_DTLS_Timeouts,
|
||||||
};
|
};
|
||||||
const dtlsfuncs_t *SSPI_DTLS_InitServer(void)
|
/*static const dtlsfuncs_t *SSPI_DTLS_InitServer(void)
|
||||||
{
|
{
|
||||||
//FIXME: at this point, schannel is still returning errors when I try acting as a server.
|
//FIXME: at this point, schannel is still returning errors when I try acting as a server.
|
||||||
//so just block any attempt to use this as a server.
|
//so just block any attempt to use this as a server.
|
||||||
//clients don't need/get certs.
|
//clients don't need/get certs.
|
||||||
return NULL;
|
return &dtlsfuncs_schannel;
|
||||||
}
|
}*/
|
||||||
const dtlsfuncs_t *SSPI_DTLS_InitClient(void)
|
static const dtlsfuncs_t *SSPI_DTLS_InitClient(void)
|
||||||
{
|
{
|
||||||
return &dtlsfuncs_schannel;
|
return &dtlsfuncs_schannel;
|
||||||
}
|
}
|
||||||
|
@ -1305,12 +1253,11 @@ const dtlsfuncs_t *SSPI_DTLS_InitClient(void)
|
||||||
//#include <ntstatus.h> //windows sucks too much to actually include this. oh well.
|
//#include <ntstatus.h> //windows sucks too much to actually include this. oh well.
|
||||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
|
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
|
||||||
#define STATUS_INVALID_SIGNATURE ((NTSTATUS)0xC000A000)
|
#define STATUS_INVALID_SIGNATURE ((NTSTATUS)0xC000A000)
|
||||||
enum hashvalidation_e SSPI_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize)
|
static enum hashvalidation_e SSPI_VerifyHash(const qbyte *hashdata, size_t hashsize, const qbyte *pemcert, size_t pemcertsize, const qbyte *signdata, size_t signsize)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
BCRYPT_KEY_HANDLE pubkey;
|
BCRYPT_KEY_HANDLE pubkey;
|
||||||
size_t sz;
|
const char *pem = pemcert;
|
||||||
const char *pem = Auth_GetKnownCertificate(authority, &sz);
|
|
||||||
const char *pemend;
|
const char *pemend;
|
||||||
qbyte *der;
|
qbyte *der;
|
||||||
size_t dersize;
|
size_t dersize;
|
||||||
|
@ -1368,7 +1315,7 @@ enum hashvalidation_e SSPI_VerifyHash(qbyte *hashdata, size_t hashsize, const ch
|
||||||
}
|
}
|
||||||
|
|
||||||
//yay, now we can do what we actually wanted in the first place.
|
//yay, now we can do what we actually wanted in the first place.
|
||||||
status = pBCryptVerifySignature(pubkey, NULL, hashdata, hashsize, signdata, signsize, 0);
|
status = pBCryptVerifySignature(pubkey, NULL, (qbyte*)hashdata, hashsize, (qbyte*)signdata, signsize, 0);
|
||||||
pBCryptDestroyKey(pubkey);
|
pBCryptDestroyKey(pubkey);
|
||||||
if (status == STATUS_SUCCESS)
|
if (status == STATUS_SUCCESS)
|
||||||
return VH_CORRECT; //its okay
|
return VH_CORRECT; //its okay
|
||||||
|
@ -1377,4 +1324,14 @@ enum hashvalidation_e SSPI_VerifyHash(qbyte *hashdata, size_t hashsize, const ch
|
||||||
return VH_UNSUPPORTED; //some weird transient error...?
|
return VH_UNSUPPORTED; //some weird transient error...?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftecrypto_t crypto_sspi =
|
||||||
|
{
|
||||||
|
"WinSSPI",
|
||||||
|
SSPI_OpenVFS,
|
||||||
|
SSPI_GetChannelBinding,
|
||||||
|
SSPI_DTLS_InitClient,
|
||||||
|
NULL,//SSPI_DTLS_InitServer,
|
||||||
|
SSPI_VerifyHash,
|
||||||
|
NULL,//SSPI_GenerateHash,
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -125,7 +125,8 @@ static cvar_t net_dns_ipv6 = CVARD("net_dns_ipv6", "1", "If 0, disables dns
|
||||||
cvar_t net_enabled = CVARD("net_enabled", "1", "If 0, disables all network access, including name resolution and socket creation. Does not affect loopback/internal connections.");
|
cvar_t net_enabled = CVARD("net_enabled", "1", "If 0, disables all network access, including name resolution and socket creation. Does not affect loopback/internal connections.");
|
||||||
#if defined(HAVE_SSL)
|
#if defined(HAVE_SSL)
|
||||||
cvar_t tls_ignorecertificateerrors = CVARFD("tls_ignorecertificateerrors", "0", CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOUNSAFEEXPAND|CVAR_NOSET, "This should NEVER be set to 1!");
|
cvar_t tls_ignorecertificateerrors = CVARFD("tls_ignorecertificateerrors", "0", CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOUNSAFEEXPAND|CVAR_NOSET, "This should NEVER be set to 1!");
|
||||||
static cvar_t tls_provider = CVARFD("tls_provider", "0", CVAR_NOTFROMSERVER, "Controls which TLS provider to use.\n0: Auto.\n1: GNUTLS\n2: OpenSSL\n3: SSPI");
|
static void QDECL NET_TLS_Provider_Changed(struct cvar_s *var, char *oldvalue);
|
||||||
|
static cvar_t tls_provider = CVARFCD("tls_provider", "", CVAR_NOTFROMSERVER, NET_TLS_Provider_Changed, "Controls which TLS provider to use.");
|
||||||
#endif
|
#endif
|
||||||
#if defined(TCPCONNECT) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV))
|
#if defined(TCPCONNECT) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV))
|
||||||
#ifdef HAVE_SERVER
|
#ifdef HAVE_SERVER
|
||||||
|
@ -210,6 +211,64 @@ static neterr_t FTENET_DTLS_SendPacket(ftenet_connections_t *col, int length, co
|
||||||
static neterr_t NET_SendPacketCol (ftenet_connections_t *collection, int length, const void *data, netadr_t *to);
|
static neterr_t NET_SendPacketCol (ftenet_connections_t *collection, int length, const void *data, netadr_t *to);
|
||||||
|
|
||||||
|
|
||||||
|
static void *cryptolibmodule[cryptolib_count];
|
||||||
|
ftecrypto_t *cryptolib[cryptolib_count] =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
#ifdef HAVE_WINSSPI
|
||||||
|
&crypto_sspi,
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GNUTLS
|
||||||
|
&crypto_gnutls,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
static void NET_TLS_Provider_Changed(struct cvar_s *var, char *oldvalue)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
var->ival = 0;
|
||||||
|
if (!*var->string || !strcmp(var->string, "0"))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < cryptolib_count; i++)
|
||||||
|
{
|
||||||
|
if (cryptolib[i] && !Q_strcasecmp(var->string, cryptolib[i]->drivername))
|
||||||
|
var->ival = i+1;
|
||||||
|
}
|
||||||
|
if (host_initialized && !var->ival)
|
||||||
|
{
|
||||||
|
Con_Printf("%s: \"%s\" not loaded, valid values are:", var->name, var->string);
|
||||||
|
for (i = 0; i < cryptolib_count; i++)
|
||||||
|
if (cryptolib[i])
|
||||||
|
Con_Printf(" %s", cryptolib[i]->drivername);
|
||||||
|
Con_Printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qboolean NET_RegisterCrypto(void *module, ftecrypto_t *driver)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (!driver)
|
||||||
|
{
|
||||||
|
for (i = 0; i < cryptolib_count; i++)
|
||||||
|
if (cryptolibmodule[i] == module)
|
||||||
|
cryptolibmodule[i] = NULL, cryptolib[i] = NULL;
|
||||||
|
Cvar_ForceCallback(&tls_provider);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < cryptolib_count; i++)
|
||||||
|
if (!cryptolib[i])
|
||||||
|
{
|
||||||
|
cryptolibmodule[i] = module, cryptolib[i] = driver;
|
||||||
|
Cvar_ForceCallback(&tls_provider);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s)
|
int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s)
|
||||||
|
@ -2247,6 +2306,7 @@ void *Auth_GetKnownCertificate(const char *certname, size_t *size)
|
||||||
qbyte *cert;
|
qbyte *cert;
|
||||||
} certs[] =
|
} certs[] =
|
||||||
{ //the contents of a -pubcert FILE
|
{ //the contents of a -pubcert FILE
|
||||||
|
//note: not enforced for pk3 files (which we will otherwise happily randomly download of random servers anyway).
|
||||||
{"Spike", "-----BEGIN CERTIFICATE-----\n"
|
{"Spike", "-----BEGIN CERTIFICATE-----\n"
|
||||||
"MIIDnTCCAgUCCjE1ODQ4ODg2OTEwDQYJKoZIhvcNAQELBQAwEDEOMAwGA1UEAxMF\n"
|
"MIIDnTCCAgUCCjE1ODQ4ODg2OTEwDQYJKoZIhvcNAQELBQAwEDEOMAwGA1UEAxMF\n"
|
||||||
"U3Bpa2UwHhcNMjAwMzIyMTQ1MTMwWhcNMzAwMzIwMTQ1MTMxWjAQMQ4wDAYDVQQD\n"
|
"U3Bpa2UwHhcNMjAwMzIyMTQ1MTMwWhcNMzAwMzIwMTQ1MTMxWjAQMQ4wDAYDVQQD\n"
|
||||||
|
@ -2329,6 +2389,7 @@ void *TLS_GetKnownCertificate(const char *certname, size_t *size)
|
||||||
|
|
||||||
vfsfile_t *FS_OpenSSL(const char *peername, vfsfile_t *source, qboolean isserver)
|
vfsfile_t *FS_OpenSSL(const char *peername, vfsfile_t *source, qboolean isserver)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
vfsfile_t *f = NULL;
|
vfsfile_t *f = NULL;
|
||||||
char hostname[MAX_OSPATH];
|
char hostname[MAX_OSPATH];
|
||||||
|
|
||||||
|
@ -2356,18 +2417,13 @@ vfsfile_t *FS_OpenSSL(const char *peername, vfsfile_t *source, qboolean isserver
|
||||||
else
|
else
|
||||||
*hostname = 0;
|
*hostname = 0;
|
||||||
|
|
||||||
#ifdef HAVE_GNUTLS
|
if (tls_provider.ival>0 && tls_provider.ival <= cryptolib_count && cryptolib[tls_provider.ival-1])
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==1))
|
f = !cryptolib[tls_provider.ival-1]->OpenStream?NULL:cryptolib[tls_provider.ival-1]->OpenStream(hostname, source, isserver);
|
||||||
f = GNUTLS_OpenVFS(hostname, source, isserver);
|
else for (i = 0; !f && i < cryptolib_count; i++)
|
||||||
#endif
|
{
|
||||||
#ifdef HAVE_OPENSSL
|
if (cryptolib[i] && cryptolib[i]->OpenStream)
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==2))
|
f = cryptolib[i]->OpenStream(hostname, source, isserver);
|
||||||
f = OSSL_OpenVFS(hostname, source, isserver);
|
}
|
||||||
#endif
|
|
||||||
#ifdef HAVE_WINSSPI
|
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==3))
|
|
||||||
f = SSPI_OpenVFS(hostname, source, isserver);
|
|
||||||
#endif
|
|
||||||
if (!f) //it all failed.
|
if (!f) //it all failed.
|
||||||
{
|
{
|
||||||
Con_Printf("%s: no tls provider available\n", peername);
|
Con_Printf("%s: no tls provider available\n", peername);
|
||||||
|
@ -2378,18 +2434,12 @@ vfsfile_t *FS_OpenSSL(const char *peername, vfsfile_t *source, qboolean isserver
|
||||||
int TLS_GetChannelBinding(vfsfile_t *stream, qbyte *data, size_t *datasize)
|
int TLS_GetChannelBinding(vfsfile_t *stream, qbyte *data, size_t *datasize)
|
||||||
{
|
{
|
||||||
int r = -1;
|
int r = -1;
|
||||||
#ifdef HAVE_GNUTLS
|
int i;
|
||||||
if (r == -1)
|
for (i = 0; r==-1 && i < cryptolib_count; i++)
|
||||||
r = GNUTLS_GetChannelBinding(stream, data, datasize);
|
{
|
||||||
#endif
|
if (cryptolib[i] && cryptolib[i]->GetChannelBinding)
|
||||||
#ifdef HAVE_OPENSSL
|
r = cryptolib[i]->GetChannelBinding(stream, data, datasize);
|
||||||
if (r == -1)
|
}
|
||||||
r = OSSL_GetChannelBinding(stream, data, datasize);
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_WINSSPI
|
|
||||||
if (r == -1)
|
|
||||||
r = SSPI_GetChannelBinding(stream, data, datasize);
|
|
||||||
#endif
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2880,35 +2930,27 @@ void NET_DTLS_Timeouts(ftenet_connections_t *col)
|
||||||
const dtlsfuncs_t *DTLS_InitServer(void)
|
const dtlsfuncs_t *DTLS_InitServer(void)
|
||||||
{
|
{
|
||||||
const dtlsfuncs_t *f = NULL;
|
const dtlsfuncs_t *f = NULL;
|
||||||
#ifdef HAVE_GNUTLS
|
int i;
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==1))
|
if (tls_provider.ival>0 && tls_provider.ival <= cryptolib_count && cryptolib[tls_provider.ival-1])
|
||||||
f = GNUDTLS_InitServer();
|
f = !cryptolib[tls_provider.ival-1]->DTLS_InitServer?NULL:cryptolib[tls_provider.ival-1]->DTLS_InitServer();
|
||||||
#endif
|
else for (i = 0; !f && i < cryptolib_count; i++)
|
||||||
#ifdef HAVE_OPENSSL
|
{
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==2))
|
if (cryptolib[i] && cryptolib[i]->DTLS_InitServer)
|
||||||
f = OSSL_InitServer();
|
f = cryptolib[i]->DTLS_InitServer();
|
||||||
#endif
|
}
|
||||||
#ifdef HAVE_WINSSPI
|
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==3))
|
|
||||||
f = SSPI_DTLS_InitServer();
|
|
||||||
#endif
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
const dtlsfuncs_t *DTLS_InitClient(void)
|
const dtlsfuncs_t *DTLS_InitClient(void)
|
||||||
{
|
{
|
||||||
const dtlsfuncs_t *f = NULL;
|
const dtlsfuncs_t *f = NULL;
|
||||||
#ifdef HAVE_GNUTLS
|
int i;
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==1))
|
if (tls_provider.ival>0 && tls_provider.ival <= cryptolib_count && cryptolib[tls_provider.ival-1])
|
||||||
f = GNUDTLS_InitClient();
|
f = !cryptolib[tls_provider.ival-1]->DTLS_InitClient?NULL:cryptolib[tls_provider.ival-1]->DTLS_InitClient();
|
||||||
#endif
|
else for (i = 0; !f && i < cryptolib_count; i++)
|
||||||
#ifdef HAVE_OPENSSL
|
{
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==2))
|
if (cryptolib[i] && cryptolib[i]->DTLS_InitClient)
|
||||||
f = OSSL_InitClient();
|
f = cryptolib[i]->DTLS_InitClient();
|
||||||
#endif
|
}
|
||||||
#ifdef HAVE_WINSSPI
|
|
||||||
if (!f && (!tls_provider.ival || tls_provider.ival==3))
|
|
||||||
f = SSPI_DTLS_InitClient();
|
|
||||||
#endif
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3013,7 +3055,7 @@ qboolean NET_DTLS_Decode(ftenet_connections_t *col)
|
||||||
if (NET_CompareAdr(&peer->addr, &net_from))
|
if (NET_CompareAdr(&peer->addr, &net_from))
|
||||||
{
|
{
|
||||||
peer->timeout = realtime+timeout.value; //refresh the timeout if our peer is still alive.
|
peer->timeout = realtime+timeout.value; //refresh the timeout if our peer is still alive.
|
||||||
switch(peer->funcs->Received(peer->dtlsstate, net_message.data, net_message.cursize))
|
switch(peer->funcs->Received(peer->dtlsstate, &net_message))
|
||||||
{
|
{
|
||||||
case NETERR_DISCONNECTED:
|
case NETERR_DISCONNECTED:
|
||||||
Sys_Printf("disconnected %p\n", peer->dtlsstate);
|
Sys_Printf("disconnected %p\n", peer->dtlsstate);
|
||||||
|
@ -6278,6 +6320,8 @@ ftenet_generic_connection_t *FTENET_TCP_EstablishConnection(ftenet_connections_t
|
||||||
hostonly[port-host] = 0;
|
hostonly[port-host] = 0;
|
||||||
|
|
||||||
newcon->tcpstreams->clientstream = FS_OpenSSL(hostonly, newcon->tcpstreams->clientstream, false);
|
newcon->tcpstreams->clientstream = FS_OpenSSL(hostonly, newcon->tcpstreams->clientstream, false);
|
||||||
|
if (!newcon->tcpstreams->clientstream)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -351,35 +351,32 @@ typedef struct dtlsfuncs_s
|
||||||
void *(*CreateContext)(const char *remotehost, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver); //if remotehost is null then their certificate will not be validated.
|
void *(*CreateContext)(const char *remotehost, void *cbctx, neterr_t(*push)(void *cbctx, const qbyte *data, size_t datasize), qboolean isserver); //if remotehost is null then their certificate will not be validated.
|
||||||
void (*DestroyContext)(void *ctx);
|
void (*DestroyContext)(void *ctx);
|
||||||
neterr_t (*Transmit)(void *ctx, const qbyte *data, size_t datasize);
|
neterr_t (*Transmit)(void *ctx, const qbyte *data, size_t datasize);
|
||||||
neterr_t (*Received)(void *ctx, qbyte *data, size_t datasize);
|
neterr_t (*Received)(void *ctx, sizebuf_t *message); //operates in-place...
|
||||||
neterr_t (*Timeouts)(void *ctx);
|
neterr_t (*Timeouts)(void *ctx);
|
||||||
void (*GetPeerCertificate)(void *ctx);
|
void (*GetPeerCertificate)(void *ctx);
|
||||||
} dtlsfuncs_t;
|
} dtlsfuncs_t;
|
||||||
const dtlsfuncs_t *DTLS_InitServer(void);
|
const dtlsfuncs_t *DTLS_InitServer(void);
|
||||||
const dtlsfuncs_t *DTLS_InitClient(void);
|
const dtlsfuncs_t *DTLS_InitClient(void);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_WINSSPI
|
typedef struct ftecrypto_s
|
||||||
vfsfile_t *SSPI_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
|
{
|
||||||
int SSPI_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
|
const char *drivername;
|
||||||
const struct dtlsfuncs_s *SSPI_DTLS_InitServer(void); //returns NULL if there's no cert available.
|
|
||||||
const struct dtlsfuncs_s *SSPI_DTLS_InitClient(void); //should always return something, if implemented.
|
//tlsey things
|
||||||
enum hashvalidation_e SSPI_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
|
vfsfile_t *(*OpenStream)(const char *hostname, vfsfile_t *source, qboolean isserver); //establish a tls connection around a tcp stream
|
||||||
#endif
|
int (*GetChannelBinding)(vfsfile_t *vf, qbyte *binddata, size_t *bindsize); //returns -1 if functions don't match those from OpenStream
|
||||||
#ifdef HAVE_GNUTLS
|
|
||||||
vfsfile_t *GNUTLS_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
|
//dtls entry points
|
||||||
int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
|
const struct dtlsfuncs_s *(*DTLS_InitClient)(void); //should always return something, if implemented.
|
||||||
const struct dtlsfuncs_s *GNUDTLS_InitServer(void); //returns NULL if there's no cert available.
|
const struct dtlsfuncs_s *(*DTLS_InitServer)(void); //returns NULL if there's no cert available.
|
||||||
const struct dtlsfuncs_s *GNUDTLS_InitClient(void); //should always return something, if implemented.
|
|
||||||
enum hashvalidation_e GNUTLS_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
|
//digital signature stuff. note: uses sha2_512
|
||||||
int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax);
|
enum hashvalidation_e (*VerifyHash)(const qbyte *hashdata, size_t hashsize, const qbyte *certdata, size_t certsize, const qbyte *signdata, size_t signsize);
|
||||||
#endif
|
int (*GenerateSignature)(const qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax);
|
||||||
#ifdef HAVE_OPENSSL
|
} ftecrypto_t;
|
||||||
vfsfile_t *OSSL_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
|
#define cryptolib_count 6
|
||||||
int OSSL_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
|
extern ftecrypto_t crypto_sspi, crypto_gnutls;
|
||||||
const struct dtlsfuncs_s *OSSL_InitServer(void); //returns NULL if there's no cert available.
|
extern ftecrypto_t *cryptolib[cryptolib_count];
|
||||||
const struct dtlsfuncs_s *OSSL_InitClient(void); //should always return something, if implemented.
|
|
||||||
enum hashvalidation_e OSSL_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -401,6 +401,8 @@ static qboolean QDECL PlugBI_ExportInterface(const char *name, void *interfacept
|
||||||
return Media_RegisterEncoder(currentplug, interfaceptr);
|
return Media_RegisterEncoder(currentplug, interfaceptr);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
if (!strcmp(name, "Crypto"))
|
||||||
|
return NET_RegisterCrypto(currentplug, interfaceptr);
|
||||||
#ifdef HAVE_CLIENT
|
#ifdef HAVE_CLIENT
|
||||||
if (!strcmp(name, plugvrfuncs_name))
|
if (!strcmp(name, plugvrfuncs_name))
|
||||||
return R_RegisterVRDriver(currentplug, interfaceptr);
|
return R_RegisterVRDriver(currentplug, interfaceptr);
|
||||||
|
@ -1529,6 +1531,7 @@ void Plug_Close(plugin_t *plug)
|
||||||
#ifdef HAVE_CLIENT
|
#ifdef HAVE_CLIENT
|
||||||
S_UnregisterSoundInputModule(plug);
|
S_UnregisterSoundInputModule(plug);
|
||||||
#endif
|
#endif
|
||||||
|
NET_RegisterCrypto(plug, NULL);
|
||||||
FS_UnRegisterFileSystemModule(plug);
|
FS_UnRegisterFileSystemModule(plug);
|
||||||
Mod_UnRegisterAllModelFormats(plug);
|
Mod_UnRegisterAllModelFormats(plug);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue