summaryrefslogtreecommitdiff
path: root/libavformat/tls_openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/tls_openssl.c')
-rw-r--r--libavformat/tls_openssl.c165
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,