handle_d2cs.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:11k
源码类别:

MySQL数据库

开发平台:

Visual C++

  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. #include <stddef.h>
  20. #include <stdlib.h>
  21. #ifdef HAVE_STRING_H
  22. # include <string.h>
  23. #else
  24. # ifdef HAVE_STRINGS_H
  25. #  include <strings.h>
  26. # endif
  27. #endif
  28. #include "compat/strcasecmp.h"
  29. #include "connection.h"
  30. #include "realm.h"
  31. #include "account.h"
  32. #include "d2cs/d2cs_bnetd_protocol.h"
  33. #include "common/bnethash.h"
  34. #include "common/bnethashconv.h"
  35. #include "common/eventlog.h"
  36. #include "common/queue.h"
  37. #include "common/packet.h"
  38. #include "common/addr.h"
  39. #include "common/bn_type.h"
  40. #include "prefs.h"
  41. #include "common/util.h"
  42. #include "common/field_sizes.h"
  43. #include "handle_d2cs.h"
  44. #include "common/setup_after.h"
  45. static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet);
  46. static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet);
  47. static int on_d2cs_authreply(t_connection * c, t_packet const * packet);
  48. extern int handle_d2cs_packet(t_connection * c, t_packet const * packet)
  49. {
  50. if (!c) {
  51. eventlog(eventlog_level_error,"handle_d2cs_packet","got NULL connection");
  52. return -1;
  53. }
  54. if (!packet) {
  55. eventlog(eventlog_level_error,"handle_d2cs_packet","got NULL packet");
  56. return -1;
  57. }
  58. if (packet_get_class(packet)!=packet_class_d2cs_bnetd) {
  59. eventlog(eventlog_level_error,"handle_d2cs_packet","got bad packet class %d",
  60. packet_get_class(packet));
  61. return -1;
  62. }
  63. switch (conn_get_state(c)) {
  64. case conn_state_connected:
  65. switch (packet_get_type(packet)) {
  66. case D2CS_BNETD_AUTHREPLY:
  67. on_d2cs_authreply(c,packet);
  68. break;
  69. default:
  70. eventlog(eventlog_level_error,"handle_d2cs_packet",
  71. "got unknown packet type %d",packet_get_type(packet));
  72. break;
  73. }
  74. break;
  75. case conn_state_loggedin:
  76. switch (packet_get_type(packet)) {
  77. case D2CS_BNETD_ACCOUNTLOGINREQ:
  78. on_d2cs_accountloginreq(c,packet);
  79. break;
  80. case D2CS_BNETD_CHARLOGINREQ:
  81. on_d2cs_charloginreq(c,packet);
  82. break;
  83. default:
  84. eventlog(eventlog_level_error,"handle_d2cs_packet",
  85. "got unknown packet type %d",packet_get_type(packet));
  86. break;
  87. }
  88. break;
  89. default:
  90. eventlog(eventlog_level_error,"handle_d2cs_packet",
  91. "got unknown connection state %d",conn_get_state(c));
  92. break;
  93. }
  94. return 0;
  95. }
  96. static int on_d2cs_authreply(t_connection * c, t_packet const * packet)
  97. {
  98. t_packet * rpacket;
  99. unsigned int version;
  100. unsigned int try_version;
  101. unsigned int reply;
  102. char const * realmname;
  103. t_realm * realm;
  104. if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_authreply)) {
  105. eventlog(eventlog_level_error,"on_d2cs_authreply","got bad packet size");
  106. return -1;
  107. }
  108. if (!(realmname=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_authreply),REALM_NAME_LEN))) {
  109. eventlog(eventlog_level_error,"on_d2cs_authreply","got bad realmname");
  110. return -1;
  111. }
  112.         if (!(realm=realmlist_find_realm(realmname))) {
  113.                 eventlog(eventlog_level_error,"handle_init_packet", "realm not found");
  114.                 return -1;
  115.         }
  116. if (realm_get_name(realm) && strcasecmp(realmname,realm_get_name(realm))) {
  117.                 eventlog(eventlog_level_error,"handle_init_packet", "warn: realm name mismatch %s %s",
  118. realm_get_name(realm),realmname);
  119. }
  120. version=prefs_get_d2cs_version();
  121. try_version=bn_int_get(packet->u.d2cs_bnetd_authreply.version);
  122. if (version && version != try_version) {
  123. eventlog(eventlog_level_error,"on_d2cs_authreply","d2cs version mismatch 0x%X - 0x%X",
  124. try_version,version);
  125. reply=BNETD_D2CS_AUTHREPLY_BAD_VERSION;
  126. } else {
  127. reply=BNETD_D2CS_AUTHREPLY_SUCCEED;
  128. }
  129. if (reply==BNETD_D2CS_AUTHREPLY_SUCCEED) {
  130. eventlog(eventlog_level_info,"on_d2cs_authreply","d2cs %s authed",
  131. addr_num_to_ip_str(conn_get_addr(c)));
  132. conn_set_state(c,conn_state_loggedin);
  133. if (prefs_allow_d2cs_setname()) realm_set_name(realm,realmname);
  134. realm_active(realm,c);
  135. } else {
  136. eventlog(eventlog_level_error,"on_d2cs_authreply","failed to auth d2cs %s",
  137. addr_num_to_ip_str(conn_get_addr(c)));
  138. }
  139. if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
  140. packet_set_size(rpacket,sizeof(t_bnetd_d2cs_authreply));
  141. packet_set_type(rpacket,BNETD_D2CS_AUTHREPLY);
  142. bn_int_set(&rpacket->u.bnetd_d2cs_authreply.h.seqno,1);
  143. bn_int_set(&rpacket->u.bnetd_d2cs_authreply.reply,reply);
  144. conn_push_outqueue(c,rpacket);
  145. packet_del_ref(rpacket);
  146. }
  147. return 0;
  148. }
  149. static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet)
  150. {
  151. unsigned int sessionkey;
  152. unsigned int sessionnum;
  153. unsigned int salt;
  154. char const * account;
  155. char const * tname;
  156. t_connection * client;
  157. int reply;
  158. t_packet * rpacket;
  159. struct
  160. {
  161. bn_int   salt;
  162. bn_int   sessionkey;
  163. bn_int   sessionnum;
  164. bn_int   secret;
  165. bn_int  passhash[5];
  166. } temp;
  167. t_hash       secret_hash;
  168. char const * pass_str;
  169. t_hash      passhash;
  170. t_hash      try_hash;
  171. if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_accountloginreq)) {
  172. eventlog(eventlog_level_error,"on_d2cs_accountloginreq","got bad packet size");
  173. return -1;
  174. }
  175. if (!(account=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_accountloginreq),USER_NAME_MAX))) {
  176. eventlog(eventlog_level_error,"on_d2cs_accountloginreq","missing or too long account name");
  177. return -1;
  178. }
  179. sessionkey=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionkey);
  180. sessionnum=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionnum);
  181. salt=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.seqno);
  182. if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
  183. eventlog(eventlog_level_error,"on_d2cs_accountloginreq","sessionnum %d not found",sessionnum);
  184. reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
  185. } else if (sessionkey!=conn_get_sessionkey(client)) {
  186. eventlog(eventlog_level_error,"on_d2cs_accountloginreq","sessionkey %d not match",sessionkey);
  187. reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
  188. } else if (!(tname=conn_get_username(client))) {
  189. eventlog(eventlog_level_error,"on_d2cs_accountloginreq","got NULL username");
  190. reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
  191. } else if (strcasecmp(account,tname)) {
  192. eventlog(eventlog_level_error,"on_d2cs_accountloginreq","username %s not match",account);
  193. conn_unget_username(client,tname);
  194. reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
  195. } else {
  196. conn_unget_username(client,tname);
  197. bn_int_set(&temp.salt,salt);
  198. bn_int_set(&temp.sessionkey,sessionkey);
  199. bn_int_set(&temp.sessionnum,sessionnum);
  200. bn_int_set(&temp.secret,conn_get_secret(client));
  201. pass_str=account_get_pass(conn_get_account(client));
  202. if (hash_set_str(&passhash,pass_str)<0) {
  203. reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
  204. } else {
  205. hash_to_bnhash((t_hash const *)&passhash,temp.passhash);
  206. bnet_hash(&secret_hash,sizeof(temp),&temp);
  207. bnhash_to_hash(packet->u.d2cs_bnetd_accountloginreq.secret_hash,&try_hash);
  208. if (hash_eq(try_hash,secret_hash)==1) {
  209. eventlog(eventlog_level_debug,"on_d2cs_accountloginreq","user %s loggedin on d2cs",
  210. account);
  211. reply=BNETD_D2CS_ACCOUNTLOGINREPLY_SUCCEED;
  212. } else {
  213. eventlog(eventlog_level_error,"on_d2cs_accountloginreq","user %s hash not match",
  214. account);
  215. reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
  216. }
  217. }
  218. account_unget_pass(pass_str);
  219. }
  220. if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
  221. packet_set_size(rpacket,sizeof(t_bnetd_d2cs_accountloginreply));
  222. packet_set_type(rpacket,BNETD_D2CS_ACCOUNTLOGINREPLY);
  223. bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.h.seqno,
  224. bn_int_get(packet->u.d2cs_bnetd_accountloginreq.h.seqno));
  225. bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.reply,reply);
  226. conn_push_outqueue(c,rpacket);
  227. packet_del_ref(rpacket);
  228. }
  229. return 0;
  230. }
  231. #define CHAR_PORTRAIT_LEN 0x30
  232. static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet)
  233. {
  234. t_connection * client;
  235. char const * charname;
  236. char const * portrait;
  237. char const * clienttag;
  238. char * temp;
  239. unsigned int sessionnum;
  240. char const * realmname;
  241. unsigned int pos, reply;
  242. t_packet * rpacket;
  243. if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_charloginreq)) {
  244. eventlog(eventlog_level_error,"on_d2cs_charloginreq","got bad packet size");
  245. return -1;
  246. }
  247. sessionnum=bn_int_get(packet->u.d2cs_bnetd_charloginreq.sessionnum);
  248. pos=sizeof(t_d2cs_bnetd_charloginreq);
  249. if (!(charname=packet_get_str_const(packet,pos,CHAR_NAME_LEN))) {
  250. eventlog(eventlog_level_error,"on_d2cs_charloginreq","got bad character name");
  251. return -1;
  252. }
  253. pos+=strlen(charname)+1;
  254. if (!(portrait=packet_get_str_const(packet,pos,CHAR_PORTRAIT_LEN))) {
  255. eventlog(eventlog_level_error,"on_d2cs_charloginreq","got bad character portrait");
  256. return -1;
  257. }
  258. if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
  259. eventlog(eventlog_level_error,"on_d2cs_charloginreq","user %d not found",sessionnum);
  260. reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
  261. } else if (!(clienttag=conn_get_clienttag(client))) {
  262. eventlog(eventlog_level_error,"on_d2cs_charloginreq","got NULL clienttag");
  263. reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
  264. } else if (!(realmname=conn_get_realmname(client))) {
  265. eventlog(eventlog_level_error,"on_d2cs_charloginreq","got NULL realm name");
  266. reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
  267. } else if (!(temp=malloc(strlen(clienttag)+strlen(realmname)+1+strlen(charname)+1+
  268. strlen(portrait)+1))) {
  269. eventlog(eventlog_level_error,"on_d2cs_charloginreq","error allocate temp");
  270. reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
  271. } else {
  272. char revtag[8];
  273. reply = BNETD_D2CS_CHARLOGINREPLY_SUCCEED;
  274. strcpy(revtag,clienttag);
  275. strreverse(revtag);
  276. sprintf(temp,"%4s%s,%s,%s",revtag,realmname,charname,portrait);
  277. conn_set_charname(client,charname);
  278. conn_set_realminfo(client,temp);
  279. free(temp);
  280. eventlog(eventlog_level_debug,"on_d2cs_charloginreq",
  281. "loaded portrait for character %s",charname);
  282. }
  283. if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
  284. packet_set_size(rpacket,sizeof(t_bnetd_d2cs_charloginreply));
  285. packet_set_type(rpacket,BNETD_D2CS_CHARLOGINREPLY);
  286. bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.h.seqno,
  287. bn_int_get(packet->u.d2cs_bnetd_charloginreq.h.seqno));
  288. bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.reply,reply);
  289. conn_push_outqueue(c,rpacket);
  290. packet_del_ref(rpacket);
  291. }
  292. return 0;
  293. }
  294. extern int handle_d2cs_init(t_connection * c)
  295. {
  296. t_packet * packet;
  297. if ((packet=packet_create(packet_class_d2cs_bnetd))) {
  298. packet_set_size(packet,sizeof(t_bnetd_d2cs_authreq));
  299. packet_set_type(packet,BNETD_D2CS_AUTHREQ);
  300. bn_int_set(&packet->u.bnetd_d2cs_authreq.h.seqno,1);
  301. bn_int_set(&packet->u.bnetd_d2cs_authreq.sessionnum,conn_get_sessionnum(c));
  302. conn_push_outqueue(c,packet);
  303. packet_del_ref(packet);
  304. }
  305. eventlog(eventlog_level_info,"handle_d2cs_init","sent init packet to d2cs (sessionnum=%d)",
  306. conn_get_sessionnum(c));
  307. return 0;
  308. }