avcodec/x86/h264_idct: Fix ff_h264_luma_dc_dequant_idct_sse2 checkasm failures
[ffmpeg.git] / libavformat / tls_libtls.c
1 /*
2 * TLS/SSL Protocol
3 * Copyright (c) 2011 Martin Storsjo
4 * Copyright (c) 2017 sfan5 <sfan5@live.de>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "avformat.h"
24 #include "internal.h"
25 #include "network.h"
26 #include "url.h"
27 #include "tls.h"
28 #include "libavcodec/internal.h"
29 #include "libavutil/avutil.h"
30 #include "libavutil/opt.h"
31
32 #include <tls.h>
33
34 typedef struct TLSContext {
35 TLSShared tls_shared;
36 struct tls *ctx;
37 } TLSContext;
38
39 static int ff_tls_close(URLContext *h)
40 {
41 TLSContext *p = h->priv_data;
42 if (p->ctx) {
43 tls_close(p->ctx);
44 tls_free(p->ctx);
45 }
46 ffurl_closep(&p->tls_shared.tcp);
47 return 0;
48 }
49
50 static ssize_t tls_read_callback(struct tls *ctx, void *buf, size_t buflen, void *cb_arg)
51 {
52 URLContext *h = (URLContext*) cb_arg;
53 int ret = ffurl_read(h, buf, buflen);
54 if (ret == AVERROR(EAGAIN))
55 return TLS_WANT_POLLIN;
56 else if (ret == AVERROR_EXIT)
57 return 0;
58 return ret >= 0 ? ret : -1;
59 }
60
61 static ssize_t tls_write_callback(struct tls *ctx, const void *buf, size_t buflen, void *cb_arg)
62 {
63 URLContext *h = (URLContext*) cb_arg;
64 int ret = ffurl_write(h, buf, buflen);
65 if (ret == AVERROR(EAGAIN))
66 return TLS_WANT_POLLOUT;
67 else if (ret == AVERROR_EXIT)
68 return 0;
69 return ret >= 0 ? ret : -1;
70 }
71
72 static int ff_tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
73 {
74 TLSContext *p = h->priv_data;
75 TLSShared *c = &p->tls_shared;
76 struct tls_config *cfg = NULL;
77 int ret;
78
79 if (tls_init() == -1) {
80 ret = AVERROR(EIO);
81 goto fail;
82 }
83
84 if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
85 goto fail;
86
87 p->ctx = !c->listen ? tls_client() : tls_server();
88 if (!p->ctx) {
89 ret = AVERROR(EIO);
90 goto fail;
91 }
92
93 cfg = tls_config_new();
94 if (!p->ctx) {
95 ret = AVERROR(EIO);
96 goto fail;
97 }
98 if (tls_config_set_protocols(cfg, TLS_PROTOCOLS_ALL) == -1)
99 goto err_config;
100 // While TLSv1.0 and TLSv1.1 are already enabled by the above,
101 // we need to be less strict with ciphers so it works in practice.
102 if (tls_config_set_ciphers(cfg, "compat") == -1)
103 goto err_config;
104 if (c->ca_file && tls_config_set_ca_file(cfg, c->ca_file) == -1)
105 goto err_config;
106 if (c->cert_file && tls_config_set_cert_file(cfg, c->cert_file) == -1)
107 goto err_config;
108 if (c->key_file && tls_config_set_key_file(cfg, c->key_file) == -1)
109 goto err_config;
110 if (!c->verify) {
111 tls_config_insecure_noverifycert(cfg);
112 tls_config_insecure_noverifyname(cfg);
113 tls_config_insecure_noverifytime(cfg);
114 }
115 if (tls_configure(p->ctx, cfg) == -1)
116 goto err_ctx;
117
118 if (!c->listen) {
119 ret = tls_connect_cbs(p->ctx, tls_read_callback, tls_write_callback,
120 c->tcp, c->host);
121 } else {
122 struct tls *ctx_new;
123 ret = tls_accept_cbs(p->ctx, &ctx_new, tls_read_callback,
124 tls_write_callback, c->tcp);
125 if (ret == 0) {
126 // free "server" context and replace by "connection" context
127 tls_free(p->ctx);
128 p->ctx = ctx_new;
129 }
130 }
131 if (ret == -1)
132 goto err_ctx;
133
134 tls_config_free(cfg);
135 return 0;
136 err_config:
137 av_log(h, AV_LOG_ERROR, "%s\n", tls_config_error(cfg));
138 ret = AVERROR(EIO);
139 goto fail;
140 err_ctx:
141 av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx));
142 ret = AVERROR(EIO);
143 /* fallthrough */
144 fail:
145 if (cfg)
146 tls_config_free(cfg);
147 ff_tls_close(h);
148 return ret;
149 }
150
151 static int ff_tls_read(URLContext *h, uint8_t *buf, int size)
152 {
153 TLSContext *p = h->priv_data;
154 ssize_t ret;
155 ret = tls_read(p->ctx, buf, size);
156 if (ret > 0)
157 return ret;
158 else if (ret == 0)
159 return AVERROR_EOF;
160 else if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT)
161 return AVERROR(EAGAIN);
162 av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx));
163 return AVERROR(EIO);
164 }
165
166 static int ff_tls_write(URLContext *h, const uint8_t *buf, int size)
167 {
168 TLSContext *p = h->priv_data;
169 ssize_t ret;
170 ret = tls_write(p->ctx, buf, size);
171 if (ret > 0)
172 return ret;
173 else if (ret == 0)
174 return AVERROR_EOF;
175 else if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT)
176 return AVERROR(EAGAIN);
177 av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx));
178 return AVERROR(EIO);
179 }
180
181 static int tls_get_file_handle(URLContext *h)
182 {
183 TLSContext *c = h->priv_data;
184 return ffurl_get_file_handle(c->tls_shared.tcp);
185 }
186
187 static int tls_get_short_seek(URLContext *h)
188 {
189 TLSContext *s = h->priv_data;
190 return ffurl_get_short_seek(s->tls_shared.tcp);
191 }
192
193 static const AVOption options[] = {
194 TLS_COMMON_OPTIONS(TLSContext, tls_shared),
195 { NULL }
196 };
197
198 static const AVClass tls_class = {
199 .class_name = "tls",
200 .item_name = av_default_item_name,
201 .option = options,
202 .version = LIBAVUTIL_VERSION_INT,
203 };
204
205 const URLProtocol ff_tls_protocol = {
206 .name = "tls",
207 .url_open2 = ff_tls_open,
208 .url_read = ff_tls_read,
209 .url_write = ff_tls_write,
210 .url_close = ff_tls_close,
211 .url_get_file_handle = tls_get_file_handle,
212 .url_get_short_seek = tls_get_short_seek,
213 .priv_data_size = sizeof(TLSContext),
214 .flags = URL_PROTOCOL_FLAG_NETWORK,
215 .priv_data_class = &tls_class,
216 };