aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/entropy/proc_walk
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-01-10 03:41:59 +0000
committerlloyd <[email protected]>2014-01-10 03:41:59 +0000
commit6894dca64c04936d07048c0e8cbf7e25858548c3 (patch)
tree5d572bfde9fe667dab14e3f04b5285a85d8acd95 /src/lib/entropy/proc_walk
parent9efa3be92442afb3d0b69890a36c7f122df18eda (diff)
Move lib into src
Diffstat (limited to 'src/lib/entropy/proc_walk')
-rw-r--r--src/lib/entropy/proc_walk/info.txt30
-rw-r--r--src/lib/entropy/proc_walk/proc_walk.cpp173
-rw-r--r--src/lib/entropy/proc_walk/proc_walk.h37
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