added server support for proquake rcon when running quake protocol
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 18 Nov 2010 01:44:07 +0000 (01:44 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 18 Nov 2010 01:44:07 +0000 (01:44 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10603 d7cf8633-e32d-0410-b094-e92efae38249

console.c
console.h
netconn.c

index 7c0499a..4421def 100644 (file)
--- a/console.c
+++ b/console.c
@@ -93,6 +93,7 @@ lhnetsocket_t *rcon_redirect_sock = NULL;
 lhnetaddress_t *rcon_redirect_dest = NULL;
 int rcon_redirect_bufferpos = 0;
 char rcon_redirect_buffer[1400];
+qboolean rcon_redirect_proquakeprotocol = false;
 
 // generic functions for console buffers
 
@@ -885,20 +886,38 @@ static char qfont_table[256] = {
        'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<'
 };
 
-void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest)
+void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest, qboolean proquakeprotocol)
 {
        rcon_redirect_sock = sock;
        rcon_redirect_dest = dest;
-       memcpy(rcon_redirect_buffer, "\377\377\377\377n", 5); // QW rcon print
+       rcon_redirect_proquakeprotocol = proquakeprotocol;
+       if (rcon_redirect_proquakeprotocol)
+       {
+               // reserve space for the packet header
+               rcon_redirect_buffer[0] = 0;
+               rcon_redirect_buffer[1] = 0;
+               rcon_redirect_buffer[2] = 0;
+               rcon_redirect_buffer[3] = 0;
+               // this is a reply to a CCREQ_RCON
+               rcon_redirect_buffer[4] = CCREP_RCON;
+       }
+       else
+               memcpy(rcon_redirect_buffer, "\377\377\377\377n", 5); // QW rcon print
        rcon_redirect_bufferpos = 5;
 }
 
 void Con_Rcon_Redirect_Flush(void)
 {
        rcon_redirect_buffer[rcon_redirect_bufferpos] = 0;
+       if (rcon_redirect_proquakeprotocol)
+       {
+               // update the length in the packet header
+               StoreBigLong((unsigned char *)rcon_redirect_buffer, NETFLAG_CTL | (rcon_redirect_bufferpos & NETFLAG_LENGTH_MASK));
+       }
        NetConn_WriteString(rcon_redirect_sock, rcon_redirect_buffer, rcon_redirect_dest);
        memcpy(rcon_redirect_buffer, "\377\377\377\377n", 5); // QW rcon print
        rcon_redirect_bufferpos = 5;
+       rcon_redirect_proquakeprotocol = false;
 }
 
 void Con_Rcon_Redirect_End(void)
index f86ae15..8b2d768 100644 (file)
--- a/console.h
+++ b/console.h
@@ -28,7 +28,7 @@ extern int con_totallines;
 extern int con_backscroll;
 extern qboolean con_initialized;
 
-void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest);
+void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest, qboolean proquakeprotocol);
 void Con_Rcon_Redirect_End(void);
 void Con_Rcon_Redirect_Abort(void);
 
index dde22c2..2c1d03e 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -2636,7 +2636,7 @@ allow:
        return va("%srcon", restricted ? "restricted " : "");
 }
 
-void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const char *addressstring2, const char *userlevel, const char *s, const char *endpos)
+void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const char *addressstring2, const char *userlevel, const char *s, const char *endpos, qboolean proquakeprotocol)
 {
        if(userlevel)
        {
@@ -2653,7 +2653,7 @@ void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const ch
                Con_Printf("\n");
 
                if (!host_client || !host_client->netconnection || LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) != LHNETADDRESSTYPE_LOOP)
-                       Con_Rcon_Redirect_Init(mysocket, peeraddress);
+                       Con_Rcon_Redirect_Init(mysocket, peeraddress, proquakeprotocol);
                while(s != endpos)
                {
                        size_t l = strlen(s);
@@ -2973,7 +2973,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        ++s;
 
                        userlevel = RCon_Authenticate(peeraddress, password, s, endpos, hmac_mdfour_time_matching, timeval, endpos - timeval - 1); // not including the appended \0 into the HMAC
-                       RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos);
+                       RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos, false);
                        return true;
                }
                if (length >= 42 && !memcmp(string, "srcon HMAC-MD4 CHALLENGE ", 25))
@@ -2988,7 +2988,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        ++s;
 
                        userlevel = RCon_Authenticate(peeraddress, password, s, endpos, hmac_mdfour_challenge_matching, challenge, endpos - challenge - 1); // not including the appended \0 into the HMAC
-                       RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos);
+                       RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos, false);
                        return true;
                }
                if (length >= 5 && !memcmp(string, "rcon ", 5))
@@ -3010,7 +3010,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                        if (!ISWHITESPACE(password[0]))
                        {
                                const char *userlevel = RCon_Authenticate(peeraddress, password, s, endpos, plaintext_matching, NULL, 0);
-                               RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos);
+                               RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos, false);
                        }
                        return true;
                }
@@ -3260,6 +3260,25 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                                SZ_Clear(&net_message);
                        }
                        break;
+               case CCREQ_RCON:
+                       if (developer_extra.integer)
+                               Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_RCON from %s.\n", addressstring2);
+                       if (sv.active && !rcon_secure.integer)
+                       {
+                               char password[2048];
+                               char cmd[2048];
+                               char *s;
+                               char *endpos;
+                               const char *userlevel;
+                               strlcpy(password, MSG_ReadString(), sizeof(password));
+                               strlcpy(cmd, MSG_ReadString(), sizeof(cmd));
+                               s = cmd;
+                               endpos = cmd + strlen(cmd) + 1; // one behind the NUL, so adding strlen+1 will eventually reach it
+                               userlevel = RCon_Authenticate(peeraddress, password, s, endpos, plaintext_matching, NULL, 0);
+                               RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos, true);
+                               return true;
+                       }
+                       break;
                default:
                        break;
                }