* $Id$
*/
#include "random.h"
-#include "config.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
+#include "client.h"
+#include "ircd_log.h"
+#include "ircd_reply.h"
+#include "send.h"
#include <string.h>
+#include <sys/time.h>
+
+
+char localkey[9] = "12345678";
+
+/* This devious-looking construct rolls a character to the left by r bits */
+#define char_roll(c, r) (((c) << (r)) | ((c) >> (8 - (r))))
+
+/* this routine is intended to be called by the feature subsystem; it takes
+ * a key as found in the .conf and mashes it up for the seed for the random
+ * number generator.
+ */
+int
+random_seed_set(struct Client* from, const char* const* fields, int count)
+{
+ const char *p = 0;
+ int len, i, roll = 0;
+
+ if (count < 1) {
+ if (from) /* send an error */
+ return need_more_params(from, "SET");
+ else {
+ log_write(LS_CONFIG, L_ERROR, 0, "Not enough fields in F line");
+ return 0;
+ }
+ }
+
+ len = strlen(fields[0]);
-char localkey[9] = RANDOM_SEED;
+ /* logic is: go through loop at least 8 times, but use all bits of seed */
+ for (i = 0; i < (len < 8 ? 8 : len); i++, p++) {
+ if (!(i % len)) { /* if we've exceeded the string length, reset */
+ p = fields[0];
+ roll++; /* so latter part of string looks different from former */
+ }
+
+ /* set the appropriate location of localkey according to the following
+ * rules: first, roll current value by an amount depending on how many
+ * times we've touched this character. Then take seed value and roll
+ * it by an amount depending upon how many times we've touched that
+ * character. Finally, xor the values together.
+ */
+ localkey[i % 8] = char_roll(localkey[i % 8], (i / 8) % 8) ^
+ char_roll(*p, roll % 8);
+ }
+
+ return 1;
+}
+
+/* this is like memcpy except it xors the areas in memory. */
+static void
+memxor(void *dest, void *src, int n)
+{
+ unsigned char *d = (unsigned char *)dest;
+ unsigned char *s = (unsigned char *)src;
+
+ while (--n)
+ d[n] ^= s[n];
+}
/*
* MD5 transform algorithm, taken from code written by Colin Plumb,
* record: Cleaned up to work with ircd. RANDOM_TOKEN is defined in
* setup.h by the make script; if people start to "guess" your cookies,
* consider recompiling your server with a different random token.
+ *
+ * Kev: Now the seed comes from the feature subsystem and is fed into a
+ * mash routine (random_set_seed) that depends on previous values of the
+ * localkey array; also, part of the output of the RNG is fed back into
+ * the localkey array. Finally, the time values are xor'd with the local
+ * key to enhance non-determinability of the data fed into the MD5 core.
*/
/* The four core functions - F1 is optimized somewhat */
unsigned char in[16];
struct timeval tv;
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, 0);
memcpy((void *)in, (void *)localkey, 8);
- memcpy((void *)(in + 8), (void *)&tv.tv_sec, 4);
- memcpy((void *)(in + 12), (void *)&tv.tv_usec, 4);
+ memcpy((void *)(in + 8), (void *)localkey, 8);
+ memxor((void *)(in + 8), (void *)&tv.tv_sec, 4);
+ memxor((void *)(in + 12), (void *)&tv.tv_usec, 4);
a = 0x67452301;
b = 0xefcdab89;
MD5STEP(F4, c, d, a, b, (int)in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, (int)in[9] + 0xeb86d391, 21);
+ /* This feeds part of the output of the random number generator into the
+ * seed to further obscure any patterns
+ */
+ memxor((void *)localkey, (void *)&a, 4);
+ memxor((void *)(localkey + 4), (void *)&b, 4);
+
/*
* We have 4 unsigned longs generated by the above sequence; this scrambles
* them together so that if there is any pattern, it will be obscured.
+ *
+ * a and b are now part of the state of the random number generator;
+ * returning them is a security hazard.
*/
- return (a ^ b ^ c ^ d);
+ return (c ^ d);
}