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#include <signal.h>
31
32#include <sys/types.h>
33#include <sys/socket.h>
34#include <netdb.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37#include <unistd.h>
38
39#include "bearssl.h"
40
41/*
42 * This sample code can use three possible certificate chains:
43 * -- A full-RSA chain (server key is RSA, certificates are signed with RSA)
44 * -- A full-EC chain (server key is EC, certificates are signed with ECDSA)
45 * -- A mixed chain (server key is EC, certificates are signed with RSA)
46 *
47 * The macros below define which chain is selected. This impacts the list
48 * of supported cipher suites.
49 *
50 * Other macros, which can be defined (with a non-zero value):
51 *
52 *   SERVER_PROFILE_MIN_FS
53 *      Select a "minimal" profile with forward security (ECDHE cipher
54 *      suite).
55 *
56 *   SERVER_PROFILE_MIN_NOFS
57 *      Select a "minimal" profile without forward security (RSA or ECDH
58 *      cipher suite, but not ECDHE).
59 *
60 *   SERVER_CHACHA20
61 *      If SERVER_PROFILE_MIN_FS is selected, then this macro selects
62 *      a cipher suite with ChaCha20+Poly1305; otherwise, AES/GCM is
63 *      used. This macro has no effect otherwise, since there is no
64 *      non-forward secure cipher suite that uses ChaCha20+Poly1305.
65 */
66
67#if !(SERVER_RSA || SERVER_EC || SERVER_MIXED)
68#define SERVER_RSA     1
69#define SERVER_EC      0
70#define SERVER_MIXED   0
71#endif
72
73#if SERVER_RSA
74#include "chain-rsa.h"
75#include "key-rsa.h"
76#define SKEY   RSA
77#elif SERVER_EC
78#include "chain-ec.h"
79#include "key-ec.h"
80#define SKEY   EC
81#elif SERVER_MIXED
82#include "chain-ec+rsa.h"
83#include "key-ec.h"
84#define SKEY   EC
85#else
86#error Must use one of RSA, EC or MIXED chains.
87#endif
88
89/*
90 * Create a server socket bound to the specified host and port. If 'host'
91 * is NULL, this will bind "generically" (all addresses).
92 *
93 * Returned value is the server socket descriptor, or -1 on error.
94 */
95static int
96host_bind(const char *host, const char *port)
97{
98	struct addrinfo hints, *si, *p;
99	int fd;
100	int err;
101
102	memset(&hints, 0, sizeof hints);
103	hints.ai_family = PF_UNSPEC;
104	hints.ai_socktype = SOCK_STREAM;
105	err = getaddrinfo(host, port, &hints, &si);
106	if (err != 0) {
107		fprintf(stderr, "ERROR: getaddrinfo(): %s\n",
108			gai_strerror(err));
109		return -1;
110	}
111	fd = -1;
112	for (p = si; p != NULL; p = p->ai_next) {
113		struct sockaddr *sa;
114		struct sockaddr_in sa4;
115		struct sockaddr_in6 sa6;
116		size_t sa_len;
117		void *addr;
118		char tmp[INET6_ADDRSTRLEN + 50];
119		int opt;
120
121		sa = (struct sockaddr *)p->ai_addr;
122		if (sa->sa_family == AF_INET) {
123			sa4 = *(struct sockaddr_in *)sa;
124			sa = (struct sockaddr *)&sa4;
125			sa_len = sizeof sa4;
126			addr = &sa4.sin_addr;
127			if (host == NULL) {
128				sa4.sin_addr.s_addr = INADDR_ANY;
129			}
130		} else if (sa->sa_family == AF_INET6) {
131			sa6 = *(struct sockaddr_in6 *)sa;
132			sa = (struct sockaddr *)&sa6;
133			sa_len = sizeof sa6;
134			addr = &sa6.sin6_addr;
135			if (host == NULL) {
136				sa6.sin6_addr = in6addr_any;
137			}
138		} else {
139			addr = NULL;
140			sa_len = p->ai_addrlen;
141		}
142		if (addr != NULL) {
143			inet_ntop(p->ai_family, addr, tmp, sizeof tmp);
144		} else {
145			sprintf(tmp, "<unknown family: %d>",
146				(int)sa->sa_family);
147		}
148		fprintf(stderr, "binding to: %s\n", tmp);
149		fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
150		if (fd < 0) {
151			perror("socket()");
152			continue;
153		}
154		opt = 1;
155		setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt);
156		opt = 0;
157		setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt);
158		if (bind(fd, sa, sa_len) < 0) {
159			perror("bind()");
160			close(fd);
161			continue;
162		}
163		break;
164	}
165	if (p == NULL) {
166		freeaddrinfo(si);
167		fprintf(stderr, "ERROR: failed to bind\n");
168		return -1;
169	}
170	freeaddrinfo(si);
171	if (listen(fd, 5) < 0) {
172		perror("listen()");
173		close(fd);
174		return -1;
175	}
176	fprintf(stderr, "bound.\n");
177	return fd;
178}
179
180/*
181 * Accept a single client on the provided server socket. This is blocking.
182 * On error, this returns -1.
183 */
184static int
185accept_client(int server_fd)
186{
187	int fd;
188	struct sockaddr sa;
189	socklen_t sa_len;
190	char tmp[INET6_ADDRSTRLEN + 50];
191	const char *name;
192
193	sa_len = sizeof sa;
194	fd = accept(server_fd, &sa, &sa_len);
195	if (fd < 0) {
196		perror("accept()");
197		return -1;
198	}
199	name = NULL;
200	switch (sa.sa_family) {
201	case AF_INET:
202		name = inet_ntop(AF_INET,
203			&((struct sockaddr_in *)&sa)->sin_addr,
204			tmp, sizeof tmp);
205		break;
206	case AF_INET6:
207		name = inet_ntop(AF_INET6,
208			&((struct sockaddr_in6 *)&sa)->sin6_addr,
209			tmp, sizeof tmp);
210		break;
211	}
212	if (name == NULL) {
213		sprintf(tmp, "<unknown: %lu>", (unsigned long)sa.sa_family);
214		name = tmp;
215	}
216	fprintf(stderr, "accepting connection from: %s\n", name);
217	return fd;
218}
219
220/*
221 * Low-level data read callback for the simplified SSL I/O API.
222 */
223static int
224sock_read(void *ctx, unsigned char *buf, size_t len)
225{
226	for (;;) {
227		ssize_t rlen;
228
229		rlen = read(*(int *)ctx, buf, len);
230		if (rlen <= 0) {
231			if (rlen < 0 && errno == EINTR) {
232				continue;
233			}
234			return -1;
235		}
236		return (int)rlen;
237	}
238}
239
240/*
241 * Low-level data write callback for the simplified SSL I/O API.
242 */
243static int
244sock_write(void *ctx, const unsigned char *buf, size_t len)
245{
246	for (;;) {
247		ssize_t wlen;
248
249		wlen = write(*(int *)ctx, buf, len);
250		if (wlen <= 0) {
251			if (wlen < 0 && errno == EINTR) {
252				continue;
253			}
254			return -1;
255		}
256		return (int)wlen;
257	}
258}
259
260/*
261 * Sample HTTP response to send.
262 */
263static const char *HTTP_RES =
264	"HTTP/1.0 200 OK\r\n"
265	"Content-Length: 46\r\n"
266	"Connection: close\r\n"
267	"Content-Type: text/html; charset=iso-8859-1\r\n"
268	"\r\n"
269	"<html>\r\n"
270	"<body>\r\n"
271	"<p>Test!</p>\r\n"
272	"</body>\r\n"
273	"</html>\r\n";
274
275/*
276 * Main program: this is a simple program that expects 1 argument: a
277 * port number. This will start a simple network server on that port,
278 * that expects incoming SSL clients. It handles only one client at a
279 * time (handling several would require threads, sub-processes, or
280 * multiplexing with select()/poll(), all of which being possible).
281 *
282 * For each client, the server will wait for two successive newline
283 * characters (ignoring CR characters, so CR+LF is accepted), then
284 * produce a sample static HTTP response. This is very crude, but
285 * sufficient for explanatory purposes.
286 */
287int
288main(int argc, char *argv[])
289{
290	const char *port;
291	int fd;
292
293	if (argc != 2) {
294		return EXIT_FAILURE;
295	}
296	port = argv[1];
297
298	/*
299	 * Ignore SIGPIPE to avoid crashing in case of abrupt socket close.
300	 */
301	signal(SIGPIPE, SIG_IGN);
302
303	/*
304	 * Open the server socket.
305	 */
306	fd = host_bind(NULL, port);
307	if (fd < 0) {
308		return EXIT_FAILURE;
309	}
310
311	/*
312	 * Process each client, one at a time.
313	 */
314	for (;;) {
315		int cfd;
316		br_ssl_server_context sc;
317		unsigned char iobuf[BR_SSL_BUFSIZE_BIDI];
318		br_sslio_context ioc;
319		int lcwn, err;
320
321		cfd = accept_client(fd);
322		if (cfd < 0) {
323			return EXIT_FAILURE;
324		}
325
326		/*
327		 * Initialise the context with the cipher suites and
328		 * algorithms. This depends on the server key type
329		 * (and, for EC keys, the signature algorithm used by
330		 * the CA to sign the server's certificate).
331		 *
332		 * Depending on the defined macros, we may select one of
333		 * the "minimal" profiles. Key exchange algorithm depends
334		 * on the key type:
335		 *   RSA key: RSA or ECDHE_RSA
336		 *   EC key, cert signed with ECDSA: ECDH_ECDSA or ECDHE_ECDSA
337		 *   EC key, cert signed with RSA: ECDH_RSA or ECDHE_ECDSA
338		 */
339#if SERVER_RSA
340#if SERVER_PROFILE_MIN_FS
341#if SERVER_CHACHA20
342		br_ssl_server_init_mine2c(&sc, CHAIN, CHAIN_LEN, &SKEY);
343#else
344		br_ssl_server_init_mine2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
345#endif
346#elif SERVER_PROFILE_MIN_NOFS
347		br_ssl_server_init_minr2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
348#else
349		br_ssl_server_init_full_rsa(&sc, CHAIN, CHAIN_LEN, &SKEY);
350#endif
351#elif SERVER_EC
352#if SERVER_PROFILE_MIN_FS
353#if SERVER_CHACHA20
354		br_ssl_server_init_minf2c(&sc, CHAIN, CHAIN_LEN, &SKEY);
355#else
356		br_ssl_server_init_minf2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
357#endif
358#elif SERVER_PROFILE_MIN_NOFS
359		br_ssl_server_init_minv2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
360#else
361		br_ssl_server_init_full_ec(&sc, CHAIN, CHAIN_LEN,
362			BR_KEYTYPE_EC, &SKEY);
363#endif
364#else /* SERVER_MIXED */
365#if SERVER_PROFILE_MIN_FS
366#if SERVER_CHACHA20
367		br_ssl_server_init_minf2c(&sc, CHAIN, CHAIN_LEN, &SKEY);
368#else
369		br_ssl_server_init_minf2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
370#endif
371#elif SERVER_PROFILE_MIN_NOFS
372		br_ssl_server_init_minu2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
373#else
374		br_ssl_server_init_full_ec(&sc, CHAIN, CHAIN_LEN,
375			BR_KEYTYPE_RSA, &SKEY);
376#endif
377#endif
378		/*
379		 * Set the I/O buffer to the provided array. We
380		 * allocated a buffer large enough for full-duplex
381		 * behaviour with all allowed sizes of SSL records,
382		 * hence we set the last argument to 1 (which means
383		 * "split the buffer into separate input and output
384		 * areas").
385		 */
386		br_ssl_engine_set_buffer(&sc.eng, iobuf, sizeof iobuf, 1);
387
388		/*
389		 * Reset the server context, for a new handshake.
390		 */
391		br_ssl_server_reset(&sc);
392
393		/*
394		 * Initialise the simplified I/O wrapper context.
395		 */
396		br_sslio_init(&ioc, &sc.eng, sock_read, &cfd, sock_write, &cfd);
397
398		/*
399		 * Read bytes until two successive LF (or CR+LF) are received.
400		 */
401		lcwn = 0;
402		for (;;) {
403			unsigned char x;
404
405			if (br_sslio_read(&ioc, &x, 1) < 0) {
406				goto client_drop;
407			}
408			if (x == 0x0D) {
409				continue;
410			}
411			if (x == 0x0A) {
412				if (lcwn) {
413					break;
414				}
415				lcwn = 1;
416			} else {
417				lcwn = 0;
418			}
419		}
420
421		/*
422		 * Write a response and close the connection.
423		 */
424		br_sslio_write_all(&ioc, HTTP_RES, strlen(HTTP_RES));
425		br_sslio_close(&ioc);
426
427	client_drop:
428		err = br_ssl_engine_last_error(&sc.eng);
429		if (err == 0) {
430			fprintf(stderr, "SSL closed (correctly).\n");
431		} else {
432			fprintf(stderr, "SSL error: %d\n", err);
433		}
434		close(cfd);
435	}
436}
437