xref: /openbsd-src/regress/lib/libssl/interop/server.c (revision a8d85e88ed9b5d655d229d3ed8828f64afac8a9f)
1 /*	$OpenBSD: server.c,v 1.4 2018/11/09 06:30:41 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,
38 	    "usage: server [-vv] [-C CA] [-c crt -k key] [host port]");
39 	exit(2);
40 }
41 
42 int
43 main(int argc, char *argv[])
44 {
45 	const SSL_METHOD *method;
46 	SSL_CTX *ctx;
47 	SSL *ssl;
48 	BIO *bio;
49 	SSL_SESSION *session;
50 	int error, verify = 0;
51 	char buf[256], ch;
52 	char *ca = NULL, *crt = NULL, *key = NULL;
53 	char *host_port, *host = "127.0.0.1", *port = "0";
54 
55 	while ((ch = getopt(argc, argv, "C:c:k:v")) != -1) {
56 		switch (ch) {
57 		case 'C':
58 			ca = optarg;
59 			break;
60 		case 'c':
61 			crt = optarg;
62 			break;
63 		case 'k':
64 			key = optarg;
65 			break;
66 		case 'v':
67 			/* use twice to force client cert */
68 			verify++;
69 			break;
70 		default:
71 			usage();
72 		}
73 	}
74 	argc -= optind;
75 	argv += optind;
76 	if (argc == 2) {
77 		host = argv[0];
78 		port = argv[1];
79 	} else if (argc != 0) {
80 		usage();
81 	}
82 	if (asprintf(&host_port, strchr(host, ':') ? "[%s]:%s" : "%s:%s",
83 	    host, port) == -1)
84 		err(1, "asprintf host port");
85 	if ((crt == NULL && key != NULL) || (crt != NULL && key == NULL))
86 		errx(1, "certificate and private key must be used together");
87 	if (crt == NULL && asprintf(&crt, "%s.crt", host) == -1)
88 		err(1, "asprintf crt");
89 	if (key == NULL && asprintf(&key, "%s.key", host) == -1)
90 		err(1, "asprintf key");
91 
92 	SSL_library_init();
93 	SSL_load_error_strings();
94 	print_version();
95 
96 	/* setup method and context */
97 #if OPENSSL_VERSION_NUMBER >= 0x1010000f
98 	method = TLS_server_method();
99 	if (method == NULL)
100 		err_ssl(1, "TLS_server_method");
101 #else
102 	method = SSLv23_server_method();
103 	if (method == NULL)
104 		err_ssl(1, "SSLv23_server_method");
105 #endif
106 	ctx = SSL_CTX_new(method);
107 	if (ctx == NULL)
108 		err_ssl(1, "SSL_CTX_new");
109 
110 	/* needed when linking with OpenSSL 1.0.2p */
111 	if (SSL_CTX_set_ecdh_auto(ctx, 1) <= 0)
112 		err_ssl(1, "SSL_CTX_set_ecdh_auto");
113 
114 	/* load server certificate */
115 	if (SSL_CTX_use_certificate_file(ctx, crt, SSL_FILETYPE_PEM) <= 0)
116 		err_ssl(1, "SSL_CTX_use_certificate_file");
117 	if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0)
118 		err_ssl(1, "SSL_CTX_use_PrivateKey_file");
119 	if (SSL_CTX_check_private_key(ctx) <= 0)
120 		err_ssl(1, "SSL_CTX_check_private_key");
121 
122 	/* request client certificate and verify it */
123 	if (ca != NULL) {
124 		STACK_OF(X509_NAME) *x509stack;
125 
126 		x509stack = SSL_load_client_CA_file(ca);
127 		if (x509stack == NULL)
128 			err_ssl(1, "SSL_load_client_CA_file");
129 		SSL_CTX_set_client_CA_list(ctx, x509stack);
130 		if (SSL_CTX_load_verify_locations(ctx, ca, NULL) <= 0)
131 			err_ssl(1, "SSL_CTX_load_verify_locations");
132 	}
133 	SSL_CTX_set_verify(ctx,
134 	    verify == 0 ?  SSL_VERIFY_NONE :
135 	    verify == 1 ?  SSL_VERIFY_PEER :
136 	    SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
137 	    verify_callback);
138 
139 	/* setup ssl and bio for socket operations */
140 	ssl = SSL_new(ctx);
141 	if (ssl == NULL)
142 		err_ssl(1, "SSL_new");
143 	bio = BIO_new_accept(host_port);
144 	if (bio == NULL)
145 		err_ssl(1, "BIO_new_accept");
146 	print_ciphers(SSL_get_ciphers(ssl));
147 
148 	/* bind, listen */
149 	if (BIO_do_accept(bio) <= 0)
150 		err_ssl(1, "BIO_do_accept setup");
151 	printf("listen ");
152 	print_sockname(bio);
153 
154 	/* fork to background, set timeout, and accept */
155 	if (daemon(1, 1) == -1)
156 		err(1, "daemon");
157 	if ((int)alarm(60) == -1)
158 		err(1, "alarm");
159 	if (BIO_do_accept(bio) <= 0)
160 		err_ssl(1, "BIO_do_accept wait");
161 	bio = BIO_pop(bio);
162 	printf("accept ");
163 	print_sockname(bio);
164 	printf("accept ");
165 	print_peername(bio);
166 
167 	/* do ssl server handshake */
168 	SSL_set_bio(ssl, bio, bio);
169 	if ((error = SSL_accept(ssl)) <= 0)
170 		err_ssl(1, "SSL_accept %d", error);
171 
172 	/* print session statistics */
173 	session = SSL_get_session(ssl);
174 	if (session == NULL)
175 		err_ssl(1, "SSL_get_session");
176 	if (SSL_SESSION_print_fp(stdout, session) <= 0)
177 		err_ssl(1, "SSL_SESSION_print_fp");
178 
179 	/* write server greeting and read client hello over TLS connection */
180 	strlcpy(buf, "greeting\n", sizeof(buf));
181 	printf(">>> %s", buf);
182 	if (fflush(stdout) != 0)
183 		err(1, "fflush stdout");
184 	if ((error = SSL_write(ssl, buf, 9)) <= 0)
185 		err_ssl(1, "SSL_write %d", error);
186 	if (error != 9)
187 		errx(1, "write not 9 bytes greeting: %d", error);
188 	if ((error = SSL_read(ssl, buf, 6)) <= 0)
189 		err_ssl(1, "SSL_read %d", error);
190 	if (error != 6)
191 		errx(1, "read not 6 bytes hello: %d", error);
192 	buf[6] = '\0';
193 	printf("<<< %s", buf);
194 	if (fflush(stdout) != 0)
195 		err(1, "fflush stdout");
196 
197 	/* shutdown connection */
198 	if ((error = SSL_shutdown(ssl)) < 0)
199 		err_ssl(1, "SSL_shutdown unidirectional %d", error);
200 	if (error <= 0) {
201 		if ((error = SSL_shutdown(ssl)) <= 0)
202 			err_ssl(1, "SSL_shutdown bidirectional %d", error);
203 	}
204 
205 	/* cleanup and free resources */
206 	SSL_free(ssl);
207 	SSL_CTX_free(ctx);
208 
209 	printf("success\n");
210 
211 	return 0;
212 }
213