From 974af7e3663c5f72091f8afd91e4ed732c42b20c Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Thu, 26 Feb 2015 13:09:29 +0300 Subject: login: add way to check hashed passwords in old tmw/evol way. --- src/Makefile.am | 6 + src/login/init.c | 2 + src/login/login.c | 30 ++++ src/login/login.h | 9 ++ src/login/md5calc.c | 406 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/login/md5calc.h | 13 ++ src/login/mt_rand.c | 118 +++++++++++++++ src/login/mt_rand.h | 9 ++ 8 files changed, 593 insertions(+) create mode 100644 src/login/login.c create mode 100644 src/login/login.h create mode 100644 src/login/md5calc.c create mode 100644 src/login/md5calc.h create mode 100644 src/login/mt_rand.c create mode 100644 src/login/mt_rand.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 991f39d..4996c78 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,6 +15,12 @@ CHAR_SRC = char/char.c \ LOGIN_SRC = login/config.c \ login/config.h \ login/init.c \ + login/login.c \ + login/login.h \ + login/md5calc.c \ + login/md5calc.h \ + login/mt_rand.c \ + login/mt_rand.h \ login/parse.c \ login/parse.h \ login/send.c \ diff --git a/src/login/init.c b/src/login/init.c index 33fda69..0912ff8 100644 --- a/src/login/init.c +++ b/src/login/init.c @@ -14,6 +14,7 @@ #include "common/init.h" #include "login/config.h" +#include "login/login.h" #include "login/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) */ @@ -36,6 +37,7 @@ HPExport void plugin_init (void) addPacket(0x027c, 95, elogin_parse_client_login2, hpParse_Login); 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); } HPExport void server_preinit (void) diff --git a/src/login/login.c b/src/login/login.c new file mode 100644 index 0000000..bee7aa2 --- /dev/null +++ b/src/login/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 "login/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/login/login.h b/src/login/login.h new file mode 100644 index 0000000..0783a5c --- /dev/null +++ b/src/login/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/login/md5calc.c b/src/login/md5calc.c new file mode 100644 index 0000000..bfa7b92 --- /dev/null +++ b/src/login/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/login/md5calc.h b/src/login/md5calc.h new file mode 100644 index 0000000..cf82738 --- /dev/null +++ b/src/login/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/login/mt_rand.c b/src/login/mt_rand.c new file mode 100644 index 0000000..627d9dd --- /dev/null +++ b/src/login/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/login/mt_rand.h b/src/login/mt_rand.h new file mode 100644 index 0000000..d798fee --- /dev/null +++ b/src/login/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 */ -- cgit v1.2.3-70-g09d2