[FFmpeg-devel] [PATCH] avformat: Add a protocol blacklisting API

Derek Buitenhuis derek.buitenhuis at gmail.com
Thu Mar 3 18:18:03 CET 2016


Signed-off-by: Derek Buitenhuis <derek.buitenhuis at gmail.com>
---
This matches API with Libav, in a forthcoming merge, using our
exisiting infastructure code.

CC'd Michael, since he wrote the whitelisting code.

This has been tested with FATE.
---
 Changelog                         |  1 +
 doc/APIchanges                    |  3 +++
 libavformat/async.c               |  2 +-
 libavformat/avformat.h            |  7 +++++++
 libavformat/avidec.c              |  2 +-
 libavformat/avio.c                | 22 ++++++++++++++++++++--
 libavformat/avio.h                |  5 +++++
 libavformat/avio_internal.h       |  2 +-
 libavformat/aviobuf.c             | 13 +++++++++----
 libavformat/cache.c               |  2 +-
 libavformat/concat.c              |  2 +-
 libavformat/concatdec.c           |  2 +-
 libavformat/crypto.c              |  2 +-
 libavformat/ftp.c                 |  4 ++--
 libavformat/gopher.c              |  2 +-
 libavformat/hls.c                 |  2 +-
 libavformat/hlsproto.c            |  4 ++--
 libavformat/http.c                |  6 +++---
 libavformat/icecast.c             |  2 +-
 libavformat/internal.h            |  2 +-
 libavformat/md5proto.c            |  2 +-
 libavformat/mmst.c                |  2 +-
 libavformat/mpeg.c                |  2 +-
 libavformat/options.c             |  2 +-
 libavformat/options_table.h       |  1 +
 libavformat/rdt.c                 |  2 +-
 libavformat/rtmpcrypt.c           |  2 +-
 libavformat/rtmpproto.c           |  4 ++--
 libavformat/rtpdec_asf.c          |  2 +-
 libavformat/rtpproto.c            |  6 +++---
 libavformat/rtsp.c                | 10 +++++-----
 libavformat/rtspdec.c             |  4 ++--
 libavformat/sapdec.c              |  4 ++--
 libavformat/sapenc.c              |  4 ++--
 libavformat/smoothstreamingenc.c  |  8 ++++----
 libavformat/srtpproto.c           |  2 +-
 libavformat/subfile.c             |  2 +-
 libavformat/tls.c                 |  2 +-
 libavformat/tls_securetransport.c |  2 +-
 libavformat/url.h                 |  3 ++-
 libavformat/utils.c               | 19 +++++++++++++++----
 libavformat/version.h             |  4 ++--
 42 files changed, 114 insertions(+), 62 deletions(-)

diff --git a/Changelog b/Changelog
index d6459a8..0e70724 100644
--- a/Changelog
+++ b/Changelog
@@ -10,6 +10,7 @@ version <next>:
 - datascope filter
 - bench and abench filters
 - ciescope filter
+- protocol blacklisting API
 
 
 version 3.0:
diff --git a/doc/APIchanges b/doc/APIchanges
index a75f346..2fc6a71 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,9 @@ libavutil:     2015-08-28
 
 API changes, most recent first:
 
+2016-XX-XX - xxxxxxx - lavf 57.28.100
+  Add protocol blacklisting API
+
 2016-02-28 - xxxxxxx - lavc 57.27.101
   Validate AVFrame returned by get_buffer2 to have required
   planes not NULL and unused planes set to NULL as crashes
diff --git a/libavformat/async.c b/libavformat/async.c
index a835292..0cc6fb0 100644
--- a/libavformat/async.c
+++ b/libavformat/async.c
@@ -251,7 +251,7 @@ static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **
 
     /* wrap interrupt callback */
     c->interrupt_callback = h->interrupt_callback;
