From 2ff17aed07bc5e252dec1eb2e39da5ee2da535da Mon Sep 17 00:00:00 2001 From: Spoike Date: Mon, 24 Jun 2013 09:04:00 +0000 Subject: [PATCH] Reworked the gnutls code. Now more consistant with windows, and more generic. Still does not validate the server's certificate, so disabled by default. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4402 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 14 +- engine/botlib/be_aas_route.c | 5 +- engine/client/image.c | 2 +- engine/client/in_win.c | 4 - engine/client/m_download.c | 3 + engine/client/snd_directx.c | 9 +- engine/client/sys_linux.c | 9 +- engine/client/sys_win.c | 40 +- engine/common/bothdefs.h | 5 + engine/common/cmd.c | 2 +- engine/common/fs.c | 2 +- engine/common/fs_stdio.c | 4 +- engine/common/fs_win32.c | 26 +- engine/common/net_ssl_gnutls.c | 335 ++++++++++++++++ engine/common/net_ssl_winsspi.c | 692 ++++++++++++++++---------------- engine/common/net_wins.c | 39 +- engine/common/plugin.c | 237 ----------- engine/common/sys.h | 2 +- engine/common/sys_win_threads.c | 6 +- engine/gl/gl_model.c | 2 +- engine/gl/gl_vidnt.c | 16 +- plugins/jabber/jabberclient.c | 210 ++++++++-- 22 files changed, 957 insertions(+), 707 deletions(-) create mode 100644 engine/common/net_ssl_gnutls.c diff --git a/engine/Makefile b/engine/Makefile index 9f5b5c669..36c6e42b0 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -590,6 +590,7 @@ COMMON_OBJS = \ cvar.o \ cmd.o \ crc.o \ + net_ssl_gnutls.o \ fs.o \ fs_stdio.o \ fs_pak.o \ @@ -1587,20 +1588,17 @@ ifndef ARCH else mkdir -p libs-$(ARCH) test -f jpegsrc.v9.tar.gz || wget http://www.ijg.org/files/jpegsrc.v9.tar.gz - test -f libs-$(ARCH)/libjpeg.a || (cd libs-$(ARCH) && tar -xvzf ../jpegsrc.v9.tar.gz && cd jpeg-9 && ./configure -host=$(ARCH) && $(MAKE) && cp .libs/libjpeg.a ../ && $(ARCH)-ar -s ../libjpeg.a ) + -test -f libs-$(ARCH)/libjpeg.a || (cd libs-$(ARCH) && tar -xvzf ../jpegsrc.v9.tar.gz && cd jpeg-9 && ./configure -host=$(ARCH) && $(MAKE) && cp .libs/libjpeg.a ../ && $(ARCH)-ar -s ../libjpeg.a ) test -f zlib-1.2.8.tar.gz || wget http://zlib.net/zlib-1.2.8.tar.gz - test -f libs-$(ARCH)/libz.a || (cd libs-$(ARCH) && tar -xvzf ../zlib-1.2.8.tar.gz && cd zlib-1.2.8 && CC="$(CC) $(W32_CFLAGS)" ./configure --static && $(MAKE) libz.a CC="$(CC) $(W32_CFLAGS)" && cp libz.a ../ && $(ARCH)-ar -s ../libz.a ) + -test -f libs-$(ARCH)/libz.a || (cd libs-$(ARCH) && tar -xvzf ../zlib-1.2.8.tar.gz && cd zlib-1.2.8 && CC="$(CC) $(W32_CFLAGS)" ./configure --static && $(MAKE) libz.a CC="$(CC) $(W32_CFLAGS)" && cp libz.a ../ && $(ARCH)-ar -s ../libz.a ) test -f libpng-1.6.2.tar.gz || wget http://prdownloads.sourceforge.net/libpng/libpng-1.6.2.tar.gz?download -O libpng-1.6.2.tar.gz - test -f libs-$(ARCH)/libpng.a || (cd libs-$(ARCH) && tar -xvzf ../libpng-1.6.2.tar.gz && cd libpng-1.6.2 && ./configure -host=$(ARCH) && $(MAKE) && cp .libs/libpng16.a ../libpng.a ) + -test -f libs-$(ARCH)/libpng.a || (cd libs-$(ARCH) && tar -xvzf ../libpng-1.6.2.tar.gz && cd libpng-1.6.2 && ./configure -host=$(ARCH) CFLAGS=-I$(realpath libs-$(ARCH)/zlib-1.2.8/) LDFLAGS=-L$(realpath libs-$(ARCH)) && $(MAKE) && cp .libs/libpng16.a ../libpng.a ) test -f libogg-1.3.0.tar.gz || wget http://downloads.xiph.org/releases/ogg/libogg-1.3.0.tar.gz - test -f libs-$(ARCH)/libogg.a || (cd libs-$(ARCH) && tar -xvzf ../libogg-1.3.0.tar.gz && cd libogg-1.3.0 && ./configure -host=$(ARCH) && $(MAKE) && cp src/.libs/libogg.a ../ && $(ARCH)-ar -s ../libogg.a) + -test -f libs-$(ARCH)/libogg.a || (cd libs-$(ARCH) && tar -xvzf ../libogg-1.3.0.tar.gz && cd libogg-1.3.0 && ./configure -host=$(ARCH) && $(MAKE) && cp src/.libs/libogg.a ../ && $(ARCH)-ar -s ../libogg.a) test -f libvorbis-1.3.3.tar.gz || wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.3.tar.gz - test -f libs-$(ARCH)/libvorbisfile.a || (cd libs-$(ARCH) && tar -xvzf ../libvorbis-1.3.3.tar.gz && cd libvorbis-1.3.3 && ./configure -host=$(ARCH) --disable-oggtest --with-ogg-libraries=.. --with-ogg-includes=$(realpath libs-$(ARCH)/libogg-1.3.0/include) && $(MAKE) && cp lib/.libs/libvorbis.a ../ && cp lib/.libs/libvorbisfile.a ../ ) - - - + -test -f libs-$(ARCH)/libvorbisfile.a || (cd libs-$(ARCH) && tar -xvzf ../libvorbis-1.3.3.tar.gz && cd libvorbis-1.3.3 && ./configure PKG_CONFIG= -host=$(ARCH) --disable-oggtest --with-ogg-libraries=.. --with-ogg-includes=$(realpath libs-$(ARCH)/libogg-1.3.0/include) && $(MAKE) && cp lib/.libs/libvorbis.a ../ && cp lib/.libs/libvorbisfile.a ../ ) endif diff --git a/engine/botlib/be_aas_route.c b/engine/botlib/be_aas_route.c index 3ab9f1215..9205e6d2e 100644 --- a/engine/botlib/be_aas_route.c +++ b/engine/botlib/be_aas_route.c @@ -506,9 +506,10 @@ void AAS_CalculateAreaTravelTimes(void) aas_reversedlink_t *revlink; aas_reachability_t *reach; aas_areasettings_t *settings; - int starttime; +#ifdef DEBUG + int starttime = Sys_MilliSeconds(); +#endif - starttime = Sys_MilliSeconds(); //if there are still area travel times, free the memory if (aasworld.areatraveltimes) FreeMemory(aasworld.areatraveltimes); //get the total size of all the area travel times diff --git a/engine/client/image.c b/engine/client/image.c index 9dd69509e..69323df95 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -657,7 +657,7 @@ return NULL; void (PNGAPI *qpng_error) PNGARG((png_structp png_ptr, png_const_charp error_message)) PSTATIC(png_error); void (PNGAPI *qpng_read_end) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_read_end); void (PNGAPI *qpng_read_image) PNGARG((png_structp png_ptr, png_bytepp image)) PSTATIC(png_read_image); -png_byte (PNGAPI *qpng_get_bit_depth) PNGARG((png_const_structp png_ptr, const png_const_infop info_ptr)) PSTATIC(png_get_bit_depth); +png_byte (PNGAPI *qpng_get_bit_depth) PNGARG((png_const_structp png_ptr, png_const_infop info_ptr)) PSTATIC(png_get_bit_depth); png_byte (PNGAPI *qpng_get_channels) PNGARG((png_const_structp png_ptr, png_const_infop info_ptr)) PSTATIC(png_get_channels); png_size_t (PNGAPI *qpng_get_rowbytes) PNGARG((png_const_structp png_ptr, png_const_infop info_ptr)) PSTATIC(png_get_rowbytes); void (PNGAPI *qpng_read_update_info) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_read_update_info); diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 6fd3281ec..4f7aa0003 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -52,8 +52,6 @@ HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, #define DINPUT_VERSION_DX7 0x0700 // mouse variables -static cvar_t m_filter = CVAR("m_filter","0"); -static cvar_t m_accel = CVAR("m_accel", "0"); static cvar_t in_dinput = CVARF("in_dinput","0", CVAR_ARCHIVE); static cvar_t in_builtinkeymap = CVARF("in_builtinkeymap", "0", CVAR_ARCHIVE); static cvar_t in_simulatemultitouch = CVAR("in_simulatemultitouch", "0"); @@ -1220,8 +1218,6 @@ INS_MouseMove */ void INS_MouseMove (float *movements, int pnum) { - extern int window_x, window_y; - #ifdef AVAIL_DINPUT if (dinput && mouseactive) { diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 9b8269f76..f52704a97 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -65,6 +65,9 @@ static package_t *BuildPackageList(vfsfile_t *f, int flags, char *prefix) int version; + if (!f) + return NULL; + do { if (!VFS_GETS(f, line, sizeof(line)-1)) diff --git a/engine/client/snd_directx.c b/engine/client/snd_directx.c index 1a6104a1b..6b05a7ee1 100644 --- a/engine/client/snd_directx.c +++ b/engine/client/snd_directx.c @@ -539,7 +539,14 @@ Direct-Sound support */ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum) { - extern cvar_t snd_inactive, snd_eax; + extern cvar_t snd_inactive; +#if _MSC_VER > 1200 //fixme err +#ifndef MINIMAL +#ifdef _IKsPropertySet_ + extern cvar_t snd_eax; +#endif +#endif +#endif DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; DWORD dwSize, dwWrite; diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 559d2e196..f35d68316 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -776,14 +776,15 @@ int main (int c, const char **v) Sys_MakeCodeWriteable ================ */ -void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +#if 0 +void Sys_MakeCodeWriteable (void *startptr, unsigned long length) { int r; - unsigned long addr; + uintptr_t addr; int psize = getpagesize(); - addr = (startaddr & ~(psize-1)) - psize; + addr = ((uintptr_t)startptr & ~(psize-1)) - psize; // fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, // addr, startaddr+length, length); @@ -792,8 +793,8 @@ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) if (r < 0) Sys_Error("Protection change failed\n"); - } +#endif //fixme: some sort of taskbar/gnome panel flashing. void Sys_ServerActivity(void) diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index da3919596..b7ccf2175 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -526,7 +526,7 @@ qboolean Sys_Rename (char *oldfname, char *newfname) return !rename(oldfname, newfname); } -static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart, int (QDECL *func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath) +static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart, int (QDECL *func)(const char *fname, int fsize, void *parm, searchpathfuncs_t *spath), void *parm, searchpathfuncs_t *spath) { HANDLE r; WIN32_FIND_DATA fd; @@ -632,7 +632,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart return go; } -int Sys_EnumerateFiles (const char *gpath, const char *match, int (QDECL *func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath) +int Sys_EnumerateFiles (const char *gpath, const char *match, int (QDECL *func)(const char *fname, int fsize, void *parm, searchpathfuncs_t *spath), void *parm, searchpathfuncs_t *spath) { char fullmatch[MAX_OSPATH]; int start; @@ -661,12 +661,13 @@ SYSTEM IO Sys_MakeCodeWriteable ================ */ -void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +#if 0 +void Sys_MakeCodeWriteable (void *startaddr, unsigned long length) { DWORD flOldProtect; //@@@ copy on write or just read-write? - if (!VirtualProtect((LPVOID)startaddr, length, PAGE_EXECUTE_READWRITE, &flOldProtect)) + if (!VirtualProtect(startaddr, length, PAGE_EXECUTE_READWRITE, &flOldProtect)) { char str[1024]; @@ -680,6 +681,7 @@ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) Sys_Error("Protection change failed!\nError %d: %s\n", (int)GetLastError(), str); } } +#endif void Sys_DoFileAssociations(qboolean elevated); void Sys_Register_File_Associations_f(void) @@ -1329,7 +1331,7 @@ void Sys_SendKeyEvents (void) sys_parenttop = strtoul(Cmd_Argv(2), NULL, 0); sys_parentwidth = strtoul(Cmd_Argv(3), NULL, 0); sys_parentheight = strtoul(Cmd_Argv(4), NULL, 0); - sys_parentwindow = (HWND)strtoul(Cmd_Argv(5), NULL, 16); + sys_parentwindow = (HWND)(intptr_t)strtoull(Cmd_Argv(5), NULL, 16); } Cmd_ExecuteString(text, RESTRICT_LOCAL); memmove(text, nl, textpos - (nl - text)); @@ -1665,7 +1667,7 @@ static IShellLinkW *CreateShellLink(char *command, char *target, char *title, ch IShellLinkW_SetDescription(link, buf); /*tooltip*/ - hr = IShellLinkW_QueryInterface(link, &qIID_IPropertyStore, &prop_store); + hr = IShellLinkW_QueryInterface(link, &qIID_IPropertyStore, (void**)&prop_store); if(SUCCEEDED(hr)) { @@ -1734,7 +1736,7 @@ void Win7_TaskListInit(void) { UINT minslots; IUnknown *removed; - cdl->lpVtbl->BeginList(cdl, &minslots, &qIID_IObjectArray, &removed); + cdl->lpVtbl->BeginList(cdl, &minslots, &qIID_IObjectArray, (void**)&removed); if (SUCCEEDED(CoCreateInstance(&qCLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, &qIID_IObjectCollection, (void**)&col))) { @@ -1785,7 +1787,7 @@ void Win7_TaskListInit(void) break; } - if (SUCCEEDED(col->lpVtbl->QueryInterface(col, &qIID_IObjectArray, &arr))) + if (SUCCEEDED(col->lpVtbl->QueryInterface(col, &qIID_IObjectArray, (void**)&arr))) { cdl->lpVtbl->AddUserTasks(cdl, arr); arr->lpVtbl->Release(arr); @@ -1852,12 +1854,13 @@ int MyRegGetIntValue(HKEY base, char *keyname, char *valuename, int defaultval) qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen) { qboolean result = false; - DWORD resultlen = datalen - 1; HKEY subkey; DWORD type = REG_NONE; if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS) { - result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &datalen); + DWORD dwlen; + result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &dwlen); + datalen = dwlen; RegCloseKey (subkey); } @@ -1951,6 +1954,7 @@ static void Update_CreatePath (char *path) } } +#include "fs.h" void Update_Version_Updated(struct dl_download *dl) { //happens in a thread, avoid va @@ -2067,7 +2071,7 @@ qboolean Sys_CheckUpdated(void) if (*updatedpath) { GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1); - if (CreateProcess(updatedpath, va("\"%s\" %s --fromfrontend \"%s\" \"%s\" %s", frontendpath, COM_Parse(GetCommandLineA()), SVNREVISIONSTR, frontendpath), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) + if (CreateProcess(updatedpath, va("\"%s\" %s --fromfrontend \"%s\" \"%s\"", frontendpath, COM_Parse(GetCommandLineA()), SVNREVISIONSTR, frontendpath), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) return true; } } @@ -2139,7 +2143,7 @@ void Sys_DoFileAssociations(qboolean elevated) #define ASSOCV "1" //register the basic demo class - Q_snprintfz(command, sizeof(command), "Quake or QuakeWorld Demo", com_argv[0]); + Q_snprintfz(command, sizeof(command), "Quake or QuakeWorld Demo"); ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_DemoFile."ASSOCV, "", REG_SZ, command, strlen(command)); Q_snprintfz(command, sizeof(command), "\"%s\",0", com_argv[0]); ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_DemoFile."ASSOCV"\\DefaultIcon", "", REG_SZ, command, strlen(command)); @@ -2147,7 +2151,7 @@ void Sys_DoFileAssociations(qboolean elevated) ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_DemoFile."ASSOCV"\\shell\\open\\command", "", REG_SZ, command, strlen(command)); //register the basic map class. yeah, the command is the same as for demos. but the description is different! - Q_snprintfz(command, sizeof(command), "Quake Map", com_argv[0]); + Q_snprintfz(command, sizeof(command), "Quake Map"); ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_BSPFile."ASSOCV, "", REG_SZ, command, strlen(command)); Q_snprintfz(command, sizeof(command), "\"%s\",0", com_argv[0]); ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_BSPFile."ASSOCV"\\DefaultIcon", "", REG_SZ, command, strlen(command)); @@ -2166,23 +2170,23 @@ void Sys_DoFileAssociations(qboolean elevated) //try to get ourselves listed in windows' 'default programs' ui. Q_snprintfz(command, sizeof(command), "%s", FULLENGINENAME); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities", "ApplicationName", REG_SZ, command, strlen(command)); - Q_snprintfz(command, sizeof(command), "%s", FULLENGINENAME" is an awesome hybrid game engine able to run multiple Quake-compatible/derived games.", com_argv[0]); + Q_snprintfz(command, sizeof(command), "%s", FULLENGINENAME" is an awesome hybrid game engine able to run multiple Quake-compatible/derived games."); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities", "ApplicationDescription", REG_SZ, command, strlen(command)); - Q_snprintfz(command, sizeof(command), DISTRIBUTION"_DemoFile.1", com_argv[0]); + Q_snprintfz(command, sizeof(command), DISTRIBUTION"_DemoFile.1"); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".qtv", REG_SZ, command, strlen(command)); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".mvd", REG_SZ, command, strlen(command)); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".qwd", REG_SZ, command, strlen(command)); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".dem", REG_SZ, command, strlen(command)); // ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".dm2", REG_SZ, command, strlen(command)); - Q_snprintfz(command, sizeof(command), DISTRIBUTION"_BSPFile.1", com_argv[0]); + Q_snprintfz(command, sizeof(command), DISTRIBUTION"_BSPFile.1"); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".bsp", REG_SZ, command, strlen(command)); // ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".fmf", REG_SZ, DISTRIBUTION"_ManifestFile", strlen(DISTRIBUTION"_ManifestFile")); // ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\MIMEAssociations", "application/x-ftemanifest", REG_SZ, DISTRIBUTION"_ManifestFile", strlen(DISTRIBUTION"_ManifestFile")); - Q_snprintfz(command, sizeof(command), DISTRIBUTION"_Server.1", com_argv[0]); + Q_snprintfz(command, sizeof(command), DISTRIBUTION"_Server.1"); ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\UrlAssociations", "qw", REG_SZ, command, strlen(command)); Q_snprintfz(command, sizeof(command), "Software\\"FULLENGINENAME"\\Capabilities"); @@ -2193,7 +2197,7 @@ void Sys_DoFileAssociations(qboolean elevated) if (!ok && elevated < 2) { HINSTANCE ch = ShellExecute(mainwindow, "runas", com_argv[0], va("-register_types %i", elevated+1), NULL, SW_SHOWNORMAL); - if ((int)ch <= 32) + if ((intptr_t)ch <= 32) Sys_DoFileAssociations(2); return; } diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 9d842c9eb..070bcf823 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -113,6 +113,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #if defined(_WIN32) && !defined(_SDL) + #define HAVE_WINSSPI //built in component, checks against windows' root ca database and revocations etc. +#elif defined(__linux__) +// #define HAVE_GNUTLS //currently disabled as it does not validate the server's certificate, beware the mitm attack. +#endif +#if defined(HAVE_WINSSPI) || defined(HAVE_GNUTLS) #define HAVE_SSL #endif diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 36972e9c1..adbfb3272 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -2984,7 +2984,7 @@ static char *Macro_USDate (void) //and much but not all of EU ptm = localtime (&t); if (!ptm) return "#bad date#"; - strftime (macro_buf, sizeof(macro_buf)-1, "%m.%s.%Y", ptm); + strftime (macro_buf, sizeof(macro_buf)-1, "%m.%d.%Y", ptm); return macro_buf; } static char *Macro_ProperDate (void) //americans get it wrong. besides, this is more easily sortable for filenames etc diff --git a/engine/common/fs.c b/engine/common/fs.c index f824eb6eb..591d7c064 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -3643,7 +3643,7 @@ void COM_InitFilesystem (void) { // on XP systems, only use a home directory by default if we're a limited user or if we're on a network BOOL isadmin, isonnetwork; - SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY; + SID_IDENTIFIER_AUTHORITY ntauth = {SECURITY_NT_AUTHORITY}; PSID adminSID, networkSID; isadmin = AllocateAndInitializeSid(&ntauth, diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index e467e1aca..13b995916 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -172,8 +172,8 @@ vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsfl #ifdef _DEBUG Q_strncpyz(file->funcs.dbgname, osname, sizeof(file->funcs.dbgname)); #endif - file->funcs.ReadBytes = strchr(mode, 'r')?VFSSTDIO_ReadBytes:NULL; - file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSSTDIO_WriteBytes:NULL; + file->funcs.ReadBytes = VFSSTDIO_ReadBytes; + file->funcs.WriteBytes = VFSSTDIO_WriteBytes; file->funcs.Seek = VFSSTDIO_Seek; file->funcs.Tell = VFSSTDIO_Tell; file->funcs.GetLen = VFSSTDIO_GetSize; diff --git a/engine/common/fs_win32.c b/engine/common/fs_win32.c index ac7c09868..9b0e8bbe3 100644 --- a/engine/common/fs_win32.c +++ b/engine/common/fs_win32.c @@ -185,23 +185,23 @@ vfsfile_t *QDECL VFSW32_Open(const char *osname, const char *mode) return (vfsfile_t*)file; } -static vfsfile_t *QDECL VFSW32_OpenVFS(void *handle, flocation_t *loc, const char *mode) +static vfsfile_t *QDECL VFSW32_OpenVFS(searchpathfuncs_t *handle, flocation_t *loc, const char *mode) { //path is already cleaned, as anything that gets a valid loc needs cleaning up first. return VFSW32_Open(loc->rawname, mode); } -static void QDECL VFSW32_ClosePath(void *handle) +static void QDECL VFSW32_ClosePath(searchpathfuncs_t *handle) { - vfsw32path_t *wp = handle; + vfsw32path_t *wp = (void*)handle; if (wp->changenotification != INVALID_HANDLE_VALUE) FindCloseChangeNotification(wp->changenotification); Z_Free(wp); } -static qboolean QDECL VFSW32_PollChanges(void *handle) +static qboolean QDECL VFSW32_PollChanges(searchpathfuncs_t *handle) { qboolean result = false; - vfsw32path_t *wp = handle; + vfsw32path_t *wp = (void*)handle; if (wp->changenotification == INVALID_HANDLE_VALUE) return true; @@ -223,9 +223,9 @@ static qboolean QDECL VFSW32_PollChanges(void *handle) } return result; } -static int QDECL VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle, void *spath) +static int QDECL VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle, searchpathfuncs_t *spath) { - vfsw32path_t *wp = spath; + vfsw32path_t *wp = (void*)spath; void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle) = handle; if (filename[strlen(filename)-1] == '/') { //this is actually a directory @@ -239,15 +239,15 @@ static int QDECL VFSW32_RebuildFSHash(const char *filename, int filesize, void * AddFileHash(wp->hashdepth, filename, NULL, wp); return true; } -static void QDECL VFSW32_BuildHash(void *handle, int hashdepth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)) +static void QDECL VFSW32_BuildHash(searchpathfuncs_t *handle, int hashdepth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)) { - vfsw32path_t *wp = handle; + vfsw32path_t *wp = (void*)handle; wp->hashdepth = hashdepth; Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, AddFileHash, handle); } -static qboolean QDECL VFSW32_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +static qboolean QDECL VFSW32_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult) { - vfsw32path_t *wp = handle; + vfsw32path_t *wp = (void*)handle; FILE *f; int len; char netpath[MAX_OSPATH]; @@ -284,7 +284,7 @@ static qboolean QDECL VFSW32_FLocate(void *handle, flocation_t *loc, const char return true; } -static void QDECL VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer) +static void QDECL VFSW32_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, char *buffer) { // vfsw32path_t *wp = handle; @@ -326,4 +326,4 @@ searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc np->pub.OpenVFS = VFSW32_OpenVFS; np->pub.PollChanges = VFSW32_PollChanges; return &np->pub; -} \ No newline at end of file +} diff --git a/engine/common/net_ssl_gnutls.c b/engine/common/net_ssl_gnutls.c new file mode 100644 index 000000000..7abf15237 --- /dev/null +++ b/engine/common/net_ssl_gnutls.c @@ -0,0 +1,335 @@ +//This file should be easily portable. +//The biggest strength of this plugin system is that ALL interactions are performed via +//named functions, this makes it *really* easy to port plugins from one engine to annother. + +#include "quakedef.h" + +#ifdef HAVE_GNUTLS + +cvar_t *tls_ignorecertificateerrors; + +#if 1//defined(_WIN32) && !defined(MINGW) + +//lets rip stuff out of the header and supply a seperate dll. +//gnutls is huge. +//also this helps get around the whole msvc/mingw thing. + +struct DSTRUCT; +typedef struct DSTRUCT* gnutls_certificate_credentials; +typedef gnutls_certificate_credentials gnutls_certificate_client_credentials; +typedef struct DSTRUCT* gnutls_anon_client_credentials; +struct gnutls_session_int; +typedef struct gnutls_session_int* gnutls_session_t; +typedef void * gnutls_transport_ptr_t; + +typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, + GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP, + GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA, GNUTLS_KX_SRP_DSS +} gnutls_kx_algorithm; +typedef enum gnutls_certificate_type { GNUTLS_CRT_X509=1, GNUTLS_CRT_OPENPGP +} gnutls_certificate_type; +typedef enum gnutls_connection_end { GNUTLS_SERVER=1, GNUTLS_CLIENT } gnutls_connection_end; +typedef enum gnutls_credentials_type { GNUTLS_CRD_CERTIFICATE=1, GNUTLS_CRD_ANON, GNUTLS_CRD_SRP } gnutls_credentials_type; +typedef enum gnutls_close_request { GNUTLS_SHUT_RDWR=0, GNUTLS_SHUT_WR=1 } gnutls_close_request; +typedef ssize_t (*gnutls_pull_func) (gnutls_transport_ptr_t, void *, size_t); +typedef ssize_t (*gnutls_push_func) (gnutls_transport_ptr_t, const void *, size_t); + +#define GNUTLS_E_AGAIN -28 +#define GNUTLS_E_INTERRUPTED -52 + +static int (VARGS *gnutls_bye)(gnutls_session_t session, gnutls_close_request how); +static void (VARGS *gnutls_perror)(int error); +static int (VARGS *gnutls_handshake)(gnutls_session_t session); +static void (VARGS *gnutls_transport_set_ptr)(gnutls_session_t session, gnutls_transport_ptr_t ptr); +static void (VARGS *gnutls_transport_set_push_function)(gnutls_session_t session, gnutls_push_func push_func); +static void (VARGS *gnutls_transport_set_pull_function)(gnutls_session_t session, gnutls_pull_func pull_func); +static void (VARGS *gnutls_transport_set_errno)(gnutls_session_t session, int err); +static int (VARGS *gnutls_error_is_fatal)(int error); +static int (VARGS *gnutls_certificate_type_set_priority)(gnutls_session_t session, const int*); +static int (VARGS *gnutls_credentials_set)(gnutls_session_t, gnutls_credentials_type type, void* cred); +static int (VARGS *gnutls_kx_set_priority)(gnutls_session_t session, const int*); +static int (VARGS *gnutls_init)(gnutls_session_t * session, gnutls_connection_end con_end); +static int (VARGS *gnutls_set_default_priority)(gnutls_session_t session); +static int (VARGS *gnutls_certificate_allocate_credentials)(gnutls_certificate_credentials *sc); +static int (VARGS *gnutls_anon_allocate_client_credentials)(gnutls_anon_client_credentials *sc); +static int (VARGS *gnutls_global_init)(void); +static int (VARGS *gnutls_record_send)(gnutls_session_t session, const void *data, size_t sizeofdata); +static int (VARGS *gnutls_record_recv)(gnutls_session_t session, void *data, size_t sizeofdata); + +static qboolean Init_GNUTLS(void) +{ + dllhandle_t hmod; + + dllfunction_t functable[] = + { + {(void**)&gnutls_bye, "gnutls_bye"}, + {(void**)&gnutls_perror, "gnutls_perror"}, + {(void**)&gnutls_handshake, "gnutls_handshake"}, + {(void**)&gnutls_transport_set_ptr, "gnutls_transport_set_ptr"}, + {(void**)&gnutls_transport_set_push_function, "gnutls_transport_set_push_function"}, + {(void**)&gnutls_transport_set_pull_function, "gnutls_transport_set_pull_function"}, + {(void**)&gnutls_transport_set_errno, "gnutls_transport_set_errno"}, + {(void**)&gnutls_error_is_fatal, "gnutls_error_is_fatal"}, + {(void**)&gnutls_certificate_type_set_priority, "gnutls_certificate_type_set_priority"}, + {(void**)&gnutls_credentials_set, "gnutls_credentials_set"}, + {(void**)&gnutls_kx_set_priority, "gnutls_kx_set_priority"}, + {(void**)&gnutls_init, "gnutls_init"}, + {(void**)&gnutls_set_default_priority, "gnutls_set_default_priority"}, + {(void**)&gnutls_certificate_allocate_credentials, "gnutls_certificate_allocate_credentials"}, + {(void**)&gnutls_anon_allocate_client_credentials, "gnutls_anon_allocate_client_credentials"}, + {(void**)&gnutls_global_init, "gnutls_global_init"}, + {(void**)&gnutls_record_send, "gnutls_record_send"}, + {(void**)&gnutls_record_recv, "gnutls_record_recv"}, + {NULL, NULL} + }; + + hmod = Sys_LoadLibrary("libgnutls.so.26", functable); + if (!hmod) + return false; + return true; +} + +#else +#include +static qboolean Init_GNUTLS(void) {return true;} +#endif + +struct sslbuf +{ + char data[8192]; + int avail; +}; +typedef struct +{ + vfsfile_t funcs; + vfsfile_t *stream; + + gnutls_session_t session; + + qboolean handshaking; + + struct sslbuf outplain; + struct sslbuf outcrypt; + struct sslbuf inplain; + struct sslbuf incrypt; +} gnutlsfile_t; + +static void SSL_Close(vfsfile_t *vfs) +{ + gnutlsfile_t *file = (void*)vfs; + + gnutls_bye (file->session, GNUTLS_SHUT_RDWR); + VFS_CLOSE(file->stream); +} +static int SSL_Read(struct vfsfile_s *f, void *buffer, int bytestoread) +{ + gnutlsfile_t *file = (void*)f; + int read; + + if (file->handshaking) + { + read = gnutls_handshake (file->session); + if (read == GNUTLS_E_AGAIN || read == GNUTLS_E_INTERRUPTED) + return 0; + if (read < 0) + gnutls_perror (read); + file->handshaking = false; + } + + read = gnutls_record_recv(file->session, buffer, bytestoread); + if (read < 0) + { + if (!gnutls_error_is_fatal(read)) + return 0; + else + { + Con_Printf("TLS Read Error %i (bufsize %i)\n", read, bytestoread); + return -1; + } + } + else if (read == 0) + return -1; //closed by remote connection. + return read; +} +static int SSL_Write(struct vfsfile_s *f, const void *buffer, int bytestowrite) +{ + gnutlsfile_t *file = (void*)f; + int written; + + if (file->handshaking) + { + written = gnutls_handshake (file->session); + if (written == GNUTLS_E_AGAIN || written == GNUTLS_E_INTERRUPTED) + return 0; + if (written < 0) + gnutls_perror (written); + file->handshaking = false; + } + + written = gnutls_record_send(file->session, buffer, bytestowrite); + if (written < 0) + { + if (!gnutls_error_is_fatal(written)) + return 0; + else + { + Con_Printf("TLS Send Error %i (%i bytes)\n", written, bytestowrite); + return -1; + } + } + else if (written == 0) + return -1; //closed by remote connection. + return written; +} +static qboolean QDECL SSL_Seek (struct vfsfile_s *file, unsigned long pos) +{ + return false; +} +static unsigned long QDECL SSL_Tell (struct vfsfile_s *file) +{ + return 0; +} +static unsigned long QDECL SSL_GetLen (struct vfsfile_s *file) +{ + return 0; +} + + +#include + +/*functions for gnutls to call when it wants to send data*/ +static ssize_t SSL_Push(gnutls_transport_ptr_t p, const void *data, size_t size) +{ + gnutlsfile_t *file = p; + int done = VFS_WRITE(file->stream, data, size); + if (!done) + { + gnutls_transport_set_errno(file->session, EAGAIN); + return -1; + } + if (done < 0) + return 0; + gnutls_transport_set_errno(file->session, done<0?errno:0); + return done; +} +/*static ssize_t SSL_PushV(gnutls_transport_ptr_t p, giovec_t *iov, int iovcnt) +{ + int i; + ssize_t written; + ssize_t total; + gnutlsfile_t *file = p; + for (i = 0; i < iovcnt; i++) + { + written = SSL_Push(file, iov[i].iov_base, iov[i].iov_len); + if (written <= 0) + break; + total += written; + if (written < iov[i].iov_len) + break; + } + if (!total) + { + gnutls_transport_set_errno(file->session, EAGAIN); + return -1; + } + gnutls_transport_set_errno(file->session, 0); + return total; +}*/ +static ssize_t SSL_Pull(gnutls_transport_ptr_t p, void *data, size_t size) +{ + gnutlsfile_t *file = p; + int done = VFS_READ(file->stream, data, size); + if (!done) + { + gnutls_transport_set_errno(file->session, EAGAIN); + return -1; + } + if (done < 0) + { + return 0; + } + gnutls_transport_set_errno(file->session, done<0?errno:0); + return done; +} + +vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server) +{ + gnutlsfile_t *newf; + qboolean anon = false; + + static gnutls_anon_client_credentials anoncred; + static gnutls_certificate_credentials xcred; + +// long _false = false; +// long _true = true; + + /* Need to enable anonymous KX specifically. */ + const int kx_prio[] = {GNUTLS_KX_ANON_DH, 0}; + const int cert_type_priority[3] = {GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0}; + + + { + static qboolean needinit = true; + if (needinit) + { + if (!Init_GNUTLS()) + { + Con_Printf("GnuTLS library not available.\n"); + VFS_CLOSE(source); + return NULL; + } + gnutls_global_init (); + + gnutls_anon_allocate_client_credentials (&anoncred); + gnutls_certificate_allocate_credentials (&xcred); + // gnutls_certificate_set_x509_trust_file (xcred, "ca.pem", GNUTLS_X509_FMT_PEM); + + needinit = false; + } + } + + newf = Z_Malloc(sizeof(*newf)); + if (!newf) + { + VFS_CLOSE(source); + return NULL; + } + newf->stream = source; + newf->funcs.Close = SSL_Close; + newf->funcs.Flush = NULL; + newf->funcs.GetLen = SSL_GetLen; + newf->funcs.ReadBytes = SSL_Read; + newf->funcs.WriteBytes = SSL_Write; + newf->funcs.Seek = SSL_Seek; + newf->funcs.Tell = SSL_Tell; + newf->funcs.seekingisabadplan = true; + + // Initialize TLS session + gnutls_init (&newf->session, GNUTLS_CLIENT); + + // Use default priorities + gnutls_set_default_priority (newf->session); + if (anon) + { + gnutls_kx_set_priority (newf->session, kx_prio); + gnutls_credentials_set (newf->session, GNUTLS_CRD_ANON, anoncred); + } + else + { + gnutls_certificate_type_set_priority (newf->session, cert_type_priority); + gnutls_credentials_set (newf->session, GNUTLS_CRD_CERTIFICATE, xcred); + } + + // tell gnutls how to send/receive data + gnutls_transport_set_ptr (newf->session, newf); + gnutls_transport_set_push_function(newf->session, SSL_Push); + //gnutls_transport_set_vec_push_function(newf->session, SSL_PushV); + gnutls_transport_set_pull_function(newf->session, SSL_Pull); + //gnutls_transport_set_pull_timeout_function(newf->session, NULL); + + newf->handshaking = true; + + return &newf->funcs; +} +#endif + diff --git a/engine/common/net_ssl_winsspi.c b/engine/common/net_ssl_winsspi.c index 7cf2cc839..531f2edf2 100644 --- a/engine/common/net_ssl_winsspi.c +++ b/engine/common/net_ssl_winsspi.c @@ -1,12 +1,12 @@ -#include "quakedef.h" -#if defined(_WIN32) && !defined(_SDL) && defined(HAVE_SSL) -cvar_t *tls_ignorecertificateerrors; - -#include -#define SECURITY_WIN32 -#include -#include -#include +#include "quakedef.h" +#if defined(HAVE_WINSSPI) +cvar_t *tls_ignorecertificateerrors; + +#include +#define SECURITY_WIN32 +#include +#include +#include //hungarian ensures we hit no macros. static struct @@ -18,14 +18,14 @@ static struct SECURITY_STATUS (WINAPI *pInitializeSecurityContextA) (PCredHandle,PCtxtHandle,SEC_CHAR*,ULONG,ULONG,ULONG,PSecBufferDesc,ULONG,PCtxtHandle,PSecBufferDesc,PULONG,PTimeStamp); SECURITY_STATUS (WINAPI *pCompleteAuthToken) (PCtxtHandle,PSecBufferDesc); SECURITY_STATUS (WINAPI *pQueryContextAttributesA) (PCtxtHandle,ULONG,PVOID); - SECURITY_STATUS (WINAPI *pFreeCredentialsHandle) (PCredHandle); + SECURITY_STATUS (WINAPI *pFreeCredentialsHandle) (PCredHandle); SECURITY_STATUS (WINAPI *pDeleteSecurityContext) (PCtxtHandle); } secur; static struct { void *lib; - BOOL (WINAPI *pCertGetCertificateChain) (HCERTCHAINENGINE,PCCERT_CONTEXT,LPFILETIME,HCERTSTORE,PCERT_CHAIN_PARA,DWORD,LPVOID,PCCERT_CHAIN_CONTEXT*); - BOOL (WINAPI *pCertVerifyCertificateChainPolicy) (LPCSTR,PCCERT_CHAIN_CONTEXT,PCERT_CHAIN_POLICY_PARA,PCERT_CHAIN_POLICY_STATUS); + BOOL (WINAPI *pCertGetCertificateChain) (HCERTCHAINENGINE,PCCERT_CONTEXT,LPFILETIME,HCERTSTORE,PCERT_CHAIN_PARA,DWORD,LPVOID,PCCERT_CHAIN_CONTEXT*); + BOOL (WINAPI *pCertVerifyCertificateChainPolicy) (LPCSTR,PCCERT_CHAIN_CONTEXT,PCERT_CHAIN_POLICY_PARA,PCERT_CHAIN_POLICY_STATUS); void (WINAPI *pCertFreeCertificateChain) (PCCERT_CHAIN_CONTEXT); } crypt; static qboolean SSL_Init(void) @@ -59,17 +59,17 @@ static qboolean SSL_Init(void) crypt.lib = Sys_LoadLibrary("crypt32.dll", crypt_functable); return !!secur.lib && !!crypt.lib; -} - -#define MessageAttribute (ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_MANUAL_CRED_VALIDATION) - -struct sslbuf -{ +} + +#define MessageAttribute (ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_MANUAL_CRED_VALIDATION) + +struct sslbuf +{ char data[8192]; - int avail; - int newd; -}; - + int avail; + int newd; +}; + typedef struct { vfsfile_t funcs; vfsfile_t *stream; @@ -151,38 +151,38 @@ static int SSPI_CheckNewInCrypt(sslfile_t *f) //convert inbound crypt->data static void SSPI_Decode(sslfile_t *f) { - SECURITY_STATUS ss; - SecBufferDesc BuffDesc; - SecBuffer SecBuff[4]; - ULONG ulQop = 0; - SecBuffer *data = NULL; - SecBuffer *extra = NULL; - int i; - - if (!f->incrypt.avail) - return; - - BuffDesc.ulVersion = SECBUFFER_VERSION; - BuffDesc.cBuffers = 4; - BuffDesc.pBuffers = SecBuff; - - SecBuff[0].BufferType = SECBUFFER_DATA; - SecBuff[0].cbBuffer = f->incrypt.avail; - SecBuff[0].pvBuffer = f->incrypt.data; - - SecBuff[1].BufferType = SECBUFFER_EMPTY; //space for header - SecBuff[2].BufferType = SECBUFFER_EMPTY; //space for footer - SecBuff[3].BufferType = SECBUFFER_EMPTY; //space for extra marker - - ss = secur.pDecryptMessage(&f->sechnd, &BuffDesc, 0, &ulQop); - - if (ss < 0) - { - if (ss == SEC_E_INCOMPLETE_MESSAGE) - return; //no error if its incomplete, we can just get more data later on. - SSPI_Error(f, "DecryptMessage failed"); - return; - } + SECURITY_STATUS ss; + SecBufferDesc BuffDesc; + SecBuffer SecBuff[4]; + ULONG ulQop = 0; + SecBuffer *data = NULL; + SecBuffer *extra = NULL; + int i; + + if (!f->incrypt.avail) + return; + + BuffDesc.ulVersion = SECBUFFER_VERSION; + BuffDesc.cBuffers = 4; + BuffDesc.pBuffers = SecBuff; + + SecBuff[0].BufferType = SECBUFFER_DATA; + SecBuff[0].cbBuffer = f->incrypt.avail; + SecBuff[0].pvBuffer = f->incrypt.data; + + SecBuff[1].BufferType = SECBUFFER_EMPTY; //space for header + SecBuff[2].BufferType = SECBUFFER_EMPTY; //space for footer + SecBuff[3].BufferType = SECBUFFER_EMPTY; //space for extra marker + + ss = secur.pDecryptMessage(&f->sechnd, &BuffDesc, 0, &ulQop); + + if (ss < 0) + { + if (ss == SEC_E_INCOMPLETE_MESSAGE) + return; //no error if its incomplete, we can just get more data later on. + SSPI_Error(f, "DecryptMessage failed"); + return; + } for (i = 0; i < BuffDesc.cBuffers; i++) { @@ -197,11 +197,11 @@ static void SSPI_Decode(sslfile_t *f) SSPI_CopyIntoBuffer(&f->inraw, data->pvBuffer, data->cbBuffer); //retain the extra. if there's no extra then mark it so. - if (extra) - { - memmove(f->incrypt.data, f->incrypt.data + (f->incrypt.avail - extra->cbBuffer), extra->cbBuffer); - f->incrypt.avail = extra->cbBuffer; - } + if (extra) + { + memmove(f->incrypt.data, f->incrypt.data + (f->incrypt.avail - extra->cbBuffer), extra->cbBuffer); + f->incrypt.avail = extra->cbBuffer; + } else f->incrypt.avail = 0; } @@ -209,314 +209,314 @@ static void SSPI_Decode(sslfile_t *f) //convert outgoing data->crypt static void SSPI_Encode(sslfile_t *f) { - SECURITY_STATUS ss; - SecBufferDesc BuffDesc; - SecBuffer SecBuff[4]; - ULONG ulQop = 0; - - if (f->outcrypt.avail) - { - SSPI_TryFlushCryptOut(f); - if (f->outcrypt.avail) - return; //don't flood too much - } - - - //don't corrupt the handshake data. - if (f->handshaking) - return; - - if (!f->outraw.avail) - return; - - BuffDesc.ulVersion = SECBUFFER_VERSION; - BuffDesc.cBuffers = 4; - BuffDesc.pBuffers = SecBuff; - - SecBuff[0].BufferType = SECBUFFER_STREAM_HEADER; - SecBuff[0].cbBuffer = f->headersize; - SecBuff[0].pvBuffer = f->headerdata; - - SecBuff[1].BufferType = SECBUFFER_DATA; - SecBuff[1].cbBuffer = f->outraw.avail; - SecBuff[1].pvBuffer = f->outraw.data; - - SecBuff[2].BufferType = SECBUFFER_STREAM_TRAILER; - SecBuff[2].cbBuffer = f->footersize; - SecBuff[2].pvBuffer = f->footerdata; - - SecBuff[3].BufferType = SECBUFFER_EMPTY; - - ss = secur.pEncryptMessage(&f->sechnd, ulQop, &BuffDesc, 0); - - if (ss < 0) - { - SSPI_Error(f, "EncryptMessage failed"); - return; + SECURITY_STATUS ss; + SecBufferDesc BuffDesc; + SecBuffer SecBuff[4]; + ULONG ulQop = 0; + + if (f->outcrypt.avail) + { + SSPI_TryFlushCryptOut(f); + if (f->outcrypt.avail) + return; //don't flood too much + } + + + //don't corrupt the handshake data. + if (f->handshaking) + return; + + if (!f->outraw.avail) + return; + + BuffDesc.ulVersion = SECBUFFER_VERSION; + BuffDesc.cBuffers = 4; + BuffDesc.pBuffers = SecBuff; + + SecBuff[0].BufferType = SECBUFFER_STREAM_HEADER; + SecBuff[0].cbBuffer = f->headersize; + SecBuff[0].pvBuffer = f->headerdata; + + SecBuff[1].BufferType = SECBUFFER_DATA; + SecBuff[1].cbBuffer = f->outraw.avail; + SecBuff[1].pvBuffer = f->outraw.data; + + SecBuff[2].BufferType = SECBUFFER_STREAM_TRAILER; + SecBuff[2].cbBuffer = f->footersize; + SecBuff[2].pvBuffer = f->footerdata; + + SecBuff[3].BufferType = SECBUFFER_EMPTY; + + ss = secur.pEncryptMessage(&f->sechnd, ulQop, &BuffDesc, 0); + + if (ss < 0) + { + SSPI_Error(f, "EncryptMessage failed"); + return; } f->outraw.avail = 0; //fixme: these should be made non-fatal. if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[0].pvBuffer, SecBuff[0].cbBuffer) < SecBuff[0].cbBuffer) - { - SSPI_Error(f, "crypt buffer overflowed"); - return; + { + SSPI_Error(f, "crypt buffer overflowed"); + return; } if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[1].pvBuffer, SecBuff[1].cbBuffer) < SecBuff[1].cbBuffer) - { - SSPI_Error(f, "crypt buffer overflowed"); - return; + { + SSPI_Error(f, "crypt buffer overflowed"); + return; } if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[2].pvBuffer, SecBuff[2].cbBuffer) < SecBuff[2].cbBuffer) - { - SSPI_Error(f, "crypt buffer overflowed"); - return; + { + SSPI_Error(f, "crypt buffer overflowed"); + return; } SSPI_TryFlushCryptOut(f); } -static DWORD VerifyServerCertificate(PCCERT_CONTEXT pServerCert, PWSTR pwszServerName, DWORD dwCertFlags) -{ - HTTPSPolicyCallbackData polHttps; - CERT_CHAIN_POLICY_PARA PolicyPara; - CERT_CHAIN_POLICY_STATUS PolicyStatus; - CERT_CHAIN_PARA ChainPara; - PCCERT_CHAIN_CONTEXT pChainContext; - DWORD Status; - LPSTR rgszUsages[] = - { - szOID_PKIX_KP_SERVER_AUTH, - szOID_SERVER_GATED_CRYPTO, - szOID_SGC_NETSCAPE - }; - DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR); - - if(pServerCert == NULL) - return SEC_E_WRONG_PRINCIPAL; - if(!*pwszServerName) - return SEC_E_WRONG_PRINCIPAL; - - // Build certificate chain. - memset(&ChainPara, 0, sizeof(ChainPara)); - ChainPara.cbSize = sizeof(ChainPara); - ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; - ChainPara.RequestedUsage.Usage.cUsageIdentifier = cUsages; - ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages; - - if (!crypt.pCertGetCertificateChain(NULL, pServerCert, NULL, pServerCert->hCertStore, &ChainPara, 0, NULL, &pChainContext)) - { - Status = GetLastError(); - Sys_Printf("Error 0x%x returned by CertGetCertificateChain!\n", Status); - } - else - { - // Validate certificate chain. - memset(&polHttps, 0, sizeof(HTTPSPolicyCallbackData)); - polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData); - polHttps.dwAuthType = AUTHTYPE_SERVER; - polHttps.fdwChecks = dwCertFlags; - polHttps.pwszServerName = pwszServerName; - - memset(&PolicyPara, 0, sizeof(PolicyPara)); - PolicyPara.cbSize = sizeof(PolicyPara); - PolicyPara.pvExtraPolicyPara = &polHttps; - - memset(&PolicyStatus, 0, sizeof(PolicyStatus)); - PolicyStatus.cbSize = sizeof(PolicyStatus); - - if (!crypt.pCertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, pChainContext, &PolicyPara, &PolicyStatus)) - { - Status = GetLastError(); - Sys_Printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!\n", Status); - } - else - { - if (PolicyStatus.dwError) - { - char *err; - Status = PolicyStatus.dwError; - switch (Status) - { - case CERT_E_EXPIRED: err = "CERT_E_EXPIRED"; break; - case CERT_E_VALIDITYPERIODNESTING: err = "CERT_E_VALIDITYPERIODNESTING"; break; - case CERT_E_ROLE: err = "CERT_E_ROLE"; break; - case CERT_E_PATHLENCONST: err = "CERT_E_PATHLENCONST"; break; - case CERT_E_CRITICAL: err = "CERT_E_CRITICAL"; break; - case CERT_E_PURPOSE: err = "CERT_E_PURPOSE"; break; - case CERT_E_ISSUERCHAINING: err = "CERT_E_ISSUERCHAINING"; break; - case CERT_E_MALFORMED: err = "CERT_E_MALFORMED"; break; - case CERT_E_UNTRUSTEDROOT: err = "CERT_E_UNTRUSTEDROOT"; break; - case CERT_E_CHAINING: err = "CERT_E_CHAINING"; break; - case TRUST_E_FAIL: err = "TRUST_E_FAIL"; break; - case CERT_E_REVOKED: err = "CERT_E_REVOKED"; break; - case CERT_E_UNTRUSTEDTESTROOT: err = "CERT_E_UNTRUSTEDTESTROOT"; break; - case CERT_E_REVOCATION_FAILURE: err = "CERT_E_REVOCATION_FAILURE"; break; - case CERT_E_CN_NO_MATCH: err = "CERT_E_CN_NO_MATCH"; break; - case CERT_E_WRONG_USAGE: err = "CERT_E_WRONG_USAGE"; break; - default: err = "(unknown)"; break; - } - Con_Printf("Error verifying certificate for '%S': %s\n", pwszServerName, err); - - if (tls_ignorecertificateerrors->ival) - { - Con_Printf("pretending it didn't happen... (tls_ignorecertificateerrors is set)\n"); - Status = SEC_E_OK; - } - } - else - Status = SEC_E_OK; - } - crypt.pCertFreeCertificateChain(pChainContext); - } - - return Status; +static DWORD VerifyServerCertificate(PCCERT_CONTEXT pServerCert, PWSTR pwszServerName, DWORD dwCertFlags) +{ + HTTPSPolicyCallbackData polHttps; + CERT_CHAIN_POLICY_PARA PolicyPara; + CERT_CHAIN_POLICY_STATUS PolicyStatus; + CERT_CHAIN_PARA ChainPara; + PCCERT_CHAIN_CONTEXT pChainContext; + DWORD Status; + LPSTR rgszUsages[] = + { + szOID_PKIX_KP_SERVER_AUTH, + szOID_SERVER_GATED_CRYPTO, + szOID_SGC_NETSCAPE + }; + DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR); + + if(pServerCert == NULL) + return SEC_E_WRONG_PRINCIPAL; + if(!*pwszServerName) + return SEC_E_WRONG_PRINCIPAL; + + // Build certificate chain. + memset(&ChainPara, 0, sizeof(ChainPara)); + ChainPara.cbSize = sizeof(ChainPara); + ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; + ChainPara.RequestedUsage.Usage.cUsageIdentifier = cUsages; + ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages; + + if (!crypt.pCertGetCertificateChain(NULL, pServerCert, NULL, pServerCert->hCertStore, &ChainPara, 0, NULL, &pChainContext)) + { + Status = GetLastError(); + Sys_Printf("Error 0x%x returned by CertGetCertificateChain!\n", (unsigned int)Status); + } + else + { + // Validate certificate chain. + memset(&polHttps, 0, sizeof(HTTPSPolicyCallbackData)); + polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData); + polHttps.dwAuthType = AUTHTYPE_SERVER; + polHttps.fdwChecks = dwCertFlags; + polHttps.pwszServerName = pwszServerName; + + memset(&PolicyPara, 0, sizeof(PolicyPara)); + PolicyPara.cbSize = sizeof(PolicyPara); + PolicyPara.pvExtraPolicyPara = &polHttps; + + memset(&PolicyStatus, 0, sizeof(PolicyStatus)); + PolicyStatus.cbSize = sizeof(PolicyStatus); + + if (!crypt.pCertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, pChainContext, &PolicyPara, &PolicyStatus)) + { + Status = GetLastError(); + Sys_Printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!\n", (unsigned int)Status); + } + else + { + if (PolicyStatus.dwError) + { + char *err; + Status = PolicyStatus.dwError; + switch (Status) + { + case CERT_E_EXPIRED: err = "CERT_E_EXPIRED"; break; + case CERT_E_VALIDITYPERIODNESTING: err = "CERT_E_VALIDITYPERIODNESTING"; break; + case CERT_E_ROLE: err = "CERT_E_ROLE"; break; + case CERT_E_PATHLENCONST: err = "CERT_E_PATHLENCONST"; break; + case CERT_E_CRITICAL: err = "CERT_E_CRITICAL"; break; + case CERT_E_PURPOSE: err = "CERT_E_PURPOSE"; break; + case CERT_E_ISSUERCHAINING: err = "CERT_E_ISSUERCHAINING"; break; + case CERT_E_MALFORMED: err = "CERT_E_MALFORMED"; break; + case CERT_E_UNTRUSTEDROOT: err = "CERT_E_UNTRUSTEDROOT"; break; + case CERT_E_CHAINING: err = "CERT_E_CHAINING"; break; + case TRUST_E_FAIL: err = "TRUST_E_FAIL"; break; + case CERT_E_REVOKED: err = "CERT_E_REVOKED"; break; + case CERT_E_UNTRUSTEDTESTROOT: err = "CERT_E_UNTRUSTEDTESTROOT"; break; + case CERT_E_REVOCATION_FAILURE: err = "CERT_E_REVOCATION_FAILURE"; break; + case CERT_E_CN_NO_MATCH: err = "CERT_E_CN_NO_MATCH"; break; + case CERT_E_WRONG_USAGE: err = "CERT_E_WRONG_USAGE"; break; + default: err = "(unknown)"; break; + } + Con_Printf("Error verifying certificate for '%S': %s\n", pwszServerName, err); + + if (tls_ignorecertificateerrors->ival) + { + Con_Printf("pretending it didn't happen... (tls_ignorecertificateerrors is set)\n"); + Status = SEC_E_OK; + } + } + else + Status = SEC_E_OK; + } + crypt.pCertFreeCertificateChain(pChainContext); + } + + return Status; } -static void SSPI_Handshake (sslfile_t *f) -{ - SECURITY_STATUS ss; - TimeStamp Lifetime; - SecBufferDesc OutBuffDesc; - SecBuffer OutSecBuff; - SecBufferDesc InBuffDesc; - SecBuffer InSecBuff[2]; - ULONG ContextAttributes; - SCHANNEL_CRED SchannelCred; - - if (f->outcrypt.avail) - { - //don't let things build up too much - SSPI_TryFlushCryptOut(f); - if (f->outcrypt.avail) - return; - } - - OutBuffDesc.ulVersion = SECBUFFER_VERSION; - OutBuffDesc.cBuffers = 1; - OutBuffDesc.pBuffers = &OutSecBuff; - - OutSecBuff.cbBuffer = sizeof(f->outcrypt.data) - f->outcrypt.avail; - OutSecBuff.BufferType = SECBUFFER_TOKEN; - OutSecBuff.pvBuffer = f->outcrypt.data + f->outcrypt.avail; - - if (f->handshaking == HS_STARTCLIENT) - { - //no input data yet. - f->handshaking = HS_CLIENT; - - memset(&SchannelCred, 0, sizeof(SchannelCred)); - SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; - SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1 | SP_PROT_SSL3; - SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; /*don't use windows login info or anything*/ - - ss = secur.pAcquireCredentialsHandleA (NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &f->cred, &Lifetime); - if (ss < 0) - { - SSPI_Error(f, "AcquireCredentialsHandle failed\n"); - return; - } - - ss = secur.pInitializeSecurityContextA (&f->cred, NULL, NULL, MessageAttribute, 0, SECURITY_NATIVE_DREP, NULL, 0, &f->sechnd, &OutBuffDesc, &ContextAttributes, &Lifetime); - } - else - { - //only if we actually have data. - if (!f->incrypt.avail) - return; - - InBuffDesc.ulVersion = SECBUFFER_VERSION; - InBuffDesc.cBuffers = 2; - InBuffDesc.pBuffers = InSecBuff; - - InSecBuff[0].BufferType = SECBUFFER_TOKEN; - InSecBuff[0].cbBuffer = f->incrypt.avail; - InSecBuff[0].pvBuffer = f->incrypt.data; - - InSecBuff[1].BufferType = SECBUFFER_EMPTY; - InSecBuff[1].pvBuffer = NULL; - InSecBuff[1].cbBuffer = 0; - - ss = secur.pInitializeSecurityContextA (&f->cred, &f->sechnd, NULL, MessageAttribute, 0, SECURITY_NATIVE_DREP, &InBuffDesc, 0, &f->sechnd, &OutBuffDesc, &ContextAttributes, &Lifetime); - - if (ss == SEC_E_INCOMPLETE_MESSAGE) - return; - - //any extra data should still remain for the next time around. this might be more handshake data or payload data. - if (InSecBuff[1].BufferType == SECBUFFER_EXTRA) - { - memmove(f->incrypt.data, f->incrypt.data + (f->incrypt.avail - InSecBuff[1].cbBuffer), InSecBuff[1].cbBuffer); - f->incrypt.avail = InSecBuff[1].cbBuffer; - } - else f->incrypt.avail = 0; - } - - if (ss == SEC_I_INCOMPLETE_CREDENTIALS) - { - SSPI_Error(f, "server requires credentials\n"); - return; - } - - if (ss < 0) - { - SSPI_Error(f, "InitializeSecurityContext failed\n"); - return; - } - - if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss)) - { - ss = secur.pCompleteAuthToken (&f->sechnd, &OutBuffDesc); - if (ss < 0) - { - SSPI_Error(f, "CompleteAuthToken failed\n"); - return; - } - } - - if (SSPI_CopyIntoBuffer(&f->outcrypt, OutSecBuff.pvBuffer, OutSecBuff.cbBuffer) < OutSecBuff.cbBuffer) - { - SSPI_Error(f, "crypt overflow\n"); - return; - } - - //send early, send often. - SSPI_TryFlushCryptOut(f); - - //its all okay and established if we get this far. - if (ss == SEC_E_OK) - { - SecPkgContext_StreamSizes strsizes; - CERT_CONTEXT *remotecert; - - secur.pQueryContextAttributesA(&f->sechnd, SECPKG_ATTR_STREAM_SIZES, &strsizes); - f->headersize = strsizes.cbHeader; - f->footersize = strsizes.cbTrailer; - f->handshaking = HS_ESTABLISHED; - - if (*f->wpeername) - { - ss = secur.pQueryContextAttributesA(&f->sechnd, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &remotecert); - if (ss != SEC_E_OK) - { - SSPI_Error(f, "unable to read server's certificate\n"); - return; - } - if (VerifyServerCertificate(remotecert, f->wpeername, 0)) - SSPI_Error(f, "Error validating certificante"); - } - else - Sys_Printf("SSL/TLS Server name not specified, skipping verification\n"); - - - SSPI_Encode(f); - } +static void SSPI_Handshake (sslfile_t *f) +{ + SECURITY_STATUS ss; + TimeStamp Lifetime; + SecBufferDesc OutBuffDesc; + SecBuffer OutSecBuff; + SecBufferDesc InBuffDesc; + SecBuffer InSecBuff[2]; + ULONG ContextAttributes; + SCHANNEL_CRED SchannelCred; + + if (f->outcrypt.avail) + { + //don't let things build up too much + SSPI_TryFlushCryptOut(f); + if (f->outcrypt.avail) + return; + } + + OutBuffDesc.ulVersion = SECBUFFER_VERSION; + OutBuffDesc.cBuffers = 1; + OutBuffDesc.pBuffers = &OutSecBuff; + + OutSecBuff.cbBuffer = sizeof(f->outcrypt.data) - f->outcrypt.avail; + OutSecBuff.BufferType = SECBUFFER_TOKEN; + OutSecBuff.pvBuffer = f->outcrypt.data + f->outcrypt.avail; + + if (f->handshaking == HS_STARTCLIENT) + { + //no input data yet. + f->handshaking = HS_CLIENT; + + memset(&SchannelCred, 0, sizeof(SchannelCred)); + SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; + SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1 | SP_PROT_SSL3; + SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; /*don't use windows login info or anything*/ + + ss = secur.pAcquireCredentialsHandleA (NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &f->cred, &Lifetime); + if (ss < 0) + { + SSPI_Error(f, "AcquireCredentialsHandle failed\n"); + return; + } + + ss = secur.pInitializeSecurityContextA (&f->cred, NULL, NULL, MessageAttribute, 0, SECURITY_NATIVE_DREP, NULL, 0, &f->sechnd, &OutBuffDesc, &ContextAttributes, &Lifetime); + } + else + { + //only if we actually have data. + if (!f->incrypt.avail) + return; + + InBuffDesc.ulVersion = SECBUFFER_VERSION; + InBuffDesc.cBuffers = 2; + InBuffDesc.pBuffers = InSecBuff; + + InSecBuff[0].BufferType = SECBUFFER_TOKEN; + InSecBuff[0].cbBuffer = f->incrypt.avail; + InSecBuff[0].pvBuffer = f->incrypt.data; + + InSecBuff[1].BufferType = SECBUFFER_EMPTY; + InSecBuff[1].pvBuffer = NULL; + InSecBuff[1].cbBuffer = 0; + + ss = secur.pInitializeSecurityContextA (&f->cred, &f->sechnd, NULL, MessageAttribute, 0, SECURITY_NATIVE_DREP, &InBuffDesc, 0, &f->sechnd, &OutBuffDesc, &ContextAttributes, &Lifetime); + + if (ss == SEC_E_INCOMPLETE_MESSAGE) + return; + + //any extra data should still remain for the next time around. this might be more handshake data or payload data. + if (InSecBuff[1].BufferType == SECBUFFER_EXTRA) + { + memmove(f->incrypt.data, f->incrypt.data + (f->incrypt.avail - InSecBuff[1].cbBuffer), InSecBuff[1].cbBuffer); + f->incrypt.avail = InSecBuff[1].cbBuffer; + } + else f->incrypt.avail = 0; + } + + if (ss == SEC_I_INCOMPLETE_CREDENTIALS) + { + SSPI_Error(f, "server requires credentials\n"); + return; + } + + if (ss < 0) + { + SSPI_Error(f, "InitializeSecurityContext failed\n"); + return; + } + + if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss)) + { + ss = secur.pCompleteAuthToken (&f->sechnd, &OutBuffDesc); + if (ss < 0) + { + SSPI_Error(f, "CompleteAuthToken failed\n"); + return; + } + } + + if (SSPI_CopyIntoBuffer(&f->outcrypt, OutSecBuff.pvBuffer, OutSecBuff.cbBuffer) < OutSecBuff.cbBuffer) + { + SSPI_Error(f, "crypt overflow\n"); + return; + } + + //send early, send often. + SSPI_TryFlushCryptOut(f); + + //its all okay and established if we get this far. + if (ss == SEC_E_OK) + { + SecPkgContext_StreamSizes strsizes; + CERT_CONTEXT *remotecert; + + secur.pQueryContextAttributesA(&f->sechnd, SECPKG_ATTR_STREAM_SIZES, &strsizes); + f->headersize = strsizes.cbHeader; + f->footersize = strsizes.cbTrailer; + f->handshaking = HS_ESTABLISHED; + + if (*f->wpeername) + { + ss = secur.pQueryContextAttributesA(&f->sechnd, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &remotecert); + if (ss != SEC_E_OK) + { + SSPI_Error(f, "unable to read server's certificate\n"); + return; + } + if (VerifyServerCertificate(remotecert, f->wpeername, 0)) + SSPI_Error(f, "Error validating certificante"); + } + else + Sys_Printf("SSL/TLS Server name not specified, skipping verification\n"); + + + SSPI_Encode(f); + } } static int QDECL SSPI_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) { sslfile_t *f = (sslfile_t *)file; - int err = SSPI_CheckNewInCrypt(f); + int err = SSPI_CheckNewInCrypt(f); if (f->handshaking) { @@ -537,7 +537,7 @@ static int QDECL SSPI_ReadBytes (struct vfsfile_s *file, void *buffer, int bytes } else { - if (err) + if (err) return err; } return bytestoread; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 6b0f1a8e3..9ee0eb9c2 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -98,7 +98,7 @@ typedef struct ftenet_generic_connection_s { netadrtype_t addrtype[FTENET_ADDRTYPES]; qboolean islisten; - int thesocket; + SOCKET thesocket; } ftenet_generic_connection_t; @@ -2518,7 +2518,7 @@ ftenet_generic_connection_t *FTENET_IPX_EstablishConnection(qboolean isserver, c #ifdef TCPCONNECT typedef struct ftenet_tcpconnect_stream_s { - int socketnum; + SOCKET socketnum; int inlen; int outlen; @@ -4458,7 +4458,7 @@ int TCP_OpenStream (netadr_t *remoteaddr) temp = NetadrToSockadr(remoteaddr, &qs); if ((newsocket = socket (((struct sockaddr_in*)&qs)->sin_family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) - return INVALID_SOCKET; + return (int)INVALID_SOCKET; setsockopt(newsocket, SOL_SOCKET, SO_RCVBUF, (void*)&recvbufsize, sizeof(recvbufsize)); @@ -4472,23 +4472,23 @@ int TCP_OpenStream (netadr_t *remoteaddr) if (connect(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET) { int err = qerrno; - if (err != EWOULDBLOCK) + if (err != EWOULDBLOCK && err != EINPROGRESS) { + char buf[256]; + NET_AdrToString(buf, sizeof(buf), remoteaddr); if (err == EADDRNOTAVAIL) { - char buf[128]; - NET_AdrToString(buf, sizeof(buf), remoteaddr); if (remoteaddr->port == 0 && (remoteaddr->type == NA_IP || remoteaddr->type == NA_IPV6)) - Con_Printf ("TCP_OpenStream: no port specified\n"); + Con_Printf ("TCP_OpenStream: no port specified (%s)\n", buf); else Con_Printf ("TCP_OpenStream: invalid address trying to connect to %s\n", buf); } else if (err == EACCES) - Con_Printf ("TCP_OpenStream: access denied: check firewall\n"); + Con_Printf ("TCP_OpenStream: access denied: check firewall (%s)\n", buf); else - Con_Printf ("TCP_OpenStream: connect: error %i\n", err); + Con_Printf ("TCP_OpenStream: connect: error %i (%s)\n", err, buf); closesocket(newsocket); - return INVALID_SOCKET; + return (int)INVALID_SOCKET; } } @@ -4585,7 +4585,7 @@ int UDP_OpenSocket (int port, qboolean bcast) int maxport = port + 100; if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) - return INVALID_SOCKET; + return (int)INVALID_SOCKET; if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); @@ -4596,7 +4596,7 @@ int maxport = port + 100; if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) == -1) { Con_Printf("Cannot create broadcast socket\n"); - return INVALID_SOCKET; + return (int)INVALID_SOCKET; } } @@ -4646,7 +4646,7 @@ int maxport = port + 100; if ((newsocket = socket (PF_INET6, SOCK_DGRAM, 0)) == INVALID_SOCKET) { Con_Printf("IPV6 is not supported: %s\n", strerror(qerrno)); - return INVALID_SOCKET; + return (int)INVALID_SOCKET; } if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) @@ -4660,7 +4660,7 @@ int maxport = port + 100; // { Con_Printf("Cannot create broadcast socket\n"); closesocket(newsocket); - return INVALID_SOCKET; + return (int)INVALID_SOCKET; // } } @@ -4691,7 +4691,7 @@ int maxport = port + 100; err = qerrno; Con_Printf ("UDP6_OpenSocket: bind: (%i) %s", err, strerror(err)); closesocket(newsocket); - return INVALID_SOCKET; + return (int)INVALID_SOCKET; } port++; if (port > maxport) @@ -4699,7 +4699,7 @@ int maxport = port + 100; err = qerrno; Con_Printf ("UDP6_OpenSocket: bind: (%i) %s", err, strerror(err)); closesocket(newsocket); - return INVALID_SOCKET; + return (int)INVALID_SOCKET; } } else @@ -5604,7 +5604,7 @@ int QDECL VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestorea timeout.tv_usec = 0; FD_ZERO(&fd); FD_SET(tf->sock, &fd); - if (!select((int)tf->sock, NULL, &fd, NULL, &timeout)) + if (!select((int)tf->sock+1, NULL, &fd, NULL, &timeout)) return 0; tf->conpending = false; } @@ -5665,7 +5665,10 @@ int QDECL VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestorea else { if (tf->sock == INVALID_SOCKET) + { +perror("moo"); return -1; //signal an error + } return 0; //signal nothing available } } @@ -5685,7 +5688,7 @@ int QDECL VFSTCP_WriteBytes (struct vfsfile_s *file, const void *buffer, int byt timeout.tv_usec = 0; FD_ZERO(&fd); FD_SET(tf->sock, &fd); - if (!select((int)tf->sock, NULL, &fd, NULL, &timeout)) + if (!select((int)tf->sock+1, NULL, &fd, NULL, &timeout)) return 0; tf->conpending = false; } diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 1cfd7d780..4b8260e83 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -11,94 +11,6 @@ #define PLUG_EITHER 3 #ifdef PLUGINS -//#define GNUTLS -#ifdef GNUTLS - -#if defined(_WIN32) && !defined(MINGW) - -//lets rip stuff out of the header and supply a seperate dll. -//gnutls is huge. -//also this helps get around the whole msvc/mingw thing. - -struct DSTRUCT; -typedef struct DSTRUCT* gnutls_certificate_credentials; -typedef gnutls_certificate_credentials gnutls_certificate_client_credentials; -typedef struct DSTRUCT* gnutls_anon_client_credentials; -struct gnutls_session_int; -typedef struct gnutls_session_int* gnutls_session; -typedef void * gnutls_transport_ptr; - -typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, - GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP, - GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA, GNUTLS_KX_SRP_DSS -} gnutls_kx_algorithm; -typedef enum gnutls_certificate_type { GNUTLS_CRT_X509=1, GNUTLS_CRT_OPENPGP -} gnutls_certificate_type; -typedef enum gnutls_connection_end { GNUTLS_SERVER=1, GNUTLS_CLIENT } gnutls_connection_end; -typedef enum gnutls_credentials_type { GNUTLS_CRD_CERTIFICATE=1, GNUTLS_CRD_ANON, GNUTLS_CRD_SRP } gnutls_credentials_type; -typedef enum gnutls_close_request { GNUTLS_SHUT_RDWR=0, GNUTLS_SHUT_WR=1 } gnutls_close_request; - -#define GNUTLS_E_AGAIN -28 -#define GNUTLS_E_INTERRUPTED -52 - -int (VARGS *gnutls_bye)( gnutls_session session, gnutls_close_request how); -void (VARGS *gnutls_perror)( int error); -int (VARGS *gnutls_handshake)( gnutls_session session); -void (VARGS *gnutls_transport_set_ptr)(gnutls_session session, gnutls_transport_ptr ptr); -int (VARGS *gnutls_certificate_type_set_priority)( gnutls_session session, const int*); -int (VARGS *gnutls_credentials_set)( gnutls_session, gnutls_credentials_type type, void* cred); -int (VARGS *gnutls_kx_set_priority)( gnutls_session session, const int*); -int (VARGS *gnutls_init)(gnutls_session * session, gnutls_connection_end con_end); -int (VARGS *gnutls_set_default_priority)(gnutls_session session); -int (VARGS *gnutls_certificate_allocate_credentials)( gnutls_certificate_credentials *sc); -int (VARGS *gnutls_anon_allocate_client_credentials)( gnutls_anon_client_credentials *sc); -int (VARGS *gnutls_global_init)(void); -int (VARGS *gnutls_record_send)( gnutls_session session, const void *data, size_t sizeofdata); -int (VARGS *gnutls_record_recv)( gnutls_session session, void *data, size_t sizeofdata); - -qboolean Init_GNUTLS(void) -{ - HMODULE hmod; - hmod = LoadLibrary("gnutls.dll"); - if (!hmod) - return false; - - gnutls_bye = (void*)GetProcAddress(hmod, "gnutls_bye"); - gnutls_perror = (void*)GetProcAddress(hmod, "gnutls_perror"); - gnutls_handshake = (void*)GetProcAddress(hmod, "gnutls_handshake"); - gnutls_transport_set_ptr = (void*)GetProcAddress(hmod, "gnutls_transport_set_ptr"); - gnutls_certificate_type_set_priority = (void*)GetProcAddress(hmod, "gnutls_certificate_type_set_priority"); - gnutls_credentials_set = (void*)GetProcAddress(hmod, "gnutls_credentials_set"); - gnutls_kx_set_priority = (void*)GetProcAddress(hmod, "gnutls_kx_set_priority"); - gnutls_init = (void*)GetProcAddress(hmod, "gnutls_init"); - gnutls_set_default_priority = (void*)GetProcAddress(hmod, "gnutls_set_default_priority"); - gnutls_certificate_allocate_credentials = (void*)GetProcAddress(hmod, "gnutls_certificate_allocate_credentials"); - gnutls_anon_allocate_client_credentials = (void*)GetProcAddress(hmod, "gnutls_anon_allocate_client_credentials"); - gnutls_global_init = (void*)GetProcAddress(hmod, "gnutls_global_init"); - gnutls_record_send = (void*)GetProcAddress(hmod, "gnutls_record_send"); - gnutls_record_recv = (void*)GetProcAddress(hmod, "gnutls_record_recv"); - - if (!gnutls_bye || !gnutls_perror || !gnutls_handshake || !gnutls_transport_set_ptr - || !gnutls_certificate_type_set_priority || !gnutls_credentials_set - || !gnutls_kx_set_priority || !gnutls_init || !gnutls_set_default_priority - || !gnutls_certificate_allocate_credentials || !gnutls_anon_allocate_client_credentials - || !gnutls_global_init || !gnutls_record_send || !gnutls_record_recv) - { - Con_Printf("gnutls.dll doesn't contain all required exports\n"); - FreeLibrary(hmod); - return false; - } - - return true; -} - -#else -#include -qboolean Init_GNUTLS(void) {return true;} -#endif - -#endif - cvar_t plug_sbar = SCVAR("plug_sbar", "1"); cvar_t plug_loaddefault = SCVAR("plug_loaddefault", "1"); @@ -816,7 +728,6 @@ static void VARGS Plug_FreeConCommands(plugin_t *plug) typedef enum{ STREAM_NONE, STREAM_SOCKET, - STREAM_TLS, STREAM_VFS } plugstream_e; @@ -832,9 +743,6 @@ typedef struct { int curlen; int curpos; } file; -#ifdef GNUTLS - gnutls_session session; -#endif } pluginstream_t; pluginstream_t *pluginstreamarray; int pluginstreamarraylen; @@ -995,7 +903,6 @@ qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, const qintp { pluginstream_t *stream; int handle = VM_LONG(arg[0]); - qboolean anon = false; if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) { Con_Printf("Plug_Net_SetTLSClient: socket does not belong to you (or is invalid)\n"); @@ -1014,104 +921,6 @@ qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, const qintp Plug_Net_Close_Internal(handle); return -1; } - return 0; -} -#endif - -#ifdef GNUTLS - -qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - static gnutls_anon_client_credentials anoncred; - static gnutls_certificate_credentials xcred; - - int ret; - - long _false = false; - long _true = true; - - /* Need to enable anonymous KX specifically. */ - const int kx_prio[] = {GNUTLS_KX_ANON_DH, 0}; - const int cert_type_priority[3] = {GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0}; - - - pluginstream_t *stream; - int handle = VM_LONG(arg[0]); - qboolean anon = false; - if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) - { - Con_Printf("Plug_Net_SetTLSClient: socket does not belong to you (or is invalid)\n"); - return -2; - } - stream = &pluginstreamarray[handle]; - if (stream->type != STREAM_SOCKET) - { //not a socket - invalid - Con_Printf("Plug_Net_SetTLSClient: Not a socket handle\n"); - return -2; - } - - ioctlsocket (stream->socket, FIONBIO, &_false); - - -{ - static qboolean needinit = true; - if (needinit) - { - gnutls_global_init (); - - gnutls_anon_allocate_client_credentials (&anoncred); - gnutls_certificate_allocate_credentials (&xcred); -// gnutls_certificate_set_x509_trust_file (xcred, "ca.pem", GNUTLS_X509_FMT_PEM); - - needinit = false; - } -} - - stream->type = STREAM_TLS; - - // Initialize TLS session - gnutls_init (&stream->session, GNUTLS_CLIENT); - - // Use default priorities - gnutls_set_default_priority (stream->session); - if (anon) - { - gnutls_kx_set_priority (stream->session, kx_prio); - gnutls_credentials_set (stream->session, GNUTLS_CRD_ANON, anoncred); - } - else - { - gnutls_certificate_type_set_priority (stream->session, cert_type_priority); - gnutls_credentials_set (stream->session, GNUTLS_CRD_CERTIFICATE, xcred); - } - - // connect to the peer - gnutls_transport_set_ptr (stream->session, (gnutls_transport_ptr) stream->socket); - - // Perform the TLS handshake - - - ret = GNUTLS_E_AGAIN; - while ((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) - { - ret = gnutls_handshake (stream->session); - } - - if (ret < 0) - { - Con_Printf (CON_ERROR "*** TLS handshake failed (%i)\n", ret); - gnutls_perror (ret); - - stream->type = STREAM_SOCKET; //go back to regular socket - gnutls_bye (pluginstreamarray[handle].session, GNUTLS_SHUT_RDWR); - - return -2; - } - - ioctlsocket (stream->socket, FIONBIO, &_true); - - - return 0; } #endif @@ -1257,14 +1066,6 @@ void Plug_Net_Close_Internal(int handle) case STREAM_SOCKET: #ifndef NACL closesocket(pluginstreamarray[handle].socket); -#endif - break; - case STREAM_TLS: -#ifdef GNUTLS - gnutls_bye (pluginstreamarray[handle].session, GNUTLS_SHUT_RDWR); - pluginstreamarray[handle].type = STREAM_SOCKET; - Plug_Net_Close_Internal(handle); - return; #endif break; } @@ -1300,23 +1101,6 @@ qintptr_t VARGS Plug_Net_Recv(void *offset, quintptr_t mask, const qintptr_t *ar return read; #endif -#ifdef GNUTLS - case STREAM_TLS: - read = gnutls_record_recv(pluginstreamarray[handle].session, dest, destlen); - if (read < 0) - { - if (read == GNUTLS_E_AGAIN || read == -9) - return -1; - else - { - Con_Printf("TLS Read Error %i (bufsize %i)\n", read, destlen); - return -2; - } - } - else if (read == 0) - return -2; //closed by remote connection. - return read; -#endif case STREAM_VFS: return VFS_READ(pluginstreamarray[handle].vfs, dest, destlen); default: @@ -1348,23 +1132,6 @@ qintptr_t VARGS Plug_Net_Send(void *offset, quintptr_t mask, const qintptr_t *ar return written; #endif -#ifdef GNUTLS - case STREAM_TLS: - written = gnutls_record_send(pluginstreamarray[handle].session, src, srclen); - if (written < 0) - { - if (written == GNUTLS_E_AGAIN || written == GNUTLS_E_INTERRUPTED) - return -1; - else - { - Con_Printf("TLS Send Error %i (%i bytes)\n", written, srclen); - return -2; - } - } - else if (written == 0) - return -2; //closed by remote connection. - return written; -#endif case STREAM_VFS: return VFS_WRITE(pluginstreamarray[handle].vfs, src, srclen); @@ -1531,10 +1298,6 @@ void Plug_Initialise(qboolean fromgamedir) Plug_RegisterBuiltin("Net_TCPListen", Plug_Net_TCPListen, 0); Plug_RegisterBuiltin("Net_Accept", Plug_Net_Accept, 0); Plug_RegisterBuiltin("Net_TCPConnect", Plug_Net_TCPConnect, 0); -#ifdef GNUTLS - if (Init_GNUTLS()) - Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0); -#endif #ifdef HAVE_SSL Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0); #endif diff --git a/engine/common/sys.h b/engine/common/sys.h index 6069e396f..847a93ced 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -32,7 +32,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base // // memory protection // -void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length); +void Sys_MakeCodeWriteable (void * startaddr, unsigned long length); // // system IO diff --git a/engine/common/sys_win_threads.c b/engine/common/sys_win_threads.c index 0e54e1c2a..8c22589d4 100644 --- a/engine/common/sys_win_threads.c +++ b/engine/common/sys_win_threads.c @@ -32,12 +32,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* Thread creation calls */ typedef struct threadwrap_s { - void (*func)(void *); + int (*func)(void *); void *args; } threadwrap_t; // the thread call is wrapped so we don't need WINAPI everywhere -DWORD WINAPI threadwrapper(void *args) +unsigned int WINAPI threadwrapper(void *args) { threadwrap_t tw; tw.func = ((threadwrap_t *)args)->func; @@ -85,7 +85,7 @@ void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority { threadwrap_t *tw = (threadwrap_t *)malloc(sizeof(threadwrap_t)); HANDLE handle; - DWORD tid; + unsigned int tid; if (!tw) return NULL; diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 8eb488e3a..382bbcb2a 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -75,7 +75,7 @@ model_t *lightmodel; int numlightdata; qboolean writelitfile; -int relitsurface; +long relitsurface; void RMod_UpdateLightmap(int snum) { msurface_t *s; diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 8484fde8a..9243a961f 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -551,7 +551,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) { int i; HDC hdc; - int lastmodestate, wwidth, wheight, pleft, ptop, pwidth, pheight; + int wwidth, wheight, pleft, ptop, pwidth, pheight; RECT rect; hdc = GetDC(NULL); @@ -563,8 +563,6 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) } ReleaseDC(NULL, hdc); - lastmodestate = modestate; - WindowRect.top = WindowRect.left = 0; WindowRect.right = info->width; @@ -725,7 +723,7 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info) { int i; HDC hdc; - int lastmodestate, wwidth, wheight; + int wwidth, wheight; RECT rect; if (leavecurrentmode) //don't do this with d3d - d3d should set it's own video mode. @@ -753,7 +751,6 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info) } } - lastmodestate = modestate; modestate = MS_FULLDIB; WindowRect.top = WindowRect.left = 0; @@ -1755,12 +1752,10 @@ qboolean GLAppActivate(BOOL fActive, BOOL minimize) ****************************************************************************/ { static BOOL sound_active; - HWND foregroundwindow; if (ActiveApp == fActive && Minimized == minimize) return false; //so windows doesn't crash us over and over again. - foregroundwindow = GetForegroundWindow(); ActiveApp = fActive;// && (foregroundwindow==mainwindow); Minimized = minimize; @@ -1821,7 +1816,8 @@ LONG WINAPI GLMainWndProc ( LPARAM lParam) { LONG lRet = 1; - int fActive, fMinimized, temp; +// int fActive, fMinimized; + int temp; extern unsigned int uiWheelMessage; if ( uMsg == uiWheelMessage ) @@ -1991,8 +1987,8 @@ LONG WINAPI GLMainWndProc ( break; case WM_ACTIVATE: - fActive = LOWORD(wParam); - fMinimized = (BOOL) HIWORD(wParam); +// fActive = LOWORD(wParam); +// fMinimized = (BOOL) HIWORD(wParam); // if (!GLAppActivate(!(fActive == WA_INACTIVE), fMinimized)) break;//so, urm, tell me microsoft, what changed? if (modestate == MS_FULLDIB) diff --git a/plugins/jabber/jabberclient.c b/plugins/jabber/jabberclient.c index f6d49c0fd..cb777dae1 100644 --- a/plugins/jabber/jabberclient.c +++ b/plugins/jabber/jabberclient.c @@ -746,8 +746,8 @@ void JCL_FlushOutgoing(jclient_t *jcl) jcl->outbufpos += sent; jcl->outbuflen -= sent; } - else - Con_Printf("Unable to send anything\n"); +// else +// Con_Printf("Unable to send anything\n"); } void JCL_AddClientMessage(jclient_t *jcl, char *msg, int datalen) { @@ -959,6 +959,58 @@ void Base64_Finish(void) base64_cur = 0; } +//decode a base64 byte to a 0-63 value. Cannot cope with =. +static int Base64_DecodeByte(char byt) +{ + if (byt >= 'A' && byt <= 'Z') + return (byt-'A') + 0; + if (byt >= 'a' && byt <= 'z') + return (byt-'a') + 26; + if (byt >= '0' && byt <= '9') + return (byt-'0') + 52; + if (byt == '+') + return 62; + if (byt == '/') + return 63; + return -1; +} +int Base64_Decode(char *out, int outlen, char *src, int srclen) +{ + int len = 0; + int result; + + //4 input chars give 3 output chars + while(srclen >= 4) + { + if (len+3 > outlen) + break; + result = Base64_DecodeByte(src[0])<<18; + result |= Base64_DecodeByte(src[1])<<12; + out[len++] = (result>>16)&0xff; + if (src[2] != '=') + { + result |= Base64_DecodeByte(src[2])<<6; + out[len++] = (result>>8)&0xff; + if (src[3] != '=') + { + result |= Base64_DecodeByte(src[3])<<0; + out[len++] = (result>>0)&0xff; + } + } + if (result & 0xff000000) + return 0; //some kind of invalid char + + src += 4; + srclen -= 4; + } + + //some kind of error + if (srclen) + return 0; + + return len; +} + char *TrimResourceFromJid(char *jid) { char *slash; @@ -1088,6 +1140,7 @@ static qboolean JCL_RosterReply(jclient_t *jcl, xmltree_t *tree) if (c) { JCL_RosterUpdate(jcl, c); + JCL_GeneratePresence(true); return true; } JCL_GeneratePresence(true); @@ -1409,51 +1462,136 @@ int JCL_ClientFrame(jclient_t *jcl) } else if ((ot=XML_ChildOfTree(tree, "mechanisms", 0))) { + qboolean canplain = false; +// qboolean canmd5 = false; +// qboolean canscramsha1 = false; +// qboolean canxoath2 = false; + for(ot = ot->child; ot; ot = ot->sibling) { if (!strcmp(ot->body, "PLAIN")) - { - char msg[2048]; - if (!jclient->issecure && !pCvar_GetFloat("xmpp_allowplainauth")) //probably don't send plain without tls. - { - //plain can still be read with man-in-the-middle attacks, of course, even with tls if the certificate is spoofed. - Con_Printf("Ignoring auth \'%s\'\n", ot->body); - continue; - } - Con_Printf("Authing with \'%s\'%s\n", ot->body, jclient->issecure?" over tls/ssl":""); - -// Base64_Add(jclient->username, strlen(jcl->username)); -// Base64_Add("@", 1); -// Base64_Add(jclient->domain, strlen(jcl->domain)); - Base64_Add("", 1); - Base64_Add(jclient->username, strlen(jcl->username)); - Base64_Add("", 1); - Base64_Add(jcl->password, strlen(jcl->password)); - Base64_Finish(); - Q_snprintf(msg, sizeof(msg), "%s", base64); - JCL_AddClientMessageString(jcl, msg); -// JCL_AddClientMessageString(jcl, ""); -// JCL_AddClientMessageString(jcl, base64); -// JCL_AddClientMessageString(jcl, ""); - unparsable = false; - break; - } - else - Con_Printf("Unable to use auth method \'%s\'\n", ot->body); + canplain = true; +// else if (!strcmp(ot->body, "SCRAM-SHA-1")) +// cansha1 = true; +// else if (!strcmp(ot->body, "DIGEST-MD5")) +// canmd5 = true; +// else if (!strcmp(ot->body, "X-OAUTH2")) +// canxoath2 = true; +// else +// Con_Printf("Unknown auth method \'%s\'\n", ot->body); } - if (!ot) +/* + if (canscramsha1) { - Con_Printf("JCL: No suitable auth methods\n"); - unparsable = true; + Con_Printf("Using scram-sha-1%s\n", jclient->issecure?" over tls/ssl":""); + strcpy(jcl->authnonce, "abcdefghijklmnopqrstuvwxyz"); //FIXME: should be random + Base64_Add("n,,n=", 5); + Base64_Add(jclient->username, strlen(jcl->username)); + Base64_Add(",r=", 3); + Base64_Add(jcl->authnonce, strlen(jcl->authnonce)); //must be random ascii. + Base64_Finish(); + JCL_AddClientMessagef(jcl, "%s", base64); + unparsable = false; + } + else +*/ + if (canplain && (jclient->issecure || pCvar_GetFloat("xmpp_allowplainauth"))) + { + //plain can still be read with man-in-the-middle attacks, of course, even with tls if the certificate is spoofed, so this should always be the lowest priority. + //we just hope that the tls certificate cannot be spoofed. + Con_Printf("Using plain auth%s\n", jclient->issecure?" over tls/ssl":""); + + Base64_Add("", 1); + Base64_Add(jclient->username, strlen(jcl->username)); + Base64_Add("", 1); + Base64_Add(jcl->password, strlen(jcl->password)); + Base64_Finish(); + JCL_AddClientMessagef(jcl, "%s", base64); + unparsable = false; + } + else + { + Con_Printf("XMPP: No suitable auth methods. Unable to connect.\n"); + XML_ConPrintTree(tree, 0); + XML_Destroy(tree); + return JCL_KILL; } } else //we cannot auth, no suitable method. { - Con_Printf("JCL: Neither SASL or TLS are usable\n"); - unparsable = true; + Con_Printf("XMPP: Neither SASL or TLS are usable\n"); + XML_Destroy(tree); + return JCL_KILL; } } } +/* + else if (!strcmp(tree->name, "challenge") && !strcmp(tree->xmlns, "urn:ietf:params:xml:ns:xmpp-sasl")) + { + //sasl SCRAM-SHA-1 challenge + //send back the same 'r' attribute + buf saslchal; + int l, i; + buf salt; + buf csn; + buf itr; + buf final; + buf sigkey; + char salted_password[20]; + char proof[20]; + char proof64[30]; + char clientkey[20]; + char storedkey[20]; + + void hmacsha1(char *out, char *key, int keysize, char *data, int datalen); + void Hi(char *out, char *password, buf salt, int i); + + saslchal.len = Base64_Decode(saslchal.buf, sizeof(saslchal.buf), tree->body, strlen(tree->body)); + //be warned, these CAN contain nulls. + csn = saslattr(&saslchal, 'r'); + salt = saslattr(&saslchal, 's'); + itr = saslattr(&saslchal, 'i'); + + + //this is the first part of the message we're about to send, with no proof. + //c(channel) is mandatory but nulled and forms part of the hash + final.len = 0; + buf_cat(&final, "c=", 2); + Base64_Add("n,,", 3)); + Base64_Finish(); + final.cat(&final, base64, strlen(base64)); + final.cat(&final, "r=", 2); + final.cat(&final, csn.buf, csn.len); + + //our original message + ',' + challenge + ',' + the message we're about to send. + sigkey.len = 0; + buf_cat(&sigkey, "n,,n=", 5); + buf_cat(&sigkey, jcl->username, strlen(jcl->username)); + buf_cat(&sigkey, "r=", 2); + buf_cat(&sigkey, jcl->authnonce, strlen(jcl->authnonce)); + buf_cat(&sigkey, ",", 1); + buf_cat(&sigkey, saslchal.buf, saslchal.len); + buf_cat(&sigkey, ",", 1); + buf_cat(&sigkey, final.buf, final.len); + + Hi(salted_password, password, salt, atoi(itr)); + hmacsha1(clientkey, salted_password, sizeof(salted_password), "Client Key", strlen("Client Key")); + storedkey = sha1(clientkey, sizeof(clientkey)); + hmacsha1(clientsignature, storedkey, sizeof(storedkey), sigkey.buf, sigkey.len); + + for (i = 0; i < sizeof(proof); i++) + proof[i] = clientkey[i] ^ clientsignature[i]; + + Base64_Add(proof, sizeof(proof)); + Base64_Finish(); + strcpy(proof64, base64); + Base64_Add(final, buflen(final)); + Base64_Add(",p=", 3); + Base64_Add(proof64, strlen(proof64)); + Base64_Finish(); + JCL_AddClientMessagef(jcl, "%s", base64); + } +*/ else if (!strcmp(tree->name, "proceed")) { //switch to TLS, if we can @@ -1919,7 +2057,7 @@ void JCL_GeneratePresence(qboolean force) { char caps[256]; Q_strlcpy(jclient->curquakeserver, *servermap?servermap:serveraddr, sizeof(jclient->curquakeserver)); - +Con_Printf("Sending presence %s\n", jclient->curquakeserver); //note: ext='voice-v1 camera-v1 video-v1' is some legacy nonsense, and is required for voice calls with googletalk clients or something stupid like that Q_snprintf(caps, sizeof(caps), "", buildcapshash());