1 /* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/base.h>
16
17 #include <openssl/err.h>
18 #include <openssl/ssl.h>
19
20 #include "internal.h"
21 #include "transport_common.h"
22
23
24 static const struct argument kArguments[] = {
25 {
26 "-accept", kRequiredArgument,
27 "The port of the server to bind on; eg 45102",
28 },
29 {
30 "-cipher", kOptionalArgument,
31 "An OpenSSL-style cipher suite string that configures the offered ciphers",
32 },
33 {
34 "-key", kOptionalArgument,
35 "Private-key file to use (default is server.pem)",
36 },
37 {
38 "", kOptionalArgument, "",
39 },
40 };
41
Server(const std::vector<std::string> & args)42 bool Server(const std::vector<std::string> &args) {
43 if (!InitSocketLibrary()) {
44 return false;
45 }
46
47 std::map<std::string, std::string> args_map;
48
49 if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
50 PrintUsage(kArguments);
51 return false;
52 }
53
54 SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
55 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
56
57 // Server authentication is required.
58 std::string key_file = "server.pem";
59 if (args_map.count("-key") != 0) {
60 key_file = args_map["-key"];
61 }
62 if (SSL_CTX_use_PrivateKey_file(ctx, key_file.c_str(), SSL_FILETYPE_PEM) <= 0) {
63 fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str());
64 return false;
65 }
66 if (SSL_CTX_use_certificate_chain_file(ctx, key_file.c_str()) != 1) {
67 fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str());
68 return false;
69 }
70
71 if (args_map.count("-cipher") != 0 &&
72 !SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str())) {
73 fprintf(stderr, "Failed setting cipher list\n");
74 return false;
75 }
76
77 int sock = -1;
78 if (!Accept(&sock, args_map["-accept"])) {
79 return false;
80 }
81
82 BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
83 SSL *ssl = SSL_new(ctx);
84 SSL_set_bio(ssl, bio, bio);
85
86 int ret = SSL_accept(ssl);
87 if (ret != 1) {
88 int ssl_err = SSL_get_error(ssl, ret);
89 fprintf(stderr, "Error while connecting: %d\n", ssl_err);
90 ERR_print_errors_cb(PrintErrorCallback, stderr);
91 return false;
92 }
93
94 fprintf(stderr, "Connected.\n");
95 PrintConnectionInfo(ssl);
96
97 bool ok = TransferData(ssl, sock);
98
99 SSL_free(ssl);
100 SSL_CTX_free(ctx);
101 return ok;
102 }
103