Improved 'client_hash_check' config. (Hercules e4a1ca2)

- 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.

Improvements on script command 'axtoi'; added 'strtol'. (Hercules 1cf7c1e)
- Added script command 'strtol' (conforming to the ISO C90 function).
- Modified script command 'axtoi' to internally use 'strtol' instead of an unnecessary separate implementation.

Cleaned up many sections of script documentation, and modernized syntax in examples.
Added documentation for 'rentitem2' and 'makeitem2'. (follow-up 339c0a8)

Added 'true' (1) and 'false' (2) as script constants.

'freeloop' argument is now optional, and will only return the value of freeloop if no argument is given. (tid:92470)
http://rathena.org/board/topic/92470-freeloop-optional-argument/

Added a missing mapflag to custom 'devil_square' script. (bugreport:8611)
http://rathena.org/board/tracker/issue-8611-devil-square-bug/

Signed-off-by: Euphy <euphy.raliel@rathena.org>
This commit is contained in:
Euphy 2014-02-08 15:32:28 -05:00
parent 339c0a8c48
commit de46393592
8 changed files with 419 additions and 406 deletions

View File

@ -165,14 +165,20 @@ account.engine: auto
// Client MD5 hash check
// If turned on, the login server will check if the client's hash matches
// the value below, and will not connect tampered clients.
// Note: see doc\md5_hashcheck.txt for more details.
// Note: see 'doc/md5_hashcheck.txt' for more details.
client_hash_check: off
// Client MD5 hashes
// A player can login with a client hash at or below the account group_id.
// The client with the specified hash can be used to log in by players with
// a group_id equal to or greater than the given value.
// If you specify 'disabled' as hash, players with a group_id greater than or
// equal to the given value will be able to log in regardless of hash (and even
// if their client does not send a hash at all.)
// Format: group_id, hash
client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5
client_hash: 99, cb1ea78023d337c38e8ba5124e2338ae
// Note: see 'doc/md5_hashcheck.txt' for more details.
//client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5
//client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae
//client_hash: 99, disabled
import: conf/inter_athena.conf
import: conf/import/login_conf.txt

View File

@ -4559,3 +4559,6 @@ VAR_MAX_GUILD_STORAGE 8
VAR_MAX_BG_MEMBERS 9
VAR_VIP_SCRIPT 10
VAR_MIN_STORAGE 11
false 0
true 1

View File

@ -13,25 +13,25 @@ and 'getgroupitem' script commands. The table below explains which fields are
accessed in each.
+===============+====================+================+
| Field | 'getrandgroupitem' | 'getgroupitem' |
| Field | 'getrandgroupitem' | 'getgroupitem' |
+===============+====================+================+
| GroupID | YES | YES |
| GroupID | YES | YES |
+===============+====================+================+
| ItemID | YES | YES |
| ItemID | YES | YES |
+===============+====================+================+
| Rate | YES | YES |
| Rate | YES | YES |
+===============+====================+================+
| Amount | no | YES |
| Amount | no | YES |
+===============+====================+================+
| Random | no | YES |
| Random | no | YES |
+===============+====================+================+
| isAnnounced | no | YES |
| isAnnounced | no | YES |
+===============+====================+================+
| Duration | no | YES |
| Duration | no | YES |
+===============+====================+================+
| isNamed | no | YES |
| isNamed | no | YES |
+===============+====================+================+
| isBound | no | YES |
| isBound | no | YES |
+===============+====================+================+
---------------------------------------

View File