-    ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist);
+    ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist);
     if (ret != 0) {
         av_log(h, AV_LOG_ERROR, "ffurl_open failed : %s, %s\n", av_err2str(ret), arg);
         goto url_fail;
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index b843a4b..b133575 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1838,6 +1838,13 @@ typedef struct AVFormatContext {
      */
     char *protocol_whitelist;
 
+    /**
+     * ',' separated list of disallowed protocols.
+     * - encoding: unused
+     * - decoding: set by user through AVOptions (NO direct access)
+     */
+    char *protocol_blacklist;
+
     /*
      * A callback for opening new IO streams.
      *
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 3859810..eaf8421 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -1089,7 +1089,7 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 
         ast->sub_ctx->pb = pb;
 
-        if (ff_copy_whitelists(ast->sub_ctx, s) < 0)
+        if (ff_copy_whiteblacklists(ast->sub_ctx, s) < 0)
             goto error;
 
         if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) {
diff --git a/libavformat/avio.c b/libavformat/avio.c
index 69b6eaa..0be820b 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -55,6 +55,7 @@ static void *urlcontext_child_next(void *obj, void *prev)
 #define D AV_OPT_FLAG_DECODING_PARAM
 static const AVOption options[] = {
     {"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 },
+    {"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 },
     { NULL }
 };
 
@@ -173,12 +174,19 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
     // Check that URLContext was initialized correctly and lists are matching if set
     av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
                (uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value)));
+    av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
+               (uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value)));
 
     if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) {
         av_log(uc, AV_LOG_ERROR, "Protocol not on whitelist \'%s\'!\n", uc->protocol_whitelist);
         return AVERROR(EINVAL);
     }
 
+    if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) {
+        av_log(uc, AV_LOG_ERROR, "Protocol blacklisted \'%s\'!\n", uc->protocol_blacklist);
+        return AVERROR(EINVAL);
+    }
+
     if (!uc->protocol_whitelist && uc->prot->default_whitelist) {
         av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist);
         uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist);
@@ -190,6 +198,8 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
 
     if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
         return err;
+    if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0)
+        return err;
 
     err =
         uc->prot->url_open2 ? uc->prot->url_open2(uc,
@@ -199,6 +209,7 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
         uc->prot->url_open(uc, uc->filename, uc->flags);
 
     av_dict_set(options, "protocol_whitelist", NULL, 0);
+    av_dict_set(options, "protocol_blacklist", NULL, 0);
 
     if (err)
         return err;
@@ -290,7 +301,8 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
 }
 
 int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
-                         const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
+                         const AVIOInterruptCB *int_cb, AVDictionary **options,
+                         const char *whitelist, const char* blacklist)
 {
     AVDictionary *tmp_opts = NULL;
     AVDictionaryEntry *e;
@@ -307,10 +319,16 @@ int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
     av_assert0(!whitelist ||
                !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
                !strcmp(whitelist, e->value));
+    av_assert0(!blacklist ||
+               !(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
+               !strcmp(blacklist, e->value));
 
     if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
         goto fail;
 
+    if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0)
+        goto fail;
+
     if ((ret = av_opt_set_dict(*puc, options)) < 0)
         goto fail;
 
@@ -328,7 +346,7 @@ int ffurl_open(URLContext **puc, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options)
 {
     return ffurl_open_whitelist(puc, filename, flags,
-                                int_cb, options, NULL);
+                                int_cb, options, NULL, NULL);
 }
 
 static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 7fbce32..2321403 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -254,6 +254,11 @@ typedef struct AVIOContext {
      * ',' separated list of allowed protocols.
      */
     const char *protocol_whitelist;
+
+    /**
+     * ',' separated list of disallowed protocols.
+     */
+    const char *protocol_blacklist;
 } AVIOContext;
 
 /* unbuffered I/O */
diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h
index 1e2a18e..ba9bd4e 100644
--- a/libavformat/avio_internal.h
+++ b/libavformat/avio_internal.h
@@ -155,7 +155,7 @@ int ffio_open_null_buf(AVIOContext **s);
 
 int ffio_open_whitelist(AVIOContext **s, const char *url, int flags,
                          const AVIOInterruptCB *int_cb, AVDictionary **options,
-                         const char *whitelist);
+                         const char *whitelist, const char *blacklist);
 
 /**
  * Close a null buffer.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index e45afd1..00f7c5a 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -848,6 +848,11 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
         avio_closep(s);
         goto fail;
     }
+    (*s)->protocol_blacklist = av_strdup(h->protocol_blacklist);
+    if (!(*s)->protocol_blacklist && h->protocol_blacklist) {
+        avio_closep(s);
+        goto fail;
+    }
     (*s)->direct = h->flags & AVIO_FLAG_DIRECT;
 
     (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
@@ -974,13 +979,13 @@ int avio_open(AVIOContext **s, const char *filename, int flags)
 
 int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
                          const AVIOInterruptCB *int_cb, AVDictionary **options,
-                         const char *whitelist
+                         const char *whitelist, const char *blacklist
                         )
 {
     URLContext *h;
     int err;
 
-    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist);
+    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist);
     if (err < 0)
         return err;
     err = ffio_fdopen(s, h);
@@ -994,13 +999,13 @@ int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
 int avio_open2(AVIOContext **s, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options)
 {
-    return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL);
+    return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL, NULL);
 }
 
 int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
                        const AVIOInterruptCB *int_cb, AVDictionary **options)
 {
-    return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist);
+    return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist, s->protocol_blacklist);
 }
 
 int avio_close(AVIOContext *s)
diff --git a/libavformat/cache.c b/libavformat/cache.c
index 59d7fe6..1d26cb8 100644
--- a/libavformat/cache.c
+++ b/libavformat/cache.c
@@ -87,7 +87,7 @@ static int cache_open(URLContext *h, const char *arg, int flags, AVDictionary **
     av_freep(&buffername);
 
     return ffurl_open_whitelist(&c->inner, arg, flags, &h->interrupt_callback,
-                                options, h->protocol_whitelist);
+                                options, h->protocol_whitelist, h->protocol_blacklist);
 }
 
 static int add_entry(URLContext *h, const unsigned char *buf, int size)
diff --git a/libavformat/concat.c b/libavformat/concat.c
index 190f36d..288bf14 100644
--- a/libavformat/concat.c
+++ b/libavformat/concat.c
@@ -98,7 +98,7 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags)
 
         /* creating URLContext */
         err = ffurl_open_whitelist(&uc, node_uri, flags,
-                                   &h->interrupt_callback, NULL, h->protocol_whitelist);
+                                   &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist);
         if (err < 0)
             break;
 
diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index d226e15..e69096f 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -301,7 +301,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
 
     cat->avf->interrupt_callback = avf->interrupt_callback;
 
-    if ((ret = ff_copy_whitelists(cat->avf, avf)) < 0)
+    if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0)
         return ret;
 
     if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 ||
diff --git a/libavformat/crypto.c b/libavformat/crypto.c
index 221cb9a..4222e1e 100644
--- a/libavformat/crypto.c
+++ b/libavformat/crypto.c
@@ -138,7 +138,7 @@ static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary
 
     if ((ret = ffurl_open_whitelist(&c->hd, nested_url, flags,
                                     &h->interrupt_callback, options,
-                                    h->protocol_whitelist)) < 0) {
+                                    h->protocol_whitelist, h->protocol_blacklist)) < 0) {
         av_log(h, AV_LOG_ERROR, "Unable to open resource: %s\n", nested_url);
         goto err;
     }
diff --git a/libavformat/ftp.c b/libavformat/ftp.c
index 50b28e2..890930c 100644
--- a/libavformat/ftp.c
+++ b/libavformat/ftp.c
@@ -539,7 +539,7 @@ static int ftp_connect_control_connection(URLContext *h)
         } /* if option is not given, don't pass it and let tcp use its own default */
         err = ffurl_open_whitelist(&s->conn_control, buf, AVIO_FLAG_READ_WRITE,
                                    &h->interrupt_callback, &opts,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist);
         av_dict_free(&opts);
         if (err < 0) {
             av_log(h, AV_LOG_ERROR, "Cannot open control connection\n");
@@ -593,7 +593,7 @@ static int ftp_connect_data_connection(URLContext *h)
         } /* if option is not given, don't pass it and let tcp use its own default */
         err = ffurl_open_whitelist(&s->conn_data, buf, h->flags,
                                    &h->interrupt_callback, &opts,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist);
         av_dict_free(&opts);
         if (err < 0)
             return err;
