Blame


1 5c7abf01 2021-12-29 op /*
2 6e4ba818 2023-10-14 op * Copyright (c) 2021-2023 Omar Polo <op@omarpolo.com>
3 5c7abf01 2021-12-29 op *
4 5c7abf01 2021-12-29 op * Permission to use, copy, modify, and distribute this software for any
5 5c7abf01 2021-12-29 op * purpose with or without fee is hereby granted, provided that the above
6 5c7abf01 2021-12-29 op * copyright notice and this permission notice appear in all copies.
7 5c7abf01 2021-12-29 op *
8 5c7abf01 2021-12-29 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 5c7abf01 2021-12-29 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 5c7abf01 2021-12-29 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 5c7abf01 2021-12-29 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 5c7abf01 2021-12-29 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 5c7abf01 2021-12-29 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 5c7abf01 2021-12-29 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 5c7abf01 2021-12-29 op */
16 5c7abf01 2021-12-29 op
17 5c7abf01 2021-12-29 op #include "gmid.h"
18 5c7abf01 2021-12-29 op
19 5c7abf01 2021-12-29 op #include <sys/socket.h>
20 5c7abf01 2021-12-29 op
21 5c7abf01 2021-12-29 op #include <assert.h>
22 5c7abf01 2021-12-29 op #include <ctype.h>
23 5c7abf01 2021-12-29 op #include <errno.h>
24 0046c1fe 2023-06-06 op #include <locale.h>
25 5c7abf01 2021-12-29 op #include <string.h>
26 7980a5d2 2023-10-18 op #include <wchar.h>
27 5c7abf01 2021-12-29 op
28 5c7abf01 2021-12-29 op enum debug {
29 5c7abf01 2021-12-29 op DEBUG_NONE,
30 5c7abf01 2021-12-29 op DEBUG_CODE,
31 5c7abf01 2021-12-29 op DEBUG_HEADER,
32 5c7abf01 2021-12-29 op DEBUG_META,
33 e89f4739 2022-01-27 op DEBUG_ALL,
34 5c7abf01 2021-12-29 op };
35 5c7abf01 2021-12-29 op
36 5c7abf01 2021-12-29 op /* flags */
37 5c7abf01 2021-12-29 op int debug;
38 5c7abf01 2021-12-29 op int dont_verify_name;
39 5c7abf01 2021-12-29 op int flag2;
40 5c7abf01 2021-12-29 op int flag3;
41 5c7abf01 2021-12-29 op int nop;
42 5c7abf01 2021-12-29 op int redirects = 5;
43 5c7abf01 2021-12-29 op int timer;
44 5c7abf01 2021-12-29 op const char *cert;
45 5c7abf01 2021-12-29 op const char *key;
46 5c7abf01 2021-12-29 op const char *proxy_host;
47 5c7abf01 2021-12-29 op const char *proxy_port;
48 5c7abf01 2021-12-29 op const char *sni;
49 5c7abf01 2021-12-29 op
50 5c7abf01 2021-12-29 op /* state */
51 5c7abf01 2021-12-29 op struct tls_config *tls_conf;
52 5c7abf01 2021-12-29 op
53 5c7abf01 2021-12-29 op static void
54 5c7abf01 2021-12-29 op timeout(int signo)
55 5c7abf01 2021-12-29 op {
56 5c7abf01 2021-12-29 op dprintf(2, "%s: timer expired\n", getprogname());
57 5c7abf01 2021-12-29 op exit(1);
58 5c7abf01 2021-12-29 op }
59 5c7abf01 2021-12-29 op
60 5c7abf01 2021-12-29 op static void
61 5c7abf01 2021-12-29 op load_tls_conf(void)
62 5c7abf01 2021-12-29 op {
63 5c7abf01 2021-12-29 op if ((tls_conf = tls_config_new()) == NULL)
64 5c7abf01 2021-12-29 op err(1, "tls_config_new");
65 5c7abf01 2021-12-29 op
66 5c7abf01 2021-12-29 op tls_config_insecure_noverifycert(tls_conf);
67 5c7abf01 2021-12-29 op if (dont_verify_name)
68 5c7abf01 2021-12-29 op tls_config_insecure_noverifyname(tls_conf);
69 5c7abf01 2021-12-29 op
70 5c7abf01 2021-12-29 op if (flag2 &&
71 5c7abf01 2021-12-29 op tls_config_set_protocols(tls_conf, TLS_PROTOCOL_TLSv1_2) == -1)
72 5c7abf01 2021-12-29 op errx(1, "can't set TLSv1.2");
73 5c7abf01 2021-12-29 op if (flag3 &&
74 5c7abf01 2021-12-29 op tls_config_set_protocols(tls_conf, TLS_PROTOCOL_TLSv1_3) == -1)
75 5c7abf01 2021-12-29 op errx(1, "can't set TLSv1.3");
76 5c7abf01 2021-12-29 op
77 5c7abf01 2021-12-29 op if (cert != NULL &&
78 5c7abf01 2021-12-29 op tls_config_set_keypair_file(tls_conf, cert, key) == -1)
79 5c7abf01 2021-12-29 op errx(1, "can't load client certificate %s", cert);
80 5c7abf01 2021-12-29 op }
81 5c7abf01 2021-12-29 op
82 5c7abf01 2021-12-29 op static void
83 5c7abf01 2021-12-29 op connectto(struct tls *ctx, const char *host, const char *port)
84 5c7abf01 2021-12-29 op {
85 5c7abf01 2021-12-29 op struct addrinfo hints, *res, *res0;
86 5c7abf01 2021-12-29 op int error;
87 5c7abf01 2021-12-29 op int saved_errno;
88 5c7abf01 2021-12-29 op int s;
89 5c7abf01 2021-12-29 op const char *cause = NULL;
90 5c7abf01 2021-12-29 op const char *sname;
91 5c7abf01 2021-12-29 op
92 5c7abf01 2021-12-29 op if (proxy_host != NULL) {
93 5c7abf01 2021-12-29 op host = proxy_host;
94 5c7abf01 2021-12-29 op port = proxy_port;
95 5c7abf01 2021-12-29 op }
96 5c7abf01 2021-12-29 op
97 5c7abf01 2021-12-29 op if ((sname = sni) == NULL)
98 5c7abf01 2021-12-29 op sname = host;
99 5c7abf01 2021-12-29 op
100 5c7abf01 2021-12-29 op memset(&hints, 0, sizeof(hints));
101 5c7abf01 2021-12-29 op hints.ai_family = AF_UNSPEC;
102 5c7abf01 2021-12-29 op hints.ai_socktype = SOCK_STREAM;
103 5c7abf01 2021-12-29 op error = getaddrinfo(host, port, &hints, &res0);
104 5c7abf01 2021-12-29 op if (error)
105 5c7abf01 2021-12-29 op errx(1, "%s", gai_strerror(error));
106 5c7abf01 2021-12-29 op
107 5c7abf01 2021-12-29 op s = -1;
108 5c7abf01 2021-12-29 op for (res = res0; res != NULL; res = res->ai_next) {
109 5c7abf01 2021-12-29 op s = socket(res->ai_family, res->ai_socktype,
110 5c7abf01 2021-12-29 op res->ai_protocol);
111 5c7abf01 2021-12-29 op if (s == -1) {
112 5c7abf01 2021-12-29 op cause = "socket";
113 5c7abf01 2021-12-29 op continue;
114 5c7abf01 2021-12-29 op }
115 5c7abf01 2021-12-29 op
116 5c7abf01 2021-12-29 op if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
117 5c7abf01 2021-12-29 op cause = "connect";
118 5c7abf01 2021-12-29 op saved_errno = errno;
119 5c7abf01 2021-12-29 op close(s);
120 5c7abf01 2021-12-29 op errno = saved_errno;
121 5c7abf01 2021-12-29 op s = -1;
122 5c7abf01 2021-12-29 op continue;
123 5c7abf01 2021-12-29 op }
124 5c7abf01 2021-12-29 op
125 5c7abf01 2021-12-29 op break;
126 5c7abf01 2021-12-29 op }
127 5c7abf01 2021-12-29 op
128 5c7abf01 2021-12-29 op if (s == -1)
129 5c7abf01 2021-12-29 op err(1, "%s: can't connect to %s:%s", cause,
130 5c7abf01 2021-12-29 op host, port);
131 5c7abf01 2021-12-29 op
132 5c7abf01 2021-12-29 op freeaddrinfo(res0);
133 5c7abf01 2021-12-29 op
134 5c7abf01 2021-12-29 op if (tls_connect_socket(ctx, s, sname) == -1)
135 5c7abf01 2021-12-29 op errx(1, "tls_connect_socket: %s", tls_error(ctx));
136 5c7abf01 2021-12-29 op }
137 5c7abf01 2021-12-29 op
138 5c7abf01 2021-12-29 op static void
139 5c7abf01 2021-12-29 op doreq(struct tls *ctx, const char *buf)
140 5c7abf01 2021-12-29 op {
141 5c7abf01 2021-12-29 op size_t s;
142 5c7abf01 2021-12-29 op ssize_t w;
143 5c7abf01 2021-12-29 op
144 5c7abf01 2021-12-29 op s = strlen(buf);
145 5c7abf01 2021-12-29 op while (s != 0) {
146 5c7abf01 2021-12-29 op switch (w = tls_write(ctx, buf, s)) {
147 5c7abf01 2021-12-29 op case 0:
148 5c7abf01 2021-12-29 op case -1:
149 5c7abf01 2021-12-29 op errx(1, "tls_write: %s", tls_error(ctx));
150 5c7abf01 2021-12-29 op case TLS_WANT_POLLIN:
151 5c7abf01 2021-12-29 op case TLS_WANT_POLLOUT:
152 5c7abf01 2021-12-29 op continue;
153 5c7abf01 2021-12-29 op }
154 5c7abf01 2021-12-29 op
155 5c7abf01 2021-12-29 op s -= w;
156 5c7abf01 2021-12-29 op buf += w;
157 5c7abf01 2021-12-29 op }
158 5c7abf01 2021-12-29 op }
159 5c7abf01 2021-12-29 op
160 5c7abf01 2021-12-29 op static size_t
161 10cc8193 2023-06-13 op dorep(struct tls *ctx, uint8_t *buf, size_t len)
162 5c7abf01 2021-12-29 op {
163 5c7abf01 2021-12-29 op ssize_t w;
164 5c7abf01 2021-12-29 op size_t tot = 0;
165 5c7abf01 2021-12-29 op
166 5c7abf01 2021-12-29 op while (len != 0) {
167 5c7abf01 2021-12-29 op switch (w = tls_read(ctx, buf, len)) {
168 5c7abf01 2021-12-29 op case 0:
169 5c7abf01 2021-12-29 op return tot;
170 5c7abf01 2021-12-29 op case -1:
171 5c7abf01 2021-12-29 op errx(1, "tls_write: %s", tls_error(ctx));
172 5c7abf01 2021-12-29 op case TLS_WANT_POLLIN:
173 5c7abf01 2021-12-29 op case TLS_WANT_POLLOUT:
174 5c7abf01 2021-12-29 op continue;
175 5c7abf01 2021-12-29 op }
176 5c7abf01 2021-12-29 op
177 5c7abf01 2021-12-29 op len -= w;
178 5c7abf01 2021-12-29 op buf += w;
179 5c7abf01 2021-12-29 op tot += w;
180 5c7abf01 2021-12-29 op }
181 5c7abf01 2021-12-29 op
182 5c7abf01 2021-12-29 op return tot;
183 5c7abf01 2021-12-29 op }
184 5c7abf01 2021-12-29 op
185 7980a5d2 2023-10-18 op static void
186 7980a5d2 2023-10-18 op safeprint(FILE *fp, const char *str)
187 7980a5d2 2023-10-18 op {
188 7980a5d2 2023-10-18 op int len;
189 7980a5d2 2023-10-18 op wchar_t wc;
190 7980a5d2 2023-10-18 op
191 7980a5d2 2023-10-18 op for (; *str != '\0'; str += len) {
192 7980a5d2 2023-10-18 op if ((len = mbtowc(&wc, str, MB_CUR_MAX)) == -1) {
193 7980a5d2 2023-10-18 op mbtowc(NULL, NULL, MB_CUR_MAX);
194 7980a5d2 2023-10-18 op fputc('?', fp);
195 7980a5d2 2023-10-18 op len = 1;
196 7980a5d2 2023-10-18 op } else if (wcwidth(wc) == -1) {
197 7980a5d2 2023-10-18 op fputc('?', fp);
198 7980a5d2 2023-10-18 op } else if (wc != L'\n')
199 7980a5d2 2023-10-18 op putwc(wc, fp);
200 7980a5d2 2023-10-18 op }
201 7980a5d2 2023-10-18 op
202 7980a5d2 2023-10-18 op fputc('\n', fp);
203 7980a5d2 2023-10-18 op }
204 7980a5d2 2023-10-18 op
205 5c7abf01 2021-12-29 op static int
206 5c7abf01 2021-12-29 op get(const char *r)
207 5c7abf01 2021-12-29 op {
208 5c7abf01 2021-12-29 op struct tls *ctx;
209 5c7abf01 2021-12-29 op struct iri iri;
210 5c7abf01 2021-12-29 op int foundhdr = 0, code = -1, od;
211 5c7abf01 2021-12-29 op char iribuf[GEMINI_URL_LEN];
212 5c7abf01 2021-12-29 op char req[GEMINI_URL_LEN];
213 10cc8193 2023-06-13 op uint8_t buf[2048];
214 5c7abf01 2021-12-29 op const char *parse_err, *host, *port;
215 5c7abf01 2021-12-29 op
216 5c7abf01 2021-12-29 op if (strlcpy(iribuf, r, sizeof(iribuf)) >= sizeof(iribuf))
217 5c7abf01 2021-12-29 op errx(1, "iri too long: %s", r);
218 5c7abf01 2021-12-29 op
219 5c7abf01 2021-12-29 op if (strlcpy(req, r, sizeof(req)) >= sizeof(req))
220 5c7abf01 2021-12-29 op errx(1, "iri too long: %s", r);
221 5c7abf01 2021-12-29 op
222 5c7abf01 2021-12-29 op if (strlcat(req, "\r\n", sizeof(req)) >= sizeof(req))
223 5c7abf01 2021-12-29 op errx(1, "iri too long: %s", r);
224 5c7abf01 2021-12-29 op
225 5c7abf01 2021-12-29 op if (!parse_iri(iribuf, &iri, &parse_err))
226 5c7abf01 2021-12-29 op errx(1, "invalid IRI: %s", parse_err);
227 5c7abf01 2021-12-29 op
228 5c7abf01 2021-12-29 op if (nop)
229 5c7abf01 2021-12-29 op errx(0, "IRI OK");
230 5c7abf01 2021-12-29 op
231 5c7abf01 2021-12-29 op if ((ctx = tls_client()) == NULL)
232 5c7abf01 2021-12-29 op errx(1, "can't create tls context");
233 5c7abf01 2021-12-29 op
234 5c7abf01 2021-12-29 op if (tls_configure(ctx, tls_conf) == -1)
235 5c7abf01 2021-12-29 op errx(1, "tls_configure: %s", tls_error(ctx));
236 5c7abf01 2021-12-29 op
237 5c7abf01 2021-12-29 op host = iri.host;
238 5c7abf01 2021-12-29 op port = "1965";
239 5c7abf01 2021-12-29 op if (*iri.port != '\0')
240 5c7abf01 2021-12-29 op port = iri.port;
241 5c7abf01 2021-12-29 op
242 5c7abf01 2021-12-29 op connectto(ctx, host, port);
243 5c7abf01 2021-12-29 op
244 5c7abf01 2021-12-29 op od = 0;
245 5c7abf01 2021-12-29 op while (!od) {
246 5c7abf01 2021-12-29 op switch (tls_handshake(ctx)) {
247 5c7abf01 2021-12-29 op case 0:
248 5c7abf01 2021-12-29 op od = 1;
249 5c7abf01 2021-12-29 op break;
250 5c7abf01 2021-12-29 op case -1:
251 5c7abf01 2021-12-29 op errx(1, "handshake: %s", tls_error(ctx));
252 5c7abf01 2021-12-29 op }
253 5c7abf01 2021-12-29 op }
254 5c7abf01 2021-12-29 op
255 5c7abf01 2021-12-29 op doreq(ctx, req);
256 5c7abf01 2021-12-29 op
257 5c7abf01 2021-12-29 op for (;;) {
258 10cc8193 2023-06-13 op uint8_t *t;
259 5c7abf01 2021-12-29 op size_t len;
260 5c7abf01 2021-12-29 op
261 5c7abf01 2021-12-29 op len = dorep(ctx, buf, sizeof(buf));
262 5c7abf01 2021-12-29 op if (len == 0)
263 800aa93c 2023-07-22 op break;
264 5c7abf01 2021-12-29 op
265 5c7abf01 2021-12-29 op if (foundhdr) {
266 5c7abf01 2021-12-29 op write(1, buf, len);
267 5c7abf01 2021-12-29 op continue;
268 5c7abf01 2021-12-29 op }
269 5c7abf01 2021-12-29 op foundhdr = 1;
270 5c7abf01 2021-12-29 op
271 5c7abf01 2021-12-29 op if (memmem(buf, len, "\r\n", 2) == NULL)
272 5c7abf01 2021-12-29 op errx(1, "invalid reply: no \\r\\n");
273 6130e0ee 2022-11-17 op if (!isdigit((unsigned char)buf[0]) ||
274 6130e0ee 2022-11-17 op !isdigit((unsigned char)buf[1]) ||
275 6130e0ee 2022-11-17 op buf[2] != ' ')
276 5c7abf01 2021-12-29 op errx(1, "invalid reply: invalid response format");
277 5c7abf01 2021-12-29 op
278 5c7abf01 2021-12-29 op code = (buf[0] - '0') * 10 + buf[1] - '0';
279 5c7abf01 2021-12-29 op
280 5c7abf01 2021-12-29 op if (debug == DEBUG_CODE) {
281 5c7abf01 2021-12-29 op printf("%d\n", code);
282 800aa93c 2023-07-22 op break;
283 5c7abf01 2021-12-29 op }
284 5c7abf01 2021-12-29 op
285 5c7abf01 2021-12-29 op if (debug == DEBUG_HEADER) {
286 5c7abf01 2021-12-29 op t = memmem(buf, len, "\r\n", 2);
287 5c7abf01 2021-12-29 op assert(t != NULL);
288 5c7abf01 2021-12-29 op *t = '\0';
289 5c7abf01 2021-12-29 op printf("%s\n", buf);
290 800aa93c 2023-07-22 op break;
291 5c7abf01 2021-12-29 op }
292 5c7abf01 2021-12-29 op
293 5c7abf01 2021-12-29 op if (debug == DEBUG_META) {
294 5c7abf01 2021-12-29 op t = memmem(buf, len, "\r\n", 2);
295 5c7abf01 2021-12-29 op assert(t != NULL);
296 5c7abf01 2021-12-29 op *t = '\0';
297 5c7abf01 2021-12-29 op printf("%s\n", buf+3);
298 800aa93c 2023-07-22 op break;
299 5c7abf01 2021-12-29 op }
300 5c7abf01 2021-12-29 op
301 e89f4739 2022-01-27 op if (debug == DEBUG_ALL) {
302 5c7abf01 2021-12-29 op write(1, buf, len);
303 5c7abf01 2021-12-29 op continue;
304 5c7abf01 2021-12-29 op }
305 5c7abf01 2021-12-29 op
306 5c7abf01 2021-12-29 op /* skip the header */
307 5c7abf01 2021-12-29 op t = memmem(buf, len, "\r\n", 2);
308 5c7abf01 2021-12-29 op assert(t != NULL);
309 7980a5d2 2023-10-18 op if (code < 20 || code >= 30) {
310 7980a5d2 2023-10-18 op *t = '\0';
311 e8b2d8e3 2023-10-18 op fprintf(stderr, "Server says: ");
312 7980a5d2 2023-10-18 op safeprint(stderr, buf + 3); /* skip return code */
313 7980a5d2 2023-10-18 op }
314 5c7abf01 2021-12-29 op t += 2; /* skip \r\n */
315 5c7abf01 2021-12-29 op len -= t - buf;
316 5c7abf01 2021-12-29 op write(1, t, len);
317 5c7abf01 2021-12-29 op }
318 5c7abf01 2021-12-29 op
319 800aa93c 2023-07-22 op for (;;) {
320 800aa93c 2023-07-22 op switch (tls_close(ctx)) {
321 800aa93c 2023-07-22 op case TLS_WANT_POLLIN:
322 800aa93c 2023-07-22 op case TLS_WANT_POLLOUT:
323 800aa93c 2023-07-22 op continue;
324 800aa93c 2023-07-22 op case -1:
325 800aa93c 2023-07-22 op warnx("tls_close: %s", tls_error(ctx));
326 800aa93c 2023-07-22 op /* fallthrough */
327 800aa93c 2023-07-22 op default:
328 800aa93c 2023-07-22 op tls_free(ctx);
329 800aa93c 2023-07-22 op return code;
330 800aa93c 2023-07-22 op }
331 800aa93c 2023-07-22 op }
332 5c7abf01 2021-12-29 op }
333 5c7abf01 2021-12-29 op
334 88c03474 2023-07-23 op static void __attribute__((noreturn))
335 5c7abf01 2021-12-29 op usage(void)
336 5c7abf01 2021-12-29 op {
337 c5b4db93 2022-09-10 op fprintf(stderr, "version: " GG_STRING "\n");
338 21cf735f 2022-10-30 op fprintf(stderr, "usage: %s [-23Nn] [-C cert] [-d mode] [-H sni] "
339 febfcde8 2022-01-13 op "[-K key] [-P host[:port]]\n",
340 5c7abf01 2021-12-29 op getprogname());
341 5c7abf01 2021-12-29 op fprintf(stderr, " [-T seconds] gemini://...\n");
342 5c7abf01 2021-12-29 op exit(1);
343 5c7abf01 2021-12-29 op }
344 5c7abf01 2021-12-29 op
345 5c7abf01 2021-12-29 op static int
346 5c7abf01 2021-12-29 op parse_debug(const char *arg)
347 5c7abf01 2021-12-29 op {
348 5c7abf01 2021-12-29 op if (!strcmp(arg, "none"))
349 5c7abf01 2021-12-29 op return DEBUG_NONE;
350 5c7abf01 2021-12-29 op if (!strcmp(arg, "code"))
351 5c7abf01 2021-12-29 op return DEBUG_CODE;
352 5c7abf01 2021-12-29 op if (!strcmp(arg, "header"))
353 5c7abf01 2021-12-29 op return DEBUG_HEADER;
354 5c7abf01 2021-12-29 op if (!strcmp(arg, "meta"))
355 5c7abf01 2021-12-29 op return DEBUG_META;
356 e89f4739 2022-01-27 op if (!strcmp(arg, "all"))
357 e89f4739 2022-01-27 op return DEBUG_ALL;
358 5c7abf01 2021-12-29 op usage();
359 5c7abf01 2021-12-29 op }
360 5c7abf01 2021-12-29 op
361 5c7abf01 2021-12-29 op static void
362 5c7abf01 2021-12-29 op parse_proxy(const char *arg)
363 5c7abf01 2021-12-29 op {
364 5c7abf01 2021-12-29 op char *at;
365 5c7abf01 2021-12-29 op
366 5c7abf01 2021-12-29 op if ((proxy_host = strdup(arg)) == NULL)
367 5c7abf01 2021-12-29 op err(1, "strdup");
368 5c7abf01 2021-12-29 op
369 5c7abf01 2021-12-29 op proxy_port = "1965";
370 5c7abf01 2021-12-29 op
371 5c7abf01 2021-12-29 op if ((at = strchr(proxy_host, ':')) == NULL)
372 5c7abf01 2021-12-29 op return;
373 5c7abf01 2021-12-29 op *at = '\0';
374 5c7abf01 2021-12-29 op proxy_port = ++at;
375 5c7abf01 2021-12-29 op
376 5c7abf01 2021-12-29 op if (strchr(proxy_port, ':') != NULL)
377 5c7abf01 2021-12-29 op errx(1, "invalid port %s", proxy_port);
378 5c7abf01 2021-12-29 op }
379 5c7abf01 2021-12-29 op
380 5c7abf01 2021-12-29 op int
381 5c7abf01 2021-12-29 op main(int argc, char **argv)
382 5c7abf01 2021-12-29 op {
383 5c7abf01 2021-12-29 op int ch, code;
384 5c7abf01 2021-12-29 op const char *errstr;
385 5c7abf01 2021-12-29 op
386 0046c1fe 2023-06-06 op setlocale(LC_CTYPE, "");
387 0046c1fe 2023-06-06 op
388 21cf735f 2022-10-30 op while ((ch = getopt(argc, argv, "23C:d:H:K:NP:T:")) != -1) {
389 5c7abf01 2021-12-29 op switch (ch) {
390 5c7abf01 2021-12-29 op case '2':
391 5c7abf01 2021-12-29 op flag2 = 1;
392 5c7abf01 2021-12-29 op break;
393 5c7abf01 2021-12-29 op case '3':
394 5c7abf01 2021-12-29 op flag3 = 1;
395 5c7abf01 2021-12-29 op break;
396 5c7abf01 2021-12-29 op case 'C':
397 5c7abf01 2021-12-29 op cert = optarg;
398 5c7abf01 2021-12-29 op break;
399 5c7abf01 2021-12-29 op case 'd':
400 5c7abf01 2021-12-29 op debug = parse_debug(optarg);
401 5c7abf01 2021-12-29 op break;
402 5c7abf01 2021-12-29 op case 'H':
403 5c7abf01 2021-12-29 op sni = optarg;
404 5c7abf01 2021-12-29 op break;
405 5c7abf01 2021-12-29 op case 'K':
406 5c7abf01 2021-12-29 op key = optarg;
407 5c7abf01 2021-12-29 op break;
408 5c7abf01 2021-12-29 op case 'N':
409 5c7abf01 2021-12-29 op dont_verify_name = 1;
410 5c7abf01 2021-12-29 op break;
411 5c7abf01 2021-12-29 op case 'n':
412 5c7abf01 2021-12-29 op nop = 1;
413 5c7abf01 2021-12-29 op break;
414 5c7abf01 2021-12-29 op case 'P':
415 5c7abf01 2021-12-29 op parse_proxy(optarg);
416 5c7abf01 2021-12-29 op dont_verify_name = 1;
417 5c7abf01 2021-12-29 op break;
418 5c7abf01 2021-12-29 op case 'T':
419 5c7abf01 2021-12-29 op timer = strtonum(optarg, 1, 1000, &errstr);
420 5c7abf01 2021-12-29 op if (errstr != NULL)
421 5c7abf01 2021-12-29 op errx(1, "timeout is %s: %s",
422 5c7abf01 2021-12-29 op errstr, optarg);
423 5c7abf01 2021-12-29 op signal(SIGALRM, timeout);
424 5c7abf01 2021-12-29 op alarm(timer);
425 5c7abf01 2021-12-29 op break;
426 5c7abf01 2021-12-29 op default:
427 5c7abf01 2021-12-29 op usage();
428 5c7abf01 2021-12-29 op }
429 5c7abf01 2021-12-29 op }
430 5c7abf01 2021-12-29 op argc -= optind;
431 5c7abf01 2021-12-29 op argv += optind;
432 5c7abf01 2021-12-29 op
433 5c7abf01 2021-12-29 op if (flag2 + flag3 > 1) {
434 5c7abf01 2021-12-29 op warnx("only -2 or -3 can be specified at the same time");
435 5c7abf01 2021-12-29 op usage();
436 5c7abf01 2021-12-29 op }
437 5c7abf01 2021-12-29 op
438 5c7abf01 2021-12-29 op if ((cert != NULL && key == NULL) ||
439 5c7abf01 2021-12-29 op (cert == NULL && key != NULL)) {
440 5c7abf01 2021-12-29 op warnx("cert or key is missing");
441 5c7abf01 2021-12-29 op usage();
442 5c7abf01 2021-12-29 op }
443 5c7abf01 2021-12-29 op
444 b3602923 2022-01-13 op if (argc != 1)
445 b3602923 2022-01-13 op usage();
446 5c7abf01 2021-12-29 op
447 5c7abf01 2021-12-29 op load_tls_conf();
448 b3602923 2022-01-13 op
449 b3602923 2022-01-13 op signal(SIGPIPE, SIG_IGN);
450 5c7abf01 2021-12-29 op
451 5c7abf01 2021-12-29 op #ifdef __OpenBSD__
452 5c7abf01 2021-12-29 op if (pledge("stdio inet dns", NULL) == -1)
453 5c7abf01 2021-12-29 op err(1, "pledge");
454 5c7abf01 2021-12-29 op #endif
455 5c7abf01 2021-12-29 op
456 5c7abf01 2021-12-29 op code = get(*argv);
457 c7bcd4a8 2023-10-15 op if (code >= 20 && code < 30)
458 c7bcd4a8 2023-10-15 op return 0;
459 c7bcd4a8 2023-10-15 op return code;
460 5c7abf01 2021-12-29 op }