Add 1024-bit Diffie-Hellman parameters to vconn-ssl.
[sliver-openvswitch.git] / lib / vconn-ssl.c
1 /* Copyright (C) 2008 Board of Trustees, Leland Stanford Jr. University.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21
22 #include "vconn-ssl.h"
23 #include "dhparams.h"
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <netinet/tcp.h>
28 #include <openssl/err.h>
29 #include <openssl/ssl.h>
30 #include <poll.h>
31 #include <unistd.h>
32 #include "buffer.h"
33 #include "socket-util.h"
34 #include "util.h"
35 #include "openflow.h"
36 #include "ofp-print.h"
37 #include "vconn.h"
38
39 #include "vlog.h"
40 #define THIS_MODULE VLM_vconn_ssl
41
42 /* Active SSL. */
43
44 enum ssl_state {
45     STATE_SSL_CONNECTING,
46     STATE_CONNECTED
47 };
48
49 enum session_type {
50     CLIENT,
51     SERVER
52 };
53
54 struct ssl_vconn
55 {
56     struct vconn vconn;
57     enum ssl_state state;
58     int connect_error;
59     enum session_type type;
60     int fd;
61     SSL *ssl;
62     struct buffer *rxbuf;
63     struct buffer *txbuf;
64 };
65
66 /* SSL context created by ssl_init(). */
67 static SSL_CTX *ctx;
68
69 /* Required configuration. */
70 static bool has_private_key, has_certificate, has_ca_cert;
71
72 static int ssl_init(void);
73 static int do_ssl_init(void);
74 static void connect_completed(struct ssl_vconn *, int error);
75 static bool ssl_wants_io(int ssl_error);
76 static void ssl_close(struct vconn *);
77 static bool state_machine(struct ssl_vconn *sslv);
78 static DH *tmp_dh_callback(SSL *ssl, int is_export UNUSED, int keylength);
79
80 static int
81 new_ssl_vconn(const char *name, int fd, enum session_type type,
82               struct vconn **vconnp)
83 {
84     struct ssl_vconn *sslv;
85     SSL *ssl = NULL;
86     int on = 1;
87     int retval;
88
89     /* Check for all the needful configuration. */
90     if (!has_private_key) {
91         VLOG_ERR("Private key must be configured to use SSL");
92         goto error;
93     }
94     if (!has_certificate) {
95         VLOG_ERR("Certificate must be configured to use SSL");
96         goto error;
97     }
98     if (!has_ca_cert) {
99         VLOG_ERR("CA certificate must be configured to use SSL");
100         goto error;
101     }
102     if (!SSL_CTX_check_private_key(ctx)) {
103         VLOG_ERR("Private key does not match certificate public key");
104         goto error;
105     }
106
107     /* Make 'fd' non-blocking and disable Nagle. */
108     retval = set_nonblocking(fd);
109     if (retval) {
110         VLOG_ERR("%s: set_nonblocking: %s", name, strerror(retval));
111         close(fd);
112         return retval;
113     }
114     retval = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on);
115     if (retval) {
116         VLOG_ERR("%s: setsockopt(TCP_NODELAY): %s", name, strerror(errno));
117         close(fd);
118         return errno;
119     }
120
121     /* Create and configure OpenSSL stream. */
122     ssl = SSL_new(ctx);
123     if (ssl == NULL) {
124         VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL));
125         close(fd);
126         return ENOPROTOOPT;
127     }
128     if (SSL_set_fd(ssl, fd) == 0) {
129         VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL));
130         goto error;
131     }
132
133     /* Create and return the ssl_vconn. */
134     sslv = xmalloc(sizeof *sslv);
135     sslv->vconn.class = &ssl_vconn_class;
136     sslv->state = STATE_SSL_CONNECTING;
137     sslv->type = type;
138     sslv->fd = fd;
139     sslv->ssl = ssl;
140     sslv->rxbuf = NULL;
141     sslv->txbuf = NULL;
142     *vconnp = &sslv->vconn;
143     return 0;
144
145 error:
146     if (ssl) {
147         SSL_free(ssl);
148     }
149     close(fd);
150     return ENOPROTOOPT;
151 }
152
153 static struct ssl_vconn *
154 ssl_vconn_cast(struct vconn *vconn)
155 {
156     assert(vconn->class == &ssl_vconn_class);
157     return CONTAINER_OF(vconn, struct ssl_vconn, vconn);
158 }
159
160 static int
161 ssl_open(const char *name, char *suffix, struct vconn **vconnp)
162 {
163     char *save_ptr, *host_name, *port_string;
164     struct sockaddr_in sin;
165     int retval;
166     int fd;
167
168     retval = ssl_init();
169     if (retval) {
170         return retval;
171     }
172
173     /* Glibc 2.7 has a bug in strtok_r when compiling with optimization that
174      * can cause segfaults here:
175      * http://sources.redhat.com/bugzilla/show_bug.cgi?id=5614.
176      * Using "::" instead of the obvious ":" works around it. */
177     host_name = strtok_r(suffix, "::", &save_ptr);
178     port_string = strtok_r(NULL, "::", &save_ptr);
179     if (!host_name) {
180         fatal(0, "%s: bad peer name format", name);
181     }
182
183     memset(&sin, 0, sizeof sin);
184     sin.sin_family = AF_INET;
185     if (lookup_ip(host_name, &sin.sin_addr)) {
186         return ENOENT;
187     }
188     sin.sin_port = htons(port_string && *port_string ? atoi(port_string)
189                          : OFP_SSL_PORT);
190
191     /* Create socket. */
192     fd = socket(AF_INET, SOCK_STREAM, 0);
193     if (fd < 0) {
194         VLOG_ERR("%s: socket: %s", name, strerror(errno));
195         return errno;
196     }
197
198     /* Connect socket (blocking). */
199     retval = connect(fd, (struct sockaddr *) &sin, sizeof sin);
200     if (retval < 0) {
201         int error = errno;
202         VLOG_ERR("%s: connect: %s", name, strerror(error));
203         close(fd);
204         return error;
205     }
206
207     /* Make an ssl_vconn for the socket. */
208     return new_ssl_vconn(name, fd, CLIENT, vconnp);
209 }
210
211 static void
212 ssl_close(struct vconn *vconn)
213 {
214     struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
215     SSL_free(sslv->ssl);
216     close(sslv->fd);
217     free(sslv);
218 }
219
220 static bool
221 ssl_want_io_to_events(SSL *ssl, short int *events)
222 {
223     if (SSL_want_read(ssl)) {
224         *events |= POLLIN;
225         return true;
226     } else if (SSL_want_write(ssl)) {
227         *events |= POLLOUT;
228         return true;
229     } else {
230         return false;
231     }
232 }
233
234 static bool
235 ssl_prepoll(struct vconn *vconn, int want, struct pollfd *pfd)
236 {
237     struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
238     pfd->fd = sslv->fd;
239     if (!state_machine(sslv)) {
240         switch (sslv->state) {
241         case STATE_SSL_CONNECTING:
242             if (!ssl_want_io_to_events(sslv->ssl, &pfd->events)) {
243                 /* state_machine() should have transitioned us away to another
244                  * state. */
245                 NOT_REACHED();
246             }
247             break;
248         default:
249             NOT_REACHED();
250         }
251     } else if (sslv->connect_error) {
252         pfd->events = 0;
253         return true;
254     } else if (!ssl_want_io_to_events(sslv->ssl, &pfd->events)) {
255         if (want & WANT_RECV) {
256             pfd->events |= POLLIN;
257         }
258         if (want & WANT_SEND || sslv->txbuf) {
259             pfd->events |= POLLOUT;
260         }
261     }
262     return false;
263 }
264
265 static void
266 ssl_postpoll(struct vconn *vconn, short int *revents)
267 {
268     struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
269     if (!state_machine(sslv)) {
270         *revents = 0;
271     } else if (sslv->connect_error) {
272         *revents |= POLLERR;
273     } else if (*revents & POLLOUT && sslv->txbuf) {
274         ssize_t n = SSL_write(sslv->ssl, sslv->txbuf->data, sslv->txbuf->size);
275         if (n > 0) {
276             buffer_pull(sslv->txbuf, n);
277             if (sslv->txbuf->size == 0) {
278                 buffer_delete(sslv->txbuf);
279                 sslv->txbuf = NULL;
280             }
281         }
282         if (sslv->txbuf) {
283             *revents &= ~POLLOUT;
284         }
285     }
286 }
287
288 static int
289 interpret_ssl_error(const char *function, int ret, int error)
290 {
291     switch (error) {
292     case SSL_ERROR_NONE:
293         VLOG_ERR("%s: unexpected SSL_ERROR_NONE", function);
294         break;
295
296     case SSL_ERROR_ZERO_RETURN:
297         VLOG_ERR("%s: unexpected SSL_ERROR_ZERO_RETURN", function);
298         break;
299
300     case SSL_ERROR_WANT_READ:
301     case SSL_ERROR_WANT_WRITE:
302         return EAGAIN;
303
304     case SSL_ERROR_WANT_CONNECT:
305         VLOG_ERR("%s: unexpected SSL_ERROR_WANT_CONNECT", function);
306         break;
307
308     case SSL_ERROR_WANT_ACCEPT:
309         VLOG_ERR("%s: unexpected SSL_ERROR_WANT_ACCEPT", function);
310         break;
311
312     case SSL_ERROR_WANT_X509_LOOKUP:
313         VLOG_ERR("%s: unexpected SSL_ERROR_WANT_X509_LOOKUP", function);
314         break;
315
316     case SSL_ERROR_SYSCALL: {
317         int queued_error = ERR_get_error();
318         if (queued_error == 0) {
319             if (ret < 0) {
320                 int status = errno;
321                 VLOG_WARN("%s: system error (%s)", function, strerror(status));
322                 return status;
323             } else {
324                 VLOG_WARN("%s: unexpected SSL connection close", function);
325                 return EPROTO;
326             }
327         } else {
328             VLOG_DBG("%s: %s", function, ERR_error_string(queued_error, NULL));
329             break;
330         }
331     }
332
333     case SSL_ERROR_SSL: {
334         int queued_error = ERR_get_error();
335         if (queued_error != 0) {
336             VLOG_DBG("%s: %s", function, ERR_error_string(queued_error, NULL));
337         } else {
338             VLOG_ERR("%s: SSL_ERROR_SSL without queued error", function);
339         }
340         break;
341     }
342
343     default:
344         VLOG_ERR("%s: bad SSL error code %d", function, error);
345         break;
346     }
347     return EIO;
348 }
349
350 static int
351 ssl_recv(struct vconn *vconn, struct buffer **bufferp)
352 {
353     struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
354     struct buffer *rx;
355     size_t want_bytes;
356     ssize_t ret;
357
358     if (!state_machine(sslv)) {
359         return EAGAIN;
360     } else if (sslv->connect_error) {
361         return sslv->connect_error;
362     }
363
364     if (sslv->rxbuf == NULL) {
365         sslv->rxbuf = buffer_new(1564);
366     }
367     rx = sslv->rxbuf;
368
369 again:
370     if (sizeof(struct ofp_header) > rx->size) {
371         want_bytes = sizeof(struct ofp_header) - rx->size;
372     } else {
373         struct ofp_header *oh = rx->data;
374         size_t length = ntohs(oh->length);
375         if (length < sizeof(struct ofp_header)) {
376             VLOG_ERR("received too-short ofp_header (%zu bytes)", length);
377             return EPROTO;
378         }
379         want_bytes = length - rx->size;
380     }
381     buffer_reserve_tailroom(rx, want_bytes);
382
383     /* Behavior of zero-byte SSL_read is poorly defined. */
384     assert(want_bytes > 0);
385
386     ret = SSL_read(sslv->ssl, buffer_tail(rx), want_bytes);
387     if (ret > 0) {
388         rx->size += ret;
389         if (ret == want_bytes) {
390             if (rx->size > sizeof(struct ofp_header)) {
391                 *bufferp = rx;
392                 sslv->rxbuf = NULL;
393                 return 0;
394             } else {
395                 goto again;
396             }
397         }
398         return EAGAIN;
399     } else {
400         int error = SSL_get_error(sslv->ssl, ret);
401         if (error == SSL_ERROR_ZERO_RETURN) {
402             /* Connection closed (EOF). */
403             if (rx->size) {
404                 VLOG_WARN("SSL_read: unexpected connection close");
405                 return EPROTO;
406             } else {
407                 return EOF;
408             }
409         } else {
410             return interpret_ssl_error("SSL_read", ret, error);
411         }
412     }
413 }
414
415 static int
416 ssl_send(struct vconn *vconn, struct buffer *buffer)
417 {
418     struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
419     ssize_t ret;
420
421     if (!state_machine(sslv)) {
422         return EAGAIN;
423     } else if (sslv->connect_error) {
424         return sslv->connect_error;
425     }
426
427     if (sslv->txbuf) {
428         return EAGAIN;
429     }
430
431     ret = SSL_write(sslv->ssl, buffer->data, buffer->size);
432     if (ret > 0) {
433         if (ret == buffer->size) {
434             buffer_delete(buffer);
435         } else {
436             sslv->txbuf = buffer;
437             buffer_pull(buffer, ret);
438         }
439         return 0;
440     } else {
441         int error = SSL_get_error(sslv->ssl, ret);
442         if (error == SSL_ERROR_ZERO_RETURN) {
443             /* Connection closed (EOF). */
444             VLOG_WARN("SSL_write: connection close");
445             return EPIPE;
446         } else {
447             return interpret_ssl_error("SSL_write", ret, error);
448         }
449     }
450 }
451
452 struct vconn_class ssl_vconn_class = {
453     .name = "ssl",
454     .open = ssl_open,
455     .close = ssl_close,
456     .prepoll = ssl_prepoll,
457     .postpoll = ssl_postpoll,
458     .recv = ssl_recv,
459     .send = ssl_send,
460 };
461 \f
462 /* Passive SSL. */
463
464 struct pssl_vconn
465 {
466     struct vconn vconn;
467     int fd;
468 };
469
470 static struct pssl_vconn *
471 pssl_vconn_cast(struct vconn *vconn)
472 {
473     assert(vconn->class == &pssl_vconn_class);
474     return CONTAINER_OF(vconn, struct pssl_vconn, vconn);
475 }
476
477 static int
478 pssl_open(const char *name, char *suffix, struct vconn **vconnp)
479 {
480     struct sockaddr_in sin;
481     struct pssl_vconn *pssl;
482     int retval;
483     int fd;
484     unsigned int yes = 1;
485
486     retval = ssl_init();
487     if (retval) {
488         return retval;
489     }
490
491     /* Create socket. */
492     fd = socket(AF_INET, SOCK_STREAM, 0);
493     if (fd < 0) {
494         int error = errno;
495         VLOG_ERR("%s: socket: %s", name, strerror(error));
496         return error;
497     }
498
499     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
500         int error = errno;
501         VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", name, strerror(errno));
502         return error;
503     }
504
505     memset(&sin, 0, sizeof sin);
506     sin.sin_family = AF_INET;
507     sin.sin_addr.s_addr = htonl(INADDR_ANY);
508     sin.sin_port = htons(atoi(suffix) ? atoi(suffix) : OFP_SSL_PORT);
509     retval = bind(fd, (struct sockaddr *) &sin, sizeof sin);
510     if (retval < 0) {
511         int error = errno;
512         VLOG_ERR("%s: bind: %s", name, strerror(error));
513         close(fd);
514         return error;
515     }
516
517     retval = listen(fd, 10);
518     if (retval < 0) {
519         int error = errno;
520         VLOG_ERR("%s: listen: %s", name, strerror(error));
521         close(fd);
522         return error;
523     }
524
525     retval = set_nonblocking(fd);
526     if (retval) {
527         VLOG_ERR("%s: set_nonblocking: %s", name, strerror(retval));
528         close(fd);
529         return retval;
530     }
531
532     pssl = xmalloc(sizeof *pssl);
533     pssl->vconn.class = &pssl_vconn_class;
534     pssl->fd = fd;
535     *vconnp = &pssl->vconn;
536     return 0;
537 }
538
539 static void
540 pssl_close(struct vconn *vconn)
541 {
542     struct pssl_vconn *pssl = pssl_vconn_cast(vconn);
543     close(pssl->fd);
544     free(pssl);
545 }
546
547 static bool
548 pssl_prepoll(struct vconn *vconn, int want, struct pollfd *pfd)
549 {
550     struct pssl_vconn *pssl = pssl_vconn_cast(vconn);
551     pfd->fd = pssl->fd;
552     if (want & WANT_ACCEPT) {
553         pfd->events |= POLLIN;
554     }
555     return false;
556 }
557
558 static int
559 pssl_accept(struct vconn *vconn, struct vconn **new_vconnp)
560 {
561     struct pssl_vconn *pssl = pssl_vconn_cast(vconn);
562     int new_fd;
563
564     new_fd = accept(pssl->fd, NULL, NULL);
565     if (new_fd < 0) {
566         int error = errno;
567         if (error != EAGAIN) {
568             VLOG_DBG("pssl: accept: %s", strerror(error));
569         }
570         return error;
571     }
572
573     return new_ssl_vconn("ssl" /* FIXME */, new_fd, SERVER, new_vconnp);
574 }
575
576 struct vconn_class pssl_vconn_class = {
577     .name = "pssl",
578     .open = pssl_open,
579     .close = pssl_close,
580     .prepoll = pssl_prepoll,
581     .accept = pssl_accept,
582 };
583 \f
584 /*
585  * Returns true if OpenSSL error is WANT_READ or WANT_WRITE, indicating that
586  * OpenSSL is requesting that we call it back when the socket is ready for read
587  * or writing, respectively.
588  */
589 static bool
590 ssl_wants_io(int ssl_error)
591 {
592     return (ssl_error == SSL_ERROR_WANT_WRITE
593             || ssl_error == SSL_ERROR_WANT_READ);
594 }
595
596 static int
597 ssl_init(void)
598 {
599     static int init_status = -1;
600     if (init_status < 0) {
601         init_status = do_ssl_init();
602         assert(init_status >= 0);
603     }
604     return init_status;
605 }
606
607 static int
608 do_ssl_init(void)
609 {
610     SSL_METHOD *method;
611
612     SSL_library_init();
613     SSL_load_error_strings();
614
615     method = TLSv1_method();
616     if (method == NULL) {
617         VLOG_ERR("TLSv1_method: %s", ERR_error_string(ERR_get_error(), NULL));
618         return ENOPROTOOPT;
619     }
620
621     ctx = SSL_CTX_new(method);
622     if (ctx == NULL) {
623         VLOG_ERR("SSL_CTX_new: %s", ERR_error_string(ERR_get_error(), NULL));
624         return ENOPROTOOPT;
625     }
626     SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
627     SSL_CTX_set_tmp_dh_callback(ctx, tmp_dh_callback);
628     SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
629     SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
630     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
631                        NULL);
632
633     return 0;
634 }
635
636 static bool
637 state_machine(struct ssl_vconn *sslv)
638 {
639     if (sslv->state == STATE_SSL_CONNECTING) {
640         int ret = (sslv->type == CLIENT
641                    ? SSL_connect(sslv->ssl) : SSL_accept(sslv->ssl));
642         if (ret != 1) {
643             int error = SSL_get_error(sslv->ssl, ret);
644             if (ret < 0 && ssl_wants_io(error)) {
645                 /* Stay in this state to repeat the SSL_connect later. */
646                 return false;
647             } else {
648                 interpret_ssl_error((sslv->type == CLIENT ? "SSL_connect"
649                                      : "SSL_accept"), ret, error);
650                 shutdown(sslv->fd, SHUT_RDWR);
651                 connect_completed(sslv, EPROTO);
652             }
653         } else {
654             connect_completed(sslv, 0);
655         }
656     }
657     return sslv->state == STATE_CONNECTED;
658 }
659
660 static void
661 connect_completed(struct ssl_vconn *sslv, int error)
662 {
663     sslv->state = STATE_CONNECTED;
664     sslv->connect_error = error;
665 }
666
667 static DH *
668 tmp_dh_callback(SSL *ssl, int is_export UNUSED, int keylength)
669 {
670     struct dh {
671         int keylength;
672         DH *dh;
673         DH *(*constructor)(void);
674     };
675
676     static struct dh dh_table[] = {
677         {1024, NULL, get_dh1024},
678         {2048, NULL, get_dh2048},
679         {4096, NULL, get_dh4096},
680     };
681
682     struct dh *dh;
683
684     for (dh = dh_table; dh < &dh_table[ARRAY_SIZE(dh_table)]; dh++) {
685         if (dh->keylength == keylength) {
686             if (!dh->dh) {
687                 dh->dh = dh->constructor();
688                 if (!dh->dh) {
689                     fatal(ENOMEM, "out of memory constructing "
690                           "Diffie-Hellman parameters");
691                 }
692             }
693             return dh->dh;
694         }
695     }
696     VLOG_ERR("no Diffie-Hellman parameters for key length %d", keylength);
697     return NULL;
698 }
699
700 void
701 vconn_ssl_set_private_key_file(const char *file_name)
702 {
703     if (ssl_init()) {
704         return;
705     }
706     if (SSL_CTX_use_PrivateKey_file(ctx, file_name, SSL_FILETYPE_PEM) != 1) {
707         VLOG_ERR("SSL_use_PrivateKey_file: %s",
708                  ERR_error_string(ERR_get_error(), NULL));
709         return;
710     }
711     has_private_key = true;
712 }
713
714 void
715 vconn_ssl_set_certificate_file(const char *file_name)
716 {
717     if (ssl_init()) {
718         return;
719     }
720     if (SSL_CTX_use_certificate_chain_file(ctx, file_name) != 1) {
721         VLOG_ERR("SSL_use_certificate_file: %s",
722                  ERR_error_string(ERR_get_error(), NULL));
723         return;
724     }
725     has_certificate = true;
726 }
727
728 void
729 vconn_ssl_set_ca_cert_file(const char *file_name)
730 {
731     STACK_OF(X509_NAME) *ca_list;
732
733     if (ssl_init()) {
734         return;
735     }
736
737     /* Set up list of CAs that the server will accept from the client. */
738     ca_list = SSL_load_client_CA_file(file_name);
739     if (ca_list == NULL) {
740         VLOG_ERR("SSL_load_client_CA_file: %s",
741                  ERR_error_string(ERR_get_error(), NULL));
742         return;
743     }
744     SSL_CTX_set_client_CA_list(ctx, ca_list);
745
746     /* Set up CAs for OpenSSL to trust in verifying the peer's certificate. */
747     if (SSL_CTX_load_verify_locations(ctx, file_name, NULL) != 1) {
748         VLOG_ERR("SSL_load_verify_locations: %s",
749                  ERR_error_string(ERR_get_error(), NULL));
750         return;
751     }
752
753     has_ca_cert = true;
754 }