diff options
author | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2010-02-09 02:22:27 +0000 |
---|---|---|
committer | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2010-02-09 02:22:27 +0000 |
commit | aab7998583ca16590a32c7bdb80955a18b090700 (patch) | |
tree | a2b7f6d82a523e683347b7489ab77f0e940bdede | |
parent | db790d9d1516c9c7cd48738340e5df1c8a2bebe3 (diff) |
Add random number generation functions to InspIRCd class.
Default implementation uses libc random(), which can be better than rand().
If gnutls is loaded, gcrypt will be used to provide random numbers.
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@12404 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r-- | include/dns.h | 7 | ||||
-rw-r--r-- | include/inspircd.h | 16 | ||||
-rw-r--r-- | include/modules.h | 2 | ||||
-rw-r--r-- | src/dns.cpp | 19 | ||||
-rw-r--r-- | src/helperfuncs.cpp | 28 | ||||
-rw-r--r-- | src/inspircd.cpp | 3 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_gnutls.cpp | 15 | ||||
-rw-r--r-- | src/modules/m_conn_waitpong.cpp | 12 | ||||
-rw-r--r-- | src/modules/m_randquote.cpp | 40 | ||||
-rw-r--r-- | src/modules/m_spanningtree/capab.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_spanningtree/hmac.cpp | 30 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket.h | 4 |
12 files changed, 79 insertions, 99 deletions
diff --git a/include/dns.h b/include/dns.h index 3d326a69c..528490015 100644 --- a/include/dns.h +++ b/include/dns.h @@ -405,13 +405,6 @@ class CoreExport DNS : public EventHandler */ ~DNS(); - /** Portable random number generator, generates - * its random number from the ircd stats counters, - * effective user id, time of day and the rollover - * counter (currid) - */ - unsigned long PRNG(); - /** * Turn an in6_addr into a .ip6.arpa domain */ diff --git a/include/inspircd.h b/include/inspircd.h index 25ba846bc..b4fd12026 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -234,6 +234,7 @@ class serverstats }; DEFINE_HANDLER2(IsNickHandler, bool, const char*, size_t); +DEFINE_HANDLER2(GenRandomHandler, void, char*, size_t); DEFINE_HANDLER1(IsIdentHandler, bool, const char*); DEFINE_HANDLER1(FloodQuitUserHandler, void, User*); DEFINE_HANDLER2(IsChannelHandler, bool, const char*, size_t); @@ -310,6 +311,7 @@ class CoreExport InspIRCd IsChannelHandler HandleIsChannel; IsSIDHandler HandleIsSID; RehashHandler HandleRehash; + GenRandomHandler HandleGenRandom; /** Globally accessible fake user record. This is used to force mode changes etc across s2s, etc.. bit ugly, but.. better than how this was done in 1.1 * Reason for it: @@ -449,6 +451,20 @@ class CoreExport InspIRCd /** Update the current time. Don't call this unless you have reason to do so. */ void UpdateTime(); + /** Generate a random string with the given length + * @param length The length in bytes + * @param printable if false, the string will use characters 0-255; otherwise, + * it will be limited to 0x30-0x7E ('0'-'~', nonspace printable characters) + */ + std::string GenRandomStr(int length, bool printable = true); + /** Generate a random integer. + * This is generally more secure than rand() + */ + unsigned long GenRandomInt(unsigned long max); + + /** Fill a buffer with random bits */ + caller2<void, char*, size_t> GenRandom; + /** Bind all ports specified in the configuration file. * @return The number of ports bound without error */ diff --git a/include/modules.h b/include/modules.h index 25c57cb61..6e8e685aa 100644 --- a/include/modules.h +++ b/include/modules.h @@ -97,7 +97,7 @@ struct ModResult { /** If you change the module API in any way, increment this value. * This MUST be a pure integer, with no parenthesis */ -#define API_VERSION 138 +#define API_VERSION 139 /** * This #define allows us to call a method in all diff --git a/src/dns.cpp b/src/dns.cpp index dee83d3ac..8526d5be2 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -242,11 +242,9 @@ DNSRequest* DNS::AddQuery(DNSHeader *header, int &id, const char* original) return NULL; /* Create an id */ - id = this->PRNG() & DNS::MAX_REQUEST_ID; - - /* If this id is already 'in flight', pick another. */ - while (requests[id]) - id = this->PRNG() & DNS::MAX_REQUEST_ID; + do { + id = ServerInstance->GenRandomInt(DNS::MAX_REQUEST_ID); + } while (requests[id]); DNSRequest* req = new DNSRequest(this, id, original); @@ -1041,14 +1039,3 @@ void DNS::CleanResolvers(Module* module) } } } - -/** Generate pseudo-random number */ -unsigned long DNS::PRNG() -{ - unsigned long val = 0; - serverstats* s = ServerInstance->stats; - val = (rand() ^ this->currid++ ^ s->statsAccept) + ServerInstance->Time_ns(); - val += (s->statsCollisions ^ s->statsDnsGood) * s->statsDnsBad; - val += (s->statsConnects ^ (unsigned long)s->statsSent ^ (unsigned long)s->statsRecv); - return val; -} diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp index bba8dc8dc..66a84bbce 100644 --- a/src/helperfuncs.cpp +++ b/src/helperfuncs.cpp @@ -411,3 +411,31 @@ void InspIRCd::AddExtBanChar(char c) tok.insert(ebpos, 1, c); } } + +std::string InspIRCd::GenRandomStr(int length, bool printable) +{ + char* buf = new char[length]; + GenRandom(buf, length); + std::string rv; + rv.resize(length); + for(int i=0; i < length; i++) + rv[i] = printable ? 0x3F + (buf[i] & 0x3F) : buf[i]; + delete[] buf; + return rv; +} + +// NOTE: this has a slight bias for lower values if max is not a power of 2. +// Don't use it if that matters. +unsigned long InspIRCd::GenRandomInt(unsigned long max) +{ + unsigned long rv; + GenRandom((char*)&rv, sizeof(rv)); + return rv % max; +} + +// This is overridden by a higher-quality algorithm when SSL support is loaded +void GenRandomHandler::Call(char *output, size_t max) +{ + for(unsigned int i=0; i < max; i++) + output[i] = random(); +} diff --git a/src/inspircd.cpp b/src/inspircd.cpp index fe0ac0a11..b95a6fecb 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -295,6 +295,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : */ NICKForced("NICKForced", NULL), OperQuit("OperQuit", NULL), + GenRandom(&HandleGenRandom), IsChannel(&HandleIsChannel), IsSID(&HandleIsSID), Rehash(&HandleRehash), @@ -375,7 +376,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : this->Config->cmdline.argv = argv; this->Config->cmdline.argc = argc; - srand(TIME.tv_nsec ^ TIME.tv_sec); + srandom(TIME.tv_nsec ^ TIME.tv_sec); struct option longopts[] = { diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index a0804ddf9..c2dc4c878 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -14,6 +14,7 @@ #include "inspircd.h" #include <gnutls/gnutls.h> #include <gnutls/x509.h> +#include <gcrypt.h> #include "ssl.h" #include "m_cap.h" @@ -69,6 +70,16 @@ static ssize_t gnutls_push_wrapper(gnutls_transport_ptr_t user_wrap, const void* return rv; } +class RandGen : public HandlerBase2<void, char*, size_t> +{ + public: + RandGen() {} + void Call(char* buffer, size_t len) + { + gcry_randomize(buffer, len, GCRY_STRONG_RANDOM); + } +}; + /** Represents an SSL user's extra data */ class issl_session @@ -136,6 +147,7 @@ class ModuleSSLGnuTLS : public Module bool cred_alloc; + RandGen randhandler; CommandStartTLS starttls; GenericCap capHandler; @@ -159,6 +171,8 @@ class ModuleSSLGnuTLS : public Module // Needs the flag as it ignores a plain /rehash OnModuleRehash(NULL,"ssl"); + ServerInstance->GenRandom = &randhandler; + // Void return, guess we assume success gnutls_certificate_set_dh_params(x509_cred, dh_params); Implementation eventlist[] = { I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnUserConnect, @@ -294,6 +308,7 @@ class ModuleSSLGnuTLS : public Module } gnutls_global_deinit(); delete[] sessions; + ServerInstance->GenRandom = &ServerInstance->HandleGenRandom; } void OnCleanup(int target_type, void* item) diff --git a/src/modules/m_conn_waitpong.cpp b/src/modules/m_conn_waitpong.cpp index 1b9301de5..00b728b51 100644 --- a/src/modules/m_conn_waitpong.cpp +++ b/src/modules/m_conn_waitpong.cpp @@ -45,19 +45,9 @@ class ModuleWaitPong : public Module killonbadreply = true; } - std::string RandString() - { - char out[11]; - for(unsigned int i = 0; i < 10; i++) - out[i] = ((rand() % 26) + 65); - out[10] = '\0'; - - return out; - } - ModResult OnUserRegister(LocalUser* user) { - std::string pingrpl = RandString(); + std::string pingrpl = ServerInstance->GenRandomStr(10); user->Write("PING :%s", pingrpl.c_str()); diff --git a/src/modules/m_randquote.cpp b/src/modules/m_randquote.cpp index 5214d9ad2..7d4ad042f 100644 --- a/src/modules/m_randquote.cpp +++ b/src/modules/m_randquote.cpp @@ -15,7 +15,6 @@ static FileReader *quotes = NULL; -std::string q_file; std::string prefix; std::string suffix; @@ -35,17 +34,9 @@ class CommandRandquote : public Command std::string str; int fsize; - if (q_file.empty() || quotes->Exists()) - { - fsize = quotes->FileSize(); - str = quotes->GetLine(rand() % fsize); - user->WriteServ("NOTICE %s :%s%s%s",user->nick.c_str(),prefix.c_str(),str.c_str(),suffix.c_str()); - } - else - { - user->WriteServ("NOTICE %s :Your administrator specified an invalid quotes file, please bug them about this.", user->nick.c_str()); - return CMD_FAILURE; - } + fsize = quotes->FileSize(); + str = quotes->GetLine(ServerInstance->GenRandomInt(fsize)); + user->WriteServ("NOTICE %s :%s%s%s",user->nick.c_str(),prefix.c_str(),str.c_str(),suffix.c_str()); return CMD_SUCCESS; } @@ -59,29 +50,22 @@ class ModuleRandQuote : public Module ModuleRandQuote() : cmd(this) { - ConfigReader conf; - // Sort the Randomizer thingie.. - srand(ServerInstance->Time()); + } - q_file = conf.ReadValue("randquote","file",0); - prefix = conf.ReadValue("randquote","prefix",0); - suffix = conf.ReadValue("randquote","suffix",0); + void init() + { + ConfigTag* conf = ServerInstance->Config->ConfValue("randquote"); - if (q_file.empty()) - { - throw ModuleException("m_randquote: Quotefile not specified - Please check your config."); - } + std::string q_file = conf->getString("file","quotes"); + prefix = conf->getString("prefix"); + suffix = conf->getString("suffix"); quotes = new FileReader(q_file); - if(!quotes->Exists()) + if (!quotes->Exists()) { throw ModuleException("m_randquote: QuoteFile not Found!! Please check your config - module will not function."); } - else - { - /* Hidden Command -- Mode clients assume /quote sends raw data to an IRCd >:D */ - ServerInstance->AddCommand(&cmd); - } + ServerInstance->AddCommand(&cmd); Implementation eventlist[] = { I_OnUserConnect }; ServerInstance->Modules->Attach(eventlist, this, 1); } diff --git a/src/modules/m_spanningtree/capab.cpp b/src/modules/m_spanningtree/capab.cpp index 80236c37e..ba34d67b4 100644 --- a/src/modules/m_spanningtree/capab.cpp +++ b/src/modules/m_spanningtree/capab.cpp @@ -129,7 +129,7 @@ void TreeSocket::SendCapabilities(int phase) /* Do we have sha256 available? If so, we send a challenge */ if (Utils->ChallengeResponse && (ServerInstance->Modules->Find("m_sha256.so"))) { - this->SetOurChallenge(RandString(20)); + SetOurChallenge(ServerInstance->GenRandomStr(20)); extra = " CHALLENGE=" + this->GetOurChallenge(); } diff --git a/src/modules/m_spanningtree/hmac.cpp b/src/modules/m_spanningtree/hmac.cpp index c08ac1522..52128b17b 100644 --- a/src/modules/m_spanningtree/hmac.cpp +++ b/src/modules/m_spanningtree/hmac.cpp @@ -96,36 +96,6 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string return password; } -std::string TreeSocket::RandString(unsigned int ilength) -{ - char* randombuf = new char[ilength+1]; - std::string out; -#ifndef WINDOWS - int f = open("/dev/urandom", O_RDONLY, 0); - - if (f >= 0) - { - if (read(f, randombuf, ilength) < (int)ilength) - ServerInstance->Logs->Log("m_spanningtree", DEFAULT, "Entropy source has gone predictable (did not return enough data)"); - close(f); - } - else -#endif - { - for (unsigned int i = 0; i < ilength; i++) - randombuf[i] = rand(); - } - - for (unsigned int i = 0; i < ilength; i++) - { - char randchar = static_cast<char>(0x3F + (randombuf[i] & 0x3F)); - out += randchar; - } - - delete[] randombuf; - return out; -} - bool TreeSocket::ComparePass(const Link& link, const std::string &theirs) { capab->auth_fingerprint = !link.Fingerprint.empty(); diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 4438b473d..1eefc500e 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -146,10 +146,6 @@ class TreeSocket : public BufferedSocket */ ~TreeSocket(); - /** Generate random string used for challenge-response auth - */ - std::string RandString(unsigned int length); - /** Construct a password, optionally hashed with the other side's * challenge string */ |