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

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

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