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