diff --git a/libavformat/gopher.c b/libavformat/gopher.c
index 271c825..d1113e7 100644
--- a/libavformat/gopher.c
+++ b/libavformat/gopher.c
@@ -94,7 +94,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags)
 
     s->hd = NULL;
     err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
-                               &h->interrupt_callback, NULL, h->protocol_whitelist);
+                               &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist);
     if (err < 0)
         goto fail;
 
diff --git a/libavformat/hls.c b/libavformat/hls.c
index 1715445..61ab5c8 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -1619,7 +1619,7 @@ static int hls_read_header(AVFormatContext *s)
         pls->ctx->io_open  = nested_io_open;
         pls->stream_offset = stream_offset;
 
-        if ((ret = ff_copy_whitelists(pls->ctx, s)) < 0)
+        if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
             goto fail;
 
         ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL);
diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c
index 1f2e63d..097e520 100644
--- a/libavformat/hlsproto.c
+++ b/libavformat/hlsproto.c
@@ -119,7 +119,7 @@ static int parse_playlist(URLContext *h, const char *url)
 
     if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
                                    &h->interrupt_callback, NULL,
-                                   h->protocol_whitelist)) < 0)
+                                   h->protocol_whitelist, h->protocol_blacklist)) < 0)
         return ret;
 
     read_chomp_line(in, line, sizeof(line));
@@ -307,7 +307,7 @@ retry:
     av_log(h, AV_LOG_DEBUG, "opening %s\n", url);
     ret = ffurl_open_whitelist(&s->seg_hd, url, AVIO_FLAG_READ,
                                &h->interrupt_callback, NULL,
-                               h->protocol_whitelist);
+                               h->protocol_whitelist, h->protocol_blacklist);
     if (ret < 0) {
         if (ff_check_interrupt(&h->interrupt_callback))
             return AVERROR_EXIT;
diff --git a/libavformat/http.c b/libavformat/http.c
index a4ce479..ae77b64 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -221,7 +221,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
     if (!s->hd) {
         err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
                                    &h->interrupt_callback, options,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist);
         if (err < 0)
             return err;
     }
@@ -456,7 +456,7 @@ static int http_listen(URLContext *h, const char *uri, int flags,
         goto fail;
     if ((ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
                                     &h->interrupt_callback, options,
-                                    h->protocol_whitelist
+                                    h->protocol_whitelist, h->protocol_blacklist
                                    )) < 0)
         goto fail;
     s->handshake_step = LOWER_PROTO;
@@ -1582,7 +1582,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags)
 redo:
     ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
                                &h->interrupt_callback, NULL,
-                               h->protocol_whitelist);
+                               h->protocol_whitelist, h->protocol_blacklist);
     if (ret < 0)
         return ret;
 
diff --git a/libavformat/icecast.c b/libavformat/icecast.c
index e5f1a95..f7ca5cb 100644
--- a/libavformat/icecast.c
+++ b/libavformat/icecast.c
@@ -165,7 +165,7 @@ static int icecast_open(URLContext *h, const char *uri, int flags)
     ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path);
     // Finally open http proto handler
     ret = ffurl_open_whitelist(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL,
-                               &opt_dict, h->protocol_whitelist);
+                               &opt_dict, h->protocol_whitelist, h->protocol_blacklist);
 
 cleanup:
     av_freep(&user);
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 63e0632..f66348c 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -532,7 +532,7 @@ enum AVWriteUncodedFrameFlags {
 /**
  * Copies the whilelists from one context to the other
  */
-int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src);
+int ff_copy_whiteblacklists(AVFormatContext *dst, AVFormatContext *src);
 
 int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
                        const AVIOInterruptCB *int_cb, AVDictionary **options);
diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c
index 3d8c2a0..2df34c6 100644
--- a/libavformat/md5proto.c
+++ b/libavformat/md5proto.c
@@ -71,7 +71,7 @@ static int md5_close(URLContext *h)
     if (*filename) {
         err = ffurl_open_whitelist(&out, filename, AVIO_FLAG_WRITE,
                                    &h->interrupt_callback, NULL,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist);
         if (err)
             return err;
         err = ffurl_write(out, buf, i*2+1);
diff --git a/libavformat/mmst.c b/libavformat/mmst.c
index b168903..0f48b46 100644
--- a/libavformat/mmst.c
+++ b/libavformat/mmst.c
@@ -530,7 +530,7 @@ static int mms_open(URLContext *h, const char *uri, int flags)
     ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
     err = ffurl_open_whitelist(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
                                &h->interrupt_callback, NULL,
-                               h->protocol_whitelist);
+                               h->protocol_whitelist, h->protocol_blacklist);
     if (err)
         goto fail;
 
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index 69685cf..a7ceeaf 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -732,7 +732,7 @@ static int vobsub_read_header(AVFormatContext *s)
         goto end;
     }
 
-    if ((ret = ff_copy_whitelists(vobsub->sub_ctx, s)) < 0)
+    if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0)
         goto end;
 
     ret = avformat_open_input(&vobsub->sub_ctx, vobsub->sub_name, iformat, NULL);
diff --git a/libavformat/options.c b/libavformat/options.c
index 8fe0017..04d9c45 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -109,7 +109,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-    return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist);
+    return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist);
 }
 
 static void io_close_default(AVFormatContext *s, AVIOContext *pb)
diff --git a/libavformat/options_table.h b/libavformat/options_table.h
index 74923d8..0be5221 100644
--- a/libavformat/options_table.h
+++ b/libavformat/options_table.h
@@ -101,6 +101,7 @@ static const AVOption avformat_options[] = {
 {"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 },
 {"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 },
 {"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 },
+{"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 },
 {NULL},
 };
 
diff --git a/libavformat/rdt.c b/libavformat/rdt.c
index c3ac198..0300b76 100644
--- a/libavformat/rdt.c
+++ b/libavformat/rdt.c
@@ -531,7 +531,7 @@ static av_cold int rdt_init(AVFormatContext *s, int st_index, PayloadContext *rd
     if (!rdt->rmctx)
         return AVERROR(ENOMEM);
 
-    if ((ret = ff_copy_whitelists(rdt->rmctx, s)) < 0)
+    if ((ret = ff_copy_whiteblacklists(rdt->rmctx, s)) < 0)
         return ret;
 
     return avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL);
diff --git a/libavformat/rtmpcrypt.c b/libavformat/rtmpcrypt.c
index 77ca2d1..3d5eb22 100644
--- a/libavformat/rtmpcrypt.c
+++ b/libavformat/rtmpcrypt.c
@@ -266,7 +266,7 @@ static int rtmpe_open(URLContext *h, const char *uri, int flags)
     /* open the tcp or ffrtmphttp connection */
     if ((ret = ffurl_open_whitelist(&rt->stream, url, AVIO_FLAG_READ_WRITE,
                                     &h->interrupt_callback, NULL,
-                                    h->protocol_whitelist)) < 0) {
+                                    h->protocol_whitelist, h->protocol_blacklist)) < 0) {
         rtmpe_close(h);
         return ret;
     }
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index ee8c8a6..c01bc40 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -1120,7 +1120,7 @@ static int rtmp_calc_swfhash(URLContext *s)
     /* Get the SWF player file. */
     if ((ret = ffurl_open_whitelist(&stream, rt->swfverify, AVIO_FLAG_READ,
                                     &s->interrupt_callback, NULL,
-                                    s->protocol_whitelist)) < 0) {
+                                    s->protocol_whitelist, s->protocol_blacklist)) < 0) {
         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
         goto fail;
     }
@@ -2650,7 +2650,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
 reconnect:
     if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
                                     &s->interrupt_callback, &opts,
-                                    s->protocol_whitelist)) < 0) {
+                                    s->protocol_whitelist, s->protocol_blacklist)) < 0) {
         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
         goto fail;
     }
diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c
index 2b1ddf1..041085f 100644
--- a/libavformat/rtpdec_asf.c
+++ b/libavformat/rtpdec_asf.c
@@ -131,7 +131,7 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
         rt->asf_ctx->pb      = &pb;
         av_dict_set(&opts, "no_resync_search", "1", 0);
 
