Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/logsrvd/logsrvd_journal.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2021-2022 Todd C. Miller <[email protected]>
5
*
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
9
*
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <config.h>
20
21
#include <sys/stat.h>
22
#include <sys/types.h>
23
#include <sys/socket.h>
24
#include <netinet/in.h>
25
#include <netinet/tcp.h>
26
#include <arpa/inet.h>
27
28
#include <errno.h>
29
#include <fcntl.h>
30
#include <limits.h>
31
#ifdef HAVE_STDBOOL_H
32
# include <stdbool.h>
33
#else
34
# include <compat/stdbool.h>
35
#endif /* HAVE_STDBOOL_H */
36
#if defined(HAVE_STDINT_H)
37
# include <stdint.h>
38
#elif defined(HAVE_INTTYPES_H)
39
# include <inttypes.h>
40
#endif
41
#include <stdio.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <time.h>
45
#include <unistd.h>
46
47
#include <sudo_compat.h>
48
#include <sudo_conf.h>
49
#include <sudo_debug.h>
50
#include <sudo_event.h>
51
#include <sudo_eventlog.h>
52
#include <sudo_fatal.h>
53
#include <sudo_gettext.h>
54
#include <sudo_iolog.h>
55
#include <sudo_util.h>
56
57
#include <logsrvd.h>
58
59
/*
60
* Helper function to set closure->journal and closure->journal_path.
61
*/
62
static bool
63
journal_fdopen(int fd, const char *journal_path,
64
struct connection_closure *closure)
65
{
66
debug_decl(journal_fdopen, SUDO_DEBUG_UTIL);
67
68
free(closure->journal_path);
69
closure->journal_path = strdup(journal_path);
70
if (closure->journal_path == NULL) {
71
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
72
debug_return_bool(false);
73
}
74
75
/* Defer fdopen() until last--it cannot be undone. */
76
if (closure->journal != NULL)
77
fclose(closure->journal);
78
if ((closure->journal = fdopen(fd, "r+")) == NULL) {
79
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
80
"unable to fdopen journal file %s", journal_path);
81
free(closure->journal_path);
82
closure->journal_path = NULL;
83
debug_return_bool(false);
84
}
85
86
debug_return_bool(true);
87
}
88
89
static int
90
journal_mkuuid(const char *parent_dir, char *pathbuf, size_t pathsize)
91
{
92
int len, dfd = -1, fd = -1;
93
mode_t dirmode, oldmask;
94
unsigned char uuid[16];
95
char uuid_str[37];
96
debug_decl(journal_mkuuid, SUDO_DEBUG_UTIL);
97
98
/* umask must not be more restrictive than the file modes. */
99
dirmode = logsrvd_conf_iolog_mode() | S_IXUSR;
100
if (dirmode & (S_IRGRP|S_IWGRP))
101
dirmode |= S_IXGRP;
102
if (dirmode & (S_IROTH|S_IWOTH))
103
dirmode |= S_IXOTH;
104
oldmask = umask(ACCESSPERMS & ~dirmode);
105
106
do {
107
sudo_uuid_create(uuid);
108
if (sudo_uuid_to_string(uuid, uuid_str, sizeof(uuid_str)) == NULL) {
109
sudo_warnx("%s", U_("unable to generate UUID"));
110
goto done;
111
}
112
113
len = snprintf(pathbuf, pathsize, "%s/%s/%s",
114
logsrvd_conf_relay_dir(), parent_dir, uuid_str);
115
if ((size_t)len >= pathsize) {
116
errno = ENAMETOOLONG;
117
sudo_warn("%s/%s/%s",
118
logsrvd_conf_relay_dir(), parent_dir, uuid_str);
119
goto done;
120
}
121
if (dfd == -1) {
122
dfd = sudo_open_parent_dir(pathbuf, logsrvd_conf_iolog_uid(),
123
logsrvd_conf_iolog_gid(), S_IRWXU|S_IXGRP|S_IXOTH, false);
124
if (dfd == -1) {
125
sudo_debug_printf(
126
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
127
"unable to create parent dir for %s", pathbuf);
128
goto done;
129
}
130
}
131
fd = openat(dfd, uuid_str, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
132
} while (fd == -1 && errno == EEXIST);
133
if (fd == -1) {
134
sudo_warn(U_("%s: %s"), "openat", pathbuf);
135
goto done;
136
}
137
138
done:
139
umask(oldmask);
140
if (dfd != -1)
141
close(dfd);
142
143
debug_return_int(fd);
144
}
145
146
/*
147
* Create a temporary file in the relay dir and store it in the closure.
148
*/
149
static bool
150
journal_create(struct connection_closure *closure)
151
{
152
char journal_path[PATH_MAX];
153
int fd;
154
debug_decl(journal_create, SUDO_DEBUG_UTIL);
155
156
fd = journal_mkuuid("incoming", journal_path, sizeof(journal_path));
157
if (fd == -1) {
158
closure->errstr = _("unable to create journal file");
159
debug_return_bool(false);
160
}
161
if (!sudo_lock_file(fd, SUDO_TLOCK)) {
162
sudo_warn(U_("unable to lock %s"), journal_path);
163
unlink(journal_path);
164
close(fd);
165
closure->errstr = _("unable to lock journal file");
166
debug_return_bool(false);
167
}
168
if (!journal_fdopen(fd, journal_path, closure)) {
169
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
170
"unable to fdopen journal file %s", journal_path);
171
unlink(journal_path);
172
close(fd);
173
closure->errstr = _("unable to open journal file");
174
debug_return_bool(false);
175
}
176
177
debug_return_bool(true);
178
}
179
180
/*
181
* Flush any buffered data, rewind journal to the beginning and
182
* move to the outgoing directory.
183
* The actual open file is closed in connection_closure_free().
184
*/
185
static bool
186
journal_finish(struct connection_closure *closure)
187
{
188
char outgoing_path[PATH_MAX];
189
size_t len;
190
int fd;
191
debug_decl(journal_finish, SUDO_DEBUG_UTIL);
192
193
if (fflush(closure->journal) != 0) {
194
closure->errstr = _("unable to write journal file");
195
debug_return_bool(false);
196
}
197
rewind(closure->journal);
198
199
/* Move journal to the outgoing directory. */
200
fd = journal_mkuuid("outgoing", outgoing_path, sizeof(outgoing_path));
201
if (fd == -1) {
202
closure->errstr = _("unable to rename journal file");
203
debug_return_bool(false);
204
}
205
close(fd);
206
if (rename(closure->journal_path, outgoing_path) == -1) {
207
sudo_warn(U_("unable to rename %s to %s"), closure->journal_path,
208
outgoing_path);
209
closure->errstr = _("unable to rename journal file");
210
unlink(outgoing_path);
211
debug_return_bool(false);
212
}
213
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
214
"renamed %s -> %s", closure->journal_path, outgoing_path);
215
len = strlen(outgoing_path);
216
if (strlen(closure->journal_path) == len) {
217
/* This should always be true. */
218
memcpy(closure->journal_path, outgoing_path, len);
219
} else {
220
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
221
"length mismatch %zu != %zu", strlen(closure->journal_path), len);
222
free(closure->journal_path);
223
closure->journal_path = strdup(outgoing_path);
224
if (closure->journal_path == NULL) {
225
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
226
closure->errstr = _("unable to allocate memory");
227
debug_return_bool(false);
228
}
229
}
230
231
debug_return_bool(true);
232
}
233
234
/*
235
* Seek ahead in the journal to the specified target time.
236
* Returns true if we reached the target time exactly, else false.
237
*/
238
static bool
239
journal_seek(const struct timespec *target, struct connection_closure *closure)
240
{
241
ClientMessage *msg = NULL;
242
size_t nread, bufsize = 0;
243
uint8_t *buf = NULL;
244
uint32_t msg_len;
245
bool ret = false;
246
debug_decl(journal_seek, SUDO_DEBUG_UTIL);
247
248
for (;;) {
249
TimeSpec *delay = NULL;
250
251
/* Read message size (uint32_t in network byte order). */
252
nread = fread(&msg_len, sizeof(msg_len), 1, closure->journal);
253
if (nread != 1) {
254
if (feof(closure->journal)) {
255
sudo_warnx(U_("%s: %s"), closure->journal_path,
256
U_("unexpected EOF reading journal file"));
257
closure->errstr = _("unexpected EOF reading journal file");
258
} else {
259
sudo_warn(U_("%s: %s"), closure->journal_path,
260
U_("error reading journal file"));
261
closure->errstr = _("error reading journal file");
262
}
263
break;
264
}
265
msg_len = ntohl(msg_len);
266
if (msg_len > MESSAGE_SIZE_MAX) {
267
sudo_warnx(U_("%s: %s"), closure->journal_path,
268
U_("client message too large"));
269
closure->errstr = _("client message too large");
270
break;
271
}
272
273
/* Read actual message now that we know the size. */
274
if (msg_len != 0) {
275
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
276
"%s: reading message %u bytes", closure->journal_path, msg_len);
277
278
if (msg_len > bufsize) {
279
bufsize = sudo_pow2_roundup(msg_len);
280
if (bufsize < msg_len) {
281
/* overflow */
282
errno = ENOMEM;
283
closure->errstr = _("unable to allocate memory");
284
break;
285
}
286
free(buf);
287
if ((buf = malloc(bufsize)) == NULL) {
288
closure->errstr = _("unable to allocate memory");
289
break;
290
}
291
}
292
293
nread = fread(buf, msg_len, 1, closure->journal);
294
if (nread != 1) {
295
if (feof(closure->journal)) {
296
sudo_warnx(U_("%s: %s"), closure->journal_path,
297
U_("unexpected EOF reading journal file"));
298
closure->errstr = _("unexpected EOF reading journal file");
299
} else {
300
sudo_warn(U_("%s: %s"), closure->journal_path,
301
U_("error reading journal file"));
302
closure->errstr = _("error reading journal file");
303
}
304
break;
305
}
306
}
307
308
client_message__free_unpacked(msg, NULL);
309
msg = client_message__unpack(NULL, msg_len, buf);
310
if (msg == NULL) {
311
sudo_warnx(U_("unable to unpack %s size %zu"), "ClientMessage",
312
(size_t)msg_len);
313
closure->errstr = _("invalid journal file, unable to restart");
314
break;
315
}
316
317
switch (msg->type_case) {
318
case CLIENT_MESSAGE__TYPE_HELLO_MSG:
319
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
320
"seeking past ClientHello (%d)", msg->type_case);
321
break;
322
case CLIENT_MESSAGE__TYPE_ACCEPT_MSG:
323
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
324
"seeking past AcceptMessage (%d)", msg->type_case);
325
break;
326
case CLIENT_MESSAGE__TYPE_REJECT_MSG:
327
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
328
"seeking past RejectMessage (%d)", msg->type_case);
329
break;
330
case CLIENT_MESSAGE__TYPE_EXIT_MSG:
331
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
332
"seeking past ExitMessage (%d)", msg->type_case);
333
break;
334
case CLIENT_MESSAGE__TYPE_RESTART_MSG:
335
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
336
"seeking past RestartMessage (%d)", msg->type_case);
337
break;
338
case CLIENT_MESSAGE__TYPE_ALERT_MSG:
339
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
340
"seeking past AlertMessage (%d)", msg->type_case);
341
break;
342
case CLIENT_MESSAGE__TYPE_TTYIN_BUF:
343
if (msg->u.ttyin_buf == NULL ||
344
!valid_timespec(msg->u.ttyin_buf->delay)) {
345
sudo_warnx(U_("%s: %s"), closure->journal_path,
346
U_("invalid IoBuffer"));
347
closure->errstr = _("invalid IoBuffer");
348
goto done;
349
}
350
delay = msg->u.ttyin_buf->delay;
351
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
352
"read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
353
(long long)delay->tv_sec, (long)delay->tv_nsec);
354
break;
355
case CLIENT_MESSAGE__TYPE_TTYOUT_BUF:
356
if (msg->u.ttyout_buf == NULL ||
357
!valid_timespec(msg->u.ttyout_buf->delay)) {
358
sudo_warnx(U_("%s: %s"), closure->journal_path,
359
U_("invalid IoBuffer"));
360
closure->errstr = _("invalid IoBuffer");
361
goto done;
362
}
363
delay = msg->u.ttyout_buf->delay;
364
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
365
"read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
366
(long long)delay->tv_sec, (long)delay->tv_nsec);
367
break;
368
case CLIENT_MESSAGE__TYPE_STDIN_BUF:
369
if (msg->u.stdin_buf == NULL ||
370
!valid_timespec(msg->u.stdin_buf->delay)) {
371
sudo_warnx(U_("%s: %s"), closure->journal_path,
372
U_("invalid IoBuffer"));
373
closure->errstr = _("invalid IoBuffer");
374
goto done;
375
}
376
delay = msg->u.stdin_buf->delay;
377
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
378
"read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
379
(long long)delay->tv_sec, (long)delay->tv_nsec);
380
break;
381
case CLIENT_MESSAGE__TYPE_STDOUT_BUF:
382
if (msg->u.stdout_buf == NULL ||
383
!valid_timespec(msg->u.stdout_buf->delay)) {
384
sudo_warnx(U_("%s: %s"), closure->journal_path,
385
U_("invalid IoBuffer"));
386
closure->errstr = _("invalid IoBuffer");
387
goto done;
388
}
389
delay = msg->u.stdout_buf->delay;
390
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
391
"read stdout_buf (%d), delay [%lld, %ld]", msg->type_case,
392
(long long)delay->tv_sec, (long)delay->tv_nsec);
393
break;
394
case CLIENT_MESSAGE__TYPE_STDERR_BUF:
395
if (msg->u.stderr_buf == NULL ||
396
!valid_timespec(msg->u.stderr_buf->delay)) {
397
sudo_warnx(U_("%s: %s"), closure->journal_path,
398
U_("invalid IoBuffer"));
399
closure->errstr = _("invalid IoBuffer");
400
goto done;
401
}
402
delay = msg->u.stderr_buf->delay;
403
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
404
"read stderr_buf (%d), delay [%lld, %ld]", msg->type_case,
405
(long long)delay->tv_sec, (long)delay->tv_nsec);
406
break;
407
case CLIENT_MESSAGE__TYPE_WINSIZE_EVENT:
408
if (msg->u.winsize_event == NULL ||
409
!valid_timespec(msg->u.winsize_event->delay)) {
410
sudo_warnx(U_("%s: %s"), closure->journal_path,
411
U_("invalid ChangeWindowSize"));
412
closure->errstr = _("invalid ChangeWindowSize");
413
goto done;
414
}
415
delay = msg->u.winsize_event->delay;
416
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
417
"read ChangeWindowSize (%d), delay [%lld, %ld]", msg->type_case,
418
(long long)delay->tv_sec, (long)delay->tv_nsec);
419
break;
420
case CLIENT_MESSAGE__TYPE_SUSPEND_EVENT:
421
if (msg->u.suspend_event == NULL ||
422
!valid_timespec(msg->u.suspend_event->delay)) {
423
sudo_warnx(U_("%s: %s"), closure->journal_path,
424
U_("invalid invalid CommandSuspend"));
425
closure->errstr = _("invalid CommandSuspend");
426
goto done;
427
}
428
delay = msg->u.suspend_event->delay;
429
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
430
"read CommandSuspend (%d), delay [%lld, %ld]", msg->type_case,
431
(long long)delay->tv_sec, (long)delay->tv_nsec);
432
break;
433
default:
434
sudo_warnx(U_("unexpected type_case value %d in %s from %s"),
435
msg->type_case, "ClientMessage", closure->journal_path);
436
break;
437
}
438
if (delay != NULL)
439
update_elapsed_time(delay, &closure->elapsed_time);
440
441
if (sudo_timespeccmp(&closure->elapsed_time, target, >=)) {
442
if (sudo_timespeccmp(&closure->elapsed_time, target, ==)) {
443
ret = true;
444
break;
445
}
446
447
/* Mismatch between resume point and stored log. */
448
closure->errstr = _("invalid journal file, unable to restart");
449
sudo_warnx(U_("%s: unable to find resume point [%lld, %ld]"),
450
closure->journal_path, (long long)target->tv_sec,
451
target->tv_nsec);
452
break;
453
}
454
}
455
456
done:
457
client_message__free_unpacked(msg, NULL);
458
free(buf);
459
460
debug_return_bool(ret);
461
}
462
463
/*
464
* Restart an existing journal.
465
* Seeks to the resume_point in RestartMessage before continuing.
466
* Returns true if we reached the target time exactly, else false.
467
*/
468
static bool
469
journal_restart(const RestartMessage *msg, const uint8_t *buf, size_t buflen,
470
struct connection_closure *closure)
471
{
472
char uuid_str[37], journal_path[PATH_MAX];
473
unsigned char uuid[16];
474
struct timespec target;
475
int fd, len;
476
debug_decl(journal_restart, SUDO_DEBUG_UTIL);
477
478
/* A journal log_id must be a base64-encoded UUID. */
479
if (strlen(msg->log_id) != ((16 + 2) / 3 * 4))
480
goto parse_err;
481
if (sudo_base64_decode(msg->log_id, uuid, sizeof(uuid)) != sizeof(uuid))
482
goto parse_err;
483
if (sudo_uuid_to_string(uuid, uuid_str, sizeof(uuid_str)) == NULL) {
484
parse_err:
485
sudo_warnx(U_("%s: %s"), __func__, U_("unable to parse log_id"));
486
closure->errstr = _("unable to open journal file");
487
debug_return_bool(false);
488
}
489
490
/* Journal files are stored by UUID. */
491
len = snprintf(journal_path, sizeof(journal_path), "%s/incoming/%s",
492
logsrvd_conf_relay_dir(), uuid_str);
493
if (len >= ssizeof(journal_path)) {
494
errno = ENAMETOOLONG;
495
sudo_warn("%s/incoming/%s", logsrvd_conf_relay_dir(), uuid_str);
496
closure->errstr = _("unable to open journal file");
497
debug_return_bool(false);
498
}
499
if ((fd = open(journal_path, O_RDWR)) == -1) {
500
sudo_warn(U_("unable to open %s"), journal_path);
501
closure->errstr = _("unable to open journal file");
502
debug_return_bool(false);
503
}
504
if (!sudo_lock_file(fd, SUDO_TLOCK)) {
505
sudo_warn(U_("unable to lock %s"), journal_path);
506
close(fd);
507
closure->errstr = _("unable to lock journal file");
508
debug_return_bool(false);
509
}
510
if (!journal_fdopen(fd, journal_path, closure)) {
511
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
512
close(fd);
513
closure->errstr = _("unable to allocate memory");
514
debug_return_bool(false);
515
}
516
517
/* Seek forward to resume point. */
518
target.tv_sec = (time_t)msg->resume_point->tv_sec;
519
target.tv_nsec = (long)msg->resume_point->tv_nsec;
520
if (!journal_seek(&target, closure)) {
521
sudo_warn(U_("unable to seek to [%lld, %ld] in journal file %s"),
522
(long long)target.tv_sec, target.tv_nsec, journal_path);
523
debug_return_bool(false);
524
}
525
526
debug_return_bool(true);
527
}
528
529
static bool
530
journal_write(const uint8_t * restrict buf, size_t len,
531
struct connection_closure * restrict closure)
532
{
533
uint32_t msg_len;
534
debug_decl(journal_write, SUDO_DEBUG_UTIL);
535
536
/* 32-bit message length in network byte order. */
537
msg_len = htonl((uint32_t)len);
538
if (fwrite(&msg_len, 1, sizeof(msg_len), closure->journal) != sizeof(msg_len)) {
539
closure->errstr = _("unable to write journal file");
540
debug_return_bool(false);
541
}
542
/* message payload */
543
if (fwrite(buf, 1, len, closure->journal) != len) {
544
closure->errstr = _("unable to write journal file");
545
debug_return_bool(false);
546
}
547
debug_return_bool(true);
548
}
549
550
/*
551
* Store an AcceptMessage from the client in the journal.
552
*/
553
static bool
554
journal_accept(const AcceptMessage *msg, const uint8_t *buf, size_t len,
555
struct connection_closure *closure)
556
{
557
debug_decl(journal_accept, SUDO_DEBUG_UTIL);
558
559
if (closure->journal_path != NULL) {
560
/* Reuse existing journal file. */
561
debug_return_bool(journal_write(buf, len, closure));
562
}
563
564
/* Store message in a journal for later relaying. */
565
if (!journal_create(closure))
566
debug_return_bool(false);
567
if (!journal_write(buf, len, closure))
568
debug_return_bool(false);
569
570
if (msg->expect_iobufs) {
571
/* Send log ID to client for restarting connections. */
572
unsigned char uuid[16];
573
const char *uuid_str;
574
575
/* Journaled I/O log files are files stored by UUID. */
576
uuid_str = strrchr(closure->journal_path, '/');
577
if (uuid_str == NULL)
578
debug_return_bool(false);
579
uuid_str++;
580
581
/* Parse UUID and format as a log ID (base64-encoded). */
582
if (sudo_uuid_from_string(uuid_str, uuid) != 0)
583
debug_return_bool(false);
584
if (!fmt_log_id_message(uuid, "", closure))
585
debug_return_bool(false);
586
if (sudo_ev_add(closure->evbase, closure->write_ev,
587
logsrvd_conf_server_timeout(), false) == -1) {
588
sudo_warnx("%s", U_("unable to add event to queue"));
589
debug_return_bool(false);
590
}
591
}
592
593
debug_return_bool(true);
594
}
595
596
/*
597
* Store a RejectMessage from the client in the journal.
598
*/
599
static bool
600
journal_reject(const RejectMessage *msg, const uint8_t * restrict buf,
601
size_t len, struct connection_closure * restrict closure)
602
{
603
debug_decl(journal_reject, SUDO_DEBUG_UTIL);
604
605
/* Store message in a journal for later relaying. */
606
if (closure->journal_path == NULL) {
607
if (!journal_create(closure))
608
debug_return_bool(false);
609
}
610
if (!journal_write(buf, len, closure))
611
debug_return_bool(false);
612
613
debug_return_bool(true);
614
}
615
616
/*
617
* Store an ExitMessage from the client in the journal.
618
*/
619
static bool
620
journal_exit(const ExitMessage *msg, const uint8_t * restrict buf, size_t len,
621
struct connection_closure * restrict closure)
622
{
623
debug_decl(journal_exit, SUDO_DEBUG_UTIL);
624
625
/* Store exit message in journal. */
626
if (!journal_write(buf, len, closure))
627
debug_return_bool(false);
628
if (!journal_finish(closure))
629
debug_return_bool(false);
630
631
debug_return_bool(true);
632
}
633
634
/*
635
* Store an AlertMessage from the client in the journal.
636
*/
637
static bool
638
journal_alert(const AlertMessage *msg, const uint8_t * restrict buf, size_t len,
639
struct connection_closure * restrict closure)
640
{
641
debug_decl(journal_alert, SUDO_DEBUG_UTIL);
642
643
/* Store message in a journal for later relaying. */
644
if (closure->journal_path == NULL) {
645
if (!journal_create(closure))
646
debug_return_bool(false);
647
}
648
if (!journal_write(buf, len, closure))
649
debug_return_bool(false);
650
651
debug_return_bool(true);
652
}
653
654
/*
655
* Store an IoBuffer from the client in the journal.
656
*/
657
static bool
658
journal_iobuf(int iofd, const IoBuffer *iobuf, const uint8_t * restrict buf,
659
size_t len, struct connection_closure * restrict closure)
660
{
661
debug_decl(journal_iobuf, SUDO_DEBUG_UTIL);
662
663
if (!journal_write(buf, len, closure))
664
debug_return_bool(false);
665
update_elapsed_time(iobuf->delay, &closure->elapsed_time);
666
667
debug_return_bool(true);
668
}
669
670
/*
671
* Store a CommandSuspend message from the client in the journal.
672
*/
673
static bool
674
journal_suspend(const CommandSuspend *msg, const uint8_t * restrict buf,
675
size_t len, struct connection_closure * restrict closure)
676
{
677
debug_decl(journal_suspend, SUDO_DEBUG_UTIL);
678
679
update_elapsed_time(msg->delay, &closure->elapsed_time);
680
681
debug_return_bool(journal_write(buf, len, closure));
682
}
683
684
/*
685
* Store a ChangeWindowSize message from the client in the journal.
686
*/
687
static bool
688
journal_winsize(const ChangeWindowSize *msg, const uint8_t * restrict buf,
689
size_t len, struct connection_closure * restrict closure)
690
{
691
debug_decl(journal_winsize, SUDO_DEBUG_UTIL);
692
693
update_elapsed_time(msg->delay, &closure->elapsed_time);
694
695
debug_return_bool(journal_write(buf, len, closure));
696
}
697
698
struct client_message_switch cms_journal = {
699
journal_accept,
700
journal_reject,
701
journal_exit,
702
journal_restart,
703
journal_alert,
704
journal_iobuf,
705
journal_suspend,
706
journal_winsize
707
};
708
709