Browse code

avformat: Add a protocol blacklisting API

Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>

Derek Buitenhuis authored on 2016/03/04 02:14:26
Showing 42 changed files
... ...
@@ -10,6 +10,7 @@ version <next>:
10 10
 - datascope filter
11 11
 - bench and abench filters
12 12
 - ciescope filter
13
+- protocol blacklisting API
13 14
 
14 15
 
15 16
 version 3.0:
... ...
@@ -15,6 +15,9 @@ libavutil:     2015-08-28
15 15
 
16 16
 API changes, most recent first:
17 17
 
18
+2016-XX-XX - xxxxxxx - lavf 57.28.100
19
+  Add protocol blacklisting API
20
+
18 21
 2016-02-28 - xxxxxxx - lavc 57.27.101
19 22
   Validate AVFrame returned by get_buffer2 to have required
20 23
   planes not NULL and unused planes set to NULL as crashes
... ...
@@ -251,7 +251,7 @@ static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **
251 251
 
252 252
     /* wrap interrupt callback */
253 253
     c->interrupt_callback = h->interrupt_callback;
254
-    ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist);
254
+    ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist);
255 255
     if (ret != 0) {
256 256
         av_log(h, AV_LOG_ERROR, "ffurl_open failed : %s, %s\n", av_err2str(ret), arg);
257 257
         goto url_fail;
... ...
@@ -1832,11 +1832,11 @@ typedef struct AVFormatContext {
1832 1832
 #endif
1833 1833
 
1834 1834
     /**
1835
-     * ',' separated list of allowed protocols.
1835
+     * ',' separated list of disallowed protocols.
1836 1836
      * - encoding: unused
1837 1837
      * - decoding: set by user through AVOptions (NO direct access)
1838 1838
      */
1839
-    char *protocol_whitelist;
1839
+    char *protocol_blacklist;
1840 1840
 
1841 1841
     /*
1842 1842
      * A callback for opening new IO streams.
... ...
@@ -1865,6 +1865,13 @@ typedef struct AVFormatContext {
1865 1865
      * A callback for closing the streams opened with AVFormatContext.io_open().
1866 1866
      */
1867 1867
     void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
1868
+
1869
+    /**
1870
+     * ',' separated list of disallowed protocols.
1871
+     * - encoding: unused
1872
+     * - decoding: set by user through AVOptions (NO direct access)
1873
+     */
1874
+    char *protocol_blacklist;
1868 1875
 } AVFormatContext;
1869 1876
 
1870 1877
 int av_format_get_probe_score(const AVFormatContext *s);
... ...
@@ -1089,7 +1089,7 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
1089 1089
 
1090 1090
         ast->sub_ctx->pb = pb;
1091 1091
 
1092
-        if (ff_copy_whitelists(ast->sub_ctx, s) < 0)
1092
+        if (ff_copy_whiteblacklists(ast->sub_ctx, s) < 0)
1093 1093
             goto error;
1094 1094
 
1095 1095
         if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) {
... ...
@@ -55,6 +55,7 @@ static void *urlcontext_child_next(void *obj, void *prev)
55 55
 #define D AV_OPT_FLAG_DECODING_PARAM
56 56
 static const AVOption options[] = {
57 57
     {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
58
+    {"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
58 59
     { NULL }
59 60
 };
60 61
 
... ...
@@ -173,12 +174,19 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
173 173
     // Check that URLContext was initialized correctly and lists are matching if set
174 174
     av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
175 175
                (uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value)));
176
+    av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
177
+               (uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value)));
176 178
 
177 179
     if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) {
178 180
         av_log(uc, AV_LOG_ERROR, "Protocol not on whitelist \'%s\'!\n", uc->protocol_whitelist);
179 181
         return AVERROR(EINVAL);
180 182
     }
181 183
 
184
+    if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) {
185
+        av_log(uc, AV_LOG_ERROR, "Protocol blacklisted \'%s\'!\n", uc->protocol_blacklist);
186
+        return AVERROR(EINVAL);
187
+    }
188
+
182 189
     if (!uc->protocol_whitelist && uc->prot->default_whitelist) {
183 190
         av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist);
184 191
         uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist);
... ...
@@ -190,6 +198,8 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
190 190
 
