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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Sat Jun 10 16:20:19 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
Changes since 1.1: +16 -3 lines
Content type: text/x-csrc
Antibot

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

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