FFmpeg
tls_openssl.c
Go to the documentation of this file.
1 /*
2  * TLS/SSL Protocol
3  * Copyright (c) 2011 Martin Storsjo
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "avformat.h"
23 #include "internal.h"
24 #include "network.h"
25 #include "os_support.h"
26 #include "url.h"
27 #include "tls.h"
28 #include "libavcodec/internal.h"
29 #include "libavutil/avstring.h"
30 #include "libavutil/avutil.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/parseutils.h"
33 #include "libavutil/thread.h"
34 
35 #include <openssl/bio.h>
36 #include <openssl/ssl.h>
37 #include <openssl/err.h>
38 
39 static int openssl_init;
40 
41 typedef struct TLSContext {
42  const AVClass *class;
44  SSL_CTX *ctx;
45  SSL *ssl;
46 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
47  BIO_METHOD* url_bio_method;
48 #endif
49 } TLSContext;
50 
51 #if HAVE_THREADS
52 #include <openssl/crypto.h>
53 pthread_mutex_t *openssl_mutexes;
54 static void openssl_lock(int mode, int type, const char *file, int line)
55 {
56  if (mode & CRYPTO_LOCK)
57  pthread_mutex_lock(&openssl_mutexes[type]);
58  else
59  pthread_mutex_unlock(&openssl_mutexes[type]);
60 }
61 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
62 static unsigned long openssl_thread_id(void)
63 {
64  return (intptr_t) pthread_self();
65 }
66 #endif
67 #endif
68 
69 int ff_openssl_init(void)
70 {
72  if (!openssl_init) {
73  SSL_library_init();
74  SSL_load_error_strings();
75 #if HAVE_THREADS
76  if (!CRYPTO_get_locking_callback()) {
77  int i;
78  openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks());
79  if (!openssl_mutexes) {
81  return AVERROR(ENOMEM);
82  }
83 
84  for (i = 0; i < CRYPTO_num_locks(); i++)
85  pthread_mutex_init(&openssl_mutexes[i], NULL);
86  CRYPTO_set_locking_callback(openssl_lock);
87 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
88  CRYPTO_set_id_callback(openssl_thread_id);
89 #endif
90  }
91 #endif
92  }
93  openssl_init++;
95 
96  return 0;
97 }
98 
100 {
102  openssl_init--;
103  if (!openssl_init) {
104 #if HAVE_THREADS
105  if (CRYPTO_get_locking_callback() == openssl_lock) {
106  int i;
107  CRYPTO_set_locking_callback(NULL);
108  for (i = 0; i < CRYPTO_num_locks(); i++)
109  pthread_mutex_destroy(&openssl_mutexes[i]);
110  av_free(openssl_mutexes);
111  }
112 #endif
113  }
115 }
116 
117 static int print_tls_error(URLContext *h, int ret)
118 {
119  TLSContext *c = h->priv_data;
120  if (h->flags & AVIO_FLAG_NONBLOCK) {
121  int err = SSL_get_error(c->ssl, ret);
122  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
123  return AVERROR(EAGAIN);
124  }
125  av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
126  return AVERROR(EIO);
127 }
128 
129 static int tls_close(URLContext *h)
130 {
131  TLSContext *c = h->priv_data;
132  if (c->ssl) {
133  SSL_shutdown(c->ssl);
134  SSL_free(c->ssl);
135  }
136  if (c->ctx)
137  SSL_CTX_free(c->ctx);
138  if (c->tls_shared.tcp)
140 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
141  if (c->url_bio_method)
142  BIO_meth_free(c->url_bio_method);
143 #endif
145  return 0;
146 }
147 
148 static int url_bio_create(BIO *b)
149 {
150 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
151  BIO_set_init(b, 1);
152  BIO_set_data(b, NULL);
153  BIO_set_flags(b, 0);
154 #else
155  b->init = 1;
156  b->ptr = NULL;
157  b->flags = 0;
158 #endif
159  return 1;
160 }
161 
162 static int url_bio_destroy(BIO *b)
163 {
164  return 1;
165 }
166 
167 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
168 #define GET_BIO_DATA(x) BIO_get_data(x)
169 #else
170 #define GET_BIO_DATA(x) (x)->ptr
171 #endif
172 
173 static int url_bio_bread(BIO *b, char *buf, int len)
174 {
175  URLContext *h = GET_BIO_DATA(b);
176  int ret = ffurl_read(h, buf, len);
177  if (ret >= 0)
178  return ret;
179  BIO_clear_retry_flags(b);
180  if (ret == AVERROR(EAGAIN))
181  BIO_set_retry_read(b);
182  if (ret == AVERROR_EXIT)
183  return 0;
184  return -1;
185 }
186 
187 static int url_bio_bwrite(BIO *b, const char *buf, int len)
188 {
189  URLContext *h = GET_BIO_DATA(b);
190  int ret = ffurl_write(h, buf, len);
191  if (ret >= 0)
192  return ret;
193  BIO_clear_retry_flags(b);
194  if (ret == AVERROR(EAGAIN))
195  BIO_set_retry_write(b);
196  if (ret == AVERROR_EXIT)
197  return 0;
198  return -1;
199 }
200 
201 static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
202 {
203  if (cmd == BIO_CTRL_FLUSH) {
204  BIO_clear_retry_flags(b);
205  return 1;
206  }
207  return 0;
208 }
209 
210 static int url_bio_bputs(BIO *b, const char *str)
211 {
212  return url_bio_bwrite(b, str, strlen(str));
213 }
214 
215 #if OPENSSL_VERSION_NUMBER < 0x1010000fL
216 static BIO_METHOD url_bio_method = {
217  .type = BIO_TYPE_SOURCE_SINK,
218  .name = "urlprotocol bio",
219  .bwrite = url_bio_bwrite,
220  .bread = url_bio_bread,
221  .bputs = url_bio_bputs,
222  .bgets = NULL,
223  .ctrl = url_bio_ctrl,
224  .create = url_bio_create,
225  .destroy = url_bio_destroy,
226 };
227 #endif
228 
229 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
230 {
231  TLSContext *p = h->priv_data;
232  TLSShared *c = &p->tls_shared;
233  BIO *bio;
234  int ret;
235 
236  if ((ret = ff_openssl_init()) < 0)
237  return ret;
238 
239  if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
240  goto fail;
241 
242  // We want to support all versions of TLS >= 1.0, but not the deprecated
243  // and insecure SSLv2 and SSLv3. Despite the name, SSLv23_*_method()
244  // enables support for all versions of SSL and TLS, and we then disable
245  // support for the old protocols immediately after creating the context.
246  p->ctx = SSL_CTX_new(c->listen ? SSLv23_server_method() : SSLv23_client_method());
247  if (!p->ctx) {
248  av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
249  ret = AVERROR(EIO);
250  goto fail;
251  }
252  SSL_CTX_set_options(p->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
253  if (c->ca_file) {
254  if (!SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL))
255  av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", ERR_error_string(ERR_get_error(), NULL));
256  }
257  if (c->cert_file && !SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file)) {
258  av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n",
259  c->cert_file, ERR_error_string(ERR_get_error(), NULL));
260  ret = AVERROR(EIO);
261  goto fail;
262  }
263  if (c->key_file && !SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM)) {
264  av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n",
265  c->key_file, ERR_error_string(ERR_get_error(), NULL));
266  ret = AVERROR(EIO);
267  goto fail;
268  }
269  // Note, this doesn't check that the peer certificate actually matches
270  // the requested hostname.
271  if (c->verify)
272  SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
273  p->ssl = SSL_new(p->ctx);
274  if (!p->ssl) {
275  av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
276  ret = AVERROR(EIO);
277  goto fail;
278  }
279 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
280  p->url_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "urlprotocol bio");
281  BIO_meth_set_write(p->url_bio_method, url_bio_bwrite);
282  BIO_meth_set_read(p->url_bio_method, url_bio_bread);
283  BIO_meth_set_puts(p->url_bio_method, url_bio_bputs);
284  BIO_meth_set_ctrl(p->url_bio_method, url_bio_ctrl);
285  BIO_meth_set_create(p->url_bio_method, url_bio_create);
286  BIO_meth_set_destroy(p->url_bio_method, url_bio_destroy);
287  bio = BIO_new(p->url_bio_method);
288  BIO_set_data(bio, c->tcp);
289 #else
290  bio = BIO_new(&url_bio_method);
291  bio->ptr = c->tcp;
292 #endif
293  SSL_set_bio(p->ssl, bio, bio);
294  if (!c->listen && !c->numerichost)
295  SSL_set_tlsext_host_name(p->ssl, c->host);
296  ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl);
297  if (ret == 0) {
298  av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
299  ret = AVERROR(EIO);
300  goto fail;
301  } else if (ret < 0) {
302  ret = print_tls_error(h, ret);
303  goto fail;
304  }
305 
306  return 0;
307 fail:
308  tls_close(h);
309  return ret;
310 }
311 
312 static int tls_read(URLContext *h, uint8_t *buf, int size)
313 {
314  TLSContext *c = h->priv_data;
315  int ret;
316  // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
319  ret = SSL_read(c->ssl, buf, size);
320  if (ret > 0)
321  return ret;
322  if (ret == 0)
323  return AVERROR_EOF;
324  return print_tls_error(h, ret);
325 }
326 
327 static int tls_write(URLContext *h, const uint8_t *buf, int size)
328 {
329  TLSContext *c = h->priv_data;
330  int ret;
331  // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
334  ret = SSL_write(c->ssl, buf, size);
335  if (ret > 0)
336  return ret;
337  if (ret == 0)
338  return AVERROR_EOF;
339  return print_tls_error(h, ret);
340 }
341 
343 {
344  TLSContext *c = h->priv_data;
346 }
347 
348 static const AVOption options[] = {
350  { NULL }
351 };
352 
353 static const AVClass tls_class = {
354  .class_name = "tls",
355  .item_name = av_default_item_name,
356  .option = options,
357  .version = LIBAVUTIL_VERSION_INT,
358 };
359 
361  .name = "tls",
362  .url_open2 = tls_open,
363  .url_read = tls_read,
364  .url_write = tls_write,
365  .url_close = tls_close,
366  .url_get_file_handle = tls_get_file_handle,
367  .priv_data_size = sizeof(TLSContext),
369  .priv_data_class = &tls_class,
370 };
#define NULL
Definition: coverity.c:32
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:108
static int openssl_init
Definition: tls_openssl.c:39
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
#define pthread_mutex_lock(a)
Definition: ffprobe.c:61
AVOption.
Definition: opt.h:246
int verify
Definition: tls.h:31
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:421
static int url_bio_bwrite(BIO *b, const char *buf, int len)
Definition: tls_openssl.c:187
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
Convenience header that includes libavutil&#39;s core.
GLint GLenum type
Definition: opengl_enc.c:104
int flags
Definition: url.h:43
int listen
Definition: tls.h:34
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
static int url_bio_bread(BIO *b, char *buf, int len)
Definition: tls_openssl.c:173
uint8_t
AVOptions.
miscellaneous OS support macros and functions.
static int url_bio_bputs(BIO *b, const char *str)
Definition: tls_openssl.c:210
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
#define GET_BIO_DATA(x)
Definition: tls_openssl.c:170
Definition: tls.h:29
#define AVERROR_EOF
End of file.
Definition: error.h:55
ptrdiff_t size
Definition: opengl_enc.c:100
static int tls_get_file_handle(URLContext *h)
Definition: tls_openssl.c:342
#define av_log(a,...)
SSL * ssl
Definition: tls_openssl.c:45
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
Definition: graph2dot.c:48
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_openssl.c:229
#define fail()
Definition: checkasm.h:120
char * host
Definition: tls.h:36
static const AVOption options[]
Definition: tls_openssl.c:348
void ff_openssl_deinit(void)
Definition: tls_openssl.c:99
#define b
Definition: input.c:41
static const AVClass tls_class
Definition: tls_openssl.c:353
int ff_unlock_avformat(void)
Definition: utils.c:88
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:45
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:100
char * cert_file
Definition: tls.h:32
static int tls_write(URLContext *h, const uint8_t *buf, int size)
Definition: tls_openssl.c:327
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:65
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:626
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
char * ca_file
Definition: tls.h:30
static int url_bio_destroy(BIO *b)
Definition: tls_openssl.c:162
static int print_tls_error(URLContext *h, int ret)
Definition: tls_openssl.c:117
SSL_CTX * ctx
Definition: tls_openssl.c:44
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:693
int ff_openssl_init(void)
Definition: tls_openssl.c:69
TLSShared tls_shared
Definition: tls_gnutls.c:50
void * buf
Definition: avisynth_c.h:766
Definition: url.h:38
static int tls_read(URLContext *h, uint8_t *buf, int size)
Definition: tls_openssl.c:312
Describe the class of an AVClass context structure.
Definition: log.h:67
void * priv_data
Definition: url.h:41
static int tls_close(URLContext *h)
Definition: tls_openssl.c:129
const URLProtocol ff_tls_protocol
Definition: tls_openssl.c:360
misc parsing utilities
const char * name
Definition: url.h:55
#define flags(name, subs,...)
Definition: cbs_av1.c:561
int ffurl_close(URLContext *h)
Definition: avio.c:467
Main libavformat public API header.
common internal api header.
_fmutex pthread_mutex_t
Definition: os2threads.h:49
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
Definition: tls.c:56
struct tls * ctx
Definition: tls_libtls.c:37
URLContext * tcp
Definition: tls.h:41
static BIO_METHOD url_bio_method
Definition: tls_openssl.c:216
int numerichost
Definition: tls.h:39
static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
Definition: tls_openssl.c:201
#define av_free(p)
int len
int ff_lock_avformat(void)
Definition: utils.c:83
unbuffered private I/O API
#define av_malloc_array(a, b)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
Definition: avio.c:407
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83
char * key_file
Definition: tls.h:33
static int url_bio_create(BIO *b)
Definition: tls_openssl.c:148