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 */ 95 static int 96 host_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 */ 184 static int 185 accept_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 */ 223 static int 224 sock_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 */ 243 static int 244 sock_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 */ 263 static 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 */ 287 int 288 main(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