/[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.3 - (show annotations)
Thu Jun 22 05:33:55 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, HEAD
Changes since 1.2: +33 -11 lines
Content type: text/x-csrc
Error occurred while calculating annotation data.
Account verification

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

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