forked from packetflinger/q2admin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathg_cloud.h
More file actions
292 lines (257 loc) · 8.44 KB
/
Copy pathg_cloud.h
File metadata and controls
292 lines (257 loc) · 8.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#ifndef G_REMOTE_H
#define G_REMOTE_H
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <fcntl.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#define CLOUDFILE "q2a_cloud.cfg"
#define MAGIC_CLIENT (('C' << 24) + ('A' << 16) + ('2' << 8) + 'Q')
#define MAGIC_PEER (('P' << 24) + ('A' << 16) + ('2' << 8) + 'Q')
#define NS_INT16SZ 2
#define NS_INADDRSZ 4
#define NS_IN6ADDRSZ 16
#define QUEUE_SIZE 0x55FF
#define CA_FRAME (cloud.frame_number)
// arg in seconds
#define FUTURE_CA_FRAME(t) (CA_FRAME + SECS_TO_FRAMES(t))
#define CLOUDCMD_LAYOUT "sv !cloud <status|(dis|en)able|rule>"
// Cloud Admin flags, enabled features
#define CFL_FRAGS BIT(0)
#define CFL_CHAT BIT(1)
#define CFL_TELEPORT BIT(2)
#define CFL_INVITE BIT(3)
#define CFL_FIND BIT(4)
#define CFL_WHOIS BIT(5)
#define CFL_DEBUG BIT(11) // 1024
#define CFL(f) ((cloud.flags & CFL_##f) != 0)
#define MAX_MSG_LEN 1000
#define PING_FREQ_SECS 40
#define PING_MISS_MAX 3
#define RSA_LEN 256 // bytes, 2048 bits
#define CHALLENGE_LEN 16 // bytes
#define AESKEY_LEN 16 // bytes, 128 bits
#define AESBLOCK_LEN 16 // bytes, 128 bits
#define AES_IV_LEN 16
#define AUTH_FAIL_LIMIT 3 // stop trying after
#define DIGEST_LEN (SHA256_DIGEST_LENGTH)
#define TELE_NAME_MAX 20
/**
* The various states of the cloud admin connection. A normal connection will
* hang out in the TRUSTED state most of the time (unless disabled).
*/
typedef enum {
CLOUD_STATE_DISABLED, // not using CA at all
CLOUD_STATE_DISCONNECTED, // will try to connect when possible
CLOUD_STATE_CONNECTING, // mid connection
CLOUD_STATE_CONNECTED, // connected, but still authenticating
CLOUD_STATE_TRUSTED // authenticated and ready to go
} cloud_state_t;
#define CLOUD_OK (cloud.state == CLOUD_STATE_TRUSTED)
#define STATE(s) (cloud.state == CLOUD_STATE_##s)
typedef struct {
byte data[QUEUE_SIZE];
size_t length;
uint32_t index; // for reading
} message_queue_t;
/**
* For pinging the server, if no reply after x frames, assuming connection is
* broken and reconnect.
*/
typedef struct {
bool waiting; // we sent a ping, waiting for a pong
uint32_t frame_sent; // when it was sent
uint32_t frame_next; // when to send the next one
uint8_t miss_count; // how many sent without a reply
} cloud_ping_t;
/**
* Authenticating with a Cloud Admin server is a 4-way handshake. These
* describe those levels.
*/
typedef enum {
CLOUD_AUTH_SENT_CL_NONCE,
CLOUD_AUTH_REC_KEY,
CLOUD_AUTH_SENT_SV_NONCE,
CLOUD_AUTH_REC_ACK,
} cloud_auth_t;
/**
* Connection specific stuff. Also holds the asymmetric and symmetric
* encryption keys and nonces.
*/
typedef struct {
uint32_t socket;
bool ipv6; // is this a v6 connection?
bool trusted; // is the server trusted?
bool encrypted; // should we encrypt?
bool have_keys; // do we have the shared keys?
cloud_auth_t authstage;
uint8_t auth_fail_count;
// auth and encryption stuff
byte cl_nonce[CHALLENGE_LEN]; // random data
byte sv_nonce[CHALLENGE_LEN]; // random data
byte session_key[AESKEY_LEN]; // shared encryption key (128bit)
byte initial_value[AES_IV_LEN]; // CBC IV is 16 bytes
EVP_PKEY *public_key; // our public key
EVP_PKEY *private_key; // our private key
EVP_PKEY *server_key; // CA server's public key
EVP_CIPHER_CTX *e_ctx; // encryption context
EVP_CIPHER_CTX *d_ctx; // decryption context
fd_set set_r; // read
fd_set set_w; // write
fd_set set_e; // error
} cloud_connection_t;
/**
* Holds all info and state about the cloud admin connection
*/
typedef struct {
cloud_state_t state;
cloud_connection_t connection;
uint32_t connect_retry_frame;
uint32_t connection_attempts;
uint32_t disconnect_count;
uint32_t connected_frame; // the frame when we connected
struct addrinfo *addr;
uint32_t flags;
uint32_t frame_number;
char mapname[32];
uint8_t maxclients;
uint16_t port;
message_queue_t queue; // messages outgoing to RA server
message_queue_t queue_in; // messages incoming from RA server
cloud_ping_t ping;
} cloud_t;
/**
* Major client (q2server) to server (q2admin server) commands.
*/
typedef enum {
CMD_NULL,
CMD_HELLO,
CMD_QUIT, // server quit
CMD_CONNECT, // player
CMD_DISCONNECT, // player
CMD_PLAYERLIST,
CMD_PLAYERUPDATE,
CMD_PRINT,
CMD_COMMAND, // teleport, invite, etc
CMD_PLAYERS,
CMD_FRAG, // someone fragged someone else
CMD_MAP, // map changed
CMD_PING,
CMD_AUTH
} cloud_client_cmd_t;
/**
* Server to client commands
*/
typedef enum {
SCMD_NULL,
SCMD_HELLOACK,
SCMD_ERROR,
SCMD_PONG,
SCMD_COMMAND,
SCMD_SAYCLIENT,
SCMD_SAYALL,
SCMD_AUTH,
SCMD_TRUSTED,
SCMD_KEY,
SCMD_GETPLAYERS,
} cloud_server_cmd_t;
/**
* Sub commands. These are initiated by players
*/
typedef enum {
CMD_COMMAND_TELEPORT,
CMD_COMMAND_INVITE,
CMD_COMMAND_WHOIS
} cloud_cl_command_t;
/**
* Cloud admin configuration
*/
typedef struct {
char address[256];
char cmd_invite[25];
char cmd_seen[25];
char cmd_teleport[25];
char cmd_whois[25];
char dns[3];
bool enabled;
bool encryption;
int flags;
int port;
char private[256];
char public[256];
char serverkey[256];
char uuid[37];
} cloud_config_t;
void CA_Send(void);
void CA_Init(void);
void CA_Shutdown(void);
void CA_RunFrame(void);
void CA_Register(void);
void CA_Unregister(void);
void CA_PlayerConnect(edict_t *ent);
void CA_PlayerDisconnect(edict_t *ent);
void CA_PlayerCommand(edict_t *ent);
uint8_t CA_ReadByte(void);
uint16_t CA_ReadShort(void);
int32_t CA_ReadLong(void);
char *CA_ReadString(void);
void CA_ReadData(void *out, size_t len);
void CA_WriteString(const char *fmt, ...);
void CA_WriteByte(uint8_t b);
void CA_WriteLong(uint32_t i);
void CA_WriteShort(uint16_t s);
void CA_WriteData(const void *data, size_t length);
void CA_InitBuffer(void);
uint16_t getport(void);
void CA_Print(uint8_t level, char *text);
void CA_Teleport(uint8_t client_id, char *where);
void CA_Frag(uint8_t victim, uint8_t attacker);
void CA_PlayerUpdate(uint8_t cl, const char *ui);
void CA_Invite(uint8_t cl, const char *text);
void CA_Whois(uint8_t cl, const char *name);
void CA_Map(const char *mapname);
void CA_Authorize(const char *authkey);
void CA_HeartBeat(void);
void CA_Encrypt(void);
void CA_Connect(void);
void CA_Disconnect(void);
void CA_CheckConnection(void);
void CA_SendMessages(void);
void CA_ReadMessages(void);
void CA_ParseMessage(void);
void CA_ParseCommand(void);
void CA_DisconnectedPeer(void);
void CA_Ping(void);
void CA_PlayerList(void);
void CA_LookupAddress(void);
void G_StartThread(void *func, void *arg);
void CA_SayHello(void);
void CA_ParsePong(void);
void CA_ParseError(void);
void CA_SayClient(void);
void CA_SayAll(void);
bool G_LoadKeys(void);
bool CA_VerifyServerAuth(void);
void G_RSAError(void);
void hexDump (char *desc, void *addr, int len);
void CA_RotateKeys(void);
void debug_print(char *str);
void cloudRun(int startarg, edict_t *ent, int client);
void CA_printf(char *fmt, ...);
void CA_dprintf(char *fmt, ...);
void ReadCloudConfigFile(void);
void Cmd_Invite_f(edict_t *ent);
void Cmd_Teleport_f(edict_t *ent);
extern cloud_t cloud;
extern cloud_config_t cloud_config;
extern cvar_t *gamelib;
#endif