1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc. 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies. 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/base.h> 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ssl.h> 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h" 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "transport_common.h" 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const struct argument kArguments[] = { 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 26e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "-accept", kRequiredArgument, 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "The port of the server to bind on; eg 45102", 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley }, 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 30e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "-cipher", kOptionalArgument, 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "An OpenSSL-style cipher suite string that configures the offered ciphers", 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley }, 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 34e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "-key", kOptionalArgument, 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "Private-key file to use (default is server.pem)", 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley }, 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 38b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root "-ocsp-response", kOptionalArgument, 39b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root "OCSP response file to send", 40b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root }, 41b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root { 42e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "", kOptionalArgument, "", 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley }, 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 46b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic bool LoadOCSPResponse(SSL_CTX *ctx, const char *filename) { 47b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root void *data = NULL; 48b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root bool ret = false; 49b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root size_t bytes_read; 50b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root long length; 51b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 52b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root FILE *f = fopen(filename, "rb"); 53b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 54b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (f == NULL || 55b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root fseek(f, 0, SEEK_END) != 0) { 56b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root goto out; 57b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 58b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 59b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root length = ftell(f); 60b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (length < 0) { 61b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root goto out; 62b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 63b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 64b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root data = malloc(length); 65b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (data == NULL) { 66b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root goto out; 67b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 68b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root rewind(f); 69b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 70b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root bytes_read = fread(data, 1, length, f); 71b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (ferror(f) != 0 || 72b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root bytes_read != (size_t)length || 73b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root !SSL_CTX_set_ocsp_response(ctx, (uint8_t*)data, bytes_read)) { 74b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root goto out; 75b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 76b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 77b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root ret = true; 78b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootout: 79b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (f != NULL) { 80b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root fclose(f); 81b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 82b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root free(data); 83b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return ret; 84b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root} 85b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langleybool Server(const std::vector<std::string> &args) { 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!InitSocketLibrary()) { 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return false; 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley std::map<std::string, std::string> args_map; 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ParseKeyValueArguments(&args_map, args, kArguments)) { 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PrintUsage(kArguments); 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return false; 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method()); 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley // Server authentication is required. 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley std::string key_file = "server.pem"; 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (args_map.count("-key") != 0) { 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley key_file = args_map["-key"]; 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1064139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (!SSL_CTX_use_PrivateKey_file(ctx, key_file.c_str(), SSL_FILETYPE_PEM)) { 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str()); 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return false; 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1104139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (!SSL_CTX_use_certificate_chain_file(ctx, key_file.c_str())) { 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str()); 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return false; 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (args_map.count("-cipher") != 0 && 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str())) { 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Failed setting cipher list\n"); 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return false; 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 121b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (args_map.count("-ocsp-response") != 0 && 122b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root !LoadOCSPResponse(ctx, args_map["-ocsp-response"].c_str())) { 123b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root fprintf(stderr, "Failed to load OCSP response: %s\n", args_map["-ocsp-response"].c_str()); 124b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return false; 125b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 126b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int sock = -1; 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!Accept(&sock, args_map["-accept"])) { 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return false; 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *bio = BIO_new_socket(sock, BIO_CLOSE); 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley SSL *ssl = SSL_new(ctx); 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley SSL_set_bio(ssl, bio, bio); 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = SSL_accept(ssl); 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret != 1) { 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ssl_err = SSL_get_error(ssl, ret); 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Error while connecting: %d\n", ssl_err); 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_print_errors_cb(PrintErrorCallback, stderr); 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return false; 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Connected.\n"); 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley PrintConnectionInfo(ssl); 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bool ok = TransferData(ssl, sock); 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley SSL_free(ssl); 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley SSL_CTX_free(ctx); 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ok; 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 153