From 58b8c8d8cb9f78537495f908887fea9d0a451637 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sat, 4 Jul 2015 22:37:51 +0300 Subject: Rename login/char/map dirs to elogin/echar/emap for avoid conflicts with hercules. --- src/elogin/config.c | 43 ++++++ src/elogin/config.h | 14 ++ src/elogin/init.c | 59 ++++++++ src/elogin/login.c | 30 ++++ src/elogin/login.h | 9 ++ src/elogin/md5calc.c | 406 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/elogin/md5calc.h | 13 ++ src/elogin/mt_rand.c | 118 +++++++++++++++ src/elogin/mt_rand.h | 9 ++ src/elogin/parse.c | 210 ++++++++++++++++++++++++++ src/elogin/parse.h | 14 ++ src/elogin/send.c | 47 ++++++ src/elogin/send.h | 11 ++ 13 files changed, 983 insertions(+) create mode 100644 src/elogin/config.c create mode 100644 src/elogin/config.h create mode 100644 src/elogin/init.c create mode 100644 src/elogin/login.c create mode 100644 src/elogin/login.h create mode 100644 src/elogin/md5calc.c create mode 100644 src/elogin/md5calc.h create mode 100644 src/elogin/mt_rand.c create mode 100644 src/elogin/mt_rand.h create mode 100644 src/elogin/parse.c create mode 100644 src/elogin/parse.h create mode 100644 src/elogin/send.c create mode 100644 src/elogin/send.h (limited to 'src/elogin') diff --git a/src/elogin/config.c b/src/elogin/config.c new file mode 100644 index 0000000..83c3c4f --- /dev/null +++ b/src/elogin/config.c @@ -0,0 +1,43 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#include +#include +#include + +#include "common/HPMi.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/socket.h" +#include "common/strlib.h" + +#include "elogin/config.h" + +char *update_server = NULL; +char *inter_server_ip = NULL; + +void config_update_server(const char *val) +{ + update_server = aStrdup(val); +} + +void config_inter_server_ip(const char *val) +{ + char buf[1000]; + + if (strlen(val) > 900) + return; + + strcpy(buf, ","); + strcat(buf, val); + strcat(buf, ","); + inter_server_ip = aStrdup(buf); +} + +void config_final(void) +{ + if (update_server) + aFree(update_server); + if (inter_server_ip) + aFree(inter_server_ip); +} diff --git a/src/elogin/config.h b/src/elogin/config.h new file mode 100644 index 0000000..ad63371 --- /dev/null +++ b/src/elogin/config.h @@ -0,0 +1,14 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#ifndef EVOL_LOGIN_CONFIG +#define EVOL_LOGIN_CONFIG + +void config_update_server(const char *val); +void config_final(void); +void config_inter_server_ip(const char *val); + +extern char *update_server; +extern char *inter_server_ip; + +#endif // EVOL_LOGIN_CONFIG diff --git a/src/elogin/init.c b/src/elogin/init.c new file mode 100644 index 0000000..6105b3b --- /dev/null +++ b/src/elogin/init.c @@ -0,0 +1,59 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#include +#include +#include + +#include "common/HPMi.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "login/login.h" + +#include "ecommon/init.h" +#include "elogin/config.h" +#include "elogin/login.h" +#include "elogin/parse.h" + +#include "common/HPMDataCheck.h" /* should always be the last file included! (if you don't make it last, it'll intentionally break compile time) */ + +HPExport struct hplugin_info pinfo = +{ + "evol_login", + SERVER_TYPE_LOGIN, + "0.1", + HPM_VERSION +}; + +HPExport void plugin_init (void) +{ + interfaces_init_common(); + + login = GET_SYMBOL("login"); + + addPacket(0x7530, 22, login_parse_version, hpParse_Login); + addPacket(0x027c, 95, elogin_parse_client_login2, hpParse_Login); + addPacket(0x5000, 54, elogin_parse_change_paassword, hpParse_FromChar); + addHookPre("login->parse_client_login", elogin_parse_client_login_pre); + addHookPre("login->parse_request_connection", elogin_parse_request_connection); + addHookPre("login->check_password", elogin_check_password); + addHookPre("login->parse_ping", elogin_parse_ping); +} + +HPExport void server_preinit (void) +{ + iMalloc = GET_SYMBOL("iMalloc"); + addLoginConf("update_server", config_update_server); + addLoginConf("inter_server_ip", config_inter_server_ip); +} + +HPExport void server_online (void) +{ +} + +HPExport void plugin_final (void) +{ + config_final(); +} diff --git a/src/elogin/login.c b/src/elogin/login.c new file mode 100644 index 0000000..3766a1e --- /dev/null +++ b/src/elogin/login.c @@ -0,0 +1,30 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#include +#include +#include + +#include "common/HPMi.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "login/login.h" + +#include "elogin/md5calc.h" + +bool elogin_check_password(const char* md5key __attribute__ ((unused)), + int *passwdenc __attribute__ ((unused)), + const char* passwd, + const char* refpass) +{ + if (!strcmp(passwd, refpass) || pass_ok(passwd, refpass)) + { + hookStop(); + return 1; + } + + hookStop(); + return 0; +} diff --git a/src/elogin/login.h b/src/elogin/login.h new file mode 100644 index 0000000..0783a5c --- /dev/null +++ b/src/elogin/login.h @@ -0,0 +1,9 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#ifndef EVOL_LOGIN_LOGIN +#define EVOL_LOGIN_LOGIN + +bool elogin_check_password(const char* md5key, int *passwdenc, const char* passwd, const char* refpass); + +#endif // EVOL_LOGIN_SEND diff --git a/src/elogin/md5calc.c b/src/elogin/md5calc.c new file mode 100644 index 0000000..bfa7b92 --- /dev/null +++ b/src/elogin/md5calc.c @@ -0,0 +1,406 @@ +// $Id: md5calc.c,v 1.1.1.1 2004/09/10 17:26:54 MagicalTux Exp $ +/*********************************************************** + * md5 calculation algorithm + * + * The source code referred to the following URL. + * http://www.geocities.co.jp/SiliconValley-Oakland/8878/lab17/lab17.html + * + ***********************************************************/ + +#include "md5calc.h" +#include +#include +#include "mt_rand.h" + +#ifndef UINT_MAX +#define UINT_MAX 4294967295U +#endif + +// Global variable +static unsigned int *pX; + +// Stirng Table +static const unsigned int T[] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, //0 + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, //4 + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, //8 + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, //12 + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, //16 + 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, //20 + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, //24 + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, //28 + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, //32 + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, //36 + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, //40 + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, //44 + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, //48 + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, //52 + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, //56 + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 //60 +}; + +// ROTATE_LEFT The left is made to rotate x [ n-bit ]. This is diverted as it is from RFC. +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +// The function used for other calculation +static unsigned int F (unsigned int X, unsigned int Y, unsigned int Z) +{ + return (X & Y) | (~X & Z); +} + +static unsigned int G (unsigned int X, unsigned int Y, unsigned int Z) +{ + return (X & Z) | (Y & ~Z); +} + +static unsigned int H (unsigned int X, unsigned int Y, unsigned int Z) +{ + return X ^ Y ^ Z; +} + +static unsigned int I (unsigned int X, unsigned int Y, unsigned int Z) +{ + return Y ^ (X | ~Z); +} + +static unsigned int Round (unsigned int a, unsigned int b, unsigned int FGHI, + unsigned int k, unsigned int s, unsigned int i) +{ + return b + ROTATE_LEFT (a + FGHI + pX[k] + T[i], s); +} + +static void Round1 (unsigned int *a, unsigned int b, unsigned int c, + unsigned int d, unsigned int k, unsigned int s, + unsigned int i) +{ + *a = Round (*a, b, F (b, c, d), k, s, i); +} + +static void Round2 (unsigned int *a, unsigned int b, unsigned int c, + unsigned int d, unsigned int k, unsigned int s, + unsigned int i) +{ + *a = Round (*a, b, G (b, c, d), k, s, i); +} + +static void Round3 (unsigned int *a, unsigned int b, unsigned int c, + unsigned int d, unsigned int k, unsigned int s, + unsigned int i) +{ + *a = Round (*a, b, H (b, c, d), k, s, i); +} + +static void Round4 (unsigned int *a, unsigned int b, unsigned int c, + unsigned int d, unsigned int k, unsigned int s, + unsigned int i) +{ + *a = Round (*a, b, I (b, c, d), k, s, i); +} + +static void MD5_Round_Calculate (const unsigned char *block, + unsigned int *A2, unsigned int *B2, + unsigned int *C2, unsigned int *D2) +{ + //create X It is since it is required. + unsigned int X[16]; //512bit 64byte + int j, k; + + //Save A as AA, B as BB, C as CC, and and D as DD (saving of A, B, C, and D) + unsigned int A = *A2, B = *B2, C = *C2, D = *D2; + unsigned int AA = A, BB = B, CC = C, DD = D; + + //It is a large region variable reluctantly because of calculation of a round. . . for Round1...4 + pX = X; + + //Copy block(padding_message) i into X + for (j = 0, k = 0; j < 64; j += 4, k++) + X[k] = ((unsigned int) block[j]) // 8byte*4 -> 32byte conversion + | (((unsigned int) block[j + 1]) << 8) // A function called Decode as used in the field of RFC + | (((unsigned int) block[j + 2]) << 16) + | (((unsigned int) block[j + 3]) << 24); + + //Round 1 + Round1 (&A, B, C, D, 0, 7, 0); + Round1 (&D, A, B, C, 1, 12, 1); + Round1 (&C, D, A, B, 2, 17, 2); + Round1 (&B, C, D, A, 3, 22, 3); + Round1 (&A, B, C, D, 4, 7, 4); + Round1 (&D, A, B, C, 5, 12, 5); + Round1 (&C, D, A, B, 6, 17, 6); + Round1 (&B, C, D, A, 7, 22, 7); + Round1 (&A, B, C, D, 8, 7, 8); + Round1 (&D, A, B, C, 9, 12, 9); + Round1 (&C, D, A, B, 10, 17, 10); + Round1 (&B, C, D, A, 11, 22, 11); + Round1 (&A, B, C, D, 12, 7, 12); + Round1 (&D, A, B, C, 13, 12, 13); + Round1 (&C, D, A, B, 14, 17, 14); + Round1 (&B, C, D, A, 15, 22, 15); + + //Round 2 + Round2 (&A, B, C, D, 1, 5, 16); + Round2 (&D, A, B, C, 6, 9, 17); + Round2 (&C, D, A, B, 11, 14, 18); + Round2 (&B, C, D, A, 0, 20, 19); + Round2 (&A, B, C, D, 5, 5, 20); + Round2 (&D, A, B, C, 10, 9, 21); + Round2 (&C, D, A, B, 15, 14, 22); + Round2 (&B, C, D, A, 4, 20, 23); + Round2 (&A, B, C, D, 9, 5, 24); + Round2 (&D, A, B, C, 14, 9, 25); + Round2 (&C, D, A, B, 3, 14, 26); + Round2 (&B, C, D, A, 8, 20, 27); + Round2 (&A, B, C, D, 13, 5, 28); + Round2 (&D, A, B, C, 2, 9, 29); + Round2 (&C, D, A, B, 7, 14, 30); + Round2 (&B, C, D, A, 12, 20, 31); + + //Round 3 + Round3 (&A, B, C, D, 5, 4, 32); + Round3 (&D, A, B, C, 8, 11, 33); + Round3 (&C, D, A, B, 11, 16, 34); + Round3 (&B, C, D, A, 14, 23, 35); + Round3 (&A, B, C, D, 1, 4, 36); + Round3 (&D, A, B, C, 4, 11, 37); + Round3 (&C, D, A, B, 7, 16, 38); + Round3 (&B, C, D, A, 10, 23, 39); + Round3 (&A, B, C, D, 13, 4, 40); + Round3 (&D, A, B, C, 0, 11, 41); + Round3 (&C, D, A, B, 3, 16, 42); + Round3 (&B, C, D, A, 6, 23, 43); + Round3 (&A, B, C, D, 9, 4, 44); + Round3 (&D, A, B, C, 12, 11, 45); + Round3 (&C, D, A, B, 15, 16, 46); + Round3 (&B, C, D, A, 2, 23, 47); + + //Round 4 + Round4 (&A, B, C, D, 0, 6, 48); + Round4 (&D, A, B, C, 7, 10, 49); + Round4 (&C, D, A, B, 14, 15, 50); + Round4 (&B, C, D, A, 5, 21, 51); + Round4 (&A, B, C, D, 12, 6, 52); + Round4 (&D, A, B, C, 3, 10, 53); + Round4 (&C, D, A, B, 10, 15, 54); + Round4 (&B, C, D, A, 1, 21, 55); + Round4 (&A, B, C, D, 8, 6, 56); + Round4 (&D, A, B, C, 15, 10, 57); + Round4 (&C, D, A, B, 6, 15, 58); + Round4 (&B, C, D, A, 13, 21, 59); + Round4 (&A, B, C, D, 4, 6, 60); + Round4 (&D, A, B, C, 11, 10, 61); + Round4 (&C, D, A, B, 2, 15, 62); + Round4 (&B, C, D, A, 9, 21, 63); + + // Then perform the following additions. (let's add) + *A2 = A + AA; + *B2 = B + BB; + *C2 = C + CC; + *D2 = D + DD; + + //The clearance of confidential information + memset (pX, 0, sizeof (X)); +} + +//------------------------------------------------------------------- +// The function for the exteriors + +/** output is the coded binary in the character sequence which wants to code string. */ +void MD5_String2binary (const char *string, char *output) +{ + if (!output) + return; + if (!string) + { + *output=0; + return; + } +//var + /*8bit */ + unsigned char padding_message[64]; //Extended message 512bit 64byte + unsigned char *pstring; //The position of string in the present scanning notes is held. + +// unsigned char digest[16]; + /*32bit */ + unsigned int string_byte_len, //The byte chief of string is held. + string_bit_len, //The bit length of string is held. + copy_len, //The number of bytes which is used by 1-3 and which remained + msg_digest[4]; //Message digest 128bit 4byte + unsigned int *A = &msg_digest[0], //The message digest in accordance with RFC (reference) + *B = &msg_digest[1], *C = &msg_digest[2], *D = &msg_digest[3]; + int i; + +//prog + //Step 3.Initialize MD Buffer (although it is the initialization; step 3 of A, B, C, and D -- unavoidable -- a head) + *A = 0x67452301; + *B = 0xefcdab89; + *C = 0x98badcfe; + *D = 0x10325476; + + //Step 1.Append Padding Bits (extension of a mark bit) + //1-1 + string_byte_len = strlen (string); //The byte chief of a character sequence is acquired. + pstring = (unsigned char *) string; //The position of the present character sequence is set. + + //1-2 Repeat calculation until length becomes less than 64 bytes. + for (i = string_byte_len; 64 <= i; i -= 64, pstring += 64) + MD5_Round_Calculate (pstring, A, B, C, D); + + //1-3 + copy_len = string_byte_len % 64; //The number of bytes which remained is computed. + strncpy ((char *) padding_message, (char *) pstring, copy_len); //A message is copied to an extended bit sequence. + memset (padding_message + copy_len, 0, 64 - copy_len); //It buries by 0 until it becomes extended bit length. + padding_message[copy_len] |= 0x80; //The next of a message is 1. + + //1-4 + //If 56 bytes or more (less than 64 bytes) of remainder becomes, it will calculate by extending to 64 bytes. + if (56 <= copy_len) + { + MD5_Round_Calculate (padding_message, A, B, C, D); + memset (padding_message, 0, 56); //56 bytes is newly fill uped with 0. + } + + //Step 2.Append Length (the information on length is added) + string_bit_len = string_byte_len * 8; //From the byte chief to bit length (32 bytes of low rank) + memcpy (&padding_message[56], &string_bit_len, 4); //32 bytes of low rank is set. + + //When bit length cannot be expressed in 32 bytes of low rank, it is a beam raising to a higher rank. + if (UINT_MAX / 8 < string_byte_len) + { + unsigned int high = (string_byte_len - UINT_MAX / 8) * 8; + memcpy (&padding_message[60], &high, 4); + } + else + memset (&padding_message[60], 0, 4); //In this case, it is good for a higher rank at 0. + + //Step 4.Process Message in 16-Word Blocks (calculation of MD5) + MD5_Round_Calculate (padding_message, A, B, C, D); + + //Step 5.Output (output) + memcpy (output, msg_digest, 16); +// memcpy (digest, msg_digest, and 16); //8 byte*4 < - 32byte conversion A function called Encode as used in the field of RFC +/* sprintf(output, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + digest[ 0], digest[ 1], digest[ 2], digest[ 3], + digest[ 4], digest[ 5], digest[ 6], digest[ 7], + digest[ 8], digest[ 9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15]);*/ +} + +/** output is the coded character sequence in the character sequence which wants to code string. */ +void MD5_String (const char *string, char *output) +{ + if (!output) + return; + if (!string) + { + *output=0; + return; + } + unsigned char digest[16]; + + MD5_String2binary (string, (char *)digest); + sprintf (output, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15]); +} + +// Hash a password with a salt. +char *MD5_saltcrypt(const char *key, const char *salt) +{ + if (!salt) + return 0; + + char buf[66], *sbuf = buf+32; + static char obuf[33]; + + // hash the key then the salt + // buf ends up as a 64char null terminated string + MD5_String(key, buf); + MD5_String(salt, sbuf); + + // Hash the buffer back into sbuf + MD5_String(buf, sbuf); + + snprintf(obuf, 32, "!%s$%s", salt, sbuf); + return(obuf); +} + +char *make_salt(void) +{ + static char salt[6]; + int i; + for (i=0; i<5; i++) + salt[i] = (char)((mt_rand() % 78) + 48); + salt[5] = '\0'; + return(salt); +} + +int pass_ok(const char *password, const char *crypted) +{ + if (!password || !crypted) + return 0; + + char buf[40], *salt=buf+1; + + strncpy(buf, crypted, 40); + buf[39] = 0; + char *ptr = strchr(buf, '$'); + if (ptr) + { + *ptr = '\0'; + + if (!strcmp(crypted, MD5_saltcrypt(password, salt))) + return(1); + } + else + { + //++ may be here need compare non encripted passwords? +// if (!strcmp(crypted, password)) +// return(1); + } + + return(0); +} + +// [M|h]ashes up an IP address and a secret key +// to return a hopefully unique masked IP. +in_addr_t MD5_ip(char *secret, in_addr_t ip) +{ + char ipbuf[32]; + char obuf[16]; + union { + struct bytes { + unsigned char b1; + unsigned char b2; + unsigned char b3; + unsigned char b4; + } bytes; + in_addr_t ip; + } conv; + + if (!secret) + { + conv.bytes.b1 = 0; + conv.bytes.b2 = 0; + conv.bytes.b3 = 0; + conv.bytes.b4 = 0; + return conv.ip; + } + + // MD5sum a secret + the IP address + memset(&ipbuf, 0, sizeof(ipbuf)); + snprintf(ipbuf, sizeof(ipbuf), "%lu%s", (unsigned long)ip, secret); + MD5_String2binary(ipbuf, obuf); + + // Fold the md5sum to 32 bits, pack the bytes to an in_addr_t + conv.bytes.b1 = obuf[0] ^ obuf[1] ^ obuf[8] ^ obuf[9]; + conv.bytes.b2 = obuf[2] ^ obuf[3] ^ obuf[10] ^ obuf[11]; + conv.bytes.b3 = obuf[4] ^ obuf[5] ^ obuf[12] ^ obuf[13]; + conv.bytes.b4 = obuf[6] ^ obuf[7] ^ obuf[14] ^ obuf[15]; + + return conv.ip; +} + diff --git a/src/elogin/md5calc.h b/src/elogin/md5calc.h new file mode 100644 index 0000000..cf82738 --- /dev/null +++ b/src/elogin/md5calc.h @@ -0,0 +1,13 @@ +// $Id: md5calc.h,v 1.1.1.1 2004/09/10 17:26:54 MagicalTux Exp $ +#ifndef _MD5CALC_H_ +#define _MD5CALC_H_ +#include + +void MD5_String (const char *string, char *output); +void MD5_String2binary (const char *string, char *output); +char *MD5_saltcrypt(const char *key, const char *salt); +char *make_salt(void); +int pass_ok(const char *password, const char *crypted); +in_addr_t MD5_ip(char *secret, in_addr_t ip); + +#endif diff --git a/src/elogin/mt_rand.c b/src/elogin/mt_rand.c new file mode 100644 index 0000000..627d9dd --- /dev/null +++ b/src/elogin/mt_rand.c @@ -0,0 +1,118 @@ +/* +// This is the ``Mersenne Twister'' random number generator MT19937, which +// generates pseudorandom integers uniformly distributed in 0..(2^32 - 1) +// starting from any odd seed in 0..(2^32 - 1). This version is a recode +// by Shawn Cokus (Cokus@math.washington.edu) on March 8, 1998 of a version by +// Takuji Nishimura (who had suggestions from Topher Cooper and Marc Rieffel in +// July-August 1997). +// +// Effectiveness of the recoding (on Goedel2.math.washington.edu, a DEC Alpha +// running OSF/1) using GCC -O3 as a compiler: before recoding: 51.6 sec. to +// generate 300 million random numbers; after recoding: 24.0 sec. for the same +// (i.e., 46.5% of original time), so speed is now about 12.5 million random +// number generations per second on this machine. +// +// According to the URL +// (and paraphrasing a bit in places), the Mersenne Twister is ``designed +// with consideration of the flaws of various existing generators,'' has +// a period of 2^19937 - 1, gives a sequence that is 623-dimensionally +// equidistributed, and ``has passed many stringent tests, including the +// die-hard test of G. Marsaglia and the load test of P. Hellekalek and +// S. Wegenkittl.'' It is efficient in memory usage (typically using 2506 +// to 5012 bytes of static data, depending on data type sizes, and the code +// is quite short as well). It generates random numbers in batches of 624 +// at a time, so the caching and pipelining of modern systems is exploited. +// It is also divide- and mod-free. +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Library General Public License as published by +// the Free Software Foundation (either version 2 of the License or, at your +// option, any later version). This library is distributed in the hope that +// it will be useful, but WITHOUT ANY WARRANTY, without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +// the GNU Library General Public License for more details. You should have +// received a copy of the GNU Library General Public License along with this +// library; if not, write to the Free Software Foundation, Inc., 59 Temple +// Place, Suite 330, Boston, MA 02111-1307, USA. +// +// The code as Shawn received it included the following notice: +// +// Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. When +// you use this, send an e-mail to with +// an appropriate reference to your work. +// +// It would be nice to CC: when you write. +// +*/ + +#include +#include "mt_rand.h" + +#define N (624) /* length of state vector */ +#define M (397) /* a period parameter */ +#define K (0x9908B0DFU) /* a magic constant */ +#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */ +#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */ +#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ +#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ + +static unsigned long state[N + 1]; /* state vector + 1 extra to not violate ANSI C */ +static unsigned long *next; /* next random value is computed from here */ +static int left = -1; /* can *next++ this many times before reloading */ + +void mt_seed (unsigned long seed) +{ + register unsigned long x = (seed | 1U) & 0xFFFFFFFFU, *s = state; + register int j; + + for (left = 0, *s++ = x, j = N; --j; *s++ = (x *= 69069U) & 0xFFFFFFFFU); +} + +unsigned long mt_reload (void) +{ + register unsigned long *p0 = state, *p2 = state + 2, *pM = + state + M, s0, s1; + register int j; + + if (left < -1) + mt_seed (time (NULL)); + + left = N - 1, next = state + 1; + + for (s0 = state[0], s1 = state[1], j = N - M + 1; --j; + s0 = s1, s1 = *p2++) + *p0++ = *pM++ ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U); + + for (pM = state, j = M; --j; s0 = s1, s1 = *p2++) + *p0++ = *pM++ ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U); + + s1 = state[0], *p0 = + *pM ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U); + s1 ^= (s1 >> 11); + s1 ^= (s1 << 7) & 0x9D2C5680U; + s1 ^= (s1 << 15) & 0xEFC60000U; + return (s1 ^ (s1 >> 18)); +} + +unsigned long mt_random (void) +{ + unsigned long y; + + if (--left < 0) + return (mt_reload ()); + + y = *next++; + y ^= (y >> 11); + y ^= (y << 7) & 0x9D2C5680U; + y ^= (y << 15) & 0xEFC60000U; + return (y ^ (y >> 18)); +} + +int mt_rand (void) +{ + unsigned long r = mt_random (); + while (r >> 16) + r = (r & 0xFFFF) + (r >> 16); + + return (r); +} diff --git a/src/elogin/mt_rand.h b/src/elogin/mt_rand.h new file mode 100644 index 0000000..d798fee --- /dev/null +++ b/src/elogin/mt_rand.h @@ -0,0 +1,9 @@ +#ifndef __mt_rand_h +#define __mt_rand_h + +void mt_seed (unsigned long seed); +unsigned long mt_reload (void); +unsigned long mt_random (void); +int mt_rand (void); + +#endif /* __mt_rand_h */ diff --git a/src/elogin/parse.c b/src/elogin/parse.c new file mode 100644 index 0000000..8f62e9f --- /dev/null +++ b/src/elogin/parse.c @@ -0,0 +1,210 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#include +#include +#include + +#include "common/HPMi.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "login/account.h" +#include "login/login.h" + +#include "ecommon/ip.h" +#include "elogin/config.h" +#include "elogin/md5calc.h" +#include "elogin/parse.h" +#include "elogin/send.h" + +int clientVersion = 0; + +void login_parse_version(int fd) +{ + struct login_session_data* sd = (struct login_session_data*)session[fd]->session_data; + if (!sd) + return; + + clientVersion = RFIFOL(fd, 2); + + if (clientVersion < 2) + { + login->login_error(fd, 5); + return; + } + + send_update_host(fd); + send_server_version(fd); +} + +int elogin_parse_client_login_pre(int *fdPtr, + struct login_session_data* sd __attribute__ ((unused)), + const char *const ip __attribute__ ((unused))) +{ + int fd = *fdPtr; + uint16 command = RFIFOW(fd,0); + if (command != 0x64) + { + login->login_error(fd, 3); + hookStop(); + return 1; + } + char username[NAME_LENGTH]; + safestrncpy(username, (const char*)RFIFOP(fd, 6), NAME_LENGTH); + int len = strnlen(username, NAME_LENGTH); + if (clientVersion < 2) + { + login->login_error(fd, 5); + hookStop(); + return 1; + } + else if (len >= 2 && username[len - 2] == '_' && memchr("FfMm", username[len - 1], 4)) + { + login->login_error(fd, 3); + hookStop(); + return 1; + } + + return 0; +} + +void elogin_parse_client_login2(int fd) +{ + char username[NAME_LENGTH]; + char password[PASSWD_LEN]; + char email[40]; + uint8 clienttype; + int result; + + safestrncpy(username, (const char*)RFIFOP(fd, 2), NAME_LENGTH); + + int len = strnlen(username, NAME_LENGTH); + if (len < 2 || !(username[len - 2] == '_') || !memchr("FfMm", username[len - 1], 4)) + { + login->login_error(fd, 3); + return; + } + + safestrncpy(password, (const char*)RFIFOP(fd, 26), NAME_LENGTH); + safestrncpy(email, (const char*)RFIFOP(fd, 51), 40); + clienttype = RFIFOB(fd, 50); + + struct login_session_data* sd = (struct login_session_data*)session[fd]->session_data; + if (!sd) + return; + + char ip[16]; + uint32 ipl = session[fd]->client_addr; + ip2str(ipl, ip); + sd->clienttype = clienttype; + sd->version = clientVersion; + sd->passwdenc = 0; + safestrncpy(sd->userid, username, NAME_LENGTH); + ShowStatus("Request for connection of %s (ip: %s).\n", sd->userid, ip); + safestrncpy(sd->passwd, password, PASSWD_LEN); + + if (e_mail_check(email) == 0) + { + ShowNotice("Attempt to create an e-mail REFUSED - e-mail is invalid (ip: %s)\n", ip); + login->login_error(fd, 11); + return; + } + + result = login->mmo_auth(sd, false); + + if (result == -1) + { + int account_id = sd->account_id; + struct mmo_account acc; + if (!login->accounts->load_num(login->accounts, &acc, account_id)) + { + ShowNotice("Attempt to create an e-mail on an account REFUSED - account: %d, ip: %s).\n", account_id, ip); + } + else + { + memcpy(acc.email, email, 40); + ShowNotice("Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n", account_id, email, ip); + // Save + login->accounts->save(login->accounts, &acc); + } + + login->auth_ok(sd); + } + else + { + login->auth_failed(sd, result); + } + + return; +} + +void elogin_parse_request_connection(int *fd, struct login_session_data* sd, const char *const ip) +{ + if (!inter_server_ip || !ip) + return; + if (!checkAllowedIp(inter_server_ip, ip)) + { + hookStop(); + login->char_server_connection_status(*fd, sd, 3); + ShowNotice("Connection of the char-server from ip %s REFUSED.\n", ip); + } +} + +void elogin_parse_ping(int *fd, struct login_session_data* sd) +{ + RFIFOSKIP(*fd, 26); + if (!sd) + { + hookStop(); + return; + } + struct online_login_data* data = (struct online_login_data*)idb_get(login->online_db, sd->account_id); + if (data == NULL) + { + hookStop(); + return; + } + if (data->waiting_disconnect != INVALID_TIMER) + { + timer->delete(data->waiting_disconnect, login->waiting_disconnect_timer); + data->waiting_disconnect = timer->add(timer->gettick() + 30000, login->waiting_disconnect_timer, sd->account_id, 0); + } + hookStop(); +} + +void elogin_parse_change_paassword(int fd) +{ + char actual_pass[24], new_pass[24]; + int status = 0; + struct mmo_account acc; + const int accountId = RFIFOL (fd, 2); + + memcpy (actual_pass, RFIFOP (fd, 6), 24); + actual_pass[23] = '\0'; + memcpy (new_pass, RFIFOP (fd, 30), 24); + new_pass[23] = '\0'; + + if (!login->accounts->load_num(login->accounts, &acc, accountId)) + { + // account not found + send_char_password_change_ack(fd, accountId, 0); + return; + } + + if (!strcmp(actual_pass, acc.pass) || pass_ok(actual_pass, acc.pass)) + { + // changed ok + status = 1; + safestrncpy(acc.pass, new_pass, sizeof(acc.pass)); + login->accounts->save(login->accounts, &acc); + } + else + { + // wrong password + status = 2; + } + send_char_password_change_ack(fd, accountId, status); +} diff --git a/src/elogin/parse.h b/src/elogin/parse.h new file mode 100644 index 0000000..b5c2418 --- /dev/null +++ b/src/elogin/parse.h @@ -0,0 +1,14 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#ifndef EVOL_LOGIN_PARSE +#define EVOL_LOGIN_PARSE + +void login_parse_version(int fd); +int elogin_parse_client_login_pre(int *fd, struct login_session_data* sd, const char *const ip); +void elogin_parse_client_login2(int fd); +void elogin_parse_request_connection(int *fd, struct login_session_data* sd, const char *const ip); +void elogin_parse_ping(int *fd, struct login_session_data* sd); +void elogin_parse_change_paassword(int fd); + +#endif // EVOL_LOGIN_PARSE diff --git a/src/elogin/send.c b/src/elogin/send.c new file mode 100644 index 0000000..396c314 --- /dev/null +++ b/src/elogin/send.c @@ -0,0 +1,47 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#include +#include +#include + +#include "common/HPMi.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "login/login.h" + +#include "elogin/config.h" +#include "elogin/send.h" + +void send_server_version(int fd) +{ + WFIFOHEAD(fd, 4 + 8); + WFIFOW(fd, 0) = 0x7531; + WFIFOW(fd, 2) = 4 + 8; + WFIFOL(fd, 4) = 0; // unused + WFIFOL(fd, 8) = 6; // server version + WFIFOSET(fd, WFIFOW(fd,2)); +} + +void send_update_host(int fd) +{ + if (!update_server) + return; + const int sz = strlen(update_server); + WFIFOHEAD(fd, sz + 4); + WFIFOW(fd, 0) = 0x63; + WFIFOW(fd, 2) = sz + 4; + memcpy(WFIFOP (fd, 4), update_server, sz); + WFIFOSET(fd, sz + 4); +} + +void send_char_password_change_ack(int fd, int accoundId, char status) +{ + WFIFOHEAD(fd, 7); + WFIFOW(fd, 0) = 0x5001; + WFIFOL(fd, 2) = accoundId; + WFIFOB(fd, 6) = status; + WFIFOSET(fd, 7); +} diff --git a/src/elogin/send.h b/src/elogin/send.h new file mode 100644 index 0000000..5fdb6c4 --- /dev/null +++ b/src/elogin/send.h @@ -0,0 +1,11 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 Evol developers + +#ifndef EVOL_LOGIN_SEND +#define EVOL_LOGIN_SEND + +void send_server_version(); +void send_update_host(int fd); +void send_char_password_change_ack(int fd, int accoundId, char status); + +#endif // EVOL_LOGIN_SEND -- cgit v1.2.3-60-g2f50