1 /*
2  * Copyright 2016 MongoDB, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "mongoc-config.h"
18 
19 #ifdef MONGOC_ENABLE_SSL_OPENSSL
20 
21 #include <bson/bson.h>
22 
23 #include <errno.h>
24 #include <string.h>
25 #include <openssl/bio.h>
26 #include <openssl/ssl.h>
27 #include <openssl/err.h>
28 #include <openssl/x509v3.h>
29 
30 #include "mongoc-counters-private.h"
31 #include "mongoc-errno-private.h"
32 #include "mongoc-ssl.h"
33 #include "mongoc-ssl-private.h"
34 #include "mongoc-stream-tls.h"
35 #include "mongoc-stream-private.h"
36 #include "mongoc-stream-tls-private.h"
37 #include "mongoc-stream-tls-openssl-bio-private.h"
38 #include "mongoc-stream-tls-openssl-private.h"
39 #include "mongoc-openssl-private.h"
40 #include "mongoc-trace-private.h"
41 #include "mongoc-log.h"
42 #include "mongoc-error.h"
43 
44 
45 #undef MONGOC_LOG_DOMAIN
46 #define MONGOC_LOG_DOMAIN "stream-tls-openssl"
47 
48 #define MONGOC_STREAM_TLS_OPENSSL_BUFFER_SIZE 4096
49 
50 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
51    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
52 static void
BIO_meth_free(BIO_METHOD * meth)53 BIO_meth_free (BIO_METHOD *meth)
54 {
55    /* Nothing to free pre OpenSSL 1.1.0 */
56 }
57 #endif
58 
59 
60 /*
61  *--------------------------------------------------------------------------
62  *
63  * _mongoc_stream_tls_openssl_destroy --
64  *
65  *       Cleanup after usage of a mongoc_stream_tls_openssl_t. Free all
66  *allocated
67  *       resources and ensure connections are closed.
68  *
69  * Returns:
70  *       None.
71  *
72  * Side effects:
73  *       None.
74  *
75  *--------------------------------------------------------------------------
76  */
77 
78 static void
_mongoc_stream_tls_openssl_destroy(mongoc_stream_t * stream)79 _mongoc_stream_tls_openssl_destroy (mongoc_stream_t *stream)
80 {
81    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
82    mongoc_stream_tls_openssl_t *openssl =
83       (mongoc_stream_tls_openssl_t *) tls->ctx;
84 
85    BSON_ASSERT (tls);
86 
87    BIO_free_all (openssl->bio);
88    openssl->bio = NULL;
89 
90    BIO_meth_free (openssl->meth);
91    openssl->meth = NULL;
92 
93    mongoc_stream_destroy (tls->base_stream);
94    tls->base_stream = NULL;
95 
96    SSL_CTX_free (openssl->ctx);
97    openssl->ctx = NULL;
98 
99    mongoc_openssl_ocsp_opt_destroy (openssl->ocsp_opts);
100    openssl->ocsp_opts = NULL;
101 
102    bson_free (openssl);
103    bson_free (stream);
104 
105    mongoc_counter_streams_active_dec ();
106    mongoc_counter_streams_disposed_inc ();
107 }
108 
109 
110 /*
111  *--------------------------------------------------------------------------
112  *
113  * _mongoc_stream_tls_openssl_failed --
114  *
115  *       Called on stream failure. Same as _mongoc_stream_tls_openssl_destroy()
116  *
117  * Returns:
118  *       None.
119  *
120  * Side effects:
121  *       None.
122  *
123  *--------------------------------------------------------------------------
124  */
125 
126 static void
_mongoc_stream_tls_openssl_failed(mongoc_stream_t * stream)127 _mongoc_stream_tls_openssl_failed (mongoc_stream_t *stream)
128 {
129    _mongoc_stream_tls_openssl_destroy (stream);
130 }
131 
132 
133 /*
134  *--------------------------------------------------------------------------
135  *
136  * _mongoc_stream_tls_openssl_close --
137  *
138  *       Close the underlying socket.
139  *
140  *       Linus dictates that you should not check the result of close()
141  *       since there is a race condition with EAGAIN and a new file
142  *       descriptor being opened.
143  *
144  * Returns:
145  *       0 on success; otherwise -1.
146  *
147  * Side effects:
148  *       The BIO fd is closed.
149  *
150  *--------------------------------------------------------------------------
151  */
152 
153 static int
_mongoc_stream_tls_openssl_close(mongoc_stream_t * stream)154 _mongoc_stream_tls_openssl_close (mongoc_stream_t *stream)
155 {
156    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
157    int ret = 0;
158    ENTRY;
159 
160    BSON_ASSERT (tls);
161 
162    ret = mongoc_stream_close (tls->base_stream);
163    RETURN (ret);
164 }
165 
166 
167 /*
168  *--------------------------------------------------------------------------
169  *
170  * _mongoc_stream_tls_openssl_flush --
171  *
172  *       Flush the underlying stream.
173  *
174  * Returns:
175  *       0 if successful; otherwise -1.
176  *
177  * Side effects:
178  *       None.
179  *
180  *--------------------------------------------------------------------------
181  */
182 
183 static int
_mongoc_stream_tls_openssl_flush(mongoc_stream_t * stream)184 _mongoc_stream_tls_openssl_flush (mongoc_stream_t *stream)
185 {
186    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
187    mongoc_stream_tls_openssl_t *openssl =
188       (mongoc_stream_tls_openssl_t *) tls->ctx;
189 
190    BSON_ASSERT (openssl);
191 
192    return BIO_flush (openssl->bio);
193 }
194 
195 
196 static ssize_t
_mongoc_stream_tls_openssl_write(mongoc_stream_tls_t * tls,char * buf,size_t buf_len)197 _mongoc_stream_tls_openssl_write (mongoc_stream_tls_t *tls,
198                                   char *buf,
199                                   size_t buf_len)
200 {
201    mongoc_stream_tls_openssl_t *openssl =
202       (mongoc_stream_tls_openssl_t *) tls->ctx;
203    ssize_t ret;
204    int64_t now;
205    int64_t expire = 0;
206    ENTRY;
207 
208    BSON_ASSERT (tls);
209    BSON_ASSERT (buf);
210    BSON_ASSERT (buf_len);
211 
212    if (tls->timeout_msec >= 0) {
213       expire = bson_get_monotonic_time () + (tls->timeout_msec * 1000UL);
214    }
215 
216    ret = BIO_write (openssl->bio, buf, buf_len);
217 
218    if (ret <= 0) {
219       return ret;
220    }
221 
222    if (expire) {
223       now = bson_get_monotonic_time ();
224 
225       if ((expire - now) < 0) {
226          if (ret < buf_len) {
227             mongoc_counter_streams_timeout_inc ();
228          }
229 
230          tls->timeout_msec = 0;
231       } else {
232          tls->timeout_msec = (expire - now) / 1000L;
233       }
234    }
235 
236    RETURN (ret);
237 }
238 
239 
240 /*
241  *--------------------------------------------------------------------------
242  *
243  * _mongoc_stream_tls_openssl_writev --
244  *
245  *       Write the iovec to the stream. This function will try to write
246  *       all of the bytes or fail. If the number of bytes is not equal
247  *       to the number requested, a failure or EOF has occurred.
248  *
249  * Returns:
250  *       -1 on failure, otherwise the number of bytes written.
251  *
252  * Side effects:
253  *       None.
254  *
255  * This function is copied as _mongoc_stream_tls_secure_transport_writev
256  *--------------------------------------------------------------------------
257  */
258 
259 static ssize_t
_mongoc_stream_tls_openssl_writev(mongoc_stream_t * stream,mongoc_iovec_t * iov,size_t iovcnt,int32_t timeout_msec)260 _mongoc_stream_tls_openssl_writev (mongoc_stream_t *stream,
261                                    mongoc_iovec_t *iov,
262                                    size_t iovcnt,
263                                    int32_t timeout_msec)
264 {
265    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
266    char buf[MONGOC_STREAM_TLS_OPENSSL_BUFFER_SIZE];
267    ssize_t ret = 0;
268    ssize_t child_ret;
269    size_t i;
270    size_t iov_pos = 0;
271 
272    /* There's a bit of a dance to coalesce vectorized writes into
273     * MONGOC_STREAM_TLS_OPENSSL_BUFFER_SIZE'd writes to avoid lots of small tls
274     * packets.
275     *
276     * The basic idea is that we want to combine writes in the buffer if they're
277     * smaller than the buffer, flushing as it gets full.  For larger writes, or
278     * the last write in the iovec array, we want to ignore the buffer and just
279     * write immediately.  We take care of doing buffer writes by re-invoking
280     * ourself with a single iovec_t, pointing at our stack buffer.
281     */
282    char *buf_head = buf;
283    char *buf_tail = buf;
284    char *buf_end = buf + MONGOC_STREAM_TLS_OPENSSL_BUFFER_SIZE;
285    size_t bytes;
286 
287    char *to_write = NULL;
288    size_t to_write_len;
289 
290    BSON_ASSERT (tls);
291    BSON_ASSERT (iov);
292    BSON_ASSERT (iovcnt);
293    ENTRY;
294 
295    tls->timeout_msec = timeout_msec;
296 
297    for (i = 0; i < iovcnt; i++) {
298       iov_pos = 0;
299 
300       while (iov_pos < iov[i].iov_len) {
301          if (buf_head != buf_tail ||
302              ((i + 1 < iovcnt) &&
303               ((buf_end - buf_tail) > (iov[i].iov_len - iov_pos)))) {
304             /* If we have either of:
305              *   - buffered bytes already
306              *   - another iovec to send after this one and we don't have more
307              *     bytes to send than the size of the buffer.
308              *
309              * copy into the buffer */
310 
311             bytes = BSON_MIN (iov[i].iov_len - iov_pos, buf_end - buf_tail);
312 
313             memcpy (buf_tail, (char *) iov[i].iov_base + iov_pos, bytes);
314             buf_tail += bytes;
315             iov_pos += bytes;
316 
317             if (buf_tail == buf_end) {
318                /* If we're full, request send */
319 
320                to_write = buf_head;
321                to_write_len = buf_tail - buf_head;
322 
323                buf_tail = buf_head = buf;
324             }
325          } else {
326             /* Didn't buffer, so just write it through */
327 
328             to_write = (char *) iov[i].iov_base + iov_pos;
329             to_write_len = iov[i].iov_len - iov_pos;
330 
331             iov_pos += to_write_len;
332          }
333 
334          if (to_write) {
335             /* We get here if we buffered some bytes and filled the buffer, or
336              * if we didn't buffer and have to send out of the iovec */
337 
338             child_ret =
339                _mongoc_stream_tls_openssl_write (tls, to_write, to_write_len);
340             if (child_ret != to_write_len) {
341                TRACE ("Got child_ret: %ld while to_write_len is: %ld",
342                       child_ret,
343                       to_write_len);
344             }
345 
346             if (child_ret < 0) {
347                TRACE ("Returning what I had (%ld) as apposed to the error "
348                       "(%ld, errno:%d)",
349                       ret,
350                       child_ret,
351                       errno);
352                RETURN (ret);
353             }
354 
355             ret += child_ret;
356 
357             if (child_ret < to_write_len) {
358                /* we timed out, so send back what we could send */
359 
360                RETURN (ret);
361             }
362 
363             to_write = NULL;
364          }
365       }
366    }
367 
368    if (buf_head != buf_tail) {
369       /* If we have any bytes buffered, send */
370 
371       child_ret =
372          _mongoc_stream_tls_openssl_write (tls, buf_head, buf_tail - buf_head);
373 
374       if (child_ret < 0) {
375          RETURN (child_ret);
376       }
377 
378       ret += child_ret;
379    }
380 
381    if (ret >= 0) {
382       mongoc_counter_streams_egress_add (ret);
383    }
384 
385    RETURN (ret);
386 }
387 
388 
389 /*
390  *--------------------------------------------------------------------------
391  *
392  * _mongoc_stream_tls_openssl_readv --
393  *
394  *       Read from the stream into iov. This function will try to read
395  *       all of the bytes or fail. If the number of bytes is not equal
396  *       to the number requested, a failure or EOF has occurred.
397  *
398  * Returns:
399  *       -1 on failure, 0 on EOF, otherwise the number of bytes read.
400  *
401  * Side effects:
402  *       iov buffers will be written to.
403  *
404  * This function is copied as _mongoc_stream_tls_secure_transport_readv
405  *
406  *--------------------------------------------------------------------------
407  */
408 
409 static ssize_t
_mongoc_stream_tls_openssl_readv(mongoc_stream_t * stream,mongoc_iovec_t * iov,size_t iovcnt,size_t min_bytes,int32_t timeout_msec)410 _mongoc_stream_tls_openssl_readv (mongoc_stream_t *stream,
411                                   mongoc_iovec_t *iov,
412                                   size_t iovcnt,
413                                   size_t min_bytes,
414                                   int32_t timeout_msec)
415 {
416    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
417    mongoc_stream_tls_openssl_t *openssl =
418       (mongoc_stream_tls_openssl_t *) tls->ctx;
419    ssize_t ret = 0;
420    size_t i;
421    int read_ret;
422    size_t iov_pos = 0;
423    int64_t now;
424    int64_t expire = 0;
425    ENTRY;
426 
427    BSON_ASSERT (tls);
428    BSON_ASSERT (iov);
429    BSON_ASSERT (iovcnt);
430 
431    tls->timeout_msec = timeout_msec;
432 
433    if (timeout_msec >= 0) {
434       expire = bson_get_monotonic_time () + (timeout_msec * 1000UL);
435    }
436 
437    for (i = 0; i < iovcnt; i++) {
438       iov_pos = 0;
439 
440       while (iov_pos < iov[i].iov_len) {
441          read_ret = BIO_read (openssl->bio,
442                               (char *) iov[i].iov_base + iov_pos,
443                               (int) (iov[i].iov_len - iov_pos));
444 
445          /* https://www.openssl.org/docs/crypto/BIO_should_retry.html:
446           *
447           * If BIO_should_retry() returns false then the precise "error
448           * condition" depends on the BIO type that caused it and the return
449           * code of the BIO operation. For example if a call to BIO_read() on a
450           * socket BIO returns 0 and BIO_should_retry() is false then the cause
451           * will be that the connection closed.
452           */
453          if (read_ret < 0 ||
454              (read_ret == 0 && !BIO_should_retry (openssl->bio))) {
455             return -1;
456          }
457 
458          if (expire) {
459             now = bson_get_monotonic_time ();
460 
461             if ((expire - now) < 0) {
462                if (read_ret == 0) {
463                   mongoc_counter_streams_timeout_inc ();
464 #ifdef _WIN32
465                   errno = WSAETIMEDOUT;
466 #else
467                   errno = ETIMEDOUT;
468 #endif
469                   RETURN (-1);
470                }
471 
472                tls->timeout_msec = 0;
473             } else {
474                tls->timeout_msec = (expire - now) / 1000L;
475             }
476          }
477 
478          ret += read_ret;
479 
480          if ((size_t) ret >= min_bytes) {
481             mongoc_counter_streams_ingress_add (ret);
482             RETURN (ret);
483          }
484 
485          iov_pos += read_ret;
486       }
487    }
488 
489    if (ret >= 0) {
490       mongoc_counter_streams_ingress_add (ret);
491    }
492 
493    RETURN (ret);
494 }
495 
496 
497 /*
498  *--------------------------------------------------------------------------
499  *
500  * _mongoc_stream_tls_openssl_setsockopt --
501  *
502  *       Perform a setsockopt on the underlying stream.
503  *
504  * Returns:
505  *       -1 on failure, otherwise opt specific value.
506  *
507  * Side effects:
508  *       None.
509  *
510  *--------------------------------------------------------------------------
511  */
512 
513 static int
_mongoc_stream_tls_openssl_setsockopt(mongoc_stream_t * stream,int level,int optname,void * optval,mongoc_socklen_t optlen)514 _mongoc_stream_tls_openssl_setsockopt (mongoc_stream_t *stream,
515                                        int level,
516                                        int optname,
517                                        void *optval,
518                                        mongoc_socklen_t optlen)
519 {
520    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
521 
522    BSON_ASSERT (tls);
523 
524    return mongoc_stream_setsockopt (
525       tls->base_stream, level, optname, optval, optlen);
526 }
527 
528 
529 static mongoc_stream_t *
_mongoc_stream_tls_openssl_get_base_stream(mongoc_stream_t * stream)530 _mongoc_stream_tls_openssl_get_base_stream (mongoc_stream_t *stream)
531 {
532    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
533    return tls->base_stream;
534 }
535 
536 
537 static bool
_mongoc_stream_tls_openssl_check_closed(mongoc_stream_t * stream)538 _mongoc_stream_tls_openssl_check_closed (mongoc_stream_t *stream) /* IN */
539 {
540    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
541    BSON_ASSERT (stream);
542    return mongoc_stream_check_closed (tls->base_stream);
543 }
544 
545 
546 /**
547  * mongoc_stream_tls_openssl_handshake:
548  */
549 static bool
_mongoc_stream_tls_openssl_handshake(mongoc_stream_t * stream,const char * host,int * events,bson_error_t * error)550 _mongoc_stream_tls_openssl_handshake (mongoc_stream_t *stream,
551                                       const char *host,
552                                       int *events,
553                                       bson_error_t *error)
554 {
555    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
556    mongoc_stream_tls_openssl_t *openssl =
557       (mongoc_stream_tls_openssl_t *) tls->ctx;
558    SSL *ssl;
559 
560    BSON_ASSERT (tls);
561    BSON_ASSERT (host);
562    ENTRY;
563 
564    BIO_get_ssl (openssl->bio, &ssl);
565 
566    if (BIO_do_handshake (openssl->bio) == 1) {
567       *events = 0;
568 
569 #ifdef MONGOC_ENABLE_OCSP_OPENSSL
570       /* Validate OCSP */
571       if (openssl->ocsp_opts &&
572           1 != _mongoc_ocsp_tlsext_status (ssl, openssl->ocsp_opts)) {
573          bson_set_error (error,
574                          MONGOC_ERROR_STREAM,
575                          MONGOC_ERROR_STREAM_SOCKET,
576                          "TLS handshake failed: Failed OCSP verification");
577          RETURN (false);
578       }
579 #endif
580 
581       if (_mongoc_openssl_check_peer_hostname (
582              ssl, host, tls->ssl_opts.allow_invalid_hostname)) {
583          RETURN (true);
584       }
585 
586       bson_set_error (error,
587                       MONGOC_ERROR_STREAM,
588                       MONGOC_ERROR_STREAM_SOCKET,
589                       "TLS handshake failed: Failed certificate verification");
590 
591       RETURN (false);
592    }
593 
594    if (BIO_should_retry (openssl->bio)) {
595       *events = BIO_should_read (openssl->bio) ? POLLIN : POLLOUT;
596       RETURN (false);
597    }
598 
599    if (!errno) {
600 #ifdef _WIN32
601       errno = WSAETIMEDOUT;
602 #else
603       errno = ETIMEDOUT;
604 #endif
605    }
606 
607 
608    *events = 0;
609    bson_set_error (error,
610                    MONGOC_ERROR_STREAM,
611                    MONGOC_ERROR_STREAM_SOCKET,
612                    "TLS handshake failed: %s",
613                    ERR_error_string (ERR_get_error (), NULL));
614 
615    RETURN (false);
616 }
617 
618 /* Callback to get the client provided SNI, if any
619  * It is only called in SSL "server mode" (e.g. when using the Mock Server),
620  * and we don't actually use the hostname for anything, just debug print it
621  */
622 static int
_mongoc_stream_tls_openssl_sni(SSL * ssl,int * ad,void * arg)623 _mongoc_stream_tls_openssl_sni (SSL *ssl, int *ad, void *arg)
624 {
625    const char *hostname;
626 
627    if (ssl == NULL) {
628       TRACE ("%s", "No SNI hostname provided");
629       return SSL_TLSEXT_ERR_NOACK;
630    }
631 
632    hostname = SSL_get_servername (ssl, TLSEXT_NAMETYPE_host_name);
633    /* This is intentionally debug since its only used by the mock test server */
634    MONGOC_DEBUG ("Got SNI: '%s'", hostname);
635 
636    return SSL_TLSEXT_ERR_OK;
637 }
638 
639 static bool
_mongoc_stream_tls_openssl_timed_out(mongoc_stream_t * stream)640 _mongoc_stream_tls_openssl_timed_out (mongoc_stream_t *stream)
641 {
642    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
643 
644    ENTRY;
645 
646    RETURN (mongoc_stream_timed_out (tls->base_stream));
647 }
648 
649 static bool
_mongoc_stream_tls_openssl_should_retry(mongoc_stream_t * stream)650 _mongoc_stream_tls_openssl_should_retry (mongoc_stream_t *stream)
651 {
652    mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
653    mongoc_stream_tls_openssl_t *openssl =
654       (mongoc_stream_tls_openssl_t *) tls->ctx;
655 
656    ENTRY;
657 
658    if (BIO_should_retry (openssl->bio)) {
659       RETURN (true);
660    }
661 
662    RETURN (mongoc_stream_should_retry (tls->base_stream));
663 }
664 
665 /*
666  *--------------------------------------------------------------------------
667  *
668  * mongoc_stream_tls_openssl_new --
669  *
670  *       Creates a new mongoc_stream_tls_openssl_t to communicate with a remote
671  *       server using a TLS stream.
672  *
673  *       @base_stream should be a stream that will become owned by the
674  *       resulting tls stream. It will be used for raw I/O.
675  *
676  *       @trust_store_dir should be a path to the SSL cert db to use for
677  *       verifying trust of the remote server.
678  *
679  * Returns:
680  *       NULL on failure, otherwise a mongoc_stream_t.
681  *
682  * Side effects:
683  *       None.
684  *
685  *--------------------------------------------------------------------------
686  */
687 
688 mongoc_stream_t *
mongoc_stream_tls_openssl_new(mongoc_stream_t * base_stream,const char * host,mongoc_ssl_opt_t * opt,int client)689 mongoc_stream_tls_openssl_new (mongoc_stream_t *base_stream,
690                                const char *host,
691                                mongoc_ssl_opt_t *opt,
692                                int client)
693 {
694    mongoc_stream_tls_t *tls;
695    mongoc_stream_tls_openssl_t *openssl;
696    mongoc_openssl_ocsp_opt_t *ocsp_opts = NULL;
697    SSL_CTX *ssl_ctx = NULL;
698    BIO *bio_ssl = NULL;
699    BIO *bio_mongoc_shim = NULL;
700    BIO_METHOD *meth;
701 
702    BSON_ASSERT (base_stream);
703    BSON_ASSERT (opt);
704    ENTRY;
705 
706    ssl_ctx = _mongoc_openssl_ctx_new (opt);
707 
708    if (!ssl_ctx) {
709       RETURN (NULL);
710    }
711 
712 #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
713    if (!opt->allow_invalid_hostname) {
714       struct in_addr addr;
715       struct in6_addr addr6;
716       X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new ();
717 
718       X509_VERIFY_PARAM_set_hostflags (param,
719                                        X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
720       if (inet_pton (AF_INET, host, &addr) ||
721           inet_pton (AF_INET6, host, &addr6)) {
722          X509_VERIFY_PARAM_set1_ip_asc (param, host);
723       } else {
724          X509_VERIFY_PARAM_set1_host (param, host, 0);
725       }
726       SSL_CTX_set1_param (ssl_ctx, param);
727       X509_VERIFY_PARAM_free (param);
728    }
729 #endif
730 
731    if (!client) {
732       /* Only used by the Mock Server.
733        * Set a callback to get the SNI, if provided */
734       SSL_CTX_set_tlsext_servername_callback (ssl_ctx,
735                                               _mongoc_stream_tls_openssl_sni);
736    }
737 
738    if (opt->weak_cert_validation) {
739       SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, NULL);
740    } else {
741       SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_PEER, NULL);
742    }
743 
744    bio_ssl = BIO_new_ssl (ssl_ctx, client);
745    if (!bio_ssl) {
746       SSL_CTX_free (ssl_ctx);
747       RETURN (NULL);
748    }
749    meth = mongoc_stream_tls_openssl_bio_meth_new ();
750    bio_mongoc_shim = BIO_new (meth);
751    if (!bio_mongoc_shim) {
752       BIO_free_all (bio_ssl);
753       BIO_meth_free (meth);
754       SSL_CTX_free (ssl_ctx);
755       RETURN (NULL);
756    }
757 
758 /* Added in OpenSSL 0.9.8f, as a build time option */
759 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
760    if (client) {
761       SSL *ssl;
762       /* Set the SNI hostname we are expecting certificate for */
763       BIO_get_ssl (bio_ssl, &ssl);
764       SSL_set_tlsext_host_name (ssl, host);
765 #endif
766    }
767 
768    BIO_push (bio_ssl, bio_mongoc_shim);
769 
770 #ifdef MONGOC_ENABLE_OCSP_OPENSSL
771    if (client && !opt->weak_cert_validation &&
772        !_mongoc_ssl_opts_disable_certificate_revocation_check (opt)) {
773       SSL *ssl;
774 
775       BIO_get_ssl (bio_ssl, &ssl);
776 
777       /* Set the status_request extension on the SSL object.
778        * Do not use SSL_CTX_set_tlsext_status_type, since that requires OpenSSL
779        * 1.1.0.
780        */
781       if (!SSL_set_tlsext_status_type (ssl, TLSEXT_STATUSTYPE_ocsp)) {
782          MONGOC_ERROR ("cannot enable OCSP status request extension");
783          mongoc_openssl_ocsp_opt_destroy (ocsp_opts);
784          BIO_free_all (bio_ssl);
785          BIO_meth_free (meth);
786          SSL_CTX_free (ssl_ctx);
787          RETURN (NULL);
788       }
789 
790       ocsp_opts = bson_malloc0 (sizeof (mongoc_openssl_ocsp_opt_t));
791       ocsp_opts->allow_invalid_hostname = opt->allow_invalid_hostname;
792       ocsp_opts->weak_cert_validation = opt->weak_cert_validation;
793       ocsp_opts->disable_endpoint_check =
794          _mongoc_ssl_opts_disable_ocsp_endpoint_check (opt);
795       ocsp_opts->host = bson_strdup (host);
796       _mongoc_ssl_opts_copy_to (opt, &ocsp_opts->ssl_opts, true);
797    }
798 #endif /* MONGOC_ENABLE_OCSP_OPENSSL */
799 
800    openssl = (mongoc_stream_tls_openssl_t *) bson_malloc0 (sizeof *openssl);
801    openssl->bio = bio_ssl;
802    openssl->meth = meth;
803    openssl->ctx = ssl_ctx;
804    openssl->ocsp_opts = ocsp_opts;
805 
806    tls = (mongoc_stream_tls_t *) bson_malloc0 (sizeof *tls);
807    tls->parent.type = MONGOC_STREAM_TLS;
808    tls->parent.destroy = _mongoc_stream_tls_openssl_destroy;
809    tls->parent.failed = _mongoc_stream_tls_openssl_failed;
810    tls->parent.close = _mongoc_stream_tls_openssl_close;
811    tls->parent.flush = _mongoc_stream_tls_openssl_flush;
812    tls->parent.writev = _mongoc_stream_tls_openssl_writev;
813    tls->parent.readv = _mongoc_stream_tls_openssl_readv;
814    tls->parent.setsockopt = _mongoc_stream_tls_openssl_setsockopt;
815    tls->parent.get_base_stream = _mongoc_stream_tls_openssl_get_base_stream;
816    tls->parent.check_closed = _mongoc_stream_tls_openssl_check_closed;
817    tls->parent.timed_out = _mongoc_stream_tls_openssl_timed_out;
818    tls->parent.should_retry = _mongoc_stream_tls_openssl_should_retry;
819    memcpy (&tls->ssl_opts, opt, sizeof tls->ssl_opts);
820    tls->handshake = _mongoc_stream_tls_openssl_handshake;
821    tls->ctx = (void *) openssl;
822    tls->timeout_msec = -1;
823    tls->base_stream = base_stream;
824    mongoc_stream_tls_openssl_bio_set_data (bio_mongoc_shim, tls);
825 
826    mongoc_counter_streams_active_inc ();
827 
828    RETURN ((mongoc_stream_t *) tls);
829 }
830 
831 void
mongoc_openssl_ocsp_opt_destroy(void * ocsp_opt)832 mongoc_openssl_ocsp_opt_destroy (void *ocsp_opt)
833 {
834    mongoc_openssl_ocsp_opt_t *casted;
835 
836    if (!ocsp_opt) {
837       return;
838    }
839    casted = (mongoc_openssl_ocsp_opt_t *) ocsp_opt;
840    bson_free (casted->host);
841    _mongoc_ssl_opts_cleanup (&casted->ssl_opts, true);
842    bson_free (ocsp_opt);
843 }
844 
845 #endif /* MONGOC_ENABLE_SSL_OPENSSL */
846