summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2013-08-01 18:14:36 +0200
committerHaru <haru@dotalux.com>2013-08-01 18:57:31 +0200
commit38b8bf02b69f3841fd496f8d628bf71040c99709 (patch)
tree4be62808f7696dbd706688f14be2994da09cdbe6
parent94502b74233035b07c8c73a1f991a17b7bf22c55 (diff)
downloadhercules-38b8bf02b69f3841fd496f8d628bf71040c99709.tar.gz
hercules-38b8bf02b69f3841fd496f8d628bf71040c99709.tar.bz2
hercules-38b8bf02b69f3841fd496f8d628bf71040c99709.tar.xz
hercules-38b8bf02b69f3841fd496f8d628bf71040c99709.zip
Improved packet obfuscation reliability
- Fixes bugreport:7607 http://hercules.ws/board/tracker/issue-7607-changing-emblem-with-packet-obfuscation-2-unknown-packet/ - Resolved unintended disconnections caused by invalid packets when obfuscation is enabled and a fragmented packet is received. - Improved packet parsing reliability when packet obfuscation is set to optional. Special thanks to serverkid for reporting the issue and Ind for figuring out the cause and suggesting a solution. Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/map/clif.c58
-rw-r--r--src/map/clif.h3
-rw-r--r--src/map/pc.h3
3 files changed, 41 insertions, 23 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 5110ca76b..2f63ec5c0 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9209,8 +9209,11 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
CREATE(sd, TBL_PC, 1);
sd->fd = fd;
- sd->cryptKey = (( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
-
+
+ sd->cryptKey = (( ((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF)
+ * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
+ sd->parse_cmd_func = clif->parse_cmd;
+
session[fd]->session_data = sd;
pc->setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd);
@@ -17481,42 +17484,41 @@ void clif_cart_additem_ack(struct map_session_data *sd, int flag) {
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
if( sd ) {
- sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
return (cmd ^ ((sd->cryptKey >> 16) & 0x7FFF));
}
return (cmd ^ (((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) >> 16) & 0x7FFF));
}
-unsigned short clif_parse_cmd_normal ( int fd, struct map_session_data *sd ) {
+unsigned short clif_parse_cmd_normal( int fd, struct map_session_data *sd ) {
unsigned short cmd = RFIFOW(fd,0);
+
// filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0)
+ if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 )
return 0;
return cmd;
}
-unsigned short clif_parse_cmd_optional ( int fd, struct map_session_data *sd ) {
+unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) {
unsigned short cmd = RFIFOW(fd,0);
+ cmd = clif->decrypt_cmd(cmd, sd);
+
// filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0) {
- cmd = clif->decrypt_cmd( cmd, sd );
- if( cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
- return 0;
- RFIFOW(fd, 0) = cmd;
- }
+ if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 )
+ return 0;
return cmd;
}
-unsigned short clif_parse_cmd_decrypt ( int fd, struct map_session_data *sd ) {
+unsigned short clif_parse_cmd_optional( int fd, struct map_session_data *sd ) {
unsigned short cmd = RFIFOW(fd,0);
- cmd = clif->decrypt_cmd( cmd, sd );
-
// filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
- return 0;
-
- RFIFOW(fd, 0) = cmd;
+ if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 ) {
+ if( sd )
+ sd->parse_cmd_func = clif_parse_cmd_decrypt;
+ return clif_parse_cmd_decrypt(fd, sd);
+ } else if( sd ) {
+ sd->parse_cmd_func = clif_parse_cmd_normal;
+ }
return cmd;
}
@@ -17536,6 +17538,8 @@ int clif_parse(int fd) {
// begin main client packet processing loop
sd = (TBL_PC *)session[fd]->session_data;
+ unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd);
+
if (session[fd]->flag.eof) {
if (sd) {
if (sd->state.autotrade) {
@@ -17563,8 +17567,13 @@ int clif_parse(int fd) {
if (RFIFOREST(fd) < 2)
return 0;
- if( !( cmd = clif->parse_cmd(fd,sd) ) ) {
- ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", RFIFOW(fd,0), RFIFOREST(fd), fd);
+ if( sd )
+ parse_cmd_func = sd->parse_cmd_func;
+ else
+ parse_cmd_func = clif->parse_cmd;
+
+ if( !( cmd = parse_cmd_func(fd,sd) ) ) {
+ ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x (0x%04x), %d bytes received), disconnecting session #%d.\n", cmd, RFIFOW(fd,0), RFIFOREST(fd), fd);
#ifdef DUMP_INVALID_PACKET
ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
#endif
@@ -17593,6 +17602,13 @@ int clif_parse(int fd) {
if ((int)RFIFOREST(fd) < packet_len)
return 0; // not enough data received to form the packet
+ if( cmd != RFIFOW(fd, 0) ) {
+ RFIFOW(fd, 0) = cmd;
+ if( sd ) {
+ sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF; // Update key for the next packet
+ }
+ }
+
if( packet_db[cmd].func == clif->pDebug )
packet_db[cmd].func(fd, sd);
else if( packet_db[cmd].func != NULL ) {
diff --git a/src/map/clif.h b/src/map/clif.h
index 9bb5f25e7..43b2fa1a6 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -52,7 +52,8 @@ struct skill_cd;
* Enumerations
**/
enum {// packet DB
- MAX_PACKET_DB = 0xF00,
+ MIN_PACKET_DB = 0x0064,
+ MAX_PACKET_DB = 0x0F00,
MAX_PACKET_POS = 20,
};
diff --git a/src/map/pc.h b/src/map/pc.h
index 42bfb56c1..1f1538e1f 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -502,7 +502,8 @@ struct map_session_data {
unsigned int queues_count;
/* Made Possible Thanks to Yommy~! */
- unsigned int cryptKey;
+ unsigned int cryptKey; ///< Packet obfuscation key to be used for the next received packet
+ unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd); ///< parse_cmd_func used by this player
unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules]