]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
sorry for this 100% untested change... making srcon use the new challenge-based proto...
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 2 Oct 2009 09:22:33 +0000 (09:22 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 2 Oct 2009 09:22:33 +0000 (09:22 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9279 d7cf8633-e32d-0410-b094-e92efae38249

client.h
host_cmd.c
netconn.c

index f6a8a4d67e3a22a44c7b1964fd8b43b02c24a083..acab743af8b32db34498a07040461a7558e9c5ad 100644 (file)
--- a/client.h
+++ b/client.h
@@ -581,6 +581,12 @@ typedef struct client_static_s
        // (kept outside client_state_t because it's used between levels)
        protocolversion_t protocol;
 
+#define MAX_RCONS 64
+       int rcon_trying;
+       lhnetaddress_t rcon_addresses[MAX_RCONS];
+       char rcon_commands[MAX_RCONS][MAX_INPUTLINE];
+       int rcon_ringpos;
+
 // connection information
        // 0 to SIGNONS
        int signon;
index dc84be9d5411153c8c944ac5d0884f76e6387b90..895bb2d2d586d2fe82c2691646283f5aa3cb1a09 100644 (file)
@@ -33,7 +33,7 @@ cvar_t sv_adminnick = {CVAR_SAVE, "sv_adminnick", "", "nick name to use for admi
 cvar_t sv_status_privacy = {CVAR_SAVE, "sv_status_privacy", "0", "do not show IP addresses in 'status' replies to clients"};
 cvar_t sv_status_show_qcstatus = {CVAR_SAVE, "sv_status_show_qcstatus", "0", "show the 'qcstatus' field in status replies, not the 'frags' field. Turn this on if your mod uses this field, and the 'frags' field on the other hand has no meaningful value."};
 cvar_t rcon_password = {CVAR_PRIVATE, "rcon_password", "", "password to authenticate rcon commands; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
-cvar_t rcon_secure = {CVAR_NQUSERINFOHACK, "rcon_secure", "0", "force secure rcon authentication; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
+cvar_t rcon_secure = {CVAR_NQUSERINFOHACK, "rcon_secure", "0", "force secure rcon authentication (1 = time based, 2 = challenge based); NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
 cvar_t rcon_address = {0, "rcon_address", "", "server address to send rcon commands to (when not connected to a server)"};
 cvar_t team = {CVAR_USERINFO | CVAR_SAVE, "team", "none", "QW team (4 character limit, example: blue)"};
 cvar_t skin = {CVAR_USERINFO | CVAR_SAVE, "skin", "", "QW player skin name (example: base)"};
@@ -2436,10 +2436,19 @@ void Host_Rcon_f (void) // credit: taken from QuakeWorld
                LHNETADDRESS_FromString(&to, rcon_address.string, sv_netport.integer);
        }
        mysocket = NetConn_ChooseClientSocketForAddress(&to);
-       if (mysocket)
+       if (mysocket && Cmd_Args()[0])
        {
                // simply put together the rcon packet and send it
-               if(Cmd_Argv(0)[0] == 's' || rcon_secure.integer)
+               if(Cmd_Argv(0)[0] == 's' || rcon_secure.integer > 1)
+               {
+                       if(!cls.rcon_commands[cls.rcon_ringpos][0])
+                               ++cls.rcon_trying;
+                       strlcpy(cls.rcon_commands[cls.rcon_ringpos], Cmd_Args(), sizeof(cls.rcon_commands[cls.rcon_ringpos]));
+                       cls.rcon_addresses[cls.rcon_ringpos] = to;
+                       cls.rcon_ringpos = (cls.rcon_ringpos) % 64;
+                       NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", &to);
+               }
+               else if(rcon_secure.integer)
                {
                        char buf[1500];
                        char argbuf[1500];
index 80355210aa5eeb8eb499be71f2390ccad9363fa9..1dfb0cc008baa2fab45f1d520fbd7cf991ac0ec5 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -1554,6 +1554,30 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        Com_HexDumpToConsole(data, length);
                }
 
+               if (length > 10 && !memcmp(string, "challenge ", 10) && cls.rcon_trying)
+               {
+                       int i;
+                       for (i = 0;i < MAX_RCONS;i++)
+                               if(cls.rcon_commands[i][0])
+                                       if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i]))
+                                               break;
+                       if (i < MAX_RCONS)
+                       {
+                               char buf[1500];
+                               char argbuf[1500];
+                               dpsnprintf(argbuf, sizeof(argbuf), "%s %s", string + 10, cls.rcon_commands[i]);
+                               memcpy(buf, "\377\377\377\377srcon HMAC-MD4 CHALLENGE ", 29);
+                               if(HMAC_MDFOUR_16BYTES((unsigned char *) (buf + 29), (unsigned char *) argbuf, strlen(argbuf), (unsigned char *) rcon_password.string, strlen(rcon_password.string)))
+                               {
+                                       buf[45] = ' ';
+                                       strlcpy(buf + 46, argbuf, sizeof(buf) - 46);
+                                       NetConn_Write(mysocket, buf, 46 + strlen(buf + 46), peeraddress);
+                                       cls.rcon_commands[i][0] = 0;
+                                       --cls.rcon_trying;
+                                       return true; // we used up the challenge, so we can't use this oen for connecting now anyway
+                               }
+                       }
+               }
                if (length > 10 && !memcmp(string, "challenge ", 10) && cls.connect_trying)
                {
                        // darkplaces or quake3