/src/openvswitch/lib/stream-ssl.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2008-2016, 2019 Nicira, Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at: |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include <config.h> |
18 | | #include "stream-ssl.h" |
19 | | #include "dhparams.h" |
20 | | #include <ctype.h> |
21 | | #include <errno.h> |
22 | | #include <inttypes.h> |
23 | | #include <string.h> |
24 | | #include <sys/types.h> |
25 | | #include <sys/socket.h> |
26 | | #include <netinet/tcp.h> |
27 | | #include <openssl/err.h> |
28 | | #include <openssl/rand.h> |
29 | | #include <openssl/ssl.h> |
30 | | #include <openssl/x509v3.h> |
31 | | #include <poll.h> |
32 | | #include <fcntl.h> |
33 | | #include <sys/stat.h> |
34 | | #include <unistd.h> |
35 | | #include "bitmap.h" |
36 | | #include "coverage.h" |
37 | | #include "openvswitch/dynamic-string.h" |
38 | | #include "entropy.h" |
39 | | #include "openvswitch/ofpbuf.h" |
40 | | #include "openflow/openflow.h" |
41 | | #include "packets.h" |
42 | | #include "openvswitch/poll-loop.h" |
43 | | #include "openvswitch/shash.h" |
44 | | #include "socket-util.h" |
45 | | #include "util.h" |
46 | | #include "sset.h" |
47 | | #include "stream-provider.h" |
48 | | #include "stream.h" |
49 | | #include "timeval.h" |
50 | | #include "openvswitch/vlog.h" |
51 | | |
52 | | #ifdef _WIN32 |
53 | | /* Ref: https://www.openssl.org/support/faq.html#PROG2 |
54 | | * Your application must link against the same version of the Win32 C-Runtime |
55 | | * against which your openssl libraries were linked. The default version for |
56 | | * OpenSSL is /MD - "Multithreaded DLL". If we compile Open vSwitch with |
57 | | * something other than /MD, instead of re-compiling OpenSSL |
58 | | * toolkit, openssl/applink.c can be #included. Also, it is important |
59 | | * to add CRYPTO_malloc_init prior first call to OpenSSL. |
60 | | * |
61 | | * XXX: The behavior of the following #include when Open vSwitch is |
62 | | * compiled with /MD is not tested. */ |
63 | | #include <openssl/applink.c> |
64 | | #define SHUT_RDWR SD_BOTH |
65 | | #endif |
66 | | |
67 | | VLOG_DEFINE_THIS_MODULE(stream_ssl); |
68 | | |
69 | | /* Active SSL/TLS. */ |
70 | | |
71 | | enum ssl_state { |
72 | | STATE_TCP_CONNECTING, |
73 | | STATE_SSL_CONNECTING |
74 | | }; |
75 | | |
76 | | enum session_type { |
77 | | CLIENT, |
78 | | SERVER |
79 | | }; |
80 | | |
81 | | struct ssl_stream |
82 | | { |
83 | | struct stream stream; |
84 | | enum ssl_state state; |
85 | | enum session_type type; |
86 | | int fd; |
87 | | SSL *ssl; |
88 | | struct ofpbuf *txbuf; |
89 | | unsigned int session_nr; |
90 | | |
91 | | /* rx_want and tx_want record the result of the last call to SSL_read() |
92 | | * and SSL_write(), respectively: |
93 | | * |
94 | | * - If the call reported that data needed to be read from the file |
95 | | * descriptor, the corresponding member is set to SSL_READING. |
96 | | * |
97 | | * - If the call reported that data needed to be written to the file |
98 | | * descriptor, the corresponding member is set to SSL_WRITING. |
99 | | * |
100 | | * - Otherwise, the member is set to SSL_NOTHING, indicating that the |
101 | | * call completed successfully (or with an error) and that there is no |
102 | | * need to block. |
103 | | * |
104 | | * These are needed because there is no way to ask OpenSSL what a data read |
105 | | * or write would require without giving it a buffer to receive into or |
106 | | * data to send, respectively. (Note that the SSL_want() status is |
107 | | * overwritten by each SSL_read() or SSL_write() call, so we can't rely on |
108 | | * its value.) |
109 | | * |
110 | | * A single call to SSL_read() or SSL_write() can perform both reading |
111 | | * and writing and thus invalidate not one of these values but actually |
112 | | * both. Consider this situation, for example: |
113 | | * |
114 | | * - SSL_write() blocks on a read, so tx_want gets SSL_READING. |
115 | | * |
116 | | * - SSL_read() laters succeeds reading from 'fd' and clears out the |
117 | | * whole receive buffer, so rx_want gets SSL_READING. |
118 | | * |
119 | | * - Client calls stream_wait(STREAM_RECV) and stream_wait(STREAM_SEND) |
120 | | * and blocks. |
121 | | * |
122 | | * - Now we're stuck blocking until the peer sends us data, even though |
123 | | * SSL_write() could now succeed, which could easily be a deadlock |
124 | | * condition. |
125 | | * |
126 | | * On the other hand, we can't reset both tx_want and rx_want on every call |
127 | | * to SSL_read() or SSL_write(), because that would produce livelock, |
128 | | * e.g. in this situation: |
129 | | * |
130 | | * - SSL_write() blocks, so tx_want gets SSL_READING or SSL_WRITING. |
131 | | * |
132 | | * - SSL_read() blocks, so rx_want gets SSL_READING or SSL_WRITING, |
133 | | * but tx_want gets reset to SSL_NOTHING. |
134 | | * |
135 | | * - Client calls stream_wait(STREAM_RECV) and stream_wait(STREAM_SEND) |
136 | | * and blocks. |
137 | | * |
138 | | * - Client wakes up immediately since SSL_NOTHING in tx_want indicates |
139 | | * that no blocking is necessary. |
140 | | * |
141 | | * The solution we adopt here is to set tx_want to SSL_NOTHING after |
142 | | * calling SSL_read() only if the SSL state of the connection changed, |
143 | | * which indicates that an SSL-level renegotiation made some progress, and |
144 | | * similarly for rx_want and SSL_write(). This prevents both the |
145 | | * deadlock and livelock situations above. |
146 | | */ |
147 | | int rx_want, tx_want; |
148 | | |
149 | | /* A few bytes of header data in case SSL negotiation fails. */ |
150 | | uint8_t head[2]; |
151 | | short int n_head; |
152 | | }; |
153 | | |
154 | | /* SSL context created by ssl_init(). */ |
155 | | static SSL_CTX *ctx; |
156 | | |
157 | | struct ssl_config_file { |
158 | | bool read; /* Whether the file was successfully read. */ |
159 | | char *file_name; /* Configured file name, if any. */ |
160 | | struct timespec mtime; /* File mtime as of last time we read it. */ |
161 | | }; |
162 | | |
163 | | /* SSL configuration files. */ |
164 | | static struct ssl_config_file private_key; |
165 | | static struct ssl_config_file certificate; |
166 | | static struct ssl_config_file ca_cert; |
167 | | static char *ssl_protocols = "TLSv1.2+"; |
168 | | static char *ssl_ciphers = "DEFAULT:@SECLEVEL=2"; |
169 | | static char *ssl_ciphersuites = ""; /* Using default ones, unless specified. */ |
170 | | |
171 | | /* Server name override for SNI (Server Name Indication). |
172 | | * If set, this name will be used for SNI instead of the hostname |
173 | | * extracted from the connection string. */ |
174 | | static char *ssl_server_name_override; |
175 | | |
176 | | /* Ordinarily, the SSL client and server verify each other's certificates using |
177 | | * a CA certificate. Setting this to false disables this behavior. (This is a |
178 | | * security risk.) */ |
179 | | static bool verify_peer_cert = true; |
180 | | |
181 | | /* Ordinarily, we require a CA certificate for the peer to be locally |
182 | | * available. We can, however, bootstrap the CA certificate from the peer at |
183 | | * the beginning of our first connection then use that certificate on all |
184 | | * subsequent connections, saving it to a file for use in future runs also. In |
185 | | * this case, 'bootstrap_ca_cert' is true. */ |
186 | | static bool bootstrap_ca_cert; |
187 | | |
188 | | /* Session number. Used in debug logging messages to uniquely identify a |
189 | | * session. */ |
190 | | static unsigned int next_session_nr; |
191 | | |
192 | | /* Who knows what can trigger various SSL errors, so let's throttle them down |
193 | | * quite a bit. */ |
194 | | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 25); |
195 | | |
196 | | static int ssl_init(void); |
197 | | static int do_ssl_init(void); |
198 | | static bool ssl_wants_io(int ssl_error); |
199 | | static void ssl_close(struct stream *); |
200 | | static void ssl_clear_txbuf(struct ssl_stream *); |
201 | | static void interpret_queued_ssl_error(const char *function); |
202 | | static int interpret_ssl_error(const char *function, int ret, int error, |
203 | | int *want); |
204 | | #if OPENSSL_VERSION_NUMBER < 0x3000000fL |
205 | | static DH *tmp_dh_callback(SSL *ssl, int is_export OVS_UNUSED, int keylength); |
206 | | #endif |
207 | | static void log_ca_cert(const char *file_name, X509 *cert); |
208 | | static void stream_ssl_set_ca_cert_file__(const char *file_name, |
209 | | bool bootstrap, bool force); |
210 | | static void ssl_protocol_cb(int write_p, int version, int content_type, |
211 | | const void *, size_t, SSL *, void *sslv_); |
212 | | static bool update_ssl_config(struct ssl_config_file *, const char *file_name); |
213 | | static int sock_errno(void); |
214 | | |
215 | | static short int |
216 | | want_to_poll_events(int want) |
217 | 0 | { |
218 | 0 | switch (want) { |
219 | 0 | case SSL_NOTHING: |
220 | 0 | OVS_NOT_REACHED(); |
221 | | |
222 | 0 | case SSL_READING: |
223 | 0 | return POLLIN; |
224 | | |
225 | 0 | case SSL_WRITING: |
226 | 0 | return POLLOUT; |
227 | | |
228 | 0 | default: |
229 | 0 | OVS_NOT_REACHED(); |
230 | 0 | } |
231 | 0 | } |
232 | | |
233 | | /* Creates a new SSL connection based on socket 'fd', as either a client or a |
234 | | * server according to 'type', initially in 'state'. On success, returns 0 and |
235 | | * stores the new stream in '*streamp', otherwise returns an errno value and |
236 | | * doesn't bother with '*streamp'. |
237 | | * |
238 | | * Takes ownership of 'name', which should be the name of the connection in the |
239 | | * format that would be used to connect to it, e.g. "ssl:1.2.3.4:5". |
240 | | * |
241 | | * For client connections, 'server_name' should be the host name of the server |
242 | | * being connected to, for use with SSL SNI (server name indication). Takes |
243 | | * ownership of 'server_name'. */ |
244 | | static int |
245 | | new_ssl_stream(char *name, char *server_name, int fd, enum session_type type, |
246 | | enum ssl_state state, struct stream **streamp) |
247 | 0 | { |
248 | 0 | struct ssl_stream *sslv; |
249 | 0 | SSL *ssl = NULL; |
250 | 0 | int retval; |
251 | | |
252 | | /* Check for all the needful configuration. */ |
253 | 0 | retval = 0; |
254 | 0 | if (!private_key.read) { |
255 | 0 | VLOG_ERR("Private key must be configured to use SSL"); |
256 | 0 | retval = ENOPROTOOPT; |
257 | 0 | } |
258 | 0 | if (!certificate.read) { |
259 | 0 | VLOG_ERR("Certificate must be configured to use SSL"); |
260 | 0 | retval = ENOPROTOOPT; |
261 | 0 | } |
262 | 0 | if (!ca_cert.read && verify_peer_cert && !bootstrap_ca_cert) { |
263 | 0 | VLOG_ERR("CA certificate must be configured to use SSL"); |
264 | 0 | retval = ENOPROTOOPT; |
265 | 0 | } |
266 | 0 | if (!retval && !SSL_CTX_check_private_key(ctx)) { |
267 | 0 | VLOG_ERR("Private key does not match certificate public key: %s", |
268 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
269 | 0 | retval = ENOPROTOOPT; |
270 | 0 | } |
271 | 0 | if (retval) { |
272 | 0 | goto error; |
273 | 0 | } |
274 | | |
275 | | /* Disable Nagle. |
276 | | * On windows platforms, this can only be called upon TCP connected. |
277 | | */ |
278 | 0 | if (state == STATE_SSL_CONNECTING) { |
279 | 0 | setsockopt_tcp_nodelay(fd); |
280 | 0 | } |
281 | | |
282 | | /* Create and configure OpenSSL stream. */ |
283 | 0 | ssl = SSL_new(ctx); |
284 | 0 | if (ssl == NULL) { |
285 | 0 | VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL)); |
286 | 0 | retval = ENOPROTOOPT; |
287 | 0 | goto error; |
288 | 0 | } |
289 | 0 | if (SSL_set_fd(ssl, fd) == 0) { |
290 | 0 | VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL)); |
291 | 0 | retval = ENOPROTOOPT; |
292 | 0 | goto error; |
293 | 0 | } |
294 | 0 | if (!verify_peer_cert || (bootstrap_ca_cert && type == CLIENT)) { |
295 | 0 | SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); |
296 | 0 | } |
297 | 0 | if (server_name && !SSL_set_tlsext_host_name(ssl, server_name)) { |
298 | 0 | VLOG_ERR("%s: failed to set server name indication (%s)", |
299 | 0 | server_name, ERR_error_string(ERR_get_error(), NULL)); |
300 | 0 | retval = ENOPROTOOPT; |
301 | 0 | goto error; |
302 | 0 | } |
303 | | |
304 | | /* Create and return the ssl_stream. */ |
305 | 0 | sslv = xmalloc(sizeof *sslv); |
306 | 0 | stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name); |
307 | 0 | sslv->state = state; |
308 | 0 | sslv->type = type; |
309 | 0 | sslv->fd = fd; |
310 | 0 | sslv->ssl = ssl; |
311 | 0 | sslv->txbuf = NULL; |
312 | 0 | sslv->rx_want = sslv->tx_want = SSL_NOTHING; |
313 | 0 | sslv->session_nr = next_session_nr++; |
314 | 0 | sslv->n_head = 0; |
315 | |
|
316 | 0 | if (VLOG_IS_DBG_ENABLED()) { |
317 | 0 | SSL_set_msg_callback(ssl, ssl_protocol_cb); |
318 | 0 | SSL_set_msg_callback_arg(ssl, sslv); |
319 | 0 | } |
320 | |
|
321 | 0 | *streamp = &sslv->stream; |
322 | 0 | free(server_name); |
323 | 0 | return 0; |
324 | | |
325 | 0 | error: |
326 | 0 | if (ssl) { |
327 | 0 | SSL_free(ssl); |
328 | 0 | } |
329 | 0 | closesocket(fd); |
330 | 0 | free(name); |
331 | 0 | free(server_name); |
332 | 0 | return retval; |
333 | 0 | } |
334 | | |
335 | | static struct ssl_stream * |
336 | | ssl_stream_cast(struct stream *stream) |
337 | 0 | { |
338 | 0 | stream_assert_class(stream, &ssl_stream_class); |
339 | 0 | return CONTAINER_OF(stream, struct ssl_stream, stream); |
340 | 0 | } |
341 | | |
342 | | /* Extracts and returns the server name from 'suffix'. The caller must |
343 | | * eventually free it. |
344 | | * |
345 | | * Returns NULL if there is no server name, and particularly if it is an IP |
346 | | * address rather than a host name, since RFC 3546 is explicit that IP |
347 | | * addresses are unsuitable as server name indication (SNI). */ |
348 | | static char * |
349 | | get_server_name(const char *suffix_) |
350 | 0 | { |
351 | 0 | char *suffix = xstrdup(suffix_); |
352 | |
|
353 | 0 | char *host, *port; |
354 | 0 | inet_parse_host_port_tokens(suffix, &host, &port); |
355 | |
|
356 | 0 | ovs_be32 ipv4; |
357 | 0 | struct in6_addr ipv6; |
358 | 0 | char *server_name = (ip_parse(host, &ipv4) || ipv6_parse(host, &ipv6) |
359 | 0 | ? NULL : xstrdup(host)); |
360 | |
|
361 | 0 | free(suffix); |
362 | |
|
363 | 0 | return server_name; |
364 | 0 | } |
365 | | |
366 | | static int |
367 | | ssl_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp) |
368 | 0 | { |
369 | 0 | int error, fd; |
370 | |
|
371 | 0 | error = ssl_init(); |
372 | 0 | if (error) { |
373 | 0 | return error; |
374 | 0 | } |
375 | | |
376 | 0 | error = inet_open_active(SOCK_STREAM, suffix, OFP_PORT, NULL, &fd, |
377 | 0 | dscp); |
378 | 0 | if (fd >= 0) { |
379 | 0 | int state = error ? STATE_TCP_CONNECTING : STATE_SSL_CONNECTING; |
380 | 0 | char *server_name = ssl_server_name_override |
381 | 0 | ? xstrdup(ssl_server_name_override) |
382 | 0 | : get_server_name(suffix); |
383 | |
|
384 | 0 | return new_ssl_stream(xstrdup(name), server_name, |
385 | 0 | fd, CLIENT, state, streamp); |
386 | 0 | } else { |
387 | 0 | VLOG_ERR("%s: connect: %s", name, ovs_strerror(error)); |
388 | 0 | return error; |
389 | 0 | } |
390 | 0 | } |
391 | | |
392 | | static int |
393 | | do_ca_cert_bootstrap(struct stream *stream) |
394 | 0 | { |
395 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
396 | 0 | STACK_OF(X509) *chain; |
397 | 0 | X509 *cert; |
398 | 0 | FILE *file; |
399 | 0 | int error; |
400 | 0 | int fd; |
401 | |
|
402 | 0 | chain = SSL_get_peer_cert_chain(sslv->ssl); |
403 | 0 | if (!chain || !sk_X509_num(chain)) { |
404 | 0 | VLOG_ERR("could not bootstrap CA cert: no certificate presented by " |
405 | 0 | "peer"); |
406 | 0 | return EPROTO; |
407 | 0 | } |
408 | 0 | cert = sk_X509_value(chain, sk_X509_num(chain) - 1); |
409 | | |
410 | | /* Check that 'cert' is self-signed. Otherwise it is not a CA |
411 | | * certificate and we should not attempt to use it as one. */ |
412 | 0 | error = X509_check_issued(cert, cert); |
413 | 0 | if (error) { |
414 | 0 | VLOG_ERR("could not bootstrap CA cert: obtained certificate is " |
415 | 0 | "not self-signed (%s)", |
416 | 0 | X509_verify_cert_error_string(error)); |
417 | 0 | if (sk_X509_num(chain) < 2) { |
418 | 0 | VLOG_ERR("only one certificate was received, so probably the peer " |
419 | 0 | "is not configured to send its CA certificate"); |
420 | 0 | } |
421 | 0 | return EPROTO; |
422 | 0 | } |
423 | | |
424 | 0 | fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444); |
425 | 0 | if (fd < 0) { |
426 | 0 | if (errno == EEXIST) { |
427 | 0 | VLOG_INFO_RL(&rl, "reading CA cert %s created by another process", |
428 | 0 | ca_cert.file_name); |
429 | 0 | stream_ssl_set_ca_cert_file__(ca_cert.file_name, true, true); |
430 | 0 | return EPROTO; |
431 | 0 | } else { |
432 | 0 | VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", |
433 | 0 | ca_cert.file_name, ovs_strerror(errno)); |
434 | 0 | return errno; |
435 | 0 | } |
436 | 0 | } |
437 | | |
438 | 0 | file = fdopen(fd, "w"); |
439 | 0 | if (!file) { |
440 | 0 | error = errno; |
441 | 0 | VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s", |
442 | 0 | ovs_strerror(error)); |
443 | 0 | unlink(ca_cert.file_name); |
444 | 0 | return error; |
445 | 0 | } |
446 | | |
447 | 0 | if (!PEM_write_X509(file, cert)) { |
448 | 0 | VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: " |
449 | 0 | "%s", ca_cert.file_name, |
450 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
451 | 0 | fclose(file); |
452 | 0 | unlink(ca_cert.file_name); |
453 | 0 | return EIO; |
454 | 0 | } |
455 | | |
456 | 0 | if (fclose(file)) { |
457 | 0 | error = errno; |
458 | 0 | VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s", |
459 | 0 | ca_cert.file_name, ovs_strerror(error)); |
460 | 0 | unlink(ca_cert.file_name); |
461 | 0 | return error; |
462 | 0 | } |
463 | | |
464 | 0 | VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert.file_name); |
465 | 0 | log_ca_cert(ca_cert.file_name, cert); |
466 | 0 | bootstrap_ca_cert = false; |
467 | 0 | ca_cert.read = true; |
468 | | |
469 | | /* SSL_CTX_add_client_CA makes a copy of cert's relevant data. */ |
470 | 0 | SSL_CTX_add_client_CA(ctx, cert); |
471 | |
|
472 | 0 | SSL_CTX_set_cert_store(ctx, X509_STORE_new()); |
473 | 0 | if (SSL_CTX_load_verify_locations(ctx, ca_cert.file_name, NULL) != 1) { |
474 | 0 | VLOG_ERR("SSL_CTX_load_verify_locations: %s", |
475 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
476 | 0 | return EPROTO; |
477 | 0 | } |
478 | 0 | VLOG_INFO("killing successful connection to retry using CA cert"); |
479 | 0 | return EPROTO; |
480 | 0 | } |
481 | | |
482 | | static char * |
483 | | get_peer_common_name(const struct ssl_stream *sslv) |
484 | 0 | { |
485 | 0 | char *peer_name = NULL; |
486 | 0 | #if OPENSSL_VERSION_NUMBER < 0x3000000fL |
487 | 0 | X509 *peer_cert = SSL_get_peer_certificate(sslv->ssl); |
488 | | #else |
489 | | X509 *peer_cert = SSL_get1_peer_certificate(sslv->ssl); |
490 | | #endif |
491 | 0 | if (!peer_cert) { |
492 | 0 | return NULL; |
493 | 0 | } |
494 | | |
495 | 0 | int cn_index = X509_NAME_get_index_by_NID(X509_get_subject_name(peer_cert), |
496 | 0 | NID_commonName, -1); |
497 | 0 | if (cn_index < 0) { |
498 | 0 | goto error; |
499 | 0 | } |
500 | | |
501 | 0 | X509_NAME_ENTRY *cn_entry = X509_NAME_get_entry( |
502 | 0 | X509_get_subject_name(peer_cert), cn_index); |
503 | 0 | if (!cn_entry) { |
504 | 0 | goto error; |
505 | 0 | } |
506 | | |
507 | 0 | ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(cn_entry); |
508 | 0 | if (!cn_data) { |
509 | 0 | goto error; |
510 | 0 | } |
511 | | |
512 | 0 | peer_name = xstrdup((const char *) ASN1_STRING_get0_data(cn_data)); |
513 | |
|
514 | 0 | error: |
515 | 0 | X509_free(peer_cert); |
516 | 0 | return peer_name; |
517 | 0 | } |
518 | | |
519 | | static int |
520 | | ssl_connect(struct stream *stream) |
521 | 0 | { |
522 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
523 | 0 | int retval; |
524 | |
|
525 | 0 | switch (sslv->state) { |
526 | 0 | case STATE_TCP_CONNECTING: |
527 | 0 | retval = check_connection_completion(sslv->fd); |
528 | 0 | if (retval) { |
529 | 0 | return retval; |
530 | 0 | } |
531 | 0 | sslv->state = STATE_SSL_CONNECTING; |
532 | 0 | setsockopt_tcp_nodelay(sslv->fd); |
533 | | /* Fall through. */ |
534 | |
|
535 | 0 | case STATE_SSL_CONNECTING: |
536 | | /* Capture the first few bytes of received data so that we can guess |
537 | | * what kind of funny data we've been sent if SSL negotiation fails. */ |
538 | 0 | if (sslv->n_head <= 0) { |
539 | 0 | sslv->n_head = recv(sslv->fd, sslv->head, sizeof sslv->head, |
540 | 0 | MSG_PEEK); |
541 | 0 | } |
542 | |
|
543 | 0 | retval = (sslv->type == CLIENT |
544 | 0 | ? SSL_connect(sslv->ssl) : SSL_accept(sslv->ssl)); |
545 | 0 | if (retval != 1) { |
546 | 0 | int error = SSL_get_error(sslv->ssl, retval); |
547 | 0 | if (retval < 0 && ssl_wants_io(error)) { |
548 | 0 | return EAGAIN; |
549 | 0 | } else { |
550 | 0 | int unused; |
551 | |
|
552 | 0 | interpret_ssl_error((sslv->type == CLIENT ? "SSL_connect" |
553 | 0 | : "SSL_accept"), retval, error, &unused); |
554 | 0 | shutdown(sslv->fd, SHUT_RDWR); |
555 | 0 | stream_report_content(sslv->head, sslv->n_head, STREAM_SSL, |
556 | 0 | &this_module, stream_get_name(stream)); |
557 | 0 | return EPROTO; |
558 | 0 | } |
559 | 0 | } else if (bootstrap_ca_cert) { |
560 | 0 | return do_ca_cert_bootstrap(stream); |
561 | 0 | } else if (verify_peer_cert |
562 | 0 | && ((SSL_get_verify_mode(sslv->ssl) |
563 | 0 | & (SSL_VERIFY_NONE | SSL_VERIFY_PEER)) |
564 | 0 | != SSL_VERIFY_PEER)) { |
565 | | /* Two or more SSL connections completed at the same time while we |
566 | | * were in bootstrap mode. Only one of these can finish the |
567 | | * bootstrap successfully. The other one(s) must be rejected |
568 | | * because they were not verified against the bootstrapped CA |
569 | | * certificate. (Alternatively we could verify them against the CA |
570 | | * certificate, but that's more trouble than it's worth. These |
571 | | * connections will succeed the next time they retry, assuming that |
572 | | * they have a certificate against the correct CA.) */ |
573 | 0 | VLOG_INFO( |
574 | 0 | "rejecting SSL/TLS connection during bootstrap race window"); |
575 | 0 | return EPROTO; |
576 | 0 | } else { |
577 | 0 | const char *servername = SSL_get_servername( |
578 | 0 | sslv->ssl, TLSEXT_NAMETYPE_host_name); |
579 | 0 | if (servername) { |
580 | 0 | VLOG_DBG("connection indicated server name %s", servername); |
581 | 0 | } |
582 | |
|
583 | 0 | char *cn = get_peer_common_name(sslv); |
584 | |
|
585 | 0 | if (cn) { |
586 | 0 | stream_set_peer_id(stream, cn); |
587 | 0 | free(cn); |
588 | 0 | } |
589 | 0 | return 0; |
590 | 0 | } |
591 | 0 | } |
592 | | |
593 | 0 | OVS_NOT_REACHED(); |
594 | 0 | } |
595 | | |
596 | | static void |
597 | | ssl_close(struct stream *stream) |
598 | 0 | { |
599 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
600 | 0 | ssl_clear_txbuf(sslv); |
601 | | |
602 | | /* Attempt clean shutdown of the SSL connection. This will work most of |
603 | | * the time, as long as the kernel send buffer has some free space and the |
604 | | * SSL connection isn't renegotiating, etc. That has to be good enough, |
605 | | * since we don't have any way to continue the close operation in the |
606 | | * background. */ |
607 | 0 | SSL_shutdown(sslv->ssl); |
608 | | |
609 | | /* SSL_shutdown() might have signaled an error, in which case we need to |
610 | | * flush it out of the OpenSSL error queue or the next OpenSSL operation |
611 | | * will falsely signal an error. */ |
612 | 0 | ERR_clear_error(); |
613 | |
|
614 | 0 | SSL_free(sslv->ssl); |
615 | 0 | closesocket(sslv->fd); |
616 | 0 | free(sslv); |
617 | 0 | } |
618 | | |
619 | | static void |
620 | | interpret_queued_ssl_error(const char *function) |
621 | 0 | { |
622 | 0 | int queued_error = ERR_get_error(); |
623 | 0 | if (queued_error != 0) { |
624 | 0 | VLOG_WARN_RL(&rl, "%s: %s", |
625 | 0 | function, ERR_error_string(queued_error, NULL)); |
626 | 0 | } else { |
627 | 0 | VLOG_ERR_RL(&rl, "%s: SSL_ERROR_SSL without queued error", function); |
628 | 0 | } |
629 | 0 | } |
630 | | |
631 | | static int |
632 | | interpret_ssl_error(const char *function, int ret, int error, |
633 | | int *want) |
634 | 0 | { |
635 | 0 | *want = SSL_NOTHING; |
636 | |
|
637 | 0 | switch (error) { |
638 | 0 | case SSL_ERROR_NONE: |
639 | 0 | VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_NONE", function); |
640 | 0 | break; |
641 | | |
642 | 0 | case SSL_ERROR_ZERO_RETURN: |
643 | 0 | VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_ZERO_RETURN", function); |
644 | 0 | break; |
645 | | |
646 | 0 | case SSL_ERROR_WANT_READ: |
647 | 0 | *want = SSL_READING; |
648 | 0 | return EAGAIN; |
649 | | |
650 | 0 | case SSL_ERROR_WANT_WRITE: |
651 | 0 | *want = SSL_WRITING; |
652 | 0 | return EAGAIN; |
653 | | |
654 | 0 | case SSL_ERROR_WANT_CONNECT: |
655 | 0 | VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_WANT_CONNECT", function); |
656 | 0 | break; |
657 | | |
658 | 0 | case SSL_ERROR_WANT_ACCEPT: |
659 | 0 | VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_WANT_ACCEPT", function); |
660 | 0 | break; |
661 | | |
662 | 0 | case SSL_ERROR_WANT_X509_LOOKUP: |
663 | 0 | VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_WANT_X509_LOOKUP", |
664 | 0 | function); |
665 | 0 | break; |
666 | | |
667 | 0 | case SSL_ERROR_SYSCALL: { |
668 | 0 | int queued_error = ERR_get_error(); |
669 | 0 | if (queued_error == 0) { |
670 | 0 | if (ret < 0) { |
671 | 0 | int status = errno; |
672 | 0 | VLOG_WARN_RL(&rl, "%s: system error (%s)", |
673 | 0 | function, ovs_strerror(status)); |
674 | 0 | return status; |
675 | 0 | } else { |
676 | 0 | VLOG_WARN_RL(&rl, "%s: unexpected SSL/TLS connection close", |
677 | 0 | function); |
678 | 0 | return EPROTO; |
679 | 0 | } |
680 | 0 | } else { |
681 | 0 | VLOG_WARN_RL(&rl, "%s: %s", |
682 | 0 | function, ERR_error_string(queued_error, NULL)); |
683 | 0 | break; |
684 | 0 | } |
685 | 0 | } |
686 | | |
687 | 0 | case SSL_ERROR_SSL: |
688 | 0 | interpret_queued_ssl_error(function); |
689 | 0 | break; |
690 | | |
691 | 0 | default: |
692 | 0 | VLOG_ERR_RL(&rl, "%s: bad SSL error code %d", function, error); |
693 | 0 | break; |
694 | 0 | } |
695 | 0 | return EIO; |
696 | 0 | } |
697 | | |
698 | | static ssize_t |
699 | | ssl_recv(struct stream *stream, void *buffer, size_t n) |
700 | 0 | { |
701 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
702 | 0 | int old_state; |
703 | 0 | ssize_t ret; |
704 | | |
705 | | /* Behavior of zero-byte SSL_read is poorly defined. */ |
706 | 0 | ovs_assert(n > 0); |
707 | |
|
708 | 0 | old_state = SSL_get_state(sslv->ssl); |
709 | 0 | ret = SSL_read(sslv->ssl, buffer, n); |
710 | 0 | if (old_state != SSL_get_state(sslv->ssl)) { |
711 | 0 | sslv->tx_want = SSL_NOTHING; |
712 | 0 | } |
713 | 0 | sslv->rx_want = SSL_NOTHING; |
714 | |
|
715 | 0 | if (ret > 0) { |
716 | 0 | return ret; |
717 | 0 | } else { |
718 | 0 | int error = SSL_get_error(sslv->ssl, ret); |
719 | 0 | if (error == SSL_ERROR_ZERO_RETURN) { |
720 | 0 | return 0; |
721 | 0 | } else { |
722 | 0 | return -interpret_ssl_error("SSL_read", ret, error, |
723 | 0 | &sslv->rx_want); |
724 | 0 | } |
725 | 0 | } |
726 | 0 | } |
727 | | |
728 | | static void |
729 | | ssl_clear_txbuf(struct ssl_stream *sslv) |
730 | 0 | { |
731 | 0 | ofpbuf_delete(sslv->txbuf); |
732 | 0 | sslv->txbuf = NULL; |
733 | 0 | } |
734 | | |
735 | | static int |
736 | | ssl_do_tx(struct stream *stream) |
737 | 0 | { |
738 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
739 | |
|
740 | 0 | for (;;) { |
741 | 0 | int old_state = SSL_get_state(sslv->ssl); |
742 | 0 | int ret = SSL_write(sslv->ssl, sslv->txbuf->data, sslv->txbuf->size); |
743 | 0 | if (old_state != SSL_get_state(sslv->ssl)) { |
744 | 0 | sslv->rx_want = SSL_NOTHING; |
745 | 0 | } |
746 | 0 | sslv->tx_want = SSL_NOTHING; |
747 | 0 | if (ret > 0) { |
748 | 0 | ofpbuf_pull(sslv->txbuf, ret); |
749 | 0 | if (sslv->txbuf->size == 0) { |
750 | 0 | return 0; |
751 | 0 | } |
752 | 0 | } else { |
753 | 0 | int ssl_error = SSL_get_error(sslv->ssl, ret); |
754 | 0 | if (ssl_error == SSL_ERROR_ZERO_RETURN) { |
755 | 0 | VLOG_WARN_RL(&rl, "SSL_write: connection closed"); |
756 | 0 | return EPIPE; |
757 | 0 | } else { |
758 | 0 | return interpret_ssl_error("SSL_write", ret, ssl_error, |
759 | 0 | &sslv->tx_want); |
760 | 0 | } |
761 | 0 | } |
762 | 0 | } |
763 | 0 | } |
764 | | |
765 | | static ssize_t |
766 | | ssl_send(struct stream *stream, const void *buffer, size_t n) |
767 | 0 | { |
768 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
769 | |
|
770 | 0 | if (sslv->txbuf) { |
771 | 0 | return -EAGAIN; |
772 | 0 | } else { |
773 | 0 | struct ofpbuf buf; |
774 | 0 | int error; |
775 | |
|
776 | 0 | ofpbuf_use_const(&buf, buffer, n); |
777 | 0 | sslv->txbuf = &buf; |
778 | 0 | error = ssl_do_tx(stream); |
779 | 0 | switch (error) { |
780 | 0 | case 0: |
781 | 0 | sslv->txbuf = NULL; |
782 | 0 | return n; |
783 | 0 | case EAGAIN: |
784 | | /* Copy remaining data. */ |
785 | 0 | sslv->txbuf = ofpbuf_clone_data(buf.data, buf.size); |
786 | 0 | return n; |
787 | 0 | default: |
788 | 0 | sslv->txbuf = NULL; |
789 | 0 | return -error; |
790 | 0 | } |
791 | 0 | } |
792 | 0 | } |
793 | | |
794 | | static void |
795 | | ssl_run(struct stream *stream) |
796 | 0 | { |
797 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
798 | |
|
799 | 0 | if (sslv->txbuf && ssl_do_tx(stream) != EAGAIN) { |
800 | 0 | ssl_clear_txbuf(sslv); |
801 | 0 | } |
802 | 0 | } |
803 | | |
804 | | static void |
805 | | ssl_run_wait(struct stream *stream) |
806 | 0 | { |
807 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
808 | |
|
809 | 0 | if (sslv->tx_want != SSL_NOTHING) { |
810 | 0 | poll_fd_wait(sslv->fd, want_to_poll_events(sslv->tx_want)); |
811 | 0 | } |
812 | 0 | } |
813 | | |
814 | | static void |
815 | | ssl_wait(struct stream *stream, enum stream_wait_type wait) |
816 | 0 | { |
817 | 0 | struct ssl_stream *sslv = ssl_stream_cast(stream); |
818 | |
|
819 | 0 | switch (wait) { |
820 | 0 | case STREAM_CONNECT: |
821 | 0 | if (stream_connect(stream) != EAGAIN) { |
822 | 0 | poll_immediate_wake(); |
823 | 0 | } else { |
824 | 0 | switch (sslv->state) { |
825 | 0 | case STATE_TCP_CONNECTING: |
826 | 0 | poll_fd_wait(sslv->fd, POLLOUT); |
827 | 0 | break; |
828 | | |
829 | 0 | case STATE_SSL_CONNECTING: |
830 | | /* ssl_connect() called SSL_accept() or SSL_connect(), which |
831 | | * set up the status that we test here. */ |
832 | 0 | poll_fd_wait(sslv->fd, |
833 | 0 | want_to_poll_events(SSL_want(sslv->ssl))); |
834 | 0 | break; |
835 | | |
836 | 0 | default: |
837 | 0 | OVS_NOT_REACHED(); |
838 | 0 | } |
839 | 0 | } |
840 | 0 | break; |
841 | | |
842 | 0 | case STREAM_RECV: |
843 | 0 | if (sslv->rx_want != SSL_NOTHING) { |
844 | 0 | poll_fd_wait(sslv->fd, want_to_poll_events(sslv->rx_want)); |
845 | 0 | } else { |
846 | 0 | poll_immediate_wake(); |
847 | 0 | } |
848 | 0 | break; |
849 | | |
850 | 0 | case STREAM_SEND: |
851 | 0 | if (!sslv->txbuf) { |
852 | | /* We have room in our tx queue. */ |
853 | 0 | poll_immediate_wake(); |
854 | 0 | } else { |
855 | | /* stream_run_wait() will do the right thing; don't bother with |
856 | | * redundancy. */ |
857 | 0 | } |
858 | 0 | break; |
859 | | |
860 | 0 | default: |
861 | 0 | OVS_NOT_REACHED(); |
862 | 0 | } |
863 | 0 | } |
864 | | |
865 | | const struct stream_class ssl_stream_class = { |
866 | | "ssl", /* name */ |
867 | | true, /* needs_probes */ |
868 | | ssl_open, /* open */ |
869 | | ssl_close, /* close */ |
870 | | ssl_connect, /* connect */ |
871 | | ssl_recv, /* recv */ |
872 | | ssl_send, /* send */ |
873 | | ssl_run, /* run */ |
874 | | ssl_run_wait, /* run_wait */ |
875 | | ssl_wait, /* wait */ |
876 | | }; |
877 | | |
878 | | /* Passive SSL/TLS. */ |
879 | | |
880 | | struct pssl_pstream |
881 | | { |
882 | | struct pstream pstream; |
883 | | int fd; |
884 | | }; |
885 | | |
886 | | const struct pstream_class pssl_pstream_class; |
887 | | |
888 | | static struct pssl_pstream * |
889 | | pssl_pstream_cast(struct pstream *pstream) |
890 | 0 | { |
891 | 0 | pstream_assert_class(pstream, &pssl_pstream_class); |
892 | 0 | return CONTAINER_OF(pstream, struct pssl_pstream, pstream); |
893 | 0 | } |
894 | | |
895 | | static int |
896 | | pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp, |
897 | | uint8_t dscp) |
898 | 0 | { |
899 | 0 | struct sockaddr_storage ss; |
900 | 0 | struct pssl_pstream *pssl; |
901 | 0 | uint16_t port; |
902 | 0 | int retval; |
903 | 0 | int fd; |
904 | |
|
905 | 0 | retval = ssl_init(); |
906 | 0 | if (retval) { |
907 | 0 | return retval; |
908 | 0 | } |
909 | | |
910 | 0 | fd = inet_open_passive(SOCK_STREAM, suffix, OFP_PORT, &ss, dscp, true); |
911 | 0 | if (fd < 0) { |
912 | 0 | return -fd; |
913 | 0 | } |
914 | | |
915 | 0 | port = ss_get_port(&ss); |
916 | |
|
917 | 0 | struct ds bound_name = DS_EMPTY_INITIALIZER; |
918 | 0 | ds_put_format(&bound_name, "pssl:%"PRIu16":", port); |
919 | 0 | ss_format_address(&ss, &bound_name); |
920 | |
|
921 | 0 | pssl = xmalloc(sizeof *pssl); |
922 | 0 | pstream_init(&pssl->pstream, &pssl_pstream_class, |
923 | 0 | ds_steal_cstr(&bound_name)); |
924 | 0 | pstream_set_bound_port(&pssl->pstream, htons(port)); |
925 | 0 | pssl->fd = fd; |
926 | 0 | *pstreamp = &pssl->pstream; |
927 | |
|
928 | 0 | return 0; |
929 | 0 | } |
930 | | |
931 | | static void |
932 | | pssl_close(struct pstream *pstream) |
933 | 0 | { |
934 | 0 | struct pssl_pstream *pssl = pssl_pstream_cast(pstream); |
935 | 0 | closesocket(pssl->fd); |
936 | 0 | free(pssl); |
937 | 0 | } |
938 | | |
939 | | static int |
940 | | pssl_accept(struct pstream *pstream, struct stream **new_streamp) |
941 | 0 | { |
942 | 0 | struct pssl_pstream *pssl = pssl_pstream_cast(pstream); |
943 | 0 | struct sockaddr_storage ss; |
944 | 0 | socklen_t ss_len = sizeof ss; |
945 | 0 | int new_fd; |
946 | 0 | int error; |
947 | |
|
948 | 0 | new_fd = accept(pssl->fd, (struct sockaddr *) &ss, &ss_len); |
949 | 0 | if (new_fd < 0) { |
950 | 0 | error = sock_errno(); |
951 | | #ifdef _WIN32 |
952 | | if (error == WSAEWOULDBLOCK) { |
953 | | error = EAGAIN; |
954 | | } |
955 | | #endif |
956 | 0 | if (error != EAGAIN) { |
957 | 0 | VLOG_DBG_RL(&rl, "accept: %s", sock_strerror(error)); |
958 | 0 | } |
959 | 0 | return error; |
960 | 0 | } |
961 | | |
962 | 0 | error = set_nonblocking(new_fd); |
963 | 0 | if (error) { |
964 | 0 | closesocket(new_fd); |
965 | 0 | return error; |
966 | 0 | } |
967 | | |
968 | 0 | struct ds name = DS_EMPTY_INITIALIZER; |
969 | 0 | ds_put_cstr(&name, "ssl:"); |
970 | 0 | ss_format_address(&ss, &name); |
971 | 0 | ds_put_format(&name, ":%"PRIu16, ss_get_port(&ss)); |
972 | 0 | return new_ssl_stream(ds_steal_cstr(&name), NULL, new_fd, SERVER, |
973 | 0 | STATE_SSL_CONNECTING, new_streamp); |
974 | 0 | } |
975 | | |
976 | | static void |
977 | | pssl_wait(struct pstream *pstream) |
978 | 0 | { |
979 | 0 | struct pssl_pstream *pssl = pssl_pstream_cast(pstream); |
980 | 0 | poll_fd_wait(pssl->fd, POLLIN); |
981 | 0 | } |
982 | | |
983 | | const struct pstream_class pssl_pstream_class = { |
984 | | "pssl", |
985 | | true, |
986 | | pssl_open, |
987 | | pssl_close, |
988 | | pssl_accept, |
989 | | pssl_wait, |
990 | | }; |
991 | | |
992 | | /* |
993 | | * Returns true if OpenSSL error is WANT_READ or WANT_WRITE, indicating that |
994 | | * OpenSSL is requesting that we call it back when the socket is ready for read |
995 | | * or writing, respectively. |
996 | | */ |
997 | | static bool |
998 | | ssl_wants_io(int ssl_error) |
999 | 0 | { |
1000 | 0 | return (ssl_error == SSL_ERROR_WANT_WRITE |
1001 | 0 | || ssl_error == SSL_ERROR_WANT_READ); |
1002 | 0 | } |
1003 | | |
1004 | | static int |
1005 | | ssl_init(void) |
1006 | 0 | { |
1007 | 0 | static int init_status = -1; |
1008 | 0 | if (init_status < 0) { |
1009 | 0 | init_status = do_ssl_init(); |
1010 | 0 | ovs_assert(init_status >= 0); |
1011 | 0 | } |
1012 | 0 | return init_status; |
1013 | 0 | } |
1014 | | |
1015 | | static int |
1016 | | do_ssl_init(void) |
1017 | 0 | { |
1018 | 0 | if (!RAND_status()) { |
1019 | | /* We occasionally see OpenSSL fail to seed its random number generator |
1020 | | * in heavily loaded hypervisors. I suspect the following scenario: |
1021 | | * |
1022 | | * 1. OpenSSL calls read() to get 32 bytes from /dev/urandom. |
1023 | | * 2. The kernel generates 10 bytes of randomness and copies it out. |
1024 | | * 3. A signal arrives (perhaps SIGALRM). |
1025 | | * 4. The kernel interrupts the system call to service the signal. |
1026 | | * 5. Userspace gets 10 bytes of entropy. |
1027 | | * 6. OpenSSL doesn't read again to get the final 22 bytes. Therefore |
1028 | | * OpenSSL doesn't have enough entropy to consider itself |
1029 | | * initialized. |
1030 | | * |
1031 | | * The only part I'm not entirely sure about is #6, because the OpenSSL |
1032 | | * code is so hard to read. */ |
1033 | 0 | uint8_t seed[32]; |
1034 | 0 | int retval; |
1035 | |
|
1036 | 0 | VLOG_WARN("OpenSSL random seeding failed, reseeding ourselves"); |
1037 | |
|
1038 | 0 | retval = get_entropy(seed, sizeof seed); |
1039 | 0 | if (retval) { |
1040 | 0 | VLOG_ERR("failed to obtain entropy (%s)", |
1041 | 0 | ovs_retval_to_string(retval)); |
1042 | 0 | return retval > 0 ? retval : ENOPROTOOPT; |
1043 | 0 | } |
1044 | | |
1045 | 0 | RAND_seed(seed, sizeof seed); |
1046 | 0 | } |
1047 | | |
1048 | | /* Using version-flexible "connection method". Allowed versions will |
1049 | | * be restricted below. |
1050 | | * |
1051 | | * The context can be used for both client and server connections, so |
1052 | | * not using specific TLS_server_method() or TLS_client_method() here. */ |
1053 | 0 | const SSL_METHOD *method = TLS_method(); |
1054 | 0 | if (method == NULL) { |
1055 | 0 | VLOG_ERR("TLS_method: %s", ERR_error_string(ERR_get_error(), NULL)); |
1056 | 0 | return ENOPROTOOPT; |
1057 | 0 | } |
1058 | | |
1059 | 0 | ctx = SSL_CTX_new(method); |
1060 | 0 | if (ctx == NULL) { |
1061 | 0 | VLOG_ERR("SSL_CTX_new: %s", ERR_error_string(ERR_get_error(), NULL)); |
1062 | 0 | return ENOPROTOOPT; |
1063 | 0 | } |
1064 | | |
1065 | | #ifdef SSL_OP_IGNORE_UNEXPECTED_EOF |
1066 | | SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); |
1067 | | #endif |
1068 | | |
1069 | | /* Only allow TLSv1.2 or later. */ |
1070 | 0 | SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); |
1071 | 0 | SSL_CTX_set_max_proto_version(ctx, 0); |
1072 | |
|
1073 | 0 | #if OPENSSL_VERSION_NUMBER < 0x3000000fL |
1074 | 0 | SSL_CTX_set_tmp_dh_callback(ctx, tmp_dh_callback); |
1075 | | #else |
1076 | | SSL_CTX_set_dh_auto(ctx, 1); |
1077 | | #endif |
1078 | 0 | SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); |
1079 | 0 | SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); |
1080 | 0 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, |
1081 | 0 | NULL); |
1082 | 0 | SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); |
1083 | 0 | SSL_CTX_set_cipher_list(ctx, "DEFAULT:@SECLEVEL=2"); |
1084 | |
|
1085 | 0 | return 0; |
1086 | 0 | } |
1087 | | |
1088 | | #if OPENSSL_VERSION_NUMBER < 0x3000000fL |
1089 | | static DH * |
1090 | | tmp_dh_callback(SSL *ssl OVS_UNUSED, int is_export OVS_UNUSED, int keylength) |
1091 | 0 | { |
1092 | 0 | struct dh { |
1093 | 0 | int keylength; |
1094 | 0 | DH *dh; |
1095 | 0 | DH *(*constructor)(void); |
1096 | 0 | }; |
1097 | |
|
1098 | 0 | static struct dh dh_table[] = { |
1099 | 0 | {2048, NULL, get_dh2048}, |
1100 | 0 | {4096, NULL, get_dh4096}, |
1101 | 0 | }; |
1102 | |
|
1103 | 0 | struct dh *dh; |
1104 | |
|
1105 | 0 | for (dh = dh_table; dh < &dh_table[ARRAY_SIZE(dh_table)]; dh++) { |
1106 | 0 | if (dh->keylength >= keylength) { |
1107 | 0 | if (!dh->dh) { |
1108 | 0 | dh->dh = dh->constructor(); |
1109 | 0 | if (!dh->dh) { |
1110 | 0 | out_of_memory(); |
1111 | 0 | } |
1112 | 0 | } |
1113 | 0 | return dh->dh; |
1114 | 0 | } |
1115 | 0 | } |
1116 | 0 | VLOG_ERR_RL(&rl, "no Diffie-Hellman parameters for key length %d", |
1117 | 0 | keylength); |
1118 | 0 | return NULL; |
1119 | 0 | } |
1120 | | #endif |
1121 | | |
1122 | | /* Returns true if SSL/TLS is at least partially configured. */ |
1123 | | bool |
1124 | | stream_ssl_is_configured(void) |
1125 | 0 | { |
1126 | 0 | return private_key.file_name || certificate.file_name || ca_cert.file_name; |
1127 | 0 | } |
1128 | | |
1129 | | static bool |
1130 | | update_ssl_config(struct ssl_config_file *config, const char *file_name) |
1131 | 0 | { |
1132 | 0 | struct timespec mtime; |
1133 | 0 | int error; |
1134 | |
|
1135 | 0 | if (ssl_init() || !file_name) { |
1136 | 0 | return false; |
1137 | 0 | } |
1138 | | |
1139 | | /* If the file name hasn't changed and neither has the file contents, stop |
1140 | | * here. */ |
1141 | 0 | error = get_mtime(file_name, &mtime); |
1142 | 0 | if (error && error != ENOENT) { |
1143 | 0 | VLOG_ERR_RL(&rl, "%s: stat failed (%s)", |
1144 | 0 | file_name, ovs_strerror(error)); |
1145 | 0 | } |
1146 | 0 | if (config->file_name |
1147 | 0 | && !strcmp(config->file_name, file_name) |
1148 | 0 | && mtime.tv_sec == config->mtime.tv_sec |
1149 | 0 | && mtime.tv_nsec == config->mtime.tv_nsec) { |
1150 | 0 | return false; |
1151 | 0 | } |
1152 | | |
1153 | | /* Update 'config'. */ |
1154 | 0 | config->mtime = mtime; |
1155 | 0 | if (file_name != config->file_name) { |
1156 | 0 | free(config->file_name); |
1157 | 0 | config->file_name = xstrdup(file_name); |
1158 | 0 | } |
1159 | 0 | return true; |
1160 | 0 | } |
1161 | | |
1162 | | static void |
1163 | | stream_ssl_set_private_key_file__(const char *file_name) |
1164 | 0 | { |
1165 | 0 | if (SSL_CTX_use_PrivateKey_file(ctx, file_name, SSL_FILETYPE_PEM) == 1) { |
1166 | 0 | private_key.read = true; |
1167 | 0 | } else { |
1168 | 0 | VLOG_ERR("SSL_use_PrivateKey_file: %s", |
1169 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
1170 | 0 | } |
1171 | 0 | } |
1172 | | |
1173 | | void |
1174 | | stream_ssl_set_private_key_file(const char *file_name) |
1175 | 0 | { |
1176 | 0 | if (update_ssl_config(&private_key, file_name)) { |
1177 | 0 | stream_ssl_set_private_key_file__(file_name); |
1178 | 0 | } |
1179 | 0 | } |
1180 | | |
1181 | | static void |
1182 | | stream_ssl_set_certificate_file__(const char *file_name) |
1183 | 0 | { |
1184 | 0 | if (SSL_CTX_use_certificate_file(ctx, file_name, SSL_FILETYPE_PEM) == 1) { |
1185 | 0 | certificate.read = true; |
1186 | 0 | } else { |
1187 | 0 | VLOG_ERR("SSL_use_certificate_file: %s", |
1188 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
1189 | 0 | } |
1190 | 0 | } |
1191 | | |
1192 | | void |
1193 | | stream_ssl_set_certificate_file(const char *file_name) |
1194 | 0 | { |
1195 | 0 | if (update_ssl_config(&certificate, file_name)) { |
1196 | 0 | stream_ssl_set_certificate_file__(file_name); |
1197 | 0 | } |
1198 | 0 | } |
1199 | | |
1200 | | /* Sets the private key and certificate files in one operation. Use this |
1201 | | * interface, instead of calling stream_ssl_set_private_key_file() and |
1202 | | * stream_ssl_set_certificate_file() individually, in the main loop of a |
1203 | | * long-running program whose key and certificate might change at runtime. |
1204 | | * |
1205 | | * This is important because of OpenSSL's behavior. If an OpenSSL context |
1206 | | * already has a certificate, and stream_ssl_set_private_key_file() is called |
1207 | | * to install a new private key, OpenSSL will report an error because the new |
1208 | | * private key does not match the old certificate. The other order, of setting |
1209 | | * a new certificate, then setting a new private key, does work. |
1210 | | * |
1211 | | * If this were the only problem, calling stream_ssl_set_certificate_file() |
1212 | | * before stream_ssl_set_private_key_file() would fix it. But, if the private |
1213 | | * key is changed before the certificate (e.g. someone "scp"s or "mv"s the new |
1214 | | * private key in place before the certificate), then OpenSSL would reject that |
1215 | | * change, and then the change of certificate would succeed, but there would be |
1216 | | * no associated private key (because it had only changed once and therefore |
1217 | | * there was no point in re-reading it). |
1218 | | * |
1219 | | * This function avoids both problems by, whenever either the certificate or |
1220 | | * the private key file changes, re-reading both of them, in the correct order. |
1221 | | */ |
1222 | | void |
1223 | | stream_ssl_set_key_and_cert(const char *private_key_file, |
1224 | | const char *certificate_file) |
1225 | 0 | { |
1226 | 0 | if (update_ssl_config(&private_key, private_key_file) |
1227 | 0 | && update_ssl_config(&certificate, certificate_file)) { |
1228 | 0 | stream_ssl_set_certificate_file__(certificate_file); |
1229 | 0 | stream_ssl_set_private_key_file__(private_key_file); |
1230 | 0 | } |
1231 | 0 | } |
1232 | | |
1233 | | /* Sets SSL/TLS ciphers for TLSv1.2 based on string input. |
1234 | | * Aborts with an error message if 'arg' is not valid. */ |
1235 | | void |
1236 | | stream_ssl_set_ciphers(const char *arg) |
1237 | 0 | { |
1238 | 0 | if (ssl_init() || !arg || !strcmp(ssl_ciphers, arg)) { |
1239 | 0 | return; |
1240 | 0 | } |
1241 | 0 | if (SSL_CTX_set_cipher_list(ctx,arg) == 0) { |
1242 | 0 | VLOG_ERR("SSL_CTX_set_cipher_list: %s", |
1243 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
1244 | 0 | } |
1245 | 0 | ssl_ciphers = xstrdup(arg); |
1246 | 0 | } |
1247 | | |
1248 | | /* Sets TLS ciphersuites for TLSv1.3 and later based on string input. |
1249 | | * Aborts with an error message if 'arg' is not valid. */ |
1250 | | void |
1251 | | stream_ssl_set_ciphersuites(const char *arg) |
1252 | 0 | { |
1253 | 0 | if (ssl_init() || !arg || !strcmp(ssl_ciphersuites, arg)) { |
1254 | 0 | return; |
1255 | 0 | } |
1256 | 0 | if (SSL_CTX_set_ciphersuites(ctx, arg) == 0) { |
1257 | 0 | VLOG_ERR("SSL_CTX_set_ciphersuites: %s", |
1258 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
1259 | 0 | } |
1260 | 0 | ssl_ciphersuites = xstrdup(arg); |
1261 | 0 | } |
1262 | | |
1263 | | /* Sets the server name override for SNI (Server Name Indication). |
1264 | | * If 'server_name' is NULL, clears any existing override and SNI will |
1265 | | * use the hostname from the connection string. */ |
1266 | | void |
1267 | | stream_ssl_set_server_name(const char *server_name) |
1268 | 0 | { |
1269 | 0 | free(ssl_server_name_override); |
1270 | 0 | ssl_server_name_override = nullable_xstrdup(server_name); |
1271 | 0 | } |
1272 | | |
1273 | | /* Set SSL/TLS protocols based on the string input. Aborts with an error |
1274 | | * message if 'arg' is invalid. */ |
1275 | | void |
1276 | | stream_ssl_set_protocols(const char *arg) |
1277 | 0 | { |
1278 | 0 | if (ssl_init() || !arg || !strcmp(arg, ssl_protocols)) { |
1279 | 0 | return; |
1280 | 0 | } |
1281 | | |
1282 | 0 | struct sset set = SSET_INITIALIZER(&set); |
1283 | 0 | struct { |
1284 | 0 | const char *name; |
1285 | 0 | int version; |
1286 | 0 | bool deprecated; |
1287 | 0 | } protocols[] = { |
1288 | 0 | {"later", 0 /* any version */, false}, |
1289 | 0 | {"TLSv1.2", TLS1_2_VERSION, false}, |
1290 | 0 | {"TLSv1.3", TLS1_3_VERSION, false}, |
1291 | 0 | }; |
1292 | 0 | char *dash = strchr(arg, '-'); |
1293 | 0 | bool or_later = false; |
1294 | 0 | int len = strlen(arg); |
1295 | |
|
1296 | 0 | if (len && arg[len - 1] == '+') { |
1297 | | /* We only support full ranges, so more than one version or later "X+" |
1298 | | * doesn't make a lot of sense. */ |
1299 | 0 | sset_add_and_free(&set, xmemdup0(arg, len - 1)); |
1300 | 0 | or_later = true; |
1301 | 0 | } else if (dash) { |
1302 | | /* Again, do not attempt to parse multiple ranges. The range should |
1303 | | * always be a single "X-Y". */ |
1304 | 0 | sset_add_and_free(&set, xmemdup0(arg, dash - arg)); |
1305 | 0 | sset_add_and_free(&set, xstrdup(dash + 1)); |
1306 | 0 | } else { |
1307 | | /* Otherwise, it's a list that should not include ranges. */ |
1308 | 0 | sset_from_delimited_string(&set, arg, " ,\t"); |
1309 | 0 | } |
1310 | |
|
1311 | 0 | if (sset_is_empty(&set)) { |
1312 | 0 | VLOG_ERR("SSL/TLS protocol settings invalid"); |
1313 | 0 | goto exit; |
1314 | 0 | } |
1315 | | |
1316 | 0 | size_t min_version = ARRAY_SIZE(protocols) + 1; |
1317 | 0 | size_t max_version = 0; |
1318 | 0 | unsigned long map = 0; |
1319 | |
|
1320 | 0 | for (size_t i = 1; i < ARRAY_SIZE(protocols); i++) { |
1321 | 0 | if (sset_contains(&set, protocols[i].name)) { |
1322 | 0 | min_version = MIN(min_version, i); |
1323 | 0 | max_version = MAX(max_version, i); |
1324 | 0 | if (protocols[i].deprecated) { |
1325 | 0 | VLOG_WARN("%s protocol is deprecated", protocols[i].name); |
1326 | 0 | } |
1327 | 0 | bitmap_set1(&map, i); |
1328 | 0 | sset_find_and_delete(&set, protocols[i].name); |
1329 | 0 | } |
1330 | 0 | } |
1331 | |
|
1332 | 0 | if (!sset_is_empty(&set)) { |
1333 | 0 | const char *word; |
1334 | |
|
1335 | 0 | SSET_FOR_EACH (word, &set) { |
1336 | 0 | VLOG_ERR("%s: SSL/TLS protocol not recognized", word); |
1337 | 0 | } |
1338 | 0 | goto exit; |
1339 | 0 | } |
1340 | | |
1341 | | /* At this point we must have parsed at least one protocol. */ |
1342 | 0 | ovs_assert(min_version && min_version < ARRAY_SIZE(protocols)); |
1343 | 0 | ovs_assert(max_version && max_version < ARRAY_SIZE(protocols)); |
1344 | 0 | if (!or_later && !dash) { |
1345 | 0 | for (size_t i = min_version + 1; i < max_version; i++) { |
1346 | 0 | if (!bitmap_is_set(&map, i)) { |
1347 | 0 | VLOG_WARN("SSL/TLS protocol %s" |
1348 | 0 | " is not configured, but will be enabled anyway.", |
1349 | 0 | protocols[i].name); |
1350 | 0 | } |
1351 | 0 | } |
1352 | 0 | } |
1353 | |
|
1354 | 0 | if (or_later) { |
1355 | 0 | ovs_assert(min_version == max_version); |
1356 | 0 | max_version = 0; |
1357 | 0 | } |
1358 | | |
1359 | | /* Set the actual versions. */ |
1360 | 0 | SSL_CTX_set_min_proto_version(ctx, protocols[min_version].version); |
1361 | 0 | SSL_CTX_set_max_proto_version(ctx, protocols[max_version].version); |
1362 | 0 | VLOG_DBG("Enabled protocol range: %s%s%s", protocols[min_version].name, |
1363 | 0 | max_version ? " - " : " or ", |
1364 | 0 | protocols[max_version].name); |
1365 | 0 | ssl_protocols = xstrdup(arg); |
1366 | |
|
1367 | 0 | exit: |
1368 | 0 | sset_destroy(&set); |
1369 | 0 | } |
1370 | | |
1371 | | /* Reads the X509 certificate or certificates in file 'file_name'. On success, |
1372 | | * stores the address of the first element in an array of pointers to |
1373 | | * certificates in '*certs' and the number of certificates in the array in |
1374 | | * '*n_certs', and returns 0. On failure, stores a null pointer in '*certs', 0 |
1375 | | * in '*n_certs', and returns a positive errno value. |
1376 | | * |
1377 | | * The caller is responsible for freeing '*certs'. */ |
1378 | | static int |
1379 | | read_cert_file(const char *file_name, X509 ***certs, size_t *n_certs) |
1380 | 0 | { |
1381 | 0 | FILE *file; |
1382 | 0 | size_t allocated_certs = 0; |
1383 | |
|
1384 | 0 | *certs = NULL; |
1385 | 0 | *n_certs = 0; |
1386 | |
|
1387 | 0 | file = fopen(file_name, "r"); |
1388 | 0 | if (!file) { |
1389 | 0 | VLOG_ERR("failed to open %s for reading: %s", |
1390 | 0 | file_name, ovs_strerror(errno)); |
1391 | 0 | return errno; |
1392 | 0 | } |
1393 | | |
1394 | 0 | for (;;) { |
1395 | 0 | X509 *cert; |
1396 | 0 | int c; |
1397 | | |
1398 | | /* Read certificate from file. */ |
1399 | 0 | cert = PEM_read_X509(file, NULL, NULL, NULL); |
1400 | 0 | if (!cert) { |
1401 | 0 | size_t i; |
1402 | |
|
1403 | 0 | VLOG_ERR("PEM_read_X509 failed reading %s: %s", |
1404 | 0 | file_name, ERR_error_string(ERR_get_error(), NULL)); |
1405 | 0 | for (i = 0; i < *n_certs; i++) { |
1406 | 0 | X509_free((*certs)[i]); |
1407 | 0 | } |
1408 | 0 | free(*certs); |
1409 | 0 | *certs = NULL; |
1410 | 0 | *n_certs = 0; |
1411 | 0 | fclose(file); |
1412 | 0 | return EIO; |
1413 | 0 | } |
1414 | | |
1415 | | /* Add certificate to array. */ |
1416 | 0 | if (*n_certs >= allocated_certs) { |
1417 | 0 | *certs = x2nrealloc(*certs, &allocated_certs, sizeof **certs); |
1418 | 0 | } |
1419 | 0 | (*certs)[(*n_certs)++] = cert; |
1420 | | |
1421 | | /* Are there additional certificates in the file? */ |
1422 | 0 | do { |
1423 | 0 | c = getc(file); |
1424 | 0 | } while (isspace(c)); |
1425 | 0 | if (c == EOF) { |
1426 | 0 | break; |
1427 | 0 | } |
1428 | 0 | ungetc(c, file); |
1429 | 0 | } |
1430 | 0 | fclose(file); |
1431 | 0 | return 0; |
1432 | 0 | } |
1433 | | |
1434 | | |
1435 | | /* Sets 'file_name' as the name of a file containing one or more X509 |
1436 | | * certificates to send to the peer. Typical use in OpenFlow is to send the CA |
1437 | | * certificate to the peer, which enables a switch to pick up the controller's |
1438 | | * CA certificate on its first connection. */ |
1439 | | void |
1440 | | stream_ssl_set_peer_ca_cert_file(const char *file_name) |
1441 | 0 | { |
1442 | 0 | X509 **certs; |
1443 | 0 | size_t n_certs; |
1444 | 0 | size_t i; |
1445 | |
|
1446 | 0 | if (ssl_init()) { |
1447 | 0 | return; |
1448 | 0 | } |
1449 | | |
1450 | 0 | if (!read_cert_file(file_name, &certs, &n_certs)) { |
1451 | 0 | for (i = 0; i < n_certs; i++) { |
1452 | 0 | if (SSL_CTX_add_extra_chain_cert(ctx, certs[i]) != 1) { |
1453 | 0 | VLOG_ERR("SSL_CTX_add_extra_chain_cert: %s", |
1454 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
1455 | 0 | } |
1456 | 0 | } |
1457 | 0 | free(certs); |
1458 | 0 | } |
1459 | 0 | } |
1460 | | |
1461 | | /* Logs fingerprint of CA certificate 'cert' obtained from 'file_name'. */ |
1462 | | static void |
1463 | | log_ca_cert(const char *file_name, X509 *cert) |
1464 | 0 | { |
1465 | 0 | unsigned char digest[EVP_MAX_MD_SIZE]; |
1466 | 0 | unsigned int n_bytes; |
1467 | 0 | struct ds fp; |
1468 | 0 | char *subject; |
1469 | |
|
1470 | 0 | ds_init(&fp); |
1471 | 0 | if (!X509_digest(cert, EVP_sha1(), digest, &n_bytes)) { |
1472 | 0 | ds_put_cstr(&fp, "<out of memory>"); |
1473 | 0 | } else { |
1474 | 0 | unsigned int i; |
1475 | 0 | for (i = 0; i < n_bytes; i++) { |
1476 | 0 | if (i) { |
1477 | 0 | ds_put_char(&fp, ':'); |
1478 | 0 | } |
1479 | 0 | ds_put_format(&fp, "%02x", digest[i]); |
1480 | 0 | } |
1481 | 0 | } |
1482 | 0 | subject = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); |
1483 | 0 | VLOG_INFO("Trusting CA cert from %s (%s) (fingerprint %s)", file_name, |
1484 | 0 | subject ? subject : "<out of memory>", ds_cstr(&fp)); |
1485 | 0 | OPENSSL_free(subject); |
1486 | 0 | ds_destroy(&fp); |
1487 | 0 | } |
1488 | | |
1489 | | static void |
1490 | | stream_ssl_set_ca_cert_file__(const char *file_name, |
1491 | | bool bootstrap, bool force) |
1492 | 0 | { |
1493 | 0 | struct stat s; |
1494 | |
|
1495 | 0 | if (!update_ssl_config(&ca_cert, file_name) && !force) { |
1496 | 0 | return; |
1497 | 0 | } |
1498 | | |
1499 | 0 | if (!strcmp(file_name, "none")) { |
1500 | 0 | verify_peer_cert = false; |
1501 | 0 | VLOG_WARN("Peer certificate validation disabled " |
1502 | 0 | "(this is a security risk)"); |
1503 | 0 | } else if (bootstrap && stat(file_name, &s) && errno == ENOENT) { |
1504 | 0 | bootstrap_ca_cert = true; |
1505 | 0 | } else { |
1506 | 0 | STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(file_name); |
1507 | 0 | if (cert_names) { |
1508 | | /* Set up list of CAs that the server will accept from the |
1509 | | * client. */ |
1510 | 0 | SSL_CTX_set_client_CA_list(ctx, cert_names); |
1511 | | |
1512 | | /* Set up CAs for OpenSSL to trust in verifying the peer's |
1513 | | * certificate. */ |
1514 | 0 | SSL_CTX_set_cert_store(ctx, X509_STORE_new()); |
1515 | 0 | if (SSL_CTX_load_verify_locations(ctx, file_name, NULL) != 1) { |
1516 | 0 | VLOG_ERR("SSL_CTX_load_verify_locations: %s", |
1517 | 0 | ERR_error_string(ERR_get_error(), NULL)); |
1518 | 0 | return; |
1519 | 0 | } |
1520 | 0 | bootstrap_ca_cert = false; |
1521 | 0 | } else { |
1522 | 0 | VLOG_ERR("failed to load client certificates from %s: %s", |
1523 | 0 | file_name, ERR_error_string(ERR_get_error(), NULL)); |
1524 | 0 | } |
1525 | 0 | } |
1526 | 0 | ca_cert.read = true; |
1527 | 0 | } |
1528 | | |
1529 | | /* Sets 'file_name' as the name of the file from which to read the CA |
1530 | | * certificate used to verify the peer within SSL/TLS connections. If |
1531 | | * 'bootstrap' is false, the file must exist. If 'bootstrap' is false, then |
1532 | | * the file is read if it is exists; if it does not, then it will be created |
1533 | | * from the CA certificate received from the peer on the first SSL/TLS |
1534 | | * connection. */ |
1535 | | void |
1536 | | stream_ssl_set_ca_cert_file(const char *file_name, bool bootstrap) |
1537 | 0 | { |
1538 | 0 | stream_ssl_set_ca_cert_file__(file_name, bootstrap, false); |
1539 | 0 | } |
1540 | | |
1541 | | /* SSL/TLS protocol logging. */ |
1542 | | |
1543 | | static const char * |
1544 | | ssl_alert_level_to_string(uint8_t type) |
1545 | 0 | { |
1546 | 0 | switch (type) { |
1547 | 0 | case 1: return "warning"; |
1548 | 0 | case 2: return "fatal"; |
1549 | 0 | default: return "<unknown>"; |
1550 | 0 | } |
1551 | 0 | } |
1552 | | |
1553 | | static const char * |
1554 | | ssl_alert_description_to_string(uint8_t type) |
1555 | 0 | { |
1556 | 0 | switch (type) { |
1557 | 0 | case 0: return "close_notify"; |
1558 | 0 | case 10: return "unexpected_message"; |
1559 | 0 | case 20: return "bad_record_mac"; |
1560 | 0 | case 21: return "decryption_failed"; |
1561 | 0 | case 22: return "record_overflow"; |
1562 | 0 | case 30: return "decompression_failure"; |
1563 | 0 | case 40: return "handshake_failure"; |
1564 | 0 | case 42: return "bad_certificate"; |
1565 | 0 | case 43: return "unsupported_certificate"; |
1566 | 0 | case 44: return "certificate_revoked"; |
1567 | 0 | case 45: return "certificate_expired"; |
1568 | 0 | case 46: return "certificate_unknown"; |
1569 | 0 | case 47: return "illegal_parameter"; |
1570 | 0 | case 48: return "unknown_ca"; |
1571 | 0 | case 49: return "access_denied"; |
1572 | 0 | case 50: return "decode_error"; |
1573 | 0 | case 51: return "decrypt_error"; |
1574 | 0 | case 60: return "export_restriction"; |
1575 | 0 | case 70: return "protocol_version"; |
1576 | 0 | case 71: return "insufficient_security"; |
1577 | 0 | case 80: return "internal_error"; |
1578 | 0 | case 90: return "user_canceled"; |
1579 | 0 | case 100: return "no_renegotiation"; |
1580 | 0 | default: return "<unknown>"; |
1581 | 0 | } |
1582 | 0 | } |
1583 | | |
1584 | | static const char * |
1585 | | ssl_handshake_type_to_string(uint8_t type) |
1586 | 0 | { |
1587 | 0 | switch (type) { |
1588 | 0 | case 0: return "hello_request"; |
1589 | 0 | case 1: return "client_hello"; |
1590 | 0 | case 2: return "server_hello"; |
1591 | 0 | case 11: return "certificate"; |
1592 | 0 | case 12: return "server_key_exchange"; |
1593 | 0 | case 13: return "certificate_request"; |
1594 | 0 | case 14: return "server_hello_done"; |
1595 | 0 | case 15: return "certificate_verify"; |
1596 | 0 | case 16: return "client_key_exchange"; |
1597 | 0 | case 20: return "finished"; |
1598 | 0 | default: return "<unknown>"; |
1599 | 0 | } |
1600 | 0 | } |
1601 | | |
1602 | | static void |
1603 | | ssl_protocol_cb(int write_p, int version OVS_UNUSED, int content_type, |
1604 | | const void *buf_, size_t len, SSL *ssl OVS_UNUSED, void *sslv_) |
1605 | 0 | { |
1606 | 0 | const struct ssl_stream *sslv = sslv_; |
1607 | 0 | const uint8_t *buf = buf_; |
1608 | 0 | struct ds details; |
1609 | |
|
1610 | 0 | if (!VLOG_IS_DBG_ENABLED()) { |
1611 | 0 | return; |
1612 | 0 | } |
1613 | | |
1614 | 0 | ds_init(&details); |
1615 | 0 | if (content_type == 20) { |
1616 | 0 | ds_put_cstr(&details, "change_cipher_spec"); |
1617 | 0 | } else if (content_type == 21) { |
1618 | 0 | ds_put_format(&details, "alert: %s, %s", |
1619 | 0 | ssl_alert_level_to_string(buf[0]), |
1620 | 0 | ssl_alert_description_to_string(buf[1])); |
1621 | 0 | } else if (content_type == 22) { |
1622 | 0 | ds_put_format(&details, "handshake: %s", |
1623 | 0 | ssl_handshake_type_to_string(buf[0])); |
1624 | 0 | } else { |
1625 | 0 | ds_put_format(&details, "type %d", content_type); |
1626 | 0 | } |
1627 | |
|
1628 | 0 | VLOG_DBG("%s%u%s%s %s (%"PRIuSIZE" bytes)", |
1629 | 0 | sslv->type == CLIENT ? "client" : "server", |
1630 | 0 | sslv->session_nr, write_p ? "-->" : "<--", |
1631 | 0 | stream_get_name(&sslv->stream), ds_cstr(&details), len); |
1632 | |
|
1633 | 0 | ds_destroy(&details); |
1634 | 0 | } |