lavu: Add version information for av_version_info()
[ffmpeg.git] / libavformat / tls_openssl.c
1 /*
2  * TLS/SSL Protocol
3  * Copyright (c) 2011 Martin Storsjo
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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;
43     TLSShared tls_shared;
44     SSL_CTX *ctx;
45     SSL *ssl;
46 } TLSContext;
47
48 #if HAVE_THREADS
49 #include <openssl/crypto.h>
50 pthread_mutex_t *openssl_mutexes;
51 static void openssl_lock(int mode, int type, const char *file, int line)
52 {
53     if (mode & CRYPTO_LOCK)
54         pthread_mutex_lock(&openssl_mutexes[type]);
55     else
56         pthread_mutex_unlock(&openssl_mutexes[type]);
57 }
58 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
59 static unsigned long openssl_thread_id(void)
60 {
61     return (intptr_t) pthread_self();
62 }
63 #endif
64 #endif
65
66 void ff_openssl_init(void)
67 {
68     avpriv_lock_avformat();
69     if (!openssl_init) {
70         SSL_library_init();
71         SSL_load_error_strings();
72 #if HAVE_THREADS
73         if (!CRYPTO_get_locking_callback()) {
74             int i;
75             openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
76             for (i = 0; i < CRYPTO_num_locks(); i++)
77                 pthread_mutex_init(&openssl_mutexes[i], NULL);
78             CRYPTO_set_locking_callback(openssl_lock);
79 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
80             CRYPTO_set_id_callback(openssl_thread_id);
81 #endif
82         }
83 #endif
84     }
85     openssl_init++;
86     avpriv_unlock_avformat();
87 }
88
89 void ff_openssl_deinit(void)
90 {
91     avpriv_lock_avformat();
92     openssl_init--;
93     if (!openssl_init) {
94 #if HAVE_THREADS
95         if (CRYPTO_get_locking_callback() == openssl_lock) {
96             int i;
97             CRYPTO_set_locking_callback(NULL);
98             for (i = 0; i < CRYPTO_num_locks(); i++)
99                 pthread_mutex_destroy(&openssl_mutexes[i]);
100             av_free(openssl_mutexes);
101         }
102 #endif
103     }
104     avpriv_unlock_avformat();
105 }
106
107 static int print_tls_error(URLContext *h, int ret)
108 {
109     av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
110     return AVERROR(EIO);
111 }
112
113 static int tls_close(URLContext *h)
114 {
115     TLSContext *c = h->priv_data;
116     if (c->ssl) {
117         SSL_shutdown(c->ssl);
118         SSL_free(c->ssl);
119     }
120     if (c->ctx)
121         SSL_CTX_free(c->ctx);
122     if (c->tls_shared.tcp)
123         ffurl_close(c->tls_shared.tcp);
124     ff_openssl_deinit();
125     return 0;
126 }
127
128 static int url_bio_create(BIO *b)
129 {
130     b->init = 1;
131     b->ptr = NULL;
132     b->flags = 0;
133     return 1;
134 }
135
136 static int url_bio_destroy(BIO *b)
137 {
138     return 1;
139 }
140
141 static int url_bio_bread(BIO *b, char *buf, int len)
142 {
143     URLContext *h = b->ptr;
144     int ret = ffurl_read(h, buf, len);
145     if (ret >= 0)
146         return ret;
147     BIO_clear_retry_flags(b);
148     if (ret == AVERROR_EXIT)
149         return 0;
150     return -1;
151 }
152
153 static int url_bio_bwrite(BIO *b, const char *buf, int len)
154 {
155     URLContext *h = b->ptr;
156     int ret = ffurl_write(h, buf, len);
157     if (ret >= 0)
158         return ret;
159     BIO_clear_retry_flags(b);
160     if (ret == AVERROR_EXIT)
161         return 0;
162     return -1;
163 }
164
165 static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
166 {
167     if (cmd == BIO_CTRL_FLUSH) {
168         BIO_clear_retry_flags(b);
169         return 1;
170     }
171     return 0;
172 }
173
174 static int url_bio_bputs(BIO *b, const char *str)
175 {
176     return url_bio_bwrite(b, str, strlen(str));
177 }
178
179 static BIO_METHOD url_bio_method = {
180     .type = BIO_TYPE_SOURCE_SINK,
181     .name = "urlprotocol bio",
182     .bwrite = url_bio_bwrite,
183     .bread = url_bio_bread,
184     .bputs = url_bio_bputs,
185     .bgets = NULL,
186     .ctrl = url_bio_ctrl,
187     .create = url_bio_create,
188     .destroy = url_bio_destroy,
189 };
190
191 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
192 {
193     TLSContext *p = h->priv_data;
194     TLSShared *c = &p->tls_shared;
195     BIO *bio;
196     int ret;
197
198     ff_openssl_init();
199
200     if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
201         goto fail;
202
203     p->ctx = SSL_CTX_new(c->listen ? TLSv1_server_method() : TLSv1_client_method());
204     if (!p->ctx) {
205         av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
206         ret = AVERROR(EIO);
207         goto fail;
208     }
209     if (c->ca_file)
210         SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL);
211     if (c->cert_file && !SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file)) {
212         av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n",
213                c->cert_file, ERR_error_string(ERR_get_error(), NULL));
214         ret = AVERROR(EIO);
215         goto fail;
216     }
217     if (c->key_file && !SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM)) {
218         av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n",
219                c->key_file, ERR_error_string(ERR_get_error(), NULL));
220         ret = AVERROR(EIO);
221         goto fail;
222     }
223     // Note, this doesn't check that the peer certificate actually matches
224     // the requested hostname.
225     if (c->verify)
226         SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER, NULL);
227     p->ssl = SSL_new(p->ctx);
228     if (!p->ssl) {
229         av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
230         ret = AVERROR(EIO);
231         goto fail;
232     }
233     bio = BIO_new(&url_bio_method);
234     bio->ptr = c->tcp;
235     SSL_set_bio(p->ssl, bio, bio);
236     if (!c->listen && !c->numerichost)
237         SSL_set_tlsext_host_name(p->ssl, c->host);
238     ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl);
239     if (ret == 0) {
240         av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
241         ret = AVERROR(EIO);
242         goto fail;
243     } else if (ret < 0) {
244         ret = print_tls_error(h, ret);
245         goto fail;
246     }
247
248     return 0;
249 fail:
250     tls_close(h);
251     return ret;
252 }
253
254 static int tls_read(URLContext *h, uint8_t *buf, int size)
255 {
256     TLSContext *c = h->priv_data;
257     int ret = SSL_read(c->ssl, buf, size);
258     if (ret > 0)
259         return ret;
260     if (ret == 0)
261         return AVERROR_EOF;
262     return print_tls_error(h, ret);
263 }
264
265 static int tls_write(URLContext *h, const uint8_t *buf, int size)
266 {
267     TLSContext *c = h->priv_data;
268     int ret = SSL_write(c->ssl, buf, size);
269     if (ret > 0)
270         return ret;
271     if (ret == 0)
272         return AVERROR_EOF;
273     return print_tls_error(h, ret);
274 }
275
276 static const AVOption options[] = {
277     TLS_COMMON_OPTIONS(TLSContext, tls_shared),
278     { NULL }
279 };
280
281 static const AVClass tls_class = {
282     .class_name = "tls",
283     .item_name  = av_default_item_name,
284     .option     = options,
285     .version    = LIBAVUTIL_VERSION_INT,
286 };
287
288 URLProtocol ff_tls_openssl_protocol = {
289     .name           = "tls",
290     .url_open2      = tls_open,
291     .url_read       = tls_read,
292     .url_write      = tls_write,
293     .url_close      = tls_close,
294     .priv_data_size = sizeof(TLSContext),
295     .flags          = URL_PROTOCOL_FLAG_NETWORK,
296     .priv_data_class = &tls_class,
297 };