Blame


1 f48e3b85 2021-05-24 op /*
2 f48e3b85 2021-05-24 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 f48e3b85 2021-05-24 op *
4 f48e3b85 2021-05-24 op * Permission to use, copy, modify, and distribute this software for any
5 f48e3b85 2021-05-24 op * purpose with or without fee is hereby granted, provided that the above
6 f48e3b85 2021-05-24 op * copyright notice and this permission notice appear in all copies.
7 f48e3b85 2021-05-24 op *
8 f48e3b85 2021-05-24 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 f48e3b85 2021-05-24 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 f48e3b85 2021-05-24 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 f48e3b85 2021-05-24 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 f48e3b85 2021-05-24 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 f48e3b85 2021-05-24 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 f48e3b85 2021-05-24 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 f48e3b85 2021-05-24 op */
16 f48e3b85 2021-05-24 op
17 f48e3b85 2021-05-24 op #include "../gmid.h"
18 f48e3b85 2021-05-24 op
19 f48e3b85 2021-05-24 op #include <string.h>
20 f48e3b85 2021-05-24 op
21 f48e3b85 2021-05-24 op int flag2, flag3, bflag, cflag, hflag, Nflag, Vflag, vflag;
22 f48e3b85 2021-05-24 op const char *cert, *key;
23 f48e3b85 2021-05-24 op
24 321341f6 2021-07-06 op static void
25 321341f6 2021-07-06 op timeout(int signo)
26 321341f6 2021-07-06 op {
27 321341f6 2021-07-06 op dprintf(2, "%s: timer expired\n", getprogname());
28 321341f6 2021-07-06 op exit(1);
29 321341f6 2021-07-06 op }
30 321341f6 2021-07-06 op
31 f48e3b85 2021-05-24 op int
32 f48e3b85 2021-05-24 op main(int argc, char **argv)
33 f48e3b85 2021-05-24 op {
34 f48e3b85 2021-05-24 op struct iri iri;
35 f48e3b85 2021-05-24 op struct tls_config *conf;
36 f48e3b85 2021-05-24 op struct tls *ctx;
37 f48e3b85 2021-05-24 op char iribuf[GEMINI_URL_LEN], buf[GEMINI_URL_LEN];
38 321341f6 2021-07-06 op const char *parse_err = "unknown error", *port = "1965", *errstr;
39 f48e3b85 2021-05-24 op const char *hostname;
40 f48e3b85 2021-05-24 op char *t;
41 321341f6 2021-07-06 op int ch, handshake, timer;
42 f48e3b85 2021-05-24 op ssize_t len;
43 f48e3b85 2021-05-24 op
44 f48e3b85 2021-05-24 op hostname = NULL;
45 321341f6 2021-07-06 op while ((ch = getopt(argc, argv, "23C:cbH:hK:NT:Vv")) != -1) {
46 f48e3b85 2021-05-24 op switch (ch) {
47 f48e3b85 2021-05-24 op case '2':
48 f48e3b85 2021-05-24 op flag2 = 1;
49 f48e3b85 2021-05-24 op break;
50 f48e3b85 2021-05-24 op case '3':
51 f48e3b85 2021-05-24 op flag3 = 1;
52 f48e3b85 2021-05-24 op break;
53 f48e3b85 2021-05-24 op case 'b':
54 f48e3b85 2021-05-24 op bflag = 1;
55 f48e3b85 2021-05-24 op break;
56 f48e3b85 2021-05-24 op case 'C':
57 f48e3b85 2021-05-24 op cert = optarg;
58 f48e3b85 2021-05-24 op break;
59 f48e3b85 2021-05-24 op case 'c':
60 f48e3b85 2021-05-24 op cflag = 1;
61 f48e3b85 2021-05-24 op break;
62 f48e3b85 2021-05-24 op case 'H':
63 f48e3b85 2021-05-24 op hostname = optarg;
64 f48e3b85 2021-05-24 op break;
65 f48e3b85 2021-05-24 op case 'h':
66 f48e3b85 2021-05-24 op hflag = 1;
67 f48e3b85 2021-05-24 op break;
68 f48e3b85 2021-05-24 op case 'K':
69 f48e3b85 2021-05-24 op key = optarg;
70 f48e3b85 2021-05-24 op break;
71 f48e3b85 2021-05-24 op case 'N':
72 f48e3b85 2021-05-24 op Nflag = 1;
73 f48e3b85 2021-05-24 op break;
74 321341f6 2021-07-06 op case 'T':
75 321341f6 2021-07-06 op timer = strtonum(optarg, 1, 1000, &errstr);
76 321341f6 2021-07-06 op if (errstr != NULL)
77 321341f6 2021-07-06 op errx(1, "timeout is %s: %s", errstr, optarg);
78 321341f6 2021-07-06 op signal(SIGALRM, timeout);
79 321341f6 2021-07-06 op alarm(timer);
80 321341f6 2021-07-06 op break;
81 f48e3b85 2021-05-24 op case 'V':
82 f48e3b85 2021-05-24 op Vflag = 1;
83 f48e3b85 2021-05-24 op break;
84 f48e3b85 2021-05-24 op case 'v':
85 f48e3b85 2021-05-24 op vflag = 1;
86 f48e3b85 2021-05-24 op break;
87 f48e3b85 2021-05-24 op default:
88 f48e3b85 2021-05-24 op fprintf(stderr, "USAGE: %s [-23cbhNVv] [-H hostname]\n",
89 f48e3b85 2021-05-24 op *argv);
90 f48e3b85 2021-05-24 op return 1;
91 f48e3b85 2021-05-24 op }
92 f48e3b85 2021-05-24 op }
93 f48e3b85 2021-05-24 op argc -= optind;
94 f48e3b85 2021-05-24 op argv += optind;
95 f48e3b85 2021-05-24 op
96 f48e3b85 2021-05-24 op if ((bflag + cflag + hflag + Vflag) > 1)
97 f48e3b85 2021-05-24 op errx(1, "only one of bchr flags can be used.");
98 f48e3b85 2021-05-24 op
99 f48e3b85 2021-05-24 op if (flag2 + flag3 > 1)
100 f48e3b85 2021-05-24 op errx(1, "only -2 or -3 can be specified at the same time.");
101 f48e3b85 2021-05-24 op
102 f48e3b85 2021-05-24 op if ((cert != NULL && key == NULL) || (cert == NULL && key != NULL))
103 f48e3b85 2021-05-24 op errx(1, "missing certificate or key");
104 f48e3b85 2021-05-24 op
105 f48e3b85 2021-05-24 op if (argc != 1)
106 f48e3b85 2021-05-24 op errx(1, "missing IRI");
107 f48e3b85 2021-05-24 op
108 f48e3b85 2021-05-24 op if (strlcpy(iribuf, argv[0], sizeof(iribuf)) >= sizeof(iribuf))
109 f48e3b85 2021-05-24 op errx(1, "request too long: %s", argv[0]);
110 f48e3b85 2021-05-24 op if (strlcpy(buf, argv[0], sizeof(buf)) >= sizeof(iribuf))
111 f48e3b85 2021-05-24 op errx(1, "request too long: %s", argv[0]);
112 f48e3b85 2021-05-24 op if (strlcat(buf, "\r\n", sizeof(buf)) >= sizeof(buf))
113 f48e3b85 2021-05-24 op errx(1, "request too long: %s", argv[0]);
114 f48e3b85 2021-05-24 op
115 f48e3b85 2021-05-24 op if (!parse_iri(iribuf, &iri, &parse_err))
116 f48e3b85 2021-05-24 op errx(1, "invalid IRI: %s", parse_err);
117 f48e3b85 2021-05-24 op
118 f48e3b85 2021-05-24 op if (Vflag)
119 f48e3b85 2021-05-24 op errx(0, "IRI: OK");
120 f48e3b85 2021-05-24 op
121 f48e3b85 2021-05-24 op if ((conf = tls_config_new()) == NULL)
122 f48e3b85 2021-05-24 op errx(1, "tls_config_new");
123 f48e3b85 2021-05-24 op
124 f48e3b85 2021-05-24 op tls_config_insecure_noverifycert(conf);
125 f48e3b85 2021-05-24 op if (Nflag)
126 f48e3b85 2021-05-24 op tls_config_insecure_noverifyname(conf);
127 f48e3b85 2021-05-24 op
128 f48e3b85 2021-05-24 op if (flag2 && tls_config_set_protocols(conf, TLS_PROTOCOL_TLSv1_2) == -1)
129 f48e3b85 2021-05-24 op errx(1, "cannot set TLSv1.2");
130 f48e3b85 2021-05-24 op if (flag3 && tls_config_set_protocols(conf, TLS_PROTOCOL_TLSv1_3) == -1)
131 f48e3b85 2021-05-24 op errx(1, "cannot set TLSv1.3");
132 f48e3b85 2021-05-24 op
133 f48e3b85 2021-05-24 op if (cert != NULL && tls_config_set_keypair_file(conf, cert, key))
134 f48e3b85 2021-05-24 op errx(1, "couldn't load cert: %s", cert);
135 f48e3b85 2021-05-24 op
136 f48e3b85 2021-05-24 op if ((ctx = tls_client()) == NULL)
137 f48e3b85 2021-05-24 op errx(1, "tls_client creation failed");
138 f48e3b85 2021-05-24 op
139 f48e3b85 2021-05-24 op if (tls_configure(ctx, conf) == -1)
140 f48e3b85 2021-05-24 op errx(1, "tls_configure: %s", tls_error(ctx));
141 f48e3b85 2021-05-24 op
142 f48e3b85 2021-05-24 op if (*iri.port != '\0')
143 f48e3b85 2021-05-24 op port = iri.port;
144 f48e3b85 2021-05-24 op
145 f48e3b85 2021-05-24 op if (hostname == NULL)
146 f48e3b85 2021-05-24 op hostname = iri.host;
147 f48e3b85 2021-05-24 op
148 f48e3b85 2021-05-24 op if (tls_connect_servername(ctx, iri.host, port, hostname) == -1)
149 f48e3b85 2021-05-24 op errx(1, "tls_connect: %s", tls_error(ctx));
150 f48e3b85 2021-05-24 op
151 f48e3b85 2021-05-24 op for (handshake = 0; !handshake;) {
152 f48e3b85 2021-05-24 op switch (tls_handshake(ctx)) {
153 f48e3b85 2021-05-24 op case 0:
154 f48e3b85 2021-05-24 op case -1:
155 f48e3b85 2021-05-24 op handshake = 1;
156 f48e3b85 2021-05-24 op break;
157 f48e3b85 2021-05-24 op }
158 f48e3b85 2021-05-24 op }
159 f48e3b85 2021-05-24 op
160 f48e3b85 2021-05-24 op if (vflag)
161 f48e3b85 2021-05-24 op printf("%s", buf);
162 f48e3b85 2021-05-24 op if (tls_write(ctx, buf, strlen(buf)) == -1)
163 f48e3b85 2021-05-24 op errx(1, "tls_write: %s", tls_error(ctx));
164 f48e3b85 2021-05-24 op
165 f48e3b85 2021-05-24 op for (;;) {
166 f48e3b85 2021-05-24 op switch (len = tls_read(ctx, buf, sizeof(buf))) {
167 f48e3b85 2021-05-24 op case 0:
168 f48e3b85 2021-05-24 op case -1:
169 f48e3b85 2021-05-24 op goto end;
170 f48e3b85 2021-05-24 op case TLS_WANT_POLLIN:
171 f48e3b85 2021-05-24 op case TLS_WANT_POLLOUT:
172 f48e3b85 2021-05-24 op continue;
173 f48e3b85 2021-05-24 op }
174 f48e3b85 2021-05-24 op
175 f48e3b85 2021-05-24 op if (bflag) {
176 f48e3b85 2021-05-24 op bflag = 0;
177 f48e3b85 2021-05-24 op if ((t = strchr(buf, '\r')) != NULL)
178 f48e3b85 2021-05-24 op t += 2;
179 f48e3b85 2021-05-24 op else if ((t = strchr(buf, '\n')) != NULL)
180 f48e3b85 2021-05-24 op t += 1;
181 f48e3b85 2021-05-24 op else
182 f48e3b85 2021-05-24 op continue;
183 f48e3b85 2021-05-24 op len -= t - buf;
184 f48e3b85 2021-05-24 op write(1, t, len);
185 f48e3b85 2021-05-24 op continue;
186 f48e3b85 2021-05-24 op }
187 f48e3b85 2021-05-24 op
188 f48e3b85 2021-05-24 op if (cflag) {
189 f48e3b85 2021-05-24 op write(1, buf, 2);
190 f48e3b85 2021-05-24 op write(1, "\n", 1);
191 f48e3b85 2021-05-24 op break;
192 f48e3b85 2021-05-24 op }
193 f48e3b85 2021-05-24 op
194 f48e3b85 2021-05-24 op if (hflag) {
195 f48e3b85 2021-05-24 op t = strchr(buf, '\r');
196 f48e3b85 2021-05-24 op if (t == NULL)
197 f48e3b85 2021-05-24 op t = strchr(buf, '\n');
198 f48e3b85 2021-05-24 op if (t == NULL)
199 f48e3b85 2021-05-24 op t = &buf[len];
200 f48e3b85 2021-05-24 op write(1, buf, t - buf);
201 f48e3b85 2021-05-24 op write(1, "\n", 1);
202 f48e3b85 2021-05-24 op break;
203 f48e3b85 2021-05-24 op }
204 f48e3b85 2021-05-24 op
205 f48e3b85 2021-05-24 op write(1, buf, len);
206 f48e3b85 2021-05-24 op }
207 f48e3b85 2021-05-24 op end:
208 f48e3b85 2021-05-24 op
209 f48e3b85 2021-05-24 op tls_close(ctx);
210 f48e3b85 2021-05-24 op tls_free(ctx);
211 f48e3b85 2021-05-24 op
212 f48e3b85 2021-05-24 op return 0;
213 f48e3b85 2021-05-24 op }