@ -3,7 +3,7 @@
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20120921
//= 20140208
//===== Description: =========================================
//= This file outlines the login server's MD5 hash check.
//============================================================
@ -14,25 +14,41 @@ the client is the one specific to your server.
The client can only send the correct MD5 hash to the server on certain
server types, so a client diff is required to ensure the hash is sent.
A link containing the required WeeDiffGen plugin can be found at:
Please refer to your client diff tool manual for the appropriate patch,
called "Force Send Client Hash Packet" or a similar name. A link
containing the WeeDiffGen plugin can be found at:
http://rathena.org/board/topic/70841-r16771-client-md5-hash-check/
The settings for the hash check are located in conf\login_athena.conf:
The server-side settings for the hash check are located in
'conf\login_athena.conf':
// Client MD5 hash check
// If turned on, the login server will check if the client's hash matches
// the value below, and will not connect tampered clients.
// Note: see doc\md5_hashcheck.txt for more details.
// Note: see 'doc/md5_hashcheck.txt' for more details.
client_hash_check: off
// Client MD5 hashes
// A player can login with a client hash at or below the account group_id.
// The client with the specified hash can be used to log in by players with
// a group_id equal to or greater than the given value.
// If you specify 'disabled' as hash, players with a group_id greater than or
// equal to the given value will be able to log in regardless of hash (and even
// if their client does not send a hash at all.)
// Format: group_id, hash
// Note: see 'doc/md5_hashcheck.txt' for more details.
client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5
client_hash: 99, cb1ea78023d337c38e8ba5124e2338ae
client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae
client_hash: 99, disabled
To enable MD5 hash checks, set 'client_hash_check' to 'on'.
The 'client_hash' group_id can be any of the groups in conf\groups.conf,
and is particularly useful if you wanted to allow GMs a different client
than normal players; for example, a GM client could be hexed differently
with dual-clienting enabled and chat flood disabled.
To enable MD5 hash checks, set 'client_hash_check' to 'on' and add one
'client_hash' entry for each client you want to use.
The group_id can be any of the groups in 'conf/groups.conf', and it is
useful in case if you want to allow GMs to use a different client
than normal players; for example, a GM client could be hexed
differently, perhaps with dual-clienting enabled and chat flood
disabled.
You will need to replace the example MD5 hashes with the actual hash of
your client. You can use any MD5 hash tools to generate it, e.g.:
- md5sum (command line) on linux
- WinMD5 on Windows
- md5 (command line) on Mac OS X

File diff suppressed because it is too large Load Diff

View File

@ -227,6 +227,7 @@ ordeal_1-1,246,245,7 script Devil Square Guardian#2 406,{
ordeal_1-1 mapflag nowarp
ordeal_1-1 mapflag nowarpto
ordeal_1-1 mapflag noteleport
ordeal_1-1 mapflag monster_noteleport
ordeal_1-1 mapflag nosave SavePoint
ordeal_1-1 mapflag nomemo
ordeal_1-1 mapflag nobranch

View File

