summaryrefslogtreecommitdiff
path: root/src/monitor-gui.cc
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@yahoo.com>2017-07-24 23:43:07 +0200
committerJoel Klinghed <the_jk@yahoo.com>2017-07-24 23:43:07 +0200
commit2dbfb58efe5e53b56bfda3ed21a3e41562205437 (patch)
tree1f37423bc091a66930316add25258d3a934ffc0a /src/monitor-gui.cc
parent5540079928fd36e656becdbaff7e44138a647ede (diff)
Add tools -> Generate CA
Added file field to GuiForm
Diffstat (limited to 'src/monitor-gui.cc')
-rw-r--r--src/monitor-gui.cc121
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);
}