191 191
     if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
192 192
         return err;
193
+    if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0)
194
+        return err;
193 195
 
194 196
     err =
195 197
         uc->prot->url_open2 ? uc->prot->url_open2(uc,
... ...
@@ -199,6 +209,7 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
199 199
         uc->prot->url_open(uc, uc->filename, uc->flags);
200 200
 
201 201
     av_dict_set(options, "protocol_whitelist", NULL, 0);
202
+    av_dict_set(options, "protocol_blacklist", NULL, 0);
202 203
 
203 204
     if (err)
204 205
         return err;
... ...
@@ -290,7 +301,8 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
290 290
 }
291 291
 
292 292
 int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
293
-                         const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
293
+                         const AVIOInterruptCB *int_cb, AVDictionary **options,
294
+                         const char *whitelist, const char* blacklist)
294 295
 {
295 296
     AVDictionary *tmp_opts = NULL;
296 297
     AVDictionaryEntry *e;
... ...
@@ -307,10 +319,16 @@ int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
307 307
     av_assert0(!whitelist ||
308 308
                !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
309 309
                !strcmp(whitelist, e->value));
310
+    av_assert0(!blacklist ||
311
+               !(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
312
+               !strcmp(blacklist, e->value));
310 313
 
311 314
     if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
312 315
         goto fail;
313 316
 
317
+    if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0)
318
+        goto fail;
319
+
314 320
     if ((ret = av_opt_set_dict(*puc, options)) < 0)
315 321
         goto fail;
316 322
 
... ...
@@ -328,7 +346,7 @@ int ffurl_open(URLContext **puc, const char *filename, int flags,
328 328
                const AVIOInterruptCB *int_cb, AVDictionary **options)
329 329
 {
330 330
     return ffurl_open_whitelist(puc, filename, flags,
331
-                                int_cb, options, NULL);
331
+                                int_cb, options, NULL, NULL);
332 332
 }
333 333
 
334 334
 static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
... ...
@@ -254,6 +254,11 @@ typedef struct AVIOContext {
254 254
      * ',' separated list of allowed protocols.
255 255
      */
256 256
     const char *protocol_whitelist;
257
+
258
+    /**
259
+     * ',' separated list of disallowed protocols.
260
+     */
261
+    const char *protocol_blacklist;
257 262
 } AVIOContext;
258 263
 
259 264
 /* unbuffered I/O */
... ...
@@ -155,7 +155,7 @@ int ffio_open_null_buf(AVIOContext **s);
155 155
 
156 156
 int ffio_open_whitelist(AVIOContext **s, const char *url, int flags,
157 157
                          const AVIOInterruptCB *int_cb, AVDictionary **options,
158
-                         const char *whitelist);
158
+                         const char *whitelist, const char *blacklist);
159 159
 
160 160
 /**
161 161
  * Close a null buffer.
... ...
@@ -848,6 +848,11 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
848 848
         avio_closep(s);
849 849
         goto fail;
850 850
     }
851
+    (*s)->protocol_blacklist = av_strdup(h->protocol_blacklist);
852
+    if (!(*s)->protocol_blacklist && h->protocol_blacklist) {
853
+        avio_closep(s);
854
+        goto fail;
855
+    }
851 856
     (*s)->direct = h->flags & AVIO_FLAG_DIRECT;
852 857
 
853 858
     (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
... ...
@@ -974,13 +979,13 @@ int avio_open(AVIOContext **s, const char *filename, int flags)
974 974
 
975 975
 int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
976 976
                          const AVIOInterruptCB *int_cb, AVDictionary **options,
977
-                         const char *whitelist
977
+                         const char *whitelist, const char *blacklist
978 978
                         )
979 979
 {
980 980
     URLContext *h;
981 981
     int err;
982 982
 
983
-    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist);
983
+    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist);
984 984
     if (err < 0)
985 985
         return err;
986 986
     err = ffio_fdopen(s, h);
... ...
@@ -994,13 +999,13 @@ int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
994 994
 int avio_open2(AVIOContext **s, const char *filename, int flags,
995 995
                const AVIOInterruptCB *int_cb, AVDictionary **options)
996 996
 {
997
-    return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL);
997
+    return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL, NULL);
998 998
 }
999 999
 
1000 1000
 int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
1001 1001
                        const AVIOInterruptCB *int_cb, AVDictionary **options)
1002 1002
 {
1003
-    return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist);
1003
+    return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist, s->protocol_blacklist);
1004 1004
 }
1005 1005
 
1006 1006
 int avio_close(AVIOContext *s)
... ...
@@ -87,7 +87,7 @@ static int cache_open(URLContext *h, const char *arg, int flags, AVDictionary **
87 87
     av_freep(&buffername);
88 88
 
89 89
     return ffurl_open_whitelist(&c->inner, arg, flags, &h->interrupt_callback,
90
-                                options, h->protocol_whitelist);
90
+                                options, h->protocol_whitelist, h->protocol_blacklist);
91 91
 }
92 92
 
93 93
 static int add_entry(URLContext *h, const unsigned char *buf, int size)
... ...
@@ -98,7 +98,7 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags)
98 98
 
99 99
         /* creating URLContext */
