/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/handle_bnet.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/bnetd/handle_bnet.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU
CVS Tags: arelease
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
Error occurred while calculating annotation data.
no message

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

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1