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