Bug Summary

File:build-scan/../src/journal-remote/journal-gatewayd.c
Warning:line 311, column 27
Potential leak of memory pointed to by 't'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name journal-gatewayd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I systemd-journal-gatewayd.p -I . -I .. -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I /usr/include/p11-kit-1 -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/journal-remote/journal-gatewayd.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <fcntl.h>
4#include <getopt.h>
5#include <microhttpd.h>
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9
10#include "sd-bus.h"
11#include "sd-daemon.h"
12#include "sd-journal.h"
13
14#include "alloc-util.h"
15#include "bus-util.h"
16#include "fd-util.h"
17#include "fileio.h"
18#include "hostname-util.h"
19#include "log.h"
20#include "logs-show.h"
21#include "microhttpd-util.h"
22#include "os-util.h"
23#include "parse-util.h"
24#include "sigbus.h"
25#include "util.h"
26
27#define JOURNAL_WAIT_TIMEOUT(10*((usec_t) 1000000ULL)) (10*USEC_PER_SEC((usec_t) 1000000ULL))
28
29static char *arg_key_pem = NULL((void*)0);
30static char *arg_cert_pem = NULL((void*)0);
31static char *arg_trust_pem = NULL((void*)0);
32static char *arg_directory = NULL((void*)0);
33
34typedef struct RequestMeta {
35 sd_journal *journal;
36
37 OutputMode mode;
38
39 char *cursor;
40 int64_t n_skip;
41 uint64_t n_entries;
42 bool_Bool n_entries_set;
43
44 FILE *tmp;
45 uint64_t delta, size;
46
47 int argument_parse_error;
48
49 bool_Bool follow;
50 bool_Bool discrete;
51
52 uint64_t n_fields;
53 bool_Bool n_fields_set;
54} RequestMeta;
55
56static const char* const mime_types[_OUTPUT_MODE_MAX] = {
57 [OUTPUT_SHORT] = "text/plain",
58 [OUTPUT_JSON] = "application/json",
59 [OUTPUT_JSON_SSE] = "text/event-stream",
60 [OUTPUT_EXPORT] = "application/vnd.fdo.journal",
61};
62
63static RequestMeta *request_meta(void **connection_cls) {
64 RequestMeta *m;
65
66 assert(connection_cls)do { if ((__builtin_expect(!!(!(connection_cls)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection_cls"), "../src/journal-remote/journal-gatewayd.c"
, 66, __PRETTY_FUNCTION__); } while (0)
;
67 if (*connection_cls)
68 return *connection_cls;
69
70 m = new0(RequestMeta, 1)((RequestMeta*) calloc((1), sizeof(RequestMeta)));
71 if (!m)
72 return NULL((void*)0);
73
74 *connection_cls = m;
75 return m;
76}
77
78static void request_meta_free(
79 void *cls,
80 struct MHD_Connection *connection,
81 void **connection_cls,
82 enum MHD_RequestTerminationCode toe) {
83
84 RequestMeta *m = *connection_cls;
85
86 if (!m)
87 return;
88
89 sd_journal_close(m->journal);
90
91 safe_fclose(m->tmp);
92
93 free(m->cursor);
94 free(m);
95}
96
97static int open_journal(RequestMeta *m) {
98 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 98, __PRETTY_FUNCTION__); } while (0)
;
99
100 if (m->journal)
101 return 0;
102
103 if (arg_directory)
104 return sd_journal_open_directory(&m->journal, arg_directory, 0);
105 else
106 return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM);
107}
108
109static int request_meta_ensure_tmp(RequestMeta *m) {
110 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 110, __PRETTY_FUNCTION__); } while (0)
;
111
112 if (m->tmp)
113 rewind(m->tmp);
114 else {
115 int fd;
116
117 fd = open_tmpfile_unlinkable("/tmp", O_RDWR02|O_CLOEXEC02000000);
118 if (fd < 0)
119 return fd;
120
121 m->tmp = fdopen(fd, "w+");
122 if (!m->tmp) {
123 safe_close(fd);
124 return -errno(*__errno_location ());
125 }
126 }
127
128 return 0;
129}
130
131static ssize_t request_reader_entries(
132 void *cls,
133 uint64_t pos,
134 char *buf,
135 size_t max) {
136
137 RequestMeta *m = cls;
138 int r;
139 size_t n, k;
140
141 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 141, __PRETTY_FUNCTION__); } while (0)
;
142 assert(buf)do { if ((__builtin_expect(!!(!(buf)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("buf"), "../src/journal-remote/journal-gatewayd.c"
, 142, __PRETTY_FUNCTION__); } while (0)
;
143 assert(max > 0)do { if ((__builtin_expect(!!(!(max > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("max > 0"), "../src/journal-remote/journal-gatewayd.c"
, 143, __PRETTY_FUNCTION__); } while (0)
;
144 assert(pos >= m->delta)do { if ((__builtin_expect(!!(!(pos >= m->delta)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pos >= m->delta"), "../src/journal-remote/journal-gatewayd.c"
, 144, __PRETTY_FUNCTION__); } while (0)
;
145
146 pos -= m->delta;
147
148 while (pos >= m->size) {
149 off_t sz;
150
151 /* End of this entry, so let's serialize the next
152 * one */
153
154 if (m->n_entries_set &&
155 m->n_entries <= 0)
156 return MHD_CONTENT_READER_END_OF_STREAM(18446744073709551615UL);
157
158 if (m->n_skip < 0)
159 r = sd_journal_previous_skip(m->journal, (uint64_t) -m->n_skip + 1);
160 else if (m->n_skip > 0)
161 r = sd_journal_next_skip(m->journal, (uint64_t) m->n_skip + 1);
162 else
163 r = sd_journal_next(m->journal);
164
165 if (r < 0) {
166 log_error_errno(r, "Failed to advance journal pointer: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 166, __func__, "Failed to advance journal pointer: %m"
) : -abs(_e); })
;
167 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
168 } else if (r == 0) {
169
170 if (m->follow) {
171 r = sd_journal_wait(m->journal, (uint64_t) JOURNAL_WAIT_TIMEOUT(10*((usec_t) 1000000ULL)));
172 if (r < 0) {
173 log_error_errno(r, "Couldn't wait for journal event: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 173, __func__, "Couldn't wait for journal event: %m"
) : -abs(_e); })
;
174 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
175 }
176 if (r == SD_JOURNAL_NOP)
177 break;
178
179 continue;
180 }
181
182 return MHD_CONTENT_READER_END_OF_STREAM(18446744073709551615UL);
183 }
184
185 if (m->discrete) {
186 assert(m->cursor)do { if ((__builtin_expect(!!(!(m->cursor)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->cursor"), "../src/journal-remote/journal-gatewayd.c"
, 186, __PRETTY_FUNCTION__); } while (0)
;
187
188 r = sd_journal_test_cursor(m->journal, m->cursor);
189 if (r < 0) {
190 log_error_errno(r, "Failed to test cursor: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 190, __func__, "Failed to test cursor: %m"
) : -abs(_e); })
;
191 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
192 }
193
194 if (r == 0)
195 return MHD_CONTENT_READER_END_OF_STREAM(18446744073709551615UL);
196 }
197
198 pos -= m->size;
199 m->delta += m->size;
200
201 if (m->n_entries_set)
202 m->n_entries -= 1;
203
204 m->n_skip = 0;
205
206 r = request_meta_ensure_tmp(m);
207 if (r < 0) {
208 log_error_errno(r, "Failed to create temporary file: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 208, __func__, "Failed to create temporary file: %m"
) : -abs(_e); })
;
209 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
210 }
211
212 r = show_journal_entry(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH,
213 NULL((void*)0), NULL((void*)0), NULL((void*)0));
214 if (r < 0) {
215 log_error_errno(r, "Failed to serialize item: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 215, __func__, "Failed to serialize item: %m"
) : -abs(_e); })
;
216 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
217 }
218
219 sz = ftello(m->tmp);
220 if (sz == (off_t) -1) {
221 log_error_errno(errno, "Failed to retrieve file position: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/journal-remote/journal-gatewayd.c"
, 221, __func__, "Failed to retrieve file position: %m") : -abs
(_e); })
;
222 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
223 }
224
225 m->size = (uint64_t) sz;
226 }
227
228 if (m->tmp == NULL((void*)0) && m->follow)
229 return 0;
230
231 if (fseeko(m->tmp, pos, SEEK_SET0) < 0) {
232 log_error_errno(errno, "Failed to seek to position: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/journal-remote/journal-gatewayd.c"
, 232, __func__, "Failed to seek to position: %m") : -abs(_e)
; })
;
233 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
234 }
235
236 n = m->size - pos;
237 if (n < 1)
238 return 0;
239 if (n > max)
240 n = max;
241
242 errno(*__errno_location ()) = 0;
243 k = fread(buf, 1, n, m->tmp);
244 if (k != n) {
245 log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 245, __func__, "Failed to read from file: %s"
, (*__errno_location ()) ? strerror((*__errno_location ())) :
"Premature EOF") : -abs(_e); })
;
246 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
247 }
248
249 return (ssize_t) k;
250}
251
252static int request_parse_accept(
253 RequestMeta *m,
254 struct MHD_Connection *connection) {
255
256 const char *header;
257
258 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 258, __PRETTY_FUNCTION__); } while (0)
;
259 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 259, __PRETTY_FUNCTION__); } while (0)
;
260
261 header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept");
262 if (!header)
263 return 0;
264
265 if (streq(header, mime_types[OUTPUT_JSON])(strcmp((header),(mime_types[OUTPUT_JSON])) == 0))
266 m->mode = OUTPUT_JSON;
267 else if (streq(header, mime_types[OUTPUT_JSON_SSE])(strcmp((header),(mime_types[OUTPUT_JSON_SSE])) == 0))
268 m->mode = OUTPUT_JSON_SSE;
269 else if (streq(header, mime_types[OUTPUT_EXPORT])(strcmp((header),(mime_types[OUTPUT_EXPORT])) == 0))
270 m->mode = OUTPUT_EXPORT;
271 else
272 m->mode = OUTPUT_SHORT;
273
274 return 0;
275}
276
277static int request_parse_range(
278 RequestMeta *m,
279 struct MHD_Connection *connection) {
280
281 const char *range, *colon, *colon2;
282 int r;
283
284 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 284, __PRETTY_FUNCTION__); } while (0)
;
29
Taking false branch
30
Loop condition is false. Exiting loop
285 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 285, __PRETTY_FUNCTION__); } while (0)
;
31
Taking false branch
32
Loop condition is false. Exiting loop
286
287 range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range");
288 if (!range)
33
Assuming 'range' is non-null
34
Taking false branch
289 return 0;
290
291 if (!startswith(range, "entries="))
35
Taking false branch
292 return 0;
293
294 range += 8;
295 range += strspn(range, WHITESPACE" \t\n\r");
296
297 colon = strchr(range, ':');
298 if (!colon)
36
Assuming 'colon' is non-null
37
Taking false branch
299 m->cursor = strdup(range);
300 else {
301 const char *p;
302
303 colon2 = strchr(colon + 1, ':');
304 if (colon2) {
38
Assuming 'colon2' is non-null
39
Taking true branch
305 _cleanup_free___attribute__((cleanup(freep))) char *t;
306
307 t = strndup(colon + 1, colon2 - colon - 1);
40
Memory is allocated
308 if (!t)
41
Assuming 't' is non-null
42
Taking false branch
309 return -ENOMEM12;
310
311 r = safe_atoi64(t, &m->n_skip);
43
Potential leak of memory pointed to by 't'
312 if (r < 0)
313 return r;
314 }
315
316 p = (colon2 ? colon2 : colon) + 1;
317 if (*p) {
318 r = safe_atou64(p, &m->n_entries);
319 if (r < 0)
320 return r;
321
322 if (m->n_entries <= 0)
323 return -EINVAL22;
324
325 m->n_entries_set = true1;
326 }
327
328 m->cursor = strndup(range, colon - range);
329 }
330
331 if (!m->cursor)
332 return -ENOMEM12;
333
334 m->cursor[strcspn(m->cursor, WHITESPACE" \t\n\r")] = 0;
335 if (isempty(m->cursor))
336 m->cursor = mfree(m->cursor);
337
338 return 0;
339}
340
341static mhd_resultenum MHD_Result request_parse_arguments_iterator(
342 void *cls,
343 enum MHD_ValueKind kind,
344 const char *key,
345 const char *value) {
346
347 RequestMeta *m = cls;
348 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
349 int r;
350
351 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 351, __PRETTY_FUNCTION__); } while (0)
;
352
353 if (isempty(key)) {
354 m->argument_parse_error = -EINVAL22;
355 return MHD_NO;
356 }
357
358 if (streq(key, "follow")(strcmp((key),("follow")) == 0)) {
359 if (isempty(value)) {
360 m->follow = true1;
361 return MHD_YES;
362 }
363
364 r = parse_boolean(value);
365 if (r < 0) {
366 m->argument_parse_error = r;
367 return MHD_NO;
368 }
369
370 m->follow = r;
371 return MHD_YES;
372 }
373
374 if (streq(key, "discrete")(strcmp((key),("discrete")) == 0)) {
375 if (isempty(value)) {
376 m->discrete = true1;
377 return MHD_YES;
378 }
379
380 r = parse_boolean(value);
381 if (r < 0) {
382 m->argument_parse_error = r;
383 return MHD_NO;
384 }
385
386 m->discrete = r;
387 return MHD_YES;
388 }
389
390 if (streq(key, "boot")(strcmp((key),("boot")) == 0)) {
391 if (isempty(value))
392 r = true1;
393 else {
394 r = parse_boolean(value);
395 if (r < 0) {
396 m->argument_parse_error = r;
397 return MHD_NO;
398 }
399 }
400
401 if (r) {
402 char match[9 + 32 + 1] = "_BOOT_ID=";
403 sd_id128_t bid;
404
405 r = sd_id128_get_boot(&bid);
406 if (r < 0) {
407 log_error_errno(r, "Failed to get boot ID: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 407, __func__, "Failed to get boot ID: %m"
) : -abs(_e); })
;
408 return MHD_NO;
409 }
410
411 sd_id128_to_string(bid, match + 9);
412 r = sd_journal_add_match(m->journal, match, sizeof(match)-1);
413 if (r < 0) {
414 m->argument_parse_error = r;
415 return MHD_NO;
416 }
417 }
418
419 return MHD_YES;
420 }
421
422 p = strjoin(key, "=", strempty(value))strjoin_real((key), "=", strempty(value), ((void*)0));
423 if (!p) {
424 m->argument_parse_error = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 424, __func__)
;
425 return MHD_NO;
426 }
427
428 r = sd_journal_add_match(m->journal, p, 0);
429 if (r < 0) {
430 m->argument_parse_error = r;
431 return MHD_NO;
432 }
433
434 return MHD_YES;
435}
436
437static int request_parse_arguments(
438 RequestMeta *m,
439 struct MHD_Connection *connection) {
440
441 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 441, __PRETTY_FUNCTION__); } while (0)
;
442 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 442, __PRETTY_FUNCTION__); } while (0)
;
443
444 m->argument_parse_error = 0;
445 MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, request_parse_arguments_iterator, m);
446
447 return m->argument_parse_error;
448}
449
450static int request_handler_entries(
451 struct MHD_Connection *connection,
452 void *connection_cls) {
453
454 _cleanup_(MHD_destroy_responsep)__attribute__((cleanup(MHD_destroy_responsep))) struct MHD_Response *response = NULL((void*)0);
455 RequestMeta *m = connection_cls;
456 int r;
457
458 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 458, __PRETTY_FUNCTION__); } while (0)
;
22
Taking false branch
23
Loop condition is false. Exiting loop
459 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 459, __PRETTY_FUNCTION__); } while (0)
;
24
Taking false branch
25
Loop condition is false. Exiting loop
460
461 r = open_journal(m);
462 if (r
25.1
'r' is >= 0
< 0)
26
Taking false branch
463 return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to open journal: %m");
464
465 if (request_parse_accept(m, connection) < 0)
27
Taking false branch
466 return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, "Failed to parse Accept header.");
467
468 if (request_parse_range(m, connection) < 0)
28
Calling 'request_parse_range'
469 return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, "Failed to parse Range header.");
470
471 if (request_parse_arguments(m, connection) < 0)
472 return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, "Failed to parse URL arguments.");
473
474 if (m->discrete) {
475 if (!m->cursor)
476 return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, "Discrete seeks require a cursor specification.");
477
478 m->n_entries = 1;
479 m->n_entries_set = true1;
480 }
481
482 if (m->cursor)
483 r = sd_journal_seek_cursor(m->journal, m->cursor);
484 else if (m->n_skip >= 0)
485 r = sd_journal_seek_head(m->journal);
486 else if (m->n_skip < 0)
487 r = sd_journal_seek_tail(m->journal);
488 if (r < 0)
489 return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, "Failed to seek in journal.");
490
491 response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN(18446744073709551615UL), 4*1024, request_reader_entries, m, NULL((void*)0));
492 if (!response)
493 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 493, __func__), mhd_respond_oom(connection)
;
494
495 MHD_add_response_header(response, "Content-Type", mime_types[m->mode]);
496 return MHD_queue_response(connection, MHD_HTTP_OK200, response);
497}
498
499static int output_field(FILE *f, OutputMode m, const char *d, size_t l) {
500 const char *eq;
501 size_t j;
502
503 eq = memchr(d, '=', l);
504 if (!eq)
505 return -EINVAL22;
506
507 j = l - (eq - d + 1);
508
509 if (m == OUTPUT_JSON) {
510 fprintf(f, "{ \"%.*s\" : ", (int) (eq - d), d);
511 json_escape(f, eq+1, j, OUTPUT_FULL_WIDTH);
512 fputs(" }\n", f);
513 } else {
514 fwrite(eq+1, 1, j, f);
515 fputc('\n', f);
516 }
517
518 return 0;
519}
520
521static ssize_t request_reader_fields(
522 void *cls,
523 uint64_t pos,
524 char *buf,
525 size_t max) {
526
527 RequestMeta *m = cls;
528 int r;
529 size_t n, k;
530
531 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 531, __PRETTY_FUNCTION__); } while (0)
;
532 assert(buf)do { if ((__builtin_expect(!!(!(buf)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("buf"), "../src/journal-remote/journal-gatewayd.c"
, 532, __PRETTY_FUNCTION__); } while (0)
;
533 assert(max > 0)do { if ((__builtin_expect(!!(!(max > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("max > 0"), "../src/journal-remote/journal-gatewayd.c"
, 533, __PRETTY_FUNCTION__); } while (0)
;
534 assert(pos >= m->delta)do { if ((__builtin_expect(!!(!(pos >= m->delta)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pos >= m->delta"), "../src/journal-remote/journal-gatewayd.c"
, 534, __PRETTY_FUNCTION__); } while (0)
;
535
536 pos -= m->delta;
537
538 while (pos >= m->size) {
539 off_t sz;
540 const void *d;
541 size_t l;
542
543 /* End of this field, so let's serialize the next
544 * one */
545
546 if (m->n_fields_set &&
547 m->n_fields <= 0)
548 return MHD_CONTENT_READER_END_OF_STREAM(18446744073709551615UL);
549
550 r = sd_journal_enumerate_unique(m->journal, &d, &l);
551 if (r < 0) {
552 log_error_errno(r, "Failed to advance field index: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 552, __func__, "Failed to advance field index: %m"
) : -abs(_e); })
;
553 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
554 } else if (r == 0)
555 return MHD_CONTENT_READER_END_OF_STREAM(18446744073709551615UL);
556
557 pos -= m->size;
558 m->delta += m->size;
559
560 if (m->n_fields_set)
561 m->n_fields -= 1;
562
563 r = request_meta_ensure_tmp(m);
564 if (r < 0) {
565 log_error_errno(r, "Failed to create temporary file: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 565, __func__, "Failed to create temporary file: %m"
) : -abs(_e); })
;
566 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
567 }
568
569 r = output_field(m->tmp, m->mode, d, l);
570 if (r < 0) {
571 log_error_errno(r, "Failed to serialize item: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 571, __func__, "Failed to serialize item: %m"
) : -abs(_e); })
;
572 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
573 }
574
575 sz = ftello(m->tmp);
576 if (sz == (off_t) -1) {
577 log_error_errno(errno, "Failed to retrieve file position: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/journal-remote/journal-gatewayd.c"
, 577, __func__, "Failed to retrieve file position: %m") : -abs
(_e); })
;
578 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
579 }
580
581 m->size = (uint64_t) sz;
582 }
583
584 if (fseeko(m->tmp, pos, SEEK_SET0) < 0) {
585 log_error_errno(errno, "Failed to seek to position: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/journal-remote/journal-gatewayd.c"
, 585, __func__, "Failed to seek to position: %m") : -abs(_e)
; })
;
586 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
587 }
588
589 n = m->size - pos;
590 if (n > max)
591 n = max;
592
593 errno(*__errno_location ()) = 0;
594 k = fread(buf, 1, n, m->tmp);
595 if (k != n) {
596 log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 596, __func__, "Failed to read from file: %s"
, (*__errno_location ()) ? strerror((*__errno_location ())) :
"Premature EOF") : -abs(_e); })
;
597 return MHD_CONTENT_READER_END_WITH_ERROR((18446744073709551615UL) - 1);
598 }
599
600 return (ssize_t) k;
601}
602
603static int request_handler_fields(
604 struct MHD_Connection *connection,
605 const char *field,
606 void *connection_cls) {
607
608 _cleanup_(MHD_destroy_responsep)__attribute__((cleanup(MHD_destroy_responsep))) struct MHD_Response *response = NULL((void*)0);
609 RequestMeta *m = connection_cls;
610 int r;
611
612 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 612, __PRETTY_FUNCTION__); } while (0)
;
613 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 613, __PRETTY_FUNCTION__); } while (0)
;
614
615 r = open_journal(m);
616 if (r < 0)
617 return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to open journal: %m");
618
619 if (request_parse_accept(m, connection) < 0)
620 return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, "Failed to parse Accept header.");
621
622 r = sd_journal_query_unique(m->journal, field);
623 if (r < 0)
624 return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, "Failed to query unique fields.");
625
626 response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN(18446744073709551615UL), 4*1024, request_reader_fields, m, NULL((void*)0));
627 if (!response)
628 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 628, __func__), mhd_respond_oom(connection)
;
629
630 MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]);
631 return MHD_queue_response(connection, MHD_HTTP_OK200, response);
632}
633
634static int request_handler_redirect(
635 struct MHD_Connection *connection,
636 const char *target) {
637
638 char *page;
639 _cleanup_(MHD_destroy_responsep)__attribute__((cleanup(MHD_destroy_responsep))) struct MHD_Response *response = NULL((void*)0);
640
641 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 641, __PRETTY_FUNCTION__); } while (0)
;
642 assert(target)do { if ((__builtin_expect(!!(!(target)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("target"), "../src/journal-remote/journal-gatewayd.c"
, 642, __PRETTY_FUNCTION__); } while (0)
;
643
644 if (asprintf(&page, "<html><body>Please continue to the <a href=\"%s\">journal browser</a>.</body></html>", target) < 0)
645 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 645, __func__), mhd_respond_oom(connection)
;
646
647 response = MHD_create_response_from_buffer(strlen(page), page, MHD_RESPMEM_MUST_FREE);
648 if (!response) {
649 free(page);
650 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 650, __func__), mhd_respond_oom(connection)
;
651 }
652
653 MHD_add_response_header(response, "Content-Type", "text/html");
654 MHD_add_response_header(response, "Location", target);
655 return MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY301, response);
656}
657
658static int request_handler_file(
659 struct MHD_Connection *connection,
660 const char *path,
661 const char *mime_type) {
662
663 _cleanup_(MHD_destroy_responsep)__attribute__((cleanup(MHD_destroy_responsep))) struct MHD_Response *response = NULL((void*)0);
664 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
665 struct stat st;
666
667 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 667, __PRETTY_FUNCTION__); } while (0)
;
668 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/journal-remote/journal-gatewayd.c"
, 668, __PRETTY_FUNCTION__); } while (0)
;
669 assert(mime_type)do { if ((__builtin_expect(!!(!(mime_type)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("mime_type"), "../src/journal-remote/journal-gatewayd.c"
, 669, __PRETTY_FUNCTION__); } while (0)
;
670
671 fd = open(path, O_RDONLY00|O_CLOEXEC02000000);
672 if (fd < 0)
673 return mhd_respondf(connection, errno(*__errno_location ()), MHD_HTTP_NOT_FOUND404, "Failed to open file %s: %m", path);
674
675 if (fstat(fd, &st) < 0)
676 return mhd_respondf(connection, errno(*__errno_location ()), MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to stat file: %m");
677
678 response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0);
679 if (!response)
680 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 680, __func__), mhd_respond_oom(connection)
;
681 TAKE_FD(fd)({ int _fd_ = (fd); (fd) = -1; _fd_; });
682
683 MHD_add_response_header(response, "Content-Type", mime_type);
684 return MHD_queue_response(connection, MHD_HTTP_OK200, response);
685}
686
687static int get_virtualization(char **v) {
688 _cleanup_(sd_bus_unrefp)__attribute__((cleanup(sd_bus_unrefp))) sd_bus *bus = NULL((void*)0);
689 char *b = NULL((void*)0);
690 int r;
691
692 r = sd_bus_default_system(&bus);
693 if (r < 0)
694 return r;
695
696 r = sd_bus_get_property_string(
697 bus,
698 "org.freedesktop.systemd1",
699 "/org/freedesktop/systemd1",
700 "org.freedesktop.systemd1.Manager",
701 "Virtualization",
702 NULL((void*)0),
703 &b);
704 if (r < 0)
705 return r;
706
707 if (isempty(b)) {
708 free(b);
709 *v = NULL((void*)0);
710 return 0;
711 }
712
713 *v = b;
714 return 1;
715}
716
717static int request_handler_machine(
718 struct MHD_Connection *connection,
719 void *connection_cls) {
720
721 _cleanup_(MHD_destroy_responsep)__attribute__((cleanup(MHD_destroy_responsep))) struct MHD_Response *response = NULL((void*)0);
722 RequestMeta *m = connection_cls;
723 int r;
724 _cleanup_free___attribute__((cleanup(freep))) char* hostname = NULL((void*)0), *os_name = NULL((void*)0);
725 uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0;
726 sd_id128_t mid, bid;
727 _cleanup_free___attribute__((cleanup(freep))) char *v = NULL((void*)0), *json = NULL((void*)0);
728
729 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 729, __PRETTY_FUNCTION__); } while (0)
;
730 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/journal-remote/journal-gatewayd.c"
, 730, __PRETTY_FUNCTION__); } while (0)
;
731
732 r = open_journal(m);
733 if (r < 0)
734 return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to open journal: %m");
735
736 r = sd_id128_get_machine(&mid);
737 if (r < 0)
738 return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to determine machine ID: %m");
739
740 r = sd_id128_get_boot(&bid);
741 if (r < 0)
742 return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to determine boot ID: %m");
743
744 hostname = gethostname_malloc();
745 if (!hostname)
746 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 746, __func__), mhd_respond_oom(connection)
;
747
748 r = sd_journal_get_usage(m->journal, &usage);
749 if (r < 0)
750 return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to determine disk usage: %m");
751
752 r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to);
753 if (r < 0)
754 return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "Failed to determine disk usage: %m");
755
756 (void) parse_os_release(NULL((void*)0), "PRETTY_NAME", &os_name, NULL((void*)0));
757 (void) get_virtualization(&v);
758
759 r = asprintf(&json,
760 "{ \"machine_id\" : \"" SD_ID128_FORMAT_STR"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "\","
761 "\"boot_id\" : \"" SD_ID128_FORMAT_STR"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "\","
762 "\"hostname\" : \"%s\","
763 "\"os_pretty_name\" : \"%s\","
764 "\"virtualization\" : \"%s\","
765 "\"usage\" : \"%"PRIu64"l" "u""\","
766 "\"cutoff_from_realtime\" : \"%"PRIu64"l" "u""\","
767 "\"cutoff_to_realtime\" : \"%"PRIu64"l" "u""\" }\n",
768 SD_ID128_FORMAT_VAL(mid)(mid).bytes[0], (mid).bytes[1], (mid).bytes[2], (mid).bytes[3
], (mid).bytes[4], (mid).bytes[5], (mid).bytes[6], (mid).bytes
[7], (mid).bytes[8], (mid).bytes[9], (mid).bytes[10], (mid).bytes
[11], (mid).bytes[12], (mid).bytes[13], (mid).bytes[14], (mid
).bytes[15]
,
769 SD_ID128_FORMAT_VAL(bid)(bid).bytes[0], (bid).bytes[1], (bid).bytes[2], (bid).bytes[3
], (bid).bytes[4], (bid).bytes[5], (bid).bytes[6], (bid).bytes
[7], (bid).bytes[8], (bid).bytes[9], (bid).bytes[10], (bid).bytes
[11], (bid).bytes[12], (bid).bytes[13], (bid).bytes[14], (bid
).bytes[15]
,
770 hostname_cleanup(hostname),
771 os_name ? os_name : "Linux",
772 v ? v : "bare",
773 usage,
774 cutoff_from,
775 cutoff_to);
776 if (r < 0)
777 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 777, __func__), mhd_respond_oom(connection)
;
778
779 response = MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE);
780 if (!response)
781 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 781, __func__), mhd_respond_oom(connection)
;
782 TAKE_PTR(json)({ typeof(json) _ptr_ = (json); (json) = ((void*)0); _ptr_; }
)
;
783
784 MHD_add_response_header(response, "Content-Type", "application/json");
785 return MHD_queue_response(connection, MHD_HTTP_OK200, response);
786}
787
788static mhd_resultenum MHD_Result request_handler(
789 void *cls,
790 struct MHD_Connection *connection,
791 const char *url,
792 const char *method,
793 const char *version,
794 const char *upload_data,
795 size_t *upload_data_size,
796 void **connection_cls) {
797 int r, code;
798
799 assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-gatewayd.c"
, 799, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'connection' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
800 assert(connection_cls)do { if ((__builtin_expect(!!(!(connection_cls)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("connection_cls"), "../src/journal-remote/journal-gatewayd.c"
, 800, __PRETTY_FUNCTION__); } while (0)
;
4
Assuming 'connection_cls' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
801 assert(url)do { if ((__builtin_expect(!!(!(url)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("url"), "../src/journal-remote/journal-gatewayd.c"
, 801, __PRETTY_FUNCTION__); } while (0)
;
7
Assuming 'url' is non-null
8
Taking false branch
9
Loop condition is false. Exiting loop
802 assert(method)do { if ((__builtin_expect(!!(!(method)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("method"), "../src/journal-remote/journal-gatewayd.c"
, 802, __PRETTY_FUNCTION__); } while (0)
;
10
Assuming 'method' is non-null
11
Taking false branch
12
Loop condition is false. Exiting loop
803
804 if (!streq(method, "GET")(strcmp((method),("GET")) == 0))
13
Taking false branch
805 return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE406, "Unsupported method.");
806
807 if (!*connection_cls) {
14
Assuming the condition is false
15
Taking false branch
808 if (!request_meta(connection_cls))
809 return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-gatewayd.c"
, 809, __func__), mhd_respond_oom(connection)
;
810 return MHD_YES;
811 }
812
813 if (arg_trust_pem) {
16
Assuming 'arg_trust_pem' is null
17
Taking false branch
814 r = check_permissions(connection, &code, NULL((void*)0));
815 if (r < 0)
816 return code;
817 }
818
819 if (streq(url, "/")(strcmp((url),("/")) == 0))
18
Assuming the condition is false
19
Taking false branch
820 return request_handler_redirect(connection, "/browse");
821
822 if (streq(url, "/entries")(strcmp((url),("/entries")) == 0))
20
Taking true branch
823 return request_handler_entries(connection, *connection_cls);
21
Calling 'request_handler_entries'
824
825 if (startswith(url, "/fields/"))
826 return request_handler_fields(connection, url + 8, *connection_cls);
827
828 if (streq(url, "/browse")(strcmp((url),("/browse")) == 0))
829 return request_handler_file(connection, DOCUMENT_ROOT"/usr/share/systemd/gatewayd" "/browse.html", "text/html");
830
831 if (streq(url, "/machine")(strcmp((url),("/machine")) == 0))
832 return request_handler_machine(connection, *connection_cls);
833
834 return mhd_respond(connection, MHD_HTTP_NOT_FOUND404, "Not found.");
835}
836
837static void help(void) {
838 printf("%s [OPTIONS...] ...\n\n"
839 "HTTP server for journal events.\n\n"
840 " -h --help Show this help\n"
841 " --version Show package version\n"
842 " --cert=CERT.PEM Server certificate in PEM format\n"
843 " --key=KEY.PEM Server key in PEM format\n"
844 " --trust=CERT.PEM Certificate authority certificate in PEM format\n"
845 " -D --directory=PATH Serve journal files in directory\n",
846 program_invocation_short_name);
847}
848
849static int parse_argv(int argc, char *argv[]) {
850 enum {
851 ARG_VERSION = 0x100,
852 ARG_KEY,
853 ARG_CERT,
854 ARG_TRUST,
855 };
856
857 int r, c;
858
859 static const struct option options[] = {
860 { "help", no_argument0, NULL((void*)0), 'h' },
861 { "version", no_argument0, NULL((void*)0), ARG_VERSION },
862 { "key", required_argument1, NULL((void*)0), ARG_KEY },
863 { "cert", required_argument1, NULL((void*)0), ARG_CERT },
864 { "trust", required_argument1, NULL((void*)0), ARG_TRUST },
865 { "directory", required_argument1, NULL((void*)0), 'D' },
866 {}
867 };
868
869 assert(argc >= 0)do { if ((__builtin_expect(!!(!(argc >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argc >= 0"), "../src/journal-remote/journal-gatewayd.c"
, 869, __PRETTY_FUNCTION__); } while (0)
;
870 assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argv"), "../src/journal-remote/journal-gatewayd.c"
, 870, __PRETTY_FUNCTION__); } while (0)
;
871
872 while ((c = getopt_long(argc, argv, "hD:", options, NULL((void*)0))) >= 0)
873
874 switch(c) {
875
876 case 'h':
877 help();
878 return 0;
879
880 case ARG_VERSION:
881 return version();
882
883 case ARG_KEY:
884 if (arg_key_pem) {
885 log_error("Key file specified twice")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 885, __func__, "Key file specified twice"
) : -abs(_e); })
;
886 return -EINVAL22;
887 }
888 r = read_full_file(optarg, &arg_key_pem, NULL((void*)0));
889 if (r < 0)
890 return log_error_errno(r, "Failed to read key file: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 890, __func__, "Failed to read key file: %m"
) : -abs(_e); })
;
891 assert(arg_key_pem)do { if ((__builtin_expect(!!(!(arg_key_pem)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("arg_key_pem"), "../src/journal-remote/journal-gatewayd.c"
, 891, __PRETTY_FUNCTION__); } while (0)
;
892 break;
893
894 case ARG_CERT:
895 if (arg_cert_pem) {
896 log_error("Certificate file specified twice")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 896, __func__, "Certificate file specified twice"
) : -abs(_e); })
;
897 return -EINVAL22;
898 }
899 r = read_full_file(optarg, &arg_cert_pem, NULL((void*)0));
900 if (r < 0)
901 return log_error_errno(r, "Failed to read certificate file: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 901, __func__, "Failed to read certificate file: %m"
) : -abs(_e); })
;
902 assert(arg_cert_pem)do { if ((__builtin_expect(!!(!(arg_cert_pem)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("arg_cert_pem"), "../src/journal-remote/journal-gatewayd.c"
, 902, __PRETTY_FUNCTION__); } while (0)
;
903 break;
904
905 case ARG_TRUST:
906#if HAVE_GNUTLS1
907 if (arg_trust_pem) {
908 log_error("CA certificate file specified twice")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 908, __func__, "CA certificate file specified twice"
) : -abs(_e); })
;
909 return -EINVAL22;
910 }
911 r = read_full_file(optarg, &arg_trust_pem, NULL((void*)0));
912 if (r < 0)
913 return log_error_errno(r, "Failed to read CA certificate file: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 913, __func__, "Failed to read CA certificate file: %m"
) : -abs(_e); })
;
914 assert(arg_trust_pem)do { if ((__builtin_expect(!!(!(arg_trust_pem)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("arg_trust_pem"), "../src/journal-remote/journal-gatewayd.c"
, 914, __PRETTY_FUNCTION__); } while (0)
;
915 break;
916#else
917 log_error("Option --trust is not available.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 917, __func__, "Option --trust is not available."
) : -abs(_e); })
;
918 return -EINVAL22;
919#endif
920 case 'D':
921 arg_directory = optarg;
922 break;
923
924 case '?':
925 return -EINVAL22;
926
927 default:
928 assert_not_reached("Unhandled option")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unhandled option"), "../src/journal-remote/journal-gatewayd.c"
, 928, __PRETTY_FUNCTION__); } while (0)
;
929 }
930
931 if (optind < argc) {
932 log_error("This program does not take arguments.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 932, __func__, "This program does not take arguments."
) : -abs(_e); })
;
933 return -EINVAL22;
934 }
935
936 if (!!arg_key_pem != !!arg_cert_pem) {
937 log_error("Certificate and key files must be specified together")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 937, __func__, "Certificate and key files must be specified together"
) : -abs(_e); })
;
938 return -EINVAL22;
939 }
940
941 if (arg_trust_pem && !arg_key_pem) {
942 log_error("CA certificate can only be used with certificate file")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 942, __func__, "CA certificate can only be used with certificate file"
) : -abs(_e); })
;
943 return -EINVAL22;
944 }
945
946 return 1;
947}
948
949int main(int argc, char *argv[]) {
950 struct MHD_Daemon *d = NULL((void*)0);
951 int r, n;
952
953 log_set_target(LOG_TARGET_AUTO);
954 log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD);
955 log_open();
956
957 r = parse_argv(argc, argv);
958 if (r < 0)
959 return EXIT_FAILURE1;
960 if (r == 0)
961 return EXIT_SUCCESS0;
962
963 sigbus_install();
964
965 r = setup_gnutls_logger(NULL((void*)0));
966 if (r < 0)
967 return EXIT_FAILURE1;
968
969 n = sd_listen_fds(1);
970 if (n < 0) {
971 log_error_errno(n, "Failed to determine passed sockets: %m")({ int _level = ((3)), _e = ((n)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 971, __func__, "Failed to determine passed sockets: %m"
) : -abs(_e); })
;
972 goto finish;
973 } else if (n > 1) {
974 log_error("Can't listen on more than one socket.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 974, __func__, "Can't listen on more than one socket."
) : -abs(_e); })
;
975 goto finish;
976 } else {
977 struct MHD_OptionItem opts[] = {
978 { MHD_OPTION_NOTIFY_COMPLETED,
979 (intptr_t) request_meta_free, NULL((void*)0) },
980 { MHD_OPTION_EXTERNAL_LOGGER,
981 (intptr_t) microhttpd_logger, NULL((void*)0) },
982 { MHD_OPTION_END, 0, NULL((void*)0) },
983 { MHD_OPTION_END, 0, NULL((void*)0) },
984 { MHD_OPTION_END, 0, NULL((void*)0) },
985 { MHD_OPTION_END, 0, NULL((void*)0) },
986 { MHD_OPTION_END, 0, NULL((void*)0) }};
987 int opts_pos = 2;
988
989 /* We force MHD_USE_ITC here, in order to make sure
990 * libmicrohttpd doesn't use shutdown() on our listening
991 * socket, which would break socket re-activation. See
992 *
993 * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html
994 * https://github.com/systemd/systemd/pull/1286
995 */
996
997 int flags =
998 MHD_USE_DEBUG |
999 MHD_USE_DUAL_STACK |
1000 MHD_USE_ITCMHD_USE_PIPE_FOR_SHUTDOWN |
1001 MHD_USE_POLL_INTERNAL_THREADMHD_USE_POLL_INTERNALLY |
1002 MHD_USE_THREAD_PER_CONNECTION;
1003
1004 if (n > 0)
1005 opts[opts_pos++] = (struct MHD_OptionItem)
1006 {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START3};
1007 if (arg_key_pem) {
1008 assert(arg_cert_pem)do { if ((__builtin_expect(!!(!(arg_cert_pem)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("arg_cert_pem"), "../src/journal-remote/journal-gatewayd.c"
, 1008, __PRETTY_FUNCTION__); } while (0)
;
1009 opts[opts_pos++] = (struct MHD_OptionItem)
1010 {MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem};
1011 opts[opts_pos++] = (struct MHD_OptionItem)
1012 {MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem};
1013 flags |= MHD_USE_TLSMHD_USE_SSL;
1014 }
1015 if (arg_trust_pem) {
1016 assert(flags & MHD_USE_TLS)do { if ((__builtin_expect(!!(!(flags & MHD_USE_SSL)),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("flags & MHD_USE_TLS"
), "../src/journal-remote/journal-gatewayd.c", 1016, __PRETTY_FUNCTION__
); } while (0)
;
1017 opts[opts_pos++] = (struct MHD_OptionItem)
1018 {MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem};
1019 }
1020
1021 d = MHD_start_daemon(flags, 19531,
1022 NULL((void*)0), NULL((void*)0),
1023 request_handler, NULL((void*)0),
1024 MHD_OPTION_ARRAY, opts,
1025 MHD_OPTION_END);
1026 }
1027
1028 if (!d) {
1029 log_error("Failed to start daemon!")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-gatewayd.c", 1029, __func__,
"Failed to start daemon!") : -abs(_e); })
;
1030 goto finish;
1031 }
1032
1033 pause();
1034
1035 r = EXIT_SUCCESS0;
1036
1037finish:
1038 if (d)
1039 MHD_stop_daemon(d);
1040
1041 return r;
1042}