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