aboutsummaryrefslogtreecommitdiffstats
path: root/modules/es_unix
diff options
context:
space:
mode:
authorlloyd <[email protected]>2006-05-18 18:33:19 +0000
committerlloyd <[email protected]>2006-05-18 18:33:19 +0000
commita2c99d3270eb73ef2db5704fc54356c6b75096f8 (patch)
treead3d6c4fcc8dd0f403f8105598943616246fe172 /modules/es_unix
Initial checkin1.5.6
Diffstat (limited to 'modules/es_unix')
-rw-r--r--modules/es_unix/es_unix.cpp105
-rw-r--r--modules/es_unix/es_unix.h35
-rw-r--r--modules/es_unix/modinfo.txt25
-rw-r--r--modules/es_unix/unix_cmd.cpp241
-rw-r--r--modules/es_unix/unix_cmd.h56
-rw-r--r--modules/es_unix/unix_src.cpp59
6 files changed, 521 insertions, 0 deletions
diff --git a/modules/es_unix/es_unix.cpp b/modules/es_unix/es_unix.cpp
new file mode 100644
index 000000000..d1efd4fa9
--- /dev/null
+++ b/modules/es_unix/es_unix.cpp
@@ -0,0 +1,105 @@
+/*************************************************
+* Unix EntropySource Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/es_unix.h>
+#include <botan/unix_cmd.h>
+#include <botan/parsing.h>
+#include <botan/conf.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Sort ordering by priority *
+*************************************************/
+bool Unix_Program_Cmp(const Unix_Program& a, const Unix_Program& b)
+ { return (a.priority < b.priority); }
+
+}
+
+/*************************************************
+* Unix_EntropySource Constructor *
+*************************************************/
+Unix_EntropySource::Unix_EntropySource()
+ {
+ add_default_sources(sources);
+ }
+
+/*************************************************
+* Add sources to the list *
+*************************************************/
+void Unix_EntropySource::add_sources(const Unix_Program srcs[], u32bit count)
+ {
+ sources.insert(sources.end(), srcs, srcs + count);
+ std::sort(sources.begin(), sources.end(), Unix_Program_Cmp);
+ }
+
+/*************************************************
+* Unix Fast Poll *
+*************************************************/
+void Unix_EntropySource::do_fast_poll()
+ {
+ gather(2*1024);
+ }
+
+/*************************************************
+* Unix Slow Poll *
+*************************************************/
+void Unix_EntropySource::do_slow_poll()
+ {
+ gather(16*1024);
+ }
+
+/*************************************************
+* Gather Entropy From Several Unix_Programs *
+*************************************************/
+void Unix_EntropySource::gather(u32bit target_amount)
+ {
+ const u32bit MINIMAL_WORKING = 32;
+
+ u32bit got = 0;
+ for(u32bit j = 0; j != sources.size(); j++)
+ {
+ add_timestamp();
+
+ got += gather_from(sources[j]);
+ sources[j].working = (got >= MINIMAL_WORKING) ? true : false;
+
+ if(got >= target_amount)
+ break;
+ }
+ }
+
+/*************************************************
+* Gather entropy from a Unix program *
+*************************************************/
+u32bit Unix_EntropySource::gather_from(const Unix_Program& prog)
+ {
+ const std::string BASE_PATH = "/bin:/sbin:/usr/bin:/usr/sbin";
+ const std::string EXTRA_PATH = Config::get_string("rng/unix_path");
+
+ std::string PATH = BASE_PATH;
+ if(EXTRA_PATH != "")
+ PATH += ':' + EXTRA_PATH;
+
+ DataSource_Command pipe(prog.name_and_args, PATH);
+ if(pipe.end_of_data())
+ return 0;
+
+ u32bit got = 0;
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+
+ while(!pipe.end_of_data())
+ {
+ u32bit this_loop = pipe.read(buffer, buffer.size());
+ add_bytes(buffer, this_loop);
+ got += this_loop;
+ }
+
+ return got;
+ }
+
+}
diff --git a/modules/es_unix/es_unix.h b/modules/es_unix/es_unix.h
new file mode 100644
index 000000000..74f960eb8
--- /dev/null
+++ b/modules/es_unix/es_unix.h
@@ -0,0 +1,35 @@
+/*************************************************
+* Unix EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_UNIX_H__
+#define BOTAN_EXT_ENTROPY_SRC_UNIX_H__
+
+#include <botan/buf_es.h>
+#include <botan/unix_cmd.h>
+#include <vector>
+
+namespace Botan {
+
+/*************************************************
+* Unix Entropy Source *
+*************************************************/
+class Unix_EntropySource : public Buffered_EntropySource
+ {
+ public:
+ void add_sources(const Unix_Program[], u32bit);
+ Unix_EntropySource();
+ private:
+ void do_fast_poll();
+ void do_slow_poll();
+ void gather(u32bit);
+ u32bit gather_from(const Unix_Program&);
+ static void add_default_sources(std::vector<Unix_Program>&);
+
+ std::vector<Unix_Program> sources;
+ };
+
+}
+
+#endif
diff --git a/modules/es_unix/modinfo.txt b/modules/es_unix/modinfo.txt
new file mode 100644
index 000000000..94d922c05
--- /dev/null
+++ b/modules/es_unix/modinfo.txt
@@ -0,0 +1,25 @@
+realname "Generic Unix Entropy Source"
+
+define ENTROPY_SRC_UNIX
+
+add_file es_unix.cpp
+add_file unix_src.cpp
+add_file unix_cmd.cpp
+
+add_file es_unix.h
+add_file unix_cmd.h
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+hpux
+irix
+linux
+netbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/modules/es_unix/unix_cmd.cpp b/modules/es_unix/unix_cmd.cpp
new file mode 100644
index 000000000..db79478df
--- /dev/null
+++ b/modules/es_unix/unix_cmd.cpp
@@ -0,0 +1,241 @@
+/*************************************************
+* Unix Command Execution Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 500
+#endif
+
+#ifndef _XOPEN_SOURCE_EXTENDED
+ #define _XOPEN_SOURCE_EXTENDED 1
+#endif
+
+#include <botan/unix_cmd.h>
+#include <botan/parsing.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Attempt to execute the command *
+************************************************/
+void do_exec(const std::vector<std::string>& arg_list,
+ const std::vector<std::string>& paths)
+ {
+ const u32bit args = arg_list.size() - 1;
+
+ const char* arg1 = (args >= 1) ? arg_list[1].c_str() : 0;
+ const char* arg2 = (args >= 2) ? arg_list[2].c_str() : 0;
+ const char* arg3 = (args >= 3) ? arg_list[3].c_str() : 0;
+ const char* arg4 = (args >= 4) ? arg_list[4].c_str() : 0;
+
+ for(u32bit j = 0; j != paths.size(); j++)
+ {
+ const std::string full_path = paths[j] + "/" + arg_list[0];
+ const char* fsname = full_path.c_str();
+ execl(fsname, fsname, arg1, arg2, arg3, arg4, 0);
+ }
+ }
+
+}
+
+/*************************************************
+* Local information about the pipe *
+*************************************************/
+struct pipe_wrapper
+ {
+ int fd;
+ pid_t pid;
+ pipe_wrapper() { fd = -1; pid = 0; }
+ };
+
+/*************************************************
+* Read from the pipe *
+*************************************************/
+u32bit DataSource_Command::read(byte buf[], u32bit length)
+ {
+ if(end_of_data())
+ return 0;
+
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(pipe->fd, &set);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = MAX_BLOCK_USECS;
+
+ ssize_t got = 0;
+ if(select(pipe->fd + 1, &set, 0, 0, &tv) == 1)
+ {
+ if(FD_ISSET(pipe->fd, &set))
+ got = ::read(pipe->fd, buf, length);
+ }
+
+ if(got <= 0)
+ {
+ shutdown_pipe();
+ return 0;
+ }
+
+ return (u32bit)got;
+ }
+
+/*************************************************
+* Peek at the pipe contents *
+*************************************************/
+u32bit DataSource_Command::peek(byte[], u32bit, u32bit) const
+ {
+ if(end_of_data())
+ throw Invalid_State("DataSource_Command: Cannot peek when out of data");
+ throw Stream_IO_Error("Cannot peek/seek on a command pipe");
+ }
+
+/*************************************************
+* Check if we reached EOF *
+*************************************************/
+bool DataSource_Command::end_of_data() const
+ {
+ return (pipe) ? false : true;
+ }
+
+/*************************************************
+* Return the Unix file descriptor of the pipe *
+*************************************************/
+int DataSource_Command::fd() const
+ {
+ if(!pipe)
+ return -1;
+ return pipe->fd;
+ }
+
+/*************************************************
+* Return a human-readable ID for this stream *
+*************************************************/
+std::string DataSource_Command::id() const
+ {
+ return "Unix command: " + arg_list[0];
+ }
+
+/*************************************************
+* Create the pipe *
+*************************************************/
+void DataSource_Command::create_pipe(const std::string& path)
+ {
+ const std::vector<std::string> paths = split_on(path, ':');
+
+ bool found_something = false;
+ for(u32bit j = 0; j != paths.size(); j++)
+ {
+ const std::string full_path = paths[j] + "/" + arg_list[0];
+ if(access(full_path.c_str(), X_OK) == 0)
+ {
+ found_something = true;
+ break;
+ }
+ }
+ if(!found_something)
+ return;
+
+ int pipe_fd[2];
+ if(::pipe(pipe_fd) != 0)
+ return;
+
+ pid_t pid = fork();
+
+ if(pid == -1)
+ {
+ close(pipe_fd[0]);
+ close(pipe_fd[1]);
+ }
+ else if(pid > 0)
+ {
+ pipe = new pipe_wrapper;
+ pipe->fd = pipe_fd[0];
+ pipe->pid = pid;
+ close(pipe_fd[1]);
+ }
+ else
+ {
+ if(dup2(pipe_fd[1], STDOUT_FILENO) == -1)
+ exit(127);
+ if(close(pipe_fd[0]) != 0 || close(pipe_fd[1]) != 0)
+ exit(127);
+ if(close(STDERR_FILENO) != 0)
+ exit(127);
+
+ do_exec(arg_list, paths);
+ exit(127);
+ }
+ }
+
+/*************************************************
+* Shutdown the pipe *
+*************************************************/
+void DataSource_Command::shutdown_pipe()
+ {
+ if(pipe)
+ {
+ pid_t reaped = waitpid(pipe->pid, 0, WNOHANG);
+
+ if(reaped == 0)
+ {
+ kill(pipe->pid, SIGTERM);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = KILL_WAIT;
+ select(0, 0, 0, 0, &tv);
+
+ reaped = waitpid(pipe->pid, 0, WNOHANG);
+
+ if(reaped == 0)
+ {
+ kill(pipe->pid, SIGKILL);
+ do
+ reaped = waitpid(pipe->pid, 0, 0);
+ while(reaped == -1);
+ }
+ }
+
+ close(pipe->fd);
+ delete pipe;
+ pipe = 0;
+ }
+ }
+
+/*************************************************
+* DataSource_Command Constructor *
+*************************************************/
+DataSource_Command::DataSource_Command(const std::string& prog_and_args,
+ const std::string& path) :
+ MAX_BLOCK_USECS(100000), KILL_WAIT(10000)
+ {
+ arg_list = split_on(prog_and_args, ' ');
+
+ if(arg_list.size() == 0)
+ throw Invalid_Argument("DataSource_Command: No command given");
+ if(arg_list.size() > 5)
+ throw Invalid_Argument("DataSource_Command: Too many args");
+
+ pipe = 0;
+ create_pipe(path);
+ }
+
+/*************************************************
+* DataSource_Command Destructor *
+*************************************************/
+DataSource_Command::~DataSource_Command()
+ {
+ if(!end_of_data())
+ shutdown_pipe();
+ }
+
+}
diff --git a/modules/es_unix/unix_cmd.h b/modules/es_unix/unix_cmd.h
new file mode 100644
index 000000000..8da81ccbd
--- /dev/null
+++ b/modules/es_unix/unix_cmd.h
@@ -0,0 +1,56 @@
+/*************************************************
+* Unix Command Execution Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_UNIX_CMD_H__
+#define BOTAN_EXT_UNIX_CMD_H__
+
+#include <botan/types.h>
+#include <botan/data_src.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/*************************************************
+* Unix Program Info *
+*************************************************/
+struct Unix_Program
+ {
+ Unix_Program(const char* n, u32bit p)
+ { name_and_args = n; priority = p; working = true; }
+
+ std::string name_and_args;
+ u32bit priority;
+ bool working;
+ };
+
+/*************************************************
+* Command Output DataSource *
+*************************************************/
+class DataSource_Command : public DataSource
+ {
+ public:
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit) const;
+ bool end_of_data() const;
+ std::string id() const;
+
+ int fd() const;
+
+ DataSource_Command(const std::string&, const std::string&);
+ ~DataSource_Command();
+ private:
+ void create_pipe(const std::string&);
+ void shutdown_pipe();
+
+ const u32bit MAX_BLOCK_USECS, KILL_WAIT;
+
+ std::vector<std::string> arg_list;
+ struct pipe_wrapper* pipe;
+ };
+
+}
+
+#endif
diff --git a/modules/es_unix/unix_src.cpp b/modules/es_unix/unix_src.cpp
new file mode 100644
index 000000000..5493d9fd8
--- /dev/null
+++ b/modules/es_unix/unix_src.cpp
@@ -0,0 +1,59 @@
+/*************************************************
+* Program List for Unix_EntropySource *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/es_unix.h>
+
+namespace Botan {
+
+/*************************************************
+* Default Commands for Entropy Gathering *
+*************************************************/
+void Unix_EntropySource::add_default_sources(std::vector<Unix_Program>& srcs)
+ {
+ srcs.push_back(Unix_Program("vmstat", 1));
+ srcs.push_back(Unix_Program("vmstat -s", 1));
+ srcs.push_back(Unix_Program("pfstat", 1));
+ srcs.push_back(Unix_Program("netstat -in", 1));
+
+ srcs.push_back(Unix_Program("iostat", 2));
+ srcs.push_back(Unix_Program("mpstat", 2));
+ srcs.push_back(Unix_Program("nfsstat", 2));
+ srcs.push_back(Unix_Program("portstat", 2));
+ srcs.push_back(Unix_Program("arp -a -n", 2));
+ srcs.push_back(Unix_Program("ifconfig -a", 2));
+ srcs.push_back(Unix_Program("pstat -T", 2));
+ srcs.push_back(Unix_Program("pstat -s", 2));
+ srcs.push_back(Unix_Program("uname -a", 2));
+ srcs.push_back(Unix_Program("uptime", 2));
+ srcs.push_back(Unix_Program("ipcs -a", 2));
+ srcs.push_back(Unix_Program("procinfo -a", 2));
+
+ srcs.push_back(Unix_Program("sysinfo", 3));
+ srcs.push_back(Unix_Program("listarea", 3));
+ srcs.push_back(Unix_Program("listdev", 3));
+
+ srcs.push_back(Unix_Program("who", 3));
+ srcs.push_back(Unix_Program("finger", 3));
+ srcs.push_back(Unix_Program("netstat -s", 3));
+ srcs.push_back(Unix_Program("netstat -an", 3));
+ srcs.push_back(Unix_Program("ps -A", 3));
+ srcs.push_back(Unix_Program("mailstats", 3));
+ srcs.push_back(Unix_Program("rpcinfo -p localhost", 3));
+
+ srcs.push_back(Unix_Program("dmesg", 4));
+ srcs.push_back(Unix_Program("ls -alni /tmp", 4));
+ srcs.push_back(Unix_Program("ls -alni /proc", 4));
+ srcs.push_back(Unix_Program("df -l", 4));
+ srcs.push_back(Unix_Program("last -5", 4));
+ srcs.push_back(Unix_Program("pstat -f", 4));
+
+ srcs.push_back(Unix_Program("ps aux", 5));
+ srcs.push_back(Unix_Program("ps -elf", 5));
+
+ srcs.push_back(Unix_Program("sar -A", 6));
+ srcs.push_back(Unix_Program("lsof", 6));
+ }
+
+}