1*0957b409SSimon J. Gerraty /*
2*0957b409SSimon J. Gerraty * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3*0957b409SSimon J. Gerraty *
4*0957b409SSimon J. Gerraty * Permission is hereby granted, free of charge, to any person obtaining
5*0957b409SSimon J. Gerraty * a copy of this software and associated documentation files (the
6*0957b409SSimon J. Gerraty * "Software"), to deal in the Software without restriction, including
7*0957b409SSimon J. Gerraty * without limitation the rights to use, copy, modify, merge, publish,
8*0957b409SSimon J. Gerraty * distribute, sublicense, and/or sell copies of the Software, and to
9*0957b409SSimon J. Gerraty * permit persons to whom the Software is furnished to do so, subject to
10*0957b409SSimon J. Gerraty * the following conditions:
11*0957b409SSimon J. Gerraty *
12*0957b409SSimon J. Gerraty * The above copyright notice and this permission notice shall be
13*0957b409SSimon J. Gerraty * included in all copies or substantial portions of the Software.
14*0957b409SSimon J. Gerraty *
15*0957b409SSimon J. Gerraty * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*0957b409SSimon J. Gerraty * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*0957b409SSimon J. Gerraty * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*0957b409SSimon J. Gerraty * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*0957b409SSimon J. Gerraty * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*0957b409SSimon J. Gerraty * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*0957b409SSimon J. Gerraty * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*0957b409SSimon J. Gerraty * SOFTWARE.
23*0957b409SSimon J. Gerraty */
24*0957b409SSimon J. Gerraty
25*0957b409SSimon J. Gerraty #include <stdio.h>
26*0957b409SSimon J. Gerraty #include <stdlib.h>
27*0957b409SSimon J. Gerraty #include <string.h>
28*0957b409SSimon J. Gerraty #include <stdint.h>
29*0957b409SSimon J. Gerraty #include <errno.h>
30*0957b409SSimon J. Gerraty #include <signal.h>
31*0957b409SSimon J. Gerraty
32*0957b409SSimon J. Gerraty #ifdef _WIN32
33*0957b409SSimon J. Gerraty #include <winsock2.h>
34*0957b409SSimon J. Gerraty #include <ws2tcpip.h>
35*0957b409SSimon J. Gerraty #else
36*0957b409SSimon J. Gerraty #include <sys/types.h>
37*0957b409SSimon J. Gerraty #include <sys/socket.h>
38*0957b409SSimon J. Gerraty #include <netdb.h>
39*0957b409SSimon J. Gerraty #include <netinet/in.h>
40*0957b409SSimon J. Gerraty #include <arpa/inet.h>
41*0957b409SSimon J. Gerraty #include <unistd.h>
42*0957b409SSimon J. Gerraty #include <fcntl.h>
43*0957b409SSimon J. Gerraty
44*0957b409SSimon J. Gerraty #define SOCKET int
45*0957b409SSimon J. Gerraty #define INVALID_SOCKET (-1)
46*0957b409SSimon J. Gerraty #define SOCKADDR_STORAGE struct sockaddr_storage
47*0957b409SSimon J. Gerraty #endif
48*0957b409SSimon J. Gerraty
49*0957b409SSimon J. Gerraty #include "brssl.h"
50*0957b409SSimon J. Gerraty
51*0957b409SSimon J. Gerraty static SOCKET
host_bind(const char * host,const char * port,int verbose)52*0957b409SSimon J. Gerraty host_bind(const char *host, const char *port, int verbose)
53*0957b409SSimon J. Gerraty {
54*0957b409SSimon J. Gerraty struct addrinfo hints, *si, *p;
55*0957b409SSimon J. Gerraty SOCKET fd;
56*0957b409SSimon J. Gerraty int err;
57*0957b409SSimon J. Gerraty
58*0957b409SSimon J. Gerraty memset(&hints, 0, sizeof hints);
59*0957b409SSimon J. Gerraty hints.ai_family = PF_UNSPEC;
60*0957b409SSimon J. Gerraty hints.ai_socktype = SOCK_STREAM;
61*0957b409SSimon J. Gerraty err = getaddrinfo(host, port, &hints, &si);
62*0957b409SSimon J. Gerraty if (err != 0) {
63*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: getaddrinfo(): %s\n",
64*0957b409SSimon J. Gerraty gai_strerror(err));
65*0957b409SSimon J. Gerraty return INVALID_SOCKET;
66*0957b409SSimon J. Gerraty }
67*0957b409SSimon J. Gerraty fd = INVALID_SOCKET;
68*0957b409SSimon J. Gerraty for (p = si; p != NULL; p = p->ai_next) {
69*0957b409SSimon J. Gerraty struct sockaddr *sa;
70*0957b409SSimon J. Gerraty struct sockaddr_in sa4;
71*0957b409SSimon J. Gerraty struct sockaddr_in6 sa6;
72*0957b409SSimon J. Gerraty size_t sa_len;
73*0957b409SSimon J. Gerraty void *addr;
74*0957b409SSimon J. Gerraty int opt;
75*0957b409SSimon J. Gerraty
76*0957b409SSimon J. Gerraty sa = (struct sockaddr *)p->ai_addr;
77*0957b409SSimon J. Gerraty if (sa->sa_family == AF_INET) {
78*0957b409SSimon J. Gerraty memcpy(&sa4, sa, sizeof sa4);
79*0957b409SSimon J. Gerraty sa = (struct sockaddr *)&sa4;
80*0957b409SSimon J. Gerraty sa_len = sizeof sa4;
81*0957b409SSimon J. Gerraty addr = &sa4.sin_addr;
82*0957b409SSimon J. Gerraty if (host == NULL) {
83*0957b409SSimon J. Gerraty sa4.sin_addr.s_addr = INADDR_ANY;
84*0957b409SSimon J. Gerraty }
85*0957b409SSimon J. Gerraty } else if (sa->sa_family == AF_INET6) {
86*0957b409SSimon J. Gerraty memcpy(&sa6, sa, sizeof sa6);
87*0957b409SSimon J. Gerraty sa = (struct sockaddr *)&sa6;
88*0957b409SSimon J. Gerraty sa_len = sizeof sa6;
89*0957b409SSimon J. Gerraty addr = &sa6.sin6_addr;
90*0957b409SSimon J. Gerraty if (host == NULL) {
91*0957b409SSimon J. Gerraty sa6.sin6_addr = in6addr_any;
92*0957b409SSimon J. Gerraty }
93*0957b409SSimon J. Gerraty } else {
94*0957b409SSimon J. Gerraty addr = NULL;
95*0957b409SSimon J. Gerraty sa_len = p->ai_addrlen;
96*0957b409SSimon J. Gerraty }
97*0957b409SSimon J. Gerraty if (verbose) {
98*0957b409SSimon J. Gerraty char tmp[INET6_ADDRSTRLEN + 50];
99*0957b409SSimon J. Gerraty
100*0957b409SSimon J. Gerraty if (addr != NULL) {
101*0957b409SSimon J. Gerraty if (!inet_ntop(p->ai_family, addr,
102*0957b409SSimon J. Gerraty tmp, sizeof tmp))
103*0957b409SSimon J. Gerraty {
104*0957b409SSimon J. Gerraty strcpy(tmp, "<invalid>");
105*0957b409SSimon J. Gerraty }
106*0957b409SSimon J. Gerraty } else {
107*0957b409SSimon J. Gerraty sprintf(tmp, "<unknown family: %d>",
108*0957b409SSimon J. Gerraty (int)sa->sa_family);
109*0957b409SSimon J. Gerraty }
110*0957b409SSimon J. Gerraty fprintf(stderr, "binding to: %s\n", tmp);
111*0957b409SSimon J. Gerraty }
112*0957b409SSimon J. Gerraty fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
113*0957b409SSimon J. Gerraty if (fd == INVALID_SOCKET) {
114*0957b409SSimon J. Gerraty if (verbose) {
115*0957b409SSimon J. Gerraty perror("socket()");
116*0957b409SSimon J. Gerraty }
117*0957b409SSimon J. Gerraty continue;
118*0957b409SSimon J. Gerraty }
119*0957b409SSimon J. Gerraty opt = 1;
120*0957b409SSimon J. Gerraty setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
121*0957b409SSimon J. Gerraty (void *)&opt, sizeof opt);
122*0957b409SSimon J. Gerraty #ifdef IPV6_V6ONLY
123*0957b409SSimon J. Gerraty /*
124*0957b409SSimon J. Gerraty * We want to make sure that the server socket works for
125*0957b409SSimon J. Gerraty * both IPv4 and IPv6. But IPV6_V6ONLY is not defined on
126*0957b409SSimon J. Gerraty * some very old systems.
127*0957b409SSimon J. Gerraty */
128*0957b409SSimon J. Gerraty opt = 0;
129*0957b409SSimon J. Gerraty setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
130*0957b409SSimon J. Gerraty (void *)&opt, sizeof opt);
131*0957b409SSimon J. Gerraty #endif
132*0957b409SSimon J. Gerraty if (bind(fd, sa, sa_len) < 0) {
133*0957b409SSimon J. Gerraty if (verbose) {
134*0957b409SSimon J. Gerraty perror("bind()");
135*0957b409SSimon J. Gerraty }
136*0957b409SSimon J. Gerraty #ifdef _WIN32
137*0957b409SSimon J. Gerraty closesocket(fd);
138*0957b409SSimon J. Gerraty #else
139*0957b409SSimon J. Gerraty close(fd);
140*0957b409SSimon J. Gerraty #endif
141*0957b409SSimon J. Gerraty continue;
142*0957b409SSimon J. Gerraty }
143*0957b409SSimon J. Gerraty break;
144*0957b409SSimon J. Gerraty }
145*0957b409SSimon J. Gerraty if (p == NULL) {
146*0957b409SSimon J. Gerraty freeaddrinfo(si);
147*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: failed to bind\n");
148*0957b409SSimon J. Gerraty return INVALID_SOCKET;
149*0957b409SSimon J. Gerraty }
150*0957b409SSimon J. Gerraty freeaddrinfo(si);
151*0957b409SSimon J. Gerraty if (listen(fd, 5) < 0) {
152*0957b409SSimon J. Gerraty if (verbose) {
153*0957b409SSimon J. Gerraty perror("listen()");
154*0957b409SSimon J. Gerraty }
155*0957b409SSimon J. Gerraty #ifdef _WIN32
156*0957b409SSimon J. Gerraty closesocket(fd);
157*0957b409SSimon J. Gerraty #else
158*0957b409SSimon J. Gerraty close(fd);
159*0957b409SSimon J. Gerraty #endif
160*0957b409SSimon J. Gerraty return INVALID_SOCKET;
161*0957b409SSimon J. Gerraty }
162*0957b409SSimon J. Gerraty if (verbose) {
163*0957b409SSimon J. Gerraty fprintf(stderr, "bound.\n");
164*0957b409SSimon J. Gerraty }
165*0957b409SSimon J. Gerraty return fd;
166*0957b409SSimon J. Gerraty }
167*0957b409SSimon J. Gerraty
168*0957b409SSimon J. Gerraty static SOCKET
accept_client(SOCKET server_fd,int verbose,int nonblock)169*0957b409SSimon J. Gerraty accept_client(SOCKET server_fd, int verbose, int nonblock)
170*0957b409SSimon J. Gerraty {
171*0957b409SSimon J. Gerraty int fd;
172*0957b409SSimon J. Gerraty SOCKADDR_STORAGE sa;
173*0957b409SSimon J. Gerraty socklen_t sa_len;
174*0957b409SSimon J. Gerraty
175*0957b409SSimon J. Gerraty sa_len = sizeof sa;
176*0957b409SSimon J. Gerraty fd = accept(server_fd, (struct sockaddr *)&sa, &sa_len);
177*0957b409SSimon J. Gerraty if (fd == INVALID_SOCKET) {
178*0957b409SSimon J. Gerraty if (verbose) {
179*0957b409SSimon J. Gerraty perror("accept()");
180*0957b409SSimon J. Gerraty }
181*0957b409SSimon J. Gerraty return INVALID_SOCKET;
182*0957b409SSimon J. Gerraty }
183*0957b409SSimon J. Gerraty if (verbose) {
184*0957b409SSimon J. Gerraty char tmp[INET6_ADDRSTRLEN + 50];
185*0957b409SSimon J. Gerraty const char *name;
186*0957b409SSimon J. Gerraty
187*0957b409SSimon J. Gerraty name = NULL;
188*0957b409SSimon J. Gerraty switch (((struct sockaddr *)&sa)->sa_family) {
189*0957b409SSimon J. Gerraty case AF_INET:
190*0957b409SSimon J. Gerraty name = inet_ntop(AF_INET,
191*0957b409SSimon J. Gerraty &((struct sockaddr_in *)&sa)->sin_addr,
192*0957b409SSimon J. Gerraty tmp, sizeof tmp);
193*0957b409SSimon J. Gerraty break;
194*0957b409SSimon J. Gerraty case AF_INET6:
195*0957b409SSimon J. Gerraty name = inet_ntop(AF_INET6,
196*0957b409SSimon J. Gerraty &((struct sockaddr_in6 *)&sa)->sin6_addr,
197*0957b409SSimon J. Gerraty tmp, sizeof tmp);
198*0957b409SSimon J. Gerraty break;
199*0957b409SSimon J. Gerraty }
200*0957b409SSimon J. Gerraty if (name == NULL) {
201*0957b409SSimon J. Gerraty sprintf(tmp, "<unknown: %lu>", (unsigned long)
202*0957b409SSimon J. Gerraty ((struct sockaddr *)&sa)->sa_family);
203*0957b409SSimon J. Gerraty name = tmp;
204*0957b409SSimon J. Gerraty }
205*0957b409SSimon J. Gerraty fprintf(stderr, "accepting connection from: %s\n", name);
206*0957b409SSimon J. Gerraty }
207*0957b409SSimon J. Gerraty
208*0957b409SSimon J. Gerraty /*
209*0957b409SSimon J. Gerraty * We make the socket non-blocking, since we are going to use
210*0957b409SSimon J. Gerraty * poll() or select() to organise I/O.
211*0957b409SSimon J. Gerraty */
212*0957b409SSimon J. Gerraty if (nonblock) {
213*0957b409SSimon J. Gerraty #ifdef _WIN32
214*0957b409SSimon J. Gerraty u_long arg;
215*0957b409SSimon J. Gerraty
216*0957b409SSimon J. Gerraty arg = 1;
217*0957b409SSimon J. Gerraty ioctlsocket(fd, FIONBIO, &arg);
218*0957b409SSimon J. Gerraty #else
219*0957b409SSimon J. Gerraty fcntl(fd, F_SETFL, O_NONBLOCK);
220*0957b409SSimon J. Gerraty #endif
221*0957b409SSimon J. Gerraty }
222*0957b409SSimon J. Gerraty return fd;
223*0957b409SSimon J. Gerraty }
224*0957b409SSimon J. Gerraty
225*0957b409SSimon J. Gerraty static void
usage_server(void)226*0957b409SSimon J. Gerraty usage_server(void)
227*0957b409SSimon J. Gerraty {
228*0957b409SSimon J. Gerraty fprintf(stderr,
229*0957b409SSimon J. Gerraty "usage: brssl server [ options ]\n");
230*0957b409SSimon J. Gerraty fprintf(stderr,
231*0957b409SSimon J. Gerraty "options:\n");
232*0957b409SSimon J. Gerraty fprintf(stderr,
233*0957b409SSimon J. Gerraty " -q suppress verbose messages\n");
234*0957b409SSimon J. Gerraty fprintf(stderr,
235*0957b409SSimon J. Gerraty " -trace activate extra debug messages (dump of all packets)\n");
236*0957b409SSimon J. Gerraty fprintf(stderr,
237*0957b409SSimon J. Gerraty " -b name bind to a specific address or host name\n");
238*0957b409SSimon J. Gerraty fprintf(stderr,
239*0957b409SSimon J. Gerraty " -p port bind to a specific port (default: 4433)\n");
240*0957b409SSimon J. Gerraty fprintf(stderr,
241*0957b409SSimon J. Gerraty " -mono use monodirectional buffering\n");
242*0957b409SSimon J. Gerraty fprintf(stderr,
243*0957b409SSimon J. Gerraty " -buf length set the I/O buffer length (in bytes)\n");
244*0957b409SSimon J. Gerraty fprintf(stderr,
245*0957b409SSimon J. Gerraty " -cache length set the session cache storage length (in bytes)\n");
246*0957b409SSimon J. Gerraty fprintf(stderr,
247*0957b409SSimon J. Gerraty " -cert fname read certificate chain from file 'fname'\n");
248*0957b409SSimon J. Gerraty fprintf(stderr,
249*0957b409SSimon J. Gerraty " -key fname read private key from file 'fname'\n");
250*0957b409SSimon J. Gerraty fprintf(stderr,
251*0957b409SSimon J. Gerraty " -CA file add trust anchors from 'file' (for client auth)\n");
252*0957b409SSimon J. Gerraty fprintf(stderr,
253*0957b409SSimon J. Gerraty " -anon_ok request but do not require a client certificate\n");
254*0957b409SSimon J. Gerraty fprintf(stderr,
255*0957b409SSimon J. Gerraty " -list list supported names (protocols, algorithms...)\n");
256*0957b409SSimon J. Gerraty fprintf(stderr,
257*0957b409SSimon J. Gerraty " -vmin name set minimum supported version (default: TLS-1.0)\n");
258*0957b409SSimon J. Gerraty fprintf(stderr,
259*0957b409SSimon J. Gerraty " -vmax name set maximum supported version (default: TLS-1.2)\n");
260*0957b409SSimon J. Gerraty fprintf(stderr,
261*0957b409SSimon J. Gerraty " -cs names set list of supported cipher suites (comma-separated)\n");
262*0957b409SSimon J. Gerraty fprintf(stderr,
263*0957b409SSimon J. Gerraty " -hf names add support for some hash functions (comma-separated)\n");
264*0957b409SSimon J. Gerraty fprintf(stderr,
265*0957b409SSimon J. Gerraty " -cbhash test hashing in policy callback\n");
266*0957b409SSimon J. Gerraty fprintf(stderr,
267*0957b409SSimon J. Gerraty " -serverpref enforce server's preferences for cipher suites\n");
268*0957b409SSimon J. Gerraty fprintf(stderr,
269*0957b409SSimon J. Gerraty " -noreneg prohibit renegotiations\n");
270*0957b409SSimon J. Gerraty fprintf(stderr,
271*0957b409SSimon J. Gerraty " -alpn name add protocol name to list of protocols (ALPN extension)\n");
272*0957b409SSimon J. Gerraty fprintf(stderr,
273*0957b409SSimon J. Gerraty " -strictalpn fail on ALPN mismatch\n");
274*0957b409SSimon J. Gerraty exit(EXIT_FAILURE);
275*0957b409SSimon J. Gerraty }
276*0957b409SSimon J. Gerraty
277*0957b409SSimon J. Gerraty typedef struct {
278*0957b409SSimon J. Gerraty const br_ssl_server_policy_class *vtable;
279*0957b409SSimon J. Gerraty int verbose;
280*0957b409SSimon J. Gerraty br_x509_certificate *chain;
281*0957b409SSimon J. Gerraty size_t chain_len;
282*0957b409SSimon J. Gerraty int cert_signer_algo;
283*0957b409SSimon J. Gerraty private_key *sk;
284*0957b409SSimon J. Gerraty int cbhash;
285*0957b409SSimon J. Gerraty } policy_context;
286*0957b409SSimon J. Gerraty
287*0957b409SSimon J. Gerraty static void
print_hashes(unsigned chashes)288*0957b409SSimon J. Gerraty print_hashes(unsigned chashes)
289*0957b409SSimon J. Gerraty {
290*0957b409SSimon J. Gerraty int i;
291*0957b409SSimon J. Gerraty
292*0957b409SSimon J. Gerraty for (i = 2; i <= 6; i ++) {
293*0957b409SSimon J. Gerraty if ((chashes >> i) & 1) {
294*0957b409SSimon J. Gerraty int z;
295*0957b409SSimon J. Gerraty
296*0957b409SSimon J. Gerraty switch (i) {
297*0957b409SSimon J. Gerraty case 3: z = 224; break;
298*0957b409SSimon J. Gerraty case 4: z = 256; break;
299*0957b409SSimon J. Gerraty case 5: z = 384; break;
300*0957b409SSimon J. Gerraty case 6: z = 512; break;
301*0957b409SSimon J. Gerraty default:
302*0957b409SSimon J. Gerraty z = 1;
303*0957b409SSimon J. Gerraty break;
304*0957b409SSimon J. Gerraty }
305*0957b409SSimon J. Gerraty fprintf(stderr, " sha%d", z);
306*0957b409SSimon J. Gerraty }
307*0957b409SSimon J. Gerraty }
308*0957b409SSimon J. Gerraty }
309*0957b409SSimon J. Gerraty
310*0957b409SSimon J. Gerraty static unsigned
choose_hash(unsigned chashes)311*0957b409SSimon J. Gerraty choose_hash(unsigned chashes)
312*0957b409SSimon J. Gerraty {
313*0957b409SSimon J. Gerraty unsigned hash_id;
314*0957b409SSimon J. Gerraty
315*0957b409SSimon J. Gerraty for (hash_id = 6; hash_id >= 2; hash_id --) {
316*0957b409SSimon J. Gerraty if (((chashes >> hash_id) & 1) != 0) {
317*0957b409SSimon J. Gerraty return hash_id;
318*0957b409SSimon J. Gerraty }
319*0957b409SSimon J. Gerraty }
320*0957b409SSimon J. Gerraty /*
321*0957b409SSimon J. Gerraty * Normally unreachable.
322*0957b409SSimon J. Gerraty */
323*0957b409SSimon J. Gerraty return 0;
324*0957b409SSimon J. Gerraty }
325*0957b409SSimon J. Gerraty
326*0957b409SSimon J. Gerraty static int
sp_choose(const br_ssl_server_policy_class ** pctx,const br_ssl_server_context * cc,br_ssl_server_choices * choices)327*0957b409SSimon J. Gerraty sp_choose(const br_ssl_server_policy_class **pctx,
328*0957b409SSimon J. Gerraty const br_ssl_server_context *cc,
329*0957b409SSimon J. Gerraty br_ssl_server_choices *choices)
330*0957b409SSimon J. Gerraty {
331*0957b409SSimon J. Gerraty policy_context *pc;
332*0957b409SSimon J. Gerraty const br_suite_translated *st;
333*0957b409SSimon J. Gerraty size_t u, st_num;
334*0957b409SSimon J. Gerraty unsigned chashes;
335*0957b409SSimon J. Gerraty
336*0957b409SSimon J. Gerraty pc = (policy_context *)pctx;
337*0957b409SSimon J. Gerraty st = br_ssl_server_get_client_suites(cc, &st_num);
338*0957b409SSimon J. Gerraty chashes = br_ssl_server_get_client_hashes(cc);
339*0957b409SSimon J. Gerraty if (pc->verbose) {
340*0957b409SSimon J. Gerraty fprintf(stderr, "Client parameters:\n");
341*0957b409SSimon J. Gerraty fprintf(stderr, " Maximum version: ");
342*0957b409SSimon J. Gerraty switch (cc->client_max_version) {
343*0957b409SSimon J. Gerraty case BR_SSL30:
344*0957b409SSimon J. Gerraty fprintf(stderr, "SSL 3.0");
345*0957b409SSimon J. Gerraty break;
346*0957b409SSimon J. Gerraty case BR_TLS10:
347*0957b409SSimon J. Gerraty fprintf(stderr, "TLS 1.0");
348*0957b409SSimon J. Gerraty break;
349*0957b409SSimon J. Gerraty case BR_TLS11:
350*0957b409SSimon J. Gerraty fprintf(stderr, "TLS 1.1");
351*0957b409SSimon J. Gerraty break;
352*0957b409SSimon J. Gerraty case BR_TLS12:
353*0957b409SSimon J. Gerraty fprintf(stderr, "TLS 1.2");
354*0957b409SSimon J. Gerraty break;
355*0957b409SSimon J. Gerraty default:
356*0957b409SSimon J. Gerraty fprintf(stderr, "unknown (0x%04X)",
357*0957b409SSimon J. Gerraty (unsigned)cc->client_max_version);
358*0957b409SSimon J. Gerraty break;
359*0957b409SSimon J. Gerraty }
360*0957b409SSimon J. Gerraty fprintf(stderr, "\n");
361*0957b409SSimon J. Gerraty fprintf(stderr, " Compatible cipher suites:\n");
362*0957b409SSimon J. Gerraty for (u = 0; u < st_num; u ++) {
363*0957b409SSimon J. Gerraty char csn[80];
364*0957b409SSimon J. Gerraty
365*0957b409SSimon J. Gerraty get_suite_name_ext(st[u][0], csn, sizeof csn);
366*0957b409SSimon J. Gerraty fprintf(stderr, " %s\n", csn);
367*0957b409SSimon J. Gerraty }
368*0957b409SSimon J. Gerraty fprintf(stderr, " Common sign+hash functions:\n");
369*0957b409SSimon J. Gerraty if ((chashes & 0xFF) != 0) {
370*0957b409SSimon J. Gerraty fprintf(stderr, " with RSA:");
371*0957b409SSimon J. Gerraty print_hashes(chashes);
372*0957b409SSimon J. Gerraty fprintf(stderr, "\n");
373*0957b409SSimon J. Gerraty }
374*0957b409SSimon J. Gerraty if ((chashes >> 8) != 0) {
375*0957b409SSimon J. Gerraty fprintf(stderr, " with ECDSA:");
376*0957b409SSimon J. Gerraty print_hashes(chashes >> 8);
377*0957b409SSimon J. Gerraty fprintf(stderr, "\n");
378*0957b409SSimon J. Gerraty }
379*0957b409SSimon J. Gerraty }
380*0957b409SSimon J. Gerraty for (u = 0; u < st_num; u ++) {
381*0957b409SSimon J. Gerraty unsigned tt;
382*0957b409SSimon J. Gerraty
383*0957b409SSimon J. Gerraty tt = st[u][1];
384*0957b409SSimon J. Gerraty switch (tt >> 12) {
385*0957b409SSimon J. Gerraty case BR_SSLKEYX_RSA:
386*0957b409SSimon J. Gerraty if (pc->sk->key_type == BR_KEYTYPE_RSA) {
387*0957b409SSimon J. Gerraty choices->cipher_suite = st[u][0];
388*0957b409SSimon J. Gerraty goto choose_ok;
389*0957b409SSimon J. Gerraty }
390*0957b409SSimon J. Gerraty break;
391*0957b409SSimon J. Gerraty case BR_SSLKEYX_ECDHE_RSA:
392*0957b409SSimon J. Gerraty if (pc->sk->key_type == BR_KEYTYPE_RSA) {
393*0957b409SSimon J. Gerraty choices->cipher_suite = st[u][0];
394*0957b409SSimon J. Gerraty if (br_ssl_engine_get_version(&cc->eng)
395*0957b409SSimon J. Gerraty < BR_TLS12)
396*0957b409SSimon J. Gerraty {
397*0957b409SSimon J. Gerraty if (pc->cbhash) {
398*0957b409SSimon J. Gerraty choices->algo_id = 0x0001;
399*0957b409SSimon J. Gerraty } else {
400*0957b409SSimon J. Gerraty choices->algo_id = 0xFF00;
401*0957b409SSimon J. Gerraty }
402*0957b409SSimon J. Gerraty } else {
403*0957b409SSimon J. Gerraty unsigned id;
404*0957b409SSimon J. Gerraty
405*0957b409SSimon J. Gerraty id = choose_hash(chashes);
406*0957b409SSimon J. Gerraty if (pc->cbhash) {
407*0957b409SSimon J. Gerraty choices->algo_id =
408*0957b409SSimon J. Gerraty (id << 8) + 0x01;
409*0957b409SSimon J. Gerraty } else {
410*0957b409SSimon J. Gerraty choices->algo_id = 0xFF00 + id;
411*0957b409SSimon J. Gerraty }
412*0957b409SSimon J. Gerraty }
413*0957b409SSimon J. Gerraty goto choose_ok;
414*0957b409SSimon J. Gerraty }
415*0957b409SSimon J. Gerraty break;
416*0957b409SSimon J. Gerraty case BR_SSLKEYX_ECDHE_ECDSA:
417*0957b409SSimon J. Gerraty if (pc->sk->key_type == BR_KEYTYPE_EC) {
418*0957b409SSimon J. Gerraty choices->cipher_suite = st[u][0];
419*0957b409SSimon J. Gerraty if (br_ssl_engine_get_version(&cc->eng)
420*0957b409SSimon J. Gerraty < BR_TLS12)
421*0957b409SSimon J. Gerraty {
422*0957b409SSimon J. Gerraty if (pc->cbhash) {
423*0957b409SSimon J. Gerraty choices->algo_id = 0x0203;
424*0957b409SSimon J. Gerraty } else {
425*0957b409SSimon J. Gerraty choices->algo_id =
426*0957b409SSimon J. Gerraty 0xFF00 + br_sha1_ID;
427*0957b409SSimon J. Gerraty }
428*0957b409SSimon J. Gerraty } else {
429*0957b409SSimon J. Gerraty unsigned id;
430*0957b409SSimon J. Gerraty
431*0957b409SSimon J. Gerraty id = choose_hash(chashes >> 8);
432*0957b409SSimon J. Gerraty if (pc->cbhash) {
433*0957b409SSimon J. Gerraty choices->algo_id =
434*0957b409SSimon J. Gerraty (id << 8) + 0x03;
435*0957b409SSimon J. Gerraty } else {
436*0957b409SSimon J. Gerraty choices->algo_id =
437*0957b409SSimon J. Gerraty 0xFF00 + id;
438*0957b409SSimon J. Gerraty }
439*0957b409SSimon J. Gerraty }
440*0957b409SSimon J. Gerraty goto choose_ok;
441*0957b409SSimon J. Gerraty }
442*0957b409SSimon J. Gerraty break;
443*0957b409SSimon J. Gerraty case BR_SSLKEYX_ECDH_RSA:
444*0957b409SSimon J. Gerraty if (pc->sk->key_type == BR_KEYTYPE_EC
445*0957b409SSimon J. Gerraty && pc->cert_signer_algo == BR_KEYTYPE_RSA)
446*0957b409SSimon J. Gerraty {
447*0957b409SSimon J. Gerraty choices->cipher_suite = st[u][0];
448*0957b409SSimon J. Gerraty goto choose_ok;
449*0957b409SSimon J. Gerraty }
450*0957b409SSimon J. Gerraty break;
451*0957b409SSimon J. Gerraty case BR_SSLKEYX_ECDH_ECDSA:
452*0957b409SSimon J. Gerraty if (pc->sk->key_type == BR_KEYTYPE_EC
453*0957b409SSimon J. Gerraty && pc->cert_signer_algo == BR_KEYTYPE_EC)
454*0957b409SSimon J. Gerraty {
455*0957b409SSimon J. Gerraty choices->cipher_suite = st[u][0];
456*0957b409SSimon J. Gerraty goto choose_ok;
457*0957b409SSimon J. Gerraty }
458*0957b409SSimon J. Gerraty break;
459*0957b409SSimon J. Gerraty }
460*0957b409SSimon J. Gerraty }
461*0957b409SSimon J. Gerraty return 0;
462*0957b409SSimon J. Gerraty
463*0957b409SSimon J. Gerraty choose_ok:
464*0957b409SSimon J. Gerraty choices->chain = pc->chain;
465*0957b409SSimon J. Gerraty choices->chain_len = pc->chain_len;
466*0957b409SSimon J. Gerraty if (pc->verbose) {
467*0957b409SSimon J. Gerraty char csn[80];
468*0957b409SSimon J. Gerraty
469*0957b409SSimon J. Gerraty get_suite_name_ext(choices->cipher_suite, csn, sizeof csn);
470*0957b409SSimon J. Gerraty fprintf(stderr, "Using: %s\n", csn);
471*0957b409SSimon J. Gerraty }
472*0957b409SSimon J. Gerraty return 1;
473*0957b409SSimon J. Gerraty }
474*0957b409SSimon J. Gerraty
475*0957b409SSimon J. Gerraty static uint32_t
sp_do_keyx(const br_ssl_server_policy_class ** pctx,unsigned char * data,size_t * len)476*0957b409SSimon J. Gerraty sp_do_keyx(const br_ssl_server_policy_class **pctx,
477*0957b409SSimon J. Gerraty unsigned char *data, size_t *len)
478*0957b409SSimon J. Gerraty {
479*0957b409SSimon J. Gerraty policy_context *pc;
480*0957b409SSimon J. Gerraty uint32_t r;
481*0957b409SSimon J. Gerraty size_t xoff, xlen;
482*0957b409SSimon J. Gerraty
483*0957b409SSimon J. Gerraty pc = (policy_context *)pctx;
484*0957b409SSimon J. Gerraty switch (pc->sk->key_type) {
485*0957b409SSimon J. Gerraty const br_ec_impl *iec;
486*0957b409SSimon J. Gerraty
487*0957b409SSimon J. Gerraty case BR_KEYTYPE_RSA:
488*0957b409SSimon J. Gerraty return br_rsa_ssl_decrypt(
489*0957b409SSimon J. Gerraty br_rsa_private_get_default(),
490*0957b409SSimon J. Gerraty &pc->sk->key.rsa, data, *len);
491*0957b409SSimon J. Gerraty case BR_KEYTYPE_EC:
492*0957b409SSimon J. Gerraty iec = br_ec_get_default();
493*0957b409SSimon J. Gerraty r = iec->mul(data, *len, pc->sk->key.ec.x,
494*0957b409SSimon J. Gerraty pc->sk->key.ec.xlen, pc->sk->key.ec.curve);
495*0957b409SSimon J. Gerraty xoff = iec->xoff(pc->sk->key.ec.curve, &xlen);
496*0957b409SSimon J. Gerraty memmove(data, data + xoff, xlen);
497*0957b409SSimon J. Gerraty *len = xlen;
498*0957b409SSimon J. Gerraty return r;
499*0957b409SSimon J. Gerraty default:
500*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: unknown private key type (%d)\n",
501*0957b409SSimon J. Gerraty (int)pc->sk->key_type);
502*0957b409SSimon J. Gerraty return 0;
503*0957b409SSimon J. Gerraty }
504*0957b409SSimon J. Gerraty }
505*0957b409SSimon J. Gerraty
506*0957b409SSimon J. Gerraty static size_t
sp_do_sign(const br_ssl_server_policy_class ** pctx,unsigned algo_id,unsigned char * data,size_t hv_len,size_t len)507*0957b409SSimon J. Gerraty sp_do_sign(const br_ssl_server_policy_class **pctx,
508*0957b409SSimon J. Gerraty unsigned algo_id, unsigned char *data, size_t hv_len, size_t len)
509*0957b409SSimon J. Gerraty {
510*0957b409SSimon J. Gerraty policy_context *pc;
511*0957b409SSimon J. Gerraty unsigned char hv[64];
512*0957b409SSimon J. Gerraty
513*0957b409SSimon J. Gerraty pc = (policy_context *)pctx;
514*0957b409SSimon J. Gerraty if (algo_id >= 0xFF00) {
515*0957b409SSimon J. Gerraty algo_id &= 0xFF;
516*0957b409SSimon J. Gerraty memcpy(hv, data, hv_len);
517*0957b409SSimon J. Gerraty } else {
518*0957b409SSimon J. Gerraty const br_hash_class *hc;
519*0957b409SSimon J. Gerraty br_hash_compat_context zc;
520*0957b409SSimon J. Gerraty
521*0957b409SSimon J. Gerraty if (pc->verbose) {
522*0957b409SSimon J. Gerraty fprintf(stderr, "Callback hashing, algo = 0x%04X,"
523*0957b409SSimon J. Gerraty " data_len = %lu\n",
524*0957b409SSimon J. Gerraty algo_id, (unsigned long)hv_len);
525*0957b409SSimon J. Gerraty }
526*0957b409SSimon J. Gerraty algo_id >>= 8;
527*0957b409SSimon J. Gerraty hc = get_hash_impl(algo_id);
528*0957b409SSimon J. Gerraty if (hc == NULL) {
529*0957b409SSimon J. Gerraty if (pc->verbose) {
530*0957b409SSimon J. Gerraty fprintf(stderr,
531*0957b409SSimon J. Gerraty "ERROR: unsupported hash function %u\n",
532*0957b409SSimon J. Gerraty algo_id);
533*0957b409SSimon J. Gerraty }
534*0957b409SSimon J. Gerraty return 0;
535*0957b409SSimon J. Gerraty }
536*0957b409SSimon J. Gerraty hc->init(&zc.vtable);
537*0957b409SSimon J. Gerraty hc->update(&zc.vtable, data, hv_len);
538*0957b409SSimon J. Gerraty hc->out(&zc.vtable, hv);
539*0957b409SSimon J. Gerraty hv_len = (hc->desc >> BR_HASHDESC_OUT_OFF)
540*0957b409SSimon J. Gerraty & BR_HASHDESC_OUT_MASK;
541*0957b409SSimon J. Gerraty }
542*0957b409SSimon J. Gerraty switch (pc->sk->key_type) {
543*0957b409SSimon J. Gerraty size_t sig_len;
544*0957b409SSimon J. Gerraty uint32_t x;
545*0957b409SSimon J. Gerraty const unsigned char *hash_oid;
546*0957b409SSimon J. Gerraty const br_hash_class *hc;
547*0957b409SSimon J. Gerraty
548*0957b409SSimon J. Gerraty case BR_KEYTYPE_RSA:
549*0957b409SSimon J. Gerraty hash_oid = get_hash_oid(algo_id);
550*0957b409SSimon J. Gerraty if (hash_oid == NULL && algo_id != 0) {
551*0957b409SSimon J. Gerraty if (pc->verbose) {
552*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: cannot RSA-sign with"
553*0957b409SSimon J. Gerraty " unknown hash function: %u\n",
554*0957b409SSimon J. Gerraty algo_id);
555*0957b409SSimon J. Gerraty }
556*0957b409SSimon J. Gerraty return 0;
557*0957b409SSimon J. Gerraty }
558*0957b409SSimon J. Gerraty sig_len = (pc->sk->key.rsa.n_bitlen + 7) >> 3;
559*0957b409SSimon J. Gerraty if (len < sig_len) {
560*0957b409SSimon J. Gerraty if (pc->verbose) {
561*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: cannot RSA-sign,"
562*0957b409SSimon J. Gerraty " buffer is too small"
563*0957b409SSimon J. Gerraty " (sig=%lu, buf=%lu)\n",
564*0957b409SSimon J. Gerraty (unsigned long)sig_len,
565*0957b409SSimon J. Gerraty (unsigned long)len);
566*0957b409SSimon J. Gerraty }
567*0957b409SSimon J. Gerraty return 0;
568*0957b409SSimon J. Gerraty }
569*0957b409SSimon J. Gerraty x = br_rsa_pkcs1_sign_get_default()(
570*0957b409SSimon J. Gerraty hash_oid, hv, hv_len, &pc->sk->key.rsa, data);
571*0957b409SSimon J. Gerraty if (!x) {
572*0957b409SSimon J. Gerraty if (pc->verbose) {
573*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: RSA-sign failure\n");
574*0957b409SSimon J. Gerraty }
575*0957b409SSimon J. Gerraty return 0;
576*0957b409SSimon J. Gerraty }
577*0957b409SSimon J. Gerraty return sig_len;
578*0957b409SSimon J. Gerraty
579*0957b409SSimon J. Gerraty case BR_KEYTYPE_EC:
580*0957b409SSimon J. Gerraty hc = get_hash_impl(algo_id);
581*0957b409SSimon J. Gerraty if (hc == NULL) {
582*0957b409SSimon J. Gerraty if (pc->verbose) {
583*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: cannot ECDSA-sign with"
584*0957b409SSimon J. Gerraty " unknown hash function: %u\n",
585*0957b409SSimon J. Gerraty algo_id);
586*0957b409SSimon J. Gerraty }
587*0957b409SSimon J. Gerraty return 0;
588*0957b409SSimon J. Gerraty }
589*0957b409SSimon J. Gerraty if (len < 139) {
590*0957b409SSimon J. Gerraty if (pc->verbose) {
591*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: cannot ECDSA-sign"
592*0957b409SSimon J. Gerraty " (output buffer = %lu)\n",
593*0957b409SSimon J. Gerraty (unsigned long)len);
594*0957b409SSimon J. Gerraty }
595*0957b409SSimon J. Gerraty return 0;
596*0957b409SSimon J. Gerraty }
597*0957b409SSimon J. Gerraty sig_len = br_ecdsa_sign_asn1_get_default()(
598*0957b409SSimon J. Gerraty br_ec_get_default(), hc, hv, &pc->sk->key.ec, data);
599*0957b409SSimon J. Gerraty if (sig_len == 0) {
600*0957b409SSimon J. Gerraty if (pc->verbose) {
601*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: ECDSA-sign failure\n");
602*0957b409SSimon J. Gerraty }
603*0957b409SSimon J. Gerraty return 0;
604*0957b409SSimon J. Gerraty }
605*0957b409SSimon J. Gerraty return sig_len;
606*0957b409SSimon J. Gerraty
607*0957b409SSimon J. Gerraty default:
608*0957b409SSimon J. Gerraty return 0;
609*0957b409SSimon J. Gerraty }
610*0957b409SSimon J. Gerraty }
611*0957b409SSimon J. Gerraty
612*0957b409SSimon J. Gerraty static const br_ssl_server_policy_class policy_vtable = {
613*0957b409SSimon J. Gerraty sizeof(policy_context),
614*0957b409SSimon J. Gerraty sp_choose,
615*0957b409SSimon J. Gerraty sp_do_keyx,
616*0957b409SSimon J. Gerraty sp_do_sign
617*0957b409SSimon J. Gerraty };
618*0957b409SSimon J. Gerraty
619*0957b409SSimon J. Gerraty void
free_alpn(void * alpn)620*0957b409SSimon J. Gerraty free_alpn(void *alpn)
621*0957b409SSimon J. Gerraty {
622*0957b409SSimon J. Gerraty xfree(*(char **)alpn);
623*0957b409SSimon J. Gerraty }
624*0957b409SSimon J. Gerraty
625*0957b409SSimon J. Gerraty /* see brssl.h */
626*0957b409SSimon J. Gerraty int
do_server(int argc,char * argv[])627*0957b409SSimon J. Gerraty do_server(int argc, char *argv[])
628*0957b409SSimon J. Gerraty {
629*0957b409SSimon J. Gerraty int retcode;
630*0957b409SSimon J. Gerraty int verbose;
631*0957b409SSimon J. Gerraty int trace;
632*0957b409SSimon J. Gerraty int i, bidi;
633*0957b409SSimon J. Gerraty const char *bind_name;
634*0957b409SSimon J. Gerraty const char *port;
635*0957b409SSimon J. Gerraty unsigned vmin, vmax;
636*0957b409SSimon J. Gerraty cipher_suite *suites;
637*0957b409SSimon J. Gerraty size_t num_suites;
638*0957b409SSimon J. Gerraty uint16_t *suite_ids;
639*0957b409SSimon J. Gerraty unsigned hfuns;
640*0957b409SSimon J. Gerraty int cbhash;
641*0957b409SSimon J. Gerraty br_x509_certificate *chain;
642*0957b409SSimon J. Gerraty size_t chain_len;
643*0957b409SSimon J. Gerraty int cert_signer_algo;
644*0957b409SSimon J. Gerraty private_key *sk;
645*0957b409SSimon J. Gerraty anchor_list anchors = VEC_INIT;
646*0957b409SSimon J. Gerraty VECTOR(char *) alpn_names = VEC_INIT;
647*0957b409SSimon J. Gerraty br_x509_minimal_context xc;
648*0957b409SSimon J. Gerraty const br_hash_class *dnhash;
649*0957b409SSimon J. Gerraty size_t u;
650*0957b409SSimon J. Gerraty br_ssl_server_context cc;
651*0957b409SSimon J. Gerraty policy_context pc;
652*0957b409SSimon J. Gerraty br_ssl_session_cache_lru lru;
653*0957b409SSimon J. Gerraty unsigned char *iobuf, *cache;
654*0957b409SSimon J. Gerraty size_t iobuf_len, cache_len;
655*0957b409SSimon J. Gerraty uint32_t flags;
656*0957b409SSimon J. Gerraty SOCKET server_fd, fd;
657*0957b409SSimon J. Gerraty
658*0957b409SSimon J. Gerraty retcode = 0;
659*0957b409SSimon J. Gerraty verbose = 1;
660*0957b409SSimon J. Gerraty trace = 0;
661*0957b409SSimon J. Gerraty bind_name = NULL;
662*0957b409SSimon J. Gerraty port = NULL;
663*0957b409SSimon J. Gerraty bidi = 1;
664*0957b409SSimon J. Gerraty vmin = 0;
665*0957b409SSimon J. Gerraty vmax = 0;
666*0957b409SSimon J. Gerraty suites = NULL;
667*0957b409SSimon J. Gerraty num_suites = 0;
668*0957b409SSimon J. Gerraty hfuns = 0;
669*0957b409SSimon J. Gerraty cbhash = 0;
670*0957b409SSimon J. Gerraty suite_ids = NULL;
671*0957b409SSimon J. Gerraty chain = NULL;
672*0957b409SSimon J. Gerraty chain_len = 0;
673*0957b409SSimon J. Gerraty sk = NULL;
674*0957b409SSimon J. Gerraty iobuf = NULL;
675*0957b409SSimon J. Gerraty iobuf_len = 0;
676*0957b409SSimon J. Gerraty cache = NULL;
677*0957b409SSimon J. Gerraty cache_len = (size_t)-1;
678*0957b409SSimon J. Gerraty flags = 0;
679*0957b409SSimon J. Gerraty server_fd = INVALID_SOCKET;
680*0957b409SSimon J. Gerraty fd = INVALID_SOCKET;
681*0957b409SSimon J. Gerraty for (i = 0; i < argc; i ++) {
682*0957b409SSimon J. Gerraty const char *arg;
683*0957b409SSimon J. Gerraty
684*0957b409SSimon J. Gerraty arg = argv[i];
685*0957b409SSimon J. Gerraty if (arg[0] != '-') {
686*0957b409SSimon J. Gerraty usage_server();
687*0957b409SSimon J. Gerraty goto server_exit_error;
688*0957b409SSimon J. Gerraty }
689*0957b409SSimon J. Gerraty if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
690*0957b409SSimon J. Gerraty verbose = 1;
691*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
692*0957b409SSimon J. Gerraty verbose = 0;
693*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-trace")) {
694*0957b409SSimon J. Gerraty trace = 1;
695*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-b")) {
696*0957b409SSimon J. Gerraty if (++ i >= argc) {
697*0957b409SSimon J. Gerraty fprintf(stderr,
698*0957b409SSimon J. Gerraty "ERROR: no argument for '-b'\n");
699*0957b409SSimon J. Gerraty usage_server();
700*0957b409SSimon J. Gerraty goto server_exit_error;
701*0957b409SSimon J. Gerraty }
702*0957b409SSimon J. Gerraty if (bind_name != NULL) {
703*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: duplicate bind host\n");
704*0957b409SSimon J. Gerraty usage_server();
705*0957b409SSimon J. Gerraty goto server_exit_error;
706*0957b409SSimon J. Gerraty }
707*0957b409SSimon J. Gerraty bind_name = argv[i];
708*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-p")) {
709*0957b409SSimon J. Gerraty if (++ i >= argc) {
710*0957b409SSimon J. Gerraty fprintf(stderr,
711*0957b409SSimon J. Gerraty "ERROR: no argument for '-p'\n");
712*0957b409SSimon J. Gerraty usage_server();
713*0957b409SSimon J. Gerraty goto server_exit_error;
714*0957b409SSimon J. Gerraty }
715*0957b409SSimon J. Gerraty if (port != NULL) {
716*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: duplicate bind port\n");
717*0957b409SSimon J. Gerraty usage_server();
718*0957b409SSimon J. Gerraty goto server_exit_error;
719*0957b409SSimon J. Gerraty }
720*0957b409SSimon J. Gerraty port = argv[i];
721*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-mono")) {
722*0957b409SSimon J. Gerraty bidi = 0;
723*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-buf")) {
724*0957b409SSimon J. Gerraty if (++ i >= argc) {
725*0957b409SSimon J. Gerraty fprintf(stderr,
726*0957b409SSimon J. Gerraty "ERROR: no argument for '-buf'\n");
727*0957b409SSimon J. Gerraty usage_server();
728*0957b409SSimon J. Gerraty goto server_exit_error;
729*0957b409SSimon J. Gerraty }
730*0957b409SSimon J. Gerraty arg = argv[i];
731*0957b409SSimon J. Gerraty if (iobuf_len != 0) {
732*0957b409SSimon J. Gerraty fprintf(stderr,
733*0957b409SSimon J. Gerraty "ERROR: duplicate I/O buffer length\n");
734*0957b409SSimon J. Gerraty usage_server();
735*0957b409SSimon J. Gerraty goto server_exit_error;
736*0957b409SSimon J. Gerraty }
737*0957b409SSimon J. Gerraty iobuf_len = parse_size(arg);
738*0957b409SSimon J. Gerraty if (iobuf_len == (size_t)-1) {
739*0957b409SSimon J. Gerraty usage_server();
740*0957b409SSimon J. Gerraty goto server_exit_error;
741*0957b409SSimon J. Gerraty }
742*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-cache")) {
743*0957b409SSimon J. Gerraty if (++ i >= argc) {
744*0957b409SSimon J. Gerraty fprintf(stderr,
745*0957b409SSimon J. Gerraty "ERROR: no argument for '-cache'\n");
746*0957b409SSimon J. Gerraty usage_server();
747*0957b409SSimon J. Gerraty goto server_exit_error;
748*0957b409SSimon J. Gerraty }
749*0957b409SSimon J. Gerraty arg = argv[i];
750*0957b409SSimon J. Gerraty if (cache_len != (size_t)-1) {
751*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: duplicate session"
752*0957b409SSimon J. Gerraty " cache length\n");
753*0957b409SSimon J. Gerraty usage_server();
754*0957b409SSimon J. Gerraty goto server_exit_error;
755*0957b409SSimon J. Gerraty }
756*0957b409SSimon J. Gerraty cache_len = parse_size(arg);
757*0957b409SSimon J. Gerraty if (cache_len == (size_t)-1) {
758*0957b409SSimon J. Gerraty usage_server();
759*0957b409SSimon J. Gerraty goto server_exit_error;
760*0957b409SSimon J. Gerraty }
761*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-cert")) {
762*0957b409SSimon J. Gerraty if (++ i >= argc) {
763*0957b409SSimon J. Gerraty fprintf(stderr,
764*0957b409SSimon J. Gerraty "ERROR: no argument for '-cert'\n");
765*0957b409SSimon J. Gerraty usage_server();
766*0957b409SSimon J. Gerraty goto server_exit_error;
767*0957b409SSimon J. Gerraty }
768*0957b409SSimon J. Gerraty if (chain != NULL) {
769*0957b409SSimon J. Gerraty fprintf(stderr,
770*0957b409SSimon J. Gerraty "ERROR: duplicate certificate chain\n");
771*0957b409SSimon J. Gerraty usage_server();
772*0957b409SSimon J. Gerraty goto server_exit_error;
773*0957b409SSimon J. Gerraty }
774*0957b409SSimon J. Gerraty arg = argv[i];
775*0957b409SSimon J. Gerraty chain = read_certificates(arg, &chain_len);
776*0957b409SSimon J. Gerraty if (chain == NULL || chain_len == 0) {
777*0957b409SSimon J. Gerraty goto server_exit_error;
778*0957b409SSimon J. Gerraty }
779*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-key")) {
780*0957b409SSimon J. Gerraty if (++ i >= argc) {
781*0957b409SSimon J. Gerraty fprintf(stderr,
782*0957b409SSimon J. Gerraty "ERROR: no argument for '-key'\n");
783*0957b409SSimon J. Gerraty usage_server();
784*0957b409SSimon J. Gerraty goto server_exit_error;
785*0957b409SSimon J. Gerraty }
786*0957b409SSimon J. Gerraty if (sk != NULL) {
787*0957b409SSimon J. Gerraty fprintf(stderr,
788*0957b409SSimon J. Gerraty "ERROR: duplicate private key\n");
789*0957b409SSimon J. Gerraty usage_server();
790*0957b409SSimon J. Gerraty goto server_exit_error;
791*0957b409SSimon J. Gerraty }
792*0957b409SSimon J. Gerraty arg = argv[i];
793*0957b409SSimon J. Gerraty sk = read_private_key(arg);
794*0957b409SSimon J. Gerraty if (sk == NULL) {
795*0957b409SSimon J. Gerraty goto server_exit_error;
796*0957b409SSimon J. Gerraty }
797*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-CA")) {
798*0957b409SSimon J. Gerraty if (++ i >= argc) {
799*0957b409SSimon J. Gerraty fprintf(stderr,
800*0957b409SSimon J. Gerraty "ERROR: no argument for '-CA'\n");
801*0957b409SSimon J. Gerraty usage_server();
802*0957b409SSimon J. Gerraty goto server_exit_error;
803*0957b409SSimon J. Gerraty }
804*0957b409SSimon J. Gerraty arg = argv[i];
805*0957b409SSimon J. Gerraty if (read_trust_anchors(&anchors, arg) == 0) {
806*0957b409SSimon J. Gerraty usage_server();
807*0957b409SSimon J. Gerraty goto server_exit_error;
808*0957b409SSimon J. Gerraty }
809*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-anon_ok")) {
810*0957b409SSimon J. Gerraty flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH;
811*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-list")) {
812*0957b409SSimon J. Gerraty list_names();
813*0957b409SSimon J. Gerraty goto server_exit;
814*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-vmin")) {
815*0957b409SSimon J. Gerraty if (++ i >= argc) {
816*0957b409SSimon J. Gerraty fprintf(stderr,
817*0957b409SSimon J. Gerraty "ERROR: no argument for '-vmin'\n");
818*0957b409SSimon J. Gerraty usage_server();
819*0957b409SSimon J. Gerraty goto server_exit_error;
820*0957b409SSimon J. Gerraty }
821*0957b409SSimon J. Gerraty arg = argv[i];
822*0957b409SSimon J. Gerraty if (vmin != 0) {
823*0957b409SSimon J. Gerraty fprintf(stderr,
824*0957b409SSimon J. Gerraty "ERROR: duplicate minimum version\n");
825*0957b409SSimon J. Gerraty usage_server();
826*0957b409SSimon J. Gerraty goto server_exit_error;
827*0957b409SSimon J. Gerraty }
828*0957b409SSimon J. Gerraty vmin = parse_version(arg, strlen(arg));
829*0957b409SSimon J. Gerraty if (vmin == 0) {
830*0957b409SSimon J. Gerraty fprintf(stderr,
831*0957b409SSimon J. Gerraty "ERROR: unrecognised version '%s'\n",
832*0957b409SSimon J. Gerraty arg);
833*0957b409SSimon J. Gerraty usage_server();
834*0957b409SSimon J. Gerraty goto server_exit_error;
835*0957b409SSimon J. Gerraty }
836*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-vmax")) {
837*0957b409SSimon J. Gerraty if (++ i >= argc) {
838*0957b409SSimon J. Gerraty fprintf(stderr,
839*0957b409SSimon J. Gerraty "ERROR: no argument for '-vmax'\n");
840*0957b409SSimon J. Gerraty usage_server();
841*0957b409SSimon J. Gerraty goto server_exit_error;
842*0957b409SSimon J. Gerraty }
843*0957b409SSimon J. Gerraty arg = argv[i];
844*0957b409SSimon J. Gerraty if (vmax != 0) {
845*0957b409SSimon J. Gerraty fprintf(stderr,
846*0957b409SSimon J. Gerraty "ERROR: duplicate maximum version\n");
847*0957b409SSimon J. Gerraty usage_server();
848*0957b409SSimon J. Gerraty goto server_exit_error;
849*0957b409SSimon J. Gerraty }
850*0957b409SSimon J. Gerraty vmax = parse_version(arg, strlen(arg));
851*0957b409SSimon J. Gerraty if (vmax == 0) {
852*0957b409SSimon J. Gerraty fprintf(stderr,
853*0957b409SSimon J. Gerraty "ERROR: unrecognised version '%s'\n",
854*0957b409SSimon J. Gerraty arg);
855*0957b409SSimon J. Gerraty usage_server();
856*0957b409SSimon J. Gerraty goto server_exit_error;
857*0957b409SSimon J. Gerraty }
858*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-cs")) {
859*0957b409SSimon J. Gerraty if (++ i >= argc) {
860*0957b409SSimon J. Gerraty fprintf(stderr,
861*0957b409SSimon J. Gerraty "ERROR: no argument for '-cs'\n");
862*0957b409SSimon J. Gerraty usage_server();
863*0957b409SSimon J. Gerraty goto server_exit_error;
864*0957b409SSimon J. Gerraty }
865*0957b409SSimon J. Gerraty arg = argv[i];
866*0957b409SSimon J. Gerraty if (suites != NULL) {
867*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: duplicate list"
868*0957b409SSimon J. Gerraty " of cipher suites\n");
869*0957b409SSimon J. Gerraty usage_server();
870*0957b409SSimon J. Gerraty goto server_exit_error;
871*0957b409SSimon J. Gerraty }
872*0957b409SSimon J. Gerraty suites = parse_suites(arg, &num_suites);
873*0957b409SSimon J. Gerraty if (suites == NULL) {
874*0957b409SSimon J. Gerraty usage_server();
875*0957b409SSimon J. Gerraty goto server_exit_error;
876*0957b409SSimon J. Gerraty }
877*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-hf")) {
878*0957b409SSimon J. Gerraty unsigned x;
879*0957b409SSimon J. Gerraty
880*0957b409SSimon J. Gerraty if (++ i >= argc) {
881*0957b409SSimon J. Gerraty fprintf(stderr,
882*0957b409SSimon J. Gerraty "ERROR: no argument for '-hf'\n");
883*0957b409SSimon J. Gerraty usage_server();
884*0957b409SSimon J. Gerraty goto server_exit_error;
885*0957b409SSimon J. Gerraty }
886*0957b409SSimon J. Gerraty arg = argv[i];
887*0957b409SSimon J. Gerraty x = parse_hash_functions(arg);
888*0957b409SSimon J. Gerraty if (x == 0) {
889*0957b409SSimon J. Gerraty usage_server();
890*0957b409SSimon J. Gerraty goto server_exit_error;
891*0957b409SSimon J. Gerraty }
892*0957b409SSimon J. Gerraty hfuns |= x;
893*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-cbhash")) {
894*0957b409SSimon J. Gerraty cbhash = 1;
895*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-serverpref")) {
896*0957b409SSimon J. Gerraty flags |= BR_OPT_ENFORCE_SERVER_PREFERENCES;
897*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-noreneg")) {
898*0957b409SSimon J. Gerraty flags |= BR_OPT_NO_RENEGOTIATION;
899*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-alpn")) {
900*0957b409SSimon J. Gerraty if (++ i >= argc) {
901*0957b409SSimon J. Gerraty fprintf(stderr,
902*0957b409SSimon J. Gerraty "ERROR: no argument for '-alpn'\n");
903*0957b409SSimon J. Gerraty usage_server();
904*0957b409SSimon J. Gerraty goto server_exit_error;
905*0957b409SSimon J. Gerraty }
906*0957b409SSimon J. Gerraty VEC_ADD(alpn_names, xstrdup(argv[i]));
907*0957b409SSimon J. Gerraty } else if (eqstr(arg, "-strictalpn")) {
908*0957b409SSimon J. Gerraty flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH;
909*0957b409SSimon J. Gerraty } else {
910*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
911*0957b409SSimon J. Gerraty usage_server();
912*0957b409SSimon J. Gerraty goto server_exit_error;
913*0957b409SSimon J. Gerraty }
914*0957b409SSimon J. Gerraty }
915*0957b409SSimon J. Gerraty if (port == NULL) {
916*0957b409SSimon J. Gerraty port = "4433";
917*0957b409SSimon J. Gerraty }
918*0957b409SSimon J. Gerraty if (vmin == 0) {
919*0957b409SSimon J. Gerraty vmin = BR_TLS10;
920*0957b409SSimon J. Gerraty }
921*0957b409SSimon J. Gerraty if (vmax == 0) {
922*0957b409SSimon J. Gerraty vmax = BR_TLS12;
923*0957b409SSimon J. Gerraty }
924*0957b409SSimon J. Gerraty if (vmax < vmin) {
925*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: impossible minimum/maximum protocol"
926*0957b409SSimon J. Gerraty " version combination\n");
927*0957b409SSimon J. Gerraty usage_server();
928*0957b409SSimon J. Gerraty goto server_exit_error;
929*0957b409SSimon J. Gerraty }
930*0957b409SSimon J. Gerraty if (suites == NULL) {
931*0957b409SSimon J. Gerraty num_suites = 0;
932*0957b409SSimon J. Gerraty
933*0957b409SSimon J. Gerraty for (u = 0; cipher_suites[u].name; u ++) {
934*0957b409SSimon J. Gerraty if ((cipher_suites[u].req & REQ_TLS12) == 0
935*0957b409SSimon J. Gerraty || vmax >= BR_TLS12)
936*0957b409SSimon J. Gerraty {
937*0957b409SSimon J. Gerraty num_suites ++;
938*0957b409SSimon J. Gerraty }
939*0957b409SSimon J. Gerraty }
940*0957b409SSimon J. Gerraty suites = xmalloc(num_suites * sizeof *suites);
941*0957b409SSimon J. Gerraty num_suites = 0;
942*0957b409SSimon J. Gerraty for (u = 0; cipher_suites[u].name; u ++) {
943*0957b409SSimon J. Gerraty if ((cipher_suites[u].req & REQ_TLS12) == 0
944*0957b409SSimon J. Gerraty || vmax >= BR_TLS12)
945*0957b409SSimon J. Gerraty {
946*0957b409SSimon J. Gerraty suites[num_suites ++] = cipher_suites[u];
947*0957b409SSimon J. Gerraty }
948*0957b409SSimon J. Gerraty }
949*0957b409SSimon J. Gerraty }
950*0957b409SSimon J. Gerraty if (hfuns == 0) {
951*0957b409SSimon J. Gerraty hfuns = (unsigned)-1;
952*0957b409SSimon J. Gerraty }
953*0957b409SSimon J. Gerraty if (chain == NULL || chain_len == 0) {
954*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: no certificate chain provided\n");
955*0957b409SSimon J. Gerraty goto server_exit_error;
956*0957b409SSimon J. Gerraty }
957*0957b409SSimon J. Gerraty if (sk == NULL) {
958*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: no private key provided\n");
959*0957b409SSimon J. Gerraty goto server_exit_error;
960*0957b409SSimon J. Gerraty }
961*0957b409SSimon J. Gerraty switch (sk->key_type) {
962*0957b409SSimon J. Gerraty int curve;
963*0957b409SSimon J. Gerraty uint32_t supp;
964*0957b409SSimon J. Gerraty
965*0957b409SSimon J. Gerraty case BR_KEYTYPE_RSA:
966*0957b409SSimon J. Gerraty break;
967*0957b409SSimon J. Gerraty case BR_KEYTYPE_EC:
968*0957b409SSimon J. Gerraty curve = sk->key.ec.curve;
969*0957b409SSimon J. Gerraty supp = br_ec_get_default()->supported_curves;
970*0957b409SSimon J. Gerraty if (curve > 31 || !((supp >> curve) & 1)) {
971*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: private key curve (%d)"
972*0957b409SSimon J. Gerraty " is not supported\n", curve);
973*0957b409SSimon J. Gerraty goto server_exit_error;
974*0957b409SSimon J. Gerraty }
975*0957b409SSimon J. Gerraty break;
976*0957b409SSimon J. Gerraty default:
977*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: unsupported private key type (%d)\n",
978*0957b409SSimon J. Gerraty sk->key_type);
979*0957b409SSimon J. Gerraty break;
980*0957b409SSimon J. Gerraty }
981*0957b409SSimon J. Gerraty cert_signer_algo = get_cert_signer_algo(chain);
982*0957b409SSimon J. Gerraty if (cert_signer_algo == 0) {
983*0957b409SSimon J. Gerraty goto server_exit_error;
984*0957b409SSimon J. Gerraty }
985*0957b409SSimon J. Gerraty if (verbose) {
986*0957b409SSimon J. Gerraty const char *csas;
987*0957b409SSimon J. Gerraty
988*0957b409SSimon J. Gerraty switch (cert_signer_algo) {
989*0957b409SSimon J. Gerraty case BR_KEYTYPE_RSA: csas = "RSA"; break;
990*0957b409SSimon J. Gerraty case BR_KEYTYPE_EC: csas = "EC"; break;
991*0957b409SSimon J. Gerraty default:
992*0957b409SSimon J. Gerraty csas = "unknown";
993*0957b409SSimon J. Gerraty break;
994*0957b409SSimon J. Gerraty }
995*0957b409SSimon J. Gerraty fprintf(stderr, "Issuing CA key type: %d (%s)\n",
996*0957b409SSimon J. Gerraty cert_signer_algo, csas);
997*0957b409SSimon J. Gerraty }
998*0957b409SSimon J. Gerraty if (iobuf_len == 0) {
999*0957b409SSimon J. Gerraty if (bidi) {
1000*0957b409SSimon J. Gerraty iobuf_len = BR_SSL_BUFSIZE_BIDI;
1001*0957b409SSimon J. Gerraty } else {
1002*0957b409SSimon J. Gerraty iobuf_len = BR_SSL_BUFSIZE_MONO;
1003*0957b409SSimon J. Gerraty }
1004*0957b409SSimon J. Gerraty }
1005*0957b409SSimon J. Gerraty iobuf = xmalloc(iobuf_len);
1006*0957b409SSimon J. Gerraty if (cache_len == (size_t)-1) {
1007*0957b409SSimon J. Gerraty cache_len = 5000;
1008*0957b409SSimon J. Gerraty }
1009*0957b409SSimon J. Gerraty cache = xmalloc(cache_len);
1010*0957b409SSimon J. Gerraty
1011*0957b409SSimon J. Gerraty /*
1012*0957b409SSimon J. Gerraty * Compute implementation requirements and inject implementations.
1013*0957b409SSimon J. Gerraty */
1014*0957b409SSimon J. Gerraty suite_ids = xmalloc(num_suites * sizeof *suite_ids);
1015*0957b409SSimon J. Gerraty br_ssl_server_zero(&cc);
1016*0957b409SSimon J. Gerraty br_ssl_engine_set_versions(&cc.eng, vmin, vmax);
1017*0957b409SSimon J. Gerraty br_ssl_engine_set_all_flags(&cc.eng, flags);
1018*0957b409SSimon J. Gerraty if (vmin <= BR_TLS11) {
1019*0957b409SSimon J. Gerraty if (!(hfuns & (1 << br_md5_ID))) {
1020*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need MD5\n");
1021*0957b409SSimon J. Gerraty goto server_exit_error;
1022*0957b409SSimon J. Gerraty }
1023*0957b409SSimon J. Gerraty if (!(hfuns & (1 << br_sha1_ID))) {
1024*0957b409SSimon J. Gerraty fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need SHA-1\n");
1025*0957b409SSimon J. Gerraty goto server_exit_error;
1026*0957b409SSimon J. Gerraty }
1027*0957b409SSimon J. Gerraty }
1028*0957b409SSimon J. Gerraty for (u = 0; u < num_suites; u ++) {
1029*0957b409SSimon J. Gerraty unsigned req;
1030*0957b409SSimon J. Gerraty
1031*0957b409SSimon J. Gerraty req = suites[u].req;
1032*0957b409SSimon J. Gerraty suite_ids[u] = suites[u].suite;
1033*0957b409SSimon J. Gerraty if ((req & REQ_TLS12) != 0 && vmax < BR_TLS12) {
1034*0957b409SSimon J. Gerraty fprintf(stderr,
1035*0957b409SSimon J. Gerraty "ERROR: cipher suite %s requires TLS 1.2\n",
1036*0957b409SSimon J. Gerraty suites[u].name);
1037*0957b409SSimon J. Gerraty goto server_exit_error;
1038*0957b409SSimon J. Gerraty }
1039*0957b409SSimon J. Gerraty if ((req & REQ_SHA1) != 0 && !(hfuns & (1 << br_sha1_ID))) {
1040*0957b409SSimon J. Gerraty fprintf(stderr,
1041*0957b409SSimon J. Gerraty "ERROR: cipher suite %s requires SHA-1\n",
1042*0957b409SSimon J. Gerraty suites[u].name);
1043*0957b409SSimon J. Gerraty goto server_exit_error;
1044*0957b409SSimon J. Gerraty }
1045*0957b409SSimon J. Gerraty if ((req & REQ_SHA256) != 0 && !(hfuns & (1 << br_sha256_ID))) {
1046*0957b409SSimon J. Gerraty fprintf(stderr,
1047*0957b409SSimon J. Gerraty "ERROR: cipher suite %s requires SHA-256\n",
1048*0957b409SSimon J. Gerraty suites[u].name);
1049*0957b409SSimon J. Gerraty goto server_exit_error;
1050*0957b409SSimon J. Gerraty }
1051*0957b409SSimon J. Gerraty if ((req & REQ_SHA384) != 0 && !(hfuns & (1 << br_sha384_ID))) {
1052*0957b409SSimon J. Gerraty fprintf(stderr,
1053*0957b409SSimon J. Gerraty "ERROR: cipher suite %s requires SHA-384\n",
1054*0957b409SSimon J. Gerraty suites[u].name);
1055*0957b409SSimon J. Gerraty goto server_exit_error;
1056*0957b409SSimon J. Gerraty }
1057*0957b409SSimon J. Gerraty /* TODO: algorithm implementation selection */
1058*0957b409SSimon J. Gerraty if ((req & REQ_AESCBC) != 0) {
1059*0957b409SSimon J. Gerraty br_ssl_engine_set_default_aes_cbc(&cc.eng);
1060*0957b409SSimon J. Gerraty }
1061*0957b409SSimon J. Gerraty if ((req & REQ_AESCCM) != 0) {
1062*0957b409SSimon J. Gerraty br_ssl_engine_set_default_aes_ccm(&cc.eng);
1063*0957b409SSimon J. Gerraty }
1064*0957b409SSimon J. Gerraty if ((req & REQ_AESGCM) != 0) {
1065*0957b409SSimon J. Gerraty br_ssl_engine_set_default_aes_gcm(&cc.eng);
1066*0957b409SSimon J. Gerraty }
1067*0957b409SSimon J. Gerraty if ((req & REQ_CHAPOL) != 0) {
1068*0957b409SSimon J. Gerraty br_ssl_engine_set_default_chapol(&cc.eng);
1069*0957b409SSimon J. Gerraty }
1070*0957b409SSimon J. Gerraty if ((req & REQ_3DESCBC) != 0) {
1071*0957b409SSimon J. Gerraty br_ssl_engine_set_default_des_cbc(&cc.eng);
1072*0957b409SSimon J. Gerraty }
1073*0957b409SSimon J. Gerraty if ((req & (REQ_ECDHE_RSA | REQ_ECDHE_ECDSA)) != 0) {
1074*0957b409SSimon J. Gerraty br_ssl_engine_set_default_ec(&cc.eng);
1075*0957b409SSimon J. Gerraty }
1076*0957b409SSimon J. Gerraty }
1077*0957b409SSimon J. Gerraty br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites);
1078*0957b409SSimon J. Gerraty
1079*0957b409SSimon J. Gerraty dnhash = NULL;
1080*0957b409SSimon J. Gerraty for (u = 0; hash_functions[u].name; u ++) {
1081*0957b409SSimon J. Gerraty const br_hash_class *hc;
1082*0957b409SSimon J. Gerraty int id;
1083*0957b409SSimon J. Gerraty
1084*0957b409SSimon J. Gerraty hc = hash_functions[u].hclass;
1085*0957b409SSimon J. Gerraty id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
1086*0957b409SSimon J. Gerraty if ((hfuns & ((unsigned)1 << id)) != 0) {
1087*0957b409SSimon J. Gerraty dnhash = hc;
1088*0957b409SSimon J. Gerraty br_ssl_engine_set_hash(&cc.eng, id, hc);
1089*0957b409SSimon J. Gerraty }
1090*0957b409SSimon J. Gerraty }
1091*0957b409SSimon J. Gerraty if (vmin <= BR_TLS11) {
1092*0957b409SSimon J. Gerraty br_ssl_engine_set_prf10(&cc.eng, &br_tls10_prf);
1093*0957b409SSimon J. Gerraty }
1094*0957b409SSimon J. Gerraty if (vmax >= BR_TLS12) {
1095*0957b409SSimon J. Gerraty if ((hfuns & ((unsigned)1 << br_sha256_ID)) != 0) {
1096*0957b409SSimon J. Gerraty br_ssl_engine_set_prf_sha256(&cc.eng,
1097*0957b409SSimon J. Gerraty &br_tls12_sha256_prf);
1098*0957b409SSimon J. Gerraty }
1099*0957b409SSimon J. Gerraty if ((hfuns & ((unsigned)1 << br_sha384_ID)) != 0) {
1100*0957b409SSimon J. Gerraty br_ssl_engine_set_prf_sha384(&cc.eng,
1101*0957b409SSimon J. Gerraty &br_tls12_sha384_prf);
1102*0957b409SSimon J. Gerraty }
1103*0957b409SSimon J. Gerraty }
1104*0957b409SSimon J. Gerraty
1105*0957b409SSimon J. Gerraty br_ssl_session_cache_lru_init(&lru, cache, cache_len);
1106*0957b409SSimon J. Gerraty br_ssl_server_set_cache(&cc, &lru.vtable);
1107*0957b409SSimon J. Gerraty
1108*0957b409SSimon J. Gerraty if (VEC_LEN(alpn_names) != 0) {
1109*0957b409SSimon J. Gerraty br_ssl_engine_set_protocol_names(&cc.eng,
1110*0957b409SSimon J. Gerraty (const char **)&VEC_ELT(alpn_names, 0),
1111*0957b409SSimon J. Gerraty VEC_LEN(alpn_names));
1112*0957b409SSimon J. Gerraty }
1113*0957b409SSimon J. Gerraty
1114*0957b409SSimon J. Gerraty /*
1115*0957b409SSimon J. Gerraty * Set the policy handler (that chooses the actual cipher suite,
1116*0957b409SSimon J. Gerraty * selects the certificate chain, and runs the private key
1117*0957b409SSimon J. Gerraty * operations).
1118*0957b409SSimon J. Gerraty */
1119*0957b409SSimon J. Gerraty pc.vtable = &policy_vtable;
1120*0957b409SSimon J. Gerraty pc.verbose = verbose;
1121*0957b409SSimon J. Gerraty pc.chain = chain;
1122*0957b409SSimon J. Gerraty pc.chain_len = chain_len;
1123*0957b409SSimon J. Gerraty pc.cert_signer_algo = cert_signer_algo;
1124*0957b409SSimon J. Gerraty pc.sk = sk;
1125*0957b409SSimon J. Gerraty pc.cbhash = cbhash;
1126*0957b409SSimon J. Gerraty br_ssl_server_set_policy(&cc, &pc.vtable);
1127*0957b409SSimon J. Gerraty
1128*0957b409SSimon J. Gerraty /*
1129*0957b409SSimon J. Gerraty * If trust anchors have been configured, then set an X.509
1130*0957b409SSimon J. Gerraty * validation engine and activate client certificate
1131*0957b409SSimon J. Gerraty * authentication.
1132*0957b409SSimon J. Gerraty */
1133*0957b409SSimon J. Gerraty if (VEC_LEN(anchors) != 0) {
1134*0957b409SSimon J. Gerraty br_x509_minimal_init(&xc, dnhash,
1135*0957b409SSimon J. Gerraty &VEC_ELT(anchors, 0), VEC_LEN(anchors));
1136*0957b409SSimon J. Gerraty for (u = 0; hash_functions[u].name; u ++) {
1137*0957b409SSimon J. Gerraty const br_hash_class *hc;
1138*0957b409SSimon J. Gerraty int id;
1139*0957b409SSimon J. Gerraty
1140*0957b409SSimon J. Gerraty hc = hash_functions[u].hclass;
1141*0957b409SSimon J. Gerraty id = (hc->desc >> BR_HASHDESC_ID_OFF)
1142*0957b409SSimon J. Gerraty & BR_HASHDESC_ID_MASK;
1143*0957b409SSimon J. Gerraty if ((hfuns & ((unsigned)1 << id)) != 0) {
1144*0957b409SSimon J. Gerraty br_x509_minimal_set_hash(&xc, id, hc);
1145*0957b409SSimon J. Gerraty }
1146*0957b409SSimon J. Gerraty }
1147*0957b409SSimon J. Gerraty br_ssl_engine_set_default_rsavrfy(&cc.eng);
1148*0957b409SSimon J. Gerraty br_ssl_engine_set_default_ecdsa(&cc.eng);
1149*0957b409SSimon J. Gerraty br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default());
1150*0957b409SSimon J. Gerraty br_x509_minimal_set_ecdsa(&xc,
1151*0957b409SSimon J. Gerraty br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
1152*0957b409SSimon J. Gerraty br_ssl_engine_set_x509(&cc.eng, &xc.vtable);
1153*0957b409SSimon J. Gerraty br_ssl_server_set_trust_anchor_names_alt(&cc,
1154*0957b409SSimon J. Gerraty &VEC_ELT(anchors, 0), VEC_LEN(anchors));
1155*0957b409SSimon J. Gerraty }
1156*0957b409SSimon J. Gerraty
1157*0957b409SSimon J. Gerraty br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
1158*0957b409SSimon J. Gerraty
1159*0957b409SSimon J. Gerraty /*
1160*0957b409SSimon J. Gerraty * On Unix systems, we need to ignore SIGPIPE.
1161*0957b409SSimon J. Gerraty */
1162*0957b409SSimon J. Gerraty #ifndef _WIN32
1163*0957b409SSimon J. Gerraty signal(SIGPIPE, SIG_IGN);
1164*0957b409SSimon J. Gerraty #endif
1165*0957b409SSimon J. Gerraty
1166*0957b409SSimon J. Gerraty /*
1167*0957b409SSimon J. Gerraty * Open the server socket.
1168*0957b409SSimon J. Gerraty */
1169*0957b409SSimon J. Gerraty server_fd = host_bind(bind_name, port, verbose);
1170*0957b409SSimon J. Gerraty if (server_fd == INVALID_SOCKET) {
1171*0957b409SSimon J. Gerraty goto server_exit_error;
1172*0957b409SSimon J. Gerraty }
1173*0957b409SSimon J. Gerraty
1174*0957b409SSimon J. Gerraty /*
1175*0957b409SSimon J. Gerraty * Process incoming clients, one at a time. Note that we do not
1176*0957b409SSimon J. Gerraty * accept any client until the previous connection has finished:
1177*0957b409SSimon J. Gerraty * this is voluntary, since the tool uses stdin/stdout for
1178*0957b409SSimon J. Gerraty * application data, and thus cannot really run two connections
1179*0957b409SSimon J. Gerraty * simultaneously.
1180*0957b409SSimon J. Gerraty */
1181*0957b409SSimon J. Gerraty for (;;) {
1182*0957b409SSimon J. Gerraty int x;
1183*0957b409SSimon J. Gerraty unsigned run_flags;
1184*0957b409SSimon J. Gerraty
1185*0957b409SSimon J. Gerraty fd = accept_client(server_fd, verbose, 1);
1186*0957b409SSimon J. Gerraty if (fd == INVALID_SOCKET) {
1187*0957b409SSimon J. Gerraty goto server_exit_error;
1188*0957b409SSimon J. Gerraty }
1189*0957b409SSimon J. Gerraty br_ssl_server_reset(&cc);
1190*0957b409SSimon J. Gerraty run_flags = (verbose ? RUN_ENGINE_VERBOSE : 0)
1191*0957b409SSimon J. Gerraty | (trace ? RUN_ENGINE_TRACE : 0);
1192*0957b409SSimon J. Gerraty x = run_ssl_engine(&cc.eng, fd, run_flags);
1193*0957b409SSimon J. Gerraty #ifdef _WIN32
1194*0957b409SSimon J. Gerraty closesocket(fd);
1195*0957b409SSimon J. Gerraty #else
1196*0957b409SSimon J. Gerraty close(fd);
1197*0957b409SSimon J. Gerraty #endif
1198*0957b409SSimon J. Gerraty fd = INVALID_SOCKET;
1199*0957b409SSimon J. Gerraty if (x < -1) {
1200*0957b409SSimon J. Gerraty goto server_exit_error;
1201*0957b409SSimon J. Gerraty }
1202*0957b409SSimon J. Gerraty }
1203*0957b409SSimon J. Gerraty
1204*0957b409SSimon J. Gerraty /*
1205*0957b409SSimon J. Gerraty * Release allocated structures.
1206*0957b409SSimon J. Gerraty */
1207*0957b409SSimon J. Gerraty server_exit:
1208*0957b409SSimon J. Gerraty xfree(suites);
1209*0957b409SSimon J. Gerraty xfree(suite_ids);
1210*0957b409SSimon J. Gerraty free_certificates(chain, chain_len);
1211*0957b409SSimon J. Gerraty free_private_key(sk);
1212*0957b409SSimon J. Gerraty VEC_CLEAREXT(anchors, &free_ta_contents);
1213*0957b409SSimon J. Gerraty VEC_CLEAREXT(alpn_names, &free_alpn);
1214*0957b409SSimon J. Gerraty xfree(iobuf);
1215*0957b409SSimon J. Gerraty xfree(cache);
1216*0957b409SSimon J. Gerraty if (fd != INVALID_SOCKET) {
1217*0957b409SSimon J. Gerraty #ifdef _WIN32
1218*0957b409SSimon J. Gerraty closesocket(fd);
1219*0957b409SSimon J. Gerraty #else
1220*0957b409SSimon J. Gerraty close(fd);
1221*0957b409SSimon J. Gerraty #endif
1222*0957b409SSimon J. Gerraty }
1223*0957b409SSimon J. Gerraty if (server_fd != INVALID_SOCKET) {
1224*0957b409SSimon J. Gerraty #ifdef _WIN32
1225*0957b409SSimon J. Gerraty closesocket(server_fd);
1226*0957b409SSimon J. Gerraty #else
1227*0957b409SSimon J. Gerraty close(server_fd);
1228*0957b409SSimon J. Gerraty #endif
1229*0957b409SSimon J. Gerraty }
1230*0957b409SSimon J. Gerraty return retcode;
1231*0957b409SSimon J. Gerraty
1232*0957b409SSimon J. Gerraty server_exit_error:
1233*0957b409SSimon J. Gerraty retcode = -1;
1234*0957b409SSimon J. Gerraty goto server_exit;
1235*0957b409SSimon J. Gerraty }
1236