@ -1208,27 +1208,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]);
@ -1832,20 +1834,30 @@ int login_config_read(const char* cfgName)
else if(!strcmpi(w1, "client_hash")) {
int group = 0;
char md5[33];
if (sscanf(w2, "%3d, %32s", &group, md5) == 2) {
struct client_hash_node *nnode;
int i;
CREATE(nnode, struct client_hash_node, 1);
for (i = 0; i < 32; i += 2) {
char buf[3];
unsigned int byte;
memcpy(buf, &md5[i], 2);
buf[2] = 0;
sscanf(buf, "%2x", &byte);
nnode->hash[i / 2] = (uint8)(byte & 0xFF);
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;
sscanf(buf, "%2x", &byte);
nnode->hash[i / 2] = (uint8)(byte & 0xFF);
}
}
nnode->group_id = group;
nnode->next = login_config.client_hash_nodes;
login_config.client_hash_nodes = nnode;
}
} else if(strcmpi(w1, "chars_per_account") == 0) { //maxchars per account [Sirius]

View File

@ -14579,6 +14579,16 @@ BUILDIN_FUNC(sscanf){
argc = script_lastdata(st)-3;
len = strlen(format);
if (len != 0 && strlen(str) == 0) {
// If the source string is empty but the format string is not, we return -1
// according to the C specs. (if the format string is also empty, we shall
// continue and return 0: 0 conversions took place out of the 0 attempted.)
script_pushint(st, -1);
return SCRIPT_CMD_SUCCESS;
}
CREATE(buf, char, len*2+1);
// Issue sscanf for each parameter
@ -14649,10 +14659,7 @@ BUILDIN_FUNC(sscanf){
*(buf_p-len+1) = '*';
}
if( !strcmp(str, "") )
script_pushint(st, -1);
else
script_pushint(st, arg);
script_pushint(st, arg);
if(buf) aFree(buf);
if(ref_str) aFree(ref_str);
@ -14923,6 +14930,29 @@ BUILDIN_FUNC(atoi)
return SCRIPT_CMD_SUCCESS;
}
BUILDIN_FUNC(axtoi)
{
const char *hex = script_getstr(st,2);
long value = strtol(hex, NULL, 16);
#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN
value = cap_value(value, INT_MIN, INT_MAX);
#endif
script_pushint(st, (int)value);
return SCRIPT_CMD_SUCCESS;
}
BUILDIN_FUNC(strtol)
{
const char *string = script_getstr(st, 2);
int base = script_getnum(st, 3);
long value = strtol(string, NULL, base);
#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN
value = cap_value(value, INT_MIN, INT_MAX);
#endif
script_pushint(st, (int)value);
return SCRIPT_CMD_SUCCESS;
}
// case-insensitive substring search [lordalfa]
BUILDIN_FUNC(compare)
{
@ -15656,47 +15686,6 @@ BUILDIN_FUNC(searchitem)
return SCRIPT_CMD_SUCCESS;
}
int axtoi(const char *hexStg)
{
int n = 0; // position in string
int16 m = 0; // position in digit[] to shift
int count; // loop index
int intValue = 0; // integer value of hex string
int digit[11]; // hold values to convert
while (n < 10) {
if (hexStg[n]=='\0')
break;
if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9
digit[n] = hexStg[n] & 0x0f; //convert to int
else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f
digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F
digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
else break;
n++;
}
count = n;
m = n - 1;
n = 0;
while(n < count) {
// digit[n] is value of hex digit at position n
// (m << 2) is the number of positions to shift
// OR the bits into return value
intValue = intValue | (digit[n] << (m << 2));
m--; // adjust the position to set
n++; // next digit to process
}
return (intValue);
}
// [Lance] Hex string to integer converter
BUILDIN_FUNC(axtoi)
{
const char *hex = script_getstr(st,2);
script_pushint(st,axtoi(hex));
return SCRIPT_CMD_SUCCESS;
}
// [zBuffer] List of player cont commands --->
BUILDIN_FUNC(rid2name)
{
@ -17556,10 +17545,12 @@ BUILDIN_FUNC(get_githash) {
**/
BUILDIN_FUNC(freeloop) {
if( script_getnum(st,2) )
st->freeloop = 1;
else
st->freeloop = 0;
if( script_hasdata(st,2) ) {
if( script_getnum(st,2) )
st->freeloop = 1;
else
st->freeloop = 0;
}
script_pushint(st, st->freeloop);
return SCRIPT_CMD_SUCCESS;
@ -18893,6 +18884,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(query_logsql,"s*"),
BUILDIN_DEF(escape_sql,"v"),
BUILDIN_DEF(atoi,"s"),
BUILDIN_DEF(strtol,"si"),
// [zBuffer] List of player cont commands --->
BUILDIN_DEF(rid2name,"i"),
BUILDIN_DEF(pcfollow,"ii"),
@ -18992,7 +18984,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(is_function,"s"),
BUILDIN_DEF(get_revision,""),
BUILDIN_DEF(get_githash,""),
BUILDIN_DEF(freeloop,"i"),
BUILDIN_DEF(freeloop,"?"),
BUILDIN_DEF(getrandgroupitem,"ii?"),
BUILDIN_DEF(cleanmap,"s"),
BUILDIN_DEF2(cleanmap,"cleanarea","siiii"),