-        if ((ret = ff_copy_whitelists(rt->asf_ctx, s)) < 0) {
+        if ((ret = ff_copy_whiteblacklists(rt->asf_ctx, s)) < 0) {
             av_dict_free(&opts);
             return ret;
         }
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index a35ff5f..451d811 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -381,7 +381,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
                       hostname, rtp_port, s->local_rtpport,
                       sources, block);
         if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
-                                 NULL, h->protocol_whitelist) < 0)
+                                 NULL, h->protocol_whitelist, h->protocol_blacklist) < 0)
             goto fail;
         s->local_rtpport = ff_udp_get_local_port(s->rtp_hd);
         if(s->local_rtpport == 65535) {
@@ -395,7 +395,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
                           sources, block);
             if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags,
                                      &h->interrupt_callback, NULL,
-                                     h->protocol_whitelist) < 0) {
+                                     h->protocol_whitelist, h->protocol_blacklist) < 0) {
                 s->local_rtpport = s->local_rtcpport = -1;
                 continue;
             }
@@ -405,7 +405,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
                       hostname, s->rtcp_port, s->local_rtcpport,
                       sources, block);
         if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags, &h->interrupt_callback,
-                                 NULL, h->protocol_whitelist) < 0)
+                                 NULL, h->protocol_whitelist, h->protocol_blacklist) < 0)
             goto fail;
         break;
     }
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index d710469..64f8c91 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -1469,7 +1469,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
                 /* we will use two ports per rtp stream (rtp and rtcp) */
                 j += 2;
                 err = ffurl_open_whitelist(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
-                                 &s->interrupt_callback, &opts, s->protocol_whitelist);
+                                 &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist);
 
                 av_dict_free(&opts);
 
@@ -1612,7 +1612,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
             ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
                         port, "%s", optbuf);
             if (ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                           &s->interrupt_callback, NULL, s->protocol_whitelist) < 0) {
+                           &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist) < 0) {
                 err = AVERROR_INVALIDDATA;
                 goto fail;
             }
@@ -1801,7 +1801,7 @@ redirect:
                     host, port,
                     "?timeout=%d", rt->stimeout);
         if ((ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
-                       &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
+                       &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist)) < 0) {
             err = ret;
             goto fail;
         }
@@ -2317,7 +2317,7 @@ static int sdp_read_header(AVFormatContext *s)
                                 rtsp_st->nb_exclude_source_addrs,
                                 rtsp_st->exclude_source_addrs);
             err = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                           &s->interrupt_callback, &opts, s->protocol_whitelist);
+                           &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist);
 
             av_dict_free(&opts);
 
@@ -2387,7 +2387,7 @@ static int rtp_read_header(AVFormatContext *s)
         return AVERROR(EIO);
 
     ret = ffurl_open_whitelist(&in, s->filename, AVIO_FLAG_READ,
-                     &s->interrupt_callback, NULL, s->protocol_whitelist);
+                     &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist);
     if (ret)
         goto fail;
 
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index 17f04c0..ca7acc8 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -296,7 +296,7 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
             av_log(s, AV_LOG_TRACE, "Opening: %s", url);
             ret = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
                                        &s->interrupt_callback, &opts,
-                                       s->protocol_whitelist);
+                                       s->protocol_whitelist, s->protocol_blacklist);
             av_dict_free(&opts);
             if (ret)
                 localport += 2;
@@ -665,7 +665,7 @@ static int rtsp_listen(AVFormatContext *s)
 
     if (ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
                                    &s->interrupt_callback, NULL,
-                                   s->protocol_whitelist)) {
+                                   s->protocol_whitelist, s->protocol_blacklist)) {
         av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n");
         return ret;
     }
diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c
index 926795b..0473b01 100644
--- a/libavformat/sapdec.c
+++ b/libavformat/sapdec.c
@@ -87,7 +87,7 @@ static int sap_read_header(AVFormatContext *s)
                 port);
     ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_READ,
                                &s->interrupt_callback, NULL,
-                               s->protocol_whitelist);
+                               s->protocol_whitelist, s->protocol_blacklist);
     if (ret)
         goto fail;
 
