NQ: Try to improve compat with proxies/port-forwarding and proquake's numeric-only passwords.
This commit is contained in:
parent
bb9f7eb51a
commit
11a5b27689
4 changed files with 79 additions and 24 deletions
|
@ -1347,6 +1347,8 @@ void CL_CheckForResend (void)
|
|||
#ifdef NQPROT
|
||||
if ((contype & 2) && !connectinfo.clogged)
|
||||
{
|
||||
char *e;
|
||||
int pwd;
|
||||
sizebuf_t sb;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
sb.data = data;
|
||||
|
@ -1366,11 +1368,18 @@ void CL_CheckForResend (void)
|
|||
which means it corrects for our public port if our nat uses different public ports for different remote ports
|
||||
thus all nq engines claim to be proquake
|
||||
*/
|
||||
|
||||
if (!*password.string || !strcmp(password.string, "none"))
|
||||
pwd = 0;
|
||||
else
|
||||
{
|
||||
pwd = strtol(password.string, &e, 0);
|
||||
if (*e)
|
||||
pwd = CalcHashInt(&hash_md4, password.string, strlen(password.string));
|
||||
}
|
||||
MSG_WriteByte(&sb, 1); /*'mod'*/
|
||||
MSG_WriteByte(&sb, 34); /*'mod' version*/
|
||||
MSG_WriteByte(&sb, 0); /*flags*/
|
||||
MSG_WriteLong(&sb, strtoul(password.string, NULL, 0)); /*password*/
|
||||
MSG_WriteLong(&sb, pwd); /*password*/
|
||||
|
||||
/*FTE servers will detect this string and treat it as a qw challenge instead (if it allows qw clients), so protocol choice is deterministic*/
|
||||
if (contype & 1)
|
||||
|
@ -4370,31 +4379,36 @@ void CLNQ_ConnectionlessPacket(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
port = htons((unsigned short)MSG_ReadLong());
|
||||
//this is the port that we're meant to respond to.
|
||||
port = htons((unsigned short)MSG_ReadLong()); //this is the port that we're meant to respond to...
|
||||
if (msg_badread) //qe has no port specified. and that's fine when its over dtls anyway.
|
||||
port = 0;
|
||||
|
||||
if (port && !msg_badread)
|
||||
{
|
||||
char buf[256];
|
||||
net_from.port = port;
|
||||
Con_DPrintf("redirecting to port %s\n", NET_AdrToString(buf, sizeof(buf), &net_from));
|
||||
}
|
||||
|
||||
cls.proquake_angles_hack = false;
|
||||
cls.protocol_nq = CPNQ_ID;
|
||||
if (MSG_ReadByte() == 1) //a proquake server adds a little extra info
|
||||
{
|
||||
int ver = MSG_ReadByte();
|
||||
int flags = MSG_ReadByte();
|
||||
Con_DPrintf("ProQuake server %i.%i\n", ver/10, ver%10);
|
||||
|
||||
// if (ver >= 34)
|
||||
cls.proquake_angles_hack = true;
|
||||
if (MSG_ReadByte() == 1)
|
||||
if (flags & 1)
|
||||
{
|
||||
//its a 'pure' server.
|
||||
Con_Printf("pure ProQuake server\n");
|
||||
return;
|
||||
}
|
||||
if (flags & 0x80)
|
||||
port = 0; //don't force the port.
|
||||
}
|
||||
|
||||
if (port && port != net_from.port)
|
||||
{
|
||||
char buf[256];
|
||||
net_from.port = port;
|
||||
Con_Printf("redirecting to port %s\n", NET_AdrToString(buf, sizeof(buf), &net_from));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1129,6 +1129,7 @@ const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned
|
|||
char *SV_BannedReason (netadr_t *a);
|
||||
void SV_EvaluatePenalties(client_t *cl);
|
||||
void SV_AutoAddPenalty (client_t *cl, unsigned int banflag, int duration, char *reason);
|
||||
void SV_AutoBanSender (int duration, char *reason); //bans net_from
|
||||
|
||||
//note: not all penalties are actually penalties, but they can still expire.
|
||||
#define BAN_BAN (1u<<0) //user is banned from the server
|
||||
|
|
|
@ -1916,6 +1916,19 @@ void SV_AutoAddPenalty (client_t *cl, unsigned int banflag, int duration, char *
|
|||
SV_AddBanEntry(&proto, reason);
|
||||
SV_EvaluatePenalties(cl);
|
||||
}
|
||||
void SV_AutoBanSender (int duration, char *reason)
|
||||
{
|
||||
bannedips_t proto;
|
||||
|
||||
proto.banflags = BAN_BAN;
|
||||
proto.expiretime = SV_BanTime() + duration;
|
||||
memset(&proto.adrmask.address, 0xff, sizeof(proto.adrmask.address));
|
||||
proto.adr = net_from;
|
||||
proto.adr.port = 0;
|
||||
proto.adrmask.type = proto.adr.type;
|
||||
|
||||
SV_AddBanEntry(&proto, reason);
|
||||
}
|
||||
|
||||
static void SV_WriteIP_f (void)
|
||||
{
|
||||
|
|
|
@ -2668,15 +2668,33 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info)
|
|||
}
|
||||
else
|
||||
{
|
||||
s = Info_ValueForKey (info->userinfo, "password");
|
||||
if (password.string[0] &&
|
||||
stricmp(password.string, "none") &&
|
||||
strcmp(password.string, s) &&
|
||||
!NET_IsLoopBackAddress(&info->adr))
|
||||
if (!password.string[0] ||
|
||||
!stricmp(password.string, "none") ||
|
||||
NET_IsLoopBackAddress(&info->adr))
|
||||
; //don't care, doesn't matter.
|
||||
else if (info->protocol == SCP_NETQUAKE)
|
||||
{ //if its a proquake client then use numeric passwords, which take a bit of processing
|
||||
char *e;
|
||||
int got = strtol(Info_ValueForKey (info->userinfo, "password"), NULL, 0);
|
||||
int need = strtol(password.string, &e, 0);
|
||||
if (*e)
|
||||
need = CalcHashInt(&hash_md4, password.string, strlen(password.string));
|
||||
if (got != need)
|
||||
{
|
||||
Con_TPrintf ("%s:password failed\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr));
|
||||
SV_RejectMessage (info->protocol, "server requires a password\n\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_TPrintf ("%s:password failed\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr));
|
||||
SV_RejectMessage (info->protocol, "server requires a password\n\n");
|
||||
return;
|
||||
s = Info_ValueForKey (info->userinfo, "password");
|
||||
if (strcmp(password.string, s))
|
||||
{
|
||||
Con_TPrintf ("%s:password failed\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr));
|
||||
SV_RejectMessage (info->protocol, "server requires a password\n\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
spectator = false;
|
||||
Info_RemoveKey (info->userinfo, "password"); // remove passwd
|
||||
|
@ -4594,12 +4612,21 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
)
|
||||
{
|
||||
if (password.string[0] &&
|
||||
stricmp(password.string, "none") &&
|
||||
strcmp(password.string, va("%i", passwd)) )
|
||||
stricmp(password.string, "none"))
|
||||
{ //make sure we don't get crippled because of being unable to specify the actual password with proquake's stuff.
|
||||
Con_TPrintf ("%s:password failed (nq)\n", NET_AdrToString (buffer2, sizeof(buffer2), &net_from));
|
||||
SV_RejectMessage (SCP_NETQUAKE, "server requires a password\n\n");
|
||||
return true;
|
||||
char *e;
|
||||
intmax_t svpass = strtoll(password.string, &e, 0);
|
||||
if (*e) //something ain't numeric... hash it so they have a chance of getting it right...
|
||||
svpass = CalcHashInt(&hash_md4, password.string, strlen(password.string));
|
||||
if (passwd != svpass)
|
||||
{
|
||||
Con_TPrintf ("%s:password failed (nq)\n", NET_AdrToString (buffer2, sizeof(buffer2), &net_from));
|
||||
SV_RejectMessage (SCP_NETQUAKE, "\x01this server requires a password\n\n");
|
||||
|
||||
//and prevent them from spamming attempts. botnets might still get through fast though.
|
||||
SV_AutoBanSender(15, "password cooldown");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
SZ_Clear(&sb);
|
||||
|
|
Loading…
Reference in a new issue