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

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 sysadm 1.3 t_account * user_account;
169 sysadm 1.1 unsigned int sessionkey;
170     unsigned int sessionnum;
171     unsigned int salt;
172     char const * account;
173     char const * tname;
174     t_connection * client;
175     int reply;
176     t_packet * rpacket;
177     struct
178     {
179     bn_int salt;
180     bn_int sessionkey;
181     bn_int sessionnum;
182     bn_int secret;
183     bn_int passhash[5];
184     } temp;
185     t_hash secret_hash;
186     char const * pass_str;
187     t_hash passhash;
188     t_hash try_hash;
189    
190     if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_accountloginreq)) {
191     eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size");
192     return -1;
193     }
194     if (!(account=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_accountloginreq),USER_NAME_MAX))) {
195     eventlog(eventlog_level_error,__FUNCTION__,"missing or too long account name");
196     return -1;
197     }
198 sysadm 1.3
199 sysadm 1.1 sessionkey=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionkey);
200     sessionnum=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionnum);
201     salt=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.seqno);
202     if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
203     eventlog(eventlog_level_error,__FUNCTION__,"sessionnum %d not found",sessionnum);
204     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
205     } else if (sessionkey!=conn_get_sessionkey(client)) {
206     eventlog(eventlog_level_error,__FUNCTION__,"sessionkey %d not match",sessionkey);
207     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
208     } else if (!(tname=conn_get_username(client))) {
209     eventlog(eventlog_level_error,__FUNCTION__,"got NULL username");
210     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
211     } else if (strcasecmp(account,tname)) {
212     eventlog(eventlog_level_error,__FUNCTION__,"username %s not match",account);
213     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
214 sysadm 1.3 } else if (!is_verified(account)) {
215 sysadm 1.4 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] account has not been verified (failed)", conn_get_socket(c));
216     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
217     } else {
218 sysadm 1.3 /* By Leaflet, 2006-06-21 */
219     if (!(user_account = accountlist_find_account(account))) {
220     eventlog(eventlog_level_info, __FUNCTION__, "[%d] login for \"%s\" refused (no such account)", conn_get_socket(c), account);
221     } else {
222     if (reset_user_email(user_account) == 0)
223     eventlog(eventlog_level_info, __FUNCTION__, "[%d] reset account \"%s\" email", conn_get_socket(c), account);
224     }
225    
226 sysadm 1.1 bn_int_set(&temp.salt,salt);
227     bn_int_set(&temp.sessionkey,sessionkey);
228     bn_int_set(&temp.sessionnum,sessionnum);
229     bn_int_set(&temp.secret,conn_get_secret(client));
230     pass_str=account_get_pass(conn_get_account(client));
231     if (hash_set_str(&passhash,pass_str)<0) {
232     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
233     } else {
234     hash_to_bnhash((t_hash const *)&passhash,temp.passhash);
235     bnet_hash(&secret_hash,sizeof(temp),&temp);
236     bnhash_to_hash(packet->u.d2cs_bnetd_accountloginreq.secret_hash,&try_hash);
237     if (hash_eq(try_hash,secret_hash)==1) {
238     eventlog(eventlog_level_debug,__FUNCTION__,"user %s loggedin on d2cs",
239     account);
240     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_SUCCEED;
241     } else {
242     eventlog(eventlog_level_error,__FUNCTION__,"user %s hash not match",
243     account);
244     reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
245     }
246     }
247     }
248     if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
249     packet_set_size(rpacket,sizeof(t_bnetd_d2cs_accountloginreply));
250     packet_set_type(rpacket,BNETD_D2CS_ACCOUNTLOGINREPLY);
251     bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.h.seqno,
252     bn_int_get(packet->u.d2cs_bnetd_accountloginreq.h.seqno));
253     bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.reply,reply);
254     conn_push_outqueue(c,rpacket);
255     packet_del_ref(rpacket);
256     }
257     return 0;
258     }
259    
260     #define CHAR_PORTRAIT_LEN 0x30
261     static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet)
262     {
263     t_connection * client;
264     char const * charname;
265     char const * portrait;
266     char const * clienttag;
267     char * temp;
268     unsigned int sessionnum;
269     t_realm * realm;
270     char const * realmname;
271     unsigned int pos, reply;
272     t_packet * rpacket;
273 sysadm 1.2 char const *checknum;
274 sysadm 1.1
275     if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_charloginreq)) {
276     eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size");
277     return -1;
278     }
279     sessionnum=bn_int_get(packet->u.d2cs_bnetd_charloginreq.sessionnum);
280     pos=sizeof(t_d2cs_bnetd_charloginreq);
281     if (!(charname=packet_get_str_const(packet,pos,CHAR_NAME_LEN))) {
282     eventlog(eventlog_level_error,__FUNCTION__,"got bad character name");
283     return -1;
284     }
285     pos+=strlen(charname)+1;
286     if (!(portrait=packet_get_str_const(packet,pos,CHAR_PORTRAIT_LEN))) {
287     eventlog(eventlog_level_error,__FUNCTION__,"got bad character portrait");
288     return -1;
289     }
290 sysadm 1.2
291     /* get checknum generated by d2cs from packet, by sowater,20050401 */
292     pos+=strlen(portrait)+1;
293     if(!(checknum=packet_get_data_const(packet,pos,sizeof(char)))) {
294     eventlog(eventlog_level_error,__FUNCTION__,"get bad checknum");
295     return -1;
296     }
297    
298 sysadm 1.1 if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
299     eventlog(eventlog_level_error,__FUNCTION__,"user %d not found",sessionnum);
300     reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
301     } else if (!(clienttag=clienttag_uint_to_str(conn_get_clienttag(client)))) {
302     eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag");
303     reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
304     } else if (!(realm=conn_get_realm(client))) {
305     eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
306     reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
307     } else {
308     char revtag[8];
309    
310     realmname = realm_get_name(realm);
311     temp=xmalloc(strlen(clienttag)+strlen(realmname)+1+strlen(charname)+1+
312     strlen(portrait)+1);
313     reply = BNETD_D2CS_CHARLOGINREPLY_SUCCEED;
314     strcpy(revtag,clienttag);
315     strreverse(revtag);
316     sprintf(temp,"%4s%s,%s,%s",revtag,realmname,charname,portrait);
317     conn_set_charname(client,charname);
318     conn_set_realminfo(client,temp);
319     xfree(temp);
320     eventlog(eventlog_level_debug,__FUNCTION__,
321     "loaded portrait for character %s",charname);
322 sysadm 1.2 /* save checknum in t_connection, by sowater */
323     if(conn_set_checknum(client,*checknum)<0) {
324     eventlog(eventlog_level_error,__FUNCTION__,"set checknum to connection fail");
325     }
326    
327    
328 sysadm 1.1 }
329     if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
330     packet_set_size(rpacket,sizeof(t_bnetd_d2cs_charloginreply));
331     packet_set_type(rpacket,BNETD_D2CS_CHARLOGINREPLY);
332     bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.h.seqno,
333     bn_int_get(packet->u.d2cs_bnetd_charloginreq.h.seqno));
334     bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.reply,reply);
335     conn_push_outqueue(c,rpacket);
336     packet_del_ref(rpacket);
337     }
338     return 0;
339     }
340    
341     extern int handle_d2cs_init(t_connection * c)
342     {
343     t_packet * packet;
344    
345     if ((packet=packet_create(packet_class_d2cs_bnetd))) {
346     packet_set_size(packet,sizeof(t_bnetd_d2cs_authreq));
347     packet_set_type(packet,BNETD_D2CS_AUTHREQ);
348     bn_int_set(&packet->u.bnetd_d2cs_authreq.h.seqno,1);
349     bn_int_set(&packet->u.bnetd_d2cs_authreq.sessionnum,conn_get_sessionnum(c));
350     conn_push_outqueue(c,packet);
351     packet_del_ref(packet);
352     }
353     eventlog(eventlog_level_info,__FUNCTION__,"sent init packet to d2cs (sessionnum=%d)",
354     conn_get_sessionnum(c));
355     return 0;
356     }
357    
358     extern int send_d2cs_gameinforeq(t_connection * c)
359     {
360     t_packet * packet;
361     t_game * game;
362     t_realm * realm;
363    
364     if (!(c))
365     {
366     eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn");
367     return -1;
368     }
369    
370     if (!(game = conn_get_game(c)))
371     {
372     eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL game");
373     return -1;
374     }
375    
376     if (!(realm = conn_get_realm(c)))
377     {
378     eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL realm");
379     return -1;
380     }
381    
382    
383     if ((packet=packet_create(packet_class_d2cs_bnetd))) {
384     packet_set_size(packet,sizeof(t_bnetd_d2cs_gameinforeq));
385     packet_set_type(packet,BNETD_D2CS_GAMEINFOREQ);
386     bn_int_set(&packet->u.bnetd_d2cs_gameinforeq.h.seqno,0);
387     packet_append_string(packet,game_get_name(game));
388     conn_push_outqueue(realm_get_conn(realm),packet);
389     packet_del_ref(packet);
390     }
391     return 0;
392     }
393    
394     static int on_d2cs_gameinforeply(t_connection * c, t_packet const * packet)
395     {
396     t_game * game;
397     char const * gamename;
398     unsigned int difficulty;
399     t_game_difficulty diff;
400    
401     if (!(c)) {
402     eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
403     return -1;
404     }
405    
406     if (!(gamename = packet_get_str_const(packet,sizeof(t_d2cs_bnetd_gameinforeply),GAME_NAME_LEN)))
407     {
408     eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename");
409     return -1;
410     }
411    
412     if (!(game = gamelist_find_game(gamename,game_type_diablo2closed)))
413     {
414     eventlog(eventlog_level_error,__FUNCTION__,"reply for unknown game \"%s\"",gamename);
415     return -1;
416     }
417    
418     difficulty = bn_byte_get(packet->u.d2cs_bnetd_gameinforeply.difficulty);
419    
420     switch (difficulty)
421     {
422     case 0:
423     diff = game_difficulty_normal;
424     break;
425     case 1:
426     diff = game_difficulty_nightmare;
427     break;
428     case 2:
429     diff = game_difficulty_hell;
430     break;
431     default:
432     diff = game_difficulty_none;
433     }
434    
435     game_set_difficulty(game,diff);
436    
437     return 0;
438     }
439    

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