1 /* $OpenBSD: server.c,v 1.3 2018/11/07 19:09:01 bluhm Exp $ */ 2 /* 3 * Copyright (c) 2018 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 <string.h> 25 #include <unistd.h> 26 27 #include <openssl/err.h> 28 #include <openssl/ssl.h> 29 30 #include "util.h" 31 32 void __dead usage(void); 33 34 void __dead 35 usage(void) 36 { 37 fprintf(stderr, "usage: server [host port]"); 38 exit(2); 39 } 40 41 int 42 main(int argc, char *argv[]) 43 { 44 const SSL_METHOD *method; 45 SSL_CTX *ctx; 46 SSL *ssl; 47 BIO *bio; 48 SSL_SESSION *session; 49 int error; 50 char buf[256]; 51 char *crt, *key, *host_port, *host = "127.0.0.1", *port = "0"; 52 53 if (argc == 3) { 54 host = argv[1]; 55 port = argv[2]; 56 } else if (argc != 1) { 57 usage(); 58 } 59 if (asprintf(&host_port, strchr(host, ':') ? "[%s]:%s" : "%s:%s", 60 host, port) == -1) 61 err(1, "asprintf host port"); 62 if (asprintf(&crt, "%s.crt", host) == -1) 63 err(1, "asprintf crt"); 64 if (asprintf(&key, "%s.key", host) == -1) 65 err(1, "asprintf key"); 66 67 SSL_library_init(); 68 SSL_load_error_strings(); 69 print_version(); 70 71 /* setup method and context */ 72 #if OPENSSL_VERSION_NUMBER >= 0x1010000f 73 method = TLS_server_method(); 74 if (method == NULL) 75 err_ssl(1, "TLS_server_method"); 76 #else 77 method = SSLv23_server_method(); 78 if (method == NULL) 79 err_ssl(1, "SSLv23_server_method"); 80 #endif 81 ctx = SSL_CTX_new(method); 82 if (ctx == NULL) 83 err_ssl(1, "SSL_CTX_new"); 84 85 /* needed when linking with OpenSSL 1.0.2p */ 86 if (SSL_CTX_set_ecdh_auto(ctx, 1) <= 0) 87 err_ssl(1, "SSL_CTX_set_ecdh_auto"); 88 89 /* load server certificate */ 90 if (SSL_CTX_use_certificate_file(ctx, crt, SSL_FILETYPE_PEM) <= 0) 91 err_ssl(1, "SSL_CTX_use_certificate_file"); 92 if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) 93 err_ssl(1, "SSL_CTX_use_PrivateKey_file"); 94 if (SSL_CTX_check_private_key(ctx) <= 0) 95 err_ssl(1, "SSL_CTX_check_private_key"); 96 97 /* setup ssl and bio for socket operations */ 98 ssl = SSL_new(ctx); 99 if (ssl == NULL) 100 err_ssl(1, "SSL_new"); 101 bio = BIO_new_accept(host_port); 102 if (bio == NULL) 103 err_ssl(1, "BIO_new_accept"); 104 print_ciphers(SSL_get_ciphers(ssl)); 105 106 /* bind, listen */ 107 if (BIO_do_accept(bio) <= 0) 108 err_ssl(1, "BIO_do_accept setup"); 109 printf("listen "); 110 print_sockname(bio); 111 112 /* fork to background and accept */ 113 if (daemon(1, 1) == -1) 114 err(1, "daemon"); 115 if (BIO_do_accept(bio) <= 0) 116 err_ssl(1, "BIO_do_accept wait"); 117 bio = BIO_pop(bio); 118 printf("accept "); 119 print_sockname(bio); 120 printf("accept "); 121 print_peername(bio); 122 123 /* do ssl server handshake */ 124 SSL_set_bio(ssl, bio, bio); 125 if ((error = SSL_accept(ssl)) <= 0) 126 err_ssl(1, "SSL_accept %d", error); 127 128 /* print session statistics */ 129 session = SSL_get_session(ssl); 130 if (session == NULL) 131 err_ssl(1, "SSL_get_session"); 132 if (SSL_SESSION_print_fp(stdout, session) <= 0) 133 err_ssl(1, "SSL_SESSION_print_fp"); 134 135 /* write server greeting and read client hello over TLS connection */ 136 strlcpy(buf, "greeting\n", sizeof(buf)); 137 printf(">>> %s", buf); 138 if (fflush(stdout) != 0) 139 err(1, "fflush stdout"); 140 if ((error = SSL_write(ssl, buf, 9)) <= 0) 141 err_ssl(1, "SSL_write %d", error); 142 if (error != 9) 143 errx(1, "write not 9 bytes greeting: %d", error); 144 if ((error = SSL_read(ssl, buf, 6)) <= 0) 145 err_ssl(1, "SSL_read %d", error); 146 if (error != 6) 147 errx(1, "read not 6 bytes hello: %d", error); 148 buf[6] = '\0'; 149 printf("<<< %s", buf); 150 if (fflush(stdout) != 0) 151 err(1, "fflush stdout"); 152 153 /* shutdown connection */ 154 if ((error = SSL_shutdown(ssl)) < 0) 155 err_ssl(1, "SSL_shutdown unidirectional %d", error); 156 if (error <= 0) { 157 if ((error = SSL_shutdown(ssl)) <= 0) 158 err_ssl(1, "SSL_shutdown bidirectional %d", error); 159 } 160 161 /* cleanup and free resources */ 162 SSL_free(ssl); 163 SSL_CTX_free(ctx); 164 165 printf("success\n"); 166 167 return 0; 168 } 169