[Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues.
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: |
[Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues. |
From: |
"Vasco Alexandre da Silva Costa" <vasc@xxxxxxxxxxxxxx> |
Date: |
Mon, 15 Nov 2004 15:46:32 -0800 |
Reply-to: |
rt@xxxxxxxxxxx |
<URL: http://rt.freeciv.org/Ticket/Display.html?id=10727 >
Like hack-4, but uses challenge_$PORT_$CONNECTION_ID as the filename so
you can run multiple servers with the same user without a problem.
Index: client/connectdlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/connectdlg_common.c,v
retrieving revision 1.26
diff -u -r1.26 connectdlg_common.c
--- client/connectdlg_common.c 24 Oct 2004 23:18:07 -0000 1.26
+++ client/connectdlg_common.c 15 Nov 2004 23:45:25 -0000
@@ -37,7 +37,9 @@
#include <sys/wait.h>
#endif
+#include "capability.h"
#include "fcintl.h"
+#include "log.h"
#include "mem.h"
#include "netintf.h"
#include "rand.h"
@@ -67,6 +69,7 @@
char player_name[MAX_LEN_NAME];
char *current_filename = NULL;
+static char challenge_fullname[MAX_LEN_PATH];
static bool client_has_hack = FALSE;
int internal_server_port;
@@ -369,33 +372,58 @@
#endif
}
+/*************************************************************************
+ generate a random string.
+*************************************************************************/
+static void randomize_string(char *str, size_t n)
+{
+ const char chars[] =
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ for (i = 0; i < n - 1; i++) {
+ str[i] = chars[myrand(sizeof(chars) - 1)];
+ }
+ str[i] = '\0';
+}
+
/****************************************************************
if the client is capable of 'wanting hack', then the server will
send the client a filename in the packet_join_game_reply packet.
-this function creates the file with a suitably random number in it
-and then sends the filename and number to the server. If the server
-can open and read the number, then the client is given hack access.
+this function creates the file with a suitably random string in it
+and then sends the string to the server. If the server can open
+and read the string, then the client is given hack access.
*****************************************************************/
-void send_client_wants_hack(char * filename)
+void send_client_wants_hack(const char *filename)
{
- struct section_file file;
-
- /* find some entropy */
- int entropy = myrand(MAX_UINT32) - time(NULL);
+ if (has_capability("new_hack", aconnection.capability)) {
+ if (filename[0] != '\0') {
+ struct packet_single_want_hack_req req;
+ struct section_file file;
+
+ /* generate an authentication token */
+ randomize_string(req.token, sizeof(req.token));
+
+ /* get the full filename path */
+ interpret_tilde(challenge_fullname, sizeof(challenge_fullname),
+ "~/.freeciv/");
+ make_dir(challenge_fullname);
+
+ sz_strlcat(challenge_fullname, filename);
+
+ section_file_init(&file);
+ secfile_insert_str(&file, req.token, "challenge.token");
+ if (!section_file_save(&file, challenge_fullname, 0)) {
+ freelog(LOG_ERROR, "Couldn't write token to temporary file: %s",
+ challenge_fullname);
+ }
+ section_file_free(&file);
- /* we don't want zero */
- if (entropy == 0) {
- entropy++;
+ /* tell the server what we put into the file */
+ send_packet_single_want_hack_req(&aconnection, &req);
+ }
}
-
- section_file_init(&file);
- secfile_insert_int(&file, entropy, "challenge.entropy");
- section_file_save(&file, filename, 0);
- section_file_free(&file);
-
- /* tell the server what we put into the file */
- dsend_packet_single_want_hack_req(&aconnection, entropy);
}
/****************************************************************
@@ -403,6 +431,17 @@
*****************************************************************/
void handle_single_want_hack_reply(bool you_have_hack)
{
+ if (has_capability("new_hack", aconnection.capability)) {
+ /* remove challenge file */
+ if (challenge_fullname[0] != '\0') {
+ if (remove(challenge_fullname) == -1) {
+ freelog(LOG_ERROR, "Couldn't remove temporary file: %s",
+ challenge_fullname);
+ }
+ challenge_fullname[0] = '\0';
+ }
+ }
+
if (you_have_hack) {
append_output_window(_("We have control of the server "
"(command access level hack)"));
Index: client/connectdlg_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/connectdlg_common.h,v
retrieving revision 1.6
diff -u -r1.6 connectdlg_common.h
--- client/connectdlg_common.h 21 Aug 2004 16:34:03 -0000 1.6
+++ client/connectdlg_common.h 15 Nov 2004 23:45:25 -0000
@@ -25,7 +25,7 @@
bool is_server_running(void);
bool can_client_access_hack(void);
-void send_client_wants_hack(char *filename);
+void send_client_wants_hack(const char *filename);
void send_start_saved_game(void);
void send_save_game(char *filename);
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.194
diff -u -r1.194 capstr.c
--- common/capstr.c 4 Nov 2004 03:02:10 -0000 1.194
+++ common/capstr.c 15 Nov 2004 23:45:25 -0000
@@ -90,7 +90,7 @@
* as long as possible. We want to maintain network compatibility with
* the stable branch for as long as possible.
*/
-#define CAPABILITY "+2.0 connecting conn_ping_info username_info"
+#define CAPABILITY "+2.0 connecting conn_ping_info username_info new_hack"
void init_our_capability(void)
{
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.58
diff -u -r1.58 packets.def
--- common/packets.def 4 Nov 2004 03:02:10 -0000 1.58
+++ common/packets.def 15 Nov 2004 23:45:26 -0000
@@ -1254,8 +1254,9 @@
/*********************************************************
Below are the packets that control single-player mode.
*********************************************************/
-PACKET_SINGLE_WANT_HACK_REQ=108;cs,handle-per-conn,no-handle,dsend
- UINT32 challenge;
+PACKET_SINGLE_WANT_HACK_REQ=108;cs,handle-per-conn,no-handle
+ UINT32 old_token; remove-cap(new_hack)
+ STRING token[MAX_LEN_NAME]; add-cap(new_hack)
end
PACKET_SINGLE_WANT_HACK_REPLY=109;sc,dsend
Index: common/packets_gen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.c,v
retrieving revision 1.60
diff -u -r1.60 packets_gen.c
--- common/packets_gen.c 4 Nov 2004 03:02:10 -0000 1.60
+++ common/packets_gen.c 15 Nov 2004 23:45:31 -0000
@@ -27081,11 +27081,102 @@
}
if (BV_ISSET(fields, 0)) {
+ dio_get_string(&din, real_packet->token, sizeof(real_packet->token));
+ }
+
+ clone = fc_malloc(sizeof(*clone));
+ *clone = *real_packet;
+ if (old) {
+ free(old);
+ }
+ hash_insert(*hash, clone, clone);
+
+ RECEIVE_PACKET_END(real_packet);
+}
+
+static int send_packet_single_want_hack_req_100(struct connection *pc, const
struct packet_single_want_hack_req *packet)
+{
+ const struct packet_single_want_hack_req *real_packet = packet;
+ packet_single_want_hack_req_100_fields fields;
+ struct packet_single_want_hack_req *old, *clone;
+ bool differ, old_from_hash, force_send_of_unchanged = TRUE;
+ struct hash_table **hash = &pc->phs.sent[PACKET_SINGLE_WANT_HACK_REQ];
+ int different = 0;
+ SEND_PACKET_START(PACKET_SINGLE_WANT_HACK_REQ);
+
+ if (!*hash) {
+ *hash = hash_new(hash_packet_single_want_hack_req_100,
cmp_packet_single_want_hack_req_100);
+ }
+ BV_CLR_ALL(fields);
+
+ old = hash_lookup_data(*hash, real_packet);
+ old_from_hash = (old != NULL);
+ if (!old) {
+ old = fc_malloc(sizeof(*old));
+ memset(old, 0, sizeof(*old));
+ force_send_of_unchanged = TRUE;
+ }
+
+ differ = (strcmp(old->token, real_packet->token) != 0);
+ if(differ) {different++;}
+ if(differ) {BV_SET(fields, 0);}
+
+ if (different == 0 && !force_send_of_unchanged) {
+ return 0;
+ }
+
+ DIO_BV_PUT(&dout, fields);
+
+ if (BV_ISSET(fields, 0)) {
+ dio_put_string(&dout, real_packet->token);
+ }
+
+
+ if (old_from_hash) {
+ hash_delete_entry(*hash, old);
+ }
+
+ clone = old;
+
+ *clone = *real_packet;
+ hash_insert(*hash, clone, clone);
+ SEND_PACKET_END;
+}
+
+#define hash_packet_single_want_hack_req_101 hash_const
+
+#define cmp_packet_single_want_hack_req_101 cmp_const
+
+BV_DEFINE(packet_single_want_hack_req_101_fields, 1);
+
+static struct packet_single_want_hack_req
*receive_packet_single_want_hack_req_101(struct connection *pc, enum
packet_type type)
+{
+ packet_single_want_hack_req_101_fields fields;
+ struct packet_single_want_hack_req *old;
+ struct hash_table **hash = &pc->phs.received[type];
+ struct packet_single_want_hack_req *clone;
+ RECEIVE_PACKET_START(packet_single_want_hack_req, real_packet);
+
+ DIO_BV_GET(&din, fields);
+
+
+ if (!*hash) {
+ *hash = hash_new(hash_packet_single_want_hack_req_101,
cmp_packet_single_want_hack_req_101);
+ }
+ old = hash_delete_entry(*hash, real_packet);
+
+ if (old) {
+ *real_packet = *old;
+ } else {
+ memset(real_packet, 0, sizeof(*real_packet));
+ }
+
+ if (BV_ISSET(fields, 0)) {
{
int readin;
dio_get_uint32(&din, &readin);
- real_packet->challenge = readin;
+ real_packet->old_token = readin;
}
}
@@ -27099,10 +27190,10 @@
RECEIVE_PACKET_END(real_packet);
}
-static int send_packet_single_want_hack_req_100(struct connection *pc, const
struct packet_single_want_hack_req *packet)
+static int send_packet_single_want_hack_req_101(struct connection *pc, const
struct packet_single_want_hack_req *packet)
{
const struct packet_single_want_hack_req *real_packet = packet;
- packet_single_want_hack_req_100_fields fields;
+ packet_single_want_hack_req_101_fields fields;
struct packet_single_want_hack_req *old, *clone;
bool differ, old_from_hash, force_send_of_unchanged = TRUE;
struct hash_table **hash = &pc->phs.sent[PACKET_SINGLE_WANT_HACK_REQ];
@@ -27110,7 +27201,7 @@
SEND_PACKET_START(PACKET_SINGLE_WANT_HACK_REQ);
if (!*hash) {
- *hash = hash_new(hash_packet_single_want_hack_req_100,
cmp_packet_single_want_hack_req_100);
+ *hash = hash_new(hash_packet_single_want_hack_req_101,
cmp_packet_single_want_hack_req_101);
}
BV_CLR_ALL(fields);
@@ -27122,7 +27213,7 @@
force_send_of_unchanged = TRUE;
}
- differ = (old->challenge != real_packet->challenge);
+ differ = (old->old_token != real_packet->old_token);
if(differ) {different++;}
if(differ) {BV_SET(fields, 0);}
@@ -27133,7 +27224,7 @@
DIO_BV_PUT(&dout, fields);
if (BV_ISSET(fields, 0)) {
- dio_put_uint32(&dout, real_packet->challenge);
+ dio_put_uint32(&dout, real_packet->old_token);
}
@@ -27157,8 +27248,10 @@
}
if(FALSE) {
- } else if(TRUE) {
+ } else if((has_capability("new_hack", pc->capability) &&
has_capability("new_hack", our_capability))) {
variant = 100;
+ } else if(!(has_capability("new_hack", pc->capability) &&
has_capability("new_hack", our_capability))) {
+ variant = 101;
} else {
die("unknown variant");
}
@@ -27181,6 +27274,7 @@
switch(pc->phs.variant[PACKET_SINGLE_WANT_HACK_REQ]) {
case 100: return receive_packet_single_want_hack_req_100(pc, type);
+ case 101: return receive_packet_single_want_hack_req_101(pc, type);
default: die("unknown variant"); return NULL;
}
}
@@ -27201,19 +27295,11 @@
switch(pc->phs.variant[PACKET_SINGLE_WANT_HACK_REQ]) {
case 100: return send_packet_single_want_hack_req_100(pc, packet);
+ case 101: return send_packet_single_want_hack_req_101(pc, packet);
default: die("unknown variant"); return -1;
}
}
-int dsend_packet_single_want_hack_req(struct connection *pc, int challenge)
-{
- struct packet_single_want_hack_req packet, *real_packet = &packet;
-
- real_packet->challenge = challenge;
-
- return send_packet_single_want_hack_req(pc, real_packet);
-}
-
#define hash_packet_single_want_hack_reply_100 hash_const
#define cmp_packet_single_want_hack_reply_100 cmp_const
Index: common/packets_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.h,v
retrieving revision 1.51
diff -u -r1.51 packets_gen.h
--- common/packets_gen.h 4 Nov 2004 03:02:11 -0000 1.51
+++ common/packets_gen.h 15 Nov 2004 23:45:32 -0000
@@ -979,7 +979,8 @@
};
struct packet_single_want_hack_req {
- int challenge;
+ int old_token;
+ char token[MAX_LEN_NAME];
};
struct packet_single_want_hack_reply {
@@ -1600,7 +1601,6 @@
struct packet_single_want_hack_req *receive_packet_single_want_hack_req(struct
connection *pc, enum packet_type type);
int send_packet_single_want_hack_req(struct connection *pc, const struct
packet_single_want_hack_req *packet);
-int dsend_packet_single_want_hack_req(struct connection *pc, int challenge);
struct packet_single_want_hack_reply
*receive_packet_single_want_hack_reply(struct connection *pc, enum packet_type
type);
int send_packet_single_want_hack_reply(struct connection *pc, const struct
packet_single_want_hack_reply *packet);
Index: server/connecthand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/connecthand.c,v
retrieving revision 1.35
diff -u -r1.35 connecthand.c
--- server/connecthand.c 23 Oct 2004 23:12:22 -0000 1.35
+++ server/connecthand.c 15 Nov 2004 23:45:35 -0000
@@ -82,7 +82,7 @@
sz_strlcpy(packet.capability, our_capability);
my_snprintf(packet.message, sizeof(packet.message), _("%s Welcome"),
pconn->username);
- sz_strlcpy(packet.challenge_file, create_challenge_filename());
+ sz_strlcpy(packet.challenge_file, new_challenge_filename(pconn));
packet.conn_id = pconn->id;
send_packet_server_join_reply(pconn, &packet);
Index: server/gamehand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamehand.c,v
retrieving revision 1.144
diff -u -r1.144 gamehand.c
--- server/gamehand.c 10 Oct 2004 20:02:02 -0000 1.144
+++ server/gamehand.c 15 Nov 2004 23:45:35 -0000
@@ -18,6 +18,7 @@
#include <assert.h>
#include <stdio.h> /* for remove() */
+#include "capability.h"
#include "events.h"
#include "fcintl.h"
#include "improvement.h"
@@ -34,15 +35,10 @@
#include "unittools.h"
#include "gamehand.h"
+#include "srv_main.h"
-#define NUMBER_OF_TRIES 500
-#ifndef __VMS
-# define CHALLENGE_ROOT ".freeciv-tmp"
-#else /*VMS*/
-# define CHALLENGE_ROOT "freeciv-tmp"
-#endif
+#define CHALLENGE_ROOT "challenge"
-static char challenge_filename[MAX_LEN_PATH];
/****************************************************************************
Initialize the game.id variable to a random string of characters.
@@ -413,74 +409,79 @@
}
/**************************************************************************
-find a suitably random file that we can write too, and return it's name.
+ generate challenge filename for this connection, cannot fail.
**************************************************************************/
-const char *create_challenge_filename(void)
+static void gen_challenge_filename(struct connection *pc)
{
- int i;
- unsigned int tmp = 0;
+}
- /* find a suitable file to place the challenge in, we'll remove the file
- * once the challenge is */
-#ifndef CHALLENGE_PATH
- sz_strlcpy(challenge_filename, user_home_dir());
- sz_strlcat(challenge_filename, "/");
- sz_strlcat(challenge_filename, CHALLENGE_ROOT);
-#else
- sz_strlcpy(challenge_filename, CHALLENGE_PATH);
-#endif
-
- for (i = 0; i < NUMBER_OF_TRIES; i++) {
- char test_str[MAX_LEN_PATH];
-
- sz_strlcpy(test_str, challenge_filename);
- tmp = time(NULL);
- cat_snprintf(test_str, MAX_LEN_PATH, "-%d", tmp);
-
- /* file doesn't exist but we can create one and write to it */
- if (!is_reg_file_for_access(test_str, FALSE) &&
- is_reg_file_for_access(test_str, TRUE)) {
- cat_snprintf(challenge_filename, MAX_LEN_PATH, "-%d", tmp);
- break;
- } else {
- die("we can't seem to write to the filesystem!");
- }
+/**************************************************************************
+ get challenge filename for this connection.
+**************************************************************************/
+static const char *get_challenge_filename(struct connection *pc)
+{
+ static char filename[MAX_LEN_PATH];
+
+ my_snprintf(filename, sizeof(filename), "%s_%d_%d",
+ CHALLENGE_ROOT, srvarg.port, pc->id);
+
+ return filename;
+}
+
+/**************************************************************************
+ get challenge full filename for this connection.
+**************************************************************************/
+static const char *get_challenge_fullname(struct connection *pc)
+{
+ static char fullname[MAX_LEN_PATH];
+
+ interpret_tilde(fullname, sizeof(fullname), "~/.freeciv/");
+ sz_strlcat(fullname, get_challenge_filename(pc));
+
+ return fullname;
+}
+
+/**************************************************************************
+ find a file that we can write too, and return it's name.
+**************************************************************************/
+const char *new_challenge_filename(struct connection *pc)
+{
+ if (!has_capability("new_hack", pc->capability)) {
+ return "";
}
- return challenge_filename;
+ gen_challenge_filename(pc);
+ return get_challenge_filename(pc);
}
+
/**************************************************************************
opens a file specified by the packet and compares the packet values with
the file values. Sends an answer to the client once it's done.
**************************************************************************/
-void handle_single_want_hack_req(struct connection *pc, int challenge)
+void handle_single_want_hack_req(struct connection *pc,
+ const struct packet_single_want_hack_req
+ *packet)
{
struct section_file file;
- int entropy = 0;
- bool could_load = TRUE;
+ char *token = NULL;
bool you_have_hack = FALSE;
- if (is_reg_file_for_access(challenge_filename, FALSE)) {
- if (section_file_load_nodup(&file, challenge_filename)) {
- entropy = secfile_lookup_int_default(&file, 0, "challenge.entropy");
- section_file_free(&file);
- } else {
- freelog(LOG_ERROR, "couldn't load temporary file: %s",
- challenge_filename);
- could_load = FALSE;
- }
+ if (!has_capability("new_hack", pc->capability)) {
+ dsend_packet_single_want_hack_reply(pc, FALSE);
+ return ;
+ }
- /* remove temp file */
- if (remove(challenge_filename) != 0) {
- freelog(LOG_ERROR, "couldn't remove temporary file: %s",
- challenge_filename);
- }
- } else {
- could_load = FALSE;
+ if (section_file_load_nodup(&file, get_challenge_fullname(pc))) {
+ token = secfile_lookup_str_default(&file, NULL, "challenge.token");
+ section_file_free(&file);
+ }
+
+ if (!token) {
+ freelog(LOG_DEBUG, "Failed to read authentication token");
}
- you_have_hack = (could_load && entropy && entropy == challenge);
+ you_have_hack = (token && strcmp(token, packet->token) == 0);
if (you_have_hack) {
pc->access_level = ALLOW_HACK;
Index: server/gamehand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamehand.h,v
retrieving revision 1.11
diff -u -r1.11 gamehand.h
--- server/gamehand.h 10 Apr 2004 03:47:49 -0000 1.11
+++ server/gamehand.h 15 Nov 2004 23:45:35 -0000
@@ -25,7 +25,12 @@
int update_timeout(void);
-const char *create_challenge_filename(void);
-void handle_single_want_hack_req(struct connection *pc, int challenge);
+const char *new_challenge_filename(struct connection *pc);
+
+struct packet_single_want_hack_req;
+
+void handle_single_want_hack_req(struct connection *pc,
+ const struct packet_single_want_hack_req
+ *packet);
#endif /* FC__GAMEHAND_H */
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.208
diff -u -r1.208 srv_main.c
--- server/srv_main.c 11 Nov 2004 16:56:39 -0000 1.208
+++ server/srv_main.c 15 Nov 2004 23:45:40 -0000
@@ -952,7 +952,7 @@
if (type == PACKET_SINGLE_WANT_HACK_REQ) {
handle_single_want_hack_req(pconn,
- ((struct packet_single_want_hack_req *)packet)->challenge);
+ (struct packet_single_want_hack_req *) packet);
return TRUE;
}
- [Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues., Vasco Alexandre da Silva Costa, 2004/11/15
- [Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues., Vasco Alexandre da Silva Costa, 2004/11/15
- [Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues., Vasco Alexandre da Silva Costa, 2004/11/15
- [Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues.,
Vasco Alexandre da Silva Costa <=
- [Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues., Vasco Alexandre da Silva Costa, 2004/11/15
- [Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues., Vasco Alexandre da Silva Costa, 2004/11/15
- [Freeciv-Dev] (PR#10727) [PATCH] Hack challenge protocol issues., Vasco Alexandre da Silva Costa, 2004/11/15
|
|