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    {
38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley     "", kOptionalArgument, "",
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    },
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley};
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langleybool Server(const std::vector<std::string> &args) {
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!InitSocketLibrary()) {
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  std::map<std::string, std::string> args_map;
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    PrintUsage(kArguments);
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // Server authentication is required.
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  std::string key_file = "server.pem";
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (args_map.count("-key") != 0) {
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    key_file = args_map["-key"];
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (SSL_CTX_use_PrivateKey_file(ctx, key_file.c_str(), SSL_FILETYPE_PEM) <= 0) {
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str());
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (SSL_CTX_use_certificate_chain_file(ctx, key_file.c_str()) != 1) {
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str());
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (args_map.count("-cipher") != 0 &&
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str())) {
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "Failed setting cipher list\n");
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int sock = -1;
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!Accept(&sock, args_map["-accept"])) {
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  SSL *ssl = SSL_new(ctx);
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  SSL_set_bio(ssl, bio, bio);
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ret = SSL_accept(ssl);
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret != 1) {
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    int ssl_err = SSL_get_error(ssl, ret);
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "Error while connecting: %d\n", ssl_err);
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ERR_print_errors_cb(PrintErrorCallback, stderr);
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  fprintf(stderr, "Connected.\n");
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  PrintConnectionInfo(ssl);
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  bool ok = TransferData(ssl, sock);
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  SSL_free(ssl);
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  SSL_CTX_free(ctx);
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ok;
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
103