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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 sysadm 1.1 /*
2     * Copyright (C) 2000,2001 Onlyer (onlyer@263.net)
3     *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License
6     * as published by the Free Software Foundation; either version 2
7     * of the License, or (at your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the Free Software
16     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17     */
18     #include "common/setup_before.h"
19    
20     #include <stddef.h>
21     #include <stdlib.h>
22     #ifdef HAVE_STRING_H
23     # include <string.h>
24     #else
25     # ifdef HAVE_STRINGS_H
26     # include <strings.h>
27     # endif
28     #endif
29     #include "compat/strcasecmp.h"
30    
31     #include "connection.h"
32     #include "realm.h"
33     #include "account.h"
34     #include "account_wrap.h"
35     #include "game.h"
36     #include "d2cs/d2cs_bnetd_protocol.h"
37     #include "common/bnethash.h"
38     #include "common/bnethashconv.h"
39     #include "common/eventlog.h"
40     #include "common/queue.h"
41     #include "common/packet.h"
42     #include "common/addr.h"
43     #include "common/bn_type.h"
44     #include "prefs.h"
45     #include "common/util.h"
46     #include "common/field_sizes.h"
47     #include "handle_d2cs.h"
48     #include "common/tag.h"
49     #include "common/xalloc.h"
50     #include "common/setup_after.h"
51    
52     static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet);
53     static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet);
54     static int on_d2cs_authreply(t_connection * c, t_packet const * packet);
55     static int on_d2cs_gameinforeply(t_connection * c, t_packet const * packet);
56    
57     extern int handle_d2cs_packet(t_connection * c, t_packet const * packet)
58     {
59     if (!c) {
60     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
61     return -1;
62     }
63     if (!packet) {
64     eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
65     return -1;
66     }
67     if (packet_get_class(packet)!=packet_class_d2cs_bnetd) {
68     eventlog(eventlog_level_error,__FUNCTION__,"got bad packet class %d",
69     packet_get_class(packet));
70     return -1;
71     }
72     switch (conn_get_state(c)) {
73     case conn_state_connected:
74     switch (packet_get_type(packet)) {
75     case D2CS_BNETD_AUTHREPLY:
76     on_d2cs_authreply(c,packet);
77     break;
78     default:
79     eventlog(eventlog_level_error,__FUNCTION__,
80     "got unknown packet type %d",packet_get_type(packet));
81     break;
82     }
83     break;
84     case conn_state_loggedin:
85     switch (packet_get_type(packet)) {
86     case D2CS_BNETD_ACCOUNTLOGINREQ:
87     on_d2cs_accountloginreq(c,packet);
88     break;
89     case D2CS_BNETD_CHARLOGINREQ:
90     on_d2cs_charloginreq(c,packet);
91     break;
92     case D2CS_BNETD_GAMEINFOREPLY:
93     on_d2cs_gameinforeply(c,packet);
94     break;
95     default:
96     eventlog(eventlog_level_error,__FUNCTION__,
97     "got unknown packet type %d",packet_get_type(packet));
98     break;
99     }
100     break;
101     default:
102     eventlog(eventlog_level_error,__FUNCTION__,
103     "got unknown connection state %d",conn_get_state(c));
104     break;
105     }
106     return 0;
107     }
108    
109     static int on_d2cs_authreply(t_connection * c, t_packet const * packet)
110     {
111     t_packet * rpacket;
112     unsigned int version;
113     unsigned int try_version;
114     unsigned int reply;
115     char const * realmname;
116     t_realm * realm;
117    
118     if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_authreply)) {
119     eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size");
120     return -1;
121     }
122     if (!(realmname=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_authreply),REALM_NAME_LEN))) {
123     eventlog(eventlog_level_error,__FUNCTION__,"got bad realmname");
124     return -1;
125     }
126     if (!(realm=realmlist_find_realm(realmname))) {
127     eventlog(eventlog_level_error,__FUNCTION__, "realm not found");
128     return -1;
129     }
130     if (realm_get_name(realm) && strcasecmp(realmname,realm_get_name(realm))) {
131     eventlog(eventlog_level_error,__FUNCTION__, "warn: realm name mismatch %s %s",
132     realm_get_name(realm),realmname);
133     }
134    
135     version=prefs_get_d2cs_version();
136     try_version=bn_int_get(packet->u.d2cs_bnetd_authreply.version);
137     if (version && version != try_version) {
138     eventlog(eventlog_level_error,__FUNCTION__,"d2cs version mismatch 0x%X - 0x%X",
139     try_version,version);
140     reply=BNETD_D2CS_AUTHREPLY_BAD_VERSION;
141     } else {
142     reply=BNETD_D2CS_AUTHREPLY_SUCCEED;
143     }
144    
145     if (reply==BNETD_D2CS_AUTHREPLY_SUCCEED) {
146     eventlog(eventlog_level_info,__FUNCTION__,"d2cs %s authed",
147     addr_num_to_ip_str(conn_get_addr(c)));
148     conn_set_state(c,conn_state_loggedin);
149     if (prefs_allow_d2cs_setname()) realm_set_name(realm,realmname);
150     realm_active(realm,c);
151     } else {
152     eventlog(eventlog_level_error,__FUNCTION__,"failed to auth d2cs %s",
153     addr_num_to_ip_str(conn_get_addr(c)));
154     }
155     if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
156     packet_set_size(rpacket,sizeof(t_bnetd_d2cs_authreply));
157     packet_set_type(rpacket,BNETD_D2CS_AUTHREPLY);
158     bn_int_set(&rpacket->u.bnetd_d2cs_authreply.h.seqno,1);
159     bn_int_set(&rpacket->u.bnetd_d2cs_authreply.reply,reply);
160     conn_push_outqueue(c,rpacket);
161     packet_del_ref(rpacket);
162     }
163     return 0;
164     }
165    
166     static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet)
167     {
168     unsigned int sessionkey;
169     unsigned int sessionnum;
170     unsigned int salt;
171     char const * account;
172     char const * tname;
173     t_connection * client;
174     int reply;
175     t_packet * rpacket;
176     struct
177     {
178     bn_int salt;
179     bn_int sessionkey;
180     bn_int sessionnum;
181     bn_int secret;
182     bn_int passhash[5];
183     } temp;
184     t_hash secret_hash;
185     char const * pass_str;
186     t_hash passhash;
187     t_hash try_hash;
188    
189     if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_accountloginreq)) {
190     eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size");
191     return -1;
192     }
193     if (!(account=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_accountloginreq),USER_NAME_MAX))) {
194     eventlog(eventlog_level_error,__FUNCTION__,"missing or too long account name");
195     return -1;
196     }
197     sessionkey=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionkey);
198     sessionnum=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionnum);
199     salt=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.seqno);
200     if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
201     eventlog(eventlog_level_error,__FUNCTION__,"sessionnum %d not found",sessionnum);
202     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
203     } else if (sessionkey!=conn_get_sessionkey(client)) {
204     eventlog(eventlog_level_error,__FUNCTION__,"sessionkey %d not match",sessionkey);
205     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
206     } else if (!(tname=conn_get_username(client))) {
207     eventlog(eventlog_level_error,__FUNCTION__,"got NULL username");
208     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
209     } else if (strcasecmp(account,tname)) {
210     eventlog(eventlog_level_error,__FUNCTION__,"username %s not match",account);
211     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
212     } else {
213     bn_int_set(&temp.salt,salt);
214     bn_int_set(&temp.sessionkey,sessionkey);
215     bn_int_set(&temp.sessionnum,sessionnum);
216     bn_int_set(&temp.secret,conn_get_secret(client));
217     pass_str=account_get_pass(conn_get_account(client));
218     if (hash_set_str(&passhash,pass_str)<0) {
219     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
220     } else {
221     hash_to_bnhash((t_hash const *)&passhash,temp.passhash);
222     bnet_hash(&secret_hash,sizeof(temp),&temp);
223     bnhash_to_hash(packet->u.d2cs_bnetd_accountloginreq.secret_hash,&try_hash);
224     if (hash_eq(try_hash,secret_hash)==1) {
225     eventlog(eventlog_level_debug,__FUNCTION__,"user %s loggedin on d2cs",
226     account);
227     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_SUCCEED;
228     } else {
229     eventlog(eventlog_level_error,__FUNCTION__,"user %s hash not match",
230     account);
231     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
232     }
233     }
234     }
235     if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
236     packet_set_size(rpacket,sizeof(t_bnetd_d2cs_accountloginreply));
237     packet_set_type(rpacket,BNETD_D2CS_ACCOUNTLOGINREPLY);
238     bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.h.seqno,
239     bn_int_get(packet->u.d2cs_bnetd_accountloginreq.h.seqno));
240     bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.reply,reply);
241     conn_push_outqueue(c,rpacket);
242     packet_del_ref(rpacket);
243     }
244     return 0;
245     }
246    
247     #define CHAR_PORTRAIT_LEN 0x30
248     static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet)
249     {
250     t_connection * client;
251     char const * charname;
252     char const * portrait;
253     char const * clienttag;
254     char * temp;
255     unsigned int sessionnum;
256     t_realm * realm;
257     char const * realmname;
258     unsigned int pos, reply;
259     t_packet * rpacket;
260 sysadm 1.2 char const *checknum;
261 sysadm 1.1
262     if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_charloginreq)) {
263     eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size");
264     return -1;
265     }
266     sessionnum=bn_int_get(packet->u.d2cs_bnetd_charloginreq.sessionnum);
267     pos=sizeof(t_d2cs_bnetd_charloginreq);
268     if (!(charname=packet_get_str_const(packet,pos,CHAR_NAME_LEN))) {
269     eventlog(eventlog_level_error,__FUNCTION__,"got bad character name");
270     return -1;
271     }
272     pos+=strlen(charname)+1;
273     if (!(portrait=packet_get_str_const(packet,pos,CHAR_PORTRAIT_LEN))) {
274     eventlog(eventlog_level_error,__FUNCTION__,"got bad character portrait");
275     return -1;
276     }
277 sysadm 1.2
278     /* get checknum generated by d2cs from packet, by sowater,20050401 */
279     pos+=strlen(portrait)+1;
280     if(!(checknum=packet_get_data_const(packet,pos,sizeof(char)))) {
281     eventlog(eventlog_level_error,__FUNCTION__,"get bad checknum");
282     return -1;
283     }
284    
285 sysadm 1.1 if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
286     eventlog(eventlog_level_error,__FUNCTION__,"user %d not found",sessionnum);
287     reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
288     } else if (!(clienttag=clienttag_uint_to_str(conn_get_clienttag(client)))) {
289     eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag");
290     reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
291     } else if (!(realm=conn_get_realm(client))) {
292     eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
293     reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
294     } else {
295     char revtag[8];
296    
297     realmname = realm_get_name(realm);
298     temp=xmalloc(strlen(clienttag)+strlen(realmname)+1+strlen(charname)+1+
299     strlen(portrait)+1);
300     reply = BNETD_D2CS_CHARLOGINREPLY_SUCCEED;
301     strcpy(revtag,clienttag);
302     strreverse(revtag);
303     sprintf(temp,"%4s%s,%s,%s",revtag,realmname,charname,portrait);
304     conn_set_charname(client,charname);
305     conn_set_realminfo(client,temp);
306     xfree(temp);
307     eventlog(eventlog_level_debug,__FUNCTION__,
308     "loaded portrait for character %s",charname);
309 sysadm 1.2 /* save checknum in t_connection, by sowater */
310     if(conn_set_checknum(client,*checknum)<0) {
311     eventlog(eventlog_level_error,__FUNCTION__,"set checknum to connection fail");
312     }
313    
314    
315 sysadm 1.1 }
316     if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
317     packet_set_size(rpacket,sizeof(t_bnetd_d2cs_charloginreply));
318     packet_set_type(rpacket,BNETD_D2CS_CHARLOGINREPLY);
319     bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.h.seqno,
320     bn_int_get(packet->u.d2cs_bnetd_charloginreq.h.seqno));
321     bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.reply,reply);
322     conn_push_outqueue(c,rpacket);
323     packet_del_ref(rpacket);
324     }
325     return 0;
326     }
327    
328     extern int handle_d2cs_init(t_connection * c)
329     {
330     t_packet * packet;
331    
332     if ((packet=packet_create(packet_class_d2cs_bnetd))) {
333     packet_set_size(packet,sizeof(t_bnetd_d2cs_authreq));
334     packet_set_type(packet,BNETD_D2CS_AUTHREQ);
335     bn_int_set(&packet->u.bnetd_d2cs_authreq.h.seqno,1);
336     bn_int_set(&packet->u.bnetd_d2cs_authreq.sessionnum,conn_get_sessionnum(c));
337     conn_push_outqueue(c,packet);
338     packet_del_ref(packet);
339     }
340     eventlog(eventlog_level_info,__FUNCTION__,"sent init packet to d2cs (sessionnum=%d)",
341     conn_get_sessionnum(c));
342     return 0;
343     }
344    
345     extern int send_d2cs_gameinforeq(t_connection * c)
346     {
347     t_packet * packet;
348     t_game * game;
349     t_realm * realm;
350    
351     if (!(c))
352     {
353     eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn");
354     return -1;
355     }
356    
357     if (!(game = conn_get_game(c)))
358     {
359     eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL game");
360     return -1;
361     }
362    
363     if (!(realm = conn_get_realm(c)))
364     {
365     eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL realm");
366     return -1;
367     }
368    
369    
370     if ((packet=packet_create(packet_class_d2cs_bnetd))) {
371     packet_set_size(packet,sizeof(t_bnetd_d2cs_gameinforeq));
372     packet_set_type(packet,BNETD_D2CS_GAMEINFOREQ);
373     bn_int_set(&packet->u.bnetd_d2cs_gameinforeq.h.seqno,0);
374     packet_append_string(packet,game_get_name(game));
375     conn_push_outqueue(realm_get_conn(realm),packet);
376     packet_del_ref(packet);
377     }
378     return 0;
379     }
380    
381     static int on_d2cs_gameinforeply(t_connection * c, t_packet const * packet)
382     {
383     t_game * game;
384     char const * gamename;
385     unsigned int difficulty;
386     t_game_difficulty diff;
387    
388     if (!(c)) {
389     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
390     return -1;
391     }
392    
393     if (!(gamename = packet_get_str_const(packet,sizeof(t_d2cs_bnetd_gameinforeply),GAME_NAME_LEN)))
394     {
395     eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename");
396     return -1;
397     }
398    
399     if (!(game = gamelist_find_game(gamename,game_type_diablo2closed)))
400     {
401     eventlog(eventlog_level_error,__FUNCTION__,"reply for unknown game \"%s\"",gamename);
402     return -1;
403     }
404    
405     difficulty = bn_byte_get(packet->u.d2cs_bnetd_gameinforeply.difficulty);
406    
407     switch (difficulty)
408     {
409     case 0:
410     diff = game_difficulty_normal;
411     break;
412     case 1:
413     diff = game_difficulty_nightmare;
414     break;
415     case 2:
416     diff = game_difficulty_hell;
417     break;
418     default:
419     diff = game_difficulty_none;
420     }
421    
422     game_set_difficulty(game,diff);
423    
424     return 0;
425     }
426    

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