journal-remote.c revision ce30c8dcb41dfe9264f79f30c7f51c0e74576638
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen This file is part of systemd.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2012 Zbigniew Jędrzejewski-Szmek
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is free software; you can redistribute it and/or modify it
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen under the terms of the GNU Lesser General Public License as published by
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen the Free Software Foundation; either version 2.1 of the License, or
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (at your option) any later version.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is distributed in the hope that it will be useful, but
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen WITHOUT ANY WARRANTY; without even the implied warranty of
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Lesser General Public License for more details.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen You should have received a copy of the GNU Lesser General Public License
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "journal-remote-write.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define REMOTE_JOURNAL_PATH "/var/log/journal/remote"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_getter = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_listen_raw = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_listen_http = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_listen_https = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char** arg_files = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int arg_compress = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int arg_seal = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int http_socket = -1, https_socket = -1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char** arg_gnutls_log = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic JournalWriteSplitMode arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_output = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char *arg_trust = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic bool arg_trust_all = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int spawn_child(const char* child, char** argv) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(errno, "Failed to create pager pipe: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to fork: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* In the child */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) reset_all_signal_handlers();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = dup2(fd[1], STDOUT_FILENO);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to dup pipe to stdout: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Make sure the child goes away when the parent dies */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Check whether our parent died before we were able
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * to set the death signal */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to exec child %s: %m", child);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning_errno(errno, "Failed to close write end of pipe: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int spawn_curl(const char* url) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char **argv = STRV_MAKE("curl",
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen "-HAccept: application/vnd.fdo.journal",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = spawn_child("curl", argv);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to spawn curl: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int spawn_getter(const char *getter, const char *url) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_strv_free_ char **words = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = strv_split_quoted(&words, getter, 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to split getter option: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = strv_extend(&words, url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to create command line: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = spawn_child(words[0], words);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to spawn getter %s: %m", getter);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define filename_escape(s) xescape((s), "/ ")
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int open_output(Writer *w, const char* host) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *_output = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_NONE:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal";
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_HOST: {
d171ed1c50ba64928b7fb30ee2ae729fdfe0826bThomas Hindoe Paaboel Andersen name = filename_escape(host);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = asprintf(&_output, "%s/remote-%s.journal",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen arg_output ?: REMOTE_JOURNAL_PATH,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = journal_file_open_reliably(output,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to open output journal %s: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Opened output file %s", w->journal->path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int init_writer_hashmap(RemoteServer *s) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen static const struct hash_ops *hash_ops[] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [JOURNAL_WRITE_SPLIT_NONE] = NULL,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(hash_ops));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->writers = hashmap_new(hash_ops[arg_split_mode]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int get_writer(RemoteServer *s, const char *host,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_writer_unref_ Writer *w = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_NONE:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_HOST:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_not_reached("what split mode?");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen w = hashmap_get(s->writers, key);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen w->hashmap_key = strdup(key);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_put(s->writers, w->hashmap_key ?: key, w);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/* This should go away as soon as µhttpd allows state to be passed around. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_raw_source_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_raw_source_until_block(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_blocking_source_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_raw_connection_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_http_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int get_source_for_fd(RemoteServer *s,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd, char *name, RemoteSource **source) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* This takes ownership of name, but only on success. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = get_writer(s, name, &writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_warning_errno(r, "Failed to get writer for source %s: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (s->sources[fd] == NULL) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->sources[fd] = source_new(fd, false, name, writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int remove_source(RemoteServer *s, int fd) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0 && fd < (ssize_t) s->sources_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* this closes fd too */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* This takes ownership of name, even on failure, if own_name is true. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = get_source_for_fd(s, fd, name, &source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to create source for fd:%d (%s): %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_io(s->events, &source->event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_raw_source_event, source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Add additional source for buffer processing. It will be
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * enabled later. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_defer(s->events, &source->buffer_event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_raw_source_until_block, source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (r == -EPERM) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_defer(s->events, &source->event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_blocking_source_event, source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_source_set_enabled(source->event, SD_EVENT_ON);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to register event source for fd:%d: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_source_set_description(source->event, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to set source name for fd:%d: %m", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int add_raw_socket(RemoteServer *s, int fd) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_close_ int fd_ = fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char name[sizeof("raw-socket-")-1 + DECIMAL_STR_MAX(int) + 1];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_io(s->events, &s->listen_event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_raw_connection_event, s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen xsprintf(name, "raw-socket-%d", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_source_set_description(s->listen_event, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_raw_socket(RemoteServer *s, const char *address) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return add_raw_socket(s, fd);
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int request_meta(void **connection_cls, int fd, char *hostname) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = get_writer(server, hostname, &writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_warning_errno(r, "Failed to get writer for source %s: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen source = source_new(fd, true, hostname, writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Added RemoteSource as connection metadata %p", source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void request_meta_free(void *cls,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct MHD_Connection *connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen enum MHD_RequestTerminationCode toe) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Cleaning up connection metadata %p", s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int process_http_upload(
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek struct MHD_Connection *connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_trace("%s: connection %p, %zu bytes",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen __func__, connection, *upload_data_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_trace("Received %zu bytes", *upload_data_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = push_data(source, upload_data, *upload_data_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond_oom(connection);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = process_source(source, arg_compress, arg_seal);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning("Failed to process data for connection %p", connection);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respondf(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Entry is too large, maximum is %u bytes.\n",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respondf(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_HTTP_UNPROCESSABLE_ENTITY,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Processing failed: %s.", strerror(-r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* The upload is finished */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen remaining = source_non_empty(source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning("Premature EOFbyte. %zu bytes lost.", remaining);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Premature EOF. %zu bytes of trailing data not processed.",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct MHD_Connection *connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *hostname = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_trace("Handling a connection %s %s %s", method, url, version);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return process_http_upload(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen upload_data, upload_data_size,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Unsupported method.\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_NOT_FOUND,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen header = MHD_lookup_connection_value(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_HEADER_KIND, "Content-Type");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!header || !streq(header, "application/vnd.fdo.journal"))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Content-Type: application/vnd.fdo.journal"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " is required.\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const union MHD_ConnectionInfo *ci;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen ci = MHD_get_connection_info(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_CONNECTION_INFO_CONNECTION_FD);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("MHD_get_connection_info failed: cannot get remote fd");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Cannot check remote address");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = check_permissions(connection, &code, &hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = getnameinfo_pretty(fd, &hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Cannot check remote hostname");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = request_meta(connection_cls, fd, hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return respond_oom(connection);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_microhttpd_server(RemoteServer *s,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct MHD_OptionItem opts[] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_LISTEN_SOCKET, fd},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const union MHD_DaemonInfo *info;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen opts[opts_pos++] = (struct MHD_OptionItem)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen opts[opts_pos++] = (struct MHD_OptionItem)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen opts[opts_pos++] = (struct MHD_OptionItem)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen d = new(MHDDaemonWrapper, 1);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen d->daemon = MHD_start_daemon(flags, 0,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to start µhttp daemon");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen key ? "HTTPS" : "HTTP", fd, d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("µhttp returned NULL daemon info");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("µhttp epoll fd is invalid");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_io(s->events, &d->event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to add event callback: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_source_set_description(d->event, "epoll-fd");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to set source name: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_put(s->daemons, &d->fd, d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to add daemon to hashmap: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_microhttpd_socket(RemoteServer *s,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM | SOCK_CLOEXEC);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return setup_microhttpd_server(s, fd, key, cert, trust);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_http_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHDDaemonWrapper *d = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("MHD_run failed!");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen // XXX: unregister daemon
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_signals(RemoteServer *s) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_se(sigemptyset(&mask) == 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sigset_add_many(&mask, SIGINT, SIGTERM, -1);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int negative_fd(const char *spec) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Return a non-positive number as its inverse, -EINVAL otherwise. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int remoteserver_init(RemoteServer *s,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if ((arg_listen_raw || arg_listen_http) && trust) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Option --trust makes all non-HTTPS connections untrusted.");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_default(&s->events);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to allocate event loop: %m");
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Received %d descriptors", n);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Received fewer sockets than expected");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Received a listening socket (fd:%d)", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_server(s, fd, key, cert, trust);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = getnameinfo_pretty(fd, &hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to retrieve remote name: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Received a connection socket (fd:%d) from %s", fd, hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = add_source(s, fd, hostname, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Unknown socket passed on fd:%d", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to register socket (fd:%d): %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen url = strjoina(arg_url, "/entries");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_info("Spawning getter %s...", url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = spawn_getter(arg_getter, url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_info("Spawning curl %s...", url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen startswith(arg_url, "https://") ?:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen startswith(arg_url, "http://") ?:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = add_source(s, fd, (char*) hostname, false);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Listening on a socket...");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_raw_socket(s, arg_listen_raw);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen STRV_FOREACH(file, arg_files) {
const char *output_name;
if (fd < 0)
if (s->active == 0) {
return -EINVAL;
size_t i;
MHDDaemonWrapper *d;
free(d);
for (i = 0; i < s->sources_size; i++)
remove_source(s, i);
int fd,
RemoteServer *s) {
if (remaining > 0)
} else if (r == -E2BIG) {
} else if (r == -EAGAIN) {
void *userdata) {
int fd,
void *userdata) {
void *userdata) {
int fd2, r;
if (fd2 < 0)
case AF_INET:
case AF_INET6: {
type,
*hostname = b;
return fd2;
return -EINVAL;
int fd,
void *userdata) {
int fd2;
if (fd2 < 0)
return fd2;
static int parse_config(void) {
false, NULL);
static void help(void) {
help();
case ARG_VERSION:
case ARG_URL:
if (arg_url) {
return -EINVAL;
case ARG_GETTER:
if (arg_getter) {
return -EINVAL;
case ARG_LISTEN_RAW:
if (arg_listen_raw) {
return -EINVAL;
case ARG_LISTEN_HTTP:
return -EINVAL;
http_socket = r;
case ARG_LISTEN_HTTPS:
return -EINVAL;
https_socket = r;
case ARG_KEY:
if (arg_key) {
return -EINVAL;
if (!arg_key)
return log_oom();
case ARG_CERT:
if (arg_cert) {
return -EINVAL;
if (!arg_cert)
return log_oom();
case ARG_TRUST:
return -EINVAL;
arg_trust_all = true;
#ifdef HAVE_GNUTLS
if (!arg_trust)
return log_oom();
return -EINVAL;
if (arg_output) {
return -EINVAL;
case ARG_SPLIT_MODE:
return -EINVAL;
case ARG_COMPRESS:
if (optarg) {
return -EINVAL;
arg_compress = !!r;
arg_compress = true;
case ARG_SEAL:
if (optarg) {
return -EINVAL;
arg_seal = !!r;
arg_seal = true;
case ARG_GNUTLS_LOG: {
#ifdef HAVE_GNUTLS
char *cat;
if (!cat)
return log_oom();
return log_oom();
return -EINVAL;
return -EINVAL;
|| sd_listen_fds(false) > 0;
return -EINVAL;
if (type_a) {
if (!arg_output) {
return -EINVAL;
return -EINVAL;
return -EINVAL;
if (arg_trust_all)
RemoteServer s = {};
log_show_color(true);
r = parse_config();
return EXIT_FAILURE;
return EXIT_FAILURE;
return EXIT_FAILURE;
return EXIT_FAILURE;
sd_notify(false,
while (s.active) {
if (r == SD_EVENT_FINISHED)
sd_notifyf(false,
server_destroy(&s);