From e4a1ca28de80e221198854b745be71d256e1f7b1 Mon Sep 17 00:00:00 2001
From: Haru <haru@dotalux.com>
Date: Sat, 8 Feb 2014 04:05:03 +0100
Subject: Improved client_hash_check

- Added option to disable hash check by GM group_id (specify 'disabled'
  as hash for a certain group_id to let them log in with any client,
  even if client_hash_check is enabled
- Updated and reworded related documentation for the feature, following
  user feedback about certain parts being incomplete or confusing.
---
 src/login/login.c | 40 +++++++++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 17 deletions(-)

(limited to 'src/login')

diff --git a/src/login/login.c b/src/login/login.c
index e9d0eac9d..249d008ec 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -977,27 +977,29 @@ int mmo_auth(struct login_session_data* sd, bool isServer) {
 	}
 	
 	if( login_config.client_hash_check && !isServer ) {
-		struct client_hash_node *node = login_config.client_hash_nodes;
+		struct client_hash_node *node = NULL;
 		bool match = false;
 
-		if( !sd->has_client_hash ) {
-			ShowNotice("Client doesn't sent client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, acc.state, ip);
-			return 5;
-		}
-
-		while( node ) {
-			if( node->group_id <= acc.group_id && memcmp(node->hash, sd->client_hash, 16) == 0 ) {
+		for( node = login_config.client_hash_nodes; node; node = node->next ) {
+			if( acc.group_id < node->group_id )
+				continue;
+			if( *node->hash == '\0' // Allowed to login without hash
+			 || (sd->has_client_hash && memcmp(node->hash, sd->client_hash, 16) == 0 ) // Correct hash
+			) {
 				match = true;
 				break;
 			}
-
-			node = node->next;
 		}
 
 		if( !match ) {
 			char smd5[33];
 			int i;
 
+			if( !sd->has_client_hash ) {
+				ShowNotice("Client didn't send client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, acc.state, ip);
+				return 5;
+			}
+
 			for( i = 0; i < 16; i++ )
 				sprintf(&smd5[i * 2], "%02x", sd->client_hash[i]);
 
@@ -1607,15 +1609,19 @@ int login_config_read(const char* cfgName)
 				int i;
 				CREATE(nnode, struct client_hash_node, 1);
 
-				for (i = 0; i < 32; i += 2) {
-					char buf[3];
-					unsigned int byte;
+				if (strcmpi(md5, "disabled") == 0) {
+					nnode->hash[0] = '\0';
+				} else {
+					for (i = 0; i < 32; i += 2) {
+						char buf[3];
+						unsigned int byte;
 
-					memcpy(buf, &md5[i], 2);
-					buf[2] = 0;
+						memcpy(buf, &md5[i], 2);
+						buf[2] = 0;
 
-					sscanf(buf, "%x", &byte);
-					nnode->hash[i / 2] = (uint8)(byte & 0xFF);
+						sscanf(buf, "%x", &byte);
+						nnode->hash[i / 2] = (uint8)(byte & 0xFF);
+					}
 				}
 
 				nnode->group_id = group;
-- 
cgit v1.2.3-70-g09d2