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
This commit is contained in:
Spoike 2013-06-24 09:04:00 +00:00
parent 4c3c8a2e64
commit 2ff17aed07
22 changed files with 957 additions and 707 deletions

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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)
{

View file

@ -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))

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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 <gnutls/gnutls.h>
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 <errno.h>
/*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

View file

@ -1,12 +1,12 @@
#include "quakedef.h"
#if defined(_WIN32) && !defined(_SDL) && defined(HAVE_SSL)
cvar_t *tls_ignorecertificateerrors;
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
#include <sspi.h>
#include <schannel.h>
#include "quakedef.h"
#if defined(HAVE_WINSSPI)
cvar_t *tls_ignorecertificateerrors;
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
#include <sspi.h>
#include <schannel.h>
//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;

View file

@ -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;
}

View file

@ -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 <gnutls/gnutls.h>
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

View file

@ -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

View file

@ -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;

View file

@ -75,7 +75,7 @@ model_t *lightmodel;
int numlightdata;
qboolean writelitfile;
int relitsurface;
long relitsurface;
void RMod_UpdateLightmap(int snum)
{
msurface_t *s;

View file

@ -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)

View file

@ -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), "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>%s</auth>", base64);
JCL_AddClientMessageString(jcl, msg);
// JCL_AddClientMessageString(jcl, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>");
// JCL_AddClientMessageString(jcl, base64);
// JCL_AddClientMessageString(jcl, "</auth>");
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, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'>%s</auth>", 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, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>%s</auth>", 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, "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</response>", 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), "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://fteqw.com/ftexmppplugin' ver='%s'/>", buildcapshash());