100 100
         err = ffurl_open_whitelist(&uc, node_uri, flags,
101
-                                   &h->interrupt_callback, NULL, h->protocol_whitelist);
101
+                                   &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist);
102 102
         if (err < 0)
103 103
             break;
104 104
 
... ...
@@ -301,7 +301,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
301 301
 
302 302
     cat->avf->interrupt_callback = avf->interrupt_callback;
303 303
 
304
-    if ((ret = ff_copy_whitelists(cat->avf, avf)) < 0)
304
+    if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0)
305 305
         return ret;
306 306
 
307 307
     if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 ||
... ...
@@ -138,7 +138,7 @@ static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary
138 138
 
139 139
     if ((ret = ffurl_open_whitelist(&c->hd, nested_url, flags,
140 140
                                     &h->interrupt_callback, options,
141
-                                    h->protocol_whitelist)) < 0) {
141
+                                    h->protocol_whitelist, h->protocol_blacklist)) < 0) {
142 142
         av_log(h, AV_LOG_ERROR, "Unable to open resource: %s\n", nested_url);
143 143
         goto err;
144 144
     }
... ...
@@ -539,7 +539,7 @@ static int ftp_connect_control_connection(URLContext *h)
539 539
         } /* if option is not given, don't pass it and let tcp use its own default */
540 540
         err = ffurl_open_whitelist(&s->conn_control, buf, AVIO_FLAG_READ_WRITE,
541 541
                                    &h->interrupt_callback, &opts,
542
-                                   h->protocol_whitelist);
542
+                                   h->protocol_whitelist, h->protocol_blacklist);
543 543
         av_dict_free(&opts);
544 544
         if (err < 0) {
545 545
             av_log(h, AV_LOG_ERROR, "Cannot open control connection\n");
... ...
@@ -593,7 +593,7 @@ static int ftp_connect_data_connection(URLContext *h)
593 593
         } /* if option is not given, don't pass it and let tcp use its own default */
594 594
         err = ffurl_open_whitelist(&s->conn_data, buf, h->flags,
595 595
                                    &h->interrupt_callback, &opts,
596
-                                   h->protocol_whitelist);
596
+                                   h->protocol_whitelist, h->protocol_blacklist);
597 597
         av_dict_free(&opts);
598 598
         if (err < 0)
599 599
             return err;
... ...
@@ -94,7 +94,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags)
94 94
 
95 95
     s->hd = NULL;
96 96
     err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
97
-                               &h->interrupt_callback, NULL, h->protocol_whitelist);
97
+                               &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist);
98 98
     if (err < 0)
99 99
         goto fail;
100 100
 
... ...
@@ -1619,7 +1619,7 @@ static int hls_read_header(AVFormatContext *s)
1619 1619
         pls->ctx->io_open  = nested_io_open;
1620 1620
         pls->stream_offset = stream_offset;
1621 1621
 
1622
-        if ((ret = ff_copy_whitelists(pls->ctx, s)) < 0)
1622
+        if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
1623 1623
             goto fail;
1624 1624
 
1625 1625
         ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL);
... ...
@@ -119,7 +119,7 @@ static int parse_playlist(URLContext *h, const char *url)
119 119
 
120 120
     if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
