1 /*
2 * Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu)
3 * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu)
4 * Copyright (C) 1999,2000 Rob Crittenden (rcrit@greyoak.com)
5 * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net)
6 * Copyright (C) 2003 Dizzy
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #define VERSIONCHECK_INTERNAL_ACCESS
24 #include "common/setup_before.h"
25 #include <stdio.h>
26 #include <ctype.h>
27 // amadeo
28 #ifdef WIN32_GUI
29 #include <win32/winmain.h>
30 #endif
31 // NonReal:
32 #include <sys/stat.h>
33 #ifdef HAVE_STDDEF_H
34 # include <stddef.h>
35 #else
36 # ifndef NULL
37 # define NULL ((void *)0)
38 # endif
39 #endif
40 #ifdef STDC_HEADERS /* FIXME: remove ? */
41 # include <stdlib.h>
42 #endif
43 #ifdef HAVE_STRING_H
44 # include <string.h>
45 #else
46 # ifdef HAVE_STRINGS_H
47 # include <strings.h>
48 # endif
49 # ifdef HAVE_MEMORY_H
50 # include <memory.h>
51 # endif
52 #endif
53 #ifdef WIN32
54 #include "compat/socket.h"
55 #endif
56 #include "compat/strcasecmp.h"
57 #include "compat/strncasecmp.h"
58 #include "compat/strchr.h"
59 #include "compat/strdup.h"
60 #include "common/packet.h"
61 #include "common/bnet_protocol.h"
62 #include "common/tag.h"
63 #include "message.h"
64 #include "common/eventlog.h"
65 #include "command.h"
66 #include "team.h"
67 #include "account.h"
68 #include "account_wrap.h"
69 #include "realm.h"
70 #include "connection.h"
71 #include "channel.h"
72 #include "game.h"
73 #include "common/queue.h"
74 #include "tick.h"
75 #include "file.h"
76 #include "prefs.h"
77 #include "common/util.h"
78 #include "common/bnethash.h"
79 #include "common/bnethashconv.h"
80 #include "common/bn_type.h"
81 #include "common/field_sizes.h"
82 #include "ladder.h"
83 #include "adbanner.h"
84 #include "common/list.h"
85 #include "common/bnettime.h"
86 #include "common/addr.h"
87 #include "game_conv.h"
88 #include "autoupdate.h"
89 #include "character.h"
90 #include "versioncheck.h"
91 #include "anongame.h"
92 #include "handle_anongame.h"
93 #include "common/proginfo.h"
94 #include "clan.h"
95 #include "handle_bnet.h"
96 #include "handlers.h"
97 #ifdef HAVE_NETINET_IN_H
98 # include <netinet/in.h>
99 #endif
100 #include "compat/netinet_in.h"
101 #include "watch.h"
102 #include "anongame_infos.h"
103 #include "news.h" //by Spider
104 #include "friends.h"
105 #include "server.h"
106 #include "compat/uint.h"
107 #include "common/trans.h"
108 #include "common/xalloc.h"
109 #include "common/lstr.h"
110 #include "common/setup_after.h"
111
112 extern int last_news;
113 extern int first_news;
114
115 /* handlers prototypes */
116 static int _client_unknown_1b(t_connection * c, t_packet const *const packet);
117 static int _client_compinfo1(t_connection * c, t_packet const *const packet);
118 static int _client_compinfo2(t_connection * c, t_packet const *const packet);
119 static int _client_countryinfo1(t_connection * c, t_packet const *const packet);
120 static int _client_countryinfo109(t_connection * c, t_packet const *const packet);
121 static int _client_unknown2b(t_connection * c, t_packet const *const packet);
122 static int _client_progident(t_connection * c, t_packet const *const packet);
123 static int _client_createaccountw3(t_connection * c, t_packet const *const packet);
124 static int _client_createacctreq1(t_connection * c, t_packet const *const packet);
125 static int _client_createacctreq2(t_connection * c, t_packet const *const packet);
126 static int _client_changepassreq(t_connection * c, t_packet const *const packet);
127 static int _client_echoreply(t_connection * c, t_packet const *const packet);
128 static int _client_authreq1(t_connection * c, t_packet const *const packet);
129 static int _client_authreq109(t_connection * c, t_packet const *const packet);
130 static int _client_regsnoopreply(t_connection * c, t_packet const *const packet);
131 static int _client_iconreq(t_connection * c, t_packet const *const packet);
132 static int _client_cdkey(t_connection * c, t_packet const *const packet);
133 static int _client_cdkey2(t_connection * c, t_packet const *const packet);
134 static int _client_cdkey3(t_connection * c, t_packet const *const packet);
135 static int _client_udpok(t_connection * c, t_packet const *const packet);
136 static int _client_fileinforeq(t_connection * c, t_packet const *const packet);
137 static int _client_statsreq(t_connection * c, t_packet const *const packet);
138 static int _client_loginreq1(t_connection * c, t_packet const *const packet);
139 static int _client_loginreq2(t_connection * c, t_packet const *const packet);
140 static int _client_loginreqw3(t_connection * c, t_packet const *const packet);
141 static int _client_pingreq(t_connection * c, t_packet const *const packet);
142 static int _client_logonproofreq(t_connection * c, t_packet const *const packet);
143 static int _client_changegameport(t_connection * c, t_packet const *const packet);
144 static int _client_friendslistreq(t_connection * c, t_packet const *const packet);
145 static int _client_friendinforeq(t_connection * c, t_packet const *const packet);
146 static int _client_atfriendscreen(t_connection * c, t_packet const *const packet);
147 static int _client_atinvitefriend(t_connection * c, t_packet const *const packet);
148 static int _client_atacceptinvite(t_connection * c, t_packet const *const packet);
149 static int _client_atacceptdeclineinvite(t_connection * c, t_packet const *const packet);
150 static int _client_motdw3(t_connection * c, t_packet const *const packet);
151 static int _client_realmlistreq(t_connection * c, t_packet const *const packet);
152 static int _client_realmlistreq110(t_connection * c, t_packet const *const packet);
153 static int _client_profilereq(t_connection * c, t_packet const *const packet);
154 static int _client_realmjoinreq109(t_connection * c, t_packet const *const packet);
155 static int _client_unknown39(t_connection * c, t_packet const *const packet);
156 static int _client_charlistreq(t_connection * c, t_packet const *const packet);
157 static int _client_adreq(t_connection * c, t_packet const *const packet);
158 static int _client_adack(t_connection * c, t_packet const *const packet);
159 static int _client_adclick(t_connection * c, t_packet const *const packet);
160 static int _client_adclick2(t_connection * c, t_packet const *const packet);
161 static int _client_statsupdate(t_connection * c, t_packet const *const packet);
162 static int _client_playerinforeq(t_connection * c, t_packet const *const packet);
163 static int _client_progident2(t_connection * c, t_packet const *const packet);
164 static int _client_joinchannel(t_connection * c, t_packet const *const packet);
165 static int _client_message(t_connection * c, t_packet const *const packet);
166 static int _client_gamelistreq(t_connection * c, t_packet const *const packet);
167 static int _client_joingame(t_connection * c, t_packet const *const packet);
168 static int _client_startgame1(t_connection * c, t_packet const *const packet);
169 static int _client_startgame3(t_connection * c, t_packet const *const packet);
170 static int _client_startgame4(t_connection * c, t_packet const *const packet);
171 static int _client_closegame(t_connection * c, t_packet const *const packet);
172 static int _client_gamereport(t_connection * c, t_packet const *const packet);
173 static int _client_leavechannel(t_connection * c, t_packet const *const packet);
174 static int _client_ladderreq(t_connection * c, t_packet const *const packet);
175 static int _client_laddersearchreq(t_connection * c, t_packet const *const packet);
176 static int _client_mapauthreq1(t_connection * c, t_packet const *const packet);
177 static int _client_mapauthreq2(t_connection * c, t_packet const *const packet);
178 static int _client_changeclient(t_connection * c, t_packet const *const packet);
179 static int _client_w3xp_clanmemberlistreq(t_connection * c, t_packet const *const packet);
180 static int _client_w3xp_clan_motdreq(t_connection * c, t_packet const *const packet);
181 static int _client_w3xp_clan_motdchg(t_connection * c, t_packet const *const packet);
182 static int _client_w3xp_clan_createreq(t_connection * c, t_packet const *const packet);
183 static int _client_w3xp_clan_createinvitereq(t_connection * c, t_packet const *const packet);
184 static int _client_w3xp_clan_createinvitereply(t_connection * c, t_packet const *const packet);
185 static int _client_w3xp_clan_disbandreq(t_connection * c, t_packet const *const packet);
186 static int _client_w3xp_clanmember_rankupdatereq(t_connection * c, t_packet const *const packet);
187 static int _client_w3xp_clanmember_removereq(t_connection * c, t_packet const *const packet);
188 static int _client_w3xp_clan_membernewchiefreq(t_connection * c, t_packet const *const packet);
189 static int _client_w3xp_clan_invitereq(t_connection * c, t_packet const *const packet);
190 static int _client_w3xp_clan_invitereply(t_connection * c, t_packet const *const packet);
191 static int _client_crashdump(t_connection * c, t_packet const *const packet);
192 static int _client_setemailreply(t_connection * c, t_packet const *const packet);
193 static int _client_changeemailreq(t_connection * c, t_packet const *const packet);
194 static int _client_getpasswordreq(t_connection * c, t_packet const *const packet);
195 static int _client_claninforeq(t_connection * c, t_packet const *const packet);
196
197 /* connection state connected handler table */
198 static const t_htable_row bnet_htable_con[] = {
199 {CLIENT_UNKNOWN_1B, _client_unknown_1b},
200 {CLIENT_COMPINFO1, _client_compinfo1},
201 {CLIENT_COMPINFO2, _client_compinfo2},
202 {CLIENT_COUNTRYINFO1, _client_countryinfo1},
203 {CLIENT_COUNTRYINFO_109, _client_countryinfo109},
204 {CLIENT_UNKNOWN_2B, _client_unknown2b},
205 {CLIENT_PROGIDENT, _client_progident},
206 {CLIENT_CLOSEGAME, NULL},
207 {CLIENT_CREATEACCOUNT_W3, _client_createaccountw3},
208 {CLIENT_CREATEACCTREQ1, _client_createacctreq1},
209 {CLIENT_CREATEACCTREQ2, _client_createacctreq2},
210 {CLIENT_CHANGEPASSREQ, _client_changepassreq},
211 {CLIENT_ECHOREPLY, _client_echoreply},
212 {CLIENT_AUTHREQ1, _client_authreq1},
213 {CLIENT_AUTHREQ_109, _client_authreq109},
214 {CLIENT_REGSNOOPREPLY, _client_regsnoopreply},
215 {CLIENT_ICONREQ, _client_iconreq},
216 {CLIENT_CDKEY, _client_cdkey},
217 {CLIENT_CDKEY2, _client_cdkey2},
218 {CLIENT_CDKEY3, _client_cdkey3},
219 {CLIENT_UDPOK, _client_udpok},
220 {CLIENT_FILEINFOREQ, _client_fileinforeq},
221 {CLIENT_STATSREQ, _client_statsreq},
222 {CLIENT_PINGREQ, _client_pingreq},
223 {CLIENT_LOGINREQ1, _client_loginreq1},
224 {CLIENT_LOGINREQ2, _client_loginreq2},
225 {CLIENT_LOGINREQ_W3, _client_loginreqw3},
226 {CLIENT_LOGONPROOFREQ, _client_logonproofreq},
227 /* After this packet we know to translate the packets to the normal IDs */
228 {CLIENT_CHANGECLIENT, _client_changeclient},
229 {CLIENT_GETPASSWORDREQ, _client_getpasswordreq},
230 {CLIENT_CHANGEEMAILREQ, _client_changeemailreq},
231 {CLIENT_CRASHDUMP, _client_crashdump},
232 {-1, NULL}
233 };
234
235 /* connection state loggedin handlers */
236 static const t_htable_row bnet_htable_log[] = {
237 {CLIENT_CHANGEGAMEPORT, _client_changegameport},
238 {CLIENT_FRIENDSLISTREQ, _client_friendslistreq},
239 {CLIENT_FRIENDINFOREQ, _client_friendinforeq},
240 {CLIENT_ARRANGEDTEAM_FRIENDSCREEN, _client_atfriendscreen},
241 {CLIENT_ARRANGEDTEAM_INVITE_FRIEND, _client_atinvitefriend},
242 {CLIENT_ARRANGEDTEAM_ACCEPT_INVITE, _client_atacceptinvite},
243 {CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE, _client_atacceptdeclineinvite},
244 /* anongame packet (44ff) handled in handle_anongame.c */
245 {CLIENT_FINDANONGAME, handle_anongame_packet},
246 {CLIENT_FILEINFOREQ, _client_fileinforeq},
247 {CLIENT_MOTD_W3, _client_motdw3},
248 {CLIENT_REALMLISTREQ, _client_realmlistreq},
249 {CLIENT_REALMLISTREQ_110, _client_realmlistreq110},
250 {CLIENT_PROFILEREQ, _client_profilereq},
251 {CLIENT_REALMJOINREQ_109, _client_realmjoinreq109},
252 {CLIENT_UNKNOWN_37, _client_charlistreq},
253 {CLIENT_UNKNOWN_39, _client_unknown39},
254 {CLIENT_ECHOREPLY, _client_echoreply},
255 {CLIENT_PINGREQ, _client_pingreq},
256 {CLIENT_ADREQ, _client_adreq},
257 {CLIENT_ADACK, _client_adack},
258 {CLIENT_ADCLICK, _client_adclick},
259 {CLIENT_ADCLICK2, _client_adclick2},
260 {CLIENT_STATSREQ, _client_statsreq},
261 {CLIENT_STATSUPDATE, _client_statsupdate},
262 {CLIENT_PLAYERINFOREQ, _client_playerinforeq},
263 {CLIENT_PROGIDENT2, _client_progident2},
264 {CLIENT_JOINCHANNEL, _client_joinchannel},
265 {CLIENT_MESSAGE, _client_message},
266 {CLIENT_GAMELISTREQ, _client_gamelistreq},
267 {CLIENT_JOIN_GAME, _client_joingame},
268 {CLIENT_STARTGAME1, _client_startgame1},
269 {CLIENT_STARTGAME3, _client_startgame3},
270 {CLIENT_STARTGAME4, _client_startgame4},
271 {CLIENT_CLOSEGAME, _client_closegame},
272 {CLIENT_CLOSEGAME2, _client_closegame},
273 {CLIENT_GAME_REPORT, _client_gamereport},
274 {CLIENT_LEAVECHANNEL, _client_leavechannel},
275 {CLIENT_LADDERREQ, _client_ladderreq},
276 {CLIENT_LADDERSEARCHREQ, _client_laddersearchreq},
277 {CLIENT_MAPAUTHREQ1, _client_mapauthreq1},
278 {CLIENT_MAPAUTHREQ2, _client_mapauthreq2},
279 {CLIENT_W3XP_CLAN_DISBANDREQ, _client_w3xp_clan_disbandreq},
280 {CLIENT_W3XP_CLANMEMBERLIST_REQ, _client_w3xp_clanmemberlistreq},
281 {CLIENT_W3XP_CLAN_MOTDCHG, _client_w3xp_clan_motdchg},
282 {CLIENT_W3XP_CLAN_MOTDREQ, _client_w3xp_clan_motdreq},
283 {CLIENT_W3XP_CLAN_CREATEREQ, _client_w3xp_clan_createreq},
284 {CLIENT_W3XP_CLAN_CREATEINVITEREQ, _client_w3xp_clan_createinvitereq},
285 {CLIENT_W3XP_CLAN_CREATEINVITEREPLY, _client_w3xp_clan_createinvitereply},
286 {CLIENT_W3XP_CLANMEMBER_RANKUPDATE_REQ, _client_w3xp_clanmember_rankupdatereq},
287 {CLIENT_W3XP_CLANMEMBER_REMOVE_REQ, _client_w3xp_clanmember_removereq},
288 {CLIENT_W3XP_CLAN_MEMBERNEWCHIEFREQ, _client_w3xp_clan_membernewchiefreq},
289 {CLIENT_W3XP_CLAN_INVITEREQ, _client_w3xp_clan_invitereq},
290 {CLIENT_W3XP_CLAN_INVITEREPLY, _client_w3xp_clan_invitereply},
291 {CLIENT_CRASHDUMP, _client_crashdump},
292 {CLIENT_SETEMAILREPLY, _client_setemailreply},
293 {CLIENT_CLANINFOREQ, _client_claninforeq},
294 {CLIENT_NULL, NULL},
295 {-1, NULL}
296 };
297
298 /* main handler function */
299 static int handle(const t_htable_row * htable, int type, t_connection * c, t_packet const *const packet);
300
handle_bnet_packet(t_connection * c,t_packet const * const packet)301 extern int handle_bnet_packet(t_connection * c, t_packet const *const packet)
302 {
303 if (!c) {
304 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(c));
305 return -1;
306 }
307 if (!packet) {
308 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL packet", conn_get_socket(c));
309 return -1;
310 }
311 if (packet_get_class(packet) != packet_class_bnet) {
312 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad packet (class %d)", conn_get_socket(c), (int) packet_get_class(packet));
313 return -1;
314 }
315
316 switch (conn_get_state(c)) {
317 case conn_state_connected:
318 switch (handle(bnet_htable_con, packet_get_type(packet), c, packet)) {
319 case 1:
320 eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown (unlogged in) bnet packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet));
321 break;
322 case -1:
323 eventlog(eventlog_level_error, __FUNCTION__, "[%d] (unlogged in) got error handling packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet));
324 break;
325 };
326 break;
327
328 case conn_state_loggedin:
329 switch (handle(bnet_htable_log, packet_get_type(packet), c, packet)) {
330 case 1:
331 eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown (logged in) bnet packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet));
332 break;
333 case -1:
334 eventlog(eventlog_level_error, __FUNCTION__, "[%d] (logged in) got error handling packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet));
335 break;
336 };
337 break;
338
339 case conn_state_untrusted:
340 eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown (untrusted) bnet packet type 0x%04x, len %u", conn_get_socket(c), packet_get_type(packet), packet_get_size(packet));
341 break;
342
343 default:
344 eventlog(eventlog_level_error, __FUNCTION__, "[%d] invalid login state %d", conn_get_socket(c), conn_get_state(c));
345 };
346
347 return 0;
348 }
349
handle(const t_htable_row * htable,int type,t_connection * c,t_packet const * const packet)350 static int handle(const t_htable_row * htable, int type, t_connection * c, t_packet const *const packet)
351 {
352 t_htable_row const *p;
353 int res = 1;
354
355 for (p = htable; p->type != -1; p++)
356 if (p->type == type) {
357 res = 0;
358 if (p->handler != NULL)
359 res = p->handler(c, packet);
360 if (res != 2)
361 break; /* return 2 means we want to continue parsing */
362 }
363
364 return res;
365 }
366
367 /* checks if a clienttag is in the allowed_clients list
368 * @ctag : clienttag integer to check
369 * if it's allowed returns 0
370 * if it's not allowed returns -1
371 */
_check_allowed_client(t_clienttag ctag)372 static int _check_allowed_client(t_clienttag ctag)
373 {
374 char *list, *p, *q;
375
376 /* by default allow all */
377 if (!prefs_get_allowed_clients())
378 return 0;
379
380 /* this shortcut check should make server as fast as before if
381 * the configuration is left in default mode */
382 if (!strcasecmp(prefs_get_allowed_clients(), "all"))
383 return 0;
384
385 list = xstrdup(prefs_get_allowed_clients());
386 p = list;
387 do {
388 q = strchr(p, ',');
389 if (q)
390 *q = '\0';
391 if (!strcasecmp(p, "all"))
392 goto ok;
393 if (strlen(p) != 4)
394 continue;
395 if (ctag == tag_case_str_to_uint(p))
396 goto ok; /* client allowed */
397 if (q)
398 p = q + 1;
399 } while (q);
400 xfree((void *) list);
401
402 return -1; /* client NOT allowed */
403
404 ok:
405 xfree((void *) list);
406 return 0;
407 }
408
409 /* handlers for bnet packets */
_client_unknown_1b(t_connection * c,t_packet const * const packet)410 static int _client_unknown_1b(t_connection * c, t_packet const *const packet)
411 {
412 if (packet_get_size(packet) < sizeof(t_client_unknown_1b)) {
413 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_1B packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_1b), packet_get_size(packet));
414 return -1;
415 }
416
417 {
418 unsigned int newip;
419 unsigned short newport;
420
421 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] UNKNOWN_1B unknown1=0x%04hx", conn_get_socket(c), bn_short_get(packet->u.client_unknown_1b.unknown1));
422 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] UNKNOWN_1B unknown2=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_unknown_1b.unknown2));
423 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] UNKNOWN_1B unknown3=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_unknown_1b.unknown3));
424
425 newip = bn_int_nget(packet->u.client_unknown_1b.ip);
426 newport = bn_short_nget(packet->u.client_unknown_1b.port);
427
428 eventlog(eventlog_level_info, __FUNCTION__, "[%d] UNKNOWN_1B set new UDP address to %s", conn_get_socket(c), addr_num_to_addr_str(newip, newport));
429 conn_set_game_addr(c, newip);
430 conn_set_game_port(c, newport);
431 }
432 return 0;
433 }
434
_client_compinfo1(t_connection * c,t_packet const * const packet)435 static int _client_compinfo1(t_connection * c, t_packet const *const packet)
436 {
437 t_packet *rpacket;
438
439 if (packet_get_size(packet) < sizeof(t_client_compinfo1)) {
440 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_compinfo1), packet_get_size(packet));
441 return -1;
442 }
443
444 {
445 char const *host;
446 char const *user;
447
448 if (!(host = packet_get_str_const(packet, sizeof(t_client_compinfo1), MAX_WINHOST_STR))) {
449 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO1 packet (missing or too long host)", conn_get_socket(c));
450 return -1;
451 }
452 if (!(user = packet_get_str_const(packet, sizeof(t_client_compinfo1) + strlen(host) + 1, MAX_WINUSER_STR))) {
453 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO1 packet (missing or too long user)", conn_get_socket(c));
454 return -1;
455 }
456
457 conn_set_host(c, host);
458 conn_set_user(c, user);
459 }
460
461 if ((rpacket = packet_create(packet_class_bnet))) {
462 packet_set_size(rpacket, sizeof(t_server_compreply));
463 packet_set_type(rpacket, SERVER_COMPREPLY);
464 bn_int_set(&rpacket->u.server_compreply.reg_version, SERVER_COMPREPLY_REG_VERSION);
465 bn_int_set(&rpacket->u.server_compreply.reg_auth, SERVER_COMPREPLY_REG_AUTH);
466 bn_int_set(&rpacket->u.server_compreply.client_id, SERVER_COMPREPLY_CLIENT_ID);
467 bn_int_set(&rpacket->u.server_compreply.client_token, SERVER_COMPREPLY_CLIENT_TOKEN);
468 conn_push_outqueue(c, rpacket);
469 packet_del_ref(rpacket);
470 }
471 if ((rpacket = packet_create(packet_class_bnet))) {
472 packet_set_size(rpacket, sizeof(t_server_sessionkey1));
473 packet_set_type(rpacket, SERVER_SESSIONKEY1);
474 bn_int_set(&rpacket->u.server_sessionkey1.sessionkey, conn_get_sessionkey(c));
475 conn_push_outqueue(c, rpacket);
476 packet_del_ref(rpacket);
477 }
478 return 0;
479 }
480
_client_compinfo2(t_connection * c,t_packet const * const packet)481 static int _client_compinfo2(t_connection * c, t_packet const *const packet)
482 {
483 t_packet *rpacket;
484
485 if (packet_get_size(packet) < sizeof(t_client_compinfo2)) {
486 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_compinfo2), packet_get_size(packet));
487 return -1;
488 }
489
490 {
491 char const *host;
492 char const *user;
493
494 if (!(host = packet_get_str_const(packet, sizeof(t_client_compinfo2), MAX_WINHOST_STR))) {
495 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO2 packet (missing or too long host)", conn_get_socket(c));
496 return -1;
497 }
498 if (!(user = packet_get_str_const(packet, sizeof(t_client_compinfo2) + strlen(host) + 1, MAX_WINUSER_STR))) {
499 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COMPINFO2 packet (missing or too long user)", conn_get_socket(c));
500 return -1;
501 }
502
503 conn_set_host(c, host);
504 conn_set_user(c, user);
505 }
506
507 if ((rpacket = packet_create(packet_class_bnet))) {
508 packet_set_size(rpacket, sizeof(t_server_compreply));
509 packet_set_type(rpacket, SERVER_COMPREPLY);
510 bn_int_set(&rpacket->u.server_compreply.reg_version, SERVER_COMPREPLY_REG_VERSION);
511 bn_int_set(&rpacket->u.server_compreply.reg_auth, SERVER_COMPREPLY_REG_AUTH);
512 bn_int_set(&rpacket->u.server_compreply.client_id, SERVER_COMPREPLY_CLIENT_ID);
513 bn_int_set(&rpacket->u.server_compreply.client_token, SERVER_COMPREPLY_CLIENT_TOKEN);
514 conn_push_outqueue(c, rpacket);
515 packet_del_ref(rpacket);
516 }
517
518 if ((rpacket = packet_create(packet_class_bnet))) {
519 packet_set_size(rpacket, sizeof(t_server_sessionkey2));
520 packet_set_type(rpacket, SERVER_SESSIONKEY2);
521 bn_int_set(&rpacket->u.server_sessionkey2.sessionnum, conn_get_sessionnum(c));
522 bn_int_set(&rpacket->u.server_sessionkey2.sessionkey, conn_get_sessionkey(c));
523 conn_push_outqueue(c, rpacket);
524 packet_del_ref(rpacket);
525 }
526
527 return 0;
528 }
529
_client_countryinfo1(t_connection * c,t_packet const * const packet)530 static int _client_countryinfo1(t_connection * c, t_packet const *const packet)
531 {
532 if (packet_get_size(packet) < sizeof(t_client_countryinfo1)) {
533 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_countryinfo1), packet_get_size(packet));
534 return -1;
535 }
536 {
537 char const *langstr;
538 char const *countrycode;
539 char const *country;
540 unsigned int tzbias;
541
542 if (!(langstr = packet_get_str_const(packet, sizeof(t_client_countryinfo1), MAX_LANG_STR))) {
543 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long langstr)", conn_get_socket(c));
544 return -1;
545 }
546
547 if (!(countrycode = packet_get_str_const(packet, sizeof(t_client_countryinfo1) + strlen(langstr) + 1, MAX_COUNTRYCODE_STR))) {
548 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long countrycode)", conn_get_socket(c));
549 return -1;
550 }
551
552 if (!(country = packet_get_str_const(packet, sizeof(t_client_countryinfo1) + strlen(langstr) + 1 + strlen(countrycode) + 1, MAX_COUNTRY_STR))) {
553 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long country)", conn_get_socket(c));
554 return -1;
555 }
556
557 if (!(packet_get_str_const(packet, sizeof(t_client_countryinfo1) + strlen(langstr) + 1 + strlen(countrycode) + 1 + strlen(country) + 1, MAX_COUNTRYNAME_STR))) {
558 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO1 packet (missing or too long countryname)", conn_get_socket(c));
559 return -1;
560 }
561
562 tzbias = bn_int_get(packet->u.client_countryinfo1.bias);
563 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] COUNTRYINFO1 packet from tzbias=0x%04x(%+d) langstr=%s countrycode=%s country=%s", tzbias, uint32_to_int(tzbias), conn_get_socket(c), langstr, countrycode, country);
564 conn_set_country(c, country);
565 conn_set_tzbias(c, uint32_to_int(tzbias));
566 }
567 return 0;
568 }
569
_client_countryinfo109(t_connection * c,t_packet const * const packet)570 static int _client_countryinfo109(t_connection * c, t_packet const *const packet)
571 {
572 t_packet *rpacket;
573
574 if (packet_get_size(packet) < sizeof(t_client_countryinfo_109)) {
575 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO_109 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_countryinfo_109), packet_get_size(packet));
576 return -1;
577 }
578
579 {
580 char const *langstr;
581 char const *countryname;
582 unsigned int tzbias;
583 char archtag_str[5];
584 char clienttag_str[5];
585 char gamelang_str[5];
586
587 if (!(langstr = packet_get_str_const(packet, sizeof(t_client_countryinfo_109), MAX_LANG_STR))) {
588 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO_109 packet (missing or too long langstr)", conn_get_socket(c));
589 return -1;
590 }
591
592 if (!(countryname = packet_get_str_const(packet, sizeof(t_client_countryinfo_109) + strlen(langstr) + 1, MAX_COUNTRYNAME_STR))) {
593 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad COUNTRYINFO_109 packet (missing or too long countryname)", conn_get_socket(c));
594 return -1;
595 }
596
597 /* check if it's an allowed client type */
598 if (_check_allowed_client(bn_int_get(packet->u.client_countryinfo_109.clienttag))) {
599 conn_set_state(c, conn_state_destroy);
600 return 0;
601 }
602
603 tzbias = bn_int_get(packet->u.client_countryinfo_109.bias);
604
605 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] COUNTRYINFO_109 packet tzbias=0x%04x(%+d) lcid=%u langid=%u arch=\"%s\" client=\"%s\" versionid=0x%08x gamelang=\"%s\"", conn_get_socket(c), tzbias, uint32_to_int(tzbias), bn_int_get(packet->u.client_countryinfo_109.lcid), bn_int_get(packet->u.client_countryinfo_109.langid), tag_uint_to_str(archtag_str, bn_int_get(packet->u.client_countryinfo_109.archtag)), tag_uint_to_str(clienttag_str, bn_int_get(packet->u.client_countryinfo_109.clienttag)), bn_int_get(packet->u.client_countryinfo_109.versionid), tag_uint_to_str(gamelang_str, bn_int_get(packet->u.client_countryinfo_109.gamelang)));
606
607 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] COUNTRYINFO_109 packet from \"%s\" \"%s\"", conn_get_socket(c), countryname, langstr);
608
609 conn_set_country(c, langstr); /* FIXME: This isn't right. We want USA not ENU (English-US) */
610 conn_set_tzbias(c, uint32_to_int(tzbias));
611 conn_set_versionid(c, bn_int_get(packet->u.client_countryinfo_109.versionid));
612 conn_set_archtag(c, bn_int_get(packet->u.client_countryinfo_109.archtag));
613 conn_set_clienttag(c, bn_int_get(packet->u.client_countryinfo_109.clienttag));
614 conn_set_gamelang(c, bn_int_get(packet->u.client_countryinfo_109.gamelang));
615
616 /* First, send an ECHO_REQ */
617
618 if ((rpacket = packet_create(packet_class_bnet))) {
619 packet_set_size(rpacket, sizeof(t_server_echoreq));
620 packet_set_type(rpacket, SERVER_ECHOREQ);
621 bn_int_set(&rpacket->u.server_echoreq.ticks, get_ticks());
622 conn_push_outqueue(c, rpacket);
623 packet_del_ref(rpacket);
624 }
625
626 if ((rpacket = packet_create(packet_class_bnet))) {
627 t_versioncheck *vc;
628
629 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selecting version check", conn_get_socket(c));
630 vc = versioncheck_create(conn_get_archtag(c), conn_get_clienttag(c));
631 conn_set_versioncheck(c, vc);
632 packet_set_size(rpacket, sizeof(t_server_authreq_109));
633 packet_set_type(rpacket, SERVER_AUTHREQ_109);
634
635 if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT))
636 bn_int_set(&rpacket->u.server_authreq_109.logontype, SERVER_AUTHREQ_109_LOGONTYPE_W3);
637 else if ((conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT))
638 bn_int_set(&rpacket->u.server_authreq_109.logontype, SERVER_AUTHREQ_109_LOGONTYPE_W3XP);
639 else
640 bn_int_set(&rpacket->u.server_authreq_109.logontype, SERVER_AUTHREQ_109_LOGONTYPE);
641
642 bn_int_set(&rpacket->u.server_authreq_109.sessionkey, conn_get_sessionkey(c));
643 bn_int_set(&rpacket->u.server_authreq_109.sessionnum, conn_get_sessionnum(c));
644 file_to_mod_time(versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq_109.timestamp);
645 packet_append_string(rpacket, versioncheck_get_mpqfile(vc));
646 packet_append_string(rpacket, versioncheck_get_eqn(vc));
647 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selected \"%s\" \"%s\"", conn_get_socket(c), versioncheck_get_mpqfile(vc), versioncheck_get_eqn(vc));
648 if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT)
649 || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT)) {
650 char padding[128];
651 memset(padding, 0, 128);
652 packet_append_data(rpacket, padding, 128);
653 }
654 conn_push_outqueue(c, rpacket);
655 packet_del_ref(rpacket);
656 }
657 }
658 return 0;
659 }
660
_client_unknown2b(t_connection * c,t_packet const * const packet)661 static int _client_unknown2b(t_connection * c, t_packet const *const packet)
662 {
663 if (packet_get_size(packet) < sizeof(t_client_unknown_2b)) {
664 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_2B packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_2b), packet_get_size(packet));
665 return -1;
666 }
667 return 0;
668 }
669
_client_progident(t_connection * c,t_packet const * const packet)670 static int _client_progident(t_connection * c, t_packet const *const packet)
671 {
672 t_packet *rpacket;
673
674 if (packet_get_size(packet) < sizeof(t_client_progident)) {
675 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROGIDENT packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_progident), packet_get_size(packet));
676 return -1;
677 }
678
679 if (_check_allowed_client(bn_int_get(packet->u.client_progident.clienttag))) {
680 conn_set_state(c, conn_state_destroy);
681 return 0;
682 }
683
684 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] CLIENT_PROGIDENT archtag=0x%08x clienttag=0x%08x versionid=0x%08x unknown1=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_progident.archtag), bn_int_get(packet->u.client_progident.clienttag), bn_int_get(packet->u.client_progident.versionid), bn_int_get(packet->u.client_progident.unknown1));
685
686 conn_set_archtag(c, bn_int_get(packet->u.client_progident.archtag));
687 conn_set_clienttag(c, bn_int_get(packet->u.client_progident.clienttag));
688
689 if (prefs_get_skip_versioncheck()) {
690 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] attempting to skip version check by sending early authreply", conn_get_socket(c));
691 /* skip over SERVER_AUTHREQ1 and CLIENT_AUTHREQ1 */
692 if ((rpacket = packet_create(packet_class_bnet))) {
693 packet_set_size(rpacket, sizeof(t_server_authreply1));
694 packet_set_type(rpacket, SERVER_AUTHREPLY1);
695 bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_OK);
696 packet_append_string(rpacket, "");
697 packet_append_string(rpacket, ""); /* FIXME: what's the second string for? */
698 conn_push_outqueue(c, rpacket);
699 packet_del_ref(rpacket);
700 }
701 } else {
702 t_versioncheck *vc;
703
704 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selecting version check", conn_get_socket(c));
705 vc = versioncheck_create(conn_get_archtag(c), conn_get_clienttag(c));
706 conn_set_versioncheck(c, vc);
707 if ((rpacket = packet_create(packet_class_bnet))) {
708 packet_set_size(rpacket, sizeof(t_server_authreq1));
709 packet_set_type(rpacket, SERVER_AUTHREQ1);
710 file_to_mod_time(versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq1.timestamp);
711 packet_append_string(rpacket, versioncheck_get_mpqfile(vc));
712 packet_append_string(rpacket, versioncheck_get_eqn(vc));
713 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selected \"%s\" \"%s\"", conn_get_socket(c), versioncheck_get_mpqfile(vc), versioncheck_get_eqn(vc));
714 conn_push_outqueue(c, rpacket);
715 packet_del_ref(rpacket);
716 }
717 }
718
719 return 0;
720 }
721
_client_createaccountw3(t_connection * c,t_packet const * const packet)722 static int _client_createaccountw3(t_connection * c, t_packet const *const packet)
723 {
724 t_packet *rpacket;
725 char const *username;
726 char const *plainpass;
727 char upass[20];
728 char lpass[20];
729 t_hash sc_hash;
730 unsigned int i;
731
732 if (packet_get_size(packet) < sizeof(t_client_createaccount_w3)) {
733 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCOUNT_W3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_createaccount_w3), packet_get_size(packet));
734 return -1;
735 }
736
737 username = packet_get_str_const(packet, sizeof(t_client_createaccount_w3), UNCHECKED_NAME_STR);
738 if (!username) {
739 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCOUNT_W3 (missing or too long username)", conn_get_socket(c));
740 return -1;
741 }
742
743 plainpass = packet_get_str_const(packet, 4 + 8 * 4, 16);
744 if (!plainpass) {
745 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCOUNT_W3 (missing password)", conn_get_socket(c));
746 return -1;
747 }
748
749 rpacket = packet_create(packet_class_bnet);
750 if (!rpacket)
751 return -1;
752 packet_set_size(rpacket, sizeof(t_server_createaccount_w3));
753 packet_set_type(rpacket, SERVER_CREATEACCOUNT_W3);
754
755 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] new account requested for \"%s\"", conn_get_socket(c), username);
756
757 if (prefs_get_allow_new_accounts() == 0) {
758 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (disabled)", conn_get_socket(c));
759 bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_EXIST);
760 goto out;
761 }
762
763 if (account_check_name(username) < 0) {
764 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (invalid symbols)", conn_get_socket(c));
765 bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_INVALID);
766 goto out;
767 }
768
769 /* convert plaintext password to uppercase */
770 strncpy(upass, plainpass, 16);
771 upass[16] = 0;
772 for (i = 0; i < strlen(upass); i++)
773 if (isascii((int) upass[i]) && islower((int) upass[i]))
774 upass[i] = toupper((int) upass[i]);
775
776 /* convert plaintext password to lowercase for sc etc. */
777 strncpy(lpass, plainpass, 16);
778 lpass[16] = 0;
779 for (i = 0; i < strlen(lpass); i++)
780 if (isascii((int) lpass[i]) && isupper((int) lpass[i]))
781 lpass[i] = tolower((int) lpass[i]);
782
783
784 //set password hash for sc etc.
785 bnet_hash(&sc_hash, strlen(lpass), lpass);
786 if (!accountlist_create_account(username, hash_get_str(sc_hash)))
787 bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_EXIST);
788 else {
789 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account created", conn_get_socket(c));
790 bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCOUNT_W3_RESULT_OK);
791 }
792
793 out:
794 conn_push_outqueue(c, rpacket);
795 packet_del_ref(rpacket);
796
797 return 0;
798 }
799
_client_createacctreq1(t_connection * c,t_packet const * const packet)800 static int _client_createacctreq1(t_connection * c, t_packet const *const packet)
801 {
802 t_packet *rpacket;
803 char const *username;
804 t_hash newpasshash1;
805
806 if (packet_get_size(packet) < sizeof(t_client_createacctreq1)) {
807 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCTREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_createacctreq1), packet_get_size(packet));
808 return -1;
809 }
810
811 if (!(username = packet_get_str_const(packet, sizeof(t_client_createacctreq1), UNCHECKED_NAME_STR))) {
812 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCTREQ1 (missing or too long username)", conn_get_socket(c));
813 return -1;
814 }
815
816 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] new account requested for \"%s\"", conn_get_socket(c), username);
817
818 rpacket = packet_create(packet_class_bnet);
819 if (!rpacket)
820 return -1;
821 packet_set_size(rpacket, sizeof(t_server_createacctreply1));
822 packet_set_type(rpacket, SERVER_CREATEACCTREPLY1);
823
824 if (prefs_get_allow_new_accounts() == 0) {
825 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (disabled)", conn_get_socket(c));
826 bn_int_set(&rpacket->u.server_createacctreply1.result, SERVER_CREATEACCTREPLY1_RESULT_NO);
827 goto out;
828 }
829
830 bnhash_to_hash(packet->u.client_createacctreq1.password_hash1, &newpasshash1);
831 if (!accountlist_create_account(username, hash_get_str(newpasshash1))) {
832 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (failed)", conn_get_socket(c));
833 bn_int_set(&rpacket->u.server_createacctreply1.result, SERVER_CREATEACCTREPLY1_RESULT_NO);
834 goto out;
835 }
836
837 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account created", conn_get_socket(c));
838 bn_int_set(&rpacket->u.server_createacctreply1.result, SERVER_CREATEACCTREPLY1_RESULT_OK);
839
840 out:
841 conn_push_outqueue(c, rpacket);
842 packet_del_ref(rpacket);
843
844 return 0;
845 }
846
_client_createacctreq2(t_connection * c,t_packet const * const packet)847 static int _client_createacctreq2(t_connection * c, t_packet const *const packet)
848 {
849 t_packet *rpacket;
850 char const *username;
851 t_hash newpasshash1;
852
853 if (packet_get_size(packet) < sizeof(t_client_createacctreq2)) {
854 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_CREATEACCTREQ2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_createacctreq2), packet_get_size(packet));
855 return -1;
856 }
857
858 username = packet_get_str_const(packet, sizeof(t_client_createacctreq2), UNCHECKED_NAME_STR);
859 if (!username) {
860 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CREATEACCTREQ2 (missing or too long username)", conn_get_socket(c));
861 return -1;
862 }
863
864 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] new account requested for \"%s\"", conn_get_socket(c), username);
865
866 rpacket = packet_create(packet_class_bnet);
867 if (!rpacket)
868 return -1;
869 packet_set_size(rpacket, sizeof(t_server_createacctreply2));
870 packet_set_type(rpacket, SERVER_CREATEACCTREPLY2);
871
872 if (prefs_get_allow_new_accounts() == 0) {
873 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (disabled)", conn_get_socket(c));
874 bn_int_set(&rpacket->u.server_createacctreply2.result, SERVER_CREATEACCTREPLY2_RESULT_EXIST);
875 goto out;
876 }
877
878 if (account_check_name(username) < 0) {
879 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (invalid symbols)", conn_get_socket(c));
880 bn_int_set(&rpacket->u.server_createaccount_w3.result, SERVER_CREATEACCTREPLY2_RESULT_INVALID);
881 goto out;
882 }
883
884 bnhash_to_hash(packet->u.client_createacctreq2.password_hash1, &newpasshash1);
885 if (!accountlist_create_account(username, hash_get_str(newpasshash1))) {
886 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account not created (failed)", conn_get_socket(c));
887 bn_int_set(&rpacket->u.server_createacctreply2.result, SERVER_CREATEACCTREPLY2_RESULT_EXIST); /* FIXME: return reason for failure */
888 goto out;
889 }
890
891 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account created", conn_get_socket(c));
892 bn_int_set(&rpacket->u.server_createacctreply2.result, SERVER_CREATEACCTREPLY2_RESULT_OK);
893
894 out:
895 conn_push_outqueue(c, rpacket);
896 packet_del_ref(rpacket);
897
898 return 0;
899 }
900
_client_changepassreq(t_connection * c,t_packet const * const packet)901 static int _client_changepassreq(t_connection * c, t_packet const *const packet)
902 {
903 t_packet *rpacket;
904
905 if (packet_get_size(packet) < sizeof(t_client_changepassreq)) {
906 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CHANGEPASSREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_changepassreq), packet_get_size(packet));
907 return -1;
908 }
909
910 {
911 char const *username;
912 t_account *account;
913
914 if (!(username = packet_get_str_const(packet, sizeof(t_client_changepassreq), UNCHECKED_NAME_STR))) {
915 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CHANGEPASSREQ (missing or too long username)", conn_get_socket(c));
916 return -1;
917 }
918
919 eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change requested for \"%s\"", conn_get_socket(c), username);
920
921 if (!(rpacket = packet_create(packet_class_bnet)))
922 return -1;
923 packet_set_size(rpacket, sizeof(t_server_changepassack));
924 packet_set_type(rpacket, SERVER_CHANGEPASSACK);
925
926 /* fail if logged in or no account */
927 if (connlist_find_connection_by_accountname(username) || !(account = accountlist_find_account(username))) {
928 eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (no such account)", conn_get_socket(c), username);
929 bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL);
930 } else if (account_get_auth_changepass(account) == 0) { /* default to true */
931 eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (no change access)", conn_get_socket(c), username);
932 bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL);
933 } else if (conn_get_sessionkey(c) != bn_int_get(packet->u.client_changepassreq.sessionkey)) {
934 eventlog(eventlog_level_error, __FUNCTION__, "[%d] password change for \"%s\" refused (expected session key 0x%08x, got 0x%08x)", conn_get_socket(c), username, conn_get_sessionkey(c), bn_int_get(packet->u.client_changepassreq.sessionkey));
935 bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL);
936 } else {
937 struct {
938 bn_int ticks;
939 bn_int sessionkey;
940 bn_int passhash1[5];
941 } temp;
942 char const *oldstrhash1;
943 t_hash oldpasshash1;
944 t_hash oldpasshash2;
945 t_hash trypasshash2;
946 t_hash newpasshash1;
947
948
949 if ((oldstrhash1 = account_get_pass(account))) {
950 bn_int_set(&temp.ticks, bn_int_get(packet->u.client_changepassreq.ticks));
951 bn_int_set(&temp.sessionkey, bn_int_get(packet->u.client_changepassreq.sessionkey));
952 if (hash_set_str(&oldpasshash1, oldstrhash1) < 0) {
953 bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1);
954 account_set_pass(account, hash_get_str(newpasshash1));
955 eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (bad previous password)", conn_get_socket(c), account_get_name(account));
956 bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS);
957 } else {
958 hash_to_bnhash((t_hash const *) &oldpasshash1, temp.passhash1); /* avoid warning */
959 bnet_hash(&oldpasshash2, sizeof(temp), &temp); /* do the double hash */
960 bnhash_to_hash(packet->u.client_changepassreq.oldpassword_hash2, &trypasshash2);
961
962 if (hash_eq(trypasshash2, oldpasshash2) == 1) {
963 bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1);
964 account_set_pass(account, hash_get_str(newpasshash1));
965 eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (previous password)", conn_get_socket(c), account_get_name(account));
966 bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS);
967 } else {
968 eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" refused (wrong password)", conn_get_socket(c), account_get_name(account));
969 conn_increment_passfail_count(c);
970 bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_FAIL);
971 }
972 }
973 } else {
974 bnhash_to_hash(packet->u.client_changepassreq.newpassword_hash1, &newpasshash1);
975 account_set_pass(account, hash_get_str(newpasshash1));
976 eventlog(eventlog_level_info, __FUNCTION__, "[%d] password change for \"%s\" successful (no previous password)", conn_get_socket(c), account_get_name(account));
977 bn_int_set(&rpacket->u.server_changepassack.message, SERVER_CHANGEPASSACK_MESSAGE_SUCCESS);
978 }
979 }
980
981 conn_push_outqueue(c, rpacket);
982 packet_del_ref(rpacket);
983
984 }
985
986 return 0;
987 }
988
_client_echoreply(t_connection * c,t_packet const * const packet)989 static int _client_echoreply(t_connection * c, t_packet const *const packet)
990 {
991 if (packet_get_size(packet) < sizeof(t_client_echoreply)) {
992 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ECHOREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_echoreply), packet_get_size(packet));
993 return -1;
994 }
995
996 {
997 unsigned int now;
998 unsigned int then;
999
1000 now = get_ticks();
1001 then = bn_int_get(packet->u.client_echoreply.ticks);
1002 if (!now || !then || now < then)
1003 eventlog(eventlog_level_warn, __FUNCTION__, "[%d] bad timing in echo reply: now=%u then=%u", conn_get_socket(c), now, then);
1004 else
1005 conn_set_latency(c, now - then);
1006 }
1007
1008 return 0;
1009 }
1010
_client_authreq1(t_connection * c,t_packet const * const packet)1011 static int _client_authreq1(t_connection * c, t_packet const *const packet)
1012 {
1013 t_packet *rpacket;
1014
1015 if (packet_get_size(packet) < sizeof(t_client_authreq1)) {
1016 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_authreq1), packet_get_size(packet));
1017 return -1;
1018 }
1019
1020 {
1021 char verstr[16];
1022 char const *exeinfo;
1023 char const *versiontag;
1024 int failed;
1025
1026 failed = 0;
1027 if (bn_int_get(packet->u.client_authreq1.archtag) != conn_get_archtag(c))
1028 failed = 1;
1029 if (bn_int_get(packet->u.client_authreq1.clienttag) != conn_get_clienttag(c))
1030 failed = 1;
1031
1032 if (!(exeinfo = packet_get_str_const(packet, sizeof(t_client_authreq1), MAX_EXEINFO_STR))) {
1033 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ1 (missing or too long exeinfo)", conn_get_socket(c));
1034 exeinfo = "badexe";
1035 failed = 1;
1036 }
1037 conn_set_versionid(c, bn_int_get(packet->u.client_authreq1.versionid));
1038 conn_set_checksum(c, bn_int_get(packet->u.client_authreq1.checksum));
1039 conn_set_gameversion(c, bn_int_get(packet->u.client_authreq1.gameversion));
1040 strcpy(verstr, vernum_to_verstr(bn_int_get(packet->u.client_authreq1.gameversion)));
1041 conn_set_clientver(c, verstr);
1042 conn_set_clientexe(c, exeinfo);
1043
1044 eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_AUTHREQ1 archtag=0x%08x clienttag=0x%08x verstr=%s exeinfo=\"%s\" versionid=0x%08lx gameversion=0x%08lx checksum=0x%08lx", conn_get_socket(c), bn_int_get(packet->u.client_authreq1.archtag), bn_int_get(packet->u.client_authreq1.clienttag), verstr, exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c));
1045
1046
1047 if ((rpacket = packet_create(packet_class_bnet))) {
1048 packet_set_size(rpacket, sizeof(t_server_authreply1));
1049 packet_set_type(rpacket, SERVER_AUTHREPLY1);
1050
1051
1052 if (!conn_get_versioncheck(c) && prefs_get_skip_versioncheck())
1053 eventlog(eventlog_level_info, __FUNCTION__, "[%d] skip versioncheck enabled and client did not request validation", conn_get_socket(c));
1054 else
1055 switch (versioncheck_validate(conn_get_versioncheck(c), conn_get_archtag(c), conn_get_clienttag(c), exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) {
1056 case -1: /* failed test... client has been modified */
1057 if (!prefs_get_allow_bad_version()) {
1058 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test (marking untrusted)", conn_get_socket(c));
1059 failed = 1;
1060 } else
1061 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test, allowing anyway", conn_get_socket(c));
1062 break;
1063 case 0: /* not listed in table... can't tell if client has been modified */
1064 if (!prefs_get_allow_unknown_version()) {
1065 eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client (marking untrusted)", conn_get_socket(c));
1066 failed = 1;
1067 } else
1068 eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client, allowing anyway", conn_get_socket(c));
1069 break;
1070 /* 1 == test passed... client seems to be ok */
1071 }
1072
1073 versiontag = versioncheck_get_versiontag(conn_get_versioncheck(c));
1074
1075 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client matches versiontag \"%s\"", conn_get_socket(c), versiontag);
1076
1077 if (failed) {
1078 conn_set_state(c, conn_state_untrusted);
1079 bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_BADVERSION);
1080 packet_append_string(rpacket, "");
1081 } else {
1082 char *mpqfilename;
1083
1084 mpqfilename = autoupdate_check(conn_get_archtag(c), conn_get_clienttag(c), conn_get_gamelang(c), versiontag);
1085
1086 /* Only handle updates when there is an update file available. */
1087 if (mpqfilename != NULL) {
1088 eventlog(eventlog_level_info, __FUNCTION__, "[%d] an upgrade for version %s is available \"%s\"", conn_get_socket(c), versioncheck_get_versiontag(conn_get_versioncheck(c)), mpqfilename);
1089 bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_UPDATE);
1090 packet_append_string(rpacket, mpqfilename);
1091 } else {
1092 eventlog(eventlog_level_info, __FUNCTION__, "[%d] no upgrade for %s is available", conn_get_socket(c), versioncheck_get_versiontag(conn_get_versioncheck(c)));
1093 bn_int_set(&rpacket->u.server_authreply1.message, SERVER_AUTHREPLY1_MESSAGE_OK);
1094 packet_append_string(rpacket, "");
1095 }
1096
1097 if (mpqfilename)
1098 xfree((void *) mpqfilename);
1099 }
1100
1101 packet_append_string(rpacket, ""); /* FIXME: what's the second string for? */
1102 conn_push_outqueue(c, rpacket);
1103 packet_del_ref(rpacket);
1104 }
1105 }
1106
1107 return 0;
1108 }
1109
_client_authreq109(t_connection * c,t_packet const * const packet)1110 static int _client_authreq109(t_connection * c, t_packet const *const packet)
1111 {
1112 t_packet *rpacket;
1113
1114 if (packet_get_size(packet) < sizeof(t_client_authreq_109)) {
1115 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_authreq_109), packet_get_size(packet));
1116 return 0;
1117 }
1118
1119 {
1120 char verstr[16];
1121 char const *exeinfo;
1122 char const *versiontag;
1123 int failed;
1124 char const *owner;
1125 unsigned int count;
1126 unsigned int pos;
1127
1128 failed = 0;
1129 count = bn_int_get(packet->u.client_authreq_109.cdkey_number);
1130 pos = sizeof(t_client_authreq_109) + (count * sizeof(t_cdkey_info));
1131
1132 if (!(exeinfo = packet_get_str_const(packet, pos, MAX_EXEINFO_STR))) {
1133 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 (missing or too long exeinfo)", conn_get_socket(c));
1134 exeinfo = "badexe";
1135 failed = 1;
1136 }
1137 conn_set_clientexe(c, exeinfo);
1138 pos += strlen(exeinfo) + 1;
1139
1140 if (!(owner = packet_get_str_const(packet, pos, MAX_OWNER_STR))) {
1141 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad AUTHREQ_109 (missing or too long owner)", conn_get_socket(c));
1142 owner = ""; /* maybe owner was missing, use empty string */
1143 }
1144 conn_set_owner(c, owner);
1145
1146 conn_set_checksum(c, bn_int_get(packet->u.client_authreq_109.checksum));
1147 conn_set_gameversion(c, bn_int_get(packet->u.client_authreq_109.gameversion));
1148 strcpy(verstr, vernum_to_verstr(bn_int_get(packet->u.client_authreq_109.gameversion)));
1149 conn_set_clientver(c, verstr);
1150 conn_set_clientexe(c, exeinfo);
1151
1152 eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_AUTHREQ_109 ticks=0x%08x, verstr=%s exeinfo=\"%s\" versionid=0x%08lx gameversion=0x%08lx checksum=0x%08lx", conn_get_socket(c), bn_int_get(packet->u.client_authreq_109.ticks), verstr, exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c));
1153
1154 if ((rpacket = packet_create(packet_class_bnet))) {
1155 packet_set_size(rpacket, sizeof(t_server_authreply_109));
1156 packet_set_type(rpacket, SERVER_AUTHREPLY_109);
1157
1158
1159 if (!conn_get_versioncheck(c) && prefs_get_skip_versioncheck())
1160 eventlog(eventlog_level_info, __FUNCTION__, "[%d] skip versioncheck enabled and client did not request validation", conn_get_socket(c));
1161 else
1162 switch (versioncheck_validate(conn_get_versioncheck(c), conn_get_archtag(c), conn_get_clienttag(c), exeinfo, conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) {
1163 case -1: /* failed test... client has been modified */
1164 if (!prefs_get_allow_bad_version()) {
1165 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test (closing connection)", conn_get_socket(c));
1166 failed = 1;
1167 } else
1168 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client failed test, allowing anyway", conn_get_socket(c));
1169 break;
1170 case 0: /* not listed in table... can't tell if client has been modified */
1171 if (!prefs_get_allow_unknown_version()) {
1172 eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client (closing connection)", conn_get_socket(c));
1173 failed = 1;
1174 } else
1175 eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to test client, allowing anyway", conn_get_socket(c));
1176 break;
1177 /* 1 == test passed... client seems to be ok */
1178 }
1179
1180 versiontag = versioncheck_get_versiontag(conn_get_versioncheck(c));
1181
1182 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client matches versiontag \"%s\"", conn_get_socket(c), versiontag);
1183
1184 if (failed) {
1185 conn_set_state(c, conn_state_untrusted);
1186 bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_BADVERSION);
1187 packet_append_string(rpacket, "");
1188 } else {
1189 char *mpqfilename;
1190
1191 mpqfilename = autoupdate_check(conn_get_archtag(c), conn_get_clienttag(c), conn_get_gamelang(c), versiontag);
1192
1193 /* Only handle updates when there is an update file available. */
1194 if (mpqfilename != NULL) {
1195 eventlog(eventlog_level_info, __FUNCTION__, "[%d] an upgrade for %s is available \"%s\"", conn_get_socket(c), versiontag, mpqfilename);
1196 bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_UPDATE);
1197 packet_append_string(rpacket, mpqfilename);
1198 } else {
1199 eventlog(eventlog_level_info, __FUNCTION__, "[%d] no upgrade for %s is available", conn_get_socket(c), versiontag);
1200 bn_int_set(&rpacket->u.server_authreply_109.message, SERVER_AUTHREPLY_109_MESSAGE_OK);
1201 packet_append_string(rpacket, "");
1202 }
1203 if (mpqfilename)
1204 xfree((void *) mpqfilename);
1205 }
1206
1207 conn_push_outqueue(c, rpacket);
1208 packet_del_ref(rpacket);
1209 }
1210 }
1211
1212 return 0;
1213 }
1214
_client_regsnoopreply(t_connection * c,t_packet const * const packet)1215 static int _client_regsnoopreply(t_connection * c, t_packet const *const packet)
1216 {
1217 if (packet_get_size(packet) < sizeof(t_client_regsnoopreply)) {
1218 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REGSNOOPREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_regsnoopreply), packet_get_size(packet));
1219 return -1;
1220 }
1221 return 0;
1222 }
1223
_client_iconreq(t_connection * c,t_packet const * const packet)1224 static int _client_iconreq(t_connection * c, t_packet const *const packet)
1225 {
1226 t_packet *rpacket;
1227
1228 if (packet_get_size(packet) < sizeof(t_client_iconreq)) {
1229 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ICONREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_iconreq), packet_get_size(packet));
1230 return -1;
1231 }
1232
1233 if ((rpacket = packet_create(packet_class_bnet))) {
1234 packet_set_size(rpacket, sizeof(t_server_iconreply));
1235 packet_set_type(rpacket, SERVER_ICONREPLY);
1236 file_to_mod_time(prefs_get_iconfile(), &rpacket->u.server_iconreply.timestamp);
1237
1238 /* battle.net sends different file on iconreq for WAR3 and W3XP [Omega] */
1239 if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT))
1240 packet_append_string(rpacket, prefs_get_war3_iconfile());
1241 /* battle.net still sends "icons.bni" to sc/bw clients
1242 * clients request icons_STAR.bni seperatly */
1243 /* else if (strcmp(conn_get_clienttag(c),CLIENTTAG_STARCRAFT)==0)
1244 packet_append_string(rpacket,prefs_get_star_iconfile());
1245 else if (strcmp(conn_get_clienttag(c),CLIENTTAG_BROODWARS)==0)
1246 packet_append_string(rpacket,prefs_get_star_iconfile());
1247 */
1248 else
1249 packet_append_string(rpacket, prefs_get_iconfile());
1250
1251 conn_push_outqueue(c, rpacket);
1252 packet_del_ref(rpacket);
1253 }
1254
1255 return 0;
1256 }
1257
_client_cdkey(t_connection * c,t_packet const * const packet)1258 static int _client_cdkey(t_connection * c, t_packet const *const packet)
1259 {
1260 t_packet *rpacket;
1261
1262 if (packet_get_size(packet) < sizeof(t_client_cdkey)) {
1263 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_cdkey), packet_get_size(packet));
1264 return -1;
1265 }
1266
1267 {
1268 char const *cdkey;
1269 char const *owner;
1270
1271 if (!(cdkey = packet_get_str_const(packet, sizeof(t_client_cdkey), MAX_CDKEY_STR))) {
1272 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY packet (missing or too long cdkey)", conn_get_socket(c));
1273 return -1;
1274 }
1275 if (!(owner = packet_get_str_const(packet, sizeof(t_client_cdkey) + strlen(cdkey) + 1, MAX_OWNER_STR))) {
1276 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY packet (missing or too long owner)", conn_get_socket(c));
1277 return -1;
1278 }
1279
1280 conn_set_cdkey(c, cdkey);
1281 conn_set_owner(c, owner);
1282
1283 if ((rpacket = packet_create(packet_class_bnet))) {
1284 packet_set_size(rpacket, sizeof(t_server_cdkeyreply));
1285 packet_set_type(rpacket, SERVER_CDKEYREPLY);
1286 bn_int_set(&rpacket->u.server_cdkeyreply.message, SERVER_CDKEYREPLY_MESSAGE_OK);
1287 packet_append_string(rpacket, owner);
1288 conn_push_outqueue(c, rpacket);
1289 packet_del_ref(rpacket);
1290 }
1291 }
1292 #if 0 /* Blizzard used this to track down pirates, should only be accepted by old clients */
1293 if ((rpacket = packet_create(packet_class_bnet))) {
1294 packet_set_size(rpacket, sizeof(t_server_regsnoopreq));
1295 packet_set_type(rpacket, SERVER_REGSNOOPREQ);
1296 bn_int_set(&rpacket->u.server_regsnoopreq.unknown1, SERVER_REGSNOOPREQ_UNKNOWN1); /* sequence num */
1297 bn_int_set(&rpacket->u.server_regsnoopreq.hkey, SERVER_REGSNOOPREQ_HKEY_CURRENT_USER);
1298 packet_append_string(rpacket, SERVER_REGSNOOPREQ_REGKEY);
1299 packet_append_string(rpacket, SERVER_REGSNOOPREQ_REGVALNAME);
1300 conn_push_outqueue(c, rpacket);
1301 packet_del_ref(rpacket);
1302 }
1303 #endif
1304 return 0;
1305 }
1306
_client_cdkey2(t_connection * c,t_packet const * const packet)1307 static int _client_cdkey2(t_connection * c, t_packet const *const packet)
1308 {
1309 t_packet *rpacket;
1310
1311 if (packet_get_size(packet) < sizeof(t_client_cdkey2)) {
1312 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_cdkey2), packet_get_size(packet));
1313 return -1;
1314 }
1315
1316 {
1317 char const *owner;
1318
1319 if (!(owner = packet_get_str_const(packet, sizeof(t_client_cdkey2), MAX_OWNER_STR))) {
1320 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY2 packet (missing or too long owner)", conn_get_socket(c));
1321 return -1;
1322 }
1323
1324 conn_set_owner(c, owner);
1325
1326 if ((rpacket = packet_create(packet_class_bnet))) {
1327 packet_set_size(rpacket, sizeof(t_server_cdkeyreply2));
1328 packet_set_type(rpacket, SERVER_CDKEYREPLY2);
1329 bn_int_set(&rpacket->u.server_cdkeyreply2.message, SERVER_CDKEYREPLY2_MESSAGE_OK);
1330 packet_append_string(rpacket, owner);
1331 conn_push_outqueue(c, rpacket);
1332 packet_del_ref(rpacket);
1333 }
1334 }
1335
1336 return 0;
1337 }
1338
_client_cdkey3(t_connection * c,t_packet const * const packet)1339 static int _client_cdkey3(t_connection * c, t_packet const *const packet)
1340 {
1341 t_packet *rpacket;
1342
1343 if (packet_get_size(packet) < sizeof(t_client_cdkey3)) {
1344 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_cdkey2), packet_get_size(packet));
1345 return -1;
1346 }
1347
1348 {
1349 char const *owner;
1350
1351 if (!(owner = packet_get_str_const(packet, sizeof(t_client_cdkey3), MAX_OWNER_STR))) {
1352 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CDKEY3 packet (missing or too long owner)", conn_get_socket(c));
1353 return -1;
1354 }
1355
1356 conn_set_owner(c, owner);
1357
1358 if ((rpacket = packet_create(packet_class_bnet))) {
1359 packet_set_size(rpacket, sizeof(t_server_cdkeyreply3));
1360 packet_set_type(rpacket, SERVER_CDKEYREPLY3);
1361 bn_int_set(&rpacket->u.server_cdkeyreply3.message, SERVER_CDKEYREPLY3_MESSAGE_OK);
1362 packet_append_string(rpacket, ""); /* FIXME: owner, message, ??? */
1363 conn_push_outqueue(c, rpacket);
1364 packet_del_ref(rpacket);
1365 }
1366 }
1367
1368 return 0;
1369 }
1370
_client_udpok(t_connection * c,t_packet const * const packet)1371 static int _client_udpok(t_connection * c, t_packet const *const packet)
1372 {
1373 if (packet_get_size(packet) < sizeof(t_client_udpok)) {
1374 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UDPOK packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_udpok), packet_get_size(packet));
1375 return -1;
1376 }
1377 /* we could check the contents but there really isn't any point */
1378 conn_set_udpok(c);
1379
1380 return 0;
1381 }
1382
_client_fileinforeq(t_connection * c,t_packet const * const packet)1383 static int _client_fileinforeq(t_connection * c, t_packet const *const packet)
1384 {
1385 t_packet *rpacket;
1386
1387 if (packet_get_size(packet) < sizeof(t_client_fileinforeq)) {
1388 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FILEINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_fileinforeq), packet_get_size(packet));
1389 return -1;
1390 }
1391
1392 {
1393 char const *tosfile;
1394
1395 if (!(tosfile = packet_get_str_const(packet, sizeof(t_client_fileinforeq), MAX_FILENAME_STR))) {
1396 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FILEINFOREQ packet (missing or too long tosfile)", conn_get_socket(c));
1397 return -1;
1398 }
1399 eventlog(eventlog_level_info, __FUNCTION__, "[%d] TOS requested: \"%s\" - type = 0x%02x", conn_get_socket(c), tosfile, bn_int_get(packet->u.client_fileinforeq.type));
1400
1401 /* TODO: if type is TOSFILE make bnetd to send default tosfile if selected is not found */
1402 if ((rpacket = packet_create(packet_class_bnet))) {
1403 packet_set_size(rpacket, sizeof(t_server_fileinforeply));
1404 packet_set_type(rpacket, SERVER_FILEINFOREPLY);
1405 bn_int_set(&rpacket->u.server_fileinforeply.type, bn_int_get(packet->u.client_fileinforeq.type));
1406 bn_int_set(&rpacket->u.server_fileinforeply.unknown2, bn_int_get(packet->u.client_fileinforeq.unknown2));
1407 /* Note from Sherpya:
1408 * timestamp -> 0x852b7d00 - 0x01c0e863 b.net send this (bn_int),
1409 * I suppose is not a long
1410 * if bnserver-D2DV is bad diablo 2 crashes
1411 * timestamp doesn't work correctly and starcraft
1412 * needs name in client locale or displays hostname
1413 */
1414 file_to_mod_time(tosfile, &rpacket->u.server_fileinforeply.timestamp);
1415 packet_append_string(rpacket, tosfile);
1416 conn_push_outqueue(c, rpacket);
1417 packet_del_ref(rpacket);
1418 }
1419 }
1420
1421 return 0;
1422 }
1423
_attribute_req(t_account * reqacc,t_account * myacc,const char * key)1424 static const char *_attribute_req(t_account * reqacc, t_account * myacc, const char *key)
1425 {
1426 const char *result = "";
1427 const char *tval;
1428
1429 if (!reqacc)
1430 goto out;
1431 if (reqacc != myacc && !strncasecmp(key, "BNET", 4))
1432 goto out;
1433
1434 tval = account_get_strattr(reqacc, key);
1435 if (tval)
1436 result = tval;
1437
1438 out:
1439 return result;
1440 }
1441
_client_statsreq(t_connection * c,t_packet const * const packet)1442 static int _client_statsreq(t_connection * c, t_packet const *const packet)
1443 {
1444 t_packet *rpacket;
1445 char const *name;
1446 char const *key;
1447 unsigned int name_count;
1448 unsigned int key_count;
1449 unsigned int i, j;
1450 unsigned int name_off;
1451 unsigned int keys_off;
1452 unsigned int key_off;
1453 t_account *reqacc, *myacc;
1454
1455 if (packet_get_size(packet) < sizeof(t_client_statsreq)) {
1456 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_statsreq), packet_get_size(packet));
1457 return -1;
1458 }
1459
1460 name_count = bn_int_get(packet->u.client_statsreq.name_count);
1461 key_count = bn_int_get(packet->u.client_statsreq.key_count);
1462
1463 for (i = 0, name_off = sizeof(t_client_statsreq); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1);
1464
1465 if (i < name_count) {
1466 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSREQ packet (only %u names of %u)", conn_get_socket(c), i, name_count);
1467 return -1;
1468 }
1469 keys_off = name_off;
1470
1471 if (!(rpacket = packet_create(packet_class_bnet)))
1472 return -1;
1473
1474 packet_set_size(rpacket, sizeof(t_server_statsreply));
1475 packet_set_type(rpacket, SERVER_STATSREPLY);
1476 bn_int_set(&rpacket->u.server_statsreply.name_count, name_count);
1477 bn_int_set(&rpacket->u.server_statsreply.key_count, key_count);
1478 bn_int_set(&rpacket->u.server_statsreply.requestid, bn_int_get(packet->u.client_statsreq.requestid));
1479
1480 myacc = conn_get_account(c);
1481
1482 for (i = 0, name_off = sizeof(t_client_statsreq); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1) {
1483 reqacc = accountlist_find_account(name);
1484 if (!reqacc)
1485 reqacc = myacc;
1486
1487 for (j = 0, key_off = keys_off; j < key_count && (key = packet_get_str_const(packet, key_off, MAX_ATTRKEY_STR)); j++, key_off += strlen(key) + 1) {
1488 if (*key == '\0')
1489 continue;
1490 packet_append_string(rpacket, _attribute_req(reqacc, myacc, key));
1491 }
1492 }
1493
1494 conn_push_outqueue(c, rpacket);
1495 packet_del_ref(rpacket);
1496
1497 return 0;
1498 }
1499
_client_loginreq1(t_connection * c,t_packet const * const packet)1500 static int _client_loginreq1(t_connection * c, t_packet const *const packet)
1501 {
1502 t_packet *rpacket;
1503
1504 if (packet_get_size(packet) < sizeof(t_client_loginreq1)) {
1505 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_loginreq1), packet_get_size(packet));
1506 return -1;
1507 }
1508
1509 {
1510 char const *username;
1511 t_account *account;
1512
1513 if (!(username = packet_get_str_const(packet, sizeof(t_client_loginreq1), USER_NAME_MAX))) {
1514 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ1 (missing or too long username)", conn_get_socket(c));
1515 return -1;
1516 }
1517
1518 if (!(rpacket = packet_create(packet_class_bnet)))
1519 return -1;
1520 packet_set_size(rpacket, sizeof(t_server_loginreply1));
1521 packet_set_type(rpacket, SERVER_LOGINREPLY1);
1522
1523 // too many logins? [added by NonReal]
1524 if (prefs_get_max_concurrent_logins() > 0) {
1525 if (prefs_get_max_concurrent_logins() <= connlist_login_get_length()) {
1526 eventlog(eventlog_level_error, __FUNCTION__, "[%d] login denied, too many concurrent logins. max: %d. current: %d.", conn_get_socket(c), prefs_get_max_concurrent_logins(), connlist_login_get_length());
1527 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1528 return -1;
1529 }
1530 }
1531
1532 /* fail if no account */
1533 if (!(account = accountlist_find_account(username))) {
1534 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no such account)", conn_get_socket(c), username);
1535 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1536 } else
1537 /* already logged in */
1538 if (connlist_find_connection_by_account(account) && prefs_get_kick_old_login() == 0) {
1539 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (already logged in)", conn_get_socket(c), username);
1540 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1541 } else if (account_get_auth_bnetlogin(account) == 0) { /* default to true */
1542 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no bnet access)", conn_get_socket(c), username);
1543 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1544 } else if (account_get_auth_lock(account) == 1) { /* default to false */
1545 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (this account is locked)", conn_get_socket(c), username);
1546 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1547 } else if (conn_get_sessionkey(c) != bn_int_get(packet->u.client_loginreq1.sessionkey)) {
1548 eventlog(eventlog_level_error, __FUNCTION__, "[%d] login for \"%s\" refused (expected session key 0x%08x, got 0x%08x)", conn_get_socket(c), username, conn_get_sessionkey(c), bn_int_get(packet->u.client_loginreq1.sessionkey));
1549 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1550 } else {
1551 struct {
1552 bn_int ticks;
1553 bn_int sessionkey;
1554 bn_int passhash1[5];
1555 } temp;
1556 char const *oldstrhash1;
1557 t_hash oldpasshash1;
1558 t_hash oldpasshash2;
1559 t_hash trypasshash2;
1560
1561 if ((oldstrhash1 = account_get_pass(account))) {
1562 bn_int_set(&temp.ticks, bn_int_get(packet->u.client_loginreq1.ticks));
1563 bn_int_set(&temp.sessionkey, bn_int_get(packet->u.client_loginreq1.sessionkey));
1564 if (hash_set_str(&oldpasshash1, oldstrhash1) < 0) {
1565 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (corrupted passhash1?)", conn_get_socket(c), username);
1566 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1567 } else {
1568 hash_to_bnhash((t_hash const *) &oldpasshash1, temp.passhash1); /* avoid warning */
1569
1570 bnet_hash(&oldpasshash2, sizeof(temp), &temp); /* do the double hash */
1571 bnhash_to_hash(packet->u.client_loginreq1.password_hash2, &trypasshash2);
1572
1573 if (hash_eq(trypasshash2, oldpasshash2) == 1) {
1574 conn_login(c, account, username);
1575 eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (correct password)", conn_get_socket(c), username);
1576 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_SUCCESS);
1577 #ifdef WIN32_GUI
1578 guiOnUpdateUserList();
1579 #endif
1580 } else {
1581 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (wrong password)", conn_get_socket(c), username);
1582 conn_increment_passfail_count(c);
1583 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_FAIL);
1584 }
1585 }
1586 } else {
1587 conn_login(c, account, username);
1588 eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (no password)", conn_get_socket(c), username);
1589 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY1_MESSAGE_SUCCESS);
1590 #ifdef WIN32_GUI
1591 guiOnUpdateUserList();
1592 #endif
1593 }
1594 }
1595 conn_push_outqueue(c, rpacket);
1596 packet_del_ref(rpacket);
1597 }
1598
1599 return 0;
1600 }
1601
client_init_email(t_connection * c,t_account * account)1602 void client_init_email(t_connection * c, t_account * account)
1603 {
1604 t_packet *packet;
1605 char const *email;
1606
1607 if (!c || !account)
1608 return;
1609 if (!(email = account_get_email(account))) {
1610 if ((packet = packet_create(packet_class_bnet))) {
1611 packet_set_size(packet, sizeof(t_server_setemailreq));
1612 packet_set_type(packet, SERVER_SETEMAILREQ);
1613 conn_push_outqueue(c, packet);
1614 packet_del_ref(packet);
1615 }
1616 }
1617 return;
1618 }
1619
_client_loginreq2(t_connection * c,t_packet const * const packet)1620 static int _client_loginreq2(t_connection * c, t_packet const *const packet)
1621 {
1622 t_packet *rpacket;
1623 int success = 0;
1624
1625 if (packet_get_size(packet) < sizeof(t_client_loginreq2)) {
1626 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_loginreq2), packet_get_size(packet));
1627 return -1;
1628 }
1629
1630 {
1631 char const *username;
1632 t_account *account;
1633
1634 if (!(username = packet_get_str_const(packet, sizeof(t_client_loginreq2), USER_NAME_MAX))) {
1635 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGINREQ2 (missing or too long username)", conn_get_socket(c));
1636 return -1;
1637 }
1638
1639 if (!(rpacket = packet_create(packet_class_bnet)))
1640 return -1;
1641 packet_set_size(rpacket, sizeof(t_server_loginreply2));
1642 packet_set_type(rpacket, SERVER_LOGINREPLY2);
1643
1644 // too many logins? [added by NonReal]
1645 if (prefs_get_max_concurrent_logins() > 0) {
1646 if (prefs_get_max_concurrent_logins() <= connlist_login_get_length()) {
1647 eventlog(eventlog_level_error, __FUNCTION__, "[%d] login denied, too many concurrent logins. max: %d. current: %d.", conn_get_socket(c), prefs_get_max_concurrent_logins(), connlist_login_get_length());
1648 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS);
1649 return -1;
1650 }
1651 }
1652
1653 /* fail if no account */
1654 if (!(account = accountlist_find_account(username))) {
1655 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no such account)", conn_get_socket(c), username);
1656 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_NONEXIST);
1657 }
1658 /* already logged in */
1659 else if (connlist_find_connection_by_account(account) && prefs_get_kick_old_login() == 0) {
1660 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (already logged in)", conn_get_socket(c), username);
1661 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS);
1662 } else if (account_get_auth_bnetlogin(account) == 0) { /* default to true */
1663 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no bnet access)", conn_get_socket(c), username);
1664 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS);
1665 } else if (account_get_auth_lock(account) == 1) { /* default to false */
1666 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (this account is locked)", conn_get_socket(c), username);
1667 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS);
1668 } else if (conn_get_sessionkey(c) != bn_int_get(packet->u.client_loginreq2.sessionkey)) {
1669 eventlog(eventlog_level_error, __FUNCTION__, "[%d] login for \"%s\" refused (expected session key 0x%08x, got 0x%08x)", conn_get_socket(c), username, conn_get_sessionkey(c), bn_int_get(packet->u.client_loginreq2.sessionkey));
1670 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS);
1671 } else {
1672 struct {
1673 bn_int ticks;
1674 bn_int sessionkey;
1675 bn_int passhash1[5];
1676 } temp;
1677 char const *oldstrhash1;
1678 t_hash oldpasshash1;
1679 t_hash oldpasshash2;
1680 t_hash trypasshash2;
1681
1682 if ((oldstrhash1 = account_get_pass(account))) {
1683 bn_int_set(&temp.ticks, bn_int_get(packet->u.client_loginreq2.ticks));
1684 bn_int_set(&temp.sessionkey, bn_int_get(packet->u.client_loginreq2.sessionkey));
1685 if (hash_set_str(&oldpasshash1, oldstrhash1) < 0) {
1686 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (corrupted passhash1?)", conn_get_socket(c), username);
1687 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS);
1688 } else {
1689 hash_to_bnhash((t_hash const *) &oldpasshash1, temp.passhash1); /* avoid warning */
1690
1691 bnet_hash(&oldpasshash2, sizeof(temp), &temp); /* do the double hash */
1692 bnhash_to_hash(packet->u.client_loginreq2.password_hash2, &trypasshash2);
1693
1694 if (hash_eq(trypasshash2, oldpasshash2) == 1) {
1695 conn_login(c, account, username);
1696 eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (correct password)", conn_get_socket(c), username);
1697 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_SUCCESS);
1698 success = 1;
1699 } else {
1700 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (wrong password)", conn_get_socket(c), username);
1701 conn_increment_passfail_count(c);
1702 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_BADPASS);
1703 }
1704 }
1705 } else {
1706 conn_login(c, account, username);
1707 eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" logged in (no password)", conn_get_socket(c), username);
1708 bn_int_set(&rpacket->u.server_loginreply2.message, SERVER_LOGINREPLY2_MESSAGE_SUCCESS);
1709 success = 1;
1710 }
1711 }
1712 if (success && account) {
1713 #ifdef WIN32_GUI
1714 guiOnUpdateUserList();
1715 #endif
1716 client_init_email(c, account);
1717 }
1718
1719 conn_push_outqueue(c, rpacket);
1720 packet_del_ref(rpacket);
1721 }
1722
1723 return 0;
1724 }
1725
_client_loginreqw3(t_connection * c,t_packet const * const packet)1726 static int _client_loginreqw3(t_connection * c, t_packet const *const packet)
1727 {
1728 t_packet *rpacket;
1729
1730 if (packet_get_size(packet) < sizeof(t_client_loginreq_w3)) {
1731 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_LOGINREQ_W3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_loginreq_w3), packet_get_size(packet));
1732 return -1;
1733 }
1734
1735 {
1736 char const *username;
1737 t_account *account;
1738 int i;
1739
1740 if (!(username = packet_get_str_const(packet, sizeof(t_client_loginreq_w3), USER_NAME_MAX))) {
1741 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_LOGINREQ_W3 (missing or too long username)", conn_get_socket(c));
1742 return -1;
1743 }
1744
1745 if (!(rpacket = packet_create(packet_class_bnet)))
1746 return -1;
1747 packet_set_size(rpacket, sizeof(t_server_loginreply_w3));
1748 packet_set_type(rpacket, SERVER_LOGINREPLY_W3);
1749
1750 for (i = 0; i < 16; i++)
1751 bn_int_set(&rpacket->u.server_loginreply_w3.unknown[i], 0);
1752
1753 {
1754 /* too many logins? */
1755 if (prefs_get_max_concurrent_logins() > 0 && prefs_get_max_concurrent_logins() <= connlist_login_get_length()) {
1756 eventlog(eventlog_level_error, __FUNCTION__, "[%d] login denied, too many concurrent logins. max: %d. current: %d.", conn_get_socket(c), prefs_get_max_concurrent_logins(), connlist_login_get_length());
1757 bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT);
1758 } else
1759 /* fail if no account */
1760 if (!(account = accountlist_find_account(username))) {
1761 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login for \"%s\" refused (no such account)", conn_get_socket(c), username);
1762 bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT);
1763 } else
1764 /* already logged in */
1765 if (connlist_find_connection_by_account(account) && prefs_get_kick_old_login() == 0) {
1766 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login for \"%s\" refused (already logged in)", conn_get_socket(c), username);
1767 bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_ALREADY);
1768 } else if (account_get_auth_bnetlogin(account) == 0) { /* default to true */
1769 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login for \"%s\" refused (no bnet access)", conn_get_socket(c), username);
1770 bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT);
1771 } else if (account_get_auth_lock(account) == 1) { /* default to false */
1772 eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (this account is locked)", conn_get_socket(c), username);
1773 bn_int_set(&rpacket->u.server_loginreply1.message, SERVER_LOGINREPLY_W3_MESSAGE_BADACCT);
1774 } else {
1775 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) \"%s\" passed account check", conn_get_socket(c), username);
1776 conn_set_loggeduser(c, username);
1777 bn_int_set(&rpacket->u.server_loginreply_w3.message, SERVER_LOGINREPLY_W3_MESSAGE_SUCCESS);
1778 }
1779 }
1780
1781 conn_push_outqueue(c, rpacket);
1782 packet_del_ref(rpacket);
1783
1784 }
1785
1786 return 0;
1787 }
1788
_client_pingreq(t_connection * c,t_packet const * const packet)1789 static int _client_pingreq(t_connection * c, t_packet const *const packet)
1790 {
1791 t_packet *rpacket;
1792
1793 if (packet_get_size(packet) < sizeof(t_client_pingreq)) {
1794 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PINGREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_pingreq), packet_get_size(packet));
1795 return -1;
1796 }
1797
1798 if ((rpacket = packet_create(packet_class_bnet))) {
1799 packet_set_size(rpacket, sizeof(t_server_pingreply));
1800 packet_set_type(rpacket, SERVER_PINGREPLY);
1801 conn_push_outqueue(c, rpacket);
1802 packet_del_ref(rpacket);
1803 }
1804
1805 return 0;
1806 }
1807
_client_logonproofreq(t_connection * c,t_packet const * const packet)1808 static int _client_logonproofreq(t_connection * c, t_packet const *const packet)
1809 {
1810 t_packet *rpacket;
1811
1812 if (packet_get_size(packet) < sizeof(t_client_logonproofreq)) {
1813 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LOGONPROOFREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_logonproofreq), packet_get_size(packet));
1814 return -1;
1815 }
1816
1817 {
1818 char const *username;
1819 t_account *account;
1820
1821 eventlog(eventlog_level_info, __FUNCTION__, "[%d] logon proof requested", conn_get_socket(c));
1822
1823 if (!(rpacket = packet_create(packet_class_bnet)))
1824 return -1;
1825 packet_set_size(rpacket, sizeof(t_server_logonproofreply));
1826 packet_set_type(rpacket, SERVER_LOGONPROOFREPLY);
1827
1828 bn_int_set(&rpacket->u.server_logonproofreply.response, SERVER_LOGONPROOFREPLY_RESPONSE_BADPASS);
1829
1830 bn_int_set(&rpacket->u.server_logonproofreply.unknown1, SERVER_LOGONPROOFREPLY_UNKNOWN1);
1831
1832 bn_short_set(&rpacket->u.server_logonproofreply.port0, (short) 0x0000);
1833
1834 bn_int_set(&rpacket->u.server_logonproofreply.unknown2, SERVER_LOGONPROOFREPLY_UNKNOWN2);
1835
1836 bn_short_set(&rpacket->u.server_logonproofreply.port1, (short) 0x0000);
1837
1838 bn_int_set(&rpacket->u.server_logonproofreply.unknown3, SERVER_LOGONPROOFREPLY_UNKNOWN3);
1839 bn_int_set(&rpacket->u.server_logonproofreply.unknown4, SERVER_LOGONPROOFREPLY_UNKNOWN4);
1840
1841 if (!(username = conn_get_loggeduser(c))) {
1842 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) got NULL username, 0x54ff before 0x53ff?", conn_get_socket(c));
1843 } else if (!(account = accountlist_find_account(username))) {
1844 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) login in 0x54ff for \"%s\" refused (no such account)", conn_get_socket(c), username);
1845 } else {
1846 t_hash serverhash;
1847 t_hash clienthash;
1848
1849 if (!packet_get_data_const(packet, 4, 20)) {
1850 eventlog(eventlog_level_error, __FUNCTION__, "[%d] (W3) got bad LOGONPROOFREQ packet (missing hash)", conn_get_socket(c));
1851 return -1;
1852 }
1853 // endian fix
1854 clienthash[0] = bn_int_get(packet->u.client_logonproofreq.password_hash1[0]);
1855 clienthash[1] = bn_int_get(packet->u.client_logonproofreq.password_hash1[1]);
1856 clienthash[2] = bn_int_get(packet->u.client_logonproofreq.password_hash1[2]);
1857 clienthash[3] = bn_int_get(packet->u.client_logonproofreq.password_hash1[3]);
1858 clienthash[4] = bn_int_get(packet->u.client_logonproofreq.password_hash1[4]);
1859
1860 hash_set_str(&serverhash, account_get_pass(account));
1861 if (hash_eq(clienthash, serverhash)) {
1862 conn_login(c, account, username);
1863 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) \"%s\" logged in (right password)", conn_get_socket(c), username);
1864 if ((conn_get_versionid(c) >= 0x0000000D) && (account_get_email(account) == NULL))
1865 bn_int_set(&rpacket->u.server_logonproofreply.response, SERVER_LOGONPROOFREPLY_RESPONSE_EMAIL);
1866 else
1867 bn_int_set(&rpacket->u.server_logonproofreply.response, SERVER_LOGONPROOFREPLY_RESPONSE_OK);
1868 // by amadeo updates the userlist
1869 #ifdef WIN32_GUI
1870 guiOnUpdateUserList();
1871 #endif
1872 } else {
1873 eventlog(eventlog_level_info, __FUNCTION__, "[%d] (W3) got wrong password for \"%s\"", conn_get_socket(c), username);
1874 conn_increment_passfail_count(c);
1875 }
1876 }
1877 conn_push_outqueue(c, rpacket);
1878 packet_del_ref(rpacket);
1879 }
1880 clan_send_status_window(c);
1881
1882 return 0;
1883 }
1884
_client_changegameport(t_connection * c,t_packet const * const packet)1885 static int _client_changegameport(t_connection * c, t_packet const *const packet)
1886 {
1887 if (packet_get_size(packet) < sizeof(t_client_changegameport)) {
1888 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad changegameport packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_changegameport), packet_get_size(packet));
1889 return -1;
1890 }
1891 {
1892 unsigned short port = bn_short_get(packet->u.client_changegameport.port);
1893 if (port < 1024) {
1894 eventlog(eventlog_level_error, __FUNCTION__, "[%d] invalid port in changegameport packet: %d", conn_get_socket(c), (int) port);
1895 return -1;
1896 }
1897
1898 conn_set_game_port(c, port);
1899 }
1900
1901 return 0;
1902 }
1903
_client_friendslistreq(t_connection * c,t_packet const * const packet)1904 static int _client_friendslistreq(t_connection * c, t_packet const *const packet)
1905 {
1906 t_packet *rpacket;
1907
1908 if (packet_get_size(packet) < sizeof(t_client_friendslistreq)) {
1909 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FRIENDSLISTREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_friendslistreq), packet_get_size(packet));
1910 return -1;
1911 }
1912 {
1913 int friend;
1914 t_list *flist;
1915 t_friend *fr;
1916 t_account *account = conn_get_account(c);
1917 int i;
1918 int n = account_get_friendcount(account);
1919 int friendcount = 0;
1920 t_server_friendslistreply_status status;
1921 t_connection *dest_c;
1922 t_game *game;
1923 t_channel *channel;
1924 char stat;
1925
1926 if (!(rpacket = packet_create(packet_class_bnet)))
1927 return -1;
1928
1929 packet_set_size(rpacket, sizeof(t_server_friendslistreply));
1930 packet_set_type(rpacket, SERVER_FRIENDSLISTREPLY);
1931
1932 if ((flist = account_get_friends(account)) == NULL)
1933 return -1;
1934
1935 for (i = 0; i < n; i++) {
1936 friend = account_get_friend(account, i);
1937 if ((fr = friendlist_find_uid(flist, friend)) == NULL)
1938 continue;
1939 packet_append_string(rpacket, account_get_name(friend_get_account(fr)));
1940 game = NULL;
1941 channel = NULL;
1942
1943 if (!(dest_c = connlist_find_connection_by_uid(friend))) {
1944 bn_byte_set(&status.location, FRIENDSTATUS_OFFLINE);
1945 bn_byte_set(&status.status, 0);
1946 bn_int_set(&status.clienttag, 0);
1947 } else {
1948 bn_int_set(&status.clienttag, conn_get_clienttag(dest_c));
1949 stat = 0;
1950 if ((friend_get_mutual(fr)))
1951 stat |= FRIEND_TYPE_MUTUAL;
1952 if ((conn_get_dndstr(dest_c)))
1953 stat |= FRIEND_TYPE_DND;
1954 if ((conn_get_awaystr(dest_c)))
1955 stat |= FRIEND_TYPE_AWAY;
1956 bn_byte_set(&status.status, stat);
1957 if ((game = conn_get_game(dest_c))) {
1958 if (game_get_flag(game) != game_flag_private)
1959 bn_byte_set(&status.location, FRIENDSTATUS_PUBLIC_GAME);
1960 else
1961 bn_byte_set(&status.location, FRIENDSTATUS_PRIVATE_GAME);
1962 } else if ((channel = conn_get_channel(dest_c))) {
1963 bn_byte_set(&status.location, FRIENDSTATUS_CHAT);
1964 } else {
1965 bn_byte_set(&status.location, FRIENDSTATUS_ONLINE);
1966 }
1967 }
1968
1969 packet_append_data(rpacket, &status, sizeof(status));
1970
1971 if (game)
1972 packet_append_string(rpacket, game_get_name(game));
1973 else if (channel)
1974 packet_append_string(rpacket, channel_get_name(channel));
1975 else
1976 packet_append_string(rpacket, "");
1977
1978 friendcount++;
1979 }
1980
1981 bn_byte_set(&rpacket->u.server_friendslistreply.friendcount, friendcount);
1982
1983 conn_push_outqueue(c, rpacket);
1984 packet_del_ref(rpacket);
1985 }
1986
1987 return 0;
1988 }
1989
_client_friendinforeq(t_connection * c,t_packet const * const packet)1990 static int _client_friendinforeq(t_connection * c, t_packet const *const packet)
1991 {
1992 t_packet *rpacket;
1993
1994 if (packet_get_size(packet) < sizeof(t_client_friendinforeq)) {
1995 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad FRIENDINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_friendinforeq), packet_get_size(packet));
1996 return -1;
1997 }
1998
1999 {
2000 t_connection const *dest_c;
2001 t_game const *game;
2002 t_channel const *channel;
2003 t_account *account = conn_get_account(c);
2004 int friend;
2005 t_friend *fr;
2006 t_list *flist;
2007 int n = account_get_friendcount(account);
2008 char type;
2009
2010 if (n == 0)
2011 return 0;
2012
2013 if (bn_byte_get(packet->u.client_friendinforeq.friendnum) > n) {
2014 eventlog(eventlog_level_error, __FUNCTION__, "[%d] bad friend number in FRIENDINFOREQ packet", conn_get_socket(c));
2015 return -1;
2016 }
2017
2018 if (!(rpacket = packet_create(packet_class_bnet)))
2019 return -1;
2020
2021 packet_set_size(rpacket, sizeof(t_server_friendinforeply));
2022 packet_set_type(rpacket, SERVER_FRIENDINFOREPLY);
2023
2024 friend = account_get_friend(account, bn_byte_get(packet->u.client_friendinforeq.friendnum));
2025 if (friend < 0) {
2026 eventlog(eventlog_level_error, __FUNCTION__, "[%d] friend number %d not found", conn_get_socket(c), (int) bn_byte_get(packet->u.client_friendinforeq.friendnum));
2027 return -1;
2028 }
2029
2030 bn_byte_set(&rpacket->u.server_friendinforeply.friendnum, bn_byte_get(packet->u.client_friendinforeq.friendnum));
2031
2032 flist = account_get_friends(account);
2033 fr = friendlist_find_uid(flist, friend);
2034
2035 if (fr == NULL || (dest_c = connlist_find_connection_by_account(friend_get_account(fr))) == NULL) {
2036 bn_byte_set(&rpacket->u.server_friendinforeply.type, FRIEND_TYPE_NON_MUTUAL);
2037 bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_OFFLINE);
2038 bn_int_set(&rpacket->u.server_friendinforeply.clienttag, 0);
2039 packet_append_string(rpacket, "");
2040 conn_push_outqueue(c, rpacket);
2041 packet_del_ref(rpacket);
2042 return 0;
2043 }
2044
2045 type = FRIEND_TYPE_NON_MUTUAL;
2046 if (friend_get_mutual(fr))
2047 type |= FRIEND_TYPE_MUTUAL;
2048 if ((conn_get_dndstr(dest_c)))
2049 type |= FRIEND_TYPE_DND;
2050 if ((conn_get_awaystr(dest_c)))
2051 type |= FRIEND_TYPE_AWAY;
2052 bn_byte_set(&rpacket->u.server_friendinforeply.type, type);
2053 if ((game = conn_get_game(dest_c))) {
2054 if (game_get_flag(game) != game_flag_private)
2055 bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_PUBLIC_GAME);
2056 else
2057 bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_PRIVATE_GAME);
2058 packet_append_string(rpacket, game_get_name(game));
2059 } else if ((channel = conn_get_channel(dest_c))) {
2060 bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_CHAT);
2061 packet_append_string(rpacket, channel_get_name(channel));
2062 } else {
2063 bn_byte_set(&rpacket->u.server_friendinforeply.status, FRIENDSTATUS_ONLINE);
2064 packet_append_string(rpacket, "");
2065 }
2066
2067 bn_int_set(&rpacket->u.server_friendinforeply.clienttag, conn_get_clienttag(dest_c));
2068
2069 conn_push_outqueue(c, rpacket);
2070 packet_del_ref(rpacket);
2071
2072 }
2073
2074 return 0;
2075 }
2076
_client_atfriendscreen(t_connection * c,t_packet const * const packet)2077 static int _client_atfriendscreen(t_connection * c, t_packet const *const packet)
2078 {
2079 char const *myusername;
2080 char const *fname;
2081 t_connection *dest_c;
2082 unsigned char f_cnt = 0;
2083 t_account *account;
2084 t_packet *rpacket;
2085 char const *vt;
2086 char const *nvt;
2087 t_friend *fr;
2088 t_list *flist;
2089 t_elem *curr;
2090 t_channel *mychannel, *chan;
2091 int publicchan = 1;
2092
2093 eventlog(eventlog_level_info, __FUNCTION__, "[%d] got CLIENT_ARRANGEDTEAM_FRIENDSCREEN packet", conn_get_socket(c));
2094
2095 myusername = conn_get_username(c);
2096 eventlog(eventlog_level_trace, "handle_bnet", "[%d] AT - Got Username %s", conn_get_socket(c), myusername);
2097
2098 if (!(rpacket = packet_create(packet_class_bnet))) {
2099 eventlog(eventlog_level_error, "handle_bnet", "[%d] AT - can't create friendscreen server packet", conn_get_socket(c));
2100 return -1;
2101 }
2102
2103 packet_set_size(rpacket, sizeof(t_server_arrangedteam_friendscreen));
2104 packet_set_type(rpacket, SERVER_ARRANGEDTEAM_FRIENDSCREEN);
2105
2106
2107 mychannel = conn_get_channel(c);
2108 if ((mychannel))
2109 publicchan = channel_get_flags(mychannel) & channel_flags_public;
2110
2111 vt = versioncheck_get_versiontag(conn_get_versioncheck(c));
2112 flist = account_get_friends(conn_get_account(c));
2113 LIST_TRAVERSE(flist, curr) {
2114 if (!(fr = elem_get_data(curr))) {
2115 eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
2116 continue;
2117 }
2118
2119 account = friend_get_account(fr);
2120 if (!(dest_c = connlist_find_connection_by_account(account)))
2121 continue; // if user is offline, then continue to next friend
2122 nvt = versioncheck_get_versiontag(conn_get_versioncheck(dest_c));
2123 if (vt && nvt && strcmp(vt, nvt))
2124 continue; /* friend is using another game/version */
2125
2126 if (friend_get_mutual(fr)) {
2127 if (conn_get_dndstr(dest_c))
2128 continue; // user is dnd
2129 if (conn_get_awaystr(dest_c))
2130 continue; // user is away
2131 if (conn_get_game(dest_c))
2132 continue; // user is some game
2133 if (!(chan = conn_get_channel(dest_c)))
2134 continue;
2135 if (!publicchan && (chan == mychannel))
2136 continue; // don't list YET if in same private channel
2137
2138 fname = account_get_name(account);
2139 eventlog(eventlog_level_trace, "handle_bnet", "AT - Friend: %s is available for a AT Game.", fname);
2140 f_cnt++;
2141 packet_append_string(rpacket, fname);
2142 }
2143 }
2144
2145 if (!publicchan) { // now list matching users in same private chan
2146 for (dest_c = channel_get_first(mychannel); dest_c; dest_c = channel_get_next()) {
2147 if (dest_c == c)
2148 continue; // don'tlist yourself
2149 nvt = versioncheck_get_versiontag(conn_get_versioncheck(dest_c));
2150 if (vt && nvt && strcmp(vt, nvt))
2151 continue; /* user is using another game/version */
2152 if (conn_get_dndstr(dest_c))
2153 continue; // user is dnd
2154 if (conn_get_awaystr(dest_c))
2155 continue; // user is away
2156 if (!(conn_get_account(dest_c)))
2157 continue;
2158 fname = account_get_name(conn_get_account(dest_c));
2159 eventlog(eventlog_level_trace, "handle_bnet", "AT - user in private channel: %s is available for a AT Game.", fname);
2160 f_cnt++;
2161 packet_append_string(rpacket, fname);
2162 }
2163 }
2164
2165 if (!f_cnt)
2166 eventlog(eventlog_level_info, "handle_bnet", "AT - no friends available for AT game.");
2167 bn_byte_set(&rpacket->u.server_arrangedteam_friendscreen.f_count, f_cnt);
2168 conn_push_outqueue(c, rpacket);
2169
2170 packet_del_ref(rpacket);
2171
2172 return 0;
2173 }
2174
_client_atinvitefriend(t_connection * c,t_packet const * const packet)2175 static int _client_atinvitefriend(t_connection * c, t_packet const *const packet)
2176 {
2177 t_packet *rpacket;
2178 t_clienttag ctag;
2179
2180 if (packet_get_size(packet) < sizeof(t_client_arrangedteam_invite_friend)) {
2181 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ARRANGEDTEAM_INVITE_FRIEND packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_arrangedteam_invite_friend), packet_get_size(packet));
2182 return -1;
2183 }
2184
2185 ctag = conn_get_clienttag(c);
2186
2187 {
2188 int count_to_invite, count, id;
2189 char const *invited_usernames[8];
2190 t_account *members[MAX_TEAMSIZE];
2191 int i, n, offset, teammemcount;
2192 t_connection *dest_c;
2193 t_team *team;
2194 unsigned int teamid;
2195
2196 count_to_invite = bn_byte_get(packet->u.client_arrangedteam_invite_friend.numfriends);
2197 count = bn_int_get(packet->u.client_arrangedteam_invite_friend.count);
2198 id = bn_int_get(packet->u.client_arrangedteam_invite_friend.id);
2199 teammemcount = count_to_invite + 1;
2200
2201 if ((count_to_invite < 1) || (count_to_invite > 3)) {
2202 eventlog(eventlog_level_error, __FUNCTION__, "got invalid number of users to invite to game");
2203 return -1;
2204 }
2205
2206 eventlog(eventlog_level_info, __FUNCTION__, "[%d] got ARRANGEDTEAM INVITE packet for %d invitees", conn_get_socket(c), count_to_invite);
2207
2208 offset = sizeof(t_client_arrangedteam_invite_friend);
2209
2210 for (i = 0; i < count_to_invite; i++) {
2211 if (!(invited_usernames[i] = packet_get_str_const(packet, offset, USER_NAME_MAX))) {
2212 eventlog(eventlog_level_error, "handle_bnet", "Could not get username from invite packet");
2213 return -1;
2214 } else {
2215 offset += strlen(invited_usernames[i]) + 1;
2216 eventlog(eventlog_level_debug, "handle_bnet", "Added user %s to invite array.", invited_usernames[i]);
2217 }
2218 }
2219
2220 members[0] = conn_get_account(c);
2221 for (i = 1; i < MAX_TEAMSIZE; i++) {
2222 if ((i < teammemcount)) {
2223 if (!(members[i] = accountlist_find_account(invited_usernames[i - 1]))) {
2224 eventlog(eventlog_level_error, __FUNCTION__, "got invitation for non-existant user \"%s\"", invited_usernames[i - 1]);
2225 return -1;
2226 }
2227 } else
2228 members[i] = NULL;
2229 }
2230
2231
2232 if (!(team = account_find_team_by_accounts(members[0], members, ctag))) {
2233 team = create_team(members, ctag); //no need to free on return -1 because it's allready in teamlist
2234
2235 eventlog(eventlog_level_trace, __FUNCTION__, "this team has never played before, creating new team");
2236 } else {
2237 eventlog(eventlog_level_trace, __FUNCTION__, "this team has allready played before");
2238 }
2239
2240 teamid = team_get_teamid(team);
2241 account_set_currentatteam(conn_get_account(c), team_get_teamid(team));
2242
2243
2244 //Create the packet to send to each of the users you wanted to invite
2245 conn_set_channel(c, NULL);
2246
2247 for (i = 0; i < teammemcount; i++) {
2248
2249 if (!(dest_c = account_get_conn(team_get_member(team, i))))
2250 continue;
2251
2252 if ((dest_c == c))
2253 continue;
2254
2255 if (!(rpacket = packet_create(packet_class_bnet)))
2256 return -1;
2257
2258 packet_set_size(rpacket, sizeof(t_server_arrangedteam_send_invite));
2259 packet_set_type(rpacket, SERVER_ARRANGEDTEAM_SEND_INVITE);
2260
2261 bn_int_set(&rpacket->u.server_arrangedteam_send_invite.count, count);
2262 bn_int_set(&rpacket->u.server_arrangedteam_send_invite.id, id);
2263 { /* trans support */
2264 unsigned short port = conn_get_game_port(c);
2265 unsigned int addr = conn_get_addr(c);
2266
2267 trans_net(conn_get_addr(dest_c), &addr, &port);
2268
2269 bn_int_nset(&rpacket->u.server_arrangedteam_send_invite.inviterip, addr);
2270 bn_short_set(&rpacket->u.server_arrangedteam_send_invite.port, port);
2271 }
2272 bn_byte_set(&rpacket->u.server_arrangedteam_send_invite.numfriends, count_to_invite);
2273
2274 for (n = 0; n < teammemcount; n++) {
2275 if (n != i)
2276 packet_append_string(rpacket, account_get_name(team_get_member(team, n)));
2277 }
2278
2279 //now send packet
2280 conn_push_outqueue(dest_c, rpacket);
2281 packet_del_ref(rpacket);
2282
2283 account_set_currentatteam(conn_get_account(dest_c), teamid);
2284 }
2285
2286 //now send a ACK to the inviter
2287 if (!(rpacket = packet_create(packet_class_bnet)))
2288 return -1;
2289 packet_set_size(rpacket, sizeof(t_server_arrangedteam_invite_friend_ack));
2290 packet_set_type(rpacket, SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK);
2291
2292 bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.count, count);
2293 bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.id, id);
2294 bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.timestamp, now);
2295 bn_byte_set(&rpacket->u.server_arrangedteam_invite_friend_ack.teamsize, count_to_invite + 1);
2296
2297 /*
2298 * five int's to fill
2299 * fill with uid's of all teammembers, including the inviter
2300 * and the rest with FFFFFFFF
2301 * to be used when sever recieves anongame search
2302 * [Omega]
2303 */
2304 for (i = 0; i < 5; i++) {
2305
2306 if (i < teammemcount) {
2307 bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.info[i], team_get_memberuid(team, i));
2308 } else { /* fill rest with FFFFFFFF */
2309 bn_int_set(&rpacket->u.server_arrangedteam_invite_friend_ack.info[i], 0xFFFFFFFF);
2310 }
2311 }
2312
2313 conn_push_outqueue(c, rpacket);
2314 packet_del_ref(rpacket);
2315
2316 }
2317
2318 return 0;
2319 }
2320
_client_atacceptdeclineinvite(t_connection * c,t_packet const * const packet)2321 static int _client_atacceptdeclineinvite(t_connection * c, t_packet const *const packet)
2322 {
2323 t_packet *rpacket;
2324 t_clienttag ctag;
2325
2326 if (packet_get_size(packet) < sizeof(t_client_arrangedteam_accept_decline_invite)) {
2327 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ARRANGEDTEAM_ACCEPT_DECLINE_INVITE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_arrangedteam_accept_decline_invite), packet_get_size(packet));
2328 return -1;
2329 }
2330
2331 ctag = conn_get_clienttag(c);
2332
2333 {
2334 char const *inviter;
2335 t_connection *dest_c;
2336
2337 //if user declined the invitation then
2338 if (bn_int_get(packet->u.client_arrangedteam_accept_decline_invite.option) == CLIENT_ARRANGEDTEAM_DECLINE) {
2339 inviter = packet_get_str_const(packet, sizeof(t_client_arrangedteam_accept_decline_invite), USER_NAME_MAX);
2340 dest_c = connlist_find_connection_by_accountname(inviter);
2341
2342 eventlog(eventlog_level_info, "handle_bnet", "%s declined a arranged team game with %s", conn_get_username(c), inviter);
2343
2344 if (!(rpacket = packet_create(packet_class_bnet)))
2345 return -1;
2346 packet_set_size(rpacket, sizeof(t_server_arrangedteam_member_decline));
2347 packet_set_type(rpacket, SERVER_ARRANGEDTEAM_MEMBER_DECLINE);
2348
2349 bn_int_set(&rpacket->u.server_arrangedteam_member_decline.count, bn_int_get(packet->u.client_arrangedteam_accept_decline_invite.count));
2350 bn_int_set(&rpacket->u.server_arrangedteam_member_decline.action, SERVER_ARRANGEDTEAM_DECLINE);
2351 packet_append_string(rpacket, conn_get_username(c));
2352
2353 conn_push_outqueue(dest_c, rpacket);
2354 packet_del_ref(rpacket);
2355 }
2356 }
2357
2358 return 0;
2359 }
2360
_client_atacceptinvite(t_connection * c,t_packet const * const packet)2361 static int _client_atacceptinvite(t_connection * c, t_packet const *const packet)
2362 {
2363 // t_packet * rpacket;
2364
2365 if (packet_get_size(packet) < sizeof(t_client_arrangedteam_accept_invite)) {
2366 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ARRANGEDTEAM_ACCEPT_INVITE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_arrangedteam_accept_invite), packet_get_size(packet));
2367 return -1;
2368 }
2369 /* conn_set_channel(c, "Arranged Teams"); */
2370 return 0;
2371 }
2372
2373 typedef struct {
2374 t_connection *c;
2375 unsigned lnews;
2376 unsigned fnews;
2377 } t_motd_data;
2378
_news_cb(time_t date,t_lstr * lstr,void * data)2379 static int _news_cb(time_t date, t_lstr * lstr, void *data)
2380 {
2381 t_packet *rpacket;
2382 t_motd_data *motdd = (t_motd_data *) data;
2383
2384 if (date < motdd->lnews)
2385 return -1; /* exit traversing */
2386
2387 rpacket = packet_create(packet_class_bnet);
2388 if (!rpacket)
2389 return -1;
2390
2391 packet_set_size(rpacket, sizeof(t_server_motd_w3));
2392 packet_set_type(rpacket, SERVER_MOTD_W3);
2393
2394 bn_byte_set(&rpacket->u.server_motd_w3.msgtype, SERVER_MOTD_W3_MSGTYPE);
2395 bn_int_set(&rpacket->u.server_motd_w3.curr_time, now);
2396
2397 bn_int_set(&rpacket->u.server_motd_w3.first_news_time, motdd->fnews);
2398 bn_int_set(&rpacket->u.server_motd_w3.timestamp, date);
2399 bn_int_set(&rpacket->u.server_motd_w3.timestamp2, date);
2400
2401 /* Append news to packet, we used the already cached len in the lstr */
2402 packet_append_lstr(rpacket, lstr);
2403
2404 /* Send news packet */
2405 conn_push_outqueue(motdd->c, rpacket);
2406 packet_del_ref(rpacket);
2407
2408 return 0;
2409 }
2410
_client_motdw3(t_connection * c,t_packet const * const packet)2411 static int _client_motdw3(t_connection * c, t_packet const *const packet)
2412 {
2413 t_packet *rpacket;
2414 char serverinfo[512];
2415 t_clienttag ctag;
2416 t_motd_data motdd;
2417
2418 if (packet_get_size(packet) < sizeof(t_client_motd_w3)) {
2419 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_MOTD_W3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_motd_w3), packet_get_size(packet));
2420 return -1;
2421 }
2422
2423 ctag = conn_get_clienttag(c);
2424 /* if in a game, remove user from his game */
2425 if (conn_get_game(c) != NULL)
2426 conn_set_game(c, NULL, NULL, NULL, game_type_none, 0);
2427
2428 /* News */
2429 motdd.lnews = bn_int_get(packet->u.client_motd_w3.last_news_time);
2430 motdd.fnews = news_get_firstnews();
2431 motdd.c = c;
2432
2433 eventlog(eventlog_level_trace, __FUNCTION__, "lastnews() %u news_time %u", news_get_lastnews(), motdd.lnews);
2434 news_traverse(_news_cb, &motdd);
2435
2436 /* Welcome Message */
2437 rpacket = packet_create(packet_class_bnet);
2438 if (!rpacket)
2439 return -1;
2440
2441 packet_set_size(rpacket, sizeof(t_server_motd_w3));
2442 packet_set_type(rpacket, SERVER_MOTD_W3);
2443
2444 //bn_int_set(&rpacket->u.server_motd_w3.ticks,get_ticks());
2445 bn_byte_set(&rpacket->u.server_motd_w3.msgtype, SERVER_MOTD_W3_MSGTYPE);
2446 bn_int_set(&rpacket->u.server_motd_w3.curr_time, now);
2447 bn_int_set(&rpacket->u.server_motd_w3.first_news_time, motdd.fnews);
2448 bn_int_set(&rpacket->u.server_motd_w3.timestamp, motdd.fnews + 1);
2449 bn_int_set(&rpacket->u.server_motd_w3.timestamp2, SERVER_MOTD_W3_WELCOME);
2450
2451 sprintf(serverinfo, "Welcome to the " PVPGN_SOFTWARE " Version " PVPGN_VERSION "\r\n\r\nThere are currently %u user(s) in %u games of %s, and %u user(s) playing %u games and chatting in %u channels in %s.\r\n%s", conn_get_user_count_by_clienttag(conn_get_clienttag(c)), game_get_count_by_clienttag(ctag), clienttag_get_title(conn_get_clienttag(c)), connlist_login_get_length(), gamelist_get_length(), channellist_get_length(), prefs_get_servername(),prefs_get_server_info());
2452
2453 packet_append_string(rpacket, serverinfo);
2454
2455 conn_push_outqueue(c, rpacket);
2456 packet_del_ref(rpacket);
2457
2458 return 0;
2459 }
2460
_client_realmlistreq(t_connection * c,t_packet const * const packet)2461 static int _client_realmlistreq(t_connection * c, t_packet const *const packet)
2462 {
2463 t_packet *rpacket;
2464
2465 if (packet_get_size(packet) < sizeof(t_client_realmlistreq)) {
2466 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMLISTREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_realmlistreq), packet_get_size(packet));
2467 return -1;
2468 }
2469
2470 if ((rpacket = packet_create(packet_class_bnet))) {
2471 t_elem const *curr;
2472 t_realm const *realm;
2473 t_server_realmlistreply_data realmdata;
2474 unsigned int count;
2475
2476 packet_set_size(rpacket, sizeof(t_server_realmlistreply));
2477 packet_set_type(rpacket, SERVER_REALMLISTREPLY);
2478 bn_int_set(&rpacket->u.server_realmlistreply.unknown1, SERVER_REALMLISTREPLY_UNKNOWN1);
2479 count = 0;
2480 LIST_TRAVERSE_CONST(realmlist(), curr) {
2481 realm = elem_get_data(curr);
2482 if (!realm_get_active(realm))
2483 continue;
2484 bn_int_set(&realmdata.unknown3, SERVER_REALMLISTREPLY_DATA_UNKNOWN3);
2485 bn_int_set(&realmdata.unknown4, SERVER_REALMLISTREPLY_DATA_UNKNOWN4);
2486 bn_int_set(&realmdata.unknown5, SERVER_REALMLISTREPLY_DATA_UNKNOWN5);
2487 bn_int_set(&realmdata.unknown6, SERVER_REALMLISTREPLY_DATA_UNKNOWN6);
2488 bn_int_set(&realmdata.unknown7, SERVER_REALMLISTREPLY_DATA_UNKNOWN7);
2489 bn_int_set(&realmdata.unknown8, SERVER_REALMLISTREPLY_DATA_UNKNOWN8);
2490 bn_int_set(&realmdata.unknown9, SERVER_REALMLISTREPLY_DATA_UNKNOWN9);
2491 packet_append_data(rpacket, &realmdata, sizeof(realmdata));
2492 packet_append_string(rpacket, realm_get_name(realm));
2493 packet_append_string(rpacket, realm_get_description(realm));
2494 count++;
2495 }
2496 bn_int_set(&rpacket->u.server_realmlistreply.count, count);
2497 conn_push_outqueue(c, rpacket);
2498 packet_del_ref(rpacket);
2499 }
2500
2501 return 0;
2502 }
2503
_client_realmlistreq110(t_connection * c,t_packet const * const packet)2504 static int _client_realmlistreq110(t_connection * c, t_packet const *const packet)
2505 {
2506 t_packet *rpacket;
2507
2508 if (packet_get_size(packet) < sizeof(t_client_realmlistreq_110)) {
2509 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMLISTREQ_110 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_realmlistreq), packet_get_size(packet));
2510 return -1;
2511 }
2512
2513 if ((rpacket = packet_create(packet_class_bnet))) {
2514 t_elem const *curr;
2515 t_realm const *realm;
2516 t_server_realmlistreply_110_data realmdata;
2517 unsigned int count;
2518
2519 packet_set_size(rpacket, sizeof(t_server_realmlistreply_110));
2520 packet_set_type(rpacket, SERVER_REALMLISTREPLY_110);
2521 bn_int_set(&rpacket->u.server_realmlistreply_110.unknown1, SERVER_REALMLISTREPLY_110_UNKNOWN1);
2522 count = 0;
2523 LIST_TRAVERSE_CONST(realmlist(), curr) {
2524 realm = elem_get_data(curr);
2525 if (!realm_get_active(realm))
2526 continue;
2527 bn_int_set(&realmdata.unknown1, SERVER_REALMLISTREPLY_110_DATA_UNKNOWN1);
2528 packet_append_data(rpacket, &realmdata, sizeof(realmdata));
2529 packet_append_string(rpacket, realm_get_name(realm));
2530 packet_append_string(rpacket, realm_get_description(realm));
2531 count++;
2532 }
2533 bn_int_set(&rpacket->u.server_realmlistreply_110.count, count);
2534 conn_push_outqueue(c, rpacket);
2535 packet_del_ref(rpacket);
2536 }
2537
2538 return 0;
2539 }
2540
_client_claninforeq(t_connection * c,t_packet const * const packet)2541 static int _client_claninforeq(t_connection * c, t_packet const *const packet)
2542 {
2543 t_packet *rpacket;
2544 int count;
2545 char const *username;
2546 t_account *account;
2547 t_clanmember *clanmember;
2548 t_clan *clan;
2549 int clantag1;
2550 int clantag2;
2551
2552 if (packet_get_size(packet) < sizeof(t_client_claninforeq)) {
2553 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLANINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_claninforeq), packet_get_size(packet));
2554 return -1;
2555 }
2556
2557 count = bn_int_get(packet->u.client_claninforeq.count);
2558 clantag1 = bn_int_get(packet->u.client_claninforeq.clantag);
2559 clan = NULL;
2560
2561 if (!(username = packet_get_str_const(packet, sizeof(t_client_claninforeq), USER_NAME_MAX))) {
2562 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLANINFOREQ (missing or too long username)", conn_get_socket(c));
2563 return -1;
2564 }
2565
2566 if (!(account = accountlist_find_account(username))) {
2567 eventlog(eventlog_level_error, __FUNCTION__, "requested claninfo for non-existant account");
2568 return -1;
2569 }
2570
2571 if ((clanmember = account_get_clanmember(account)) && (clan = clanmember_get_clan(clanmember)))
2572 clantag2 = clan_get_clantag(clan);
2573 else
2574 clantag2 = 0;
2575
2576 if ((rpacket = packet_create(packet_class_bnet))) {
2577 packet_set_size(rpacket, sizeof(t_server_claninforeply));
2578 packet_set_type(rpacket, SERVER_CLANINFOREPLY);
2579 bn_int_set(&rpacket->u.server_profilereply.count, count);
2580 if (clantag1 == clantag2) {
2581 int temp;
2582 t_bnettime bn_time;
2583 bn_long ltime;
2584
2585 bn_byte_set(&rpacket->u.server_claninforeply.fail, 0);
2586
2587 packet_append_string(rpacket, clan_get_name(clan));
2588 temp = clanmember_get_status(clanmember);
2589 packet_append_data(rpacket, &temp, 1);
2590 temp = clanmember_get_join_time(clanmember);
2591 bn_time = time_to_bnettime(temp, 0);
2592 bn_time = bnettime_add_tzbias(bn_time, -conn_get_tzbias(c));
2593 bnettime_to_bn_long(bn_time, <ime);
2594 packet_append_data(rpacket, <ime, 8);
2595 } else
2596 bn_byte_set(&rpacket->u.server_claninforeply.fail, 1);
2597
2598
2599 conn_push_outqueue(c, rpacket);
2600 packet_del_ref(rpacket);
2601 }
2602
2603 return 0;
2604 }
2605
_client_profilereq(t_connection * c,t_packet const * const packet)2606 static int _client_profilereq(t_connection * c, t_packet const *const packet)
2607 {
2608 t_packet *rpacket;
2609 int count;
2610 char const *username;
2611 t_account *account;
2612 t_clanmember *clanmember;
2613 t_clan *clan;
2614 bn_int clanTAG;
2615
2616 if (packet_get_size(packet) < sizeof(t_client_profilereq)) {
2617 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROFILEREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_profilereq), packet_get_size(packet));
2618 return -1;
2619 }
2620
2621 count = bn_int_get(packet->u.client_profilereq.count);
2622
2623 if (!(username = packet_get_str_const(packet, sizeof(t_client_profilereq), USER_NAME_MAX))) {
2624 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROFILEREQ (missing or too long username)", conn_get_socket(c));
2625 return -1;
2626 }
2627
2628 if (!(account = accountlist_find_account(username))) {
2629 eventlog(eventlog_level_error, __FUNCTION__, "requested profile for non-existant account");
2630 return -1;
2631 }
2632 if ((rpacket = packet_create(packet_class_bnet))) {
2633 packet_set_size(rpacket, sizeof(t_server_profilereply));
2634 packet_set_type(rpacket, SERVER_PROFILEREPLY);
2635 bn_int_set(&rpacket->u.server_profilereply.count, count);
2636 bn_byte_set(&rpacket->u.server_profilereply.fail, 0);
2637 packet_append_string(rpacket, account_get_desc(account));
2638 packet_append_string(rpacket, account_get_loc(account));
2639 if ((clanmember = account_get_clanmember(account)) && (clan = clanmember_get_clan(clanmember)))
2640 bn_int_set(&clanTAG, clan_get_clantag(clan));
2641 else
2642 bn_int_set(&clanTAG, 0);
2643 packet_append_data(rpacket, clanTAG, 4);
2644
2645 conn_push_outqueue(c, rpacket);
2646 packet_del_ref(rpacket);
2647 }
2648
2649 return 0;
2650 }
2651
2652
_client_realmjoinreq109(t_connection * c,t_packet const * const packet)2653 static int _client_realmjoinreq109(t_connection * c, t_packet const *const packet)
2654 {
2655 t_packet *rpacket;
2656
2657 if (packet_get_size(packet) < sizeof(t_client_realmjoinreq_109)) {
2658 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMJOINREQ_109 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_realmjoinreq_109), packet_get_size(packet));
2659 return -1;
2660 }
2661
2662 {
2663 char const *realmname;
2664 t_realm *realm;
2665
2666 if (!(realmname = packet_get_str_const(packet, sizeof(t_client_realmjoinreq_109), REALM_NAME_LEN))) {
2667 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad REALMJOINREQ_109 (missing or too long realmname)", conn_get_socket(c));
2668 return -1;
2669 }
2670
2671 if ((realm = realmlist_find_realm(realmname))) {
2672 unsigned int salt;
2673 struct {
2674 bn_int salt;
2675 bn_int sessionkey;
2676 bn_int sessionnum;
2677 bn_int secret;
2678 bn_int passhash[5];
2679 } temp;
2680 char const *pass_str;
2681 t_hash secret_hash;
2682 t_hash passhash;
2683 t_realm *prev_realm;
2684
2685 /* FIXME: should we only set this after they log in to the realm server? */
2686 prev_realm = conn_get_realm(c);
2687 if (prev_realm) {
2688 if (prev_realm != realm) {
2689 realm_add_player_number(realm, 1);
2690 realm_add_player_number(prev_realm, -1);
2691 conn_set_realm(c, realm);
2692 }
2693 } else {
2694 realm_add_player_number(realm, 1);
2695 conn_set_realm(c, realm);
2696 }
2697
2698 if ((pass_str = account_get_pass(conn_get_account(c)))) {
2699 if (hash_set_str(&passhash, pass_str) == 0) {
2700 hash_to_bnhash((t_hash const *) &passhash, temp.passhash);
2701 salt = bn_int_get(packet->u.client_realmjoinreq_109.seqno);
2702 bn_int_set(&temp.salt, salt);
2703 bn_int_set(&temp.sessionkey, conn_get_sessionkey(c));
2704 bn_int_set(&temp.sessionnum, conn_get_sessionnum(c));
2705 bn_int_set(&temp.secret, conn_get_secret(c));
2706 bnet_hash(&secret_hash, sizeof(temp), &temp);
2707
2708 if ((rpacket = packet_create(packet_class_bnet))) {
2709 packet_set_size(rpacket, sizeof(t_server_realmjoinreply_109));
2710 packet_set_type(rpacket, SERVER_REALMJOINREPLY_109);
2711 bn_int_set(&rpacket->u.server_realmjoinreply_109.seqno, salt);
2712 bn_int_set(&rpacket->u.server_realmjoinreply_109.u1, 0x0);
2713 bn_short_set(&rpacket->u.server_realmjoinreply_109.u3, 0x0); /* reg auth */
2714 bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr1, 0x0);
2715 bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionnum, conn_get_sessionnum(c));
2716 { /* trans support */
2717 unsigned int addr = realm_get_ip(realm);
2718 unsigned short port = realm_get_port(realm);
2719
2720 trans_net(conn_get_addr(c), &addr, &port);
2721
2722 bn_int_nset(&rpacket->u.server_realmjoinreply_109.addr, addr);
2723 bn_short_nset(&rpacket->u.server_realmjoinreply_109.port, port);
2724 }
2725 bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionkey, conn_get_sessionkey(c));
2726 bn_int_set(&rpacket->u.server_realmjoinreply_109.u5, 0);
2727 bn_int_set(&rpacket->u.server_realmjoinreply_109.u6, 0);
2728 bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr2, 0);
2729 bn_int_set(&rpacket->u.server_realmjoinreply_109.u7, 0);
2730 bn_int_set(&rpacket->u.server_realmjoinreply_109.versionid, conn_get_versionid(c));
2731 bn_int_set(&rpacket->u.server_realmjoinreply_109.clienttag, conn_get_clienttag(c));
2732 hash_to_bnhash((t_hash const *) &secret_hash, rpacket->u.server_realmjoinreply_109.secret_hash); /* avoid warning */
2733 packet_append_string(rpacket, conn_get_username(c));
2734 conn_push_outqueue(c, rpacket);
2735 packet_del_ref(rpacket);
2736 }
2737 return 0;
2738 } else
2739 eventlog(eventlog_level_info, __FUNCTION__, "[%d] realm join for \"%s\" failed (unable to hash password)", conn_get_socket(c), conn_get_loggeduser(c));
2740 } else {
2741 eventlog(eventlog_level_info, __FUNCTION__, "[%d] realm join for \"%s\" failed (no password)", conn_get_socket(c), conn_get_loggeduser(c));
2742 }
2743 } else
2744 eventlog(eventlog_level_error, __FUNCTION__, "[%d] could not find active realm \"%s\"", conn_get_socket(c), realmname);
2745
2746 if ((rpacket = packet_create(packet_class_bnet))) {
2747 packet_set_size(rpacket, sizeof(t_server_realmjoinreply_109));
2748 packet_set_type(rpacket, SERVER_REALMJOINREPLY_109);
2749 bn_int_set(&rpacket->u.server_realmjoinreply_109.seqno, bn_int_get(packet->u.client_realmjoinreq_109.seqno));
2750 bn_int_set(&rpacket->u.server_realmjoinreply_109.u1, 0);
2751 bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionnum, 0);
2752 bn_short_set(&rpacket->u.server_realmjoinreply_109.u3, 0);
2753 bn_int_nset(&rpacket->u.server_realmjoinreply_109.addr, 0);
2754 bn_short_nset(&rpacket->u.server_realmjoinreply_109.port, 0);
2755 bn_int_set(&rpacket->u.server_realmjoinreply_109.sessionkey, 0);
2756 bn_int_set(&rpacket->u.server_realmjoinreply_109.u5, 0);
2757 bn_int_set(&rpacket->u.server_realmjoinreply_109.u6, 0);
2758 bn_int_set(&rpacket->u.server_realmjoinreply_109.u7, 0);
2759 bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr1, 0);
2760 bn_int_set(&rpacket->u.server_realmjoinreply_109.bncs_addr2, 0);
2761 bn_int_set(&rpacket->u.server_realmjoinreply_109.versionid, 0);
2762 bn_int_set(&rpacket->u.server_realmjoinreply_109.clienttag, 0);
2763 bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[0], 0);
2764 bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[1], 0);
2765 bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[2], 0);
2766 bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[3], 0);
2767 bn_int_set(&rpacket->u.server_realmjoinreply_109.secret_hash[4], 0);
2768 packet_append_string(rpacket, "");
2769 conn_push_outqueue(c, rpacket);
2770 packet_del_ref(rpacket);
2771 }
2772 }
2773
2774 return 0;
2775 }
2776
_client_charlistreq(t_connection * c,t_packet const * const packet)2777 static int _client_charlistreq(t_connection * c, t_packet const *const packet)
2778 {
2779 t_packet *rpacket;
2780
2781 if (packet_get_size(packet) < sizeof(t_client_unknown_37)) {
2782 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_37 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_37), packet_get_size(packet));
2783 return -1;
2784 }
2785 /*
2786 0x0070: 83 80 ff ff ff ff ff 2f t,taran,......./
2787 0x0080: ff ff ff ff ff ff ff ff ff ff 03 ff ff ff ff ff ................
2788 0x0090: ff ff ff ff ff ff ff ff ff ff ff 07 80 80 80 80 ................
2789 0x00a0: ff ff ff 00
2790 */
2791 if ((rpacket = packet_create(packet_class_bnet))) {
2792 char const *charlist;
2793 char *temp;
2794
2795 packet_set_size(rpacket, sizeof(t_server_unknown_37));
2796 packet_set_type(rpacket, SERVER_UNKNOWN_37);
2797 bn_int_set(&rpacket->u.server_unknown_37.unknown1, SERVER_UNKNOWN_37_UNKNOWN1);
2798 bn_int_set(&rpacket->u.server_unknown_37.unknown2, SERVER_UNKNOWN_37_UNKNOWN2);
2799
2800 if (!(charlist = account_get_closed_characterlist(conn_get_account(c), conn_get_clienttag(c), realm_get_name(conn_get_realm(c))))) {
2801 bn_int_set(&rpacket->u.server_unknown_37.count, 0);
2802 conn_push_outqueue(c, rpacket);
2803 packet_del_ref(rpacket);
2804 return 0;
2805 }
2806 temp = xstrdup(charlist);
2807
2808 {
2809 char const *tok1;
2810 char const *tok2;
2811 t_character const *ch;
2812 unsigned int count;
2813
2814 count = 0;
2815 tok1 = (char const *) strtok(temp, ","); /* strtok modifies the string it is passed */
2816 tok2 = strtok(NULL, ",");
2817 while (tok1) {
2818 if (!tok2) {
2819 eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" has bad character list \"%s\"", conn_get_socket(c), conn_get_username(c), temp);
2820 break;
2821 }
2822
2823 if ((ch = characterlist_find_character(tok1, tok2))) {
2824 packet_append_ntstring(rpacket, character_get_realmname(ch));
2825 packet_append_ntstring(rpacket, ",");
2826 packet_append_string(rpacket, character_get_name(ch));
2827 packet_append_string(rpacket, character_get_playerinfo(ch));
2828 packet_append_string(rpacket, character_get_guildname(ch));
2829 count++;
2830 } else
2831 eventlog(eventlog_level_error, __FUNCTION__, "[%d] character \"%s\" is missing", conn_get_socket(c), tok2);
2832 tok1 = strtok(NULL, ",");
2833 tok2 = strtok(NULL, ",");
2834 }
2835 xfree(temp);
2836
2837 bn_int_set(&rpacket->u.server_unknown_37.count, count);
2838 conn_push_outqueue(c, rpacket);
2839 packet_del_ref(rpacket);
2840 }
2841 }
2842
2843 return 0;
2844 }
2845
_client_unknown39(t_connection * c,t_packet const * const packet)2846 static int _client_unknown39(t_connection * c, t_packet const *const packet)
2847 {
2848 if (packet_get_size(packet) < sizeof(t_client_unknown_39)) {
2849 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad UNKNOWN_39 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_unknown_39), packet_get_size(packet));
2850 return -1;
2851 }
2852 return 0;
2853 }
2854
_client_adreq(t_connection * c,t_packet const * const packet)2855 static int _client_adreq(t_connection * c, t_packet const *const packet)
2856 {
2857 t_packet *rpacket;
2858
2859 if (packet_get_size(packet) < sizeof(t_client_adreq)) {
2860 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adreq), packet_get_size(packet));
2861 return -1;
2862 }
2863
2864 {
2865 t_adbanner *ad;
2866
2867 if (!(ad = adbanner_pick(c, bn_int_get(packet->u.client_adreq.prev_adid))))
2868 return 0;
2869
2870 /* eventlog(eventlog_level_debug,__FUNCTION__,"[%d] picking ad file=\"%s\" id=0x%06x tag=%u",conn_get_socket(c),adbanner_get_filename(ad),adbanner_get_id(ad),adbanner_get_extensiontag(ad)); */
2871 if ((rpacket = packet_create(packet_class_bnet))) {
2872 packet_set_size(rpacket, sizeof(t_server_adreply));
2873 packet_set_type(rpacket, SERVER_ADREPLY);
2874 bn_int_set(&rpacket->u.server_adreply.adid, adbanner_get_id(ad));
2875 bn_int_set(&rpacket->u.server_adreply.extensiontag, adbanner_get_extensiontag(ad));
2876 file_to_mod_time(adbanner_get_filename(ad), &rpacket->u.server_adreply.timestamp);
2877 packet_append_string(rpacket, adbanner_get_filename(ad));
2878 packet_append_string(rpacket, adbanner_get_link(ad));
2879 conn_push_outqueue(c, rpacket);
2880 packet_del_ref(rpacket);
2881 }
2882 }
2883
2884 return 0;
2885 }
2886
_client_adack(t_connection * c,t_packet const * const packet)2887 static int _client_adack(t_connection * c, t_packet const *const packet)
2888 {
2889 if (packet_get_size(packet) < sizeof(t_client_adack)) {
2890 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADACK packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adack), packet_get_size(packet));
2891 return -1;
2892 }
2893
2894 /*
2895 {
2896 char const * tname;
2897
2898 eventlog(eventlog_level_info,__FUNCTION__,"[%d] ad acknowledgement for adid 0x%04x from \"%s\"",conn_get_socket(c),bn_int_get(packet->u.client_adack.adid),(tname = conn_get_chatname(c)));
2899 conn_unget_chatname(c,tname);
2900 }
2901 */
2902 return 0;
2903 }
2904
_client_adclick(t_connection * c,t_packet const * const packet)2905 static int _client_adclick(t_connection * c, t_packet const *const packet)
2906 {
2907 if (packet_get_size(packet) < sizeof(t_client_adclick)) {
2908 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADCLICK packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adclick), packet_get_size(packet));
2909 return -1;
2910 }
2911
2912 eventlog(eventlog_level_info, __FUNCTION__, "[%d] ad click for adid 0x%04x from \"%s\"", conn_get_socket(c), bn_int_get(packet->u.client_adclick.adid), conn_get_username(c));
2913
2914 return 0;
2915 }
2916
_client_adclick2(t_connection * c,t_packet const * const packet)2917 static int _client_adclick2(t_connection * c, t_packet const *const packet)
2918 {
2919 t_packet *rpacket;
2920
2921 if (packet_get_size(packet) < sizeof(t_client_adclick2)) {
2922 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad ADCLICK2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_adclick2), packet_get_size(packet));
2923 return -1;
2924 }
2925
2926 eventlog(eventlog_level_info, __FUNCTION__, "[%d] ad click2 for adid 0x%04hx from \"%s\"", conn_get_socket(c), bn_int_get(packet->u.client_adclick2.adid), conn_get_username(c));
2927
2928 {
2929 t_adbanner *ad;
2930
2931 if (!(ad = adbanner_get(c, bn_int_get(packet->u.client_adclick2.adid))))
2932 return -1;
2933
2934 if ((rpacket = packet_create(packet_class_bnet))) {
2935 packet_set_size(rpacket, sizeof(t_server_adclickreply2));
2936 packet_set_type(rpacket, SERVER_ADCLICKREPLY2);
2937 bn_int_set(&rpacket->u.server_adclickreply2.adid, adbanner_get_id(ad));
2938 packet_append_string(rpacket, adbanner_get_link(ad));
2939 conn_push_outqueue(c, rpacket);
2940 packet_del_ref(rpacket);
2941 }
2942 }
2943
2944 return 0;
2945 }
2946
_client_statsupdate(t_connection * c,t_packet const * const packet)2947 static int _client_statsupdate(t_connection * c, t_packet const *const packet)
2948 {
2949 if (packet_get_size(packet) < sizeof(t_client_statsupdate)) {
2950 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSUPDATE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_statsupdate), packet_get_size(packet));
2951 return -1;
2952 }
2953
2954 {
2955 char const *name;
2956 char const *key;
2957 char const *val;
2958 unsigned int name_count;
2959 unsigned int key_count;
2960 unsigned int i, j;
2961 unsigned int name_off;
2962 unsigned int keys_off;
2963 unsigned int key_off;
2964 unsigned int vals_off;
2965 unsigned int val_off;
2966 t_account *account;
2967
2968 name_count = bn_int_get(packet->u.client_statsupdate.name_count);
2969 key_count = bn_int_get(packet->u.client_statsupdate.key_count);
2970
2971 if (name_count != 1)
2972 eventlog(eventlog_level_warn, __FUNCTION__, "[%d] got suspicious STATSUPDATE packet (name_count=%u)", conn_get_socket(c), name_count);
2973
2974 for (i = 0, name_off = sizeof(t_client_statsupdate); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1);
2975 if (i < name_count) {
2976 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSUPDATE packet (only %u names of %u)", conn_get_socket(c), i, name_count);
2977 return -1;
2978 }
2979 keys_off = name_off;
2980
2981 for (i = 0, key_off = keys_off; i < key_count && (key = packet_get_str_const(packet, key_off, MAX_ATTRKEY_STR)); i++, key_off += strlen(key) + 1);
2982 if (i < key_count) {
2983 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STATSUPDATE packet (only %u keys of %u)", conn_get_socket(c), i, key_count);
2984 return -1;
2985 }
2986 vals_off = key_off;
2987
2988 if ((account = conn_get_account(c))) {
2989 if (account_get_auth_changeprofile(account) == 0) { /* default to true */
2990 eventlog(eventlog_level_error, __FUNCTION__, "[%d] stats update for \"%s\" refused (no change profile access)", conn_get_socket(c), conn_get_username(c));
2991 return -1;
2992 }
2993 eventlog(eventlog_level_info, __FUNCTION__, "[%d] updating player profile for \"%s\"", conn_get_socket(c), conn_get_username(c));
2994
2995 for (i = 0, name_off = sizeof(t_client_statsupdate); i < name_count && (name = packet_get_str_const(packet, name_off, UNCHECKED_NAME_STR)); i++, name_off += strlen(name) + 1)
2996 for (j = 0, key_off = keys_off, val_off = vals_off; j < key_count && (key = packet_get_str_const(packet, key_off, MAX_ATTRKEY_STR)) && (val = packet_get_str_const(packet, val_off, MAX_ATTRVAL_STR)); j++, key_off += strlen(key) + 1, val_off += strlen(val) + 1)
2997 if (strlen(key) < 9 || strncasecmp(key, "profile\\", 8) != 0)
2998 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got STATSUPDATE with suspicious key \"%s\" value \"%s\"", conn_get_socket(c), key, val);
2999 else
3000 account_set_strattr(account, key, val);
3001 }
3002 }
3003
3004 return 0;
3005 }
3006
_client_playerinforeq(t_connection * c,t_packet const * const packet)3007 static int _client_playerinforeq(t_connection * c, t_packet const *const packet)
3008 {
3009 t_packet *rpacket;
3010
3011 if (packet_get_size(packet) < sizeof(t_client_playerinforeq)) {
3012 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PLAYERINFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_playerinforeq), packet_get_size(packet));
3013 return -1;
3014 }
3015
3016 {
3017 char const *username;
3018 char const *info;
3019 t_account *account;
3020
3021 if (!(username = packet_get_str_const(packet, sizeof(t_client_playerinforeq), USER_NAME_MAX))) {
3022 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PLAYERINFOREQ (missing or too long username)", conn_get_socket(c));
3023 return -1;
3024 }
3025 if (!(info = packet_get_str_const(packet, sizeof(t_client_playerinforeq) + strlen(username) + 1, MAX_PLAYERINFO_STR))) {
3026 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PLAYERINFOREQ (missing or too long info)", conn_get_socket(c));
3027 return -1;
3028 }
3029
3030 if (info[0] != '\0')
3031 conn_set_playerinfo(c, info);
3032 if (!username[0])
3033 username = conn_get_loggeduser(c);
3034
3035 account = conn_get_account(c);
3036
3037 if (!(rpacket = packet_create(packet_class_bnet)))
3038 return -1;
3039 packet_set_size(rpacket, sizeof(t_server_playerinforeply));
3040 packet_set_type(rpacket, SERVER_PLAYERINFOREPLY);
3041
3042 if (account) {
3043 packet_append_string(rpacket, username);
3044 packet_append_string(rpacket, conn_get_playerinfo(c));
3045 packet_append_string(rpacket, username);
3046 } else {
3047 packet_append_string(rpacket, "");
3048 packet_append_string(rpacket, "");
3049 packet_append_string(rpacket, "");
3050 }
3051 conn_push_outqueue(c, rpacket);
3052 packet_del_ref(rpacket);
3053 }
3054
3055 return 0;
3056 }
3057
_client_progident2(t_connection * c,t_packet const * const packet)3058 static int _client_progident2(t_connection * c, t_packet const *const packet)
3059 {
3060 t_packet *rpacket;
3061
3062 if (packet_get_size(packet) < sizeof(t_client_progident2)) {
3063 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad PROGIDENT2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_progident2), packet_get_size(packet));
3064 return -1;
3065 }
3066
3067 /* d2 uses this packet with clienttag = 0 to request the channel list */
3068 if (bn_int_get(packet->u.client_progident2.clienttag)) {
3069 if (_check_allowed_client(bn_int_get(packet->u.client_progident2.clienttag))) {
3070 conn_set_state(c, conn_state_destroy);
3071 return 0;
3072 }
3073 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] CLIENT_PROGIDENT2 clienttag=0x%08x", conn_get_socket(c), bn_int_get(packet->u.client_progident2.clienttag));
3074
3075 /* Hmm... no archtag. Hope we get it in CLIENT_AUTHREQ1 (but we won't if we use the shortcut) */
3076
3077 conn_set_clienttag(c, bn_int_get(packet->u.client_progident2.clienttag));
3078 }
3079
3080 if ((rpacket = packet_create(packet_class_bnet))) {
3081 packet_set_size(rpacket, sizeof(t_server_channellist));
3082 packet_set_type(rpacket, SERVER_CHANNELLIST);
3083 {
3084 t_channel *ch;
3085 t_elem const *curr;
3086
3087 LIST_TRAVERSE_CONST(channellist(), curr) {
3088 ch = elem_get_data(curr);
3089 if ((!(channel_get_flags(ch) & channel_flags_clan)) && (!prefs_get_hide_temp_channels() || channel_get_permanent(ch)) && (!channel_get_clienttag(ch) || strcmp(channel_get_clienttag(ch), clienttag_uint_to_str(conn_get_clienttag(c))) == 0) && (!(channel_get_flags(ch) & channel_flags_thevoid)) && // don't display theVoid in channel list
3090 ((channel_get_max(ch) != 0) || ((channel_get_max(ch) == 0) && (account_is_operator_or_admin(conn_get_account(c), channel_get_name(ch)) == 1)))) // don't display restricted channel for no admins/ops
3091 packet_append_string(rpacket, channel_get_name(ch));
3092 }
3093 }
3094 packet_append_string(rpacket, "");
3095 conn_push_outqueue(c, rpacket);
3096 packet_del_ref(rpacket);
3097 }
3098
3099 return 0;
3100 }
3101
_client_joinchannel(t_connection * c,t_packet const * const packet)3102 static int _client_joinchannel(t_connection * c, t_packet const *const packet)
3103 {
3104 t_account *account;
3105 char const *cname;
3106 int found = 1;
3107 t_clan *user_clan;
3108 int clantag;
3109 t_uint32 clienttag;
3110 t_channel *channel;
3111
3112 if (packet_get_size(packet) < sizeof(t_client_joinchannel)) {
3113 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad JOINCHANNEL packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_joinchannel), packet_get_size(packet));
3114 return -1;
3115 }
3116
3117 account = conn_get_account(c);
3118
3119 if (!(cname = packet_get_str_const(packet, sizeof(t_client_joinchannel), CHANNEL_NAME_LEN))) {
3120 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad JOINCHANNEL (missing or too long cname)", conn_get_socket(c));
3121 return -1;
3122 }
3123
3124 if ((channel = conn_get_channel(c)) && (strcasecmp(channel_get_name(channel), cname) == 0))
3125 return 0; //we are allready in this channel
3126
3127 clienttag = conn_get_clienttag(c);
3128 if ((clienttag == CLIENTTAG_WARCRAFT3_UINT) || (clienttag == CLIENTTAG_WAR3XP_UINT)) {
3129 conn_update_w3_playerinfo(c);
3130 switch (bn_int_get(packet->u.client_joinchannel.channelflag)) {
3131 case CLIENT_JOINCHANNEL_NORMAL:
3132 eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_NORMAL channel \"%s\"", conn_get_socket(c), cname);
3133
3134 if (prefs_get_ask_new_channel() && (!(channellist_find_channel_by_name(cname, conn_get_country(c), realm_get_name(conn_get_realm(c)))))) {
3135 found = 0;
3136 eventlog(eventlog_level_info, __FUNCTION__, "[%d] didn't find channel \"%s\" to join", conn_get_socket(c), cname);
3137 message_send_text(c, message_type_channeldoesnotexist, c, cname);
3138 }
3139 break;
3140 case CLIENT_JOINCHANNEL_GENERIC:
3141
3142 if ((user_clan = account_get_clan(account)) && (clantag = clan_get_clantag(user_clan)))
3143 sprintf((char *) cname, "Clan %c%c%c%c", (clantag >> 24), (clantag >> 16) & 0xff, (clantag >> 8) & 0xff, clantag & 0xff);
3144 eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_GENERIC channel \"%s\"", conn_get_socket(c), cname);
3145
3146 /* don't have to do anything here */
3147 break;
3148 case CLIENT_JOINCHANNEL_CREATE:
3149 eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_CREATE channel \"%s\"", conn_get_socket(c), cname);
3150 eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_JOINCHANNEL_CREATE channel \"%s\"", conn_get_socket(c), cname);
3151 /* don't have to do anything here */
3152 break;
3153 }
3154
3155 if (found && conn_set_channel(c, cname) < 0)
3156 conn_set_channel(c, CHANNEL_NAME_BANNED); /* should not fail */
3157 } else {
3158
3159 // not W3
3160 if (conn_set_channel(c, cname) < 0)
3161 conn_set_channel(c, CHANNEL_NAME_BANNED); /* should not fail */
3162 }
3163 // here we set channel flags on user
3164 channel_set_userflags(c);
3165
3166 return 0;
3167 }
3168
_client_message(t_connection * c,t_packet const * const packet)3169 static int _client_message(t_connection * c, t_packet const *const packet)
3170 {
3171 if (packet_get_size(packet) < sizeof(t_client_message)) {
3172 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MESSAGE packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_message), packet_get_size(packet));
3173 return -1;
3174 }
3175
3176 {
3177 char const *text;
3178 t_channel const *channel;
3179
3180 if (!(text = packet_get_str_const(packet, sizeof(t_client_message), MAX_MESSAGE_LEN))) {
3181 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MESSAGE (missing or too long text)", conn_get_socket(c));
3182 return -1;
3183 }
3184
3185 conn_set_idletime(c);
3186
3187 if ((channel = conn_get_channel(c)))
3188 channel_message_log(channel, c, 1, text);
3189 /* we don't log game commands currently */
3190
3191
3192
3193 if (text[0] == '/')
3194 handle_command(c, text);
3195 else if (channel && !conn_quota_exceeded(c, text))
3196 channel_message_send(channel, message_type_talk, c, text);
3197 /* else discard */
3198 }
3199
3200 return 0;
3201 }
3202
3203 struct glist_cbdata {
3204 unsigned tcount, counter;
3205 t_connection *c;
3206 t_game_type gtype;
3207 t_packet *rpacket;
3208 };
3209
_glist_cb(t_game * game,void * data)3210 static int _glist_cb(t_game * game, void *data)
3211 {
3212 struct glist_cbdata *cbdata = (struct glist_cbdata*)data;
3213 char clienttag_str[5];
3214 t_server_gamelistreply_game glgame;
3215 unsigned int addr;
3216 unsigned short port;
3217 bn_int game_spacer = { 1, 0, 0, 0 };
3218
3219 cbdata->tcount++;
3220 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] considering listing game=\"%s\", pass=\"%s\" clienttag=\"%s\" gtype=%d", conn_get_socket(cbdata->c), game_get_name(game), game_get_pass(game), tag_uint_to_str(clienttag_str, game_get_clienttag(game)), (int) game_get_type(game));
3221
3222 if (prefs_get_hide_pass_games() && game_get_flag(game) == game_flag_private) {
3223 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is passworded or has private flag", conn_get_socket(cbdata->c));
3224 return 0;
3225 }
3226 if (prefs_get_hide_started_games() && game_get_status(game) != game_status_open) {
3227 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is not open", conn_get_socket(cbdata->c));
3228 return 0;
3229 }
3230 if (game_get_clienttag(game) != conn_get_clienttag(cbdata->c)) {
3231 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is for a different client", conn_get_socket(cbdata->c));
3232 return 0;
3233 }
3234 if (cbdata->gtype != game_type_all && game_get_type(game) != cbdata->gtype) {
3235 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is wrong type", conn_get_socket(cbdata->c));
3236 return 0;
3237 }
3238 if (conn_get_versioncheck(cbdata->c) &&
3239 conn_get_versioncheck(game_get_owner(game)) &&
3240 versioncheck_get_versiontag(conn_get_versioncheck(cbdata->c)) &&
3241 versioncheck_get_versiontag(conn_get_versioncheck(game_get_owner(game))) &&
3242 strcmp(versioncheck_get_versiontag(conn_get_versioncheck(cbdata->c)), versioncheck_get_versiontag(conn_get_versioncheck(game_get_owner(game)))) != 0) {
3243 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] not listing because game is wrong versiontag", conn_get_socket(cbdata->c));
3244 return 0;
3245 }
3246 bn_short_set(&glgame.gametype, gtype_to_bngtype(game_get_type(game)));
3247 bn_short_set(&glgame.unknown1, SERVER_GAMELISTREPLY_GAME_UNKNOWN1);
3248 bn_short_set(&glgame.unknown3, SERVER_GAMELISTREPLY_GAME_UNKNOWN3);
3249 addr = game_get_addr(game);
3250 port = game_get_port(game);
3251 trans_net(conn_get_addr(cbdata->c), &addr, &port);
3252 bn_short_nset(&glgame.port, port);
3253 bn_int_nset(&glgame.game_ip, addr);
3254 bn_int_set(&glgame.unknown4, SERVER_GAMELISTREPLY_GAME_UNKNOWN4);
3255 bn_int_set(&glgame.unknown5, SERVER_GAMELISTREPLY_GAME_UNKNOWN5);
3256 switch (game_get_status(game)) {
3257 case game_status_started:
3258 bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_STARTED);
3259 break;
3260 case game_status_full:
3261 bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_FULL);
3262 break;
3263 case game_status_open:
3264 bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_OPEN);
3265 break;
3266 case game_status_done:
3267 bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_DONE);
3268 break;
3269 default:
3270 eventlog(eventlog_level_warn, __FUNCTION__, "[%d] game \"%s\" has bad status=%d", conn_get_socket(cbdata->c), game_get_name(game), (int) game_get_status(game));
3271 bn_int_set(&glgame.status, 0);
3272 }
3273 bn_int_set(&glgame.unknown6, SERVER_GAMELISTREPLY_GAME_UNKNOWN6);
3274
3275 if (packet_get_size(cbdata->rpacket) + sizeof(glgame) + strlen(game_get_name(game)) + 1 + strlen(game_get_pass(game)) + 1 + strlen(game_get_info(game)) + 1 > MAX_PACKET_SIZE) {
3276 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] out of room for games", conn_get_socket(cbdata->c));
3277 return -1; /* no more room */
3278 }
3279
3280 if (cbdata->counter) {
3281 packet_append_data(cbdata->rpacket, &game_spacer, sizeof(game_spacer));
3282 }
3283
3284 packet_append_data(cbdata->rpacket, &glgame, sizeof(glgame));
3285 packet_append_string(cbdata->rpacket, game_get_name(game));
3286 packet_append_string(cbdata->rpacket, game_get_pass(game));
3287 packet_append_string(cbdata->rpacket, game_get_info(game));
3288 cbdata->counter++;
3289
3290 return 0;
3291 }
3292
_client_gamelistreq(t_connection * c,t_packet const * const packet)3293 static int _client_gamelistreq(t_connection * c, t_packet const *const packet)
3294 {
3295 t_packet *rpacket;
3296 char const *gamename;
3297 char const *gamepass;
3298 unsigned short bngtype;
3299 t_game_type gtype;
3300 t_clienttag clienttag;
3301 t_game *game;
3302 t_server_gamelistreply_game glgame;
3303 unsigned int addr;
3304 unsigned short port;
3305 char clienttag_str[5];
3306
3307 if (packet_get_size(packet) < sizeof(t_client_gamelistreq)) {
3308 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAMELISTREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_gamelistreq), packet_get_size(packet));
3309 return -1;
3310 }
3311
3312 if (!(gamename = packet_get_str_const(packet, sizeof(t_client_gamelistreq), GAME_NAME_LEN))) {
3313 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAMELISTREQ (missing or too long gamename)", conn_get_socket(c));
3314 return -1;
3315 }
3316
3317 if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_gamelistreq) + strlen(gamename) + 1, GAME_PASS_LEN))) {
3318 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAMELISTREQ (missing or too long password)", conn_get_socket(c));
3319 return -1;
3320 }
3321
3322 bngtype = bn_short_get(packet->u.client_gamelistreq.gametype);
3323 clienttag = conn_get_clienttag(c);
3324 gtype = bngreqtype_to_gtype(clienttag, bngtype);
3325 if (!(rpacket = packet_create(packet_class_bnet)))
3326 return -1;
3327 packet_set_size(rpacket, sizeof(t_server_gamelistreply));
3328 packet_set_type(rpacket, SERVER_GAMELISTREPLY);
3329
3330 bn_int_set(&rpacket->u.server_gamelistreply.sstatus, 0);
3331
3332 /* specific game requested? */
3333 if (gamename[0] != '\0') {
3334 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY looking for specific game tag=\"%s\" bngtype=0x%08x gtype=%d name=\"%s\" pass=\"%s\"", conn_get_socket(c), tag_uint_to_str(clienttag_str, clienttag), bngtype, (int) gtype, gamename, gamepass);
3335 if ((game = gamelist_find_game(gamename, clienttag, gtype))) {
3336 /* game found but first we need to make sure everything is OK */
3337 bn_int_set(&rpacket->u.server_gamelistreply.gamecount, 0);
3338 switch (game_get_status(game)) {
3339 case game_status_started:
3340 bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_STARTED);
3341 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but started", conn_get_socket(c));
3342 break;
3343 case game_status_full:
3344 bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_FULL);
3345 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but full", conn_get_socket(c));
3346 break;
3347 case game_status_done:
3348 bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_NOTFOUND);
3349 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but done", conn_get_socket(c));
3350 break;
3351 case game_status_open:
3352 case game_status_loaded:
3353 if (strcmp(gamepass, game_get_pass(game))) { /* passworded game must match password in request */
3354 bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_PASS);
3355 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found but is password protected and wrong password given", conn_get_socket(c));
3356 break;
3357 }
3358
3359 if (game_get_status(game) == game_status_loaded) {
3360 bn_int_set(&rpacket->u.server_gamelistreply.sstatus, SERVER_GAMELISTREPLY_GAME_SSTATUS_LOADED);
3361 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY found loaded game", conn_get_socket(c));
3362 }
3363
3364 /* everything seems fine, lets reply with the found game */
3365 bn_int_set(&glgame.status, SERVER_GAMELISTREPLY_GAME_STATUS_OPEN);
3366 bn_short_set(&glgame.gametype, gtype_to_bngtype(game_get_type(game)));
3367 bn_short_set(&glgame.unknown1, SERVER_GAMELISTREPLY_GAME_UNKNOWN1);
3368 bn_short_set(&glgame.unknown3, SERVER_GAMELISTREPLY_GAME_UNKNOWN3);
3369 addr = game_get_addr(game);
3370 port = game_get_port(game);
3371 trans_net(conn_get_addr(c), &addr, &port);
3372 bn_short_nset(&glgame.port, port);
3373 bn_int_nset(&glgame.game_ip, addr);
3374 bn_int_set(&glgame.unknown4, SERVER_GAMELISTREPLY_GAME_UNKNOWN4);
3375 bn_int_set(&glgame.unknown5, SERVER_GAMELISTREPLY_GAME_UNKNOWN5);
3376 bn_int_set(&glgame.unknown6, SERVER_GAMELISTREPLY_GAME_UNKNOWN6);
3377
3378 packet_append_data(rpacket, &glgame, sizeof(glgame));
3379 packet_append_string(rpacket, game_get_name(game));
3380 packet_append_string(rpacket, game_get_pass(game));
3381 packet_append_string(rpacket, game_get_info(game));
3382 bn_int_set(&rpacket->u.server_gamelistreply.gamecount, 1);
3383 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY specific game found", conn_get_socket(c));
3384 break;
3385 default:
3386 eventlog(eventlog_level_warn, __FUNCTION__, "[%d] game \"%s\" has bad status %d", conn_get_socket(c), game_get_name(game), game_get_status(game));
3387 }
3388 } else {
3389 bn_int_set(&rpacket->u.server_gamelistreply.gamecount, 0);
3390 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY specific game doesn't seem to exist", conn_get_socket(c));
3391 }
3392 } else { /* list all public games of this type */
3393 struct glist_cbdata cbdata;
3394
3395 if (gtype == game_type_all)
3396 eventlog(eventlog_level_debug, __FUNCTION__, "GAMELISTREPLY looking for public games tag=\"%s\" bngtype=0x%08x gtype=all", tag_uint_to_str(clienttag_str, clienttag), bngtype);
3397 else
3398 eventlog(eventlog_level_debug, __FUNCTION__, "GAMELISTREPLY looking for public games tag=\"%s\" bngtype=0x%08x gtype=%d", tag_uint_to_str(clienttag_str, clienttag), bngtype, (int) gtype);
3399
3400 cbdata.counter = 0;
3401 cbdata.tcount = 0;
3402 cbdata.c = c;
3403 cbdata.gtype = gtype;
3404 cbdata.rpacket = rpacket;
3405 gamelist_traverse(_glist_cb,&cbdata);
3406
3407 bn_int_set(&rpacket->u.server_gamelistreply.gamecount, cbdata.counter);
3408 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] GAMELISTREPLY sent %u of %u games", conn_get_socket(c), cbdata.counter, cbdata.tcount);
3409 }
3410
3411 conn_push_outqueue(c, rpacket);
3412 packet_del_ref(rpacket);
3413
3414 return 0;
3415 }
3416
_client_joingame(t_connection * c,t_packet const * const packet)3417 static int _client_joingame(t_connection * c, t_packet const *const packet)
3418 {
3419 char const *gamename;
3420 char const *gamepass;
3421 t_game *game;
3422 t_game_type gtype;
3423
3424 if (packet_get_size(packet) < sizeof(t_client_join_game)) {
3425 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad JOIN_GAME packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_join_game), packet_get_size(packet));
3426 return -1;
3427 }
3428
3429 if (!(gamename = packet_get_str_const(packet, sizeof(t_client_join_game), GAME_NAME_LEN))) {
3430 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_JOIN_GAME (missing or too long gamename)", conn_get_socket(c));
3431 return -1;
3432 }
3433
3434 if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_join_game) + strlen(gamename) + 1, GAME_PASS_LEN))) {
3435 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_JOIN_GAME packet (missing or too long gamepass)", conn_get_socket(c));
3436 return -1;
3437 }
3438
3439 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] trying to join game \"%s\" pass=\"%s\"", conn_get_socket(c), gamename, gamepass);
3440
3441 if (conn_get_joingamewhisper_ack(c) == 0) {
3442 watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame);
3443 conn_set_joingamewhisper_ack(c, 1); /* 1 = already whispered. We reset this each time user joins a channel */
3444 clanmember_on_change_status_by_connection(c);
3445 }
3446
3447 if (conn_get_channel(c))
3448 conn_set_channel(c, NULL);
3449
3450 if (!strcmp(gamename, "BNet") && !handle_anongame_join(c)) {
3451 gtype = game_type_anongame;
3452 gamename = NULL;
3453 return 0; /* tmp: do not record any anongames as yet */
3454 } else {
3455 if (!(game = gamelist_find_game(gamename, conn_get_clienttag(c), game_type_all))) {
3456 eventlog(eventlog_level_info, __FUNCTION__, "[%d] unable to find game \"%s\" for user to join", conn_get_socket(c), gamename);
3457 return 0;
3458 }
3459 gtype = game_get_type(game);
3460 gamename = game_get_name(game);
3461 if ((gtype == game_type_ladder && account_get_auth_joinladdergame(conn_get_account(c)) == 0) || /* default to true */
3462 (gtype != game_type_ladder && account_get_auth_joinnormalgame(conn_get_account(c)) == 0)) { /* default to true */
3463 eventlog(eventlog_level_info, __FUNCTION__, "[%d] game join for \"%s\" to \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c), gamename);
3464 /* If the user is not in a game, then map authorization
3465 will fail and keep them from playing. */
3466 return 0;
3467 }
3468 }
3469
3470 if (conn_set_game(c, gamename, gamepass, "", gtype, STARTVER_UNKNOWN) < 0)
3471 eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" joined game \"%s\", but could not be recorded on server", conn_get_socket(c), conn_get_username(c), gamename);
3472 else
3473 eventlog(eventlog_level_info, __FUNCTION__, "[%d] \"%s\" joined game \"%s\"", conn_get_socket(c), conn_get_username(c), gamename);
3474
3475 return 0;
3476 }
3477
_client_startgame1(t_connection * c,t_packet const * const packet)3478 static int _client_startgame1(t_connection * c, t_packet const *const packet)
3479 {
3480 t_packet *rpacket;
3481
3482 if (packet_get_size(packet) < sizeof(t_client_startgame1)) {
3483 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_startgame1), packet_get_size(packet));
3484 return -1;
3485 }
3486
3487 {
3488 char const *gamename;
3489 char const *gamepass;
3490 char const *gameinfo;
3491 unsigned short bngtype;
3492 unsigned int status;
3493 t_game *currgame;
3494
3495 if (!(gamename = packet_get_str_const(packet, sizeof(t_client_startgame1), GAME_NAME_LEN))) {
3496 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (missing or too long gamename)", conn_get_socket(c));
3497 return -1;
3498 }
3499 if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_startgame1) + strlen(gamename) + 1, GAME_PASS_LEN))) {
3500 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (missing or too long gamepass)", conn_get_socket(c));
3501 return -1;
3502 }
3503 if (!(gameinfo = packet_get_str_const(packet, sizeof(t_client_startgame1) + strlen(gamename) + 1 + strlen(gamepass) + 1, GAME_INFO_LEN))) {
3504 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME1 packet (missing or too long gameinfo)", conn_get_socket(c));
3505 return -1;
3506 }
3507 if (conn_get_joingamewhisper_ack(c) == 0) {
3508 if (watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame) == 0)
3509 eventlog(eventlog_level_info, "handle_bnet", "Told Mutual Friends your in game %s", gamename);
3510
3511 conn_set_joingamewhisper_ack(c, 1); //1 = already whispered. We reset this each time user joins a channel
3512 }
3513
3514
3515 bngtype = bn_short_get(packet->u.client_startgame1.gametype);
3516 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got startgame1 status for game \"%s\" is 0x%08x (gametype = 0x%04hx)", conn_get_socket(c), gamename, bn_int_get(packet->u.client_startgame1.status), bngtype);
3517 status = bn_int_get(packet->u.client_startgame1.status) & CLIENT_STARTGAME1_STATUSMASK;
3518
3519 if ((currgame = conn_get_game(c))) {
3520 switch (status) {
3521 case CLIENT_STARTGAME1_STATUS_STARTED:
3522 game_set_status(currgame, game_status_started);
3523 break;
3524 case CLIENT_STARTGAME1_STATUS_FULL:
3525 game_set_status(currgame, game_status_full);
3526 break;
3527 case CLIENT_STARTGAME1_STATUS_OPEN:
3528 game_set_status(currgame, game_status_open);
3529 break;
3530 case CLIENT_STARTGAME1_STATUS_DONE:
3531 game_set_status(currgame, game_status_done);
3532 eventlog(eventlog_level_info, __FUNCTION__, "[%d] game \"%s\" is finished", conn_get_socket(c), gamename);
3533 break;
3534 }
3535 } else if (status != CLIENT_STARTGAME1_STATUS_DONE) {
3536 t_game_type gtype;
3537
3538 gtype = bngtype_to_gtype(conn_get_clienttag(c), bngtype);
3539 if ((gtype == game_type_ladder && account_get_auth_createladdergame(conn_get_account(c)) == 0) || /* default to true */
3540 (gtype != game_type_ladder && account_get_auth_createnormalgame(conn_get_account(c)) == 0)) /* default to true */
3541 eventlog(eventlog_level_info, __FUNCTION__, "[%d] game start for \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c));
3542 else
3543 conn_set_game(c, gamename, gamepass, gameinfo, gtype, STARTVER_GW1);
3544
3545 if ((rpacket = packet_create(packet_class_bnet))) {
3546 packet_set_size(rpacket, sizeof(t_server_startgame1_ack));
3547 packet_set_type(rpacket, SERVER_STARTGAME1_ACK);
3548
3549 if (conn_get_game(c))
3550 bn_int_set(&rpacket->u.server_startgame1_ack.reply, SERVER_STARTGAME1_ACK_OK);
3551 else
3552 bn_int_set(&rpacket->u.server_startgame1_ack.reply, SERVER_STARTGAME1_ACK_NO);
3553
3554 conn_push_outqueue(c, rpacket);
3555 packet_del_ref(rpacket);
3556 }
3557 } else
3558 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client tried to set game status DONE to destroyed game", conn_get_socket(c));
3559 }
3560
3561 return 0;
3562 }
3563
_client_startgame3(t_connection * c,t_packet const * const packet)3564 static int _client_startgame3(t_connection * c, t_packet const *const packet)
3565 {
3566 t_packet *rpacket;
3567
3568 if (packet_get_size(packet) < sizeof(t_client_startgame3)) {
3569 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_startgame3), packet_get_size(packet));
3570 return -1;
3571 }
3572
3573 {
3574 char const *gamename;
3575 char const *gamepass;
3576 char const *gameinfo;
3577 unsigned short bngtype;
3578 unsigned int status;
3579 t_game *currgame;
3580
3581 if (!(gamename = packet_get_str_const(packet, sizeof(t_client_startgame3), GAME_NAME_LEN))) {
3582 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (missing or too long gamename)", conn_get_socket(c));
3583 return -1;
3584 }
3585 if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_startgame3) + strlen(gamename) + 1, GAME_PASS_LEN))) {
3586 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (missing or too long gamepass)", conn_get_socket(c));
3587 return -1;
3588 }
3589 if (!(gameinfo = packet_get_str_const(packet, sizeof(t_client_startgame3) + strlen(gamename) + 1 + strlen(gamepass) + 1, GAME_INFO_LEN))) {
3590 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME3 packet (missing or too long gameinfo)", conn_get_socket(c));
3591 return -1;
3592 }
3593 if (conn_get_joingamewhisper_ack(c) == 0) {
3594 if (watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame) == 0)
3595 eventlog(eventlog_level_info, "handle_bnet", "Told Mutual Friends your in game %s", gamename);
3596
3597 conn_set_joingamewhisper_ack(c, 1); //1 = already whispered. We reset this each time user joins a channel
3598 }
3599 bngtype = bn_short_get(packet->u.client_startgame3.gametype);
3600 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got startgame3 status for game \"%s\" is 0x%08x (gametype = 0x%04hx)", conn_get_socket(c), gamename, bn_int_get(packet->u.client_startgame3.status), bngtype);
3601 status = bn_int_get(packet->u.client_startgame3.status) & CLIENT_STARTGAME3_STATUSMASK;
3602
3603 if ((currgame = conn_get_game(c))) {
3604 switch (status) {
3605 case CLIENT_STARTGAME3_STATUS_STARTED:
3606 game_set_status(currgame, game_status_started);
3607 break;
3608 case CLIENT_STARTGAME3_STATUS_FULL:
3609 game_set_status(currgame, game_status_full);
3610 break;
3611 case CLIENT_STARTGAME3_STATUS_OPEN1:
3612 case CLIENT_STARTGAME3_STATUS_OPEN:
3613 game_set_status(currgame, game_status_open);
3614 break;
3615 case CLIENT_STARTGAME3_STATUS_DONE:
3616 game_set_status(currgame, game_status_done);
3617 eventlog(eventlog_level_info, __FUNCTION__, "[%d] game \"%s\" is finished", conn_get_socket(c), gamename);
3618 break;
3619 }
3620 } else if (status != CLIENT_STARTGAME3_STATUS_DONE) {
3621 t_game_type gtype;
3622
3623 gtype = bngtype_to_gtype(conn_get_clienttag(c), bngtype);
3624 if ((gtype == game_type_ladder && account_get_auth_createladdergame(conn_get_account(c)) == 0) || (gtype != game_type_ladder && account_get_auth_createnormalgame(conn_get_account(c)) == 0))
3625 eventlog(eventlog_level_info, __FUNCTION__, "[%d] game start for \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c));
3626 else
3627 conn_set_game(c, gamename, gamepass, gameinfo, gtype, STARTVER_GW3);
3628
3629 if ((rpacket = packet_create(packet_class_bnet))) {
3630 packet_set_size(rpacket, sizeof(t_server_startgame3_ack));
3631 packet_set_type(rpacket, SERVER_STARTGAME3_ACK);
3632
3633 if (conn_get_game(c))
3634 bn_int_set(&rpacket->u.server_startgame3_ack.reply, SERVER_STARTGAME3_ACK_OK);
3635 else
3636 bn_int_set(&rpacket->u.server_startgame3_ack.reply, SERVER_STARTGAME3_ACK_NO);
3637
3638 conn_push_outqueue(c, rpacket);
3639 packet_del_ref(rpacket);
3640 }
3641 } else
3642 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client tried to set game status DONE to destroyed game", conn_get_socket(c));
3643 }
3644
3645 return 0;
3646 }
3647
_client_startgame4(t_connection * c,t_packet const * const packet)3648 static int _client_startgame4(t_connection * c, t_packet const *const packet)
3649 {
3650 t_packet *rpacket;
3651
3652 if (packet_get_size(packet) < sizeof(t_client_startgame4)) {
3653 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_startgame4), packet_get_size(packet));
3654 return -1;
3655 }
3656 // Quick hack to make W3 part channels when creating a game
3657 if (conn_get_channel(c))
3658 conn_set_channel(c, NULL);
3659
3660 {
3661 char const *gamename;
3662 char const *gamepass;
3663 char const *gameinfo;
3664 unsigned short bngtype;
3665 unsigned int status;
3666 unsigned int flag;
3667 unsigned short option;
3668 t_game *currgame;
3669
3670 if (!(gamename = packet_get_str_const(packet, sizeof(t_client_startgame4), GAME_NAME_LEN))) {
3671 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (missing or too long gamename)", conn_get_socket(c));
3672 return -1;
3673 }
3674 if (!(gamepass = packet_get_str_const(packet, sizeof(t_client_startgame4) + strlen(gamename) + 1, GAME_PASS_LEN))) {
3675 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (missing or too long gamepass)", conn_get_socket(c));
3676 return -1;
3677 }
3678 if (!(gameinfo = packet_get_str_const(packet, sizeof(t_client_startgame4) + strlen(gamename) + 1 + strlen(gamepass) + 1, GAME_INFO_LEN))) {
3679 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad STARTGAME4 packet (missing or too long gameinfo)", conn_get_socket(c));
3680 return -1;
3681 }
3682 if (conn_get_joingamewhisper_ack(c) == 0) {
3683 if (watchlist_notify_event(conn_get_account(c), gamename, conn_get_clienttag(c), watch_event_joingame) == 0)
3684 eventlog(eventlog_level_info, "handle_bnet", "Told Mutual Friends your in game %s", gamename);
3685
3686 conn_set_joingamewhisper_ack(c, 1); //1 = already whispered. We reset this each time user joins a channel
3687 }
3688 bngtype = bn_short_get(packet->u.client_startgame4.gametype);
3689 option = bn_short_get(packet->u.client_startgame4.option);
3690 status = bn_int_get(packet->u.client_startgame4.status);
3691 flag = bn_short_get(packet->u.client_startgame4.flag);
3692
3693 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got startgame4 status for game \"%s\" is 0x%08x (gametype=0x%04hx option=0x%04hx, flag=0x%04hx)", conn_get_socket(c), gamename, status, bngtype, option, flag);
3694
3695 if ((currgame = conn_get_game(c))) {
3696 if ((status & CLIENT_STARTGAME4_STATUSMASK_OPEN_VALID) == status) {
3697 if (status & CLIENT_STARTGAME4_STATUS_START)
3698 game_set_status(currgame, game_status_started);
3699 else if (status & CLIENT_STARTGAME4_STATUS_FULL)
3700 game_set_status(currgame, game_status_full);
3701 else
3702 game_set_status(currgame, game_status_open);
3703 } else {
3704 eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown startgame4 status %d (clienttag: %s)", conn_get_socket(c), status, clienttag_uint_to_str(conn_get_clienttag(c)));
3705 }
3706 } else if ((status & CLIENT_STARTGAME4_STATUSMASK_INIT_VALID) == status) {
3707 /*valid creation status would be:
3708 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x80, 0x81, 0x82, 0x83 */
3709
3710 t_game_type gtype;
3711
3712 gtype = bngtype_to_gtype(conn_get_clienttag(c), bngtype);
3713 if ((gtype == game_type_ladder && account_get_auth_createladdergame(conn_get_account(c)) == 0) || (gtype != game_type_ladder && account_get_auth_createnormalgame(conn_get_account(c)) == 0))
3714 eventlog(eventlog_level_info, __FUNCTION__, "[%d] game start for \"%s\" refused (no authority)", conn_get_socket(c), conn_get_username(c));
3715 else if (conn_set_game(c, gamename, gamepass, gameinfo, gtype, STARTVER_GW4) == 0) {
3716 game_set_option(conn_get_game(c), bngoption_to_goption(conn_get_clienttag(c), gtype, option));
3717 if (status & CLIENT_STARTGAME4_STATUS_PRIVATE)
3718 game_set_flag(conn_get_game(c), game_flag_private);
3719 if (status & CLIENT_STARTGAME4_STATUS_FULL)
3720 game_set_status(conn_get_game(c), game_status_full);
3721 if (bngtype == CLIENT_GAMELISTREQ_LOADED) /* PELISH: seems strange but it is really needed for loaded games */
3722 game_set_status(conn_get_game(c), game_status_loaded);
3723 //FIXME: still need special handling for status disc-is-loss and replay
3724 }
3725 } else
3726 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client tried to set game status 0x%x to unexistent game (clienttag: %s)", conn_get_socket(c), status, clienttag_uint_to_str(conn_get_clienttag(c)));
3727 }
3728
3729 if ((rpacket = packet_create(packet_class_bnet))) {
3730 packet_set_size(rpacket, sizeof(t_server_startgame4_ack));
3731 packet_set_type(rpacket, SERVER_STARTGAME4_ACK);
3732
3733 if (conn_get_game(c))
3734 bn_int_set(&rpacket->u.server_startgame4_ack.reply, SERVER_STARTGAME4_ACK_OK);
3735 else
3736 bn_int_set(&rpacket->u.server_startgame4_ack.reply, SERVER_STARTGAME4_ACK_NO);
3737 conn_push_outqueue(c, rpacket);
3738 packet_del_ref(rpacket);
3739 }
3740
3741 /* First, send an ECHO_REQ */
3742 if ((rpacket = packet_create(packet_class_bnet))) {
3743 packet_set_size(rpacket, sizeof(t_server_echoreq));
3744 packet_set_type(rpacket, SERVER_ECHOREQ);
3745 bn_int_set(&rpacket->u.server_echoreq.ticks, get_ticks());
3746 conn_push_outqueue(c, rpacket);
3747 packet_del_ref(rpacket);
3748 }
3749
3750 return 0;
3751 }
3752
_client_closegame(t_connection * c,t_packet const * const packet)3753 static int _client_closegame(t_connection * c, t_packet const *const packet)
3754 {
3755 t_game *game;
3756
3757 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client closing game", conn_get_socket(c));
3758 if (packet_get_type(packet) == CLIENT_CLOSEGAME2 || ((conn_get_clienttag(c) != CLIENTTAG_WARCRAFT3_UINT) && (conn_get_clienttag(c) != CLIENTTAG_WAR3XP_UINT)))
3759 conn_set_game(c, NULL, NULL, NULL, game_type_none, 0);
3760 else if ((game = conn_get_game(c)))
3761 game_set_status(game, game_status_started);
3762
3763 return 0;
3764 }
3765
_client_gamereport(t_connection * c,t_packet const * const packet)3766 static int _client_gamereport(t_connection * c, t_packet const *const packet)
3767 {
3768 if (packet_get_size(packet) < sizeof(t_client_game_report)) {
3769 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad GAME_REPORT packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_game_report), packet_get_size(packet));
3770 return -1;
3771 }
3772
3773 {
3774 t_account *my_account;
3775 t_account *other_account;
3776 t_game *game;
3777 unsigned int player_count;
3778 unsigned int i,s;
3779 t_client_game_report_result const *result_data;
3780 unsigned int result_off;
3781 t_game_result result;
3782 char const *player;
3783 unsigned int player_off;
3784 t_game_result *results;
3785
3786 player_count = bn_int_get(packet->u.client_gamerep.count);
3787
3788 if (!(game = conn_get_game(c))) {
3789 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT when not in a game for user \"%s\"", conn_get_socket(c), conn_get_username(c));
3790 return -1;
3791 }
3792
3793 eventlog(eventlog_level_info, __FUNCTION__, "[%d] CLIENT_GAME_REPORT: %s (%u players)", conn_get_socket(c), conn_get_username(c), player_count);
3794 my_account = conn_get_account(c);
3795
3796 results = xmalloc(sizeof(t_game_result) * game_get_count(game));
3797
3798 for (i = 0; i < game_get_count(game); i++)
3799 results[i] = game_result_none;
3800
3801 for (i = 0, result_off = sizeof(t_client_game_report), player_off = sizeof(t_client_game_report) + player_count * sizeof(t_client_game_report_result); i < player_count; i++, result_off += sizeof(t_client_game_report_result), player_off += strlen(player) + 1) {
3802 if (!(result_data = packet_get_data_const(packet, result_off, sizeof(t_client_game_report_result)))) {
3803 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got corrupt GAME_REPORT packet (missing results %u-%u)", conn_get_socket(c), i + 1, player_count);
3804 break;
3805 }
3806 if (!(player = packet_get_str_const(packet, player_off, USER_NAME_MAX))) {
3807 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got corrupt GAME_REPORT packet (missing players %u-%u)", conn_get_socket(c), i + 1, player_count);
3808 break;
3809 }
3810
3811 if (player[0] == '\0') /* empty slots have empty player name */
3812 continue;
3813
3814 if (i >= game_get_count(game)) {
3815 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got more results than the game had players - ignoring extra results", conn_get_socket(c));
3816 break;
3817 }
3818
3819 if (!(other_account = accountlist_find_account(player))) {
3820 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT with unknown player \"%s\"", conn_get_socket(c), player);
3821 break;
3822 }
3823
3824 // as player position in game structure and in game report might differ,
3825 // search for right position
3826 for (s=0; s<game_get_count(game); s++)
3827 {
3828 if (game_get_player(game,s)==other_account) break;
3829 }
3830
3831 if (s<game_get_count(game))
3832 {
3833 result = bngresult_to_gresult(bn_int_get(result_data->result));
3834 results[s] = result;
3835 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got player %d (\"%s\") result %s", conn_get_socket(c), i, player, game_result_get_str(result));
3836 }
3837 else
3838 {
3839 eventlog(eventlog_level_error,__FUNCTION__,"[%d] got GAME_REPORT for non-participating player \"%s\"",conn_get_socket(c),player);
3840 }
3841
3842 }
3843
3844 if (i == player_count) { /* if everything checked out... */
3845 char const *head;
3846 char const *body;
3847
3848 if (!(head = packet_get_str_const(packet, player_off, MAX_GAMEREP_HEAD_STR)))
3849 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT with missing or too long report head", conn_get_socket(c));
3850 else {
3851 player_off += strlen(head) + 1;
3852 if (!(body = packet_get_str_const(packet, player_off, MAX_GAMEREP_BODY_STR)))
3853 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got GAME_REPORT with missing or too ling report body", conn_get_socket(c));
3854 else
3855 game_set_report(game, my_account, head, body);
3856 }
3857 }
3858
3859 if (game_set_reported_results(game, my_account, results) < 0)
3860 xfree((void *) results);
3861
3862 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] finished parsing result... now leaving game", conn_get_socket(c));
3863 conn_set_game(c, NULL, NULL, NULL, game_type_none, 0);
3864 }
3865
3866 return 0;
3867 }
3868
_client_leavechannel(t_connection * c,t_packet const * const packet)3869 static int _client_leavechannel(t_connection * c, t_packet const *const packet)
3870 {
3871 /* If this user in a channel, notify everyone that the user has left */
3872 if (conn_get_channel(c))
3873 conn_set_channel(c, NULL);
3874 return 0;
3875 }
3876
_client_ladderreq(t_connection * c,t_packet const * const packet)3877 static int _client_ladderreq(t_connection * c, t_packet const *const packet)
3878 {
3879 t_packet *rpacket;
3880
3881
3882 if (packet_get_size(packet) < sizeof(t_client_ladderreq)) {
3883 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LADDERREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_ladderreq), packet_get_size(packet));
3884 return -1;
3885 }
3886
3887 {
3888 t_ladder_entry entry;
3889 unsigned int i;
3890 unsigned int type;
3891 unsigned int start;
3892 unsigned int count;
3893 unsigned int idnum;
3894 t_account *account;
3895 t_clienttag clienttag;
3896 char const *timestr;
3897 t_bnettime bt;
3898 t_ladder_id id;
3899
3900 clienttag = conn_get_clienttag(c);
3901
3902 type = bn_int_get(packet->u.client_ladderreq.type);
3903 start = bn_int_get(packet->u.client_ladderreq.startplace);
3904 count = bn_int_get(packet->u.client_ladderreq.count);
3905 idnum = bn_int_get(packet->u.client_ladderreq.id);
3906
3907 /* eventlog(eventlog_level_debug,__FUNCTION__,"got LADDERREQ type=%u start=%u count=%u id=%u",type,start,count,id); */
3908
3909 switch (idnum) {
3910 case CLIENT_LADDERREQ_ID_STANDARD:
3911 id = ladder_id_normal;
3912 break;
3913 case CLIENT_LADDERREQ_ID_IRONMAN:
3914 id = ladder_id_ironman;
3915 break;
3916 default:
3917 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown ladder ladderreq.id=0x%08x", conn_get_socket(c), idnum);
3918 id = ladder_id_normal;
3919 }
3920
3921 if (!(rpacket = packet_create(packet_class_bnet)))
3922 return -1;
3923 packet_set_size(rpacket, sizeof(t_server_ladderreply));
3924 packet_set_type(rpacket, SERVER_LADDERREPLY);
3925
3926 bn_int_set(&rpacket->u.server_ladderreply.clienttag, clienttag);
3927 bn_int_set(&rpacket->u.server_ladderreply.id, idnum);
3928 bn_int_set(&rpacket->u.server_ladderreply.type, type);
3929 bn_int_set(&rpacket->u.server_ladderreply.startplace, start);
3930 bn_int_set(&rpacket->u.server_ladderreply.count, count);
3931
3932 for (i = start; i < start + count; i++) {
3933 switch (type) {
3934 case CLIENT_LADDERREQ_TYPE_HIGHESTRATED:
3935 if (!(account = ladder_get_account_by_rank(i + 1, ladder_sort_highestrated, ladder_time_active, clienttag, id)))
3936 account = ladder_get_account_by_rank(i + 1, ladder_sort_highestrated, ladder_time_current, clienttag, id);
3937 break;
3938 case CLIENT_LADDERREQ_TYPE_MOSTWINS:
3939 if (!(account = ladder_get_account_by_rank(i + 1, ladder_sort_mostwins, ladder_time_active, clienttag, id)))
3940 account = ladder_get_account_by_rank(i + 1, ladder_sort_mostwins, ladder_time_current, clienttag, id);
3941 break;
3942 case CLIENT_LADDERREQ_TYPE_MOSTGAMES:
3943 if (!(account = ladder_get_account_by_rank(i + 1, ladder_sort_mostgames, ladder_time_active, clienttag, id)))
3944 account = ladder_get_account_by_rank(i + 1, ladder_sort_mostgames, ladder_time_current, clienttag, id);
3945 break;
3946 default:
3947 account = NULL;
3948 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown value for ladderreq.type=%u", conn_get_socket(c), type);
3949 }
3950
3951 if (account) {
3952 bn_int_set(&entry.active.wins, account_get_ladder_active_wins(account, clienttag, id));
3953 bn_int_set(&entry.active.loss, account_get_ladder_active_losses(account, clienttag, id));
3954 bn_int_set(&entry.active.disconnect, account_get_ladder_active_disconnects(account, clienttag, id));
3955 bn_int_set(&entry.active.rating, account_get_ladder_active_rating(account, clienttag, id));
3956 bn_int_set(&entry.active.rank, account_get_ladder_active_rank(account,clienttag,id)-1);
3957 if (!(timestr = account_get_ladder_active_last_time(account, clienttag, id)))
3958 timestr = BNETD_LADDER_DEFAULT_TIME;
3959 bnettime_set_str(&bt, timestr);
3960 bnettime_to_bn_long(bt, &entry.lastgame_active);
3961
3962 bn_int_set(&entry.current.wins, account_get_ladder_wins(account, clienttag, id));
3963 bn_int_set(&entry.current.loss, account_get_ladder_losses(account, clienttag, id));
3964 bn_int_set(&entry.current.disconnect, account_get_ladder_disconnects(account, clienttag, id));
3965 bn_int_set(&entry.current.rating, account_get_ladder_rating(account, clienttag, id));
3966 bn_int_set(&entry.current.rank, account_get_ladder_rank(account,clienttag,id)-1);
3967 if (!(timestr = account_get_ladder_last_time(account, clienttag, id)))
3968 timestr = BNETD_LADDER_DEFAULT_TIME;
3969 bnettime_set_str(&bt, timestr);
3970 bnettime_to_bn_long(bt, &entry.lastgame_current);
3971 } else {
3972 bn_int_set(&entry.active.wins, 0);
3973 bn_int_set(&entry.active.loss, 0);
3974 bn_int_set(&entry.active.disconnect, 0);
3975 bn_int_set(&entry.active.rating, 0);
3976 bn_int_set(&entry.active.rank, 0);
3977 bn_long_set_a_b(&entry.lastgame_active, 0, 0);
3978
3979 bn_int_set(&entry.current.wins, 0);
3980 bn_int_set(&entry.current.loss, 0);
3981 bn_int_set(&entry.current.disconnect, 0);
3982 bn_int_set(&entry.current.rating, 0);
3983 bn_int_set(&entry.current.rank, 0);
3984 bn_long_set_a_b(&entry.lastgame_current, 0, 0);
3985 }
3986
3987 bn_int_set(&entry.ttest[0], i); // rank
3988 bn_int_set(&entry.ttest[1], 0); //
3989 bn_int_set(&entry.ttest[2], 0); //
3990 if (account)
3991 bn_int_set(&entry.ttest[3], account_get_ladder_high_rating(account, clienttag, id));
3992 else
3993 bn_int_set(&entry.ttest[3], 0);
3994 bn_int_set(&entry.ttest[4], 0); //
3995 bn_int_set(&entry.ttest[5], 0); //
3996
3997 packet_append_data(rpacket, &entry, sizeof(entry));
3998
3999 if (account)
4000 packet_append_string(rpacket, account_get_name(account));
4001 else
4002 packet_append_string(rpacket, " "); /* use a space so the client won't show the user's own account when double-clicked on */
4003 }
4004
4005 conn_push_outqueue(c, rpacket);
4006 packet_del_ref(rpacket);
4007 }
4008
4009 return 0;
4010 }
4011
_client_laddersearchreq(t_connection * c,t_packet const * const packet)4012 static int _client_laddersearchreq(t_connection * c, t_packet const *const packet)
4013 {
4014 t_packet *rpacket;
4015
4016 if (packet_get_size(packet) < sizeof(t_client_laddersearchreq)) {
4017 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LADDERSEARCHREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_laddersearchreq), packet_get_size(packet));
4018 return -1;
4019 }
4020
4021 {
4022 char const *playername;
4023 t_account *account;
4024 unsigned int idnum;
4025 unsigned int rank; /* starts at zero */
4026 t_ladder_id id;
4027 t_clienttag ctag = conn_get_clienttag(c);
4028
4029 idnum = bn_int_get(packet->u.client_laddersearchreq.id);
4030
4031 switch (idnum) {
4032 case CLIENT_LADDERREQ_ID_STANDARD:
4033 id = ladder_id_normal;
4034 break;
4035 case CLIENT_LADDERREQ_ID_IRONMAN:
4036 id = ladder_id_ironman;
4037 break;
4038 default:
4039 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown ladder laddersearchreq.id=0x%08x", conn_get_socket(c), idnum);
4040 id = ladder_id_normal;
4041 }
4042
4043 if (!(playername = packet_get_str_const(packet, sizeof(t_client_laddersearchreq), USER_NAME_MAX))) {
4044 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad LADDERSEARCHREQ packet (missing or too long playername)", conn_get_socket(c));
4045 return -1;
4046 }
4047
4048 if (!(account = accountlist_find_account(playername)))
4049 rank = SERVER_LADDERSEARCHREPLY_RANK_NONE;
4050 else {
4051 switch (bn_int_get(packet->u.client_laddersearchreq.type)) {
4052 case CLIENT_LADDERSEARCHREQ_TYPE_HIGHESTRATED:
4053 if (!(rank=ladder_get_rank_by_account(account, ladder_sort_highestrated, ladder_time_active, ctag, id)))
4054 {
4055 if (!(rank = ladder_get_rank_by_account(account, ladder_sort_highestrated,
4056 ladder_time_current, ctag, id)) ||
4057 (ladder_get_account_by_rank(rank, ladder_sort_highestrated, ladder_time_active, ctag, id)))
4058 rank = 0;
4059 }
4060 break;
4061 case CLIENT_LADDERSEARCHREQ_TYPE_MOSTWINS:
4062 if (!(rank=ladder_get_rank_by_account(account, ladder_sort_mostwins, ladder_time_active, ctag, id)))
4063 {
4064 if (!(rank = ladder_get_rank_by_account(account, ladder_sort_mostwins,
4065 ladder_time_current, ctag, id)) ||
4066 (ladder_get_account_by_rank(rank, ladder_sort_mostwins, ladder_time_active, ctag, id)))
4067 rank = 0;
4068 }
4069 break;
4070 case CLIENT_LADDERSEARCHREQ_TYPE_MOSTGAMES:
4071 if (!(rank=ladder_get_rank_by_account(account, ladder_sort_mostgames, ladder_time_active, ctag, id)))
4072 {
4073 if (!(rank = ladder_get_rank_by_account(account, ladder_sort_mostgames,
4074 ladder_time_current, ctag, id)) ||
4075 (ladder_get_account_by_rank(rank, ladder_sort_mostgames, ladder_time_active, ctag, id)))
4076 rank = 0;
4077 }
4078 break;
4079 default:
4080 rank = 0;
4081 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got unknown ladder search type %u", conn_get_socket(c), bn_int_get(packet->u.client_laddersearchreq.type));
4082 }
4083
4084 if (rank == 0)
4085 rank = SERVER_LADDERSEARCHREPLY_RANK_NONE;
4086 else
4087 rank--;
4088 }
4089
4090 if (!(rpacket = packet_create(packet_class_bnet)))
4091 return -1;
4092 packet_set_size(rpacket, sizeof(t_server_laddersearchreply));
4093 packet_set_type(rpacket, SERVER_LADDERSEARCHREPLY);
4094 bn_int_set(&rpacket->u.server_laddersearchreply.rank, rank);
4095 conn_push_outqueue(c, rpacket);
4096 packet_del_ref(rpacket);
4097 }
4098
4099 return 0;
4100 }
4101
_client_mapauthreq1(t_connection * c,t_packet const * const packet)4102 static int _client_mapauthreq1(t_connection * c, t_packet const *const packet)
4103 {
4104 t_packet *rpacket;
4105
4106 if (packet_get_size(packet) < sizeof(t_client_mapauthreq1)) {
4107 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ1 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_mapauthreq1), packet_get_size(packet));
4108 return -1;
4109 }
4110
4111 {
4112 char const *mapname;
4113 t_game *game;
4114
4115 if (!(mapname = packet_get_str_const(packet, sizeof(t_client_mapauthreq1), MAP_NAME_LEN))) {
4116 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ1 packet (missing or too long mapname)", conn_get_socket(c));
4117 return -1;
4118 }
4119
4120 game = conn_get_game(c);
4121
4122 if (game) {
4123 eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested for map \"%s\" gametype \"%s\"", conn_get_socket(c), mapname, game_type_get_str(game_get_type(game)));
4124 game_set_mapname(game, mapname);
4125 } else
4126 eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested when not in a game", conn_get_socket(c));
4127
4128 if ((rpacket = packet_create(packet_class_bnet))) {
4129 unsigned int val;
4130
4131 if (!game) {
4132 val = SERVER_MAPAUTHREPLY1_NO;
4133 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (not in a game)", conn_get_socket(c));
4134 } else if (strcasecmp(game_get_mapname(game), mapname) != 0) {
4135 val = SERVER_MAPAUTHREPLY1_NO;
4136 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (map name \"%s\" does not match game map name \"%s\")", conn_get_socket(c), mapname, game_get_mapname(game));
4137 } else {
4138 game_set_status(game, game_status_started);
4139
4140 if (game_get_type(game) == game_type_ladder) {
4141 val = SERVER_MAPAUTHREPLY1_LADDER_OK;
4142 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (in a ladder game)", conn_get_socket(c));
4143 } else if (ladder_check_map(game_get_mapname(game), game_get_maptype(game), conn_get_clienttag(c))) {
4144 val = SERVER_MAPAUTHREPLY1_LADDER_OK;
4145 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (is a ladder map)", conn_get_socket(c));
4146 } else {
4147 val = SERVER_MAPAUTHREPLY1_OK;
4148 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map normal authorization", conn_get_socket(c));
4149 }
4150 }
4151
4152 packet_set_size(rpacket, sizeof(t_server_mapauthreply1));
4153 packet_set_type(rpacket, SERVER_MAPAUTHREPLY1);
4154 bn_int_set(&rpacket->u.server_mapauthreply1.response, val);
4155 conn_push_outqueue(c, rpacket);
4156 packet_del_ref(rpacket);
4157 }
4158 }
4159
4160 return 0;
4161 }
4162
_client_mapauthreq2(t_connection * c,t_packet const * const packet)4163 static int _client_mapauthreq2(t_connection * c, t_packet const *const packet)
4164 {
4165 t_packet *rpacket;
4166
4167 if (packet_get_size(packet) < sizeof(t_client_mapauthreq2)) {
4168 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ2 packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_mapauthreq2), packet_get_size(packet));
4169 return -1;
4170 }
4171
4172 {
4173 char const *mapname;
4174 t_game *game;
4175
4176 if (!(mapname = packet_get_str_const(packet, sizeof(t_client_mapauthreq2), MAP_NAME_LEN))) {
4177 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad MAPAUTHREQ2 packet (missing or too long mapname)", conn_get_socket(c));
4178 return -1;
4179 }
4180
4181 game = conn_get_game(c);
4182
4183 if (game) {
4184 eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested for map \"%s\" gametype \"%s\"", conn_get_socket(c), mapname, game_type_get_str(game_get_type(game)));
4185 game_set_mapname(game, mapname);
4186 } else
4187 eventlog(eventlog_level_info, __FUNCTION__, "[%d] map auth requested when not in a game", conn_get_socket(c));
4188
4189 if ((rpacket = packet_create(packet_class_bnet))) {
4190 unsigned int val;
4191
4192 if (!game) {
4193 val = SERVER_MAPAUTHREPLY2_NO;
4194 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (not in a game)", conn_get_socket(c));
4195 } else if (strcasecmp(game_get_mapname(game), mapname) != 0) {
4196 val = SERVER_MAPAUTHREPLY2_NO;
4197 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] map authorization denied (map name \"%s\" does not match game map name \"%s\")", conn_get_socket(c), mapname, game_get_mapname(game));
4198 } else {
4199 game_set_status(game, game_status_started);
4200
4201 if (game_get_type(game) == game_type_ladder) {
4202 val = SERVER_MAPAUTHREPLY2_LADDER_OK;
4203 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (in a ladder game)", conn_get_socket(c));
4204 } else if (ladder_check_map(game_get_mapname(game), game_get_maptype(game), conn_get_clienttag(c))) {
4205 val = SERVER_MAPAUTHREPLY2_LADDER_OK;
4206 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map ladder authorization (is a ladder map)", conn_get_socket(c));
4207 } else {
4208 val = SERVER_MAPAUTHREPLY2_OK;
4209 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] giving map normal authorization", conn_get_socket(c));
4210 }
4211 }
4212
4213 packet_set_size(rpacket, sizeof(t_server_mapauthreply2));
4214 packet_set_type(rpacket, SERVER_MAPAUTHREPLY2);
4215 bn_int_set(&rpacket->u.server_mapauthreply2.response, val);
4216 conn_push_outqueue(c, rpacket);
4217 packet_del_ref(rpacket);
4218 }
4219 }
4220
4221 return 0;
4222 }
4223
_client_changeclient(t_connection * c,t_packet const * const packet)4224 static int _client_changeclient(t_connection * c, t_packet const *const packet)
4225 {
4226 t_versioncheck *vc;
4227
4228 if (packet_get_size(packet) < sizeof(t_client_changeclient)) {
4229 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad CLIENT_CHANGECLIENT packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_changeclient), packet_get_size(packet));
4230 return -1;
4231 }
4232
4233 if (_check_allowed_client(bn_int_get(packet->u.client_changeclient.clienttag))) {
4234 conn_set_state(c, conn_state_destroy);
4235 return 0;
4236 }
4237
4238 conn_set_clienttag(c, bn_int_get(packet->u.client_changeclient.clienttag));
4239
4240 vc = conn_get_versioncheck(c);
4241 versioncheck_set_versiontag(vc, clienttag_uint_to_str(conn_get_clienttag(c)));
4242
4243 if (vc && versioncheck_get_versiontag(vc)) {
4244 switch (versioncheck_validate(vc, conn_get_archtag(c), conn_get_clienttag(c), conn_get_clientexe(c), conn_get_versionid(c), conn_get_gameversion(c), conn_get_checksum(c))) {
4245 case -1: /* failed test... client has been modified */
4246 case 0: /* not listed in table... can't tell if client has been modified */
4247 eventlog(eventlog_level_error, __FUNCTION__, "[%d] error revalidating, allowing anyway", conn_get_socket(c));
4248 break;
4249 }
4250
4251 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client versiontag set to \"%s\"", conn_get_socket(c), versioncheck_get_versiontag(vc));
4252 }
4253
4254 return 0;
4255 }
4256
_client_w3xp_clanmemberlistreq(t_connection * c,t_packet const * const packet)4257 static int _client_w3xp_clanmemberlistreq(t_connection * c, t_packet const *const packet)
4258 {
4259 if (packet_get_size(packet) < sizeof(t_client_w3xp_clanmemberlist_req)) {
4260 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBERLIST_REQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clanmemberlist_req), packet_get_size(packet));
4261 return -1;
4262 }
4263
4264 clan_send_memberlist(c, packet);
4265 return 0;
4266 }
4267
_client_w3xp_clan_motdreq(t_connection * c,t_packet const * const packet)4268 static int _client_w3xp_clan_motdreq(t_connection * c, t_packet const *const packet)
4269 {
4270 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_motdreq)) {
4271 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_MOTDREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_motdreq), packet_get_size(packet));
4272 return -1;
4273 }
4274
4275 clan_send_motd_reply(c, packet);
4276 return 0;
4277 }
4278
_client_w3xp_clan_motdchg(t_connection * c,t_packet const * const packet)4279 static int _client_w3xp_clan_motdchg(t_connection * c, t_packet const *const packet)
4280 {
4281 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_motdreq)) {
4282 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_MOTDCHGREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_motdreq), packet_get_size(packet));
4283 return -1;
4284 }
4285
4286 clan_save_motd_chg(c, packet);
4287 return 0;
4288 }
4289
_client_w3xp_clan_disbandreq(t_connection * c,t_packet const * const packet)4290 static int _client_w3xp_clan_disbandreq(t_connection * c, t_packet const *const packet)
4291 {
4292 t_packet *rpacket;
4293
4294 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_disbandreq)) {
4295 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_DISBANDREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_disbandreq), packet_get_size(packet));
4296 return -1;
4297 }
4298
4299 if ((rpacket = packet_create(packet_class_bnet))) {
4300 t_clan *clan;
4301 t_clanmember *member;
4302 t_account *account;
4303
4304 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_disbandreply));
4305 packet_set_type(rpacket, SERVER_W3XP_CLAN_DISBANDREPLY);
4306 bn_int_set(&rpacket->u.server_w3xp_clan_disbandreply.count, bn_int_get(packet->u.client_w3xp_clan_disbandreq.count));
4307
4308 if (!((account = conn_get_account(c)) && (clan = account_get_clan(account)) && (member = account_get_clanmember(account)) && (clanmember_get_status(member) >= CLAN_CHIEFTAIN))) {
4309 eventlog(eventlog_level_warn, __FUNCTION__, "[%d] got suspicious W3XP_CLAN_DISBANDREQ packet (request without required privileges)", conn_get_socket(c));
4310 bn_byte_set(&rpacket->u.server_w3xp_clan_disbandreply.result, SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_NOT_AUTHORIZED);
4311 conn_push_outqueue(c, rpacket);
4312 packet_del_ref(rpacket);
4313 } else if ((clanlist_remove_clan(clan) == 0) && (clan_remove(clan_get_clantag(clan)) == 0)) {
4314 bn_byte_set(&rpacket->u.server_w3xp_clan_disbandreply.result, SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_OK);
4315 clan_close_status_window_on_disband(clan);
4316 clan_send_packet_to_online_members(clan, rpacket);
4317 packet_del_ref(rpacket);
4318 clan_destroy(clan);
4319 } else {
4320 bn_byte_set(&rpacket->u.server_w3xp_clan_disbandreply.result, SERVER_W3XP_CLAN_DISBANDREPLY_RESULT_EXCEPTION);
4321 conn_push_outqueue(c, rpacket);
4322 packet_del_ref(rpacket);
4323 }
4324 }
4325
4326 return 0;
4327 }
4328
_client_w3xp_clan_createreq(t_connection * c,t_packet const * const packet)4329 static int _client_w3xp_clan_createreq(t_connection * c, t_packet const *const packet)
4330 {
4331 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_createreq)) {
4332 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INFOREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet));
4333 return -1;
4334 }
4335
4336 clan_get_possible_member(c, packet);
4337
4338 return 0;
4339 }
4340
_client_w3xp_clan_createinvitereq(t_connection * c,t_packet const * const packet)4341 static int _client_w3xp_clan_createinvitereq(t_connection * c, t_packet const *const packet)
4342 {
4343 t_packet *rpacket;
4344 int size;
4345 const char *clanname;
4346 const char *username;
4347 int clantag;
4348 int offset;
4349 t_clan *clan;
4350
4351 if ((size = packet_get_size(packet)) < sizeof(t_client_w3xp_clan_createinvitereq)) {
4352 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createinvitereq), packet_get_size(packet));
4353 return -1;
4354 }
4355 offset = sizeof(t_client_w3xp_clan_createinvitereq);
4356
4357 if (!(clanname = packet_get_str_const(packet, offset, CLAN_NAME_MAX))) {
4358 eventlog(eventlog_level_error,__FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (missing clanname)", conn_get_socket(c));
4359 return -1;
4360 }
4361 offset += (strlen(clanname) + 1);
4362
4363 if (packet_get_size(packet) < offset+4) {
4364 eventlog(eventlog_level_error,__FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (missing clantag)", conn_get_socket(c));
4365 return -1;
4366 }
4367 clantag = *((int *) packet_get_data_const(packet, offset, 4));
4368 offset += 4;
4369
4370 if ((rpacket = packet_create(packet_class_bnet))) {
4371 if ((clan = clan_create(conn_get_account(c), clantag, clanname, NULL)) && clanlist_add_clan(clan)) {
4372 char membercount;
4373 if (packet_get_size(packet) < offset+1) {
4374 eventlog(eventlog_level_error,__FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREQ packet (missing membercount)", conn_get_socket(c));
4375 return -1;
4376 }
4377 membercount = *((char *) packet_get_data_const(packet, offset, 1));
4378 clan_set_created(clan, -membercount);
4379 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereq));
4380 packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREQ);
4381 bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereq.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereq.count));
4382 bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereq.clantag, clantag);
4383 packet_append_string(rpacket, clanname);
4384 packet_append_string(rpacket, conn_get_username(c));
4385 packet_append_data(rpacket, packet_get_data_const(packet, offset, size - offset), size - offset);
4386 offset++;
4387 do {
4388 username = packet_get_str_const(packet, offset, USER_NAME_MAX);
4389 if (username) {
4390 t_connection *conn;
4391 offset += (strlen(username) + 1);
4392 if ((conn = connlist_find_connection_by_accountname(username)) != NULL) {
4393 if (prefs_get_clan_newer_time() > 0)
4394 clan_add_member(clan, conn_get_account(conn), CLAN_NEW);
4395 else
4396 clan_add_member(clan, conn_get_account(conn), CLAN_PEON);
4397 conn_push_outqueue(conn, rpacket);
4398 }
4399 }
4400 } while (username && (offset < size));
4401 } else {
4402 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereply));
4403 packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREPLY);
4404 bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereply.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereply.count));
4405 bn_byte_set(&rpacket->u.server_w3xp_clan_createinvitereply.status, 0);
4406 }
4407 packet_del_ref(rpacket);
4408 }
4409
4410 return 0;
4411 }
4412
_client_w3xp_clan_createinvitereply(t_connection * c,t_packet const * const packet)4413 static int _client_w3xp_clan_createinvitereply(t_connection * c, t_packet const *const packet)
4414 {
4415 t_packet *rpacket;
4416 t_connection *conn;
4417 t_clan *clan;
4418 const char *username;
4419 int offset;
4420 char status;
4421
4422 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_createinvitereply)) {
4423 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createinvitereq), packet_get_size(packet));
4424 return -1;
4425 }
4426 offset = sizeof(t_client_w3xp_clan_createinvitereply);
4427 username = packet_get_str_const(packet, offset, USER_NAME_MAX);
4428 offset += (strlen(username) + 1);
4429 if (packet_get_size(packet) < offset+1) {
4430 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_CREATEINVITEREPLY packet (mising status)", conn_get_socket(c));
4431 return -1;
4432 }
4433 status = *((char *) packet_get_data_const(packet, offset, 1));
4434 if ((conn = connlist_find_connection_by_accountname(username)) == NULL)
4435 return -1;
4436 if ((clan = account_get_creating_clan(conn_get_account(conn))) == NULL)
4437 return -1;
4438 if ((status != W3XP_CLAN_INVITEREPLY_ACCEPT) && (rpacket = packet_create(packet_class_bnet))) {
4439 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereply));
4440 packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREPLY);
4441 bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereply.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereply.count));
4442 bn_byte_set(&rpacket->u.server_w3xp_clan_createinvitereply.status, status);
4443 packet_append_string(rpacket, conn_get_username(c));
4444 conn_push_outqueue(conn, rpacket);
4445 packet_del_ref(rpacket);
4446 if (clan) {
4447 clanlist_remove_clan(clan);
4448 clan_destroy(clan);
4449 }
4450 } else {
4451 int created = clan_get_created(clan);
4452 if (created > 0) {
4453 eventlog(eventlog_level_error, __FUNCTION__, "clan %s has already been created", clan_get_name(clan));
4454 return 0;
4455 }
4456 created++;
4457 if ((created >= 0) && (rpacket = packet_create(packet_class_bnet))) {
4458 clan_set_created(clan, 1);
4459 clan_set_creation_time(clan, time(NULL));
4460 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createinvitereply));
4461 packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEINVITEREPLY);
4462 bn_int_set(&rpacket->u.server_w3xp_clan_createinvitereply.count, bn_int_get(packet->u.client_w3xp_clan_createinvitereply.count));
4463 bn_byte_set(&rpacket->u.server_w3xp_clan_createinvitereply.status, 0);
4464 packet_append_string(rpacket, "");
4465 conn_push_outqueue(conn, rpacket);
4466 packet_del_ref(rpacket);
4467 clan_send_status_window_on_create(clan);
4468 clan_save(clan);
4469 } else
4470 clan_set_created(clan, created);
4471 }
4472 return 0;
4473 }
4474
_client_w3xp_clanmember_rankupdatereq(t_connection * c,t_packet const * const packet)4475 static int _client_w3xp_clanmember_rankupdatereq(t_connection * c, t_packet const *const packet)
4476 {
4477 t_packet *rpacket;
4478
4479 if (packet_get_size(packet) < sizeof(t_client_w3xp_clanmember_rankupdate_req)) {
4480 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBER_RANKUPDATE_REQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clanmember_rankupdate_req), packet_get_size(packet));
4481 return -1;
4482 }
4483
4484 if ((rpacket = packet_create(packet_class_bnet)) != NULL) {
4485 int offset = sizeof(t_client_w3xp_clanmember_rankupdate_req);
4486 const char *username;
4487 char status;
4488 t_clan *clan;
4489 t_clanmember *dest_member;
4490 t_clanmember *member;
4491 t_account *account;
4492
4493 packet_set_size(rpacket, sizeof(t_server_w3xp_clanmember_rankupdate_reply));
4494 packet_set_type(rpacket, SERVER_W3XP_CLANMEMBER_RANKUPDATE_REPLY);
4495 bn_int_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.count,
4496 bn_int_get(packet->u.client_w3xp_clanmember_rankupdate_req.count));
4497 username = packet_get_str_const(packet, offset, USER_NAME_MAX);
4498 offset += (strlen(username) + 1);
4499 if (packet_get_size(packet) < offset+1) {
4500 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBER_RANKUPDATE_REQ packet (mising status)", conn_get_socket(c));
4501 return -1;
4502 }
4503 status = *((char *) packet_get_data_const(packet, offset, 1));
4504
4505 account = (conn_get_account(c));
4506
4507 if ((clan = account_get_clan(account)) && (member = clan_find_member(clan,account))
4508 && (dest_member = clan_find_member_by_name(clan, username)) && (member != dest_member)) {
4509 if ((status < CLAN_PEON) || (status > CLAN_SHAMAN)) {
4510 /* PELISH: CLAN_NEW can not be promoted to anything
4511 * and also noone can be promoted to CLAN_CHIEFTAIN */
4512 DEBUG1("trying to change to bad status %u", status);
4513 bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_FAILED);
4514 }
4515 else if ((((clanmember_get_status(member) == CLAN_SHAMAN) && (status < CLAN_SHAMAN) && (clanmember_get_status(dest_member) < CLAN_SHAMAN)) ||
4516 (clanmember_get_status(member) == CLAN_CHIEFTAIN)) &&
4517 (clanmember_set_status(dest_member, status) == 0)) {
4518 bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_SUCCESS);
4519 clanmember_on_change_status(dest_member);
4520 }
4521 else {
4522 bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_FAILED);
4523 }
4524 }
4525 else
4526 {
4527 bn_byte_set(&rpacket->u.server_w3xp_clanmember_rankupdate_reply.result, SERVER_W3XP_CLANMEMBER_RANKUPDATE_FAILED);
4528 }
4529 conn_push_outqueue(c, rpacket);
4530 packet_del_ref(rpacket);
4531 }
4532
4533 return 0;
4534 }
4535
_client_w3xp_clanmember_removereq(t_connection * c,t_packet const * const packet)4536 static int _client_w3xp_clanmember_removereq(t_connection * c, t_packet const *const packet)
4537 {
4538 t_packet *rpacket;
4539
4540 if (packet_get_size(packet) < sizeof(t_client_w3xp_clanmember_remove_req)) {
4541 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLANMEMBER_REMOVE_REQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clanmember_remove_req), packet_get_size(packet));
4542 return -1;
4543 }
4544
4545 if ((rpacket = packet_create(packet_class_bnet)) != NULL) {
4546 t_account *acc;
4547 t_clan *clan;
4548 const char *username;
4549 t_clanmember *member;
4550 t_connection *dest_conn;
4551 packet_set_size(rpacket, sizeof(t_server_w3xp_clanmember_remove_reply));
4552 packet_set_type(rpacket, SERVER_W3XP_CLANMEMBER_REMOVE_REPLY);
4553 bn_int_set(&rpacket->u.server_w3xp_clanmember_remove_reply.count,
4554 bn_int_get(packet->u.client_w3xp_clanmember_remove_req.count));
4555 username = packet_get_str_const(packet, sizeof(t_client_w3xp_clanmember_remove_req), USER_NAME_MAX);
4556 bn_byte_set(&rpacket->u.server_w3xp_clanmember_remove_reply.result,
4557 SERVER_W3XP_CLANMEMBER_REMOVE_FAILED); // initially presume it failed
4558
4559 if ((acc = conn_get_account(c)) && (clan = account_get_clan(acc)) && (member = clan_find_member_by_name(clan, username))) {
4560 dest_conn = clanmember_get_conn(member);
4561 if (clan_remove_member(clan, member) == 0) {
4562 t_packet *rpacket2;
4563 if (dest_conn) {
4564 clan_close_status_window(dest_conn);
4565 conn_update_w3_playerinfo(dest_conn);
4566 channel_rejoin(dest_conn);
4567 }
4568 if ((rpacket2 = packet_create(packet_class_bnet)) != NULL) {
4569 packet_set_size(rpacket2, sizeof(t_server_w3xp_clanmember_removed_notify));
4570 packet_set_type(rpacket2, SERVER_W3XP_CLANMEMBER_REMOVED_NOTIFY);
4571 packet_append_string(rpacket2, username);
4572 clan_send_packet_to_online_members(clan, rpacket2);
4573 packet_del_ref(rpacket2);
4574 }
4575 bn_byte_set(&rpacket->u.server_w3xp_clanmember_remove_reply.result,
4576 SERVER_W3XP_CLANMEMBER_REMOVE_SUCCESS);
4577 }
4578 }
4579 conn_push_outqueue(c, rpacket);
4580 packet_del_ref(rpacket);
4581 }
4582
4583 return 0;
4584 }
4585
_client_w3xp_clan_membernewchiefreq(t_connection * c,t_packet const * const packet)4586 static int _client_w3xp_clan_membernewchiefreq(t_connection * c, t_packet const *const packet)
4587 {
4588 t_packet *rpacket;
4589
4590 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_membernewchiefreq)) {
4591 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_MEMBERNEWCHIEFREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet));
4592 return -1;
4593 }
4594
4595 if ((rpacket = packet_create(packet_class_bnet)) != NULL) {
4596 t_account *acc;
4597 t_clan *clan;
4598 t_clanmember *oldmember;
4599 t_clanmember *newmember;
4600 const char *username;
4601 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_membernewchiefreply));
4602 packet_set_type(rpacket, SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY);
4603 bn_int_set(&rpacket->u.server_w3xp_clan_membernewchiefreply.count, bn_int_get(packet->u.client_w3xp_clan_membernewchiefreq.count));
4604 username = packet_get_str_const(packet, sizeof(t_client_w3xp_clan_membernewchiefreq), USER_NAME_MAX);
4605 if ((acc = conn_get_account(c)) && (oldmember = account_get_clanmember(acc)) && (clanmember_get_status(oldmember) == CLAN_CHIEFTAIN) && (clan = clanmember_get_clan(oldmember)) && (newmember = clan_find_member_by_name(clan, username)) && (clanmember_set_status(oldmember, CLAN_GRUNT) == 0) && (clanmember_set_status(newmember, CLAN_CHIEFTAIN) == 0)) {
4606 clanmember_on_change_status(oldmember);
4607 clanmember_on_change_status(newmember);
4608 bn_byte_set(&rpacket->u.server_w3xp_clan_membernewchiefreply.result, SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY_SUCCESS);
4609 clan_send_packet_to_online_members(clan, rpacket);
4610 packet_del_ref(rpacket);
4611 } else {
4612 bn_byte_set(&rpacket->u.server_w3xp_clan_membernewchiefreply.result, SERVER_W3XP_CLAN_MEMBERNEWCHIEFREPLY_FAILED);
4613 conn_push_outqueue(c, rpacket);
4614 packet_del_ref(rpacket);
4615 }
4616 }
4617
4618 return 0;
4619 }
4620
_client_w3xp_clan_invitereq(t_connection * c,t_packet const * const packet)4621 static int _client_w3xp_clan_invitereq(t_connection * c, t_packet const *const packet)
4622 {
4623 t_packet *rpacket;
4624 t_clan *clan;
4625 int clantag;
4626 const char *username;
4627 t_connection *conn;
4628
4629 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_invitereq)) {
4630 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREQ packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet));
4631 return -1;
4632 }
4633
4634 if ((clan = account_get_clan(conn_get_account(c))) != NULL) {
4635 if (clan_get_member_count(clan) < prefs_get_clan_max_members()) {
4636 if ((clantag = clan_get_clantag(clan)) && (username = packet_get_str_const(packet, sizeof(t_client_w3xp_clan_invitereq), USER_NAME_MAX)) && (conn = connlist_find_connection_by_accountname(username)) && (rpacket = packet_create(packet_class_bnet))) {
4637 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereq));
4638 packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREQ);
4639 bn_int_set(&rpacket->u.server_w3xp_clan_invitereq.count, bn_int_get(packet->u.client_w3xp_clan_invitereq.count));
4640 bn_int_set(&rpacket->u.server_w3xp_clan_invitereq.clantag, clantag);
4641 packet_append_string(rpacket, clan_get_name(clan));
4642 packet_append_string(rpacket, conn_get_username(c));
4643 conn_push_outqueue(conn, rpacket);
4644 packet_del_ref(rpacket);
4645 }
4646 } else if ((rpacket = packet_create(packet_class_bnet)) != NULL) {
4647 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply));
4648 packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY);
4649 bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereq.count));
4650 bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, W3XP_CLAN_INVITEREPLY_CLANFULL);
4651 conn_push_outqueue(c, rpacket);
4652 packet_del_ref(rpacket);
4653 }
4654 }
4655
4656 return 0;
4657 }
4658
_client_w3xp_clan_invitereply(t_connection * c,t_packet const * const packet)4659 static int _client_w3xp_clan_invitereply(t_connection * c, t_packet const *const packet)
4660 {
4661 t_packet *rpacket;
4662 t_clan *clan;
4663 const char *username;
4664 t_connection *conn;
4665 int offset;
4666 char status;
4667
4668 if (packet_get_size(packet) < sizeof(t_client_w3xp_clan_invitereply)) {
4669 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREPLY packet (expected %u bytes, got %u)", conn_get_socket(c), sizeof(t_client_w3xp_clan_createreq), packet_get_size(packet));
4670 return -1;
4671 }
4672 offset = sizeof(t_client_w3xp_clan_invitereply);
4673
4674 if (!(username = packet_get_str_const(packet, offset, USER_NAME_MAX))) {
4675 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREPLY packet (missing username)", conn_get_socket(c));
4676 return -1;
4677 }
4678 offset += (strlen(username) + 1);
4679
4680 if (packet_get_size(packet) < offset+1) {
4681 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad W3XP_CLAN_INVITEREPLY packet (mising status)", conn_get_socket(c));
4682 return -1;
4683 }
4684 status = *((char *) packet_get_data_const(packet, offset, 1));
4685 if ((conn = connlist_find_connection_by_accountname(username)) != NULL) {
4686 if ((status == W3XP_CLAN_INVITEREPLY_ACCEPT) && (clan = account_get_clan(conn_get_account(conn)))) {
4687 char channelname[10];
4688 int clantag;
4689 if (clan_get_member_count(clan) < prefs_get_clan_max_members()) {
4690 t_clanmember *member = clan_add_member(clan, conn_get_account(c), 1);
4691 if ((member != NULL) && (clantag = clan_get_clantag(clan))) {
4692 sprintf(channelname, "Clan %c%c%c%c", (clantag >> 24), (clantag >> 16) & 0xff, (clantag >> 8) & 0xff, clantag & 0xff);
4693 if (conn_get_channel(c)) {
4694 conn_update_w3_playerinfo(c);
4695 channel_set_userflags(c);
4696 if (conn_set_channel(c, channelname) < 0)
4697 conn_set_channel(c, CHANNEL_NAME_BANNED); /* should not fail */
4698 clanmember_set_online(c);
4699 }
4700 clan_send_status_window(c);
4701 }
4702 if ((rpacket = packet_create(packet_class_bnet)) != NULL) {
4703 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply));
4704 packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY);
4705 bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereply.count));
4706 bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, W3XP_CLAN_INVITEREPLY_SUCCESS);
4707 conn_push_outqueue(conn, rpacket);
4708 packet_del_ref(rpacket);
4709 }
4710 } else if ((rpacket = packet_create(packet_class_bnet)) != NULL) {
4711 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply));
4712 packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY);
4713 bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereply.count));
4714 bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, W3XP_CLAN_INVITEREPLY_CLANFULL);
4715 conn_push_outqueue(conn, rpacket);
4716 packet_del_ref(rpacket);
4717 }
4718 } else if ((rpacket = packet_create(packet_class_bnet)) != NULL) {
4719 packet_set_size(rpacket, sizeof(t_server_w3xp_clan_invitereply));
4720 packet_set_type(rpacket, SERVER_W3XP_CLAN_INVITEREPLY);
4721 bn_int_set(&rpacket->u.server_w3xp_clan_invitereply.count, bn_int_get(packet->u.client_w3xp_clan_invitereply.count));
4722 bn_byte_set(&rpacket->u.server_w3xp_clan_invitereply.result, status);
4723 conn_push_outqueue(conn, rpacket);
4724 packet_del_ref(rpacket);
4725 }
4726 }
4727
4728 return 0;
4729 }
4730
_client_crashdump(t_connection * c,t_packet const * const packet)4731 static int _client_crashdump(t_connection * c, t_packet const *const packet)
4732 {
4733 return 0;
4734 }
4735
_client_setemailreply(t_connection * c,t_packet const * const packet)4736 static int _client_setemailreply(t_connection * c, t_packet const *const packet)
4737 {
4738 char const *email;
4739 t_account *account;
4740
4741 if (!(email = packet_get_str_const(packet, sizeof(t_client_setemailreply), MAX_EMAIL_STR))) {
4742 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad SETEMAILREPLY packet", conn_get_socket(c));
4743 return -1;
4744 }
4745 if (!(account = conn_get_account(c))) {
4746 eventlog(eventlog_level_error, __FUNCTION__, "got NULL account for connection in setemail request");
4747 return -1;
4748 }
4749 if (account_get_email(account)) {
4750 eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" already have email set, ignore set email", conn_get_socket(c), account_get_name(account));
4751 return 0;
4752 }
4753 if (account_set_email(account, email) < 0) {
4754 eventlog(eventlog_level_error, __FUNCTION__, "[%d] failed to init account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), email);
4755 return 0;
4756 } else
4757 eventlog(eventlog_level_info, __FUNCTION__, "[%d] init account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), email);
4758 return 0;
4759 }
4760
_client_changeemailreq(t_connection * c,t_packet const * const packet)4761 static int _client_changeemailreq(t_connection * c, t_packet const *const packet)
4762 {
4763 char const *old;
4764 char const *new;
4765 char const *username;
4766 char const *email;
4767 t_account *account;
4768 int pos;
4769
4770 pos = sizeof(t_client_changeemailreq);
4771 if (!(username = packet_get_str_const(packet, pos, USER_NAME_MAX))) {
4772 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad username in CHANGEEMAILREQ packet", conn_get_socket(c));
4773 return -1;
4774 }
4775 pos += (strlen(username) + 1);
4776 if (!(old = packet_get_str_const(packet, pos, MAX_EMAIL_STR))) {
4777 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad old email in CHANGEEMAILREQ packet", conn_get_socket(c));
4778 return -1;
4779 }
4780 pos += (strlen(old) + 1);
4781 if (!(new = packet_get_str_const(packet, pos, MAX_EMAIL_STR))) {
4782 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad new email in CHANGEEMAILREQ packet", conn_get_socket(c));
4783 return -1;
4784 }
4785 if (!(account = accountlist_find_account(username))) {
4786 eventlog(eventlog_level_info, __FUNCTION__, "[%d] change email for \"%s\" refused (no such account)", conn_get_socket(c), username);
4787 return 0;
4788 }
4789 if (!(email = account_get_email(account)) || !email[0]) {
4790 eventlog(eventlog_level_info, __FUNCTION__, "[%d] account \"%s\" do not have email set, ignore changing", conn_get_socket(c), account_get_name(account));
4791 return 0;
4792 }
4793 if (strcasecmp(email, old)) {
4794 eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" email mismatch, ignore changing", conn_get_socket(c), account_get_name(account));
4795 return 0;
4796 }
4797 if (account_set_email(account, new) < 0) {
4798 eventlog(eventlog_level_error, __FUNCTION__, "[%d] failed to change account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), new);
4799 return 0;
4800 } else
4801 eventlog(eventlog_level_info, __FUNCTION__, "[%d] change account \"%s\" email to \"%s\"", conn_get_socket(c), account_get_name(account), new);
4802 return 0;
4803 }
4804
_client_getpasswordreq(t_connection * c,t_packet const * const packet)4805 static int _client_getpasswordreq(t_connection * c, t_packet const *const packet)
4806 {
4807 char const *username;
4808 char const *try_email;
4809 char const *email;
4810 t_account *account;
4811 int pos;
4812
4813 pos = sizeof(t_client_getpasswordreq);
4814 if (!(username = packet_get_str_const(packet, pos, USER_NAME_MAX))) {
4815 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad username in GETPASSWORDREQ packet", conn_get_socket(c));
4816 return -1;
4817 }
4818 pos += (strlen(username) + 1);
4819 if (!(try_email = packet_get_str_const(packet, pos, MAX_EMAIL_STR))) {
4820 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad email in GETPASSWORDREQ packet", conn_get_socket(c));
4821 return -1;
4822 }
4823 if (!(account = accountlist_find_account(username))) {
4824 eventlog(eventlog_level_info, __FUNCTION__, "[%d] get password for \"%s\" refused (no such account)", conn_get_socket(c), username);
4825 return 0;
4826 }
4827 if (!(email = account_get_email(account)) || !email[0]) {
4828 eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" do not have email set, ignore get password", conn_get_socket(c), account_get_name(account));
4829 return 0;
4830 }
4831 if (strcasecmp(email, try_email)) {
4832 eventlog(eventlog_level_error, __FUNCTION__, "[%d] account \"%s\" email mismatch, ignore get password", conn_get_socket(c), account_get_name(account));
4833 return 0;
4834 }
4835 /* TODO: send mail to user with the real password or changed password!?
4836 * (as we cannot get the real password back, we should only change the password) --Soar */
4837 eventlog(eventlog_level_info, __FUNCTION__, "[%d] get password for account \"%s\" to email \"%s\"", conn_get_socket(c), account_get_name(account), email);
4838 return 0;
4839 }
4840