tizen 2.4 release
[external/systemd.git] / src / journal-remote / journal-remote.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2012 Zbigniew JÄ™drzejewski-Szmek
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/prctl.h>
28 #include <sys/socket.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <getopt.h>
33
34 #include "sd-daemon.h"
35 #include "journal-file.h"
36 #include "journald-native.h"
37 #include "socket-util.h"
38 #include "mkdir.h"
39 #include "build.h"
40 #include "macro.h"
41 #include "strv.h"
42 #include "fileio.h"
43 #include "conf-parser.h"
44 #include "siphash24.h"
45
46 #ifdef HAVE_GNUTLS
47 #include <gnutls/gnutls.h>
48 #endif
49
50 #include "journal-remote.h"
51 #include "journal-remote-write.h"
52
53 #define REMOTE_JOURNAL_PATH "/var/log/journal/remote"
54
55 #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem"
56 #define CERT_FILE     CERTIFICATE_ROOT "/certs/journal-remote.pem"
57 #define TRUST_FILE    CERTIFICATE_ROOT "/ca/trusted.pem"
58
59 static char* arg_url = NULL;
60 static char* arg_getter = NULL;
61 static char* arg_listen_raw = NULL;
62 static char* arg_listen_http = NULL;
63 static char* arg_listen_https = NULL;
64 static char** arg_files = NULL;
65 static int arg_compress = true;
66 static int arg_seal = false;
67 static int http_socket = -1, https_socket = -1;
68 static char** arg_gnutls_log = NULL;
69
70 static JournalWriteSplitMode arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;
71 static char* arg_output = NULL;
72
73 static char *arg_key = NULL;
74 static char *arg_cert = NULL;
75 static char *arg_trust = NULL;
76 static bool arg_trust_all = false;
77
78 /**********************************************************************
79  **********************************************************************
80  **********************************************************************/
81
82 static int spawn_child(const char* child, char** argv) {
83         int fd[2];
84         pid_t parent_pid, child_pid;
85         int r;
86
87         if (pipe(fd) < 0) {
88                 log_error("Failed to create pager pipe: %m");
89                 return -errno;
90         }
91
92         parent_pid = getpid();
93
94         child_pid = fork();
95         if (child_pid < 0) {
96                 r = -errno;
97                 log_error("Failed to fork: %m");
98                 safe_close_pair(fd);
99                 return r;
100         }
101
102         /* In the child */
103         if (child_pid == 0) {
104                 r = dup2(fd[1], STDOUT_FILENO);
105                 if (r < 0) {
106                         log_error("Failed to dup pipe to stdout: %m");
107                         _exit(EXIT_FAILURE);
108                 }
109
110                 safe_close_pair(fd);
111
112                 /* Make sure the child goes away when the parent dies */
113                 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
114                         _exit(EXIT_FAILURE);
115
116                 /* Check whether our parent died before we were able
117                  * to set the death signal */
118                 if (getppid() != parent_pid)
119                         _exit(EXIT_SUCCESS);
120
121                 execvp(child, argv);
122                 log_error("Failed to exec child %s: %m", child);
123                 _exit(EXIT_FAILURE);
124         }
125
126         r = close(fd[1]);
127         if (r < 0)
128                 log_warning("Failed to close write end of pipe: %m");
129
130         return fd[0];
131 }
132
133 static int spawn_curl(const char* url) {
134         char **argv = STRV_MAKE("curl",
135                                 "-HAccept: application/vnd.fdo.journal",
136                                 "--silent",
137                                 "--show-error",
138                                 url);
139         int r;
140
141         r = spawn_child("curl", argv);
142         if (r < 0)
143                 log_error("Failed to spawn curl: %m");
144         return r;
145 }
146
147 static int spawn_getter(const char *getter, const char *url) {
148         int r;
149         _cleanup_strv_free_ char **words = NULL;
150
151         assert(getter);
152         r = strv_split_quoted(&words, getter);
153         if (r < 0) {
154                 log_error("Failed to split getter option: %s", strerror(-r));
155                 return r;
156         }
157
158         r = strv_extend(&words, url);
159         if (r < 0) {
160                 log_error("Failed to create command line: %s", strerror(-r));
161                 return r;
162         }
163
164         r = spawn_child(words[0], words);
165         if (r < 0)
166                 log_error("Failed to spawn getter %s: %m", getter);
167
168         return r;
169 }
170
171 #define filename_escape(s) xescape((s), "/ ")
172
173 static int open_output(Writer *w, const char* host) {
174         _cleanup_free_ char *_output = NULL;
175         const char *output;
176         int r;
177
178         switch (arg_split_mode) {
179         case JOURNAL_WRITE_SPLIT_NONE:
180                 output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal";
181                 break;
182
183         case JOURNAL_WRITE_SPLIT_HOST: {
184                 _cleanup_free_ char *name;
185
186                 assert(host);
187
188                 name = filename_escape(host);
189                 if (!name)
190                         return log_oom();
191
192                 r = asprintf(&_output, "%s/remote-%s.journal",
193                              arg_output ?: REMOTE_JOURNAL_PATH,
194                              name);
195                 if (r < 0)
196                         return log_oom();
197
198                 output = _output;
199                 break;
200         }
201
202         default:
203                 assert_not_reached("what?");
204         }
205
206         r = journal_file_open_reliably(output,
207                                        O_RDWR|O_CREAT, 0640,
208                                        arg_compress, arg_seal,
209                                        &w->metrics,
210                                        w->mmap,
211                                        NULL, &w->journal);
212         if (r < 0)
213                 log_error("Failed to open output journal %s: %s",
214                           output, strerror(-r));
215         else
216                 log_info("Opened output file %s", w->journal->path);
217         return r;
218 }
219
220 /**********************************************************************
221  **********************************************************************
222  **********************************************************************/
223
224 static int init_writer_hashmap(RemoteServer *s) {
225         static const struct {
226                 hash_func_t hash_func;
227                 compare_func_t compare_func;
228         } functions[] = {
229                 [JOURNAL_WRITE_SPLIT_NONE] = {trivial_hash_func,
230                                               trivial_compare_func},
231                 [JOURNAL_WRITE_SPLIT_HOST] = {string_hash_func,
232                                               string_compare_func},
233         };
234
235         assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(functions));
236
237         s->writers = hashmap_new(functions[arg_split_mode].hash_func,
238                                  functions[arg_split_mode].compare_func);
239         if (!s->writers)
240                 return log_oom();
241
242         return 0;
243 }
244
245 static int get_writer(RemoteServer *s, const char *host,
246                       Writer **writer) {
247         const void *key;
248         _cleanup_writer_unref_ Writer *w = NULL;
249         int r;
250
251         switch(arg_split_mode) {
252         case JOURNAL_WRITE_SPLIT_NONE:
253                 key = "one and only";
254                 break;
255
256         case JOURNAL_WRITE_SPLIT_HOST:
257                 assert(host);
258                 key = host;
259                 break;
260
261         default:
262                 assert_not_reached("what split mode?");
263         }
264
265         w = hashmap_get(s->writers, key);
266         if (w)
267                 writer_ref(w);
268         else {
269                 w = writer_new(s);
270                 if (!w)
271                         return log_oom();
272
273                 if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST) {
274                         w->hashmap_key = strdup(key);
275                         if (!w->hashmap_key)
276                                 return log_oom();
277                 }
278
279                 r = open_output(w, host);
280                 if (r < 0)
281                         return r;
282
283                 r = hashmap_put(s->writers, w->hashmap_key ?: key, w);
284                 if (r < 0)
285                         return r;
286         }
287
288         *writer = w;
289         w = NULL;
290         return 0;
291 }
292
293 /**********************************************************************
294  **********************************************************************
295  **********************************************************************/
296
297 /* This should go away as soon as Âµhttpd allows state to be passed around. */
298 static RemoteServer *server;
299
300 static int dispatch_raw_source_event(sd_event_source *event,
301                                      int fd,
302                                      uint32_t revents,
303                                      void *userdata);
304 static int dispatch_raw_connection_event(sd_event_source *event,
305                                          int fd,
306                                          uint32_t revents,
307                                          void *userdata);
308 static int dispatch_http_event(sd_event_source *event,
309                                int fd,
310                                uint32_t revents,
311                                void *userdata);
312
313 static int get_source_for_fd(RemoteServer *s,
314                              int fd, char *name, RemoteSource **source) {
315         Writer *writer;
316         int r;
317
318         assert(fd >= 0);
319         assert(source);
320
321         if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
322                 return log_oom();
323
324         r = get_writer(s, name, &writer);
325         if (r < 0) {
326                 log_warning("Failed to get writer for source %s: %s",
327                             name, strerror(-r));
328                 return r;
329         }
330
331         if (s->sources[fd] == NULL) {
332                 s->sources[fd] = source_new(fd, false, name, writer);
333                 if (!s->sources[fd]) {
334                         writer_unref(writer);
335                         return log_oom();
336                 }
337
338                 s->active++;
339         }
340
341         *source = s->sources[fd];
342         return 0;
343 }
344
345 static int remove_source(RemoteServer *s, int fd) {
346         RemoteSource *source;
347
348         assert(s);
349         assert(fd >= 0 && fd < (ssize_t) s->sources_size);
350
351         source = s->sources[fd];
352         if (source) {
353                 /* this closes fd too */
354                 source_free(source);
355                 s->sources[fd] = NULL;
356                 s->active--;
357         }
358
359         return 0;
360 }
361
362 static int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
363
364         RemoteSource *source;
365         int r;
366
367         assert(s);
368         assert(fd >= 0);
369         assert(name);
370
371         if (!own_name) {
372                 name = strdup(name);
373                 if (!name)
374                         return log_oom();
375         }
376
377         r = get_source_for_fd(s, fd, name, &source);
378         if (r < 0) {
379                 log_error("Failed to create source for fd:%d (%s): %s",
380                           fd, name, strerror(-r));
381                 return r;
382         }
383
384         r = sd_event_add_io(s->events, &source->event,
385                             fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI,
386                             dispatch_raw_source_event, s);
387         if (r < 0) {
388                 log_error("Failed to register event source for fd:%d: %s",
389                           fd, strerror(-r));
390                 goto error;
391         }
392
393         return 1; /* work to do */
394
395  error:
396         remove_source(s, fd);
397         return r;
398 }
399
400 static int add_raw_socket(RemoteServer *s, int fd) {
401         int r;
402
403         r = sd_event_add_io(s->events, &s->listen_event,
404                             fd, EPOLLIN,
405                             dispatch_raw_connection_event, s);
406         if (r < 0) {
407                 close(fd);
408                 return r;
409         }
410
411         s->active ++;
412         return 0;
413 }
414
415 static int setup_raw_socket(RemoteServer *s, const char *address) {
416         int fd;
417
418         fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
419         if (fd < 0)
420                 return fd;
421
422         return add_raw_socket(s, fd);
423 }
424
425 /**********************************************************************
426  **********************************************************************
427  **********************************************************************/
428
429 static RemoteSource *request_meta(void **connection_cls, int fd, char *hostname) {
430         RemoteSource *source;
431         Writer *writer;
432         int r;
433
434         assert(connection_cls);
435         if (*connection_cls)
436                 return *connection_cls;
437
438         r = get_writer(server, hostname, &writer);
439         if (r < 0) {
440                 log_warning("Failed to get writer for source %s: %s",
441                             hostname, strerror(-r));
442                 return NULL;
443         }
444
445         source = source_new(fd, true, hostname, writer);
446         if (!source) {
447                 log_oom();
448                 writer_unref(writer);
449                 return NULL;
450         }
451
452         log_debug("Added RemoteSource as connection metadata %p", source);
453
454         *connection_cls = source;
455         return source;
456 }
457
458 static void request_meta_free(void *cls,
459                               struct MHD_Connection *connection,
460                               void **connection_cls,
461                               enum MHD_RequestTerminationCode toe) {
462         RemoteSource *s;
463
464         assert(connection_cls);
465         s = *connection_cls;
466
467         log_debug("Cleaning up connection metadata %p", s);
468         source_free(s);
469         *connection_cls = NULL;
470 }
471
472 static int process_http_upload(
473                 struct MHD_Connection *connection,
474                 const char *upload_data,
475                 size_t *upload_data_size,
476                 RemoteSource *source) {
477
478         bool finished = false;
479         size_t remaining;
480         int r;
481
482         assert(source);
483
484         log_debug("request_handler_upload: connection %p, %zu bytes",
485                   connection, *upload_data_size);
486
487         if (*upload_data_size) {
488                 log_debug("Received %zu bytes", *upload_data_size);
489
490                 r = push_data(source, upload_data, *upload_data_size);
491                 if (r < 0)
492                         return mhd_respond_oom(connection);
493
494                 *upload_data_size = 0;
495         } else
496                 finished = true;
497
498         while (true) {
499                 r = process_source(source, arg_compress, arg_seal);
500                 if (r == -EAGAIN || r == -EWOULDBLOCK)
501                         break;
502                 else if (r < 0) {
503                         log_warning("Failed to process data for connection %p", connection);
504                         if (r == -E2BIG)
505                                 return mhd_respondf(connection,
506                                                     MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
507                                                     "Entry is too large, maximum is %u bytes.\n",
508                                                     DATA_SIZE_MAX);
509                         else
510                                 return mhd_respondf(connection,
511                                                     MHD_HTTP_UNPROCESSABLE_ENTITY,
512                                                     "Processing failed: %s.", strerror(-r));
513                 }
514         }
515
516         if (!finished)
517                 return MHD_YES;
518
519         /* The upload is finished */
520
521         remaining = source_non_empty(source);
522         if (remaining > 0) {
523                 log_warning("Premature EOFbyte. %zu bytes lost.", remaining);
524                 return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED,
525                                     "Premature EOF. %zu bytes of trailing data not processed.",
526                                     remaining);
527         }
528
529         return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n");
530 };
531
532 static int request_handler(
533                 void *cls,
534                 struct MHD_Connection *connection,
535                 const char *url,
536                 const char *method,
537                 const char *version,
538                 const char *upload_data,
539                 size_t *upload_data_size,
540                 void **connection_cls) {
541
542         const char *header;
543         int r, code, fd;
544         _cleanup_free_ char *hostname = NULL;
545
546         assert(connection);
547         assert(connection_cls);
548         assert(url);
549         assert(method);
550
551         log_debug("Handling a connection %s %s %s", method, url, version);
552
553         if (*connection_cls)
554                 return process_http_upload(connection,
555                                            upload_data, upload_data_size,
556                                            *connection_cls);
557
558         if (!streq(method, "POST"))
559                 return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
560                                    "Unsupported method.\n");
561
562         if (!streq(url, "/upload"))
563                 return mhd_respond(connection, MHD_HTTP_NOT_FOUND,
564                                    "Not found.\n");
565
566         header = MHD_lookup_connection_value(connection,
567                                              MHD_HEADER_KIND, "Content-Type");
568         if (!header || !streq(header, "application/vnd.fdo.journal"))
569                 return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
570                                    "Content-Type: application/vnd.fdo.journal"
571                                    " is required.\n");
572
573         {
574                 const union MHD_ConnectionInfo *ci;
575
576                 ci = MHD_get_connection_info(connection,
577                                              MHD_CONNECTION_INFO_CONNECTION_FD);
578                 if (!ci) {
579                         log_error("MHD_get_connection_info failed: cannot get remote fd");
580                         return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
581                                            "Cannot check remote address");
582                         return code;
583                 }
584
585                 fd = ci->connect_fd;
586                 assert(fd >= 0);
587         }
588
589         if (server->check_trust) {
590                 r = check_permissions(connection, &code, &hostname);
591                 if (r < 0)
592                         return code;
593         } else {
594                 r = getnameinfo_pretty(fd, &hostname);
595                 if (r < 0) {
596                         return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
597                                            "Cannot check remote hostname");
598                 }
599         }
600
601         assert(hostname);
602
603         if (!request_meta(connection_cls, fd, hostname))
604                 return respond_oom(connection);
605         hostname = NULL;
606         return MHD_YES;
607 }
608
609 static int setup_microhttpd_server(RemoteServer *s,
610                                    int fd,
611                                    const char *key,
612                                    const char *cert,
613                                    const char *trust) {
614         struct MHD_OptionItem opts[] = {
615                 { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
616                 { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
617                 { MHD_OPTION_LISTEN_SOCKET, fd},
618                 { MHD_OPTION_END},
619                 { MHD_OPTION_END},
620                 { MHD_OPTION_END},
621                 { MHD_OPTION_END}};
622         int opts_pos = 3;
623         int flags =
624                 MHD_USE_DEBUG |
625                 MHD_USE_PEDANTIC_CHECKS |
626                 MHD_USE_EPOLL_LINUX_ONLY |
627                 MHD_USE_DUAL_STACK;
628
629         const union MHD_DaemonInfo *info;
630         int r, epoll_fd;
631         MHDDaemonWrapper *d;
632
633         assert(fd >= 0);
634
635         r = fd_nonblock(fd, true);
636         if (r < 0) {
637                 log_error("Failed to make fd:%d nonblocking: %s", fd, strerror(-r));
638                 return r;
639         }
640
641         if (key) {
642                 assert(cert);
643
644                 opts[opts_pos++] = (struct MHD_OptionItem)
645                         {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key};
646                 opts[opts_pos++] = (struct MHD_OptionItem)
647                         {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert};
648
649                 flags |= MHD_USE_SSL;
650
651                 if (trust)
652                         opts[opts_pos++] = (struct MHD_OptionItem)
653                                 {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust};
654         }
655
656         d = new(MHDDaemonWrapper, 1);
657         if (!d)
658                 return log_oom();
659
660         d->fd = (uint64_t) fd;
661
662         d->daemon = MHD_start_daemon(flags, 0,
663                                      NULL, NULL,
664                                      request_handler, NULL,
665                                      MHD_OPTION_ARRAY, opts,
666                                      MHD_OPTION_END);
667         if (!d->daemon) {
668                 log_error("Failed to start Âµhttp daemon");
669                 r = -EINVAL;
670                 goto error;
671         }
672
673         log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
674                   key ? "HTTPS" : "HTTP", fd, d);
675
676
677         info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
678         if (!info) {
679                 log_error("µhttp returned NULL daemon info");
680                 r = -ENOTSUP;
681                 goto error;
682         }
683
684         epoll_fd = info->listen_fd;
685         if (epoll_fd < 0) {
686                 log_error("µhttp epoll fd is invalid");
687                 r = -EUCLEAN;
688                 goto error;
689         }
690
691         r = sd_event_add_io(s->events, &d->event,
692                             epoll_fd, EPOLLIN,
693                             dispatch_http_event, d);
694         if (r < 0) {
695                 log_error("Failed to add event callback: %s", strerror(-r));
696                 goto error;
697         }
698
699         r = hashmap_ensure_allocated(&s->daemons, uint64_hash_func, uint64_compare_func);
700         if (r < 0) {
701                 log_oom();
702                 goto error;
703         }
704
705         r = hashmap_put(s->daemons, &d->fd, d);
706         if (r < 0) {
707                 log_error("Failed to add daemon to hashmap: %s", strerror(-r));
708                 goto error;
709         }
710
711         s->active ++;
712         return 0;
713
714 error:
715         MHD_stop_daemon(d->daemon);
716         free(d->daemon);
717         free(d);
718         return r;
719 }
720
721 static int setup_microhttpd_socket(RemoteServer *s,
722                                    const char *address,
723                                    const char *key,
724                                    const char *cert,
725                                    const char *trust) {
726         int fd;
727
728         fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
729         if (fd < 0)
730                 return fd;
731
732         return setup_microhttpd_server(s, fd, key, cert, trust);
733 }
734
735 static int dispatch_http_event(sd_event_source *event,
736                                int fd,
737                                uint32_t revents,
738                                void *userdata) {
739         MHDDaemonWrapper *d = userdata;
740         int r;
741
742         assert(d);
743
744         r = MHD_run(d->daemon);
745         if (r == MHD_NO) {
746                 log_error("MHD_run failed!");
747                 // XXX: unregister daemon
748                 return -EINVAL;
749         }
750
751         return 1; /* work to do */
752 }
753
754 /**********************************************************************
755  **********************************************************************
756  **********************************************************************/
757
758 static int dispatch_sigterm(sd_event_source *event,
759                             const struct signalfd_siginfo *si,
760                             void *userdata) {
761         RemoteServer *s = userdata;
762
763         assert(s);
764
765         log_received_signal(LOG_INFO, si);
766
767         sd_event_exit(s->events, 0);
768         return 0;
769 }
770
771 static int setup_signals(RemoteServer *s) {
772         sigset_t mask;
773         int r;
774
775         assert(s);
776
777         assert_se(sigemptyset(&mask) == 0);
778         sigset_add_many(&mask, SIGINT, SIGTERM, -1);
779         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
780
781         r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, dispatch_sigterm, s);
782         if (r < 0)
783                 return r;
784
785         r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, dispatch_sigterm, s);
786         if (r < 0)
787                 return r;
788
789         return 0;
790 }
791
792 static int fd_fd(const char *spec) {
793         int fd, r;
794
795         r = safe_atoi(spec, &fd);
796         if (r < 0)
797                 return r;
798         if (fd < 0)
799                 return -EINVAL;
800
801         return fd;
802 }
803
804 static int remoteserver_init(RemoteServer *s,
805                              const char* key,
806                              const char* cert,
807                              const char* trust) {
808         int r, n, fd;
809         char **file;
810
811         assert(s);
812
813         if ((arg_listen_raw || arg_listen_http) && trust) {
814                 log_error("Option --trust makes all non-HTTPS connections untrusted.");
815                 return -EINVAL;
816         }
817
818         sd_event_default(&s->events);
819
820         setup_signals(s);
821
822         assert(server == NULL);
823         server = s;
824
825         n = sd_listen_fds(true);
826         if (n < 0) {
827                 log_error("Failed to read listening file descriptors from environment: %s",
828                           strerror(-n));
829                 return n;
830         } else
831                 log_info("Received %d descriptors", n);
832
833         if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
834                 log_error("Received fewer sockets than expected");
835                 return -EBADFD;
836         }
837
838         for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
839                 if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
840                         log_info("Received a listening socket (fd:%d)", fd);
841
842                         if (fd == http_socket)
843                                 r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
844                         else if (fd == https_socket)
845                                 r = setup_microhttpd_server(s, fd, key, cert, trust);
846                         else
847                                 r = add_raw_socket(s, fd);
848                 } else if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
849                         char *hostname;
850
851                         r = getnameinfo_pretty(fd, &hostname);
852                         if (r < 0) {
853                                 log_error("Failed to retrieve remote name: %s", strerror(-r));
854                                 return r;
855                         }
856
857                         log_info("Received a connection socket (fd:%d) from %s", fd, hostname);
858
859                         r = add_source(s, fd, hostname, true);
860                         if (r < 0)
861                                 free(hostname);
862                 } else {
863                         log_error("Unknown socket passed on fd:%d", fd);
864
865                         return -EINVAL;
866                 }
867
868                 if(r < 0) {
869                         log_error("Failed to register socket (fd:%d): %s",
870                                   fd, strerror(-r));
871                         return r;
872                 }
873         }
874
875         if (arg_url) {
876                 const char *url, *hostname;
877
878                 url = strappenda(arg_url, "/entries");
879
880                 if (arg_getter) {
881                         log_info("Spawning getter %s...", url);
882                         fd = spawn_getter(arg_getter, url);
883                 } else {
884                         log_info("Spawning curl %s...", url);
885                         fd = spawn_curl(url);
886                 }
887                 if (fd < 0)
888                         return fd;
889
890                 hostname =
891                         startswith(arg_url, "https://") ?:
892                         startswith(arg_url, "http://") ?:
893                         arg_url;
894
895                 r = add_source(s, fd, (char*) hostname, false);
896                 if (r < 0)
897                         return r;
898         }
899
900         if (arg_listen_raw) {
901                 log_info("Listening on a socket...");
902                 r = setup_raw_socket(s, arg_listen_raw);
903                 if (r < 0)
904                         return r;
905         }
906
907         if (arg_listen_http) {
908                 r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
909                 if (r < 0)
910                         return r;
911         }
912
913         if (arg_listen_https) {
914                 r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
915                 if (r < 0)
916                         return r;
917         }
918
919         STRV_FOREACH(file, arg_files) {
920                 const char *output_name;
921
922                 if (streq(*file, "-")) {
923                         log_info("Using standard input as source.");
924
925                         fd = STDIN_FILENO;
926                         output_name = "stdin";
927                 } else {
928                         log_info("Reading file %s...", *file);
929
930                         fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
931                         if (fd < 0) {
932                                 log_error("Failed to open %s: %m", *file);
933                                 return -errno;
934                         }
935                         output_name = *file;
936                 }
937
938                 r = add_source(s, fd, (char*) output_name, false);
939                 if (r < 0)
940                         return r;
941         }
942
943         if (s->active == 0) {
944                 log_error("Zarro sources specified");
945                 return -EINVAL;
946         }
947
948         r = init_writer_hashmap(s);
949         if (r < 0)
950                 return r;
951
952         if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) {
953                 /* In this case we know what the writer will be
954                    called, so we can create it and verify that we can
955                    create output as expected. */
956                 r = get_writer(s, NULL, &s->_single_writer);
957                 if (r < 0)
958                         return r;
959         }
960
961         return 0;
962 }
963
964 static void server_destroy(RemoteServer *s) {
965         size_t i;
966         MHDDaemonWrapper *d;
967
968         while ((d = hashmap_steal_first(s->daemons))) {
969                 MHD_stop_daemon(d->daemon);
970                 sd_event_source_unref(d->event);
971                 free(d);
972         }
973
974         hashmap_free(s->daemons);
975
976         assert(s->sources_size == 0 || s->sources);
977         for (i = 0; i < s->sources_size; i++)
978                 remove_source(s, i);
979         free(s->sources);
980
981         writer_unref(s->_single_writer);
982         hashmap_free(s->writers);
983
984         sd_event_source_unref(s->sigterm_event);
985         sd_event_source_unref(s->sigint_event);
986         sd_event_source_unref(s->listen_event);
987         sd_event_unref(s->events);
988
989         /* fds that we're listening on remain open... */
990 }
991
992 /**********************************************************************
993  **********************************************************************
994  **********************************************************************/
995
996 static int dispatch_raw_source_event(sd_event_source *event,
997                                      int fd,
998                                      uint32_t revents,
999                                      void *userdata) {
1000
1001         RemoteServer *s = userdata;
1002         RemoteSource *source;
1003         int r;
1004
1005         assert(fd >= 0 && fd < (ssize_t) s->sources_size);
1006         source = s->sources[fd];
1007         assert(source->fd == fd);
1008
1009         r = process_source(source, arg_compress, arg_seal);
1010         if (source->state == STATE_EOF) {
1011                 size_t remaining;
1012
1013                 log_info("EOF reached with source fd:%d (%s)",
1014                          source->fd, source->name);
1015
1016                 remaining = source_non_empty(source);
1017                 if (remaining > 0)
1018                         log_warning("Premature EOF. %zu bytes lost.", remaining);
1019                 remove_source(s, source->fd);
1020                 log_info("%zd active sources remaining", s->active);
1021                 return 0;
1022         } else if (r == -E2BIG) {
1023                 log_error("Entry too big, skipped");
1024                 return 1;
1025         } else if (r == -EAGAIN) {
1026                 return 0;
1027         } else if (r < 0) {
1028                 log_info("Closing connection: %s", strerror(-r));
1029                 remove_source(server, fd);
1030                 return 0;
1031         } else
1032                 return 1;
1033 }
1034
1035 static int accept_connection(const char* type, int fd,
1036                              SocketAddress *addr, char **hostname) {
1037         int fd2, r;
1038
1039         log_debug("Accepting new %s connection on fd:%d", type, fd);
1040         fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC);
1041         if (fd2 < 0) {
1042                 log_error("accept() on fd:%d failed: %m", fd);
1043                 return -errno;
1044         }
1045
1046         switch(socket_address_family(addr)) {
1047         case AF_INET:
1048         case AF_INET6: {
1049                 _cleanup_free_ char *a = NULL;
1050                 char *b;
1051
1052                 r = socket_address_print(addr, &a);
1053                 if (r < 0) {
1054                         log_error("socket_address_print(): %s", strerror(-r));
1055                         close(fd2);
1056                         return r;
1057                 }
1058
1059                 r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
1060                 if (r < 0) {
1061                         close(fd2);
1062                         return r;
1063                 }
1064
1065                 log_info("Accepted %s %s connection from %s",
1066                          type,
1067                          socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
1068                          a);
1069
1070                 *hostname = b;
1071
1072                 return fd2;
1073         };
1074         default:
1075                 log_error("Rejected %s connection with unsupported family %d",
1076                           type, socket_address_family(addr));
1077                 close(fd2);
1078
1079                 return -EINVAL;
1080         }
1081 }
1082
1083 static int dispatch_raw_connection_event(sd_event_source *event,
1084                                          int fd,
1085                                          uint32_t revents,
1086                                          void *userdata) {
1087         RemoteServer *s = userdata;
1088         int fd2, r;
1089         SocketAddress addr = {
1090                 .size = sizeof(union sockaddr_union),
1091                 .type = SOCK_STREAM,
1092         };
1093         char *hostname;
1094
1095         fd2 = accept_connection("raw", fd, &addr, &hostname);
1096         if (fd2 < 0)
1097                 return fd2;
1098
1099         r = add_source(s, fd2, hostname, true);
1100         if (r < 0)
1101                 free(hostname);
1102         return r;
1103 }
1104
1105 /**********************************************************************
1106  **********************************************************************
1107  **********************************************************************/
1108
1109 static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
1110         [JOURNAL_WRITE_SPLIT_NONE] = "none",
1111         [JOURNAL_WRITE_SPLIT_HOST] = "host",
1112 };
1113
1114 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode);
1115 static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
1116                                 journal_write_split_mode,
1117                                 JournalWriteSplitMode,
1118                                 "Failed to parse split mode setting");
1119
1120 static int parse_config(void) {
1121         const ConfigTableItem items[] = {
1122                 { "Remote",  "SplitMode",              config_parse_write_split_mode, 0, &arg_split_mode },
1123                 { "Remote",  "ServerKeyFile",          config_parse_path,             0, &arg_key        },
1124                 { "Remote",  "ServerCertificateFile",  config_parse_path,             0, &arg_cert       },
1125                 { "Remote",  "TrustedCertificateFile", config_parse_path,             0, &arg_trust      },
1126                 {}};
1127
1128         return config_parse(NULL, PKGSYSCONFDIR "/journal-remote.conf", NULL,
1129                             "Remote\0",
1130                             config_item_table_lookup, items,
1131                             false, false, true, NULL);
1132 }
1133
1134 static void help(void) {
1135         printf("%s [OPTIONS...] {FILE|-}...\n\n"
1136                "Write external journal events to journal file(s).\n\n"
1137                "  -h --help               Show this help\n"
1138                "     --version            Show package version\n"
1139                "     --url=URL            Read events from systemd-journal-gatewayd at URL\n"
1140                "     --getter=COMMAND     Read events from the output of COMMAND\n"
1141                "     --listen-raw=ADDR    Listen for connections at ADDR\n"
1142                "     --listen-http=ADDR   Listen for HTTP connections at ADDR\n"
1143                "     --listen-https=ADDR  Listen for HTTPS connections at ADDR\n"
1144                "  -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
1145                "     --compress[=BOOL]    Use XZ-compression in the output journal (default: yes)\n"
1146                "     --seal[=BOOL]        Use Event sealing in the output journal (default: no)\n"
1147                "     --key=FILENAME       Specify key in PEM format (default:\n"
1148                "                          \"" PRIV_KEY_FILE "\")\n"
1149                "     --cert=FILENAME      Specify certificate in PEM format (default:\n"
1150                "                          \"" CERT_FILE "\")\n"
1151                "     --trust=FILENAME|all Specify CA certificate or disable checking (default:\n"
1152                "                          \"" TRUST_FILE "\")\n"
1153                "     --gnutls-log=CATEGORY...\n"
1154                "                          Specify a list of gnutls logging categories\n"
1155                "\n"
1156                "Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
1157                , program_invocation_short_name);
1158 }
1159
1160 static int parse_argv(int argc, char *argv[]) {
1161         enum {
1162                 ARG_VERSION = 0x100,
1163                 ARG_URL,
1164                 ARG_LISTEN_RAW,
1165                 ARG_LISTEN_HTTP,
1166                 ARG_LISTEN_HTTPS,
1167                 ARG_GETTER,
1168                 ARG_SPLIT_MODE,
1169                 ARG_COMPRESS,
1170                 ARG_SEAL,
1171                 ARG_KEY,
1172                 ARG_CERT,
1173                 ARG_TRUST,
1174                 ARG_GNUTLS_LOG,
1175         };
1176
1177         static const struct option options[] = {
1178                 { "help",         no_argument,       NULL, 'h'              },
1179                 { "version",      no_argument,       NULL, ARG_VERSION      },
1180                 { "url",          required_argument, NULL, ARG_URL          },
1181                 { "getter",       required_argument, NULL, ARG_GETTER       },
1182                 { "listen-raw",   required_argument, NULL, ARG_LISTEN_RAW   },
1183                 { "listen-http",  required_argument, NULL, ARG_LISTEN_HTTP  },
1184                 { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
1185                 { "output",       required_argument, NULL, 'o'              },
1186                 { "split-mode",   required_argument, NULL, ARG_SPLIT_MODE   },
1187                 { "compress",     optional_argument, NULL, ARG_COMPRESS     },
1188                 { "seal",         optional_argument, NULL, ARG_SEAL         },
1189                 { "key",          required_argument, NULL, ARG_KEY          },
1190                 { "cert",         required_argument, NULL, ARG_CERT         },
1191                 { "trust",        required_argument, NULL, ARG_TRUST        },
1192                 { "gnutls-log",   required_argument, NULL, ARG_GNUTLS_LOG   },
1193                 {}
1194         };
1195
1196         int c, r;
1197         bool type_a, type_b;
1198
1199         assert(argc >= 0);
1200         assert(argv);
1201
1202         while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
1203                 switch(c) {
1204                 case 'h':
1205                         help();
1206                         return 0 /* done */;
1207
1208                 case ARG_VERSION:
1209                         puts(PACKAGE_STRING);
1210                         puts(SYSTEMD_FEATURES);
1211                         return 0 /* done */;
1212
1213                 case ARG_URL:
1214                         if (arg_url) {
1215                                 log_error("cannot currently set more than one --url");
1216                                 return -EINVAL;
1217                         }
1218
1219                         arg_url = optarg;
1220                         break;
1221
1222                 case ARG_GETTER:
1223                         if (arg_getter) {
1224                                 log_error("cannot currently use --getter more than once");
1225                                 return -EINVAL;
1226                         }
1227
1228                         arg_getter = optarg;
1229                         break;
1230
1231                 case ARG_LISTEN_RAW:
1232                         if (arg_listen_raw) {
1233                                 log_error("cannot currently use --listen-raw more than once");
1234                                 return -EINVAL;
1235                         }
1236
1237                         arg_listen_raw = optarg;
1238                         break;
1239
1240                 case ARG_LISTEN_HTTP:
1241                         if (arg_listen_http || http_socket >= 0) {
1242                                 log_error("cannot currently use --listen-http more than once");
1243                                 return -EINVAL;
1244                         }
1245
1246                         r = fd_fd(optarg);
1247                         if (r >= 0)
1248                                 http_socket = r;
1249                         else
1250                                 arg_listen_http = optarg;
1251                         break;
1252
1253                 case ARG_LISTEN_HTTPS:
1254                         if (arg_listen_https || https_socket >= 0) {
1255                                 log_error("cannot currently use --listen-https more than once");
1256                                 return -EINVAL;
1257                         }
1258
1259                         r = fd_fd(optarg);
1260                         if (r >= 0)
1261                                 https_socket = r;
1262                         else
1263                                 arg_listen_https = optarg;
1264
1265                         break;
1266
1267                 case ARG_KEY:
1268                         if (arg_key) {
1269                                 log_error("Key file specified twice");
1270                                 return -EINVAL;
1271                         }
1272
1273                         arg_key = strdup(optarg);
1274                         if (!arg_key)
1275                                 return log_oom();
1276
1277                         break;
1278
1279                 case ARG_CERT:
1280                         if (arg_cert) {
1281                                 log_error("Certificate file specified twice");
1282                                 return -EINVAL;
1283                         }
1284
1285                         arg_cert = strdup(optarg);
1286                         if (!arg_cert)
1287                                 return log_oom();
1288
1289                         break;
1290
1291                 case ARG_TRUST:
1292                         if (arg_trust || arg_trust_all) {
1293                                 log_error("Confusing trusted CA configuration");
1294                                 return -EINVAL;
1295                         }
1296
1297                         if (streq(optarg, "all"))
1298                                 arg_trust_all = true;
1299                         else {
1300 #ifdef HAVE_GNUTLS
1301                                 arg_trust = strdup(optarg);
1302                                 if (!arg_trust)
1303                                         return log_oom();
1304 #else
1305                                 log_error("Option --trust is not available.");
1306                                 return -EINVAL;
1307 #endif
1308                         }
1309
1310                         break;
1311
1312                 case 'o':
1313                         if (arg_output) {
1314                                 log_error("cannot use --output/-o more than once");
1315                                 return -EINVAL;
1316                         }
1317
1318                         arg_output = optarg;
1319                         break;
1320
1321                 case ARG_SPLIT_MODE:
1322                         arg_split_mode = journal_write_split_mode_from_string(optarg);
1323                         if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) {
1324                                 log_error("Invalid split mode: %s", optarg);
1325                                 return -EINVAL;
1326                         }
1327                         break;
1328
1329                 case ARG_COMPRESS:
1330                         if (optarg) {
1331                                 r = parse_boolean(optarg);
1332                                 if (r < 0) {
1333                                         log_error("Failed to parse --compress= parameter.");
1334                                         return -EINVAL;
1335                                 }
1336
1337                                 arg_compress = !!r;
1338                         } else
1339                                 arg_compress = true;
1340
1341                         break;
1342
1343                 case ARG_SEAL:
1344                         if (optarg) {
1345                                 r = parse_boolean(optarg);
1346                                 if (r < 0) {
1347                                         log_error("Failed to parse --seal= parameter.");
1348                                         return -EINVAL;
1349                                 }
1350
1351                                 arg_seal = !!r;
1352                         } else
1353                                 arg_seal = true;
1354
1355                         break;
1356
1357                 case ARG_GNUTLS_LOG: {
1358 #ifdef HAVE_GNUTLS
1359                         const char *word, *state;
1360                         size_t size;
1361
1362                         FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
1363                                 char *cat;
1364
1365                                 cat = strndup(word, size);
1366                                 if (!cat)
1367                                         return log_oom();
1368
1369                                 if (strv_consume(&arg_gnutls_log, cat) < 0)
1370                                         return log_oom();
1371                         }
1372                         break;
1373 #else
1374                         log_error("Option --gnutls-log is not available.");
1375                         return -EINVAL;
1376 #endif
1377                 }
1378
1379                 case '?':
1380                         return -EINVAL;
1381
1382                 default:
1383                         assert_not_reached("Unknown option code.");
1384                 }
1385
1386         if (optind < argc)
1387                 arg_files = argv + optind;
1388
1389         type_a = arg_getter || !strv_isempty(arg_files);
1390         type_b = arg_url
1391                 || arg_listen_raw
1392                 || arg_listen_http || arg_listen_https
1393                 || sd_listen_fds(false) > 0;
1394         if (type_a && type_b) {
1395                 log_error("Cannot use file input or --getter with "
1396                           "--arg-listen-... or socket activation.");
1397                 return -EINVAL;
1398         }
1399         if (type_a) {
1400                 if (!arg_output) {
1401                         log_error("Option --output must be specified with file input or --getter.");
1402                         return -EINVAL;
1403                 }
1404
1405                 arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
1406         }
1407
1408         if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE
1409             && arg_output && is_dir(arg_output, true) > 0) {
1410                 log_error("For SplitMode=none, output must be a file.");
1411                 return -EINVAL;
1412         }
1413
1414         if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
1415             && arg_output && is_dir(arg_output, true) <= 0) {
1416                 log_error("For SplitMode=host, output must be a directory.");
1417                 return -EINVAL;
1418         }
1419
1420         log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
1421                   journal_write_split_mode_to_string(arg_split_mode),
1422                   strna(arg_key),
1423                   strna(arg_cert),
1424                   strna(arg_trust));
1425
1426         return 1 /* work to do */;
1427 }
1428
1429 static int load_certificates(char **key, char **cert, char **trust) {
1430         int r;
1431
1432         r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL);
1433         if (r < 0) {
1434                 log_error("Failed to read key from file '%s': %s",
1435                           arg_key ?: PRIV_KEY_FILE, strerror(-r));
1436                 return r;
1437         }
1438
1439         r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL);
1440         if (r < 0) {
1441                 log_error("Failed to read certificate from file '%s': %s",
1442                           arg_cert ?: CERT_FILE, strerror(-r));
1443                 return r;
1444         }
1445
1446         if (arg_trust_all)
1447                 log_info("Certificate checking disabled.");
1448         else {
1449                 r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL);
1450                 if (r < 0) {
1451                         log_error("Failed to read CA certificate file '%s': %s",
1452                                   arg_trust ?: TRUST_FILE, strerror(-r));
1453                         return r;
1454                 }
1455         }
1456
1457         return 0;
1458 }
1459
1460 static int setup_gnutls_logger(char **categories) {
1461         if (!arg_listen_http && !arg_listen_https)
1462                 return 0;
1463
1464 #ifdef HAVE_GNUTLS
1465         {
1466                 char **cat;
1467                 int r;
1468
1469                 gnutls_global_set_log_function(log_func_gnutls);
1470
1471                 if (categories)
1472                         STRV_FOREACH(cat, categories) {
1473                                 r = log_enable_gnutls_category(*cat);
1474                                 if (r < 0)
1475                                         return r;
1476                         }
1477                 else
1478                         log_reset_gnutls_level();
1479         }
1480 #endif
1481
1482         return 0;
1483 }
1484
1485 int main(int argc, char **argv) {
1486         RemoteServer s = {};
1487         int r;
1488         _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
1489
1490         log_show_color(true);
1491         log_parse_environment();
1492
1493         r = parse_config();
1494         if (r < 0)
1495                 return EXIT_FAILURE;
1496
1497         r = parse_argv(argc, argv);
1498         if (r <= 0)
1499                 return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1500
1501         r = setup_gnutls_logger(arg_gnutls_log);
1502         if (r < 0)
1503                 return EXIT_FAILURE;
1504
1505         if (arg_listen_https || https_socket >= 0)
1506                 if (load_certificates(&key, &cert, &trust) < 0)
1507                         return EXIT_FAILURE;
1508
1509         if (remoteserver_init(&s, key, cert, trust) < 0)
1510                 return EXIT_FAILURE;
1511
1512         sd_event_set_watchdog(s.events, true);
1513
1514         log_debug("%s running as pid "PID_FMT,
1515                   program_invocation_short_name, getpid());
1516         sd_notify(false,
1517                   "READY=1\n"
1518                   "STATUS=Processing requests...");
1519
1520         while (s.active) {
1521                 r = sd_event_get_state(s.events);
1522                 if (r < 0)
1523                         break;
1524                 if (r == SD_EVENT_FINISHED)
1525                         break;
1526
1527                 r = sd_event_run(s.events, -1);
1528                 if (r < 0) {
1529                         log_error("Failed to run event loop: %s", strerror(-r));
1530                         break;
1531                 }
1532         }
1533
1534         server_destroy(&s);
1535         log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
1536
1537         sd_notify(false, "STATUS=Shutting down...");
1538
1539         free(arg_key);
1540         free(arg_cert);
1541         free(arg_trust);
1542
1543         return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1544 }