Blame
Date:
Thu Jan 27 10:37:28 2022 UTC
Message:
s/whole/all
001
2021-12-29
op
/*
002
2021-12-29
op
* Copyright (c) 2021 Omar Polo <op@omarpolo.com>
003
2021-12-29
op
*
004
2021-12-29
op
* Permission to use, copy, modify, and distribute this software for any
005
2021-12-29
op
* purpose with or without fee is hereby granted, provided that the above
006
2021-12-29
op
* copyright notice and this permission notice appear in all copies.
007
2021-12-29
op
*
008
2021-12-29
op
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
009
2021-12-29
op
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
010
2021-12-29
op
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
011
2021-12-29
op
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
012
2021-12-29
op
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
013
2021-12-29
op
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
014
2021-12-29
op
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
015
2021-12-29
op
*/
016
2021-12-29
op
017
2021-12-29
op
#include "gmid.h"
018
2021-12-29
op
019
2021-12-29
op
#include <sys/socket.h>
020
2021-12-29
op
021
2021-12-29
op
#include <assert.h>
022
2021-12-29
op
#include <ctype.h>
023
2021-12-29
op
#include <errno.h>
024
2021-12-29
op
#include <string.h>
025
2021-12-29
op
026
2021-12-29
op
enum debug {
027
2021-12-29
op
DEBUG_NONE,
028
2021-12-29
op
DEBUG_CODE,
029
2021-12-29
op
DEBUG_HEADER,
030
2021-12-29
op
DEBUG_META,
031
2022-01-27
op
DEBUG_ALL,
032
2021-12-29
op
};
033
2021-12-29
op
034
2021-12-29
op
/* flags */
035
2021-12-29
op
int debug;
036
2021-12-29
op
int dont_verify_name;
037
2021-12-29
op
int flag2;
038
2021-12-29
op
int flag3;
039
2021-12-29
op
int nop;
040
2021-12-29
op
int redirects = 5;
041
2021-12-29
op
int timer;
042
2021-12-29
op
int verbose;
043
2021-12-29
op
const char *cert;
044
2021-12-29
op
const char *key;
045
2021-12-29
op
const char *proxy_host;
046
2021-12-29
op
const char *proxy_port;
047
2021-12-29
op
const char *sni;
048
2021-12-29
op
049
2021-12-29
op
/* state */
050
2021-12-29
op
struct tls_config *tls_conf;
051
2021-12-29
op
052
2021-12-29
op
static void
053
2021-12-29
op
timeout(int signo)
054
2021-12-29
op
{
055
2021-12-29
op
dprintf(2, "%s: timer expired\n", getprogname());
056
2021-12-29
op
exit(1);
057
2021-12-29
op
}
058
2021-12-29
op
059
2021-12-29
op
static void
060
2021-12-29
op
load_tls_conf(void)
061
2021-12-29
op
{
062
2021-12-29
op
if ((tls_conf = tls_config_new()) == NULL)
063
2021-12-29
op
err(1, "tls_config_new");
064
2021-12-29
op
065
2021-12-29
op
tls_config_insecure_noverifycert(tls_conf);
066
2021-12-29
op
if (dont_verify_name)
067
2021-12-29
op
tls_config_insecure_noverifyname(tls_conf);
068
2021-12-29
op
069
2021-12-29
op
if (flag2 &&
070
2021-12-29
op
tls_config_set_protocols(tls_conf, TLS_PROTOCOL_TLSv1_2) == -1)
071
2021-12-29
op
errx(1, "can't set TLSv1.2");
072
2021-12-29
op
if (flag3 &&
073
2021-12-29
op
tls_config_set_protocols(tls_conf, TLS_PROTOCOL_TLSv1_3) == -1)
074
2021-12-29
op
errx(1, "can't set TLSv1.3");
075
2021-12-29
op
076
2021-12-29
op
if (cert != NULL &&
077
2021-12-29
op
tls_config_set_keypair_file(tls_conf, cert, key) == -1)
078
2021-12-29
op
errx(1, "can't load client certificate %s", cert);
079
2021-12-29
op
}
080
2021-12-29
op
081
2021-12-29
op
static void
082
2021-12-29
op
connectto(struct tls *ctx, const char *host, const char *port)
083
2021-12-29
op
{
084
2021-12-29
op
struct addrinfo hints, *res, *res0;
085
2021-12-29
op
int error;
086
2021-12-29
op
int saved_errno;
087
2021-12-29
op
int s;
088
2021-12-29
op
const char *cause = NULL;
089
2021-12-29
op
const char *sname;
090
2021-12-29
op
091
2021-12-29
op
if (proxy_host != NULL) {
092
2021-12-29
op
host = proxy_host;
093
2021-12-29
op
port = proxy_port;
094
2021-12-29
op
}
095
2021-12-29
op
096
2021-12-29
op
if ((sname = sni) == NULL)
097
2021-12-29
op
sname = host;
098
2021-12-29
op
099
2021-12-29
op
memset(&hints, 0, sizeof(hints));
100
2021-12-29
op
hints.ai_family = AF_UNSPEC;
101
2021-12-29
op
hints.ai_socktype = SOCK_STREAM;
102
2021-12-29
op
error = getaddrinfo(host, port, &hints, &res0);
103
2021-12-29
op
if (error)
104
2021-12-29
op
errx(1, "%s", gai_strerror(error));
105
2021-12-29
op
106
2021-12-29
op
s = -1;
107
2021-12-29
op
for (res = res0; res != NULL; res = res->ai_next) {
108
2021-12-29
op
s = socket(res->ai_family, res->ai_socktype,
109
2021-12-29
op
res->ai_protocol);
110
2021-12-29
op
if (s == -1) {
111
2021-12-29
op
cause = "socket";
112
2021-12-29
op
continue;
113
2021-12-29
op
}
114
2021-12-29
op
115
2021-12-29
op
if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
116
2021-12-29
op
cause = "connect";
117
2021-12-29
op
saved_errno = errno;
118
2021-12-29
op
close(s);
119
2021-12-29
op
errno = saved_errno;
120
2021-12-29
op
s = -1;
121
2021-12-29
op
continue;
122
2021-12-29
op
}
123
2021-12-29
op
124
2021-12-29
op
break;
125
2021-12-29
op
}
126
2021-12-29
op
127
2021-12-29
op
if (s == -1)
128
2021-12-29
op
err(1, "%s: can't connect to %s:%s", cause,
129
2021-12-29
op
host, port);
130
2021-12-29
op
131
2021-12-29
op
freeaddrinfo(res0);
132
2021-12-29
op
133
2021-12-29
op
if (tls_connect_socket(ctx, s, sname) == -1)
134
2021-12-29
op
errx(1, "tls_connect_socket: %s", tls_error(ctx));
135
2021-12-29
op
}
136
2021-12-29
op
137
2021-12-29
op
static void
138
2021-12-29
op
doreq(struct tls *ctx, const char *buf)
139
2021-12-29
op
{
140
2021-12-29
op
size_t s;
141
2021-12-29
op
ssize_t w;
142
2021-12-29
op
143
2021-12-29
op
s = strlen(buf);
144
2021-12-29
op
while (s != 0) {
145
2021-12-29
op
switch (w = tls_write(ctx, buf, s)) {
146
2021-12-29
op
case 0:
147
2021-12-29
op
case -1:
148
2021-12-29
op
errx(1, "tls_write: %s", tls_error(ctx));
149
2021-12-29
op
case TLS_WANT_POLLIN:
150
2021-12-29
op
case TLS_WANT_POLLOUT:
151
2021-12-29
op
continue;
152
2021-12-29
op
}
153
2021-12-29
op
154
2021-12-29
op
s -= w;
155
2021-12-29
op
buf += w;
156
2021-12-29
op
}
157
2021-12-29
op
}
158
2021-12-29
op
159
2021-12-29
op
static size_t
160
2021-12-29
op
dorep(struct tls *ctx, void *buf, size_t len)
161
2021-12-29
op
{
162
2021-12-29
op
ssize_t w;
163
2021-12-29
op
size_t tot = 0;
164
2021-12-29
op
165
2021-12-29
op
while (len != 0) {
166
2021-12-29
op
switch (w = tls_read(ctx, buf, len)) {
167
2021-12-29
op
case 0:
168
2021-12-29
op
return tot;
169
2021-12-29
op
case -1:
170
2021-12-29
op
errx(1, "tls_write: %s", tls_error(ctx));
171
2021-12-29
op
case TLS_WANT_POLLIN:
172
2021-12-29
op
case TLS_WANT_POLLOUT:
173
2021-12-29
op
continue;
174
2021-12-29
op
}
175
2021-12-29
op
176
2021-12-29
op
len -= w;
177
2021-12-29
op
buf += w;
178
2021-12-29
op
tot += w;
179
2021-12-29
op
}
180
2021-12-29
op
181
2021-12-29
op
return tot;
182
2021-12-29
op
}
183
2021-12-29
op
184
2021-12-29
op
static int
185
2021-12-29
op
get(const char *r)
186
2021-12-29
op
{
187
2021-12-29
op
struct tls *ctx;
188
2021-12-29
op
struct iri iri;
189
2021-12-29
op
int foundhdr = 0, code = -1, od;
190
2021-12-29
op
char iribuf[GEMINI_URL_LEN];
191
2021-12-29
op
char req[GEMINI_URL_LEN];
192
2021-12-29
op
char buf[2048];
193
2021-12-29
op
const char *parse_err, *host, *port;
194
2021-12-29
op
195
2021-12-29
op
if (strlcpy(iribuf, r, sizeof(iribuf)) >= sizeof(iribuf))
196
2021-12-29
op
errx(1, "iri too long: %s", r);
197
2021-12-29
op
198
2021-12-29
op
if (strlcpy(req, r, sizeof(req)) >= sizeof(req))
199
2021-12-29
op
errx(1, "iri too long: %s", r);
200
2021-12-29
op
201
2021-12-29
op
if (strlcat(req, "\r\n", sizeof(req)) >= sizeof(req))
202
2021-12-29
op
errx(1, "iri too long: %s", r);
203
2021-12-29
op
204
2021-12-29
op
if (!parse_iri(iribuf, &iri, &parse_err))
205
2021-12-29
op
errx(1, "invalid IRI: %s", parse_err);
206
2021-12-29
op
207
2021-12-29
op
if (nop)
208
2021-12-29
op
errx(0, "IRI OK");
209
2021-12-29
op
210
2021-12-29
op
if ((ctx = tls_client()) == NULL)
211
2021-12-29
op
errx(1, "can't create tls context");
212
2021-12-29
op
213
2021-12-29
op
if (tls_configure(ctx, tls_conf) == -1)
214
2021-12-29
op
errx(1, "tls_configure: %s", tls_error(ctx));
215
2021-12-29
op
216
2021-12-29
op
host = iri.host;
217
2021-12-29
op
port = "1965";
218
2021-12-29
op
if (*iri.port != '\0')
219
2021-12-29
op
port = iri.port;
220
2021-12-29
op
221
2021-12-29
op
connectto(ctx, host, port);
222
2021-12-29
op
223
2021-12-29
op
od = 0;
224
2021-12-29
op
while (!od) {
225
2021-12-29
op
switch (tls_handshake(ctx)) {
226
2021-12-29
op
case 0:
227
2021-12-29
op
od = 1;
228
2021-12-29
op
break;
229
2021-12-29
op
case -1:
230
2021-12-29
op
errx(1, "handshake: %s", tls_error(ctx));
231
2021-12-29
op
}
232
2021-12-29
op
}
233
2021-12-29
op
234
2021-12-29
op
if (verbose)
235
2021-12-29
op
printf("%s", req);
236
2021-12-29
op
237
2021-12-29
op
doreq(ctx, req);
238
2021-12-29
op
239
2021-12-29
op
for (;;) {
240
2021-12-29
op
char *t;
241
2021-12-29
op
size_t len;
242
2021-12-29
op
243
2021-12-29
op
len = dorep(ctx, buf, sizeof(buf));
244
2021-12-29
op
if (len == 0)
245
2021-12-29
op
goto close;
246
2021-12-29
op
247
2021-12-29
op
if (foundhdr) {
248
2021-12-29
op
write(1, buf, len);
249
2021-12-29
op
continue;
250
2021-12-29
op
}
251
2021-12-29
op
foundhdr = 1;
252
2021-12-29
op
253
2021-12-29
op
if (memmem(buf, len, "\r\n", 2) == NULL)
254
2021-12-29
op
errx(1, "invalid reply: no \\r\\n");
255
2021-12-29
op
if (!isdigit(buf[0]) || !isdigit(buf[1]) || buf[2] != ' ')
256
2021-12-29
op
errx(1, "invalid reply: invalid response format");
257
2021-12-29
op
258
2021-12-29
op
code = (buf[0] - '0') * 10 + buf[1] - '0';
259
2021-12-29
op
260
2021-12-29
op
if (debug == DEBUG_CODE) {
261
2021-12-29
op
printf("%d\n", code);
262
2021-12-29
op
goto close;
263
2021-12-29
op
}
264
2021-12-29
op
265
2021-12-29
op
if (debug == DEBUG_HEADER) {
266
2021-12-29
op
t = memmem(buf, len, "\r\n", 2);
267
2021-12-29
op
assert(t != NULL);
268
2021-12-29
op
*t = '\0';
269
2021-12-29
op
printf("%s\n", buf);
270
2021-12-29
op
goto close;
271
2021-12-29
op
}
272
2021-12-29
op
273
2021-12-29
op
if (debug == DEBUG_META) {
274
2021-12-29
op
t = memmem(buf, len, "\r\n", 2);
275
2021-12-29
op
assert(t != NULL);
276
2021-12-29
op
*t = '\0';
277
2021-12-29
op
printf("%s\n", buf+3);
278
2021-12-29
op
goto close;
279
2021-12-29
op
}
280
2021-12-29
op
281
2022-01-27
op
if (debug == DEBUG_ALL) {
282
2021-12-29
op
write(1, buf, len);
283
2021-12-29
op
continue;
284
2021-12-29
op
}
285
2021-12-29
op
286
2021-12-29
op
/* skip the header */
287
2021-12-29
op
t = memmem(buf, len, "\r\n", 2);
288
2021-12-29
op
assert(t != NULL);
289
2021-12-29
op
t += 2; /* skip \r\n */
290
2021-12-29
op
len -= t - buf;
291
2021-12-29
op
write(1, t, len);
292
2021-12-29
op
}
293
2021-12-29
op
294
2021-12-29
op
close:
295
2021-12-29
op
od = tls_close(ctx);
296
2021-12-29
op
if (od == TLS_WANT_POLLIN || od == TLS_WANT_POLLOUT)
297
2021-12-29
op
goto close;
298
2021-12-29
op
299
2021-12-29
op
tls_close(ctx);
300
2021-12-29
op
tls_free(ctx);
301
2021-12-29
op
return code;
302
2021-12-29
op
}
303
2021-12-29
op
304
2021-12-29
op
static void __attribute__((noreturn))
305
2021-12-29
op
usage(void)
306
2021-12-29
op
{
307
2021-12-29
op
fprintf(stderr, "usage: %s [-23Nnv] [-C cert] [-d mode] [-H sni] "
308
2022-01-13
op
"[-K key] [-P host[:port]]\n",
309
2021-12-29
op
getprogname());
310
2021-12-29
op
fprintf(stderr, " [-T seconds] gemini://...\n");
311
2021-12-29
op
exit(1);
312
2021-12-29
op
}
313
2021-12-29
op
314
2021-12-29
op
static int
315
2021-12-29
op
parse_debug(const char *arg)
316
2021-12-29
op
{
317
2021-12-29
op
if (!strcmp(arg, "none"))
318
2021-12-29
op
return DEBUG_NONE;
319
2021-12-29
op
if (!strcmp(arg, "code"))
320
2021-12-29
op
return DEBUG_CODE;
321
2021-12-29
op
if (!strcmp(arg, "header"))
322
2021-12-29
op
return DEBUG_HEADER;
323
2021-12-29
op
if (!strcmp(arg, "meta"))
324
2021-12-29
op
return DEBUG_META;
325
2022-01-27
op
if (!strcmp(arg, "all"))
326
2022-01-27
op
return DEBUG_ALL;
327
2021-12-29
op
usage();
328
2021-12-29
op
}
329
2021-12-29
op
330
2021-12-29
op
static void
331
2021-12-29
op
parse_proxy(const char *arg)
332
2021-12-29
op
{
333
2021-12-29
op
char *at;
334
2021-12-29
op
335
2021-12-29
op
if ((proxy_host = strdup(arg)) == NULL)
336
2021-12-29
op
err(1, "strdup");
337
2021-12-29
op
338
2021-12-29
op
proxy_port = "1965";
339
2021-12-29
op
340
2021-12-29
op
if ((at = strchr(proxy_host, ':')) == NULL)
341
2021-12-29
op
return;
342
2021-12-29
op
*at = '\0';
343
2021-12-29
op
proxy_port = ++at;
344
2021-12-29
op
345
2021-12-29
op
if (strchr(proxy_port, ':') != NULL)
346
2021-12-29
op
errx(1, "invalid port %s", proxy_port);
347
2021-12-29
op
}
348
2021-12-29
op
349
2021-12-29
op
int
350
2021-12-29
op
main(int argc, char **argv)
351
2021-12-29
op
{
352
2021-12-29
op
int ch, code;
353
2021-12-29
op
const char *errstr;
354
2021-12-29
op
355
2021-12-29
op
while ((ch = getopt(argc, argv, "23C:d:H:K:NP:T:v")) != -1) {
356
2021-12-29
op
switch (ch) {
357
2021-12-29
op
case '2':
358
2021-12-29
op
flag2 = 1;
359
2021-12-29
op
break;
360
2021-12-29
op
case '3':
361
2021-12-29
op
flag3 = 1;
362
2021-12-29
op
break;
363
2021-12-29
op
case 'C':
364
2021-12-29
op
cert = optarg;
365
2021-12-29
op
break;
366
2021-12-29
op
case 'd':
367
2021-12-29
op
debug = parse_debug(optarg);
368
2021-12-29
op
break;
369
2021-12-29
op
case 'H':
370
2021-12-29
op
sni = optarg;
371
2021-12-29
op
break;
372
2021-12-29
op
case 'K':
373
2021-12-29
op
key = optarg;
374
2021-12-29
op
break;
375
2021-12-29
op
case 'N':
376
2021-12-29
op
dont_verify_name = 1;
377
2021-12-29
op
break;
378
2021-12-29
op
case 'n':
379
2021-12-29
op
nop = 1;
380
2021-12-29
op
break;
381
2021-12-29
op
case 'P':
382
2021-12-29
op
parse_proxy(optarg);
383
2021-12-29
op
dont_verify_name = 1;
384
2021-12-29
op
break;
385
2021-12-29
op
case 'T':
386
2021-12-29
op
timer = strtonum(optarg, 1, 1000, &errstr);
387
2021-12-29
op
if (errstr != NULL)
388
2021-12-29
op
errx(1, "timeout is %s: %s",
389
2021-12-29
op
errstr, optarg);
390
2021-12-29
op
signal(SIGALRM, timeout);
391
2021-12-29
op
alarm(timer);
392
2021-12-29
op
break;
393
2021-12-29
op
case 'v':
394
2021-12-29
op
verbose++;
395
2021-12-29
op
break;
396
2021-12-29
op
default:
397
2021-12-29
op
usage();
398
2021-12-29
op
}
399
2021-12-29
op
}
400
2021-12-29
op
argc -= optind;
401
2021-12-29
op
argv += optind;
402
2021-12-29
op
403
2021-12-29
op
if (flag2 + flag3 > 1) {
404
2021-12-29
op
warnx("only -2 or -3 can be specified at the same time");
405
2021-12-29
op
usage();
406
2021-12-29
op
}
407
2021-12-29
op
408
2021-12-29
op
if ((cert != NULL && key == NULL) ||
409
2021-12-29
op
(cert == NULL && key != NULL)) {
410
2021-12-29
op
warnx("cert or key is missing");
411
2021-12-29
op
usage();
412
2021-12-29
op
}
413
2021-12-29
op
414
2022-01-13
op
if (argc != 1)
415
2022-01-13
op
usage();
416
2021-12-29
op
417
2021-12-29
op
load_tls_conf();
418
2022-01-13
op
419
2022-01-13
op
signal(SIGPIPE, SIG_IGN);
420
2021-12-29
op
421
2021-12-29
op
#ifdef __OpenBSD__
422
2021-12-29
op
if (pledge("stdio inet dns", NULL) == -1)
423
2021-12-29
op
err(1, "pledge");
424
2021-12-29
op
#endif
425
2021-12-29
op
426
2021-12-29
op
code = get(*argv);
427
2021-12-29
op
428
2021-12-29
op
return code < 20 || code >= 30;
429
2021-12-29
op
}
Omar Polo