121 121
                                    &h->interrupt_callback, NULL,
122
-                                   h->protocol_whitelist)) < 0)
122
+                                   h->protocol_whitelist, h->protocol_blacklist)) < 0)
123 123
         return ret;
124 124
 
125 125
     read_chomp_line(in, line, sizeof(line));
... ...
@@ -307,7 +307,7 @@ retry:
307 307
     av_log(h, AV_LOG_DEBUG, "opening %s\n", url);
308 308
     ret = ffurl_open_whitelist(&s->seg_hd, url, AVIO_FLAG_READ,
309 309
                                &h->interrupt_callback, NULL,
310
-                               h->protocol_whitelist);
310
+                               h->protocol_whitelist, h->protocol_blacklist);
311 311
     if (ret < 0) {
312 312
         if (ff_check_interrupt(&h->interrupt_callback))
313 313
             return AVERROR_EXIT;
... ...
@@ -221,7 +221,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
221 221
     if (!s->hd) {
222 222
         err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
223 223
                                    &h->interrupt_callback, options,
224
-                                   h->protocol_whitelist);
224
+                                   h->protocol_whitelist, h->protocol_blacklist);
225 225
         if (err < 0)
226 226
             return err;
227 227
     }
... ...
@@ -456,7 +456,7 @@ static int http_listen(URLContext *h, const char *uri, int flags,
456 456
         goto fail;
457 457
     if ((ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
458 458
                                     &h->interrupt_callback, options,
459
-                                    h->protocol_whitelist
459
+                                    h->protocol_whitelist, h->protocol_blacklist
460 460
                                    )) < 0)
461 461
         goto fail;
462 462
     s->handshake_step = LOWER_PROTO;
... ...
@@ -1582,7 +1582,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags)
1582 1582
 redo:
1583 1583
     ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
1584 1584
                                &h->interrupt_callback, NULL,
1585
-                               h->protocol_whitelist);
1585
+                               h->protocol_whitelist, h->protocol_blacklist);
1586 1586
     if (ret < 0)
1587 1587
         return ret;
1588 1588
 
... ...
@@ -165,7 +165,7 @@ static int icecast_open(URLContext *h, const char *uri, int flags)
165 165
     ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path);
166 166
     // Finally open http proto handler
167 167
     ret = ffurl_open_whitelist(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL,
168
-                               &opt_dict, h->protocol_whitelist);
168
+                               &opt_dict, h->protocol_whitelist, h->protocol_blacklist);
169 169
 
170 170
 cleanup:
171 171
     av_freep(&user);
... ...
@@ -532,7 +532,7 @@ enum AVWriteUncodedFrameFlags {
532 532
 /**
533 533
  * Copies the whilelists from one context to the other
534 534
  */
535
-int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src);
535
+int ff_copy_whiteblacklists(AVFormatContext *dst, AVFormatContext *src);
536 536
 
537 537
 int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
538 538
                        const AVIOInterruptCB *int_cb, AVDictionary **options);
... ...
@@ -71,7 +71,7 @@ static int md5_close(URLContext *h)
71 71
     if (*filename) {
72 72
         err = ffurl_open_whitelist(&out, filename, AVIO_FLAG_WRITE,
73 73
                                    &h->interrupt_callback, NULL,
74
-                                   h->protocol_whitelist);
74
+                                   h->protocol_whitelist, h->protocol_blacklist);
75 75
         if (err)
76 76
             return err;
77 77
         err = ffurl_write(out, buf, i*2+1);
... ...
@@ -530,7 +530,7 @@ static int mms_open(URLContext *h, const char *uri, int flags)
530 530
     ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
531 531
     err = ffurl_open_whitelist(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
532 532
                                &h->interrupt_callback, NULL,
533
-                               h->protocol_whitelist);
533
+                               h->protocol_whitelist, h->protocol_blacklist);
534 534
     if (err)
535 535
         goto fail;
536 536
 
... ...
@@ -732,7 +732,7 @@ static int vobsub_read_header(AVFormatContext *s)
732 732
         goto end;
733 733
     }
734 734
 
735
-    if ((ret = ff_copy_whitelists(vobsub->sub_ctx, s)) < 0)
735
+    if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0)
736 736
         goto end;
