diff options
author | lloyd <[email protected]> | 2014-01-10 03:41:59 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2014-01-10 03:41:59 +0000 |
commit | 6894dca64c04936d07048c0e8cbf7e25858548c3 (patch) | |
tree | 5d572bfde9fe667dab14e3f04b5285a85d8acd95 /src/lib/entropy/proc_walk | |
parent | 9efa3be92442afb3d0b69890a36c7f122df18eda (diff) |
Move lib into src
Diffstat (limited to 'src/lib/entropy/proc_walk')
-rw-r--r-- | src/lib/entropy/proc_walk/info.txt | 30 | ||||
-rw-r--r-- | src/lib/entropy/proc_walk/proc_walk.cpp | 173 | ||||
-rw-r--r-- | src/lib/entropy/proc_walk/proc_walk.h | 37 |
3 files changed, 240 insertions, 0 deletions
diff --git a/src/lib/entropy/proc_walk/info.txt b/src/lib/entropy/proc_walk/info.txt new file mode 100644 index 000000000..2a53a7ed8 --- /dev/null +++ b/src/lib/entropy/proc_walk/info.txt @@ -0,0 +1,30 @@ +define ENTROPY_SRC_PROC_WALKER 20131128 + +<source> +proc_walk.cpp +</source> + +<header:internal> +proc_walk.h +</header:internal> + +<os> +aix +cygwin +darwin +dragonfly +freebsd +hpux +hurd +irix +linux +netbsd +openbsd +qnx +solaris +tru64 +</os> + +<requires> +alloc +</requires> diff --git a/src/lib/entropy/proc_walk/proc_walk.cpp b/src/lib/entropy/proc_walk/proc_walk.cpp new file mode 100644 index 000000000..050d9dcf7 --- /dev/null +++ b/src/lib/entropy/proc_walk/proc_walk.cpp @@ -0,0 +1,173 @@ +/* +* Entropy source based on reading files in /proc on the assumption +* that a remote attacker will have difficulty guessing some of them. +* +* (C) 1999-2008,2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/proc_walk.h> +#include <botan/secmem.h> +#include <cstring> +#include <deque> + +#ifndef _POSIX_C_SOURCE + #define _POSIX_C_SOURCE 199309 +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> +#include <fcntl.h> + +namespace Botan { + +/** +* Returns file descriptors. Until it doesn't +*/ +class File_Descriptor_Source + { + public: + /** + * @return next file descriptor, or -1 if done + */ + virtual int next_fd() = 0; + + virtual ~File_Descriptor_Source() {} + }; + +namespace { + +class Directory_Walker : public File_Descriptor_Source + { + public: + Directory_Walker(const std::string& root) : + m_cur_dir(std::make_pair<DIR*, std::string>(nullptr, "")) + { + if(DIR* root_dir = ::opendir(root.c_str())) + m_cur_dir = std::make_pair(root_dir, root); + } + + ~Directory_Walker() + { + if(m_cur_dir.first) + ::closedir(m_cur_dir.first); + } + + int next_fd(); + private: + void add_directory(const std::string& dirname) + { + m_dirlist.push_back(dirname); + } + + std::pair<struct dirent*, std::string> get_next_dirent(); + + std::pair<DIR*, std::string> m_cur_dir; + std::deque<std::string> m_dirlist; + }; + +std::pair<struct dirent*, std::string> Directory_Walker::get_next_dirent() + { + while(m_cur_dir.first) + { + if(struct dirent* dir = ::readdir(m_cur_dir.first)) + return std::make_pair(dir, m_cur_dir.second); + + ::closedir(m_cur_dir.first); + m_cur_dir = std::make_pair<DIR*, std::string>(nullptr, ""); + + while(!m_dirlist.empty() && !m_cur_dir.first) + { + const std::string next_dir_name = m_dirlist[0]; + m_dirlist.pop_front(); + + if(DIR* next_dir = ::opendir(next_dir_name.c_str())) + m_cur_dir = std::make_pair(next_dir, next_dir_name); + } + } + + return std::make_pair<struct dirent*, std::string>(nullptr, ""); // nothing left + } + +int Directory_Walker::next_fd() + { + while(true) + { + std::pair<struct dirent*, std::string> entry = get_next_dirent(); + + if(!entry.first) + break; // no more dirs + + const std::string filename = entry.first->d_name; + + if(filename == "." || filename == "..") + continue; + + const std::string full_path = entry.second + '/' + filename; + + struct stat stat_buf; + if(::lstat(full_path.c_str(), &stat_buf) == -1) + continue; + + if(S_ISDIR(stat_buf.st_mode)) + { + add_directory(full_path); + } + else if(S_ISREG(stat_buf.st_mode) && (stat_buf.st_mode & S_IROTH)) + { + int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY); + + if(fd > 0) + return fd; + } + } + + return -1; + } + +} + +/** +* ProcWalking_EntropySource Destructor +*/ +ProcWalking_EntropySource::~ProcWalking_EntropySource() + { + // for ~unique_ptr + } + +void ProcWalking_EntropySource::poll(Entropy_Accumulator& accum) + { + const size_t MAX_FILES_READ_PER_POLL = 2048; + + if(!m_dir) + m_dir = new Directory_Walker(m_path); + + secure_vector<byte>& io_buffer = accum.get_io_buffer(4096); + + for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i) + { + int fd = m_dir->next_fd(); + + // If we've exhaused this walk of the directory, halt the poll + if(fd == -1) + { + delete m_dir; + m_dir = nullptr; + break; + } + + ssize_t got = ::read(fd, &io_buffer[0], io_buffer.size()); + ::close(fd); + + if(got > 0) + accum.add(&io_buffer[0], got, .001); + + if(accum.polling_goal_achieved()) + break; + } + } + +} diff --git a/src/lib/entropy/proc_walk/proc_walk.h b/src/lib/entropy/proc_walk/proc_walk.h new file mode 100644 index 000000000..04c3b1bba --- /dev/null +++ b/src/lib/entropy/proc_walk/proc_walk.h @@ -0,0 +1,37 @@ +/* +* File Tree Walking EntropySource +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ENTROPY_SRC_PROC_WALK_H__ +#define BOTAN_ENTROPY_SRC_PROC_WALK_H__ + +#include <botan/entropy_src.h> +#include <memory> + +namespace Botan { + +/** +* File Tree Walking Entropy Source +*/ +class ProcWalking_EntropySource : public EntropySource + { + public: + std::string name() const { return "Proc Walker"; } + + void poll(Entropy_Accumulator& accum); + + ProcWalking_EntropySource(const std::string& root_dir) : + m_path(root_dir), m_dir(nullptr) {} + + ~ProcWalking_EntropySource(); + private: + const std::string m_path; + class File_Descriptor_Source* m_dir; + }; + +} + +#endif |