Rework some hashfunc_t stuff.

This commit is contained in:
Shpoike 2023-02-20 06:13:40 +00:00
parent 1fe478dfa1
commit c5f837d468
26 changed files with 184 additions and 278 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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