737 737
 
738 738
     ret = avformat_open_input(&vobsub->sub_ctx, vobsub->sub_name, iformat, NULL);
... ...
@@ -109,7 +109,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
109 109
 FF_ENABLE_DEPRECATION_WARNINGS
110 110
 #endif
111 111
 
112
-    return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist);
112
+    return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist);
113 113
 }
114 114
 
115 115
 static void io_close_default(AVFormatContext *s, AVIOContext *pb)
... ...
@@ -101,6 +101,7 @@ static const AVOption avformat_options[] = {
101 101
 {"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
102 102
 {"format_whitelist", "List of demuxers that are allowed to be used", OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
103 103
 {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
104
+{"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
104 105
 {NULL},
105 106
 };
106 107
 
... ...
@@ -531,7 +531,7 @@ static av_cold int rdt_init(AVFormatContext *s, int st_index, PayloadContext *rd
531 531
     if (!rdt->rmctx)
532 532
         return AVERROR(ENOMEM);
533 533
 
534
-    if ((ret = ff_copy_whitelists(rdt->rmctx, s)) < 0)
534
+    if ((ret = ff_copy_whiteblacklists(rdt->rmctx, s)) < 0)
535 535
         return ret;
536 536
 
537 537
     return avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL);
... ...
@@ -266,7 +266,7 @@ static int rtmpe_open(URLContext *h, const char *uri, int flags)
266 266
     /* open the tcp or ffrtmphttp connection */
267 267
     if ((ret = ffurl_open_whitelist(&rt->stream, url, AVIO_FLAG_READ_WRITE,
268 268
                                     &h->interrupt_callback, NULL,
269
-                                    h->protocol_whitelist)) < 0) {
269
+                                    h->protocol_whitelist, h->protocol_blacklist)) < 0) {
270 270
         rtmpe_close(h);
271 271
         return ret;
272 272
     }
... ...
@@ -1120,7 +1120,7 @@ static int rtmp_calc_swfhash(URLContext *s)
1120 1120
     /* Get the SWF player file. */
1121 1121
     if ((ret = ffurl_open_whitelist(&stream, rt->swfverify, AVIO_FLAG_READ,
1122 1122
                                     &s->interrupt_callback, NULL,
1123
-                                    s->protocol_whitelist)) < 0) {
1123
+                                    s->protocol_whitelist, s->protocol_blacklist)) < 0) {
1124 1124
         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1125 1125
         goto fail;
1126 1126
     }
... ...
@@ -2650,7 +2650,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
2650 2650
 reconnect:
2651 2651
     if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2652 2652
                                     &s->interrupt_callback, &opts,
2653
-                                    s->protocol_whitelist)) < 0) {
2653
+                                    s->protocol_whitelist, s->protocol_blacklist)) < 0) {
2654 2654
         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2655 2655
         goto fail;
2656 2656
     }
... ...
@@ -131,7 +131,7 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
131 131
         rt->asf_ctx->pb      = &pb;
132 132
         av_dict_set(&opts, "no_resync_search", "1", 0);
133 133
 
134
-        if ((ret = ff_copy_whitelists(rt->asf_ctx, s)) < 0) {
134
+        if ((ret = ff_copy_whiteblacklists(rt->asf_ctx, s)) < 0) {
135 135
             av_dict_free(&opts);
136 136
             return ret;
137 137
         }
... ...
@@ -381,7 +381,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
381 381
                       hostname, rtp_port, s->local_rtpport,
382 382
                       sources, block);
383 383
         if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
384
-                                 NULL, h->protocol_whitelist) < 0)
384
+                                 NULL, h->protocol_whitelist, h->protocol_blacklist) < 0)
385 385
             goto fail;
386 386
         s->local_rtpport = ff_udp_get_local_port(s->rtp_hd);
387 387
         if(s->local_rtpport == 65535) {
... ...
@@ -395,7 +395,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
395 395
                           sources, block);
396 396
             if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags,
397 397
                                      &h->interrupt_callback, NULL,
398
-                                     h->protocol_whitelist) < 0) {
398
+                                     h->protocol_whitelist, h->protocol_blacklist) < 0) {
399 399
                 s->local_rtpport = s->local_rtcpport = -1;
400 400
                 continue;
401 401
             }
