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