92c7d4223a1f70f80b6403b02e4e38b0f9b56a8a
2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 #include <sys/types.h>
33 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
42 * This sample code can use three possible certificate chains:
43 * -- A full-RSA chain (server key is RSA, certificates are signed with RSA)
44 * -- A full-EC chain (server key is EC, certificates are signed with ECDSA)
45 * -- A mixed chain (server key is EC, certificates are signed with RSA)
47 * The macros below define which chain is selected. This impacts the list
48 * of supported cipher suites.
51 #if !(SERVER_RSA || SERVER_EC || SERVER_MIXED)
54 #define SERVER_MIXED 0
58 #include "chain-rsa.h"
66 #include "chain-ec+rsa.h"
70 #error Must use one of RSA, EC or MIXED chains.
74 * Create a server socket bound to the specified host and port. If 'host'
75 * is NULL, this will bind "generically" (all addresses).
77 * Returned value is the server socket descriptor, or -1 on error.
80 host_bind(const char *host
, const char *port
)
82 struct addrinfo hints
, *si
, *p
;
86 memset(&hints
, 0, sizeof hints
);
87 hints
.ai_family
= PF_UNSPEC
;
88 hints
.ai_socktype
= SOCK_STREAM
;
89 err
= getaddrinfo(host
, port
, &hints
, &si
);
91 fprintf(stderr
, "ERROR: getaddrinfo(): %s\n",
96 for (p
= si
; p
!= NULL
; p
= p
->ai_next
) {
98 struct sockaddr_in sa4
;
99 struct sockaddr_in6 sa6
;
102 char tmp
[INET6_ADDRSTRLEN
+ 50];
105 sa
= (struct sockaddr
*)p
->ai_addr
;
106 if (sa
->sa_family
== AF_INET
) {
107 sa4
= *(struct sockaddr_in
*)sa
;
108 sa
= (struct sockaddr
*)&sa4
;
110 addr
= &sa4
.sin_addr
;
112 sa4
.sin_addr
.s_addr
= INADDR_ANY
;
114 } else if (sa
->sa_family
== AF_INET6
) {
115 sa6
= *(struct sockaddr_in6
*)sa
;
116 sa
= (struct sockaddr
*)&sa6
;
118 addr
= &sa6
.sin6_addr
;
120 sa6
.sin6_addr
= in6addr_any
;
124 sa_len
= p
->ai_addrlen
;
127 inet_ntop(p
->ai_family
, addr
, tmp
, sizeof tmp
);
129 sprintf(tmp
, "<unknown family: %d>",
132 fprintf(stderr
, "binding to: %s\n", tmp
);
133 fd
= socket(p
->ai_family
, p
->ai_socktype
, p
->ai_protocol
);
139 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof opt
);
141 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &opt
, sizeof opt
);
142 if (bind(fd
, sa
, sa_len
) < 0) {
151 fprintf(stderr
, "ERROR: failed to bind\n");
155 if (listen(fd
, 5) < 0) {
160 fprintf(stderr
, "bound.\n");
165 * Accept a single client on the provided server socket. This is blocking.
166 * On error, this returns -1.
169 accept_client(int server_fd
)
174 char tmp
[INET6_ADDRSTRLEN
+ 50];
178 fd
= accept(server_fd
, &sa
, &sa_len
);
184 switch (sa
.sa_family
) {
186 name
= inet_ntop(AF_INET
,
187 &((struct sockaddr_in
*)&sa
)->sin_addr
,
191 name
= inet_ntop(AF_INET
,
192 &((struct sockaddr_in
*)&sa
)->sin_addr
,
197 sprintf(tmp
, "<unknown: %lu>", (unsigned long)sa
.sa_family
);
200 fprintf(stderr
, "accepting connection from: %s\n", name
);
205 * Low-level data read callback for the simplified SSL I/O API.
208 sock_read(void *ctx
, unsigned char *buf
, size_t len
)
213 rlen
= read(*(int *)ctx
, buf
, len
);
215 if (rlen
< 0 && errno
== EINTR
) {
225 * Low-level data write callback for the simplified SSL I/O API.
228 sock_write(void *ctx
, const unsigned char *buf
, size_t len
)
233 wlen
= write(*(int *)ctx
, buf
, len
);
235 if (wlen
< 0 && errno
== EINTR
) {
245 * Sample HTTP response to send.
247 static const char *HTTP_RES
=
248 "HTTP/1.0 200 OK\r\n"
249 "Content-Length: 46\r\n"
250 "Connection: close\r\n"
251 "Content-Type: text/html; charset=iso-8859-1\r\n"
260 * Main program: this is a simple program that expects 1 argument: a
261 * port number. This will start a simple network server on that port,
262 * that expects incoming SSL clients. It handles only one client at a
263 * time (handling several would require threads, sub-processes, or
264 * multiplexing with select()/poll(), all of which being possible).
266 * For each client, the server will wait for two successive newline
267 * characters (ignoring CR characters, so CR+LF is accepted), then
268 * produce a sample static HTTP response. This is very crude, but
269 * sufficient for explanatory purposes.
272 main(int argc
, char *argv
[])
283 * Ignore SIGPIPE to avoid crashing in case of abrupt socket close.
285 signal(SIGPIPE
, SIG_IGN
);
288 * Open the server socket.
290 fd
= host_bind(NULL
, port
);
296 * Process each client, one at a time.
300 br_ssl_server_context sc
;
301 unsigned char iobuf
[BR_SSL_BUFSIZE_BIDI
];
302 br_sslio_context ioc
;
305 cfd
= accept_client(fd
);
311 * Initialise the context with the cipher suites and
312 * algorithms. This depends on the server key type
313 * (and, for EC keys, the signature algorithm used by
314 * the CA to sign the server's certificate).
316 * Depending on the defined macros, we may select one of
317 * the "minimal" profiles. Key exchange algorithm depends
319 * RSA key: RSA or ECDHE_RSA
320 * EC key, cert signed with ECDSA: ECDH_ECDSA or ECDHE_ECDSA
321 * EC key, cert signed with RSA: ECDH_RSA or ECDHE_ECDSA
324 #if SERVER_PROFILE_MIN_FS
325 br_ssl_server_init_mine2g(&sc
, CHAIN
, CHAIN_LEN
, &SKEY
);
326 #elif SERVER_PROFILE_MIN_NOFS
327 br_ssl_server_init_minr2g(&sc
, CHAIN
, CHAIN_LEN
, &SKEY
);
329 br_ssl_server_init_full_rsa(&sc
, CHAIN
, CHAIN_LEN
, &SKEY
);
332 #if SERVER_PROFILE_MIN_FS
333 br_ssl_server_init_minf2g(&sc
, CHAIN
, CHAIN_LEN
, &SKEY
);
334 #elif SERVER_PROFILE_MIN_NOFS
335 br_ssl_server_init_minv2g(&sc
, CHAIN
, CHAIN_LEN
, &SKEY
);
337 br_ssl_server_init_full_ec(&sc
, CHAIN
, CHAIN_LEN
,
338 BR_KEYTYPE_EC
, &SKEY
);
340 #else /* SERVER_MIXED */
341 #if SERVER_PROFILE_MIN_FS
342 br_ssl_server_init_minf2g(&sc
, CHAIN
, CHAIN_LEN
, &SKEY
);
343 #elif SERVER_PROFILE_MIN_NOFS
344 br_ssl_server_init_minu2g(&sc
, CHAIN
, CHAIN_LEN
, &SKEY
);
346 br_ssl_server_init_full_ec(&sc
, CHAIN
, CHAIN_LEN
,
347 BR_KEYTYPE_RSA
, &SKEY
);
351 * Set the I/O buffer to the provided array. We
352 * allocated a buffer large enough for full-duplex
353 * behaviour with all allowed sizes of SSL records,
354 * hence we set the last argument to 1 (which means
355 * "split the buffer into separate input and output
358 br_ssl_engine_set_buffer(&sc
.eng
, iobuf
, sizeof iobuf
, 1);
361 * Reset the server context, for a new handshake.
363 br_ssl_server_reset(&sc
);
366 * Initialise the simplified I/O wrapper context.
368 br_sslio_init(&ioc
, &sc
.eng
, sock_read
, &cfd
, sock_write
, &cfd
);
371 * Read bytes until two successive LF (or CR+LF) are received.
377 if (br_sslio_read(&ioc
, &x
, 1) < 0) {
394 * Write a response and close the connection.
396 br_sslio_write_all(&ioc
, HTTP_RES
, strlen(HTTP_RES
));
397 br_sslio_close(&ioc
);
400 err
= br_ssl_engine_last_error(&sc
.eng
);
402 fprintf(stderr
, "SSL closed (correctly).\n");
404 fprintf(stderr
, "SSL error: %d\n", err
);