src/network/network_client.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6725 23339968083f
child 6872 1c4a4a609f85
equal deleted inserted replaced
6870:ca3fd1fbe311 6871:5a9dc001e1ad
    21 #include "../console.h"
    21 #include "../console.h"
    22 #include "../variables.h"
    22 #include "../variables.h"
    23 #include "../ai/ai.h"
    23 #include "../ai/ai.h"
    24 #include "../helpers.hpp"
    24 #include "../helpers.hpp"
    25 #include "../fileio.h"
    25 #include "../fileio.h"
       
    26 #include "../md5.h"
    26 
    27 
    27 // This file handles all the client-commands
    28 // This file handles all the client-commands
    28 
    29 
    29 
    30 
    30 // So we don't make too much typos ;)
    31 // So we don't make too much typos ;)
    31 #define MY_CLIENT DEREF_CLIENT(0)
    32 #define MY_CLIENT DEREF_CLIENT(0)
    32 
    33 
    33 static uint32 last_ack_frame;
    34 static uint32 last_ack_frame;
       
    35 
       
    36 /** One bit of 'entropy' used to generate a salt for the company passwords. */
       
    37 static uint32 _password_game_seed;
       
    38 /** The other bit of 'entropy' used to generate a salt for the company passwords. */
       
    39 static char _password_server_unique_id[NETWORK_UNIQUE_ID_LENGTH];
       
    40 
       
    41 /** Make sure the unique ID length is the same as a md5 hash. */
       
    42 assert_compile(NETWORK_UNIQUE_ID_LENGTH == 16 * 2 + 1);
       
    43 
       
    44 /**
       
    45  * Generates a hashed password for the company name.
       
    46  * @param password the password to 'encrypt'.
       
    47  * @return the hashed password.
       
    48  */
       
    49 static const char *GenerateCompanyPasswordHash(const char *password)
       
    50 {
       
    51 	if (StrEmpty(password)) return password;
       
    52 
       
    53 	char salted_password[NETWORK_UNIQUE_ID_LENGTH];
       
    54 
       
    55 	memset(salted_password, 0, sizeof(salted_password));
       
    56 	snprintf(salted_password, sizeof(salted_password), "%s", password);
       
    57 	/* Add the game seed and the server's unique ID as the salt. */
       
    58 	for (uint i = 0; i < NETWORK_UNIQUE_ID_LENGTH; i++) salted_password[i] ^= _password_server_unique_id[i] ^ (_password_game_seed >> i);
       
    59 
       
    60 	md5_state_t state;
       
    61 	md5_byte_t digest[16];
       
    62 	static char hashed_password[NETWORK_UNIQUE_ID_LENGTH];
       
    63 
       
    64 	/* Generate the MD5 hash */
       
    65 	md5_init(&state);
       
    66 	md5_append(&state, (const md5_byte_t*)salted_password, sizeof(salted_password));
       
    67 	md5_finish(&state, digest);
       
    68 
       
    69 	for (int di = 0; di < 16; di++) sprintf(hashed_password + di * 2, "%02x", digest[di]);
       
    70 
       
    71 	return hashed_password;
       
    72 }
       
    73 
       
    74 /**
       
    75  * Hash the current company password; used when the server 'player' sets his/her password.
       
    76  */
       
    77 void HashCurrentCompanyPassword()
       
    78 {
       
    79 	if (StrEmpty(_network_player_info[_local_player].password)) return;
       
    80 
       
    81 	_password_game_seed = _patches.generation_seed;
       
    82 	snprintf(_password_server_unique_id, sizeof(_password_server_unique_id), _network_unique_id);
       
    83 
       
    84 	const char *new_pw = GenerateCompanyPasswordHash(_network_player_info[_local_player].password);
       
    85 	snprintf(_network_player_info[_local_player].password, sizeof(_network_player_info[_local_player].password), new_pw);
       
    86 }
       
    87 
    34 
    88 
    35 // **********
    89 // **********
    36 // Sending functions
    90 // Sending functions
    37 //   DEF_CLIENT_SEND_COMMAND has no parameters
    91 //   DEF_CLIENT_SEND_COMMAND has no parameters
    38 // **********
    92 // **********
   101 	//    uint8:  NetworkPasswordType
   155 	//    uint8:  NetworkPasswordType
   102 	//    String: Password
   156 	//    String: Password
   103 	//
   157 	//
   104 	Packet *p = NetworkSend_Init(PACKET_CLIENT_PASSWORD);
   158 	Packet *p = NetworkSend_Init(PACKET_CLIENT_PASSWORD);
   105 	p->Send_uint8 (type);
   159 	p->Send_uint8 (type);
   106 	p->Send_string(password);
   160 	p->Send_string(type == NETWORK_GAME_PASSWORD ? password : GenerateCompanyPasswordHash(password));
   107 	MY_CLIENT->Send_Packet(p);
   161 	MY_CLIENT->Send_Packet(p);
   108 }
   162 }
   109 
   163 
   110 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GETMAP)
   164 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GETMAP)
   111 {
   165 {
   222 	// Data:
   276 	// Data:
   223 	//    String: Password
   277 	//    String: Password
   224 	//
   278 	//
   225 	Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_PASSWORD);
   279 	Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_PASSWORD);
   226 
   280 
   227 	p->Send_string(password);
   281 	p->Send_string(GenerateCompanyPasswordHash(password));
   228 	MY_CLIENT->Send_Packet(p);
   282 	MY_CLIENT->Send_Packet(p);
   229 }
   283 }
   230 
   284 
   231 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name)
   285 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name)
   232 {
   286 {
   339 {
   393 {
   340 	NetworkClientInfo *ci;
   394 	NetworkClientInfo *ci;
   341 	uint16 index = p->Recv_uint16();
   395 	uint16 index = p->Recv_uint16();
   342 	PlayerID playas = (Owner)p->Recv_uint8();
   396 	PlayerID playas = (Owner)p->Recv_uint8();
   343 	char name[NETWORK_NAME_LENGTH];
   397 	char name[NETWORK_NAME_LENGTH];
   344 	char unique_id[NETWORK_NAME_LENGTH];
   398 	char unique_id[NETWORK_UNIQUE_ID_LENGTH];
   345 
   399 
   346 	p->Recv_string(name, sizeof(name));
   400 	p->Recv_string(name, sizeof(name));
   347 	p->Recv_string(unique_id, sizeof(unique_id));
   401 	p->Recv_string(unique_id, sizeof(unique_id));
   348 
   402 
   349 	if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
   403 	if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
   456 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
   510 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
   457 {
   511 {
   458 	NetworkPasswordType type = (NetworkPasswordType)p->Recv_uint8();
   512 	NetworkPasswordType type = (NetworkPasswordType)p->Recv_uint8();
   459 
   513 
   460 	switch (type) {
   514 	switch (type) {
       
   515 		case NETWORK_COMPANY_PASSWORD:
       
   516 			/* Initialize the password hash salting variables. */
       
   517 			_password_game_seed = p->Recv_uint32();
       
   518 			p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
       
   519 			if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
       
   520 
   461 		case NETWORK_GAME_PASSWORD:
   521 		case NETWORK_GAME_PASSWORD:
   462 		case NETWORK_COMPANY_PASSWORD:
       
   463 			ShowNetworkNeedPassword(type);
   522 			ShowNetworkNeedPassword(type);
   464 			return NETWORK_RECV_STATUS_OKAY;
   523 			return NETWORK_RECV_STATUS_OKAY;
   465 
   524 
   466 		default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
   525 		default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
   467 	}
   526 	}
   468 }
   527 }
   469 
   528 
   470 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
   529 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
   471 {
   530 {
   472 	_network_own_client_index = p->Recv_uint16();
   531 	_network_own_client_index = p->Recv_uint16();
       
   532 
       
   533 	/* Initialize the password hash salting variables, even if they were previously. */
       
   534 	_password_game_seed = p->Recv_uint32();
       
   535 	p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
   473 
   536 
   474 	// Start receiving the map
   537 	// Start receiving the map
   475 	SEND_COMMAND(PACKET_CLIENT_GETMAP)();
   538 	SEND_COMMAND(PACKET_CLIENT_GETMAP)();
   476 	return NETWORK_RECV_STATUS_OKAY;
   539 	return NETWORK_RECV_STATUS_OKAY;
   477 }
   540 }