Blame


1 6b5c4000 2026-03-02 rsadowski /* $OpenBSD: check_tls.c,v 1.4 2026/03/02 19:28:01 rsadowski Exp $ */
2 f4a6eef3 2017-05-27 claudio
3 f4a6eef3 2017-05-27 claudio /*
4 f4a6eef3 2017-05-27 claudio * Copyright (c) 2017 Claudio Jeker <claudio@openbsd.org>
5 f4a6eef3 2017-05-27 claudio * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
6 f4a6eef3 2017-05-27 claudio * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
7 f4a6eef3 2017-05-27 claudio *
8 f4a6eef3 2017-05-27 claudio * Permission to use, copy, modify, and distribute this software for any
9 f4a6eef3 2017-05-27 claudio * purpose with or without fee is hereby granted, provided that the above
10 f4a6eef3 2017-05-27 claudio * copyright notice and this permission notice appear in all copies.
11 f4a6eef3 2017-05-27 claudio *
12 f4a6eef3 2017-05-27 claudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 f4a6eef3 2017-05-27 claudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 f4a6eef3 2017-05-27 claudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 f4a6eef3 2017-05-27 claudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 f4a6eef3 2017-05-27 claudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 f4a6eef3 2017-05-27 claudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 f4a6eef3 2017-05-27 claudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 f4a6eef3 2017-05-27 claudio */
20 f4a6eef3 2017-05-27 claudio
21 f4a6eef3 2017-05-27 claudio #include <sys/types.h>
22 f4a6eef3 2017-05-27 claudio #include <sys/queue.h>
23 f4a6eef3 2017-05-27 claudio #include <sys/uio.h>
24 f4a6eef3 2017-05-27 claudio
25 f4a6eef3 2017-05-27 claudio #include <limits.h>
26 f4a6eef3 2017-05-27 claudio #include <event.h>
27 f4a6eef3 2017-05-27 claudio #include <unistd.h>
28 f4a6eef3 2017-05-27 claudio #include <string.h>
29 f4a6eef3 2017-05-27 claudio #include <imsg.h>
30 f4a6eef3 2017-05-27 claudio
31 f4a6eef3 2017-05-27 claudio #include "relayd.h"
32 6b5c4000 2026-03-02 rsadowski #include "log.h"
33 f4a6eef3 2017-05-27 claudio
34 f4a6eef3 2017-05-27 claudio void check_tls_read(int, short, void *);
35 f4a6eef3 2017-05-27 claudio void check_tls_write(int, short, void *);
36 f4a6eef3 2017-05-27 claudio void check_tls_handshake(int, short, void *);
37 f4a6eef3 2017-05-27 claudio void check_tls_cleanup(struct ctl_tcp_event *);
38 f4a6eef3 2017-05-27 claudio void check_tls_error(struct ctl_tcp_event *, const char *, const char *);
39 f4a6eef3 2017-05-27 claudio
40 f4a6eef3 2017-05-27 claudio void
41 f4a6eef3 2017-05-27 claudio check_tls_read(int s, short event, void *arg)
42 f4a6eef3 2017-05-27 claudio {
43 f4a6eef3 2017-05-27 claudio char rbuf[SMALL_READ_BUF_SIZE];
44 f4a6eef3 2017-05-27 claudio struct ctl_tcp_event *cte = arg;
45 f4a6eef3 2017-05-27 claudio int retry_flag = EV_READ;
46 f4a6eef3 2017-05-27 claudio int ret;
47 f4a6eef3 2017-05-27 claudio
48 f4a6eef3 2017-05-27 claudio if (event == EV_TIMEOUT) {
49 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_DOWN;
50 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
51 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_READ_TIMEOUT);
52 f4a6eef3 2017-05-27 claudio return;
53 f4a6eef3 2017-05-27 claudio }
54 f4a6eef3 2017-05-27 claudio
55 f4a6eef3 2017-05-27 claudio bzero(rbuf, sizeof(rbuf));
56 f4a6eef3 2017-05-27 claudio
57 f4a6eef3 2017-05-27 claudio ret = tls_read(cte->tls, rbuf, sizeof(rbuf));
58 f4a6eef3 2017-05-27 claudio if (ret > 0) {
59 f4a6eef3 2017-05-27 claudio if (ibuf_add(cte->buf, rbuf, ret) == -1)
60 f4a6eef3 2017-05-27 claudio fatal("check_tls_read: buf_add error");
61 f4a6eef3 2017-05-27 claudio if (cte->validate_read != NULL &&
62 f4a6eef3 2017-05-27 claudio cte->validate_read(cte) == 0) {
63 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
64 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, cte->host->he);
65 f4a6eef3 2017-05-27 claudio return;
66 f4a6eef3 2017-05-27 claudio }
67 f4a6eef3 2017-05-27 claudio } else if (ret == 0) {
68 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_DOWN;
69 f4a6eef3 2017-05-27 claudio (void)cte->validate_close(cte);
70 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
71 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, cte->host->he);
72 f4a6eef3 2017-05-27 claudio return;
73 f4a6eef3 2017-05-27 claudio } else if (ret == TLS_WANT_POLLIN) {
74 f4a6eef3 2017-05-27 claudio retry_flag = EV_READ;
75 f4a6eef3 2017-05-27 claudio } else if (ret == TLS_WANT_POLLOUT) {
76 f4a6eef3 2017-05-27 claudio retry_flag = EV_WRITE;
77 f4a6eef3 2017-05-27 claudio } else {
78 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_DOWN;
79 f4a6eef3 2017-05-27 claudio check_tls_error(cte, cte->host->conf.name, "cannot read");
80 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
81 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_READ_ERROR);
82 f4a6eef3 2017-05-27 claudio return;
83 f4a6eef3 2017-05-27 claudio }
84 f4a6eef3 2017-05-27 claudio
85 f4a6eef3 2017-05-27 claudio event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, check_tls_read,
86 f4a6eef3 2017-05-27 claudio &cte->tv_start, &cte->table->conf.timeout, cte);
87 f4a6eef3 2017-05-27 claudio return;
88 f4a6eef3 2017-05-27 claudio }
89 f4a6eef3 2017-05-27 claudio
90 f4a6eef3 2017-05-27 claudio void
91 f4a6eef3 2017-05-27 claudio check_tls_write(int s, short event, void *arg)
92 f4a6eef3 2017-05-27 claudio {
93 f4a6eef3 2017-05-27 claudio struct ctl_tcp_event *cte = arg;
94 f4a6eef3 2017-05-27 claudio int retry_flag = EV_WRITE;
95 f4a6eef3 2017-05-27 claudio int len;
96 f4a6eef3 2017-05-27 claudio int ret;
97 738b3cc9 2019-09-15 rob void *buf;
98 f4a6eef3 2017-05-27 claudio
99 f4a6eef3 2017-05-27 claudio if (event == EV_TIMEOUT) {
100 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_DOWN;
101 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
102 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_WRITE_TIMEOUT);
103 f4a6eef3 2017-05-27 claudio return;
104 f4a6eef3 2017-05-27 claudio }
105 f4a6eef3 2017-05-27 claudio
106 738b3cc9 2019-09-15 rob if (cte->table->sendbinbuf != NULL) {
107 738b3cc9 2019-09-15 rob len = ibuf_size(cte->table->sendbinbuf);
108 a4719117 2023-07-03 claudio buf = ibuf_data(cte->table->sendbinbuf);
109 738b3cc9 2019-09-15 rob log_debug("%s: table %s sending binary", __func__,
110 738b3cc9 2019-09-15 rob cte->table->conf.name);
111 a4719117 2023-07-03 claudio print_hex(buf, 0, len);
112 738b3cc9 2019-09-15 rob } else {
113 738b3cc9 2019-09-15 rob len = strlen(cte->table->sendbuf);
114 738b3cc9 2019-09-15 rob buf = cte->table->sendbuf;
115 738b3cc9 2019-09-15 rob }
116 f4a6eef3 2017-05-27 claudio
117 738b3cc9 2019-09-15 rob ret = tls_write(cte->tls, buf, len);
118 738b3cc9 2019-09-15 rob
119 f4a6eef3 2017-05-27 claudio if (ret > 0) {
120 f4a6eef3 2017-05-27 claudio if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) ==
121 f4a6eef3 2017-05-27 claudio NULL)
122 f4a6eef3 2017-05-27 claudio fatalx("ssl_write: cannot create dynamic buffer");
123 f4a6eef3 2017-05-27 claudio
124 f4a6eef3 2017-05-27 claudio event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, check_tls_read,
125 f4a6eef3 2017-05-27 claudio &cte->tv_start, &cte->table->conf.timeout, cte);
126 f4a6eef3 2017-05-27 claudio return;
127 f4a6eef3 2017-05-27 claudio } else if (ret == TLS_WANT_POLLIN) {
128 f4a6eef3 2017-05-27 claudio retry_flag = EV_READ;
129 f4a6eef3 2017-05-27 claudio } else if (ret == TLS_WANT_POLLOUT) {
130 f4a6eef3 2017-05-27 claudio retry_flag = EV_WRITE;
131 f4a6eef3 2017-05-27 claudio } else {
132 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_DOWN;
133 f4a6eef3 2017-05-27 claudio check_tls_error(cte, cte->host->conf.name, "cannot write");
134 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
135 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_WRITE_ERROR);
136 f4a6eef3 2017-05-27 claudio return;
137 f4a6eef3 2017-05-27 claudio }
138 f4a6eef3 2017-05-27 claudio
139 f4a6eef3 2017-05-27 claudio event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, check_tls_write,
140 f4a6eef3 2017-05-27 claudio &cte->tv_start, &cte->table->conf.timeout, cte);
141 f4a6eef3 2017-05-27 claudio }
142 f4a6eef3 2017-05-27 claudio
143 f4a6eef3 2017-05-27 claudio void
144 f4a6eef3 2017-05-27 claudio check_tls_handshake(int fd, short event, void *arg)
145 f4a6eef3 2017-05-27 claudio {
146 f4a6eef3 2017-05-27 claudio struct ctl_tcp_event *cte = arg;
147 f4a6eef3 2017-05-27 claudio int retry_flag = 0;
148 f4a6eef3 2017-05-27 claudio int ret;
149 f4a6eef3 2017-05-27 claudio
150 f4a6eef3 2017-05-27 claudio if (event == EV_TIMEOUT) {
151 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_DOWN;
152 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_CONNECT_TIMEOUT);
153 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
154 f4a6eef3 2017-05-27 claudio return;
155 f4a6eef3 2017-05-27 claudio }
156 f4a6eef3 2017-05-27 claudio
157 f4a6eef3 2017-05-27 claudio ret = tls_handshake(cte->tls);
158 f4a6eef3 2017-05-27 claudio if (ret == 0) {
159 f4a6eef3 2017-05-27 claudio if (cte->table->conf.check == CHECK_TCP) {
160 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_UP;
161 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_CONNECT_OK);
162 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
163 f4a6eef3 2017-05-27 claudio return;
164 f4a6eef3 2017-05-27 claudio }
165 f4a6eef3 2017-05-27 claudio if (cte->table->sendbuf != NULL) {
166 f4a6eef3 2017-05-27 claudio event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE,
167 f4a6eef3 2017-05-27 claudio check_tls_write, &cte->tv_start,
168 f4a6eef3 2017-05-27 claudio &cte->table->conf.timeout, cte);
169 f4a6eef3 2017-05-27 claudio return;
170 f4a6eef3 2017-05-27 claudio }
171 f4a6eef3 2017-05-27 claudio if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) ==
172 f4a6eef3 2017-05-27 claudio NULL)
173 f4a6eef3 2017-05-27 claudio fatalx("ssl_connect: cannot create dynamic buffer");
174 f4a6eef3 2017-05-27 claudio event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_READ,
175 f4a6eef3 2017-05-27 claudio check_tls_read, &cte->tv_start, &cte->table->conf.timeout,
176 f4a6eef3 2017-05-27 claudio cte);
177 f4a6eef3 2017-05-27 claudio return;
178 f4a6eef3 2017-05-27 claudio } else if (ret == TLS_WANT_POLLIN) {
179 f4a6eef3 2017-05-27 claudio retry_flag = EV_READ;
180 f4a6eef3 2017-05-27 claudio } else if (ret == TLS_WANT_POLLOUT) {
181 f4a6eef3 2017-05-27 claudio retry_flag = EV_WRITE;
182 f4a6eef3 2017-05-27 claudio } else {
183 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_DOWN;
184 f4a6eef3 2017-05-27 claudio check_tls_error(cte, cte->host->conf.name,
185 f4a6eef3 2017-05-27 claudio "cannot connect");
186 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_CONNECT_FAIL);
187 f4a6eef3 2017-05-27 claudio check_tls_cleanup(cte);
188 f4a6eef3 2017-05-27 claudio return;
189 f4a6eef3 2017-05-27 claudio }
190 f4a6eef3 2017-05-27 claudio
191 f4a6eef3 2017-05-27 claudio event_again(&cte->ev, cte->s, EV_TIMEOUT|retry_flag,
192 f4a6eef3 2017-05-27 claudio check_tls_handshake,
193 f4a6eef3 2017-05-27 claudio &cte->tv_start, &cte->table->conf.timeout, cte);
194 f4a6eef3 2017-05-27 claudio }
195 f4a6eef3 2017-05-27 claudio
196 f4a6eef3 2017-05-27 claudio void
197 f4a6eef3 2017-05-27 claudio check_tls_cleanup(struct ctl_tcp_event *cte)
198 f4a6eef3 2017-05-27 claudio {
199 f4a6eef3 2017-05-27 claudio tls_close(cte->tls);
200 f4a6eef3 2017-05-27 claudio tls_reset(cte->tls);
201 f4a6eef3 2017-05-27 claudio close(cte->s);
202 f4a6eef3 2017-05-27 claudio ibuf_free(cte->buf);
203 f4a6eef3 2017-05-27 claudio cte->buf = NULL;
204 f4a6eef3 2017-05-27 claudio }
205 f4a6eef3 2017-05-27 claudio
206 f4a6eef3 2017-05-27 claudio void
207 f4a6eef3 2017-05-27 claudio check_tls_error(struct ctl_tcp_event *cte, const char *where, const char *what)
208 f4a6eef3 2017-05-27 claudio {
209 f4a6eef3 2017-05-27 claudio if (log_getverbose() < 2)
210 f4a6eef3 2017-05-27 claudio return;
211 f4a6eef3 2017-05-27 claudio log_debug("TLS error: %s: %s: %s", where, what, tls_error(cte->tls));
212 f4a6eef3 2017-05-27 claudio }
213 f4a6eef3 2017-05-27 claudio
214 f4a6eef3 2017-05-27 claudio void
215 f4a6eef3 2017-05-27 claudio check_tls(struct ctl_tcp_event *cte)
216 f4a6eef3 2017-05-27 claudio {
217 f4a6eef3 2017-05-27 claudio if (cte->tls == NULL) {
218 f4a6eef3 2017-05-27 claudio cte->tls = tls_client();
219 f4a6eef3 2017-05-27 claudio if (cte->tls == NULL)
220 f4a6eef3 2017-05-27 claudio fatal("cannot create TLS connection");
221 f4a6eef3 2017-05-27 claudio }
222 f4a6eef3 2017-05-27 claudio /* need to re-configure because of tls_reset */
223 f4a6eef3 2017-05-27 claudio if (tls_configure(cte->tls, cte->table->tls_cfg) == -1)
224 f4a6eef3 2017-05-27 claudio fatal("cannot configure TLS connection");
225 f4a6eef3 2017-05-27 claudio
226 f4a6eef3 2017-05-27 claudio if (tls_connect_socket(cte->tls, cte->s, NULL) == -1) {
227 f4a6eef3 2017-05-27 claudio check_tls_error(cte, cte->host->conf.name,
228 f4a6eef3 2017-05-27 claudio "cannot connect");
229 f4a6eef3 2017-05-27 claudio tls_close(cte->tls);
230 f4a6eef3 2017-05-27 claudio tls_reset(cte->tls);
231 f4a6eef3 2017-05-27 claudio cte->host->up = HOST_UNKNOWN;
232 f4a6eef3 2017-05-27 claudio hce_notify_done(cte->host, HCE_TLS_CONNECT_ERROR);
233 f4a6eef3 2017-05-27 claudio return;
234 f4a6eef3 2017-05-27 claudio }
235 f4a6eef3 2017-05-27 claudio
236 f4a6eef3 2017-05-27 claudio event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE, check_tls_handshake,
237 f4a6eef3 2017-05-27 claudio &cte->tv_start, &cte->table->conf.timeout, cte);
238 f4a6eef3 2017-05-27 claudio }