Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/logsrvd/logsrvd_journal.c
3871 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2021-2026 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|O_NOFOLLOW,
132
S_IRUSR|S_IWUSR);
133
} while (fd == -1 && errno == EEXIST);
134
if (fd == -1) {
135
sudo_warn(U_("%s: %s"), "openat", pathbuf);
136
goto done;
137
}
138
139
done:
140
umask(oldmask);
141
if (dfd != -1)
142
close(dfd);
143
144
debug_return_int(fd);
145
}
146
147
/*
148
* Create a temporary file in the relay dir and store it in the closure.
149
*/
150
static bool
151
journal_create(struct connection_closure *closure)
152
{
153
char journal_path[PATH_MAX];
154
int fd;
155
debug_decl(journal_create, SUDO_DEBUG_UTIL);
156
157
fd = journal_mkuuid("incoming", journal_path, sizeof(journal_path));
158
if (fd == -1) {
159
closure->errstr = _("unable to create journal file");
160
debug_return_bool(false);
161
}
162
if (!sudo_lock_file(fd, SUDO_TLOCK)) {
163
sudo_warn(U_("unable to lock %s"), journal_path);
164
unlink(journal_path);
165
close(fd);
166
closure->errstr = _("unable to lock journal file");
167
debug_return_bool(false);
168
}
169
if (!journal_fdopen(fd, journal_path, closure)) {
170
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
171
"unable to fdopen journal file %s", journal_path);
172
unlink(journal_path);
173
close(fd);
174
closure->errstr = _("unable to open journal file");
175
debug_return_bool(false);
176
}
177
178
debug_return_bool(true);
179
}
180
181
/*
182
* Flush any buffered data, rewind journal to the beginning and
183
* move to the outgoing directory.
184
* The actual open file is closed in connection_closure_free().
185
*/
186
static bool
187
journal_finish(struct connection_closure *closure)
188
{
189
char outgoing_path[PATH_MAX];
190
size_t len;
191
int fd;
192
debug_decl(journal_finish, SUDO_DEBUG_UTIL);
193
194
if (fflush(closure->journal) != 0) {
195
closure->errstr = _("unable to write journal file");
196
debug_return_bool(false);
197
}
198
rewind(closure->journal);
199
200
/* Move journal to the outgoing directory. */
201
fd = journal_mkuuid("outgoing", outgoing_path, sizeof(outgoing_path));
202
if (fd == -1) {
203
closure->errstr = _("unable to rename journal file");
204
debug_return_bool(false);
205
}
206
close(fd);
207
if (rename(closure->journal_path, outgoing_path) == -1) {
208
sudo_warn(U_("unable to rename %s to %s"), closure->journal_path,
209
outgoing_path);
210
closure->errstr = _("unable to rename journal file");
211
unlink(outgoing_path);
212
debug_return_bool(false);
213
}
214
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
215
"renamed %s -> %s", closure->journal_path, outgoing_path);
216
len = strlen(outgoing_path);
217
if (strlen(closure->journal_path) == len) {
218
/* This should always be true. */
219
memcpy(closure->journal_path, outgoing_path, len);
220
} else {
221
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
222
"length mismatch %zu != %zu", strlen(closure->journal_path), len);
223
free(closure->journal_path);
224
closure->journal_path = strdup(outgoing_path);
225
if (closure->journal_path == NULL) {
226
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
227
closure->errstr = _("unable to allocate memory");
228
debug_return_bool(false);
229
}
230
}
231
232
debug_return_bool(true);
233
}
234
235
/*
236
* Seek ahead in the journal to the specified target time.
237
* Returns true if we reached the target time exactly, else false.
238
*/
239
static bool
240
journal_seek(const struct timespec *target, struct connection_closure *closure)
241
{
242
ClientMessage *msg = NULL;
243
size_t nread, bufsize = 0;
244
uint8_t *buf = NULL;
245
uint32_t msg_len;
246
bool ret = false;
247
debug_decl(journal_seek, SUDO_DEBUG_UTIL);
248
249
for (;;) {
250
TimeSpec *delay = NULL;
251
252
/* Read message size (uint32_t in network byte order). */
253
nread = fread(&msg_len, sizeof(msg_len), 1, closure->journal);
254
if (nread != 1) {
255
if (feof(closure->journal)) {
256
sudo_warnx(U_("%s: %s"), closure->journal_path,
257
U_("unexpected EOF reading journal file"));
258
closure->errstr = _("unexpected EOF reading journal file");
259
} else {
260
sudo_warn(U_("%s: %s"), closure->journal_path,
261
U_("error reading journal file"));
262
closure->errstr = _("error reading journal file");
263
}
264
break;
265
}
266
msg_len = ntohl(msg_len);
267
if (msg_len > MESSAGE_SIZE_MAX) {
268
sudo_warnx(U_("%s: %s"), closure->journal_path,
269
U_("client message too large"));
270
closure->errstr = _("client message too large");
271
break;
272
}
273
274
/* Read actual message now that we know the size. */
275
if (msg_len != 0) {
276
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
277
"%s: reading message %u bytes", closure->journal_path, msg_len);
278
279
if (msg_len > bufsize) {
280
bufsize = sudo_pow2_roundup(msg_len);
281
if (bufsize < msg_len) {
282
/* overflow */
283
errno = ENOMEM;
284
closure->errstr = _("unable to allocate memory");
285
break;
286
}
287
free(buf);
288
if ((buf = malloc(bufsize)) == NULL) {
289
closure->errstr = _("unable to allocate memory");
290
break;
291
}
292
}
293
294
nread = fread(buf, msg_len, 1, closure->journal);
295
if (nread != 1) {
296
if (feof(closure->journal)) {
297
sudo_warnx(U_("%s: %s"), closure->journal_path,
298
U_("unexpected EOF reading journal file"));
299
closure->errstr = _("unexpected EOF reading journal file");
300
} else {
301
sudo_warn(U_("%s: %s"), closure->journal_path,
302
U_("error reading journal file"));
303
closure->errstr = _("error reading journal file");
304
}
305
break;
306
}
307
}
308
309
client_message__free_unpacked(msg, NULL);
310
msg = client_message__unpack(NULL, msg_len, buf);
311
if (msg == NULL) {
312
sudo_warnx(U_("unable to unpack %s size %zu"), "ClientMessage",
313
(size_t)msg_len);
314
closure->errstr = _("invalid journal file, unable to restart");
315
break;
316
}
317
318
switch (msg->type_case) {
319
case CLIENT_MESSAGE__TYPE_HELLO_MSG:
320
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
321
"seeking past ClientHello (%d)", msg->type_case);
322
break;
323
case CLIENT_MESSAGE__TYPE_ACCEPT_MSG:
324
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
325
"seeking past AcceptMessage (%d)", msg->type_case);
326
break;
327
case CLIENT_MESSAGE__TYPE_REJECT_MSG:
328
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
329
"seeking past RejectMessage (%d)", msg->type_case);
330
break;
331
case CLIENT_MESSAGE__TYPE_EXIT_MSG:
332
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
333
"seeking past ExitMessage (%d)", msg->type_case);
334
break;
335
case CLIENT_MESSAGE__TYPE_RESTART_MSG:
336
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
337
"seeking past RestartMessage (%d)", msg->type_case);
338
break;
339
case CLIENT_MESSAGE__TYPE_ALERT_MSG:
340
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
341
"seeking past AlertMessage (%d)", msg->type_case);
342
break;
343
case CLIENT_MESSAGE__TYPE_TTYIN_BUF:
344
if (msg->u.ttyin_buf == NULL ||
345
!valid_timespec(msg->u.ttyin_buf->delay)) {
346
sudo_warnx(U_("%s: %s"), closure->journal_path,
347
U_("invalid IoBuffer"));
348
closure->errstr = _("invalid IoBuffer");
349
goto done;
350
}
351
delay = msg->u.ttyin_buf->delay;
352
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
353
"read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
354
(long long)delay->tv_sec, (long)delay->tv_nsec);
355
break;
356
case CLIENT_MESSAGE__TYPE_TTYOUT_BUF:
357
if (msg->u.ttyout_buf == NULL ||
358
!valid_timespec(msg->u.ttyout_buf->delay)) {
359
sudo_warnx(U_("%s: %s"), closure->journal_path,
360
U_("invalid IoBuffer"));
361
closure->errstr = _("invalid IoBuffer");
362
goto done;
363
}
364
delay = msg->u.ttyout_buf->delay;
365
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
366
"read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
367
(long long)delay->tv_sec, (long)delay->tv_nsec);
368
break;
369
case CLIENT_MESSAGE__TYPE_STDIN_BUF:
370
if (msg->u.stdin_buf == NULL ||
371
!valid_timespec(msg->u.stdin_buf->delay)) {
372
sudo_warnx(U_("%s: %s"), closure->journal_path,
373
U_("invalid IoBuffer"));
374
closure->errstr = _("invalid IoBuffer");
375
goto done;
376
}
377
delay = msg->u.stdin_buf->delay;
378
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
379
"read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
380
(long long)delay->tv_sec, (long)delay->tv_nsec);
381
break;
382
case CLIENT_MESSAGE__TYPE_STDOUT_BUF:
383
if (msg->u.stdout_buf == NULL ||
384
!valid_timespec(msg->u.stdout_buf->delay)) {
385
sudo_warnx(U_("%s: %s"), closure->journal_path,
386
U_("invalid IoBuffer"));
387
closure->errstr = _("invalid IoBuffer");
388
goto done;
389
}
390
delay = msg->u.stdout_buf->delay;
391
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
392
"read stdout_buf (%d), delay [%lld, %ld]", msg->type_case,
393
(long long)delay->tv_sec, (long)delay->tv_nsec);
394
break;
395
case CLIENT_MESSAGE__TYPE_STDERR_BUF:
396
if (msg->u.stderr_buf == NULL ||
397
!valid_timespec(msg->u.stderr_buf->delay)) {
398
sudo_warnx(U_("%s: %s"), closure->journal_path,
399
U_("invalid IoBuffer"));
400
closure->errstr = _("invalid IoBuffer");
401
goto done;
402
}
403
delay = msg->u.stderr_buf->delay;
404
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
405
"read stderr_buf (%d), delay [%lld, %ld]", msg->type_case,
406
(long long)delay->tv_sec, (long)delay->tv_nsec);
407
break;
408
case CLIENT_MESSAGE__TYPE_WINSIZE_EVENT:
409
if (msg->u.winsize_event == NULL ||
410
!valid_timespec(msg->u.winsize_event->delay)) {
411
sudo_warnx(U_("%s: %s"), closure->journal_path,
412
U_("invalid ChangeWindowSize"));
413
closure->errstr = _("invalid ChangeWindowSize");
414
goto done;
415
}
416
delay = msg->u.winsize_event->delay;
417
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
418
"read ChangeWindowSize (%d), delay [%lld, %ld]", msg->type_case,
419
(long long)delay->tv_sec, (long)delay->tv_nsec);
420
break;
421
case CLIENT_MESSAGE__TYPE_SUSPEND_EVENT:
422
if (msg->u.suspend_event == NULL ||
423
!valid_timespec(msg->u.suspend_event->delay)) {
424
sudo_warnx(U_("%s: %s"), closure->journal_path,
425
U_("invalid invalid CommandSuspend"));
426
closure->errstr = _("invalid CommandSuspend");
427
goto done;
428
}
429
delay = msg->u.suspend_event->delay;
430
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
431
"read CommandSuspend (%d), delay [%lld, %ld]", msg->type_case,
432
(long long)delay->tv_sec, (long)delay->tv_nsec);
433
break;
434
default:
435
sudo_warnx(U_("unexpected type_case value %d in %s from %s"),
436
msg->type_case, "ClientMessage", closure->journal_path);
437
break;
438
}
439
if (delay != NULL)
440
update_elapsed_time(delay, &closure->elapsed_time);
441
442
if (sudo_timespeccmp(&closure->elapsed_time, target, >=)) {
443
if (sudo_timespeccmp(&closure->elapsed_time, target, ==)) {
444
ret = true;
445
break;
446
}
447
448
/* Mismatch between resume point and stored log. */
449
closure->errstr = _("invalid journal file, unable to restart");
450
sudo_warnx(U_("%s: unable to find resume point [%lld, %ld]"),
451
closure->journal_path, (long long)target->tv_sec,
452
target->tv_nsec);
453
break;
454
}
455
}
456
457
done:
458
client_message__free_unpacked(msg, NULL);
459
free(buf);
460
461
debug_return_bool(ret);
462
}
463
464
/*
465
* Restart an existing journal.
466
* Seeks to the resume_point in RestartMessage before continuing.
467
* Returns true if we reached the target time exactly, else false.
468
*/
469
static bool
470
journal_restart(const RestartMessage *msg, const uint8_t *buf, size_t buflen,
471
struct connection_closure *closure)
472
{
473
char uuid_str[37], journal_path[PATH_MAX];
474
unsigned char uuid[16];
475
struct timespec target;
476
int fd, len;
477
debug_decl(journal_restart, SUDO_DEBUG_UTIL);
478
479
/* A journal log_id must be a base64-encoded UUID. */
480
if (strlen(msg->log_id) != ((16 + 2) / 3 * 4))
481
goto parse_err;
482
if (sudo_base64_decode(msg->log_id, uuid, sizeof(uuid)) != sizeof(uuid))
483
goto parse_err;
484
if (sudo_uuid_to_string(uuid, uuid_str, sizeof(uuid_str)) == NULL) {
485
parse_err:
486
sudo_warnx(U_("%s: %s"), __func__, U_("unable to parse log_id"));
487
closure->errstr = _("unable to open journal file");
488
debug_return_bool(false);
489
}
490
491
/* Journal files are stored by UUID. */
492
len = snprintf(journal_path, sizeof(journal_path), "%s/incoming/%s",
493
logsrvd_conf_relay_dir(), uuid_str);
494
if (len >= ssizeof(journal_path)) {
495
errno = ENAMETOOLONG;
496
sudo_warn("%s/incoming/%s", logsrvd_conf_relay_dir(), uuid_str);
497
closure->errstr = _("unable to open journal file");
498
debug_return_bool(false);
499
}
500
if ((fd = open(journal_path, O_RDWR|O_NOFOLLOW)) == -1) {
501
sudo_warn(U_("unable to open %s"), journal_path);
502
closure->errstr = _("unable to open journal file");
503
debug_return_bool(false);
504
}
505
if (!sudo_lock_file(fd, SUDO_TLOCK)) {
506
sudo_warn(U_("unable to lock %s"), journal_path);
507
close(fd);
508
closure->errstr = _("unable to lock journal file");
509
debug_return_bool(false);
510
}
511
if (!journal_fdopen(fd, journal_path, closure)) {
512
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
513
close(fd);
514
closure->errstr = _("unable to allocate memory");
515
debug_return_bool(false);
516
}
517
518
/* Seek forward to resume point. */
519
target.tv_sec = (time_t)msg->resume_point->tv_sec;
520
target.tv_nsec = (long)msg->resume_point->tv_nsec;
521
if (!journal_seek(&target, closure)) {
522
sudo_warn(U_("unable to seek to [%lld, %ld] in journal file %s"),
523
(long long)target.tv_sec, target.tv_nsec, journal_path);
524
debug_return_bool(false);
525
}
526
527
debug_return_bool(true);
528
}
529
530
static bool
531
journal_write(const uint8_t *buf, size_t len,
532
struct connection_closure *closure)
533
{
534
uint32_t msg_len;
535
debug_decl(journal_write, SUDO_DEBUG_UTIL);
536
537
/* 32-bit message length in network byte order. */
538
msg_len = htonl((uint32_t)len);
539
if (fwrite(&msg_len, 1, sizeof(msg_len), closure->journal) != sizeof(msg_len)) {
540
closure->errstr = _("unable to write journal file");
541
debug_return_bool(false);
542
}
543
/* message payload */
544
if (fwrite(buf, 1, len, closure->journal) != len) {
545
closure->errstr = _("unable to write journal file");
546
debug_return_bool(false);
547
}
548
debug_return_bool(true);
549
}
550
551
/*
552
* Store an AcceptMessage from the client in the journal.
553
*/
554
static bool
555
journal_accept(const AcceptMessage *msg, const uint8_t *buf, size_t len,
556
struct connection_closure *closure)
557
{
558
debug_decl(journal_accept, SUDO_DEBUG_UTIL);
559
560
if (closure->journal_path != NULL) {
561
/* Reuse existing journal file. */
562
debug_return_bool(journal_write(buf, len, closure));
563
}
564
565
/* Store message in a journal for later relaying. */
566
if (!journal_create(closure))
567
debug_return_bool(false);
568
if (!journal_write(buf, len, closure))
569
debug_return_bool(false);
570
571
if (msg->expect_iobufs) {
572
/* Send log ID to client for restarting connections. */
573
unsigned char uuid[16];
574
const char *uuid_str;
575
576
/* Journaled I/O log files are files stored by UUID. */
577
uuid_str = strrchr(closure->journal_path, '/');
578
if (uuid_str == NULL)
579
debug_return_bool(false);
580
uuid_str++;
581
582
/* Parse UUID and format as a log ID (base64-encoded). */
583
if (sudo_uuid_from_string(uuid_str, uuid) != 0)
584
debug_return_bool(false);
585
if (!fmt_log_id_message(uuid, "", closure))
586
debug_return_bool(false);
587
if (sudo_ev_add(closure->evbase, closure->write_ev,
588
logsrvd_conf_server_timeout(), false) == -1) {
589
sudo_warnx("%s", U_("unable to add event to queue"));
590
debug_return_bool(false);
591
}
592
}
593
594
debug_return_bool(true);
595
}
596
597
/*
598
* Store a RejectMessage from the client in the journal.
599
*/
600
static bool
601
journal_reject(const RejectMessage *msg, const uint8_t *buf,
602
size_t len, struct connection_closure *closure)
603
{
604
debug_decl(journal_reject, SUDO_DEBUG_UTIL);
605
606
/* Store message in a journal for later relaying. */
607
if (closure->journal_path == NULL) {
608
if (!journal_create(closure))
609
debug_return_bool(false);
610
}
611
if (!journal_write(buf, len, closure))
612
debug_return_bool(false);
613
614
debug_return_bool(true);
615
}
616
617
/*
618
* Store an ExitMessage from the client in the journal.
619
*/
620
static bool
621
journal_exit(const ExitMessage *msg, const uint8_t *buf, size_t len,
622
struct connection_closure *closure)
623
{
624
debug_decl(journal_exit, SUDO_DEBUG_UTIL);
625
626
/* Store exit message in journal. */
627
if (!journal_write(buf, len, closure))
628
debug_return_bool(false);
629
if (!journal_finish(closure))
630
debug_return_bool(false);
631
632
debug_return_bool(true);
633
}
634
635
/*
636
* Store an AlertMessage from the client in the journal.
637
*/
638
static bool
639
journal_alert(const AlertMessage *msg, const uint8_t *buf, size_t len,
640
struct connection_closure *closure)
641
{
642
debug_decl(journal_alert, SUDO_DEBUG_UTIL);
643
644
/* Store message in a journal for later relaying. */
645
if (closure->journal_path == NULL) {
646
if (!journal_create(closure))
647
debug_return_bool(false);
648
}
649
if (!journal_write(buf, len, closure))
650
debug_return_bool(false);
651
652
debug_return_bool(true);
653
}
654
655
/*
656
* Store an IoBuffer from the client in the journal.
657
*/
658
static bool
659
journal_iobuf(int iofd, const IoBuffer *iobuf, const uint8_t *buf,
660
size_t len, struct connection_closure *closure)
661
{
662
debug_decl(journal_iobuf, SUDO_DEBUG_UTIL);
663
664
if (!journal_write(buf, len, closure))
665
debug_return_bool(false);
666
update_elapsed_time(iobuf->delay, &closure->elapsed_time);
667
668
debug_return_bool(true);
669
}
670
671
/*
672
* Store a CommandSuspend message from the client in the journal.
673
*/
674
static bool
675
journal_suspend(const CommandSuspend *msg, const uint8_t *buf,
676
size_t len, struct connection_closure *closure)
677
{
678
debug_decl(journal_suspend, SUDO_DEBUG_UTIL);
679
680
update_elapsed_time(msg->delay, &closure->elapsed_time);
681
682
debug_return_bool(journal_write(buf, len, closure));
683
}
684
685
/*
686
* Store a ChangeWindowSize message from the client in the journal.
687
*/
688
static bool
689
journal_winsize(const ChangeWindowSize *msg, const uint8_t *buf,
690
size_t len, struct connection_closure *closure)
691
{
692
debug_decl(journal_winsize, SUDO_DEBUG_UTIL);
693
694
update_elapsed_time(msg->delay, &closure->elapsed_time);
695
696
debug_return_bool(journal_write(buf, len, closure));
697
}
698
699
struct client_message_switch cms_journal = {
700
journal_accept,
701
journal_reject,
702
journal_exit,
703
journal_restart,
704
journal_alert,
705
journal_iobuf,
706
journal_suspend,
707
journal_winsize
708
};
709
710