diff --git a/lib/modules/ADT.pmod/queue.pike b/lib/modules/ADT.pmod/queue.pike new file mode 100644 index 0000000000000000000000000000000000000000..9e0ba58e974c5a33aa7f0b733497dc8270f756f4 --- /dev/null +++ b/lib/modules/ADT.pmod/queue.pike @@ -0,0 +1,50 @@ +/* queue.pike + * + * A FIFO queue. Used by connection* + */ + +#define QUEUE_SIZE 100 + +array l; +int head; +int tail; + +void create() +{ + l = allocate(QUEUE_SIZE); + head = tail = 0; +} + +void put(mixed item) +{ + if (head == sizeof(l)) + { + l = l[tail ..]; + head -= tail; + tail = 0; + l += allocate(sizeof(l) + QUEUE_SIZE); + } + l[head++] = item; +// werror(sprintf("Queue->put: %O\n", l[tail..head-1])); +} + +mixed get() +{ +// werror(sprintf("Queue->get: %O\n", l[tail..head-1])); + mixed res; + if (tail == head) + return 0; + res = l[tail]; + l[tail++] = 0; + return res; +} + +mixed peek() +{ + return (tail < head) && l[tail]; +} + +void flush() +{ + create(); +} diff --git a/lib/modules/ADT.pmod/struct.pike b/lib/modules/ADT.pmod/struct.pike new file mode 100644 index 0000000000000000000000000000000000000000..e6062ddbe2499befb2bde3b1e677d852e2c23c3f --- /dev/null +++ b/lib/modules/ADT.pmod/struct.pike @@ -0,0 +1,160 @@ +/* struct.pike + * + * Read and write structures from strings. + */ + +string buffer; +int index; + +void create(void|string s) +{ + buffer = s || ""; + index = 0; +} + +void add_data(string s) +{ + buffer += s; +} + +string pop_data() +{ + string res = buffer; + create(); + return res; +} + +void put_int(int i, int len) +{ + add_data(sprintf("%*c", len, i)); +} + +void put_var_string(string s, int len) +{ + put_int(strlen(s), len); + add_data(s); +} + +void put_fix_string(string s) +{ + add_data(s); +} + +void put_fix_array(array(int) data, int item_size) +{ + foreach(data, int i) + put_int(i, item_size); +} + +void put_var_array(array(int) data, int item_size, int len) +{ + put_int(sizeof(data), len); + put_fix_array(data, item_size); +} + +mixed get_int(int len) +{ + mixed i; + if ( (strlen(buffer) - index) < len) + throw( ({ "SSL.struct->get_int: no data\n", backtrace() }) ); + if (len <= 3) + { + sscanf(buffer, "%*" + (string) index +"s%" + (string) len + "c", i); + } + else + i = Gmp.mpz(buffer[index .. index+len-1], 256); + index += len; + return i; +} + +string get_fix_string(int len) +{ + string res; + + if ((strlen(buffer) - index) < len) + throw( ({ "SSL.struct->get_fix_string: no data\n", backtrace() }) ); + res = buffer[index .. index + len - 1]; + index += len; + return res; +} + +string get_var_string(int len) +{ + return get_fix_string(get_int(len)); +} + +array(mixed) get_fix_array(int item_size, int size) +{ + array(mixed) res = allocate(size); + for(int i = 0; i<size; i++) + res[i] = get_int(item_size); + return res; +} + +array(mixed) get_var_array(int item_size, int len) +{ + return get_fix_array(item_size, get_int(len)); +} + +int is_empty() +{ + return (index == strlen(buffer)); +} + +#if 0 + +constant FIELD_int = 1; +constant FIELD_string = 2; + +class field +{ + string name; /* Name of field */ + int type; + int len; /* For integers: length, + * for strings: index to the field that holds the length */ +} + + + +array(object(field)) description; +array(function) conversions; + +class parser +{ + string buffer = ""; + object info; + int field; /* Field being read */ + object o; /* The object to fill in */ + object me; + + mapping(int:function(string, object:void)) conversions; + + create(object i) + { + info = i; + o = i->prog(); + me = this_object(); + } + + object|string recv(string data) + { + buffer += data; + while(strlen(buffer) >= info->needed_chars[field]) + { + object err; + if (err = info->conversions[field](me)) + return err; + field++; + if (field >= sizeof(info->description)) + return buffer[info->needed_chars[field-1]..]; + } + return 0; + } +} + +array compile() +{ + conversions = + + +#endif diff --git a/lib/modules/Crypto/randomness.pmod.pike b/lib/modules/Crypto/randomness.pmod.pike new file mode 100644 index 0000000000000000000000000000000000000000..7a9d4d8d10241686d2a03b0d1cc8e31d9b6ccba3 --- /dev/null +++ b/lib/modules/Crypto/randomness.pmod.pike @@ -0,0 +1,122 @@ +/* randomness.pmod + * + * Assorted stronger or weaker randomnumber generators. + */ + +/* These devices tries to collect entropy from the environment. + * They differ in behaviour when they run low on entropy, /dev/random + * will block if it can't provide enough random bits, while /dev/urandom + * will degenerate into a reasonably strong pseudo random generator */ + +#define RANDOM_DEVICE "/dev/random" +#define PRANDOM_DEVICE "/dev/urandom" + +/* Collect somewhat random data from the environment. Unfortunately, + * this is quite system dependent */ +#define PATH "/usr/sbin:/usr/etc:/usr/bin/:/sbin/:/etc:/bin" +#define SYSTEM_COMMANDS "rup & ping -s 255.255.255.255 256 30 &" \ + "uptime & ps -fel & vmstat -s & iostat -cdDItx &" + +#define PRIVATE + +PRIVATE object global_rc4; + +PRIVATE string some_entropy() +{ + object parent_pipe, child_pipe; + + parent_pipe = Stdio.File(); + child_pipe = parent_pipe->pipe(); + if (!child_pipe) + throw( ({ "Crypto.random->popen: couldn't create pipe\n", backtrace() }) ); + + if (!fork()) + { /* Child */ + catch { + object stderr = Stdio.File(); + object stdin = Stdio.File(); + + destruct(parent_pipe); + + stderr->open("/dev/null", "w"); + stderr->dup2(Stdio.File("stderr")); + + stdin->open("/dev/null", "r"); + stdin->dup2(Stdio.File("stdin")); + + child_pipe->dup2(Stdio.File("stdout")); + catch(exece("/bin/sh", ({ "-c", SYSTEM_COMMANDS }), ([ "PATH" : PATH ]) )); + }; + exit(17); + } else { + /* Parent */ + string res; + destruct(child_pipe); + res = parent_pipe->read(0x7fffffff); + return res; + } +} + +class pike_random { + string read(int len) + { + return sprintf("%@c", Array.map(allocate(len), lambda(int dummy) + { + return random(256); + } )); + } +} + +class rc4_random { + inherit Crypto.rc4 : rc4; + + void create(string secret) + { + object hash = Crypto.sha(); + hash->update(secret); + + rc4::set_encrypt_key(hash->digest()); + } + + string read(int len) + { + return rc4::crypt(replace(allocate(len), 0, "\47") * ""); + } +} + +object reasonably_random() +{ + if (file_stat(PRANDOM_DEVICE)) + { + object res = Stdio.File(); + if (res->open(PRANDOM_DEVICE, "r")) + return res; + } + + if (global_rc4) + return global_rc4; + + string seed = some_entropy(); + if (strlen(seed) > 2000) + return (global_rc4 = rc4_random(sprintf("%4c%O%s", time(), _memory_usage(), seed))); + + throw( ({ "Crypto.randomness.reasonably_random: No source found\n", backtrace() }) ); +} + +object really_random(int|void may_block) +{ + object res; + if (may_block && file_stat(RANDOM_DEVICE)) + { + if (res->open(RANDOM_DEVICE, "r")) + return res; + } + + if (file_stat(PRANDOM_DEVICE)) + { + if (res->open(PRANDOM_DEVICE, "r")) + return res; + } + + throw( ({ "Crypto.randomness.really_random: No source found\n", backtrace() }) ); +}