1 /* $OpenBSD: server.c,v 1.10 2021/07/06 11:50:34 bluhm Exp $ */ 2 /* 3 * Copyright (c) 2018-2019 Alexander Bluhm <bluhm@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/types.h> 19 #include <sys/socket.h> 20 21 #include <err.h> 22 #include <netdb.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #include <openssl/err.h> 29 #include <openssl/ssl.h> 30 31 #include "util.h" 32 33 void __dead usage(void); 34 35 void __dead 36 usage(void) 37 { 38 fprintf(stderr, "usage: server [-Lsvv] [-C CA] [-c crt -k key] " 39 "[-l ciphers] [-p dhparam] [-V version] [host port]\n"); 40 exit(2); 41 } 42 43 int 44 main(int argc, char *argv[]) 45 { 46 const SSL_METHOD *method; 47 SSL_CTX *ctx; 48 SSL *ssl; 49 BIO *abio, *cbio; 50 SSL_SESSION *session; 51 int ch, error, listciphers = 0, sessionreuse = 0, verify = 0; 52 int version = 0; 53 char buf[256], *dhparam = NULL; 54 char *ca = NULL, *crt = NULL, *key = NULL, *ciphers = NULL; 55 char *host_port, *host = "127.0.0.1", *port = "0"; 56 57 while ((ch = getopt(argc, argv, "C:c:k:Ll:p:sV:v")) != -1) { 58 switch (ch) { 59 case 'C': 60 ca = optarg; 61 break; 62 case 'c': 63 crt = optarg; 64 break; 65 case 'k': 66 key = optarg; 67 break; 68 case 'L': 69 listciphers = 1; 70 break; 71 case 'l': 72 ciphers = optarg; 73 break; 74 case 'p': 75 dhparam = optarg; 76 break; 77 case 's': 78 /* multiple reueses are possible */ 79 sessionreuse++; 80 break; 81 case 'V': 82 if (strcmp(optarg, "TLS1") == 0) { 83 version = TLS1_VERSION; 84 } else if (strcmp(optarg, "TLS1_1") == 0) { 85 version = TLS1_1_VERSION; 86 } else if (strcmp(optarg, "TLS1_2") == 0) { 87 version = TLS1_2_VERSION; 88 #ifdef TLS1_3_VERSION 89 } else if (strcmp(optarg, "TLS1_3") == 0) { 90 version = TLS1_3_VERSION; 91 #endif 92 } else { 93 errx(1, "unknown protocol version: %s", optarg); 94 } 95 break; 96 case 'v': 97 /* use twice to force client cert */ 98 verify++; 99 break; 100 default: 101 usage(); 102 } 103 } 104 argc -= optind; 105 argv += optind; 106 if (argc == 2) { 107 host = argv[0]; 108 port = argv[1]; 109 } else if (argc != 0 && !listciphers) { 110 usage(); 111 } 112 if (asprintf(&host_port, strchr(host, ':') ? "[%s]:%s" : "%s:%s", 113 host, port) == -1) 114 err(1, "asprintf host port"); 115 if ((crt == NULL && key != NULL) || (crt != NULL && key == NULL)) 116 errx(1, "certificate and private key must be used together"); 117 if (crt == NULL && asprintf(&crt, "%s.crt", host) == -1) 118 err(1, "asprintf crt"); 119 if (key == NULL && asprintf(&key, "%s.key", host) == -1) 120 err(1, "asprintf key"); 121 122 SSL_library_init(); 123 SSL_load_error_strings(); 124 print_version(); 125 126 /* setup method and context */ 127 #if OPENSSL_VERSION_NUMBER >= 0x1010000f 128 method = TLS_server_method(); 129 if (method == NULL) 130 err_ssl(1, "TLS_server_method"); 131 #else 132 switch (version) { 133 case TLS1_VERSION: 134 method = TLSv1_server_method(); 135 break; 136 case TLS1_1_VERSION: 137 method = TLSv1_1_server_method(); 138 break; 139 case TLS1_2_VERSION: 140 method = TLSv1_2_server_method(); 141 break; 142 #ifdef TLS1_3_VERSION 143 case TLS1_3_VERSION: 144 err(1, "TLS1_3 not supported"); 145 #endif 146 default: 147 method = SSLv23_server_method(); 148 break; 149 } 150 if (method == NULL) 151 err_ssl(1, "SSLv23_server_method"); 152 #endif 153 ctx = SSL_CTX_new(method); 154 if (ctx == NULL) 155 err_ssl(1, "SSL_CTX_new"); 156 157 #if OPENSSL_VERSION_NUMBER >= 0x1010000f 158 if (version) { 159 if (SSL_CTX_set_min_proto_version(ctx, version) != 1) 160 err_ssl(1, "SSL_CTX_set_min_proto_version"); 161 if (SSL_CTX_set_max_proto_version(ctx, version) != 1) 162 err_ssl(1, "SSL_CTX_set_max_proto_version"); 163 } 164 #endif 165 166 #if OPENSSL_VERSION_NUMBER >= 0x10100000 167 /* needed to use DHE cipher with libressl */ 168 if (SSL_CTX_set_dh_auto(ctx, 1) <= 0) 169 err_ssl(1, "SSL_CTX_set_dh_auto"); 170 #endif 171 /* needed to use ADH, EDH, DHE cipher with openssl */ 172 if (dhparam != NULL) { 173 DH *dh; 174 FILE *file; 175 176 file = fopen(dhparam, "r"); 177 if (file == NULL) 178 err(1, "fopen %s", dhparam); 179 dh = PEM_read_DHparams(file, NULL, NULL, NULL); 180 if (dh == NULL) 181 err_ssl(1, "PEM_read_DHparams"); 182 if (SSL_CTX_set_tmp_dh(ctx, dh) <= 0) 183 err_ssl(1, "SSL_CTX_set_tmp_dh"); 184 fclose(file); 185 } 186 187 /* needed when linking with OpenSSL 1.0.2p */ 188 if (SSL_CTX_set_ecdh_auto(ctx, 1) <= 0) 189 err_ssl(1, "SSL_CTX_set_ecdh_auto"); 190 191 /* load server certificate */ 192 if (SSL_CTX_use_certificate_file(ctx, crt, SSL_FILETYPE_PEM) <= 0) 193 err_ssl(1, "SSL_CTX_use_certificate_file"); 194 if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) 195 err_ssl(1, "SSL_CTX_use_PrivateKey_file"); 196 if (SSL_CTX_check_private_key(ctx) <= 0) 197 err_ssl(1, "SSL_CTX_check_private_key"); 198 199 /* request client certificate and verify it */ 200 if (ca != NULL) { 201 STACK_OF(X509_NAME) *x509stack; 202 203 x509stack = SSL_load_client_CA_file(ca); 204 if (x509stack == NULL) 205 err_ssl(1, "SSL_load_client_CA_file"); 206 SSL_CTX_set_client_CA_list(ctx, x509stack); 207 if (SSL_CTX_load_verify_locations(ctx, ca, NULL) <= 0) 208 err_ssl(1, "SSL_CTX_load_verify_locations"); 209 } 210 SSL_CTX_set_verify(ctx, 211 verify == 0 ? SSL_VERIFY_NONE : 212 verify == 1 ? SSL_VERIFY_PEER : 213 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 214 verify_callback); 215 216 if (sessionreuse) { 217 uint32_t context; 218 219 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); 220 context = arc4random(); 221 if (SSL_CTX_set_session_id_context(ctx, 222 (unsigned char *)&context, sizeof(context)) <= 0) 223 err_ssl(1, "SSL_CTX_set_session_id_context"); 224 } 225 226 if (ciphers) { 227 if (SSL_CTX_set_cipher_list(ctx, ciphers) <= 0) 228 err_ssl(1, "SSL_CTX_set_cipher_list"); 229 } 230 231 if (listciphers) { 232 ssl = SSL_new(ctx); 233 if (ssl == NULL) 234 err_ssl(1, "SSL_new"); 235 print_ciphers(SSL_get_ciphers(ssl)); 236 return 0; 237 } 238 239 /* setup bio for socket operations */ 240 abio = BIO_new_accept(host_port); 241 if (abio == NULL) 242 err_ssl(1, "BIO_new_accept"); 243 244 /* bind, listen */ 245 if (BIO_do_accept(abio) <= 0) 246 err_ssl(1, "BIO_do_accept setup"); 247 printf("listen "); 248 print_sockname(abio); 249 250 /* fork to background and set timeout */ 251 if (daemon(1, 1) == -1) 252 err(1, "daemon"); 253 alarm(10); 254 255 do { 256 /* accept connection */ 257 if (BIO_do_accept(abio) <= 0) 258 err_ssl(1, "BIO_do_accept wait"); 259 cbio = BIO_pop(abio); 260 printf("accept "); 261 print_sockname(cbio); 262 printf("accept "); 263 print_peername(cbio); 264 265 /* do ssl server handshake */ 266 ssl = SSL_new(ctx); 267 if (ssl == NULL) 268 err_ssl(1, "SSL_new"); 269 SSL_set_bio(ssl, cbio, cbio); 270 if ((error = SSL_accept(ssl)) <= 0) 271 err_ssl(1, "SSL_accept %d", error); 272 printf("session %d: %s\n", sessionreuse, 273 SSL_session_reused(ssl) ? "reuse" : "new"); 274 if (fflush(stdout) != 0) 275 err(1, "fflush stdout"); 276 277 278 /* print session statistics */ 279 session = SSL_get_session(ssl); 280 if (session == NULL) 281 err_ssl(1, "SSL_get_session"); 282 if (SSL_SESSION_print_fp(stdout, session) <= 0) 283 err_ssl(1, "SSL_SESSION_print_fp"); 284 285 /* write server greeting and read client hello over TLS */ 286 strlcpy(buf, "greeting\n", sizeof(buf)); 287 printf(">>> %s", buf); 288 if (fflush(stdout) != 0) 289 err(1, "fflush stdout"); 290 if ((error = SSL_write(ssl, buf, 9)) <= 0) 291 err_ssl(1, "SSL_write %d", error); 292 if (error != 9) 293 errx(1, "write not 9 bytes greeting: %d", error); 294 if ((error = SSL_read(ssl, buf, 6)) <= 0) 295 err_ssl(1, "SSL_read %d", error); 296 if (error != 6) 297 errx(1, "read not 6 bytes hello: %d", error); 298 buf[6] = '\0'; 299 printf("<<< %s", buf); 300 if (fflush(stdout) != 0) 301 err(1, "fflush stdout"); 302 303 /* shutdown connection */ 304 if ((error = SSL_shutdown(ssl)) < 0) 305 err_ssl(1, "SSL_shutdown unidirectional %d", error); 306 if (error <= 0) { 307 if ((error = SSL_shutdown(ssl)) <= 0) 308 err_ssl(1, "SSL_shutdown bidirectional %d", 309 error); 310 } 311 312 SSL_free(ssl); 313 } while (sessionreuse--); 314 315 SSL_CTX_free(ctx); 316 317 printf("success\n"); 318 319 return 0; 320 } 321