e784d07877b98f395edb4348cc6ec7dec02f8928
[BearSSL] / sslio.c
1 /*
2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdint.h>
29 #include <errno.h>
30
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netdb.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <poll.h>
39
40 #include "brssl.h"
41 #include "bearssl.h"
42
43 static void
44 dump_blob(const char *name, const void *data, size_t len)
45 {
46 const unsigned char *buf;
47 size_t u;
48
49 buf = data;
50 fprintf(stderr, "%s (len = %lu)", name, (unsigned long)len);
51 for (u = 0; u < len; u ++) {
52 if ((u & 15) == 0) {
53 fprintf(stderr, "\n%08lX ", (unsigned long)u);
54 } else if ((u & 7) == 0) {
55 fprintf(stderr, " ");
56 }
57 fprintf(stderr, " %02x", buf[u]);
58 }
59 fprintf(stderr, "\n");
60 }
61
62 /*
63 * Inspect the provided data in case it is a "command" to trigger a
64 * special behaviour. If the command is recognised, then it is executed
65 * and this function returns 1. Otherwise, this function returns 0.
66 */
67 static int
68 run_command(br_ssl_engine_context *cc, unsigned char *buf, size_t len)
69 {
70 if (len < 2 || len > 3) {
71 return 0;
72 }
73 if (len == 3 && (buf[1] != '\r' || buf[2] != '\n')) {
74 return 0;
75 }
76 if (len == 2 && buf[1] != '\n') {
77 return 0;
78 }
79 switch (buf[0]) {
80 case 'Q':
81 fprintf(stderr, "closing...\n");
82 br_ssl_engine_close(cc);
83 return 1;
84 case 'R':
85 fprintf(stderr, "renegotiating...\n");
86 br_ssl_engine_renegotiate(cc);
87 return 1;
88 case 'F':
89 /*
90 * Session forget is nominally client-only. But the
91 * session parameters are in the engine structure, which
92 * is the first field of the client context, so the cast
93 * still works properly. On the server, this forgetting
94 * has no effect.
95 */
96 fprintf(stderr, "forgetting session...\n");
97 br_ssl_client_forget_session((br_ssl_client_context *)cc);
98 return 1;
99 default:
100 return 0;
101 }
102 }
103
104 /* see brssl.h */
105 int
106 run_ssl_engine(br_ssl_engine_context *cc, int fd, unsigned flags)
107 {
108 int hsdetails;
109 int retcode;
110 int verbose;
111 int trace;
112
113 hsdetails = 0;
114 retcode = 0;
115 verbose = (flags & RUN_ENGINE_VERBOSE) != 0;
116 trace = (flags & RUN_ENGINE_TRACE) != 0;
117
118 /*
119 * Make sure that stdin and stdout are non-blocking.
120 */
121 fcntl(0, F_SETFL, O_NONBLOCK);
122 fcntl(1, F_SETFL, O_NONBLOCK);
123
124 /*
125 * Perform the loop.
126 */
127 for (;;) {
128 unsigned st;
129 int sendrec, recvrec, sendapp, recvapp;
130 struct pollfd pfd[3];
131 int n;
132 size_t u, k_fd, k_in, k_out;
133
134 /*
135 * Get current engine state.
136 */
137 st = br_ssl_engine_current_state(cc);
138 if (st == BR_SSL_CLOSED) {
139 int err;
140
141 err = br_ssl_engine_last_error(cc);
142 if (err == BR_ERR_OK) {
143 if (verbose) {
144 fprintf(stderr,
145 "SSL closed normally\n");
146 }
147 retcode = 0;
148 goto engine_exit;
149 } else {
150 fprintf(stderr, "ERROR: SSL error %d", err);
151 retcode = err;
152 if (err >= BR_ERR_SEND_FATAL_ALERT) {
153 err -= BR_ERR_SEND_FATAL_ALERT;
154 fprintf(stderr,
155 " (sent alert %d)\n", err);
156 } else if (err >= BR_ERR_RECV_FATAL_ALERT) {
157 err -= BR_ERR_RECV_FATAL_ALERT;
158 fprintf(stderr,
159 " (received alert %d)\n", err);
160 } else {
161 const char *ename;
162
163 ename = find_error_name(err, NULL);
164 if (ename == NULL) {
165 ename = "unknown";
166 }
167 fprintf(stderr, " (%s)\n", ename);
168 }
169 goto engine_exit;
170 }
171 }
172
173 /*
174 * Compute descriptors that must be polled, depending
175 * on engine state.
176 */
177 sendrec = ((st & BR_SSL_SENDREC) != 0);
178 recvrec = ((st & BR_SSL_RECVREC) != 0);
179 sendapp = ((st & BR_SSL_SENDAPP) != 0);
180 recvapp = ((st & BR_SSL_RECVAPP) != 0);
181 if (verbose && sendapp && !hsdetails) {
182 char csn[80];
183
184 fprintf(stderr, "Handshake completed\n");
185 fprintf(stderr, " version: ");
186 switch (cc->session.version) {
187 case BR_SSL30:
188 fprintf(stderr, "SSL 3.0");
189 break;
190 case BR_TLS10:
191 fprintf(stderr, "TLS 1.0");
192 break;
193 case BR_TLS11:
194 fprintf(stderr, "TLS 1.1");
195 break;
196 case BR_TLS12:
197 fprintf(stderr, "TLS 1.2");
198 break;
199 default:
200 fprintf(stderr, "unknown (0x%04X)",
201 (unsigned)cc->session.version);
202 break;
203 }
204 fprintf(stderr, "\n");
205 get_suite_name_ext(
206 cc->session.cipher_suite, csn, sizeof csn);
207 fprintf(stderr, " cipher suite: %s\n", csn);
208 fprintf(stderr, " secure renegotiation: %s\n",
209 cc->reneg == 1 ? "no" : "yes");
210 hsdetails = 1;
211 }
212
213 k_fd = 0;
214 k_in = 0;
215 k_out = 0;
216
217 u = 0;
218 if (sendrec || recvrec) {
219 pfd[u].fd = fd;
220 pfd[u].revents = 0;
221 pfd[u].events = 0;
222 if (sendrec) {
223 pfd[u].events |= POLLOUT;
224 }
225 if (recvrec) {
226 pfd[u].events |= POLLIN;
227 }
228 k_fd = u;
229 u ++;
230 }
231 if (sendapp) {
232 pfd[u].fd = 0;
233 pfd[u].revents = 0;
234 pfd[u].events = POLLIN;
235 k_in = u;
236 u ++;
237 }
238 if (recvapp) {
239 pfd[u].fd = 1;
240 pfd[u].revents = 0;
241 pfd[u].events = POLLOUT;
242 k_out = u;
243 u ++;
244 }
245 n = poll(pfd, u, -1);
246 if (n < 0) {
247 if (errno == EINTR) {
248 continue;
249 }
250 perror("ERROR: poll()");
251 retcode = -2;
252 goto engine_exit;
253 }
254 if (n == 0) {
255 continue;
256 }
257
258 /*
259 * We transform closures/errors into read+write accesses
260 * so as to force the read() or write() call that will
261 * detect the situation.
262 */
263 while (u -- > 0) {
264 if (pfd[u].revents & (POLLERR | POLLHUP)) {
265 pfd[u].revents |= POLLIN | POLLOUT;
266 }
267 }
268
269 /*
270 * We give preference to outgoing data, on stdout and on
271 * the socket.
272 */
273 if (recvapp) {
274 if (pfd[k_out].revents & POLLOUT) {
275 unsigned char *buf;
276 size_t len;
277 ssize_t wlen;
278
279 buf = br_ssl_engine_recvapp_buf(cc, &len);
280 wlen = write(1, buf, len);
281 if (wlen <= 0) {
282 if (verbose) {
283 fprintf(stderr,
284 "stdout closed...\n");
285 }
286 retcode = -2;
287 goto engine_exit;
288 }
289 br_ssl_engine_recvapp_ack(cc, wlen);
290 continue;
291 }
292 }
293 if (sendrec) {
294 if (pfd[k_fd].revents & POLLOUT) {
295 unsigned char *buf;
296 size_t len;
297 ssize_t wlen;
298
299 buf = br_ssl_engine_sendrec_buf(cc, &len);
300 wlen = write(fd, buf, len);
301 if (wlen <= 0) {
302 if (verbose) {
303 fprintf(stderr,
304 "socket closed...\n");
305 }
306 retcode = -1;
307 goto engine_exit;
308 }
309 if (trace) {
310 dump_blob("Outgoing bytes", buf, wlen);
311 }
312 br_ssl_engine_sendrec_ack(cc, wlen);
313 continue;
314 }
315 }
316 if (recvrec) {
317 if (pfd[k_fd].revents & POLLIN) {
318 unsigned char *buf;
319 size_t len;
320 ssize_t rlen;
321
322 buf = br_ssl_engine_recvrec_buf(cc, &len);
323 rlen = read(fd, buf, len);
324 if (rlen <= 0) {
325 if (verbose) {
326 fprintf(stderr,
327 "socket closed...\n");
328 }
329 retcode = -1;
330 goto engine_exit;
331 }
332 if (trace) {
333 dump_blob("Incoming bytes", buf, rlen);
334 }
335 br_ssl_engine_recvrec_ack(cc, rlen);
336 continue;
337 }
338 }
339 if (sendapp) {
340 if (pfd[k_in].revents & POLLIN) {
341 unsigned char *buf;
342 size_t len;
343 ssize_t rlen;
344
345 buf = br_ssl_engine_sendapp_buf(cc, &len);
346 rlen = read(0, buf, len);
347 if (rlen <= 0) {
348 if (verbose) {
349 fprintf(stderr,
350 "stdin closed...\n");
351 }
352 br_ssl_engine_close(cc);
353 } else if (!run_command(cc, buf, rlen)) {
354 br_ssl_engine_sendapp_ack(cc, rlen);
355 }
356 br_ssl_engine_flush(cc, 0);
357 continue;
358 }
359 }
360
361 /* We should never reach that point. */
362 fprintf(stderr, "ERROR: poll() misbehaves\n");
363 retcode = -2;
364 goto engine_exit;
365 }
366
367 /*
368 * Release allocated structures.
369 */
370 engine_exit:
371 return retcode;
372 }