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 { |
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 } |