... ...
@@ -405,7 +405,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
405 405
                       hostname, s->rtcp_port, s->local_rtcpport,
406 406
                       sources, block);
407 407
         if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags, &h->interrupt_callback,
408
-                                 NULL, h->protocol_whitelist) < 0)
408
+                                 NULL, h->protocol_whitelist, h->protocol_blacklist) < 0)
409 409
             goto fail;
410 410
         break;
411 411
     }
... ...
@@ -1469,7 +1469,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
1469 1469
                 /* we will use two ports per rtp stream (rtp and rtcp) */
1470 1470
                 j += 2;
1471 1471
                 err = ffurl_open_whitelist(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
1472
-                                 &s->interrupt_callback, &opts, s->protocol_whitelist);
1472
+                                 &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist);
1473 1473
 
1474 1474
                 av_dict_free(&opts);
1475 1475
 
... ...
@@ -1612,7 +1612,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
1612 1612
             ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
1613 1613
                         port, "%s", optbuf);
1614 1614
             if (ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
1615
-                           &s->interrupt_callback, NULL, s->protocol_whitelist) < 0) {
1615
+                           &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist) < 0) {
1616 1616
                 err = AVERROR_INVALIDDATA;
1617 1617
                 goto fail;
1618 1618
             }
... ...
@@ -1801,7 +1801,7 @@ redirect:
1801 1801
                     host, port,
1802 1802
                     "?timeout=%d", rt->stimeout);
1803 1803
         if ((ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
1804
-                       &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
1804
+                       &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist)) < 0) {
1805 1805
             err = ret;
1806 1806
             goto fail;
1807 1807
         }
... ...
@@ -2317,7 +2317,7 @@ static int sdp_read_header(AVFormatContext *s)
2317 2317
                                 rtsp_st->nb_exclude_source_addrs,
2318 2318
                                 rtsp_st->exclude_source_addrs);
2319 2319
             err = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
2320
-                           &s->interrupt_callback, &opts, s->protocol_whitelist);
2320
+                           &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist);
2321 2321
 
2322 2322
             av_dict_free(&opts);
2323 2323
 
... ...
@@ -2387,7 +2387,7 @@ static int rtp_read_header(AVFormatContext *s)
2387 2387
         return AVERROR(EIO);
2388 2388
 
2389 2389
     ret = ffurl_open_whitelist(&in, s->filename, AVIO_FLAG_READ,
2390
-                     &s->interrupt_callback, NULL, s->protocol_whitelist);
2390
+                     &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist);
2391 2391
     if (ret)
2392 2392
         goto fail;
2393 2393
 
... ...
@@ -296,7 +296,7 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
296 296
             av_log(s, AV_LOG_TRACE, "Opening: %s", url);
297 297
             ret = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
298 298
                                        &s->interrupt_callback, &opts,
299
-                                       s->protocol_whitelist);
299
+                                       s->protocol_whitelist, s->protocol_blacklist);
300 300
             av_dict_free(&opts);
301 301
             if (ret)
302 302
                 localport += 2;
... ...
@@ -665,7 +665,7 @@ static int rtsp_listen(AVFormatContext *s)
665 665
 
666 666
     if (ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
667 667
                                    &s->interrupt_callback, NULL,
668
-                                   s->protocol_whitelist)) {
668
+                                   s->protocol_whitelist, s->protocol_blacklist)) {
669 669
         av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n");
670 670
         return ret;
671 671
     }
... ...
@@ -87,7 +87,7 @@ static int sap_read_header(AVFormatContext *s)
87 87
                 port);
88 88
     ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_READ,
89 89
                                &s->interrupt_callback, NULL,
90
-                               s->protocol_whitelist);
90
+                               s->protocol_whitelist, s->protocol_blacklist);
91 91
     if (ret)
92 92
         goto fail;
93 93
 
... ...
@@ -161,7 +161,7 @@ static int sap_read_header(AVFormatContext *s)
161 161
     sap->sdp_ctx->pb        = &sap->sdp_pb;
162 162
     sap->sdp_ctx->interrupt_callback = s->interrupt_callback;
163 163
 
