diff options
Diffstat (limited to 'libavformat/tls_openssl.c')
-rw-r--r-- | libavformat/tls_openssl.c | 165 |
1 files changed, 91 insertions, 74 deletions
diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index 0abccf00a9..38af8a21c0 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -2,20 +2,20 @@ * TLS/SSL Protocol * Copyright (c) 2011 Martin Storsjo * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -66,72 +66,6 @@ static unsigned long openssl_thread_id(void) #endif #endif -void ff_openssl_init(void) -{ - avpriv_lock_avformat(); - if (!openssl_init) { - SSL_library_init(); - SSL_load_error_strings(); -#if HAVE_THREADS - if (!CRYPTO_get_locking_callback()) { - int i; - openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_init(&openssl_mutexes[i], NULL); - CRYPTO_set_locking_callback(openssl_lock); -#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 - CRYPTO_set_id_callback(openssl_thread_id); -#endif - } -#endif - } - openssl_init++; - avpriv_unlock_avformat(); -} - -void ff_openssl_deinit(void) -{ - avpriv_lock_avformat(); - openssl_init--; - if (!openssl_init) { -#if HAVE_THREADS - if (CRYPTO_get_locking_callback() == openssl_lock) { - int i; - CRYPTO_set_locking_callback(NULL); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_destroy(&openssl_mutexes[i]); - av_free(openssl_mutexes); - } -#endif - } - avpriv_unlock_avformat(); -} - -static int print_tls_error(URLContext *h, int ret) -{ - av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); - return AVERROR(EIO); -} - -static int tls_close(URLContext *h) -{ - TLSContext *c = h->priv_data; - if (c->ssl) { - SSL_shutdown(c->ssl); - SSL_free(c->ssl); - } - if (c->ctx) - SSL_CTX_free(c->ctx); - if (c->tls_shared.tcp) - ffurl_close(c->tls_shared.tcp); -#if OPENSSL_VERSION_NUMBER >= 0x1010000fL - if (c->url_bio_method) - BIO_meth_free(c->url_bio_method); -#endif - ff_openssl_deinit(); - return 0; -} - static int url_bio_create(BIO *b) { #if OPENSSL_VERSION_NUMBER >= 0x1010000fL @@ -209,6 +143,79 @@ static BIO_METHOD url_bio_method = { }; #endif +int ff_openssl_init(void) +{ + avpriv_lock_avformat(); + if (!openssl_init) { + SSL_library_init(); + SSL_load_error_strings(); +#if HAVE_THREADS + if (!CRYPTO_get_locking_callback()) { + int i; + openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks()); + if (!openssl_mutexes) { + avpriv_unlock_avformat(); + return AVERROR(ENOMEM); + } + + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_init(&openssl_mutexes[i], NULL); + CRYPTO_set_locking_callback(openssl_lock); +#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 + CRYPTO_set_id_callback(openssl_thread_id); +#endif + } +#endif + } + openssl_init++; + avpriv_unlock_avformat(); + + return 0; +} + +void ff_openssl_deinit(void) +{ + avpriv_lock_avformat(); + openssl_init--; + if (!openssl_init) { +#if HAVE_THREADS + if (CRYPTO_get_locking_callback() == openssl_lock) { + int i; + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_destroy(&openssl_mutexes[i]); + av_free(openssl_mutexes); + } +#endif + } + avpriv_unlock_avformat(); +} + +static int print_tls_error(URLContext *h, int ret) +{ + av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); + return AVERROR(EIO); +} + +static int tls_close(URLContext *h) +{ + TLSContext *c = h->priv_data; + if (c->ssl) { + SSL_shutdown(c->ssl); + SSL_free(c->ssl); + } + if (c->ctx) + SSL_CTX_free(c->ctx); + if (c->tls_shared.tcp) + ffurl_close(c->tls_shared.tcp); +#if OPENSSL_VERSION_NUMBER >= 0x1010000fL + if (c->url_bio_method) + BIO_meth_free(c->url_bio_method); +#endif + ff_openssl_deinit(); + return 0; +} + static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *p = h->priv_data; @@ -216,7 +223,8 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op BIO *bio; int ret; - ff_openssl_init(); + if ((ret = ff_openssl_init()) < 0) + return ret; if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) goto fail; @@ -232,8 +240,10 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op goto fail; } SSL_CTX_set_options(p->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - if (c->ca_file) - SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL); + if (c->ca_file) { + if (!SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL)) + av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", ERR_error_string(ERR_get_error(), NULL)); + } if (c->cert_file && !SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file)) { av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n", c->cert_file, ERR_error_string(ERR_get_error(), NULL)); @@ -249,7 +259,7 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op // Note, this doesn't check that the peer certificate actually matches // the requested hostname. if (c->verify) - SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER, NULL); + SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); p->ssl = SSL_new(p->ctx); if (!p->ssl) { av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); @@ -311,6 +321,12 @@ static int tls_write(URLContext *h, const uint8_t *buf, int size) return print_tls_error(h, ret); } +static int tls_get_file_handle(URLContext *h) +{ + TLSContext *c = h->priv_data; + return ffurl_get_file_handle(c->tls_shared.tcp); +} + static const AVOption options[] = { TLS_COMMON_OPTIONS(TLSContext, tls_shared), { NULL } @@ -329,6 +345,7 @@ const URLProtocol ff_tls_openssl_protocol = { .url_read = tls_read, .url_write = tls_write, .url_close = tls_close, + .url_get_file_handle = tls_get_file_handle, .priv_data_size = sizeof(TLSContext), .flags = URL_PROTOCOL_FLAG_NETWORK, .priv_data_class = &tls_class, |