Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/logsrvd/logsrvd_relay.c
3976 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2019-2023, 2025 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
#define NEED_INET_NTOP /* to expose sudo_inet_ntop in sudo_compat.h */
48
49
#include <sudo_compat.h>
50
#include <sudo_debug.h>
51
#include <sudo_event.h>
52
#include <sudo_eventlog.h>
53
#include <sudo_gettext.h>
54
#include <sudo_iolog.h>
55
#include <sudo_fatal.h>
56
#include <sudo_queue.h>
57
#include <sudo_util.h>
58
59
#include <logsrvd.h>
60
61
static void relay_client_msg_cb(int fd, int what, void *v);
62
static void relay_server_msg_cb(int fd, int what, void *v);
63
static void connect_cb(int sock, int what, void *v);
64
static bool start_relay(int sock, struct connection_closure *closure);
65
static void tls_connect_error_fn(struct tls_client_closure *tls_client);
66
67
/*
68
* Free a struct relay_closure container and its contents.
69
*/
70
void
71
relay_closure_free(struct relay_closure *relay_closure)
72
{
73
struct connection_buffer *buf;
74
debug_decl(relay_closure_free, SUDO_DEBUG_UTIL);
75
76
#if defined(HAVE_OPENSSL)
77
if (relay_closure->tls_client.ssl != NULL) {
78
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
79
"closing down TLS connection to %s",
80
relay_closure->relay_name.name);
81
if (SSL_shutdown(relay_closure->tls_client.ssl) == 0)
82
SSL_shutdown(relay_closure->tls_client.ssl);
83
SSL_free(relay_closure->tls_client.ssl);
84
}
85
#endif
86
if (relay_closure->relays != NULL)
87
address_list_delref(relay_closure->relays);
88
sudo_rcstr_delref(relay_closure->relay_name.name);
89
sudo_ev_free(relay_closure->read_ev);
90
sudo_ev_free(relay_closure->write_ev);
91
sudo_ev_free(relay_closure->connect_ev);
92
free(relay_closure->read_buf.data);
93
while ((buf = TAILQ_FIRST(&relay_closure->write_bufs)) != NULL) {
94
TAILQ_REMOVE(&relay_closure->write_bufs, buf, entries);
95
free(buf->data);
96
free(buf);
97
}
98
if (relay_closure->sock != -1) {
99
shutdown(relay_closure->sock, SHUT_RDWR);
100
close(relay_closure->sock);
101
}
102
free(relay_closure);
103
104
debug_return;
105
}
106
107
/*
108
* Allocate a relay closure.
109
* Note that allocation of the events is deferred until we know the socket.
110
*/
111
static struct relay_closure *
112
relay_closure_alloc(void)
113
{
114
struct relay_closure *relay_closure;
115
debug_decl(relay_closure_alloc, SUDO_DEBUG_UTIL);
116
117
if ((relay_closure = calloc(1, sizeof(*relay_closure))) == NULL)
118
debug_return_ptr(NULL);
119
120
/* We take a reference to relays so it doesn't change while connecting. */
121
relay_closure->sock = -1;
122
relay_closure->relays = logsrvd_conf_relay_address();
123
address_list_addref(relay_closure->relays);
124
TAILQ_INIT(&relay_closure->write_bufs);
125
126
relay_closure->read_buf.size = 8 * 1024;
127
relay_closure->read_buf.data = malloc(relay_closure->read_buf.size);
128
if (relay_closure->read_buf.data == NULL)
129
goto bad;
130
131
debug_return_ptr(relay_closure);
132
bad:
133
relay_closure_free(relay_closure);
134
debug_return_ptr(NULL);
135
}
136
137
/*
138
* Allocate a new buffer, copy buf to it and insert on the write queue.
139
* On success the relay write event is enabled.
140
* The length parameter does not include space for the message's wire size.
141
*/
142
static bool
143
relay_enqueue_write(const uint8_t *msgbuf, size_t len,
144
struct connection_closure *closure)
145
{
146
struct relay_closure *relay_closure = closure->relay_closure;
147
struct connection_buffer *buf;
148
uint32_t msg_len;
149
bool ret = false;
150
debug_decl(relay_enqueue_write, SUDO_DEBUG_UTIL);
151
152
/* Wire message size is used for length encoding, precedes message. */
153
msg_len = htonl((uint32_t)len);
154
155
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
156
"size + client message %zu bytes", len);
157
158
if ((buf = get_free_buf(sizeof(msg_len) + len, closure)) == NULL) {
159
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
160
"unable to allocate connection_buffer");
161
goto done;
162
}
163
memcpy(buf->data, &msg_len, sizeof(msg_len));
164
memcpy(buf->data + sizeof(msg_len), msgbuf, len);
165
buf->len = sizeof(msg_len) + len;
166
167
if (sudo_ev_add(closure->evbase, relay_closure->write_ev, NULL, false) == -1) {
168
sudo_warnx("%s", U_("unable to add event to queue"));
169
goto done;
170
}
171
172
TAILQ_INSERT_TAIL(&relay_closure->write_bufs, buf, entries);
173
buf = NULL;
174
175
ret = true;
176
177
done:
178
if (buf != NULL) {
179
free(buf->data);
180
free(buf);
181
}
182
debug_return_bool(ret);
183
}
184
185
/*
186
* Format a ClientMessage and store the wire format message in buf.
187
* Returns true on success, false on failure.
188
*/
189
static bool
190
fmt_client_message(struct connection_closure *closure, ClientMessage *msg)
191
{
192
struct relay_closure *relay_closure = closure->relay_closure;
193
struct connection_buffer *buf = NULL;
194
uint32_t msg_len;
195
bool ret = false;
196
size_t len;
197
debug_decl(fmt_client_message, SUDO_DEBUG_UTIL);
198
199
len = client_message__get_packed_size(msg);
200
if (len > MESSAGE_SIZE_MAX) {
201
sudo_warnx(U_("client message too large: %zu"), len);
202
goto done;
203
}
204
205
/* Wire message size is used for length encoding, precedes message. */
206
msg_len = htonl((uint32_t)len);
207
len += sizeof(msg_len);
208
209
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
210
"size + client message %zu bytes", len);
211
212
if ((buf = get_free_buf(len, closure)) == NULL) {
213
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
214
"unable to allocate connection_buffer");
215
goto done;
216
}
217
memcpy(buf->data, &msg_len, sizeof(msg_len));
218
client_message__pack(msg, buf->data + sizeof(msg_len));
219
buf->len = len;
220
TAILQ_INSERT_TAIL(&relay_closure->write_bufs, buf, entries);
221
222
ret = true;
223
224
done:
225
debug_return_bool(ret);
226
}
227
228
static bool
229
fmt_client_hello(struct connection_closure *closure)
230
{
231
struct relay_closure *relay_closure = closure->relay_closure;
232
ClientMessage client_msg = CLIENT_MESSAGE__INIT;
233
ClientHello hello_msg = CLIENT_HELLO__INIT;
234
bool ret;
235
debug_decl(fmt_client_hello, SUDO_DEBUG_UTIL);
236
237
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending ClientHello", __func__);
238
hello_msg.client_id = (char *)"Sudo Logsrvd " PACKAGE_VERSION;
239
240
client_msg.u.hello_msg = &hello_msg;
241
client_msg.type_case = CLIENT_MESSAGE__TYPE_HELLO_MSG;
242
ret = fmt_client_message(closure, &client_msg);
243
if (ret) {
244
if (sudo_ev_add(closure->evbase, relay_closure->read_ev, NULL, false) == -1) {
245
sudo_warnx("%s", U_("unable to add event to queue"));
246
ret = false;
247
}
248
if (sudo_ev_add(closure->evbase, relay_closure->write_ev, NULL, false) == -1) {
249
sudo_warnx("%s", U_("unable to add event to queue"));
250
ret = false;
251
}
252
}
253
254
debug_return_bool(ret);
255
}
256
257
#if defined(HAVE_OPENSSL)
258
/* Wrapper for start_relay() called via tls_connect_cb() */
259
static bool
260
tls_client_start_fn(struct tls_client_closure *tls_client)
261
{
262
sudo_ev_free(tls_client->tls_connect_ev);
263
tls_client->tls_connect_ev = NULL;
264
return start_relay(SSL_get_fd(tls_client->ssl), tls_client->parent_closure);
265
}
266
267
/* Perform TLS connection to the relay host. */
268
static bool
269
connect_relay_tls(struct connection_closure *closure)
270
{
271
struct tls_client_closure *tls_client = &closure->relay_closure->tls_client;
272
const struct timespec *timeout = logsrvd_conf_relay_connect_timeout();
273
SSL_CTX *ssl_ctx = logsrvd_relay_tls_ctx();
274
debug_decl(connect_relay_tls, SUDO_DEBUG_UTIL);
275
276
/* Populate struct tls_client_closure. */
277
tls_client->parent_closure = closure;
278
tls_client->evbase = closure->evbase;
279
tls_client->tls_connect_ev = sudo_ev_alloc(closure->relay_closure->sock,
280
SUDO_EV_WRITE, tls_connect_cb, tls_client);
281
if (tls_client->tls_connect_ev == NULL)
282
goto bad;
283
tls_client->peer_name = &closure->relay_closure->relay_name;
284
if (timeout != NULL) {
285
tls_client->connect_timeout = *timeout;
286
} else {
287
sudo_timespecclear(&tls_client->connect_timeout);
288
}
289
tls_client->start_fn = tls_client_start_fn;
290
tls_client->connect_error_fn = tls_connect_error_fn;
291
if (!tls_ctx_client_setup(ssl_ctx, closure->relay_closure->sock, tls_client))
292
goto bad;
293
294
debug_return_bool(true);
295
bad:
296
debug_return_bool(false);
297
}
298
#endif /* HAVE_OPENSSL */
299
300
/*
301
* Try to connect to the next relay host.
302
* Returns 0 on success, -1 on error, setting errno.
303
* If there is no next relay, errno is set to ENOENT.
304
*/
305
static int
306
connect_relay_next(struct connection_closure *closure)
307
{
308
struct relay_closure *relay_closure = closure->relay_closure;
309
struct server_address *relay;
310
int ret, sock = -1;
311
char *addr;
312
debug_decl(connect_relay_next, SUDO_DEBUG_UTIL);
313
314
/* Get next relay or return ENOENT none are left. */
315
if (relay_closure->relay_addr != NULL) {
316
relay = TAILQ_NEXT(relay_closure->relay_addr, entries);
317
} else {
318
relay = TAILQ_FIRST(relay_closure->relays);
319
}
320
if (relay == NULL) {
321
errno = ENOENT;
322
goto bad;
323
}
324
relay_closure->relay_addr = relay;
325
326
sock = socket(relay->sa_un.sa.sa_family, SOCK_STREAM, 0);
327
if (sock == -1) {
328
sudo_warn("socket");
329
goto bad;
330
}
331
if (logsrvd_conf_relay_tcp_keepalive()) {
332
int keepalive = 1;
333
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
334
sizeof(keepalive)) == -1) {
335
sudo_warn("SO_KEEPALIVE");
336
}
337
}
338
ret = fcntl(sock, F_GETFL, 0);
339
if (ret == -1 || fcntl(sock, F_SETFL, ret | O_NONBLOCK) == -1) {
340
sudo_warn("fcntl(O_NONBLOCK)");
341
goto bad;
342
}
343
344
ret = connect(sock, &relay->sa_un.sa, relay->sa_size);
345
if (ret == -1 && errno != EINPROGRESS)
346
goto bad;
347
348
switch (relay->sa_un.sa.sa_family) {
349
case AF_INET:
350
addr = (char *)&relay->sa_un.sin.sin_addr;
351
break;
352
#ifdef HAVE_STRUCT_IN6_ADDR
353
case AF_INET6:
354
addr = (char *)&relay->sa_un.sin6.sin6_addr;
355
break;
356
#endif
357
default:
358
errno = EAFNOSUPPORT;
359
sudo_warn("connect");
360
goto bad;
361
}
362
inet_ntop(relay->sa_un.sa.sa_family, addr,
363
relay_closure->relay_name.ipaddr,
364
sizeof(relay_closure->relay_name.ipaddr));
365
relay_closure->relay_name.name = sudo_rcstr_addref(relay->sa_host);
366
367
if (ret == 0) {
368
if (relay_closure->sock != -1) {
369
shutdown(relay_closure->sock, SHUT_RDWR);
370
close(relay_closure->sock);
371
}
372
relay_closure->sock = sock;
373
#if defined(HAVE_OPENSSL)
374
/* Relay connection succeeded, start TLS handshake. */
375
if (relay_closure->relay_addr->tls) {
376
if (!connect_relay_tls(closure))
377
goto bad;
378
} else
379
#endif
380
{
381
/* Connection succeeded without blocking. */
382
if (!start_relay(sock, closure))
383
goto bad;
384
}
385
} else {
386
/* Connection will be completed in connect_cb(). */
387
relay_closure->connect_ev = sudo_ev_alloc(sock, SUDO_EV_WRITE,
388
connect_cb, closure);
389
if (relay_closure->connect_ev == NULL)
390
goto bad;
391
if (sudo_ev_add(closure->evbase, relay_closure->connect_ev,
392
logsrvd_conf_relay_connect_timeout(), false) == -1) {
393
sudo_warnx("%s", U_("unable to add event to queue"));
394
goto bad;
395
}
396
if (relay_closure->sock != -1) {
397
shutdown(relay_closure->sock, SHUT_RDWR);
398
close(relay_closure->sock);
399
}
400
relay_closure->sock = sock;
401
closure->state = CONNECTING;
402
}
403
debug_return_int(ret);
404
405
bad:
406
/* Connection or system error. */
407
if (sock != -1) {
408
shutdown(sock, SHUT_RDWR);
409
close(sock);
410
}
411
sudo_rcstr_delref(relay_closure->relay_name.name);
412
relay_closure->relay_name.name = NULL;
413
sudo_ev_free(relay_closure->connect_ev);
414
relay_closure->connect_ev = NULL;
415
debug_return_int(-1);
416
}
417
418
static void
419
connect_cb(int sock, int what, void *v)
420
{
421
struct connection_closure *closure = v;
422
struct relay_closure *relay_closure = closure->relay_closure;
423
int errnum, optval, ret;
424
socklen_t optlen = sizeof(optval);
425
debug_decl(connect_cb, SUDO_DEBUG_UTIL);
426
427
if (what == SUDO_EV_TIMEOUT) {
428
errnum = ETIMEDOUT;
429
} else {
430
ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen);
431
errnum = ret == 0 ? optval : errno;
432
}
433
if (errnum == 0) {
434
closure->state = INITIAL;
435
#if defined(HAVE_OPENSSL)
436
/* Relay connection succeeded, start TLS handshake. */
437
if (relay_closure->relay_addr->tls) {
438
if (!connect_relay_tls(closure)) {
439
closure->errstr = _("TLS handshake with relay host failed");
440
if (!schedule_error_message(closure->errstr, closure))
441
connection_close(closure);
442
}
443
} else
444
#endif
445
{
446
/* Relay connection succeeded, start talking to the client. */
447
if (!start_relay(sock, closure)) {
448
closure->errstr = _("unable to allocate memory");
449
if (!schedule_error_message(closure->errstr, closure))
450
connection_close(closure);
451
}
452
}
453
} else {
454
/* Connection failed, try next relay (if any). */
455
int res;
456
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
457
"unable to connect to relay %s (%s): %s",
458
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr,
459
strerror(errnum));
460
while ((res = connect_relay_next(closure)) == -1) {
461
if (errno == ENOENT || errno == EINPROGRESS) {
462
/* Out of relays or connecting asynchronously. */
463
break;
464
}
465
}
466
if (res == -1 && errno != EINPROGRESS) {
467
closure->errstr = _("unable to connect to relay host");
468
if (!schedule_error_message(closure->errstr, closure))
469
connection_close(closure);
470
}
471
}
472
473
debug_return;
474
}
475
476
/* Connect to the first available relay host. */
477
bool
478
connect_relay(struct connection_closure *closure)
479
{
480
struct relay_closure *relay_closure;
481
int res;
482
debug_decl(connect_relay, SUDO_DEBUG_UTIL);
483
484
relay_closure = closure->relay_closure = relay_closure_alloc();
485
if (relay_closure == NULL)
486
debug_return_bool(false);
487
488
while ((res = connect_relay_next(closure)) == -1) {
489
if (errno == ENOENT || errno == EINPROGRESS) {
490
/* Out of relays or connecting asynchronously. */
491
break;
492
}
493
}
494
495
if (res == -1 && errno != EINPROGRESS)
496
debug_return_bool(false);
497
498
/* Switch to relay client message handlers. */
499
closure->cms = &cms_relay;
500
debug_return_bool(true);
501
}
502
503
/* Called on TLS connection error. */
504
static void
505
tls_connect_error_fn(struct tls_client_closure *tls_client)
506
{
507
struct connection_closure *closure = tls_client->parent_closure;
508
int res;
509
510
/* TLS connection failed, try next relay (if any). */
511
while ((res = connect_relay_next(closure)) == -1) {
512
if (errno == ENOENT || errno == EINPROGRESS) {
513
/* Out of relays or connecting asynchronously. */
514
break;
515
}
516
}
517
if (res == -1 && errno != EINPROGRESS) {
518
closure->errstr = _("unable to connect to relay host");
519
if (!schedule_error_message(closure->errstr, closure))
520
connection_close(closure);
521
}
522
}
523
524
/*
525
* Respond to a ServerHello message from the relay.
526
* Returns true on success, false on error.
527
*/
528
static bool
529
handle_server_hello(const ServerHello *msg, struct connection_closure *closure)
530
{
531
struct relay_closure *relay_closure = closure->relay_closure;
532
debug_decl(handle_server_hello, SUDO_DEBUG_UTIL);
533
534
if (closure->state != INITIAL) {
535
sudo_warnx(U_("unexpected state %d for %s"), closure->state,
536
relay_closure->relay_name.ipaddr);
537
closure->errstr = _("state machine error");
538
debug_return_bool(false);
539
}
540
541
/* Check that ServerHello is valid. */
542
if (msg == NULL || msg->server_id == NULL || msg->server_id[0] == '\0') {
543
sudo_warnx(U_("%s: invalid ServerHello, missing server_id"),
544
relay_closure->relay_name.ipaddr);
545
closure->errstr = _("invalid ServerHello");
546
debug_return_bool(false);
547
}
548
549
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
550
"relay server %s (%s) ID %s", relay_closure->relay_name.name,
551
relay_closure->relay_name.ipaddr, msg->server_id);
552
553
/* TODO: handle redirect */
554
555
debug_return_bool(true);
556
}
557
558
/*
559
* Respond to a commit_point ServerMessage from the relay.
560
* Returns true on success, false on error.
561
*/
562
static bool
563
handle_commit_point(const TimeSpec *commit_point,
564
struct connection_closure *closure)
565
{
566
debug_decl(handle_commit_point, SUDO_DEBUG_UTIL);
567
568
if (closure->state < RUNNING) {
569
sudo_warnx(U_("unexpected state %d for %s"), closure->state,
570
closure->relay_closure->relay_name.ipaddr);
571
closure->errstr = _("state machine error");
572
debug_return_bool(false);
573
}
574
575
/* Check that ServerMessage's commit_point is valid. */
576
if (commit_point == NULL) {
577
sudo_warnx(U_("%s: invalid ServerMessage, missing commit_point"),
578
closure->relay_closure->relay_name.ipaddr);
579
closure->errstr = _("invalid ServerMessage");
580
debug_return_bool(false);
581
}
582
583
/* Pass commit point from relay to client. */
584
debug_return_bool(schedule_commit_point(commit_point, closure));
585
}
586
587
/*
588
* Respond to a log_id ServerMessage from the relay.
589
* Returns true on success, false on error.
590
*/
591
static bool
592
handle_log_id(const char *id, struct connection_closure *closure)
593
{
594
ServerMessage msg = SERVER_MESSAGE__INIT;
595
bool ret = false;
596
debug_decl(handle_log_id, SUDO_DEBUG_UTIL);
597
598
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
599
"log ID %s from relay %s (%s)", id,
600
closure->relay_closure->relay_name.name,
601
closure->relay_closure->relay_name.ipaddr);
602
603
/* No client connection when replaying a journaled entry. */
604
if (closure->write_ev == NULL)
605
debug_return_bool(true);
606
607
if (id[0] == '\0') {
608
sudo_warnx(U_("%s: invalid ServerMessage, missing log_id string"),
609
closure->relay_closure->relay_name.ipaddr);
610
closure->errstr = _("invalid ServerMessage");
611
goto done;
612
}
613
614
/*
615
* We currently pass log_id to the client without modifying it.
616
* TODO: append relay host to the log_id so we can restart the
617
* session with the proper relay if more than one is configured.
618
*/
619
msg.u.log_id = (char *)id;
620
msg.type_case = SERVER_MESSAGE__TYPE_LOG_ID;
621
ret = fmt_server_message(closure, &msg);
622
if (ret) {
623
if (sudo_ev_add(closure->evbase, closure->write_ev,
624
logsrvd_conf_relay_timeout(), false) == -1) {
625
sudo_warnx("%s", U_("unable to add event to queue"));
626
ret = false;
627
}
628
}
629
630
done:
631
debug_return_bool(ret);
632
}
633
634
/*
635
* Respond to an error ServerMessage from the relay.
636
* Returns true on success, false on error.
637
*/
638
static bool
639
handle_server_error(const char *errmsg, struct connection_closure *closure)
640
{
641
struct relay_closure *relay_closure = closure->relay_closure;
642
debug_decl(handle_server_error, SUDO_DEBUG_UTIL);
643
644
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
645
"error message received from relay %s (%s): %s",
646
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr,
647
errmsg);
648
649
/* Server will drop connection after the error message. */
650
sudo_ev_del(closure->evbase, closure->relay_closure->read_ev);
651
sudo_ev_del(closure->evbase, closure->relay_closure->write_ev);
652
653
/* Missing error string. */
654
if (errmsg[0] == '\0')
655
errmsg = "unknown error";
656
657
if (!schedule_error_message(errmsg, closure))
658
debug_return_bool(false);
659
660
debug_return_bool(true);
661
}
662
663
/*
664
* Respond to an abort ServerMessage from the relay.
665
* Returns true on success, false on error.
666
*/
667
static bool
668
handle_server_abort(const char *errmsg, struct connection_closure *closure)
669
{
670
struct relay_closure *relay_closure = closure->relay_closure;
671
debug_decl(handle_server_abort, SUDO_DEBUG_UTIL);
672
673
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
674
"abort message received from relay %s (%s): %s",
675
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr,
676
errmsg);
677
678
/* Missing error string. */
679
if (errmsg[0] == '\0')
680
errmsg = "unknown error";
681
682
if (!schedule_error_message(errmsg, closure))
683
debug_return_bool(false);
684
685
debug_return_bool(true);
686
}
687
688
/*
689
* Respond to a ServerMessage from the relay.
690
* Returns true on success, false on error.
691
*/
692
static bool
693
handle_server_message(const uint8_t *buf, size_t len,
694
struct connection_closure *closure)
695
{
696
ServerMessage *msg;
697
bool ret = false;
698
debug_decl(handle_server_message, SUDO_DEBUG_UTIL);
699
700
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: unpacking ServerMessage", __func__);
701
msg = server_message__unpack(NULL, len, buf);
702
if (msg == NULL) {
703
sudo_warnx(U_("unable to unpack %s size %zu"), "ServerMessage", len);
704
debug_return_bool(false);
705
}
706
707
switch (msg->type_case) {
708
case SERVER_MESSAGE__TYPE_HELLO:
709
if ((ret = handle_server_hello(msg->u.hello, closure))) {
710
/* Relay server said hello, start talking to client. */
711
ret = start_protocol(closure);
712
}
713
break;
714
case SERVER_MESSAGE__TYPE_COMMIT_POINT:
715
ret = handle_commit_point(msg->u.commit_point, closure);
716
break;
717
case SERVER_MESSAGE__TYPE_LOG_ID:
718
ret = handle_log_id(msg->u.log_id, closure);
719
break;
720
case SERVER_MESSAGE__TYPE_ERROR:
721
ret = handle_server_error(msg->u.error, closure);
722
break;
723
case SERVER_MESSAGE__TYPE_ABORT:
724
ret = handle_server_abort(msg->u.abort, closure);
725
break;
726
default:
727
sudo_warnx(U_("unexpected type_case value %d in %s from %s"),
728
msg->type_case, "ServerMessage",
729
closure->relay_closure->relay_name.ipaddr);
730
closure->errstr = _("unrecognized ServerMessage type");
731
break;
732
}
733
734
server_message__free_unpacked(msg, NULL);
735
debug_return_bool(ret);
736
}
737
738
/*
739
* Read and unpack a ServerMessage from the relay (read callback).
740
*/
741
static void
742
relay_server_msg_cb(int fd, int what, void *v)
743
{
744
struct connection_closure *closure = v;
745
struct relay_closure *relay_closure = closure->relay_closure;
746
struct connection_buffer *buf = &relay_closure->read_buf;
747
size_t nread;
748
uint32_t msg_len;
749
debug_decl(relay_server_msg_cb, SUDO_DEBUG_UTIL);
750
751
/* For TLS we may need to read as part of SSL_write_ex(). */
752
if (relay_closure->write_instead_of_read) {
753
relay_closure->write_instead_of_read = false;
754
relay_client_msg_cb(fd, what, v);
755
debug_return;
756
}
757
758
if (what == SUDO_EV_TIMEOUT) {
759
sudo_warnx(U_("timed out reading from relay %s (%s)"),
760
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
761
closure->errstr = _("timeout reading from relay");
762
goto send_error;
763
}
764
765
#if defined(HAVE_OPENSSL)
766
if (relay_closure->tls_client.ssl != NULL) {
767
SSL *ssl = relay_closure->tls_client.ssl;
768
int result;
769
770
sudo_debug_printf(SUDO_DEBUG_INFO,
771
"%s: ServerMessage from relay %s (%s) [TLS]", __func__,
772
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
773
result = SSL_read_ex(ssl, buf->data + buf->len, buf->size - buf->len,
774
&nread);
775
if (result <= 0) {
776
unsigned long errcode;
777
const char *errstr;
778
779
switch (SSL_get_error(ssl, result)) {
780
case SSL_ERROR_ZERO_RETURN:
781
/* ssl connection shutdown cleanly */
782
nread = 0;
783
break;
784
case SSL_ERROR_WANT_READ:
785
/* ssl wants to read more, read event is always active */
786
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
787
"SSL_read_ex returns SSL_ERROR_WANT_READ");
788
debug_return;
789
case SSL_ERROR_WANT_WRITE:
790
/* ssl wants to write, schedule a write if not pending */
791
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
792
"SSL_read_ex returns SSL_ERROR_WANT_WRITE");
793
if (!sudo_ev_pending(relay_closure->write_ev, SUDO_EV_WRITE, NULL)) {
794
/* Enable a temporary write event. */
795
if (sudo_ev_add(closure->evbase, relay_closure->write_ev, NULL, false) == -1) {
796
sudo_warnx("%s", U_("unable to add event to queue"));
797
closure->errstr = _("unable to allocate memory");
798
goto send_error;
799
}
800
relay_closure->temporary_write_event = true;
801
}
802
/* Redirect write event to finish SSL_read_ex() */
803
relay_closure->read_instead_of_write = true;
804
debug_return;
805
case SSL_ERROR_SSL:
806
/*
807
* For TLS 1.3, if the cert verify function on the server
808
* returns an error, OpenSSL will send an internal error
809
* alert when we read ServerHello. Convert to a more useful
810
* message and hope that no actual internal error occurs.
811
*/
812
errcode = ERR_get_error();
813
#if !defined(HAVE_WOLFSSL)
814
if (closure->state == INITIAL &&
815
ERR_GET_REASON(errcode) == SSL_R_TLSV1_ALERT_INTERNAL_ERROR) {
816
errstr = _("relay host name does not match certificate");
817
closure->errstr = errstr;
818
} else
819
#endif
820
{
821
errstr = ERR_reason_error_string(errcode);
822
closure->errstr = _("error reading from relay");
823
}
824
sudo_warnx("%s: SSL_read_ex: %s",
825
relay_closure->relay_name.ipaddr,
826
errstr ? errstr : strerror(errno));
827
goto send_error;
828
case SSL_ERROR_SYSCALL:
829
if (nread == 0) {
830
/* EOF, handled below */
831
sudo_warnx(U_("EOF from %s without proper TLS shutdown"),
832
relay_closure->relay_name.ipaddr);
833
break;
834
}
835
sudo_warn("%s: SSL_read_ex", relay_closure->relay_name.ipaddr);
836
closure->errstr = _("error reading from relay");
837
goto send_error;
838
default:
839
errstr = ERR_reason_error_string(ERR_get_error());
840
sudo_warnx("%s: SSL_read_ex: %s",
841
relay_closure->relay_name.ipaddr,
842
errstr ? errstr : strerror(errno));
843
closure->errstr = _("error reading from relay");
844
goto send_error;
845
}
846
}
847
} else
848
#endif
849
{
850
ssize_t n;
851
852
sudo_debug_printf(SUDO_DEBUG_INFO,
853
"%s: ServerMessage from relay %s (%s)", __func__,
854
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
855
n = read(fd, buf->data + buf->len, buf->size - buf->len);
856
if (n < 0) {
857
if (errno == EAGAIN || errno == EINTR)
858
debug_return;
859
sudo_warn("%s: read", relay_closure->relay_name.ipaddr);
860
closure->errstr = _("error reading from relay");
861
goto send_error;
862
}
863
nread = (size_t)n;
864
}
865
866
sudo_debug_printf(SUDO_DEBUG_INFO,
867
"%s: received %zd bytes from relay %s (%s)", __func__, nread,
868
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
869
if (nread == 0) {
870
/* EOF from relay server, close the socket. */
871
shutdown(relay_closure->sock, SHUT_RDWR);
872
close(relay_closure->sock);
873
relay_closure->sock = -1;
874
sudo_ev_del(closure->evbase, relay_closure->read_ev);
875
sudo_ev_del(closure->evbase, relay_closure->write_ev);
876
877
if (closure->state != FINISHED) {
878
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
879
"premature EOF from %s (%s) [state %d]",
880
relay_closure->relay_name.name,
881
relay_closure->relay_name.ipaddr, closure->state);
882
closure->errstr = _("relay server closed connection");
883
goto send_error;
884
}
885
if (closure->sock == -1)
886
connection_close(closure);
887
debug_return;
888
}
889
if (nread > SIZE_MAX - buf->len) {
890
sudo_warnx(U_("internal error, %s overflow"), __func__);
891
closure->errstr = _("error reading from relay");
892
goto send_error;
893
}
894
buf->len += nread;
895
896
while (buf->len - buf->off >= sizeof(msg_len)) {
897
/* Read wire message size (uint32_t in network byte order). */
898
memcpy(&msg_len, buf->data + buf->off, sizeof(msg_len));
899
msg_len = ntohl(msg_len);
900
901
if (msg_len > MESSAGE_SIZE_MAX) {
902
sudo_warnx(U_("server message too large: %zu"), (size_t)msg_len);
903
closure->errstr = _("server message too large");
904
goto send_error;
905
}
906
907
if (msg_len + sizeof(msg_len) > buf->len - buf->off) {
908
/* Incomplete message, we'll read the rest next time. */
909
if (!expand_buf(buf, msg_len + sizeof(msg_len))) {
910
closure->errstr = _("unable to allocate memory");
911
goto send_error;
912
}
913
debug_return;
914
}
915
916
/* Parse ServerMessage (could be zero bytes). */
917
sudo_debug_printf(SUDO_DEBUG_INFO,
918
"%s: parsing ServerMessage, size %u", __func__, msg_len);
919
buf->off += sizeof(msg_len);
920
if (!handle_server_message(buf->data + buf->off, msg_len, closure))
921
goto send_error;
922
buf->off += msg_len;
923
}
924
if (buf->len != buf->off) {
925
memmove(buf->data, buf->data + buf->off, buf->len - buf->off);
926
}
927
buf->len -= buf->off;
928
buf->off = 0;
929
debug_return;
930
931
send_error:
932
/*
933
* Try to send client an error message before closing connection.
934
* If we are already in an error state, just give up.
935
*/
936
if (!schedule_error_message(closure->errstr, closure))
937
goto close_connection;
938
debug_return;
939
940
close_connection:
941
connection_close(closure);
942
debug_return;
943
}
944
945
/*
946
* Forward a ClientMessage to the relay (write callback).
947
*/
948
static void
949
relay_client_msg_cb(int fd, int what, void *v)
950
{
951
struct connection_closure *closure = v;
952
struct relay_closure *relay_closure = closure->relay_closure;
953
struct connection_buffer *buf;
954
size_t nwritten;
955
debug_decl(relay_client_msg_cb, SUDO_DEBUG_UTIL);
956
957
/* For TLS we may need to write as part of SSL_read_ex(). */
958
if (relay_closure->read_instead_of_write) {
959
relay_closure->read_instead_of_write = false;
960
/* Delete write event if it was only due to SSL_read_ex(). */
961
if (relay_closure->temporary_write_event) {
962
relay_closure->temporary_write_event = false;
963
sudo_ev_del(closure->evbase, relay_closure->write_ev);
964
}
965
relay_server_msg_cb(fd, what, v);
966
debug_return;
967
}
968
969
if (what == SUDO_EV_TIMEOUT) {
970
sudo_warnx(U_("timed out writing to relay %s (%s)"),
971
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
972
closure->errstr = _("timeout writing to relay");
973
goto send_error;
974
}
975
976
if ((buf = TAILQ_FIRST(&relay_closure->write_bufs)) == NULL) {
977
sudo_warnx(U_("missing write buffer for client %s"),
978
relay_closure->relay_name.ipaddr);
979
goto close_connection;
980
}
981
982
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending %zu bytes to server %s (%s)",
983
__func__, buf->len - buf->off, relay_closure->relay_name.name,
984
relay_closure->relay_name.ipaddr);
985
986
#if defined(HAVE_OPENSSL)
987
if (relay_closure->tls_client.ssl != NULL) {
988
SSL *ssl = relay_closure->tls_client.ssl;
989
const int result = SSL_write_ex(ssl, buf->data + buf->off,
990
buf->len - buf->off, &nwritten);
991
if (result <= 0) {
992
const char *errstr;
993
994
switch (SSL_get_error(ssl, result)) {
995
case SSL_ERROR_ZERO_RETURN:
996
/* ssl connection shutdown cleanly */
997
shutdown(relay_closure->sock, SHUT_RDWR);
998
close(relay_closure->sock);
999
relay_closure->sock = -1;
1000
sudo_ev_del(closure->evbase, relay_closure->read_ev);
1001
sudo_ev_del(closure->evbase, relay_closure->write_ev);
1002
1003
if (closure->state != FINISHED) {
1004
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
1005
"premature EOF from %s (state %d)",
1006
relay_closure->relay_name.ipaddr, closure->state);
1007
closure->errstr = _("relay server closed connection");
1008
goto send_error;
1009
}
1010
debug_return;
1011
case SSL_ERROR_WANT_READ:
1012
/* ssl wants to read, read event always active */
1013
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
1014
"SSL_write_ex returns SSL_ERROR_WANT_READ");
1015
/* Redirect read event to finish SSL_write_ex() */
1016
relay_closure->write_instead_of_read = true;
1017
debug_return;
1018
case SSL_ERROR_WANT_WRITE:
1019
/* ssl wants to write more, write event remains active */
1020
sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
1021
"SSL_write_ex returns SSL_ERROR_WANT_WRITE");
1022
debug_return;
1023
case SSL_ERROR_SYSCALL:
1024
sudo_warn("%s: SSL_write_ex",
1025
relay_closure->relay_name.ipaddr);
1026
closure->errstr = _("error writing to relay");
1027
goto send_error;
1028
default:
1029
errstr = ERR_reason_error_string(ERR_get_error());
1030
sudo_warnx("%s: SSL_write_ex: %s",
1031
relay_closure->relay_name.ipaddr,
1032
errstr ? errstr : strerror(errno));
1033
closure->errstr = _("error writing to relay");
1034
goto send_error;
1035
}
1036
}
1037
} else
1038
#endif
1039
{
1040
const ssize_t n = write(fd, buf->data + buf->off, buf->len - buf->off);
1041
if (n < 0) {
1042
if (errno == EAGAIN || errno == EINTR)
1043
debug_return;
1044
sudo_warn("%s: write", relay_closure->relay_name.ipaddr);
1045
closure->errstr = _("error writing to relay");
1046
goto send_error;
1047
}
1048
nwritten = (size_t)n;
1049
}
1050
if (nwritten > SIZE_MAX - buf->off) {
1051
sudo_warnx(U_("internal error, %s overflow"), __func__);
1052
closure->errstr = _("error writing to relay");
1053
goto send_error;
1054
}
1055
buf->off += nwritten;
1056
1057
if (buf->off == buf->len) {
1058
/* sent entire message, move buf to free list */
1059
sudo_debug_printf(SUDO_DEBUG_INFO,
1060
"%s: finished sending %zu bytes to server", __func__, buf->len);
1061
buf->off = 0;
1062
buf->len = 0;
1063
TAILQ_REMOVE(&relay_closure->write_bufs, buf, entries);
1064
TAILQ_INSERT_TAIL(&closure->free_bufs, buf, entries);
1065
if (TAILQ_EMPTY(&relay_closure->write_bufs)) {
1066
/* Write queue empty, check state. */
1067
sudo_ev_del(closure->evbase, relay_closure->write_ev);
1068
if (closure->error || closure->state == FINISHED ||
1069
closure->state == SHUTDOWN)
1070
goto close_connection;
1071
}
1072
}
1073
debug_return;
1074
1075
send_error:
1076
/*
1077
* Try to send client an error message before closing connection.
1078
* If we are already in an error state, just give up.
1079
*/
1080
if (!schedule_error_message(closure->errstr, closure))
1081
goto close_connection;
1082
debug_return;
1083
1084
close_connection:
1085
connection_close(closure);
1086
debug_return;
1087
}
1088
1089
/* Begin the conversation with the relay host. */
1090
static bool
1091
start_relay(int sock, struct connection_closure *closure)
1092
{
1093
struct relay_closure *relay_closure = closure->relay_closure;
1094
debug_decl(start_relay, SUDO_DEBUG_UTIL);
1095
1096
/* No longer need the connect event. */
1097
sudo_ev_free(relay_closure->connect_ev);
1098
relay_closure->connect_ev = NULL;
1099
1100
/* Allocate relay read/write events now that we know the socket. */
1101
relay_closure->read_ev = sudo_ev_alloc(sock, SUDO_EV_READ|SUDO_EV_PERSIST,
1102
relay_server_msg_cb, closure);
1103
relay_closure->write_ev = sudo_ev_alloc(sock, SUDO_EV_WRITE|SUDO_EV_PERSIST,
1104
relay_client_msg_cb, closure);
1105
if (relay_closure->read_ev == NULL || relay_closure->write_ev == NULL)
1106
debug_return_bool(false);
1107
1108
/* Start communication with the relay server by saying hello. */
1109
debug_return_bool(fmt_client_hello(closure));
1110
}
1111
1112
/*
1113
* Relay an AcceptMessage from the client to the relay server.
1114
*/
1115
static bool
1116
relay_accept(const AcceptMessage *msg, const uint8_t *buf, size_t len,
1117
struct connection_closure *closure)
1118
{
1119
struct relay_closure *relay_closure = closure->relay_closure;
1120
const char *source = closure->journal_path ? closure->journal_path :
1121
closure->ipaddr;
1122
debug_decl(relay_accept, SUDO_DEBUG_UTIL);
1123
1124
sudo_debug_printf(SUDO_DEBUG_INFO,
1125
"%s: relaying AcceptMessage from %s to %s (%s)", __func__, source,
1126
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1127
1128
debug_return_bool(relay_enqueue_write(buf, len, closure));
1129
}
1130
1131
/*
1132
* Relay a RejectMessage from the client to the relay server.
1133
*/
1134
static bool
1135
relay_reject(const RejectMessage *msg, const uint8_t *buf, size_t len,
1136
struct connection_closure *closure)
1137
{
1138
struct relay_closure *relay_closure = closure->relay_closure;
1139
const char *source = closure->journal_path ? closure->journal_path :
1140
closure->ipaddr;
1141
debug_decl(relay_reject, SUDO_DEBUG_UTIL);
1142
1143
sudo_debug_printf(SUDO_DEBUG_INFO,
1144
"%s: relaying RejectMessage from %s to %s (%s)", __func__, source,
1145
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1146
1147
debug_return_bool(relay_enqueue_write(buf, len, closure));
1148
}
1149
1150
/*
1151
* Relay an ExitMessage from the client to the relay server.
1152
*/
1153
static bool
1154
relay_exit(const ExitMessage *msg, const uint8_t *buf, size_t len,
1155
struct connection_closure *closure)
1156
{
1157
struct relay_closure *relay_closure = closure->relay_closure;
1158
const char *source = closure->journal_path ? closure->journal_path :
1159
closure->ipaddr;
1160
debug_decl(relay_exit, SUDO_DEBUG_UTIL);
1161
1162
sudo_debug_printf(SUDO_DEBUG_INFO,
1163
"%s: relaying ExitMessage from %s to %s (%s)", __func__, source,
1164
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1165
1166
debug_return_bool(relay_enqueue_write(buf, len, closure));
1167
}
1168
1169
/*
1170
* Relay a RestartMessage from the client to the relay server.
1171
*/
1172
static bool
1173
relay_restart(const RestartMessage *msg, const uint8_t *buf, size_t len,
1174
struct connection_closure *closure)
1175
{
1176
struct relay_closure *relay_closure = closure->relay_closure;
1177
const char *source = closure->journal_path ? closure->journal_path :
1178
closure->ipaddr;
1179
debug_decl(relay_restart, SUDO_DEBUG_UTIL);
1180
1181
sudo_debug_printf(SUDO_DEBUG_INFO,
1182
"%s: relaying RestartMessage from %s to %s (%s)", __func__, source,
1183
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1184
1185
debug_return_bool(relay_enqueue_write(buf, len, closure));
1186
}
1187
1188
/*
1189
* Relay an AlertMessage from the client to the relay server.
1190
*/
1191
static bool
1192
relay_alert(const AlertMessage *msg, const uint8_t *buf, size_t len,
1193
struct connection_closure *closure)
1194
{
1195
struct relay_closure *relay_closure = closure->relay_closure;
1196
const char *source = closure->journal_path ? closure->journal_path :
1197
closure->ipaddr;
1198
debug_decl(relay_alert, SUDO_DEBUG_UTIL);
1199
1200
sudo_debug_printf(SUDO_DEBUG_INFO,
1201
"%s: relaying AlertMessage from %s to %s (%s)", __func__, source,
1202
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1203
1204
debug_return_bool(relay_enqueue_write(buf, len, closure));
1205
}
1206
1207
/*
1208
* Relay a CommandSuspend from the client to the relay server.
1209
*/
1210
static bool
1211
relay_suspend(const CommandSuspend *msg, const uint8_t *buf, size_t len,
1212
struct connection_closure *closure)
1213
{
1214
struct relay_closure *relay_closure = closure->relay_closure;
1215
const char *source = closure->journal_path ? closure->journal_path :
1216
closure->ipaddr;
1217
debug_decl(relay_suspend, SUDO_DEBUG_UTIL);
1218
1219
sudo_debug_printf(SUDO_DEBUG_INFO,
1220
"%s: relaying CommandSuspend from %s to %s (%s)", __func__, source,
1221
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1222
1223
debug_return_bool(relay_enqueue_write(buf, len, closure));
1224
}
1225
1226
/*
1227
* Relay a ChangeWindowSize from the client to the relay server.
1228
*/
1229
static bool
1230
relay_winsize(const ChangeWindowSize *msg, const uint8_t *buf, size_t len,
1231
struct connection_closure *closure)
1232
{
1233
struct relay_closure *relay_closure = closure->relay_closure;
1234
const char *source = closure->journal_path ? closure->journal_path :
1235
closure->ipaddr;
1236
debug_decl(relay_winsize, SUDO_DEBUG_UTIL);
1237
1238
sudo_debug_printf(SUDO_DEBUG_INFO,
1239
"%s: relaying ChangeWindowSize from %s to %s (%s)", __func__, source,
1240
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1241
1242
debug_return_bool(relay_enqueue_write(buf, len, closure));
1243
}
1244
1245
/*
1246
* Relay an IoBuffer from the client to the relay server.
1247
*/
1248
static bool
1249
relay_iobuf(int iofd, const IoBuffer *iobuf, const uint8_t *buf, size_t len,
1250
struct connection_closure *closure)
1251
{
1252
struct relay_closure *relay_closure = closure->relay_closure;
1253
const char *source = closure->journal_path ? closure->journal_path :
1254
closure->ipaddr;
1255
debug_decl(relay_iobuf, SUDO_DEBUG_UTIL);
1256
1257
sudo_debug_printf(SUDO_DEBUG_INFO,
1258
"%s: relaying IoBuffer from %s to %s (%s)", __func__, source,
1259
relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
1260
1261
debug_return_bool(relay_enqueue_write(buf, len, closure));
1262
}
1263
1264
/*
1265
* Shutdown relay connection when server is exiting.
1266
*/
1267
bool
1268
relay_shutdown(struct connection_closure *closure)
1269
{
1270
struct relay_closure *relay_closure = closure->relay_closure;
1271
debug_decl(relay_shutdown, SUDO_DEBUG_UTIL);
1272
1273
/* Close connection unless relay events are pending. */
1274
if (!sudo_ev_pending(relay_closure->read_ev, SUDO_EV_READ, NULL) &&
1275
!sudo_ev_pending(relay_closure->write_ev, SUDO_EV_WRITE, NULL) &&
1276
TAILQ_EMPTY(&relay_closure->write_bufs)) {
1277
connection_close(closure);
1278
}
1279
1280
debug_return_bool(true);
1281
}
1282
1283
struct client_message_switch cms_relay = {
1284
relay_accept,
1285
relay_reject,
1286
relay_exit,
1287
relay_restart,
1288
relay_alert,
1289
relay_iobuf,
1290
relay_suspend,
1291
relay_winsize
1292
};
1293
1294