diff options
author | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
commit | a2c99d3270eb73ef2db5704fc54356c6b75096f8 (patch) | |
tree | ad3d6c4fcc8dd0f403f8105598943616246fe172 /modules/es_unix |
Initial checkin1.5.6
Diffstat (limited to 'modules/es_unix')
-rw-r--r-- | modules/es_unix/es_unix.cpp | 105 | ||||
-rw-r--r-- | modules/es_unix/es_unix.h | 35 | ||||
-rw-r--r-- | modules/es_unix/modinfo.txt | 25 | ||||
-rw-r--r-- | modules/es_unix/unix_cmd.cpp | 241 | ||||
-rw-r--r-- | modules/es_unix/unix_cmd.h | 56 | ||||
-rw-r--r-- | modules/es_unix/unix_src.cpp | 59 |
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)); + } + +} |