164
-    if ((ret = ff_copy_whitelists(sap->sdp_ctx, s)) < 0)
164
+    if ((ret = ff_copy_whiteblacklists(sap->sdp_ctx, s)) < 0)
165 165
         goto fail;
166 166
 
167 167
     ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
... ...
@@ -151,7 +151,7 @@ static int sap_write_header(AVFormatContext *s)
151 151
             base_port += 2;
152 152
         ret = ffurl_open_whitelist(&fd, url, AVIO_FLAG_WRITE,
153 153
                                    &s->interrupt_callback, NULL,
154
-                                   s->protocol_whitelist);
154
+                                   s->protocol_whitelist, s->protocol_blacklist);
155 155
         if (ret) {
156 156
             ret = AVERROR(EIO);
157 157
             goto fail;
... ...
@@ -171,7 +171,7 @@ static int sap_write_header(AVFormatContext *s)
171 171
                 "?ttl=%d&connect=1", ttl);
172 172
     ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_WRITE,
173 173
                                &s->interrupt_callback, NULL,
174
-                               s->protocol_whitelist);
174
+                               s->protocol_whitelist, s->protocol_blacklist);
175 175
     if (ret) {
176 176
         ret = AVERROR(EIO);
177 177
         goto fail;
... ...
@@ -123,7 +123,7 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
123 123
             os->tail_out = os->out;
124 124
             av_dict_set(&opts, "truncate", "0", 0);
125 125
             ret = ffurl_open_whitelist(&os->out, frag->file, AVIO_FLAG_WRITE,
126
-                                       &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
126
+                                       &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist, os->ctx->protocol_blacklist);
127 127
             av_dict_free(&opts);
128 128
             if (ret < 0) {
129 129
                 os->out = os->tail_out;
... ...
@@ -132,7 +132,7 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
132 132
             }
133 133
             av_dict_set(&opts, "truncate", "0", 0);
134 134
             ffurl_open_whitelist(&os->out2, frag->infofile, AVIO_FLAG_WRITE,
135
-                                 &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
135
+                                 &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist, os->ctx->protocol_blacklist);
136 136
             av_dict_free(&opts);
137 137
             ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
138 138
             if (os->out2)
... ...
@@ -332,7 +332,7 @@ static int ism_write_header(AVFormatContext *s)
332 332
         }
333 333
 
334 334
         ctx = avformat_alloc_context();
335
-        if (!ctx || ff_copy_whitelists(ctx, s) < 0) {
335
+        if (!ctx || ff_copy_whiteblacklists(ctx, s) < 0) {
336 336
             ret = AVERROR(ENOMEM);
337 337
             goto fail;
338 338
         }
... ...
@@ -526,7 +526,7 @@ static int ism_flush(AVFormatContext *s, int final)
526 526
             continue;
527 527
 
528 528
         snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
529
-        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
529
+        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist);
530 530
         if (ret < 0)
531 531
             break;
532 532
         os->cur_start_pos = os->tail_pos;
... ...
@@ -81,7 +81,7 @@ static int srtp_open(URLContext *h, const char *uri, int flags)
81 81
                  path, sizeof(path), uri);
82 82
     ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path);
83 83
     if ((ret = ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
84
-                                    NULL, h->protocol_whitelist)) < 0)
84
+                                    NULL, h->protocol_whitelist, h->protocol_blacklist)) < 0)
85 85
         goto fail;
86 86
 
87 87
     h->max_packet_size = FFMIN(s->rtp_hd->max_packet_size,
... ...
@@ -78,7 +78,7 @@ static int subfile_open(URLContext *h, const char *filename, int flags,
78 78
     }
79 79
     av_strstart(filename, "subfile:", &filename);
80 80
     ret = ffurl_open_whitelist(&c->h, filename, flags, &h->interrupt_callback,
81
-                               options, h->protocol_whitelist);
81
+                               options, h->protocol_whitelist, h->protocol_blacklist);
82 82
     if (ret < 0)
83 83
         return ret;
84 84
     c->pos = c->start;
... ...
@@ -106,5 +106,5 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
106 106
 
107 107
     return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
108 108
                                 &parent->interrupt_callback, options,
109
-                                parent->protocol_whitelist);
109
+                                parent->protocol_whitelist, parent->protocol_blacklist);
110 110
 }
