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