chiark / gitweb /
journal-gatewayd: SSL support
[elogind.git] / src / journal / journal-gatewayd.c
index 9c33218822fc11cb0094d37d2b7a1692d3727062..6922ebcf9c1c154f83cee9b24ca448e79e8a1bbb 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <getopt.h>
 
 #include <microhttpd.h>
 
@@ -32,6 +33,7 @@
 #include "sd-daemon.h"
 #include "logs-show.h"
 #include "virt.h"
+#include "build.h"
 
 typedef struct RequestMeta {
         sd_journal *journal;
@@ -859,19 +861,96 @@ static int request_handler(
         return respond_error(connection, MHD_HTTP_NOT_FOUND, "Not found.\n");
 }
 
-int main(int argc, char *argv[]) {
-        struct MHD_Daemon *d = NULL;
-        int r = EXIT_FAILURE, n;
+static char *key_pem = NULL;
+static char *cert_pem = NULL;
+
+static int parse_argv(int argc, char *argv[]) {
+        enum {
+                ARG_VERSION = 0x100,
+                ARG_KEY,
+                ARG_CERT,
+        };
+
+        int r, c;
+
+        static const struct option options[] = {
+                { "version", no_argument,       NULL, ARG_VERSION },
+                { "key",     required_argument, NULL, ARG_KEY     },
+                { "cert",    required_argument, NULL, ARG_CERT    },
+                { NULL,      0,                 NULL, 0           }
+        };
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
+                switch(c) {
+                case ARG_VERSION:
+                        puts(PACKAGE_STRING);
+                        puts(SYSTEMD_FEATURES);
+                        return 0;
+
+                case ARG_KEY:
+                        if (key_pem) {
+                                log_error("Key file specified twice");
+                                return -EINVAL;
+                        }
+                        r = read_full_file(optarg, &key_pem, NULL);
+                        if (r < 0) {
+                                log_error("Failed to read key file: %s", strerror(-r));
+                                return r;
+                        }
+                        assert(key_pem);
+                        break;
 
-        if (argc > 1) {
+                case ARG_CERT:
+                        if (cert_pem) {
+                                log_error("Certificate file specified twice");
+                                return -EINVAL;
+                        }
+                        r = read_full_file(optarg, &cert_pem, NULL);
+                        if (r < 0) {
+                                log_error("Failed to read certificate file: %s", strerror(-r));
+                                return r;
+                        }
+                        assert(cert_pem);
+                        break;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        log_error("Unknown option code %c", c);
+                        return -EINVAL;
+                }
+
+        if (optind < argc) {
                 log_error("This program does not take arguments.");
-                goto finish;
+                return -EINVAL;
+        }
+
+        if (!!key_pem != !!cert_pem) {
+                log_error("Certificate and key files must be specified together");
+                return -EINVAL;
         }
 
+        return 1;
+}
+
+int main(int argc, char *argv[]) {
+        struct MHD_Daemon *d = NULL;
+        int r, n;
+
         log_set_target(LOG_TARGET_AUTO);
         log_parse_environment();
         log_open();
 
+        r = parse_argv(argc, argv);
+        if (r < 0)
+                return EXIT_FAILURE;
+        if (r == 0)
+                return EXIT_SUCCESS;
+
         n = sd_listen_fds(1);
         if (n < 0) {
                 log_error("Failed to determine passed sockets: %s", strerror(-n));
@@ -884,18 +963,29 @@ int main(int argc, char *argv[]) {
                         { MHD_OPTION_NOTIFY_COMPLETED,
                           (intptr_t) request_meta_free, NULL },
                         { MHD_OPTION_END, 0, NULL },
+                        { MHD_OPTION_END, 0, NULL },
+                        { MHD_OPTION_END, 0, NULL },
                         { MHD_OPTION_END, 0, NULL }};
+                int opts_pos = 1;
+                int flags = MHD_USE_THREAD_PER_CONNECTION|MHD_USE_POLL|MHD_USE_DEBUG;
+
                 if (n > 0)
-                        opts[1] = (struct MHD_OptionItem)
-                                {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START, NULL};
-
-                d = MHD_start_daemon(
-                                MHD_USE_THREAD_PER_CONNECTION|MHD_USE_POLL|MHD_USE_DEBUG,
-                                19531,
-                                NULL, NULL,
-                                request_handler, NULL,
-                                MHD_OPTION_ARRAY, opts,
-                                MHD_OPTION_END);
+                        opts[opts_pos++] = (struct MHD_OptionItem)
+                                {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START};
+                if (key_pem) {
+                        assert(cert_pem);
+                        opts[opts_pos++] = (struct MHD_OptionItem)
+                                {MHD_OPTION_HTTPS_MEM_KEY, 0, key_pem};
+                        opts[opts_pos++] = (struct MHD_OptionItem)
+                                {MHD_OPTION_HTTPS_MEM_CERT, 0, cert_pem};
+                        flags |= MHD_USE_SSL;
+                }
+
+                d = MHD_start_daemon(flags, 19531,
+                                     NULL, NULL,
+                                     request_handler, NULL,
+                                     MHD_OPTION_ARRAY, opts,
+                                     MHD_OPTION_END);
         }
 
         if (!d) {