@@ -161,7 +161,7 @@ static int sap_read_header(AVFormatContext *s)
     sap->sdp_ctx->pb        = &sap->sdp_pb;
     sap->sdp_ctx->interrupt_callback = s->interrupt_callback;
 
-    if ((ret = ff_copy_whitelists(sap->sdp_ctx, s)) < 0)
+    if ((ret = ff_copy_whiteblacklists(sap->sdp_ctx, s)) < 0)
         goto fail;
 
     ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c
index b2f64b8..0699e3e 100644
--- a/libavformat/sapenc.c
+++ b/libavformat/sapenc.c
@@ -151,7 +151,7 @@ static int sap_write_header(AVFormatContext *s)
             base_port += 2;
         ret = ffurl_open_whitelist(&fd, url, AVIO_FLAG_WRITE,
                                    &s->interrupt_callback, NULL,
-                                   s->protocol_whitelist);
+                                   s->protocol_whitelist, s->protocol_blacklist);
         if (ret) {
             ret = AVERROR(EIO);
             goto fail;
@@ -171,7 +171,7 @@ static int sap_write_header(AVFormatContext *s)
                 "?ttl=%d&connect=1", ttl);
     ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_WRITE,
                                &s->interrupt_callback, NULL,
-                               s->protocol_whitelist);
+                               s->protocol_whitelist, s->protocol_blacklist);
     if (ret) {
         ret = AVERROR(EIO);
         goto fail;
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index da0e222..5333ba8 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -123,7 +123,7 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
             os->tail_out = os->out;
             av_dict_set(&opts, "truncate", "0", 0);
             ret = ffurl_open_whitelist(&os->out, frag->file, AVIO_FLAG_WRITE,
-                                       &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
+                                       &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist, os->ctx->protocol_blacklist);
             av_dict_free(&opts);
             if (ret < 0) {
                 os->out = os->tail_out;
@@ -132,7 +132,7 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
             }
             av_dict_set(&opts, "truncate", "0", 0);
             ffurl_open_whitelist(&os->out2, frag->infofile, AVIO_FLAG_WRITE,
-                                 &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
+                                 &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist, os->ctx->protocol_blacklist);
             av_dict_free(&opts);
             ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
             if (os->out2)
@@ -332,7 +332,7 @@ static int ism_write_header(AVFormatContext *s)
         }
 
         ctx = avformat_alloc_context();
-        if (!ctx || ff_copy_whitelists(ctx, s) < 0) {
+        if (!ctx || ff_copy_whiteblacklists(ctx, s) < 0) {
             ret = AVERROR(ENOMEM);
             goto fail;
         }
@@ -526,7 +526,7 @@ static int ism_flush(AVFormatContext *s, int final)
             continue;
 
         snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
-        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
+        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist);
         if (ret < 0)
             break;
         os->cur_start_pos = os->tail_pos;
diff --git a/libavformat/srtpproto.c b/libavformat/srtpproto.c
index 470f87b..ef87c08 100644
--- a/libavformat/srtpproto.c
+++ b/libavformat/srtpproto.c
@@ -81,7 +81,7 @@ static int srtp_open(URLContext *h, const char *uri, int flags)
                  path, sizeof(path), uri);
     ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path);
     if ((ret = ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
-                                    NULL, h->protocol_whitelist)) < 0)
+                                    NULL, h->protocol_whitelist, h->protocol_blacklist)) < 0)
         goto fail;
 
     h->max_packet_size = FFMIN(s->rtp_hd->max_packet_size,
diff --git a/libavformat/subfile.c b/libavformat/subfile.c
index 8a3c167..fdd328a 100644
--- a/libavformat/subfile.c
+++ b/libavformat/subfile.c
@@ -78,7 +78,7 @@ static int subfile_open(URLContext *h, const char *filename, int flags,
     }
     av_strstart(filename, "subfile:", &filename);
     ret = ffurl_open_whitelist(&c->h, filename, flags, &h->interrupt_callback,
-                               options, h->protocol_whitelist);
+                               options, h->protocol_whitelist, h->protocol_blacklist);
     if (ret < 0)
         return ret;
     c->pos = c->start;
