mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-21 19:41:14 +00:00
Rework some hashfunc_t stuff.
This commit is contained in:
parent
1fe478dfa1
commit
c5f837d468
26 changed files with 184 additions and 278 deletions
|
@ -3009,9 +3009,9 @@ fail:
|
|||
else if (!strcmp(auth, "SHA1"))
|
||||
hashfunc = &hash_sha1;
|
||||
else if (!strcmp(auth, "SHA2_256"))
|
||||
hashfunc = &hash_sha256;
|
||||
hashfunc = &hash_sha2_256;
|
||||
else if (!strcmp(auth, "SHA2_512"))
|
||||
hashfunc = &hash_sha512;
|
||||
hashfunc = &hash_sha2_512;
|
||||
else if (*auth)
|
||||
Con_Printf("Server requires unsupported auth method: %s\n", auth);
|
||||
|
||||
|
|
|
@ -536,10 +536,9 @@ char *CL_GUIDString(netadr_t *adr)
|
|||
{
|
||||
static qbyte buf[2048];
|
||||
static int buflen;
|
||||
unsigned int digest[4];
|
||||
qbyte digest[DIGEST_MAXSIZE];
|
||||
char serveraddr[256];
|
||||
void *blocks[2];
|
||||
int lens[2];
|
||||
void *ctx;
|
||||
|
||||
if (!*cl_sendguid.string && *connectinfo.ext.guidsalt)
|
||||
{
|
||||
|
@ -587,11 +586,12 @@ char *CL_GUIDString(netadr_t *adr)
|
|||
}
|
||||
}
|
||||
|
||||
blocks[0] = buf;lens[0] = buflen;
|
||||
blocks[1] = serveraddr;lens[1] = strlen(serveraddr);
|
||||
Com_BlocksChecksum(2, blocks, lens, (void*)digest);
|
||||
|
||||
Q_snprintfz(connectinfo.guid, sizeof(connectinfo.guid), "%08x%08x%08x%08x", digest[0], digest[1], digest[2], digest[3]);
|
||||
ctx = alloca(hash_md4.contextsize);
|
||||
hash_md4.init(ctx);
|
||||
hash_md4.process(ctx, buf, buflen);
|
||||
hash_md4.process(ctx, serveraddr, strlen(serveraddr));
|
||||
hash_md4.terminate(digest, ctx);
|
||||
Base16_EncodeBlock(digest, hash_md4.digestsize, connectinfo.guid, sizeof(connectinfo.guid));
|
||||
return connectinfo.guid;
|
||||
}
|
||||
|
||||
|
|
|
@ -1498,7 +1498,7 @@ static qboolean PM_ParsePackageList(const char *f, unsigned int parseflags, cons
|
|||
size_t signsize;
|
||||
enum hashvalidation_e r;
|
||||
int i;
|
||||
hashfunc_t *hf = &hash_sha512;
|
||||
hashfunc_t *hf = &hash_sha2_512;
|
||||
void *hashdata = Z_Malloc(hf->digestsize);
|
||||
void *hashctx = Z_Malloc(hf->contextsize);
|
||||
tokstart = COM_StringParse (tokstart, authority, sizeof(authority), false, false);
|
||||
|
@ -4071,7 +4071,7 @@ static void PM_StartADownload(void)
|
|||
}
|
||||
|
||||
if (p->filesha512 && tmpfile)
|
||||
tmpfile = FS_Hash_ValidateWrites(tmpfile, p->name, p->filesize, &hash_sha512, p->filesha512);
|
||||
tmpfile = FS_Hash_ValidateWrites(tmpfile, p->name, p->filesize, &hash_sha2_512, p->filesha512);
|
||||
else if (p->filesha1 && tmpfile)
|
||||
tmpfile = FS_Hash_ValidateWrites(tmpfile, p->name, p->filesize, &hash_sha1, p->filesha1);
|
||||
|
||||
|
|
|
@ -7997,7 +7997,7 @@ static qboolean CSQC_ValidateMainCSProgs(void *file, size_t filesize, unsigned i
|
|||
}
|
||||
else
|
||||
{ //FTE uses folded-md4. yeah, its broken but at least its still more awkward
|
||||
if (LittleLong(Com_BlockChecksum(file, filesize)) != checksum)
|
||||
if (LittleLong(CalcHashInt(&hash_md4, file, filesize)) != checksum)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1219,7 +1219,7 @@ static void DoSign(const char *fname, int signtype)
|
|||
}
|
||||
else if (f)
|
||||
{
|
||||
hashfunc_t *h = (signtype==1)?&hash_sha256:&hash_sha512;
|
||||
hashfunc_t *h = (signtype==1)?&hash_sha2_256:&hash_sha2_512;
|
||||
size_t l, ts = 0;
|
||||
void *ctx = alloca(h->contextsize);
|
||||
qbyte data[65536*16];
|
||||
|
|
|
@ -916,7 +916,7 @@ static void Cmd_Exec_f (void)
|
|||
Cbuf_InsertText (fs_manifest->defaultoverrides, level, false);
|
||||
|
||||
#if defined(HAVE_LEGACY) && defined(HAVE_CLIENT)
|
||||
if (l == 1914 && Com_BlockChecksum(f, l) == 0x2d7b72b9)
|
||||
if (l == 1914 && CalcHashInt(&hash_md4, f, l) == 0x2d7b72b9)
|
||||
s = (char*)replacementq1binds;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -930,14 +930,12 @@ void InfoBuf_WriteToFile(vfsfile_t *f, infobuf_t *info, const char *commandname,
|
|||
void InfoBuf_Enumerate (infobuf_t *info, void *ctx, void(*cb)(void *ctx, const char *key, const char *value));
|
||||
|
||||
|
||||
void Com_BlocksChecksum (int blocks, void **buffer, int *len, unsigned char *outbuf);
|
||||
unsigned int Com_BlockChecksum (const void *buffer, int length);
|
||||
void Com_BlockFullChecksum (const void *buffer, int len, unsigned char *outbuf);
|
||||
qbyte COM_BlockSequenceCheckByte (qbyte *base, int length, int sequence, unsigned mapchecksum);
|
||||
qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
|
||||
qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
|
||||
|
||||
size_t Base64_EncodeBlock(const qbyte *in, size_t length, char *out, size_t outsize); //tries to null terminate, but returns length without termination.
|
||||
size_t Base64_EncodeBlockURI(const qbyte *in, size_t length, char *out, size_t outsize); //slightly different chars for uri safety. also trims.
|
||||
size_t Base64_DecodeBlock(const char *in, const char *in_end, qbyte *out, size_t outsize); // +/ and =
|
||||
size_t Base16_EncodeBlock(const char *in, size_t length, qbyte *out, size_t outsize);
|
||||
size_t Base16_DecodeBlock(const char *in, qbyte *out, size_t outsize);
|
||||
|
@ -951,15 +949,16 @@ typedef struct
|
|||
void (*process) (void *context, const void *data, size_t datasize);
|
||||
void (*terminate) (unsigned char *digest, void *context);
|
||||
} hashfunc_t;
|
||||
extern hashfunc_t hash_sha1;
|
||||
extern hashfunc_t hash_sha224;
|
||||
extern hashfunc_t hash_sha256;
|
||||
extern hashfunc_t hash_sha384;
|
||||
extern hashfunc_t hash_sha512;
|
||||
extern hashfunc_t hash_crc16;
|
||||
extern hashfunc_t hash_md4; //required for vanilla qw mapchecks
|
||||
extern hashfunc_t hash_sha1; //required for websockets, and ezquake's crypted rcon
|
||||
extern hashfunc_t hash_sha2_224;
|
||||
extern hashfunc_t hash_sha2_256; //required for webrtc
|
||||
extern hashfunc_t hash_sha2_384;
|
||||
extern hashfunc_t hash_sha2_512;
|
||||
extern hashfunc_t hash_crc16; //aka ccitt, required for qw's clc_move and various bits of dp compat
|
||||
extern hashfunc_t hash_crc16_lower;
|
||||
unsigned int hashfunc_terminate_uint(const hashfunc_t *hash, void *context); //terminate, except returning the digest as a uint instead of a blob. folds the digest if longer than 4 bytes.
|
||||
unsigned int CalcHashInt(const hashfunc_t *hash, const unsigned char *data, size_t datasize);
|
||||
unsigned int CalcHashInt(const hashfunc_t *hash, const void *data, size_t datasize);
|
||||
size_t CalcHash(const hashfunc_t *hash, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datasize);
|
||||
size_t CalcHMAC(const hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datalen, const unsigned char *key, size_t keylen);
|
||||
|
||||
|
|
|
@ -1330,10 +1330,10 @@ static void COM_CalcHash_Thread(void *ctx, void *fname, size_t a, size_t b)
|
|||
// {"crc16", &hash_crc16},
|
||||
{"sha1", &hash_sha1},
|
||||
#if defined(HAVE_SERVER) || defined(HAVE_CLIENT)
|
||||
// {"sha224", &hash_sha224},
|
||||
{"sha256", &hash_sha256},
|
||||
// {"sha384", &hash_sha384},
|
||||
// {"sha512", &hash_sha512},
|
||||
// {"sha224", &hash_sha2_224},
|
||||
{"sha256", &hash_sha2_256},
|
||||
// {"sha384", &hash_sha2_384},
|
||||
// {"sha512", &hash_sha2_512},
|
||||
#endif
|
||||
};
|
||||
qbyte digest[DIGEST_MAXSIZE];
|
||||
|
|
|
@ -1235,9 +1235,9 @@ static int QDECL FSDZ_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int c
|
|||
}
|
||||
|
||||
if (crctype)
|
||||
result = Com_BlockChecksum(filecrcs, numcrcs*sizeof(int));
|
||||
result = CalcHashInt(&hash_md4, filecrcs, numcrcs*sizeof(int));
|
||||
else
|
||||
result = Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int));
|
||||
result = CalcHashInt(&hash_md4, filecrcs+1, (numcrcs-1)*sizeof(int));
|
||||
|
||||
BZ_Free(filecrcs);
|
||||
return result;
|
||||
|
|
|
@ -176,9 +176,9 @@ static int QDECL FSPAK_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int
|
|||
}
|
||||
|
||||
if (crctype)
|
||||
result = Com_BlockChecksum(filecrcs, numcrcs*sizeof(int));
|
||||
result = CalcHashInt(&hash_md4, filecrcs, numcrcs*sizeof(int));
|
||||
else
|
||||
result = Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int));
|
||||
result = CalcHashInt(&hash_md4, filecrcs+1, (numcrcs-1)*sizeof(int));
|
||||
|
||||
BZ_Free(filecrcs);
|
||||
return result;
|
||||
|
|
|
@ -788,9 +788,9 @@ static int QDECL FSZIP_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int
|
|||
}
|
||||
|
||||
if (crctype || numcrcs < 1)
|
||||
result = Com_BlockChecksum(filecrcs, numcrcs*sizeof(int));
|
||||
result = CalcHashInt(&hash_md4, filecrcs, numcrcs*sizeof(int));
|
||||
else
|
||||
result = Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int));
|
||||
result = CalcHashInt(&hash_md4, filecrcs+1, (numcrcs-1)*sizeof(int));
|
||||
|
||||
BZ_Free(filecrcs);
|
||||
return result;
|
||||
|
|
|
@ -4517,7 +4517,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
|
|||
return NULL;
|
||||
}
|
||||
|
||||
checksum = LittleLong (Com_BlockChecksum (buf, length));
|
||||
checksum = LittleLong (CalcHashInt(&hash_md4, buf, length));
|
||||
|
||||
header = *(q2dheader_t *)(buf);
|
||||
header.ident = LittleLong(header.ident);
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef struct {
|
|||
} MD4_CTX;
|
||||
|
||||
void MD4Init (MD4_CTX *);
|
||||
void MD4Update (MD4_CTX *, unsigned char *, unsigned int);
|
||||
void MD4Update (MD4_CTX *, const unsigned char *, size_t);
|
||||
void MD4Final (unsigned char [16], MD4_CTX *);
|
||||
|
||||
|
||||
|
@ -84,9 +84,9 @@ These notices must be retained in any copies of any part of this documentation a
|
|||
#define S33 11
|
||||
#define S34 15
|
||||
|
||||
static void MD4Transform (UINT4 [4], unsigned char [64]);
|
||||
static void MD4Transform (UINT4 [4], const unsigned char [64]);
|
||||
static void Encode (unsigned char *, UINT4 *, unsigned int);
|
||||
static void Decode (UINT4 *, unsigned char *, unsigned int);
|
||||
static void Decode (UINT4 *, const unsigned char *, unsigned int);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
|
@ -122,7 +122,7 @@ context->state[3] = 0x10325476;
|
|||
}
|
||||
|
||||
/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
|
||||
void MD4Update (MD4_CTX *context, unsigned char *input, unsigned int inputLen)
|
||||
void MD4Update (MD4_CTX *context, const unsigned char *input, size_t inputLen)
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
|
@ -182,7 +182,7 @@ void MD4Final (unsigned char digest[16], MD4_CTX *context)
|
|||
|
||||
|
||||
/* MD4 basic transformation. Transforms state based on block. */
|
||||
static void MD4Transform (UINT4 state[4], unsigned char block[64])
|
||||
static void MD4Transform (UINT4 state[4], const unsigned char block[64])
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
|
@ -267,7 +267,7 @@ static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
|
|||
|
||||
|
||||
/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
|
||||
static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
|
||||
static void Decode (UINT4 *output, const unsigned char *input, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
|
@ -276,40 +276,13 @@ for (i = 0, j = 0; j < len; i++, j += 4)
|
|||
}
|
||||
|
||||
//===================================================================
|
||||
|
||||
unsigned int Com_BlockChecksum (void *buffer, int length)
|
||||
#include "quakedef.h"
|
||||
hashfunc_t hash_md4 =
|
||||
{
|
||||
unsigned int digest[4];
|
||||
unsigned int val;
|
||||
MD4_CTX ctx;
|
||||
16, //digest size
|
||||
sizeof(MD4_CTX),
|
||||
(void(*)(void*ctx))MD4Init,
|
||||
(void(*)(void*ctx,const void*in,size_t))MD4Update,
|
||||
(void(*)(qbyte*out,void*ctx))MD4Final,
|
||||
};
|
||||
|
||||
MD4Init (&ctx);
|
||||
MD4Update (&ctx, (unsigned char *)buffer, length);
|
||||
MD4Final ( (unsigned char *)digest, &ctx);
|
||||
|
||||
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf)
|
||||
{
|
||||
MD4_CTX ctx;
|
||||
|
||||
MD4Init (&ctx);
|
||||
MD4Update (&ctx, (unsigned char *)buffer, len);
|
||||
MD4Final ( outbuf, &ctx);
|
||||
}
|
||||
|
||||
|
||||
void Com_BlocksChecksum (int blocks, void **buffer, int *len, unsigned char *outbuf)
|
||||
{
|
||||
MD4_CTX ctx;
|
||||
|
||||
MD4Init (&ctx);
|
||||
while(blocks --> 0)
|
||||
{
|
||||
MD4Update (&ctx, (unsigned char *)*buffer++, *len++);
|
||||
}
|
||||
MD4Final (outbuf, &ctx);
|
||||
}
|
||||
|
|
|
@ -256,6 +256,21 @@ typedef struct sctp_s
|
|||
unsigned short qstreamid; //in network endian.
|
||||
} sctp_t;
|
||||
#ifdef HAVE_DTLS
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *name;
|
||||
hashfunc_t *hash;
|
||||
} webrtc_hashes[] =
|
||||
{ //RFC8211 specifies this list of hashes
|
||||
// {"md2", &hash_md2}, //deprecated, hopefully we won't see it
|
||||
// {"md5", &hash_md5}, //deprecated, hopefully we won't see it
|
||||
{"sha-1", &hash_sha1},
|
||||
{"sha-224", &hash_sha2_224},
|
||||
{"sha-256", &hash_sha2_256},
|
||||
{"sha-384", &hash_sha2_384},
|
||||
{"sha-512", &hash_sha2_512},
|
||||
};
|
||||
extern cvar_t net_enable_dtls;
|
||||
static neterr_t SCTP_Transmit(sctp_t *sctp, struct icestate_s *peer, const void *data, size_t length);
|
||||
#endif
|
||||
|
@ -1912,26 +1927,24 @@ static void ICE_ParseSDPLine(struct icestate_s *con, const char *value)
|
|||
}
|
||||
else if (!strncmp(value, "a=fingerprint:", 14))
|
||||
{
|
||||
hashfunc_t *hash = NULL;
|
||||
int i;
|
||||
char name[64];
|
||||
value = COM_ParseOut(value+14, name, sizeof(name));
|
||||
if (!strcasecmp(name, "sha-1"))
|
||||
con->cred.peer.hash = &hash_sha1;
|
||||
else if (!strcasecmp(name, "sha-224"))
|
||||
con->cred.peer.hash = &hash_sha224;
|
||||
else if (!strcasecmp(name, "sha-256"))
|
||||
con->cred.peer.hash = &hash_sha256;
|
||||
else if (!strcasecmp(name, "sha-384"))
|
||||
con->cred.peer.hash = &hash_sha384;
|
||||
else if (!strcasecmp(name, "sha-512"))
|
||||
con->cred.peer.hash = &hash_sha512;
|
||||
else
|
||||
con->cred.peer.hash = NULL; //hash not recognised
|
||||
if (con->cred.peer.hash)
|
||||
for (i = 0; i < countof(webrtc_hashes); i++)
|
||||
{
|
||||
if (!strcasecmp(name, webrtc_hashes[i].name))
|
||||
{
|
||||
hash = webrtc_hashes[i].hash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hash && (!con->cred.peer.hash || hash->digestsize>con->cred.peer.hash->digestsize)) //FIXME: digest size is not a good indicator of whether its exploitable or not, but should work for sha1/sha2 options. the sender here is expected to be trustworthy anyway.
|
||||
{
|
||||
int b, o, v;
|
||||
while (*value == ' ')
|
||||
value++;
|
||||
for (b = 0; b < con->cred.peer.hash->digestsize; )
|
||||
for (b = 0; b < hash->digestsize; )
|
||||
{
|
||||
v = *value;
|
||||
if (v >= '0' && v <= '9')
|
||||
|
@ -1958,8 +1971,10 @@ static void ICE_ParseSDPLine(struct icestate_s *con, const char *value)
|
|||
break;
|
||||
value++;
|
||||
}
|
||||
if (b != con->cred.peer.hash->digestsize)
|
||||
con->cred.peer.hash = NULL; //bad!
|
||||
if (b == hash->digestsize)
|
||||
con->cred.peer.hash = hash; //it was the right size, woo.
|
||||
else
|
||||
con->cred.peer.hash = NULL; //bad! (should we 0-pad?)
|
||||
}
|
||||
}
|
||||
else if (!strncmp(value, "a=sctp-port:", 12))
|
||||
|
@ -2471,14 +2486,12 @@ static qboolean QDECL ICE_Get(struct icestate_s *con, const char *prop, char *va
|
|||
{
|
||||
int b;
|
||||
Q_strncatz(value, "a=fingerprint:", valuelen);
|
||||
if (con->cred.peer.hash == &hash_sha1)
|
||||
Q_strncatz(value, "sha-1", valuelen);
|
||||
else if (con->cred.peer.hash == &hash_sha256)
|
||||
Q_strncatz(value, "sha-256", valuelen);
|
||||
else if (con->cred.peer.hash == &hash_sha512)
|
||||
Q_strncatz(value, "sha-512", valuelen);
|
||||
else
|
||||
Q_strncatz(value, "UNKNOWN", valuelen);
|
||||
for (b = 0; b < countof(webrtc_hashes); b++)
|
||||
{
|
||||
if (con->cred.peer.hash == webrtc_hashes[b].hash)
|
||||
break;
|
||||
}
|
||||
Q_strncatz(value, (b==countof(webrtc_hashes))?"UNKNOWN":webrtc_hashes[b].name, valuelen);
|
||||
for (b = 0; b < con->cred.peer.hash->digestsize; b++)
|
||||
Q_strncatz(value, va(b?":%02X":" %02X", con->cred.peer.digest[b]), valuelen);
|
||||
Q_strncatz(value, "\n", valuelen);
|
||||
|
@ -2533,16 +2546,17 @@ static qboolean QDECL ICE_Get(struct icestate_s *con, const char *prop, char *va
|
|||
{ //this is a preliminary check to avoid wasting time
|
||||
if (!con->cred.local.certsize)
|
||||
return false; //fail if we cannot do dtls when its required.
|
||||
if (!strcmp(prop, "sdpanswer") || !con->cred.peer.hash)
|
||||
if (!strcmp(prop, "sdpanswer") && !con->cred.peer.hash)
|
||||
return false; //don't answer if they failed to provide a cert
|
||||
}
|
||||
if (con->cred.local.certsize)
|
||||
{
|
||||
qbyte fingerprint[DIGEST_MAXSIZE];
|
||||
int b;
|
||||
CalcHash(&hash_sha256, fingerprint, sizeof(fingerprint), con->cred.local.cert, con->cred.local.certsize);
|
||||
hashfunc_t *hash = &hash_sha2_256; //browsers use sha-256, lets match them.
|
||||
CalcHash(hash, fingerprint, sizeof(fingerprint), con->cred.local.cert, con->cred.local.certsize);
|
||||
Q_strncatz(value, "a=fingerprint:sha-256", valuelen);
|
||||
for (b = 0; b < hash_sha256.digestsize; b++)
|
||||
for (b = 0; b < hash->digestsize; b++)
|
||||
Q_strncatz(value, va(b?":%02X":" %02X", fingerprint[b]), valuelen);
|
||||
Q_strncatz(value, "\n", valuelen);
|
||||
|
||||
|
|
|
@ -1191,6 +1191,11 @@ void QDECL Plug_FS_EnumerateFiles(enum fs_relative fsroot, const char *match, in
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int Plug_BlockChecksum(const void *data, size_t datasize)
|
||||
{ //convienience function. we use md4 for legacy reasons (every qw engine must have an implementation)
|
||||
return CalcHashInt(&hash_md4, data, datasize);
|
||||
}
|
||||
|
||||
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
|
||||
static qboolean QDECL Plug_MapLog_Query(const char *packagename, const char *mapname, float *vals)
|
||||
{
|
||||
|
@ -1930,7 +1935,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
|
|||
COM_GetFileExtension,
|
||||
COM_FileBase,
|
||||
COM_CleanUpPath,
|
||||
Com_BlockChecksum,
|
||||
Plug_BlockChecksum,
|
||||
FS_LoadMallocFile,
|
||||
|
||||
FS_GetPackHashes,
|
||||
|
|
|
@ -5665,21 +5665,18 @@ static void QCBUILTIN PF_digest_internal (pubprogfuncs_t *prinst, struct globalv
|
|||
unsigned char hexdig[sizeof(digest)*2+1];
|
||||
|
||||
if (!strcmp(hashtype, "MD4"))
|
||||
{
|
||||
digestsize = 16;
|
||||
Com_BlockFullChecksum(str, len, digest);
|
||||
}
|
||||
digestsize = CalcHash(&hash_md4, digest, sizeof(digest), str, len);
|
||||
//md5?
|
||||
else if (!strcmp(hashtype, "SHA1"))
|
||||
digestsize = CalcHash(&hash_sha1, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA224"))
|
||||
digestsize = CalcHash(&hash_sha224, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA256"))
|
||||
digestsize = CalcHash(&hash_sha256, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA384"))
|
||||
digestsize = CalcHash(&hash_sha384, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA512"))
|
||||
digestsize = CalcHash(&hash_sha512, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA2-224") || !strcmp(hashtype, "SHA224"))
|
||||
digestsize = CalcHash(&hash_sha2_224, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA2-256") || !strcmp(hashtype, "SHA256"))
|
||||
digestsize = CalcHash(&hash_sha2_256, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA2-384") || !strcmp(hashtype, "SHA384"))
|
||||
digestsize = CalcHash(&hash_sha2_384, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "SHA2-512") || !strcmp(hashtype, "SHA512"))
|
||||
digestsize = CalcHash(&hash_sha2_512, digest, sizeof(digest), str, len);
|
||||
else if (!strcmp(hashtype, "CRC16"))
|
||||
digestsize = CalcHash(&hash_crc16, digest, sizeof(digest), str, len);
|
||||
else
|
||||
|
|
|
@ -194,7 +194,7 @@ unsigned int hashfunc_terminate_uint(const hashfunc_t *func, void *context)
|
|||
r ^= digest[l]<<((l%sizeof(r))*8);
|
||||
return r;
|
||||
}
|
||||
unsigned int CalcHashInt(const hashfunc_t *func, const unsigned char *data, size_t datasize)
|
||||
unsigned int CalcHashInt(const hashfunc_t *func, const void *data, size_t datasize)
|
||||
{
|
||||
void *ctx = alloca(func->contextsize);
|
||||
func->init(ctx);
|
||||
|
|
|
@ -515,7 +515,7 @@ static void sha256_finish (qbyte *digest, void *context)
|
|||
memcpy(digest, hd->buf, 256/8);
|
||||
}
|
||||
|
||||
hashfunc_t hash_sha224 =
|
||||
hashfunc_t hash_sha2_224 =
|
||||
{
|
||||
224/8,
|
||||
sizeof(SHA2_CONTEXT),
|
||||
|
@ -523,7 +523,7 @@ hashfunc_t hash_sha224 =
|
|||
sha2_write,
|
||||
sha224_finish
|
||||
};
|
||||
hashfunc_t hash_sha256 =
|
||||
hashfunc_t hash_sha2_256 =
|
||||
{
|
||||
256/8,
|
||||
sizeof(SHA2_CONTEXT),
|
||||
|
@ -547,7 +547,7 @@ static void sha512_finish (qbyte *digest, void *context)
|
|||
memcpy(digest, hd->buf, 512/8);
|
||||
}
|
||||
|
||||
hashfunc_t hash_sha384 =
|
||||
hashfunc_t hash_sha2_384 =
|
||||
{
|
||||
384/8,
|
||||
sizeof(SHA2_CONTEXT),
|
||||
|
@ -555,7 +555,7 @@ hashfunc_t hash_sha384 =
|
|||
sha2_write,
|
||||
sha384_finish
|
||||
};
|
||||
hashfunc_t hash_sha512 =
|
||||
hashfunc_t hash_sha2_512 =
|
||||
{
|
||||
512/8,
|
||||
sizeof(SHA2_CONTEXT),
|
||||
|
|
|
@ -1461,7 +1461,7 @@ static const char *Mod_RemapBuggyTexture(const char *name, const qbyte *data, un
|
|||
{
|
||||
if (!strcmp(name, buggytextures[i].oldname))
|
||||
{
|
||||
unsigned int sum = Com_BlockChecksum(data, datalen);
|
||||
unsigned int sum = CalcHashInt(&hash_md4, data, datalen);
|
||||
for (; i < sizeof(buggytextures)/sizeof(buggytextures[0]); i++)
|
||||
{
|
||||
if (strcmp(name, buggytextures[i].oldname))
|
||||
|
@ -5413,7 +5413,7 @@ static qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsi
|
|||
}
|
||||
if (i == LUMP_ENTITIES)
|
||||
continue;
|
||||
chksum = Com_BlockChecksum(mod_base + header.lumps[i].fileofs, header.lumps[i].filelen);
|
||||
chksum = CalcHashInt(&hash_md4, mod_base + header.lumps[i].fileofs, header.lumps[i].filelen);
|
||||
mod->checksum ^= chksum;
|
||||
|
||||
if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
|
||||
|
|
|
@ -8924,7 +8924,7 @@ void QCBUILTIN PF_sj_strhash (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
|
|||
{ //not quite the same, but oh well
|
||||
const char *str = PF_VarString(prinst, 0, pr_globals);
|
||||
int len = strlen(str);
|
||||
G_FLOAT(OFS_RETURN) = Com_BlockChecksum(str, len);
|
||||
G_FLOAT(OFS_RETURN) = CalcHashInt(&hash_md4, str, len);
|
||||
}
|
||||
#endif
|
||||
static void QCBUILTIN PF_StopSound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
|
|
|
@ -1154,7 +1154,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
|||
if (file)
|
||||
{
|
||||
char text[64];
|
||||
sv.csqcchecksum = Com_BlockChecksum(file, fsz);
|
||||
sv.csqcchecksum = CalcHashInt(&hash_md4, file, fsz);
|
||||
sprintf(text, "0x%x", sv.csqcchecksum);
|
||||
InfoBuf_SetValueForStarKey(&svs.info, "*csprogs", text);
|
||||
sprintf(text, "0x%x", (unsigned int)fsz);
|
||||
|
|
|
@ -266,19 +266,23 @@ int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *heade
|
|||
int raw = 0;
|
||||
char password[256] = "";
|
||||
char userinfo[1024];
|
||||
enum {
|
||||
//MUST BE ORDERED HIGHEST-PRIORITY-LAST
|
||||
QTVAM_NONE,
|
||||
QTVAM_PLAIN,
|
||||
#ifdef TCPCONNECT
|
||||
// QTVAM_CCITT, //16bit = ddos it
|
||||
QTVAM_MD4, //fucked. required for eztv compat
|
||||
// QTVAM_MD5, //fucked, no hash implemented
|
||||
QTVAM_SHA1, //fucked too nowadays
|
||||
QTVAM_SHA2_256, //
|
||||
QTVAM_SHA2_512, //
|
||||
#endif
|
||||
} authmethod = QTVAM_NONE;
|
||||
static struct
|
||||
{
|
||||
const char *name; //as seen in protocol
|
||||
hashfunc_t *func;
|
||||
int base;
|
||||
} hashes[] = {
|
||||
{"NONE", NULL, -1}, //for annonymous connections
|
||||
{"PLAIN", NULL, 0},
|
||||
// {"CCITT", &hash_crc16, 16}, //'the CCITT standard CRC used by XMODEM'. 16bit anyway, don't allow, too easy to guess.
|
||||
// {"MD4", &hash_md4, 15}, //md4 is available to all QW clients, but probably too weak to really use.
|
||||
// {"MD5", &hash_md5, 16}, //blurgh
|
||||
{"SHA1", &hash_sha1, 16},
|
||||
{"SHA2_256", &hash_sha2_256, 64},
|
||||
{"SHA2_512", &hash_sha2_512, 64},
|
||||
// {"SHA3_512", &hash_sha3_512, 16}, //eztv apparently allows this
|
||||
};
|
||||
int authmethod = 0; //which of the above we're trying to use...
|
||||
|
||||
start = headerstart;
|
||||
|
||||
|
@ -347,32 +351,20 @@ int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *heade
|
|||
{
|
||||
int thisauth;
|
||||
start = COM_ParseToken(start, NULL);
|
||||
if (!strcmp(com_token, "NONE"))
|
||||
thisauth = QTVAM_NONE;
|
||||
else if (!strcmp(com_token, "PLAIN"))
|
||||
thisauth = QTVAM_PLAIN;
|
||||
#ifdef TCPCONNECT
|
||||
// else if (!strcmp(com_token, "CCIT"))
|
||||
// thisauth = QTVAM_CCITT;
|
||||
else if (!strcmp(com_token, "MD4"))
|
||||
thisauth = QTVAM_MD4;
|
||||
// else if (!strcmp(com_token, "MD5"))
|
||||
// thisauth = QTVAM_MD5;
|
||||
else if (!strcmp(com_token, "SHA1"))
|
||||
thisauth = QTVAM_SHA1;
|
||||
else if (!strcmp(com_token, "SHA2_256"))
|
||||
thisauth = QTVAM_SHA2_256;
|
||||
else if (!strcmp(com_token, "SHA2_512"))
|
||||
thisauth = QTVAM_SHA2_512;
|
||||
#endif
|
||||
else
|
||||
for (thisauth = 1; ; thisauth++)
|
||||
{
|
||||
thisauth = QTVAM_NONE;
|
||||
Con_DPrintf("qtv: received unrecognised auth method (%s)\n", com_token);
|
||||
if (thisauth == countof(hashes))
|
||||
{
|
||||
Con_DPrintf("qtv: received unrecognised auth method (%s)\n", com_token);
|
||||
break;
|
||||
}
|
||||
if (!strcmp(com_token, hashes[thisauth].name))
|
||||
{ //we know this one.
|
||||
if (authmethod < thisauth)
|
||||
authmethod = thisauth; //and its better than the previous one we saw
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (authmethod < thisauth)
|
||||
authmethod = thisauth;
|
||||
}
|
||||
else if (!strcmp(com_token, "SOURCE"))
|
||||
{
|
||||
|
@ -416,77 +408,38 @@ int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *heade
|
|||
p->hasauthed = true; //no password, no need to auth.
|
||||
else if (*password)
|
||||
{
|
||||
hashfunc_t *func = NULL;
|
||||
if (!*p->challenge && authmethod>QTVAM_PLAIN)
|
||||
char hash[512];
|
||||
qbyte digest[DIGEST_MAXSIZE];
|
||||
if (!*p->challenge && hashes[authmethod].func)
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: Challenge wasn't given...\n\n");
|
||||
else switch (authmethod)
|
||||
switch(hashes[authmethod].base)
|
||||
{
|
||||
case QTVAM_NONE:
|
||||
default:
|
||||
case -1: //no auth at all
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: You need to provide a password.\n\n");
|
||||
break;
|
||||
case QTVAM_PLAIN:
|
||||
p->hasauthed = !strcmp(qtv_password.string, password);
|
||||
case 0: //plain text. challenge is not used.
|
||||
Q_snprintfz(hash, sizeof(hash), "%s", qtv_password.string);
|
||||
break;
|
||||
#ifdef TCPCONNECT
|
||||
/*case QTVAM_CCITT:
|
||||
{
|
||||
unsigned short ushort_result;
|
||||
QCRC_Init(&ushort_result);
|
||||
QCRC_AddBlock(&ushort_result, p->challenge, strlen(p->challenge));
|
||||
QCRC_AddBlock(&ushort_result, qtv_password.string, strlen(qtv_password.string));
|
||||
p->hasauthed = (ushort_result == strtoul(password, NULL, 0));
|
||||
}
|
||||
break;*/
|
||||
case QTVAM_MD4:
|
||||
{
|
||||
char hash[512];
|
||||
int md4sum[4];
|
||||
|
||||
Q_snprintfz(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string);
|
||||
Com_BlockFullChecksum (hash, strlen(hash), (unsigned char*)md4sum);
|
||||
Q_snprintfz(hash, sizeof(hash), "%X%X%X%X", md4sum[0], md4sum[1], md4sum[2], md4sum[3]);
|
||||
p->hasauthed = !strcmp(password, hash);
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_LEGACY //to be disabled at some point.
|
||||
case QTVAM_SHA1:
|
||||
{
|
||||
char hash[512];
|
||||
int digest[5];
|
||||
|
||||
Q_snprintfz(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string);
|
||||
CalcHash(&hash_sha1, (char*)digest, sizeof(digest), hash, strlen(hash));
|
||||
Q_snprintfz(hash, sizeof(hash), "%08X%08X%08X%08X%08X", digest[0], digest[1], digest[2], digest[3], digest[4]);
|
||||
p->hasauthed = !strcmp(password, hash);
|
||||
|
||||
if (!p->hasauthed)
|
||||
func = &hash_sha1;
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case QTVAM_SHA1: func = &hash_sha1; break;
|
||||
#endif
|
||||
case QTVAM_SHA2_256: func = &hash_sha256; break;
|
||||
case QTVAM_SHA2_512: func = &hash_sha512; break;
|
||||
// case QTVAM_MD5: func = &hash_md5; break;
|
||||
#endif
|
||||
default:
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: server bug detected.\n\n");
|
||||
break;
|
||||
}
|
||||
if (func)
|
||||
{
|
||||
char hash[DIGEST_MAXSIZE*2+1];
|
||||
qbyte digest[DIGEST_MAXSIZE];
|
||||
|
||||
case 15: //fucked encoding(missing some leading 0s)
|
||||
Q_snprintfz(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string);
|
||||
CalcHash(func, digest, sizeof(digest), hash, strlen(hash));
|
||||
Base64_EncodeBlock(digest, func->digestsize, hash, sizeof(hash));
|
||||
p->hasauthed = !strcmp(password, hash);
|
||||
CalcHash(hashes[authmethod].func, digest, sizeof(digest), hash, strlen(hash));
|
||||
Q_snprintfz(hash, sizeof(hash), "%X%X%X%X", ((quint32_t*)digest)[0], ((quint32_t*)digest)[1], ((quint32_t*)digest)[2], ((quint32_t*)digest)[3]);
|
||||
break;
|
||||
case 16:
|
||||
Q_snprintfz(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string);
|
||||
CalcHash(hashes[authmethod].func, digest, sizeof(digest), hash, strlen(hash));
|
||||
Base16_EncodeBlock(digest, hashes[authmethod].func->digestsize, hash, sizeof(hash));
|
||||
break;
|
||||
case 64:
|
||||
Q_snprintfz(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string);
|
||||
CalcHash(hashes[authmethod].func, digest, sizeof(digest), hash, strlen(hash));
|
||||
Base64_EncodeBlock(digest, hashes[authmethod].func->digestsize, hash, sizeof(hash));
|
||||
break;
|
||||
}
|
||||
p->hasauthed = !strcmp(password, hash);
|
||||
if (!p->hasauthed && !e)
|
||||
{
|
||||
if (raw)
|
||||
|
@ -499,66 +452,31 @@ int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *heade
|
|||
else
|
||||
{
|
||||
//no password, and not automagically authed
|
||||
switch (authmethod)
|
||||
switch (hashes[authmethod].base)
|
||||
{
|
||||
case QTVAM_NONE:
|
||||
case -1:
|
||||
if (raw)
|
||||
e = "";
|
||||
else
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: You need to provide a common auth method.\n\n");
|
||||
break;
|
||||
case QTVAM_PLAIN:
|
||||
case 0:
|
||||
p->hasauthed = !strcmp(qtv_password.string, password);
|
||||
break;
|
||||
#ifdef TCPCONNECT
|
||||
/*case QTVAM_CCITT:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: CCITT\n"
|
||||
"CHALLENGE: ");
|
||||
goto hashedpassword;*/
|
||||
case QTVAM_MD4:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: MD4\n"
|
||||
"CHALLENGE: ");
|
||||
goto hashedpassword;
|
||||
/*case QTVAM_MD5:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: MD5\n"
|
||||
"CHALLENGE: ");
|
||||
goto hashedpassword;*/
|
||||
case QTVAM_SHA1:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: SHA1\n"
|
||||
"CHALLENGE: ");
|
||||
goto hashedpassword;
|
||||
case QTVAM_SHA2_256:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: SHA2_256\n"
|
||||
"CHALLENGE: ");
|
||||
goto hashedpassword;
|
||||
case QTVAM_SHA2_512:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: SHA2_512\n"
|
||||
"CHALLENGE: ");
|
||||
goto hashedpassword;
|
||||
hashedpassword:
|
||||
default:
|
||||
{
|
||||
char tmp[32];
|
||||
Sys_RandomBytes(tmp, sizeof(tmp));
|
||||
tobase64(p->challenge, sizeof(p->challenge), tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
VFS_WRITE(clientstream, e, strlen(e));
|
||||
VFS_WRITE(clientstream, p->challenge, strlen(p->challenge));
|
||||
e = "\n\n";
|
||||
e = va("QTVSV 1\n"
|
||||
"AUTH: %s\n"
|
||||
"CHALLENGE: %s\n\n",
|
||||
hashes[authmethod].name, p->challenge);
|
||||
VFS_WRITE(clientstream, e, strlen(e));
|
||||
return QTV_RETRY;
|
||||
#endif
|
||||
default:
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: server bug detected.\n\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -248,10 +248,10 @@ typedef struct
|
|||
void (*terminate) (unsigned char *digest, void *context);
|
||||
} hashfunc_t;
|
||||
extern hashfunc_t hash_sha1;
|
||||
/*extern hashfunc_t hash_sha224;
|
||||
extern hashfunc_t hash_sha256;
|
||||
extern hashfunc_t hash_sha384;
|
||||
extern hashfunc_t hash_sha512;*/
|
||||
/*extern hashfunc_t hash_sha2_224;
|
||||
extern hashfunc_t hash_sha2_256;
|
||||
extern hashfunc_t hash_sha2_384;
|
||||
extern hashfunc_t hash_sha2_512;*/
|
||||
#define HMAC HMAC_quake //stop conflicts...
|
||||
size_t CalcHash(hashfunc_t *hash, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen);
|
||||
size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datalen, const unsigned char *key, size_t keylen);
|
||||
|
|
|
@ -465,7 +465,7 @@ void Net_SendQTVConnectionRequest(sv_t *qtv, char *authmethod, char *challenge)
|
|||
|
||||
snprintf(hash, sizeof(hash), "%s%s", challenge, qtv->connectpassword);
|
||||
Com_BlockFullChecksum (hash, strlen(hash), (unsigned char*)md4sum);
|
||||
sprintf(hash, "%X%X%X%X", md4sum[0], md4sum[1], md4sum[2], md4sum[3]);
|
||||
sprintf(hash, "%X%X%X%X", md4sum[0], md4sum[1], md4sum[2], md4sum[3]); //FIXME: bad formatting!
|
||||
|
||||
str = hash; Net_QueueUpstream(qtv, strlen(str), str);
|
||||
str = "\"\n"; Net_QueueUpstream(qtv, strlen(str), str);
|
||||
|
|
|
@ -1238,11 +1238,11 @@ static int sasl_scramsha1minus_initial(struct sasl_ctx_s *ctx, char *buf, int bu
|
|||
}
|
||||
static int sasl_scramsha256minus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize)
|
||||
{
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha256, false);
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha2_256, false);
|
||||
}
|
||||
static int sasl_scramsha512minus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize)
|
||||
{
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha512, false);
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha2_512, false);
|
||||
}
|
||||
static int sasl_scramsha1plus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize)
|
||||
{
|
||||
|
@ -1250,11 +1250,11 @@ static int sasl_scramsha1plus_initial(struct sasl_ctx_s *ctx, char *buf, int buf
|
|||
}
|
||||
static int sasl_scramsha256plus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize)
|
||||
{
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha256, true);
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha2_256, true);
|
||||
}
|
||||
static int sasl_scramsha512plus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize)
|
||||
{
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha512, true);
|
||||
return sasl_scram_initial(ctx, buf, bufsize, &hash_sha2_512, true);
|
||||
}
|
||||
|
||||
static void buf_cat(buf_t *buf, char *data, int len)
|
||||
|
|
|
@ -547,7 +547,7 @@ typedef struct //for plugins that need to read/write files...
|
|||
F(const char *,GetExtension,(const char *filename, const char *ignoreext));
|
||||
F(void, FileBase, (const char *in, char *out, int outlen));
|
||||
F(void, CleanUpPath, (char *str));
|
||||
F(unsigned int,BlockChecksum,(const void *buffer, int length)); //mostly for pack hashes.
|
||||
F(unsigned int,BlockChecksum,(const void *buffer, size_t length)); //mostly for pack hashes.
|
||||
F(void*, LoadFile, (const char *fname, size_t *fsize)); //plugfuncs->Free
|
||||
|
||||
//stuff that's useful for networking.
|
||||
|
|
Loading…
Reference in a new issue