diff options
| author | Joel Klinghed <the_jk@yahoo.com> | 2017-07-24 23:43:07 +0200 |
|---|---|---|
| committer | Joel Klinghed <the_jk@yahoo.com> | 2017-07-24 23:43:07 +0200 |
| commit | 2dbfb58efe5e53b56bfda3ed21a3e41562205437 (patch) | |
| tree | 1f37423bc091a66930316add25258d3a934ffc0a /src/monitor-gui.cc | |
| parent | 5540079928fd36e656becdbaff7e44138a647ede (diff) | |
Add tools -> Generate CA
Added file field to GuiForm
Diffstat (limited to 'src/monitor-gui.cc')
| -rw-r--r-- | src/monitor-gui.cc | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/src/monitor-gui.cc b/src/monitor-gui.cc index 806f8da..8044a02 100644 --- a/src/monitor-gui.cc +++ b/src/monitor-gui.cc @@ -3,10 +3,13 @@ #include "common.hh" #include <fcntl.h> +#include <fstream> #include <memory> #include <string.h> -#include <sys/types.h> #include <sys/socket.h> +#include <sys/types.h> +#include <thread> +#include <unistd.h> #include <unordered_map> #include <vector> @@ -27,6 +30,7 @@ #include "observers.hh" #include "proxy.hh" #include "resolver.hh" +#include "ssl.hh" namespace { @@ -39,6 +43,7 @@ std::string const ACTION_COPY_RAW = "copy_raw"; std::string const ACTION_COPY_TEXT = "copy_text"; std::string const ACTION_CLEAR = "clear"; std::string const ACTION_PROXY_LOG = "proxy_log"; +std::string const ACTION_GENERATE_CA = "genca"; bool valid_hostname(std::string const& host) { return !host.empty(); @@ -436,6 +441,95 @@ private: Resolver* resolver_; }; + class GenerateFormListener : public GuiFormApply::Listener { + public: + bool about_to_close(GuiForm* form) override { + auto const& output = form->get_file("output"); + if (output.empty()) { + form->set_error("No output file selected."); + return false; + } + return true; + } + }; + + class GenerateFormDelegate : public GuiFormApply::Delegate { + public: + GenerateFormDelegate(Looper* looper, Config* config) + : looper_(looper), config_(config) { + } + + ~GenerateFormDelegate() { + if (read_) looper_->remove(read_.get()); + } + + void apply(GuiFormApply* form) override { + auto const& issuer = form->get_string("issuer"); + auto const& output = form->get_file("output"); + if (output.empty()) { + form->set_error("No ouput file selected."); + form->applied(false); + return; + } + config_->set("issuer", issuer); + config_->set("genca-output", output); + int fd[2]; + if (pipe(fd)) { + form->set_error("Unable to create pipe."); + form->applied(false); + return; + } + read_.reset(fd[0]); + logger_.reset(new StringLogger()); + looper_->add(read_.get(), Looper::EVENT_READ, [=](int, uint8_t) -> void { + char c; + if (read(read_.get(), &c, 1) != 1) { + c = 0; + } + looper_->remove(read_.get()); + read_.reset(); + if (c) { + form->applied(true); + } else { + form->set_error(logger_->text()->text()); + form->applied(false); + } + }); + // Hack to get SSL lib to initialize on the right thread + SSLCert::load(Logger::null(), ""); + + std::thread(generate, issuer, output, logger_.get(), fd[1]).detach(); + } + + private: + static void generate(std::string const& issuer, std::string const& output, + Logger* logger, int fd) { + char c = doGenerate(issuer, output, logger) ? 1 : 0; + write(fd, &c, 1); + close(fd); + } + + static bool doGenerate(std::string const& issuer, std::string const& output, + Logger* logger) { + std::unique_ptr<SSLEntropy> entropy(SSLEntropy::create(logger)); + if (!entropy) return false; + std::string key; + if (!SSLKey::generate(logger, entropy.get(), &key)) return false; + std::string cert; + std::unique_ptr<SSLKey> pkey(SSLKey::load(logger, key)); + if (!SSLCert::generate(logger, entropy.get(), nullptr, nullptr, issuer, + pkey.get(), &cert)) return false; + std::ofstream of(output); + of << cert << '\n' << key << std::endl; + return of.good(); + } + + io::auto_fd read_; + Looper* looper_; + Config* config_; + std::unique_ptr<StringLogger> logger_; + }; + public: MonitorGui() : packages_(new PackageList()), @@ -456,6 +550,8 @@ public: edit->add_item(ACTION_COPY_RAW, "Copy binary"); edit->add_separator(); edit->add_item(ACTION_CLEAR, "Clear"); + auto tools = menu_->add_menu("Tools"); + tools->add_item(ACTION_GENERATE_CA, "Generate CA..."); auto help = menu_->add_menu("Help"); help->add_item(ACTION_ABOUT, "About..."); help->add_item(ACTION_PROXY_LOG, "Proxy log..."); @@ -582,6 +678,29 @@ public: } else { proxy_logwnd_->focus(); } + } else if (id == ACTION_GENERATE_CA) { + auto del = std::unique_ptr<GuiFormApply::Delegate>( + new GenerateFormDelegate(looper_.get(), main_->config())); + auto lst = std::unique_ptr<GuiFormApply::Listener>( + new GenerateFormListener()); + auto dlg = std::unique_ptr<GuiFormApply>( + GuiFormApply::create("Generate CA...", + "Generate a certificate and key pair " + "and save to file.", + "Generate", + del.get())); + dlg->add_string("issuer", "Issuer name", + main_->config()->get("issuer", ""), + "Issuer name to user instead of default."); + std::vector<GuiFormApply::Filter> filter; + filter.emplace_back(); + filter.back().name = "PEM"; + filter.back().masks.emplace_back("*.pem"); + dlg->add_file("output", "File", "", + "File to save certificate and key pair to.", + false, filter); + dlg->add_listener(lst.get()); + dlg->show(main_.get()); } else { assert(false); } |