diff --git a/libavformat/tls.c b/libavformat/tls.c
index c625983..2a59aa7 100644
--- a/libavformat/tls.c
+++ b/libavformat/tls.c
@@ -106,5 +106,5 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
 
     return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
                                 &parent->interrupt_callback, options,
-                                parent->protocol_whitelist);
+                                parent->protocol_whitelist, parent->protocol_blacklist);
 }
diff --git a/libavformat/tls_securetransport.c b/libavformat/tls_securetransport.c
index a26b969..253c89c 100644
--- a/libavformat/tls_securetransport.c
+++ b/libavformat/tls_securetransport.c
@@ -83,7 +83,7 @@ static int import_pem(URLContext *h, char *path, CFArrayRef *array)
 
     if ((ret = ffio_open_whitelist(&s, path, AVIO_FLAG_READ,
                                    &h->interrupt_callback, NULL,
-                                   h->protocol_whitelist)) < 0)
+                                   h->protocol_whitelist, h->protocol_blacklist)) < 0)
         goto end;
 
     if ((ret = avio_size(s)) < 0)
diff --git a/libavformat/url.h b/libavformat/url.h
index 95acd27..4ce60cc 100644
--- a/libavformat/url.h
+++ b/libavformat/url.h
@@ -47,6 +47,7 @@ typedef struct URLContext {
     AVIOInterruptCB interrupt_callback;
     int64_t rw_timeout;         /**< maximum time to wait for (network) read/write operation completion, in mcs */
     const char *protocol_whitelist;
+    const char *protocol_blacklist;
 } URLContext;
 
 typedef struct URLProtocol {
@@ -140,7 +141,7 @@ int ffurl_connect(URLContext *uc, AVDictionary **options);
  */
 int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options,
-               const char *whitelist);
+               const char *whitelist, const char* blacklist);
 
 int ffurl_open(URLContext **puc, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options);
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 85702dd..48e5682 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -142,18 +142,21 @@ void av_format_inject_global_side_data(AVFormatContext *s)
     }
 }
 
-int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src)
+int ff_copy_whiteblacklists(AVFormatContext *dst, AVFormatContext *src)
 {
     av_assert0(!dst->codec_whitelist &&
                !dst->format_whitelist &&
-               !dst->protocol_whitelist);
+               !dst->protocol_whitelist &&
+               !dst->protocol_blacklist);
     dst-> codec_whitelist = av_strdup(src->codec_whitelist);
     dst->format_whitelist = av_strdup(src->format_whitelist);
     dst->protocol_whitelist = av_strdup(src->protocol_whitelist);
+    dst->protocol_blacklist = av_strdup(src->protocol_blacklist);
     if (   (src-> codec_whitelist && !dst-> codec_whitelist)
         || (src->  format_whitelist && !dst->  format_whitelist)
-        || (src->protocol_whitelist && !dst->protocol_whitelist)) {
-        av_log(dst, AV_LOG_ERROR, "Failed to duplicate whitelist\n");
+        || (src->protocol_whitelist && !dst->protocol_whitelist)
+        || (src->protocol_blacklist && !dst->protocol_blacklist)) {
+        av_log(dst, AV_LOG_ERROR, "Failed to duplicate black/whitelist\n");
         return AVERROR(ENOMEM);
     }
     return 0;
@@ -460,6 +463,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
         }
     }
 
+    if (!s->protocol_blacklist && s->pb && s->pb->protocol_blacklist) {
+        s->protocol_blacklist = av_strdup(s->pb->protocol_blacklist);
+        if (!s->protocol_blacklist) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
     if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, ',') <= 0) {
         av_log(s, AV_LOG_ERROR, "Format not on whitelist \'%s\'\n", s->format_whitelist);
         ret = AVERROR(EINVAL);
diff --git a/libavformat/version.h b/libavformat/version.h
index 22f2797..7dcce2c 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -30,8 +30,8 @@
 #include "libavutil/version.h"
 
 #define LIBAVFORMAT_VERSION_MAJOR  57
-#define LIBAVFORMAT_VERSION_MINOR  27
-#define LIBAVFORMAT_VERSION_MICRO 102
+#define LIBAVFORMAT_VERSION_MINOR  28
+#define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
-- 
2.7.0



More information about the ffmpeg-devel mailing list