summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/dns.h7
-rw-r--r--include/inspircd.h16
-rw-r--r--include/modules.h2
-rw-r--r--src/dns.cpp19
-rw-r--r--src/helperfuncs.cpp28
-rw-r--r--src/inspircd.cpp3
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp15
-rw-r--r--src/modules/m_conn_waitpong.cpp12
-rw-r--r--src/modules/m_randquote.cpp40
-rw-r--r--src/modules/m_spanningtree/capab.cpp2
-rw-r--r--src/modules/m_spanningtree/hmac.cpp30
-rw-r--r--src/modules/m_spanningtree/treesocket.h4
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
*/