... ...
@@ -83,7 +83,7 @@ static int import_pem(URLContext *h, char *path, CFArrayRef *array)
83 83
 
84 84
     if ((ret = ffio_open_whitelist(&s, path, AVIO_FLAG_READ,
85 85
                                    &h->interrupt_callback, NULL,
86
-                                   h->protocol_whitelist)) < 0)
86
+                                   h->protocol_whitelist, h->protocol_blacklist)) < 0)
87 87
         goto end;
88 88
 
89 89
     if ((ret = avio_size(s)) < 0)
... ...
@@ -47,6 +47,7 @@ typedef struct URLContext {
47 47
     AVIOInterruptCB interrupt_callback;
48 48
     int64_t rw_timeout;         /**< maximum time to wait for (network) read/write operation completion, in mcs */
49 49
     const char *protocol_whitelist;
50
+    const char *protocol_blacklist;
50 51
 } URLContext;
51 52
 
52 53
 typedef struct URLProtocol {
... ...
@@ -140,7 +141,7 @@ int ffurl_connect(URLContext *uc, AVDictionary **options);
140 140
  */
141 141
 int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
142 142
                const AVIOInterruptCB *int_cb, AVDictionary **options,
143
-               const char *whitelist);
143
+               const char *whitelist, const char* blacklist);
144 144
 
145 145
 int ffurl_open(URLContext **puc, const char *filename, int flags,
146 146
                const AVIOInterruptCB *int_cb, AVDictionary **options);
... ...
@@ -142,18 +142,21 @@ void av_format_inject_global_side_data(AVFormatContext *s)
142 142
     }
143 143
 }
144 144
 
145
-int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src)
145
+int ff_copy_whiteblacklists(AVFormatContext *dst, AVFormatContext *src)
146 146
 {
147 147
     av_assert0(!dst->codec_whitelist &&
148 148
                !dst->format_whitelist &&
149
-               !dst->protocol_whitelist);
149
+               !dst->protocol_whitelist &&
150
+               !dst->protocol_blacklist);
150 151
     dst-> codec_whitelist = av_strdup(src->codec_whitelist);
151 152
     dst->format_whitelist = av_strdup(src->format_whitelist);
152 153
     dst->protocol_whitelist = av_strdup(src->protocol_whitelist);
154
+    dst->protocol_blacklist = av_strdup(src->protocol_blacklist);
153 155
     if (   (src-> codec_whitelist && !dst-> codec_whitelist)
154 156
         || (src->  format_whitelist && !dst->  format_whitelist)
155
-        || (src->protocol_whitelist && !dst->protocol_whitelist)) {
156
-        av_log(dst, AV_LOG_ERROR, "Failed to duplicate whitelist\n");
157
+        || (src->protocol_whitelist && !dst->protocol_whitelist)
158
+        || (src->protocol_blacklist && !dst->protocol_blacklist)) {
159
+        av_log(dst, AV_LOG_ERROR, "Failed to duplicate black/whitelist\n");
157 160
         return AVERROR(ENOMEM);
158 161
     }
159 162
     return 0;
... ...
@@ -460,6 +463,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
460 460
         }
461 461
     }
462 462
 
463
+    if (!s->protocol_blacklist && s->pb && s->pb->protocol_blacklist) {
464
+        s->protocol_blacklist = av_strdup(s->pb->protocol_blacklist);
465
+        if (!s->protocol_blacklist) {
466
+            ret = AVERROR(ENOMEM);
467
+            goto fail;
468
+        }
469
+    }
470
+
463 471
     if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, ',') <= 0) {
464 472
         av_log(s, AV_LOG_ERROR, "Format not on whitelist \'%s\'\n", s->format_whitelist);
465 473
         ret = AVERROR(EINVAL);
... ...
@@ -30,8 +30,8 @@
30 30
 #include "libavutil/version.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR  57
33
-#define LIBAVFORMAT_VERSION_MINOR  27
34
-#define LIBAVFORMAT_VERSION_MICRO 102
33
+#define LIBAVFORMAT_VERSION_MINOR  28
34
+#define LIBAVFORMAT_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
37 37
                                                LIBAVFORMAT_VERSION_MINOR, \