[FFmpeg-devel] [PATCH 2/2] avformat: add protocol_whitelist

Michael Niedermayer michaelni at gmx.at
Sun Jan 24 03:42:47 CET 2016


From: Michael Niedermayer <michael at niedermayer.cc>

TODO: Docs
TODO: version bump

Note to maintainers: update tools

Note, testing and checking for missing changes is needed

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
 ffmpeg_opt.c                      |    4 ++--
 libavdevice/lavfi.c               |    2 +-
 libavformat/async.c               |    2 +-
 libavformat/avformat.h            |    7 ++++++
 libavformat/avio.c                |   44 ++++++++++++++++++++++++++++++++++---
 libavformat/avio.h                |    4 ++++
 libavformat/aviobuf.c             |   16 ++++++++++----
 libavformat/cache.c               |    3 ++-
 libavformat/concat.c              |    5 +++--
 libavformat/crypto.c              |    5 +++--
 libavformat/dashenc.c             |    9 ++++----
 libavformat/ftp.c                 |   10 +++++----
 libavformat/gopher.c              |    4 ++--
 libavformat/hdsenc.c              |   12 +++++-----
 libavformat/hls.c                 |    8 ++++---
 libavformat/hlsenc.c              |   28 +++++++++++------------
 libavformat/hlsproto.c            |   10 +++++----
 libavformat/http.c                |   16 +++++++++-----
 libavformat/icecast.c             |    3 ++-
 libavformat/md5proto.c            |    5 +++--
 libavformat/mmst.c                |    5 +++--
 libavformat/movenc.c              |    2 +-
 libavformat/options_table.h       |    1 +
 libavformat/rtmpcrypt.c           |    5 +++--
 libavformat/rtmpproto.c           |   10 +++++----
 libavformat/rtpproto.c            |   10 ++++++---
 libavformat/rtsp.c                |   20 ++++++++---------
 libavformat/rtspdec.c             |   10 +++++----
 libavformat/sapdec.c              |    5 +++--
 libavformat/sapenc.c              |    9 +++++---
 libavformat/segment.c             |   16 +++++++-------
 libavformat/smoothstreamingenc.c  |   18 ++++++++-------
 libavformat/srtpproto.c           |    3 ++-
 libavformat/subfile.c             |    3 ++-
 libavformat/tee.c                 |    4 +++-
 libavformat/tls.c                 |    5 +++--
 libavformat/tls_securetransport.c |    5 +++--
 libavformat/url.h                 |    5 +++++
 libavformat/utils.c               |   13 +++++++----
 libavformat/webm_chunk.c          |    7 +++---
 40 files changed, 230 insertions(+), 123 deletions(-)

diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index 9b341cf..54a7472 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -1129,12 +1129,12 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV
         if (codec_name) {
             snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i],
                      i != 1 ? "" : "/.avconv", codec_name, preset_name);
-            ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
+            ret = avio_open_whitelist(s, filename, AVIO_FLAG_READ, &int_cb, NULL, "file");
         }
         if (ret < 0) {
             snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i],
                      i != 1 ? "" : "/.avconv", preset_name);
-            ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
+            ret = avio_open_whitelist(s, filename, AVIO_FLAG_READ, &int_cb, NULL, "file");
         }
     }
     return ret;
diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
index 077879e..85027da 100644
--- a/libavdevice/lavfi.c
+++ b/libavdevice/lavfi.c
@@ -144,7 +144,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
     if (lavfi->graph_filename) {
         AVBPrint graph_file_pb;
         AVIOContext *avio = NULL;
-        ret = avio_open(&avio, lavfi->graph_filename, AVIO_FLAG_READ);
+        ret = avio_open_whitelist(&avio, lavfi->graph_filename, AVIO_FLAG_READ, &avctx->interrupt_callback, NULL, avctx->protocol_whitelist);
         if (ret < 0)
             goto end;
         av_bprint_init(&graph_file_pb, 0, AV_BPRINT_SIZE_UNLIMITED);
diff --git a/libavformat/async.c b/libavformat/async.c
index 4308c4b..138ef13 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(&c->inner, arg, flags, &interrupt_callback, options);
+    ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist);
     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 4964263..2fb9130 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1815,6 +1815,13 @@ typedef struct AVFormatContext {
      * Demuxing: Set by user.
      */
     int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
+
+    /**
+     * ',' separated list of allowed protocols.
+     * - encoding: unused
+     * - decoding: set by user through AVOptions (NO direct access)
+     */
+    char *protocol_whitelist;
 } AVFormatContext;
 
 int av_format_get_probe_score(const AVFormatContext *s);
diff --git a/libavformat/avio.c b/libavformat/avio.c
index 05d0557..ad9712d 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -73,7 +73,13 @@ static const AVClass *urlcontext_child_class_next(const AVClass *prev)
     return NULL;
 }
 
-static const AVOption options[] = { { NULL } };
+#define OFFSET(x) offsetof(URLContext,x)
+#define E AV_OPT_FLAG_ENCODING_PARAM
+#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 },
+    { NULL }
+};
 const AVClass ffurl_context_class = {
     .class_name       = "URLContext",
     .item_name        = urlcontext_to_name,
@@ -296,18 +302,43 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
     return AVERROR_PROTOCOL_NOT_FOUND;
 }
 
-int ffurl_open(URLContext **puc, const char *filename, int flags,
-               const AVIOInterruptCB *int_cb, AVDictionary **options)
+int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
+                         const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
 {
+    AVDictionary *tmp_opts = NULL;
+    AVDictionaryEntry *e;
     int ret = ffurl_alloc(puc, filename, flags, int_cb);
     if (ret < 0)
         return ret;
     if (options && (*puc)->prot->priv_data_class &&
         (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
         goto fail;
+
+    if (!options)
+        options = &tmp_opts;
+
+    av_assert0(!whitelist ||
+               !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
+               !strcmp(whitelist, e->value));
+
+    if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
+        goto fail;
+
     if ((ret = av_opt_set_dict(*puc, options)) < 0)
         goto fail;
+
+    whitelist = (*puc)->protocol_whitelist;
+    if (whitelist && av_match_list((*puc)->prot->name, whitelist, ',') <= 0) {
+        av_log(*puc, AV_LOG_ERROR, "Protocol not on whitelist!\n");
+        ret = AVERROR(EINVAL);
+        goto fail;
+    }
+    if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
+        goto fail;
+
     ret = ffurl_connect(*puc, options);
+    av_dict_set(options, "protocol_whitelist", NULL, 0);
+
     if (!ret)
         return 0;
 fail:
@@ -316,6 +347,13 @@ fail:
     return ret;
 }
 
+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);
+}
+
 static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
                                          int size, int size_min,
                                          int (*transfer_func)(URLContext *h,
diff --git a/libavformat/avio.h b/libavformat/avio.h
index c3c0b73..26c39b2 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -595,6 +595,10 @@ int avio_open(AVIOContext **s, const char *url, int flags);
 int avio_open2(AVIOContext **s, const char *url, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options);
 
+int avio_open_whitelist(AVIOContext **s, const char *url, int flags,
+                         const AVIOInterruptCB *int_cb, AVDictionary **options,
+                         const char *whitelist);
+
 /**
  * Close the resource accessed by the AVIOContext s and free it.
  * This function can only be used if s was opened by avio_open().
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index b56d113..041210a 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -919,13 +919,15 @@ int avio_open(AVIOContext **s, const char *filename, int flags)
     return avio_open2(s, filename, flags, NULL, NULL);
 }
 
-int avio_open2(AVIOContext **s, const char *filename, int flags,
-               const AVIOInterruptCB *int_cb, AVDictionary **options)
+int avio_open_whitelist(AVIOContext **s, const char *filename, int flags,
+                         const AVIOInterruptCB *int_cb, AVDictionary **options,
+                         const char *whitelist
+                        )
 {
     URLContext *h;
     int err;
 
-    err = ffurl_open(&h, filename, flags, int_cb, options);
+    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist);
     if (err < 0)
         return err;
     err = ffio_fdopen(s, h);
@@ -936,10 +938,16 @@ int avio_open2(AVIOContext **s, const char *filename, int flags,
     return 0;
 }
 
+int avio_open2(AVIOContext **s, const char *filename, int flags,
+               const AVIOInterruptCB *int_cb, AVDictionary **options)
+{
+    return avio_open_whitelist(s, filename, flags, int_cb, options, NULL);
+}
+
 int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
                        const AVIOInterruptCB *int_cb, AVDictionary **options)
 {
-    return avio_open2(pb, url, flags, int_cb, options);
+    return avio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist);
 }
 
 int avio_close(AVIOContext *s)
diff --git a/libavformat/cache.c b/libavformat/cache.c
index d41161d..8e8b9e8 100644
--- a/libavformat/cache.c
+++ b/libavformat/cache.c
@@ -86,7 +86,8 @@ static int cache_open(URLContext *h, const char *arg, int flags, AVDictionary **
     unlink(buffername);
     av_freep(&buffername);
 
-    return ffurl_open(&c->inner, arg, flags, &h->interrupt_callback, options);
+    return ffurl_open_whitelist(&c->inner, arg, flags, &h->interrupt_callback,
+                                options, h->protocol_whitelist);
 }
 
 static int add_entry(URLContext *h, const unsigned char *buf, int size)
diff --git a/libavformat/concat.c b/libavformat/concat.c
index 7bcc279..b2fa30d 100644
--- a/libavformat/concat.c
+++ b/libavformat/concat.c
@@ -97,8 +97,9 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags)
         uri += len + strspn(uri + len, AV_CAT_SEPARATOR);
 
         /* creating URLContext */
-        if ((err = ffurl_open(&uc, node_uri, flags,
-                              &h->interrupt_callback, NULL)) < 0)
+        err = ffurl_open_whitelist(&uc, node_uri, flags,
+                                   &h->interrupt_callback, NULL, h->protocol_whitelist);
+        if (err < 0)
             break;
 
         /* creating size */
diff --git a/libavformat/crypto.c b/libavformat/crypto.c
index f56ee4e..b1871fe 100644
--- a/libavformat/crypto.c
+++ b/libavformat/crypto.c
@@ -136,8 +136,9 @@ static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary
             goto err;
     }
 
-    if ((ret = ffurl_open(&c->hd, nested_url, flags,
-                          &h->interrupt_callback, options)) < 0) {
+    if ((ret = ffurl_open_whitelist(&c->hd, nested_url, flags,
+                                    &h->interrupt_callback, options,
+                                    h->protocol_whitelist)) < 0) {
         av_log(h, AV_LOG_ERROR, "Unable to open resource: %s\n", nested_url);
         goto err;
     }
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 4509ee4..734ac1f 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -448,7 +448,8 @@ static int write_manifest(AVFormatContext *s, int final)
     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
 
     snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
+                              &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
         return ret;
@@ -648,7 +649,7 @@ static int dash_write_header(AVFormatContext *s)
             dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
         }
         snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
-        ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
         if (ret < 0)
             goto fail;
         os->init_start_pos = 0;
@@ -755,7 +756,7 @@ static void find_index_range(AVFormatContext *s, const char *full_path,
     URLContext *fd;
     int ret;
 
-    ret = ffurl_open(&fd, full_path, AVIO_FLAG_READ, &s->interrupt_callback, NULL);
+    ret = ffurl_open_whitelist(&fd, full_path, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0)
         return;
     if (ffurl_seek(fd, pos, SEEK_SET) != pos) {
@@ -838,7 +839,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
             dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
             snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
             snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
-            ret = ffurl_open(&os->out, temp_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+            ret = ffurl_open_whitelist(&os->out, temp_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
             if (ret < 0)
                 break;
             write_styp(os->ctx->pb);
diff --git a/libavformat/ftp.c b/libavformat/ftp.c
index 4526dd7..1370ced 100644
--- a/libavformat/ftp.c
+++ b/libavformat/ftp.c
@@ -537,8 +537,9 @@ static int ftp_connect_control_connection(URLContext *h)
         if (s->rw_timeout != -1) {
             av_dict_set_int(&opts, "timeout", s->rw_timeout, 0);
         } /* if option is not given, don't pass it and let tcp use its own default */
-        err = ffurl_open(&s->conn_control, buf, AVIO_FLAG_READ_WRITE,
-                         &h->interrupt_callback, &opts);
+        err = ffurl_open_whitelist(&s->conn_control, buf, AVIO_FLAG_READ_WRITE,
+                                   &h->interrupt_callback, &opts,
+                                   h->protocol_whitelist);
         av_dict_free(&opts);
         if (err < 0) {
             av_log(h, AV_LOG_ERROR, "Cannot open control connection\n");
@@ -590,8 +591,9 @@ static int ftp_connect_data_connection(URLContext *h)
         if (s->rw_timeout != -1) {
             av_dict_set_int(&opts, "timeout", s->rw_timeout, 0);
         } /* if option is not given, don't pass it and let tcp use its own default */
-        err = ffurl_open(&s->conn_data, buf, h->flags,
-                         &h->interrupt_callback, &opts);
+        err = ffurl_open_whitelist(&s->conn_data, buf, h->flags,
+                                   &h->interrupt_callback, &opts,
+                                   h->protocol_whitelist);
         av_dict_free(&opts);
         if (err < 0)
             return err;
diff --git a/libavformat/gopher.c b/libavformat/gopher.c
index a5340d2..835ad7f 100644
--- a/libavformat/gopher.c
+++ b/libavformat/gopher.c
@@ -93,8 +93,8 @@ static int gopher_open(URLContext *h, const char *uri, int flags)
     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
 
     s->hd = NULL;
-    err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE,
-                     &h->interrupt_callback, NULL);
+    err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
+                               &h->interrupt_callback, NULL, h->protocol_whitelist);
     if (err < 0)
         goto fail;
 
diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c
index 7670185..e9a03a8 100644
--- a/libavformat/hdsenc.c
+++ b/libavformat/hdsenc.c
@@ -169,8 +169,8 @@ static int write_manifest(AVFormatContext *s, int final)
 
     snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename);
     snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
+                     &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
         return ret;
@@ -238,8 +238,8 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
              "%s/stream%d.abst", s->filename, index);
     snprintf(temp_filename, sizeof(temp_filename),
              "%s/stream%d.abst.tmp", s->filename, index);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
+                     &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
         return ret;
@@ -289,8 +289,8 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
 static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
 {
     int ret, i;
-    ret = avio_open2(&os->out, os->temp_filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&os->out, os->temp_filename, AVIO_FLAG_WRITE,
+                     &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0)
         return ret;
     avio_wb32(os->out, 0);
diff --git a/libavformat/hls.c b/libavformat/hls.c
index 846d884..a800cb0 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -180,6 +180,7 @@ struct variant {
 
 typedef struct HLSContext {
     AVClass *class;
+    AVFormatContext *avfmt;
     int n_variants;
     struct variant **variants;
     int n_playlists;
@@ -626,7 +627,7 @@ static int open_url(HLSContext *c, URLContext **uc, const char *url, AVDictionar
     av_dict_copy(&tmp, c->avio_opts, 0);
     av_dict_copy(&tmp, opts, 0);
 
-    ret = ffurl_open(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+    ret = ffurl_open_whitelist(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp, c->avfmt->protocol_whitelist);
     if( ret >= 0) {
         // update cookies on http response with setcookies.
         URLContext *u = *uc;
@@ -671,8 +672,8 @@ static int parse_playlist(HLSContext *c, const char *url,
         av_dict_set(&opts, "headers", c->headers, 0);
         av_dict_set(&opts, "http_proxy", c->http_proxy, 0);
 
-        ret = avio_open2(&in, url, AVIO_FLAG_READ,
-                         c->interrupt_callback, &opts);
+        ret = avio_open_whitelist(&in, url, AVIO_FLAG_READ,
+                         c->interrupt_callback, &opts, c->avfmt->protocol_whitelist);
         av_dict_free(&opts);
         if (ret < 0)
             return ret;
@@ -1509,6 +1510,7 @@ static int hls_read_header(AVFormatContext *s)
     HLSContext *c = s->priv_data;
     int ret = 0, i, j, stream_offset = 0;
 
+    c->avfmt = s;
     c->interrupt_callback = &s->interrupt_callback;
     c->strict_std_compliance = s->strict_std_compliance;
 
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index f2d7a52..983db30 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -209,8 +209,8 @@ static int hls_encryption_start(AVFormatContext *s)
     AVIOContext *pb;
     uint8_t key[KEYSIZE];
 
-    if ((ret = avio_open2(&pb, hls->key_info_file, AVIO_FLAG_READ,
-                           &s->interrupt_callback, NULL)) < 0) {
+    if ((ret = avio_open_whitelist(&pb, hls->key_info_file, AVIO_FLAG_READ,
+                           &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
         av_log(hls, AV_LOG_ERROR,
                 "error opening key info file %s\n", hls->key_info_file);
         return ret;
@@ -237,8 +237,8 @@ static int hls_encryption_start(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    if ((ret = avio_open2(&pb, hls->key_file, AVIO_FLAG_READ,
-                           &s->interrupt_callback, NULL)) < 0) {
+    if ((ret = avio_open_whitelist(&pb, hls->key_file, AVIO_FLAG_READ,
+                           &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
         av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", hls->key_file);
         return ret;
     }
@@ -394,8 +394,8 @@ static int hls_window(AVFormatContext *s, int last)
 
     set_http_options(&options, hls);
     snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
-    if ((ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, &options)) < 0)
+    if ((ret = avio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
+                          &s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
         goto fail;
 
     for (en = hls->segments; en; en = en->next) {
@@ -445,8 +445,8 @@ static int hls_window(AVFormatContext *s, int last)
         avio_printf(out, "#EXT-X-ENDLIST\n");
 
     if( hls->vtt_m3u8_name ) {
-        if ((ret = avio_open2(&sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, &options)) < 0)
+        if ((ret = avio_open_whitelist(&sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE,
+                          &s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
             goto fail;
         avio_printf(sub_out, "#EXTM3U\n");
         avio_printf(sub_out, "#EXT-X-VERSION:%d\n", version);
@@ -542,20 +542,20 @@ static int hls_start(AVFormatContext *s)
             err = AVERROR(ENOMEM);
             goto fail;
         }
-        err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
-                         &s->interrupt_callback, &options);
+        err = avio_open_whitelist(&oc->pb, filename, AVIO_FLAG_WRITE,
+                         &s->interrupt_callback, &options, s->protocol_whitelist);
         av_free(filename);
         av_dict_free(&options);
         if (err < 0)
             return err;
     } else
-        if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, &options)) < 0)
+        if ((err = avio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+                          &s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
             goto fail;
     if (c->vtt_basename) {
         set_http_options(&options, c);
-        if ((err = avio_open2(&vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE,
-                         &s->interrupt_callback, &options)) < 0)
+        if ((err = avio_open_whitelist(&vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE,
+                         &s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
             goto fail;
     }
     av_dict_free(&options);
diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c
index 92843df..bb8f6db 100644
--- a/libavformat/hlsproto.c
+++ b/libavformat/hlsproto.c
@@ -116,8 +116,9 @@ static int parse_playlist(URLContext *h, const char *url)
     char line[1024];
     const char *ptr;
 
-    if ((ret = avio_open2(&in, url, AVIO_FLAG_READ,
-                          &h->interrupt_callback, NULL)) < 0)
+    if ((ret = avio_open_whitelist(&in, url, AVIO_FLAG_READ,
+                                   &h->interrupt_callback, NULL,
+                                   h->protocol_whitelist)) < 0)
         return ret;
 
     read_chomp_line(in, line, sizeof(line));
@@ -303,8 +304,9 @@ retry:
     }
     url = s->segments[s->cur_seq_no - s->start_seq_no]->url,
     av_log(h, AV_LOG_DEBUG, "opening %s\n", url);
-    ret = ffurl_open(&s->seg_hd, url, AVIO_FLAG_READ,
-                     &h->interrupt_callback, NULL);
+    ret = ffurl_open_whitelist(&s->seg_hd, url, AVIO_FLAG_READ,
+                               &h->interrupt_callback, NULL,
+                               h->protocol_whitelist);
     if (ret < 0) {
         if (ff_check_interrupt(&h->interrupt_callback))
             return AVERROR_EXIT;
diff --git a/libavformat/http.c b/libavformat/http.c
index a1f1807..96561e4 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -219,8 +219,9 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
     ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL);
 
     if (!s->hd) {
-        err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE,
-                         &h->interrupt_callback, options);
+        err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
+                                   &h->interrupt_callback, options,
+                                   h->protocol_whitelist);
         if (err < 0)
             return err;
     }
@@ -453,8 +454,10 @@ static int http_listen(URLContext *h, const char *uri, int flags,
                 NULL);
     if ((ret = av_dict_set_int(options, "listen", s->listen, 0)) < 0)
         goto fail;
-    if ((ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
-                          &h->interrupt_callback, options)) < 0)
+    if ((ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
+                                    &h->interrupt_callback, options,
+                                    h->protocol_whitelist
+                                   )) < 0)
         goto fail;
     s->handshake_step = LOWER_PROTO;
     if (s->listen == HTTP_SINGLE) { /* single client */
@@ -1575,8 +1578,9 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags)
     ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port,
                 NULL);
 redo:
-    ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
-                     &h->interrupt_callback, NULL);
+    ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
+                               &h->interrupt_callback, NULL,
+                               h->protocol_whitelist);
     if (ret < 0)
         return ret;
 
diff --git a/libavformat/icecast.c b/libavformat/icecast.c
index f4dca6f..a3b9a36 100644
--- a/libavformat/icecast.c
+++ b/libavformat/icecast.c
@@ -164,7 +164,8 @@ static int icecast_open(URLContext *h, const char *uri, int flags)
     // Build new URI for passing to http protocol
     ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path);
     // Finally open http proto handler
-    ret = ffurl_open(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict);
+    ret = ffurl_open_whitelist(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL,
+                               &opt_dict, h->protocol_whitelist);
 
 cleanup:
     av_freep(&user);
diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c
index 6af0a6e..9a092e4 100644
--- a/libavformat/md5proto.c
+++ b/libavformat/md5proto.c
@@ -69,8 +69,9 @@ static int md5_close(URLContext *h)
     av_strstart(filename, "md5:", &filename);
 
     if (*filename) {
-        err = ffurl_open(&out, filename, AVIO_FLAG_WRITE,
-                         &h->interrupt_callback, NULL);
+        err = ffurl_open_whitelist(&out, filename, AVIO_FLAG_WRITE,
+                                   &h->interrupt_callback, NULL,
+                                   h->protocol_whitelist);
         if (err)
             return err;
         err = ffurl_write(out, buf, i*2+1);
diff --git a/libavformat/mmst.c b/libavformat/mmst.c
index aa245ea..21cf2a6 100644
--- a/libavformat/mmst.c
+++ b/libavformat/mmst.c
@@ -528,8 +528,9 @@ static int mms_open(URLContext *h, const char *uri, int flags)
 
     // establish tcp connection.
     ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
-    err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
-                     &h->interrupt_callback, NULL);
+    err = ffurl_open_whitelist(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
+                               &h->interrupt_callback, NULL,
+                               h->protocol_whitelist);
     if (err)
         goto fail;
 
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 1aff5c5..41f9cca 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5534,7 +5534,7 @@ static int shift_data(AVFormatContext *s)
      * writing, so we re-open the same output, but for reading. It also avoids
      * a read/seek/write/seek back and forth. */
     avio_flush(s->pb);
-    ret = avio_open(&read_pb, s->filename, AVIO_FLAG_READ);
+    ret = avio_open_whitelist(&read_pb, s->filename, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
                "the second pass (faststart)\n", s->filename);
diff --git a/libavformat/options_table.h b/libavformat/options_table.h
index cc64bea..8926fe5 100644
--- a/libavformat/options_table.h
+++ b/libavformat/options_table.h
@@ -100,6 +100,7 @@ static const AVOption avformat_options[] = {
 {"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, CHAR_MIN, CHAR_MAX, D|E},
 {"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 },
 {NULL},
 };
 
diff --git a/libavformat/rtmpcrypt.c b/libavformat/rtmpcrypt.c
index a0c914f..811c74c 100644
--- a/libavformat/rtmpcrypt.c
+++ b/libavformat/rtmpcrypt.c
@@ -264,8 +264,9 @@ static int rtmpe_open(URLContext *h, const char *uri, int flags)
     }
 
     /* open the tcp or ffrtmphttp connection */
-    if ((ret = ffurl_open(&rt->stream, url, AVIO_FLAG_READ_WRITE,
-                          &h->interrupt_callback, NULL)) < 0) {
+    if ((ret = ffurl_open_whitelist(&rt->stream, url, AVIO_FLAG_READ_WRITE,
+                                    &h->interrupt_callback, NULL,
+                                    h->protocol_whitelist)) < 0) {
         rtmpe_close(h);
         return ret;
     }
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index bd1c38a..a5485ab 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -1118,8 +1118,9 @@ static int rtmp_calc_swfhash(URLContext *s)
     int ret = 0;
 
     /* Get the SWF player file. */
-    if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
-                          &s->interrupt_callback, NULL)) < 0) {
+    if ((ret = ffurl_open_whitelist(&stream, rt->swfverify, AVIO_FLAG_READ,
+                                    &s->interrupt_callback, NULL,
+                                    s->protocol_whitelist)) < 0) {
         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
         goto fail;
     }
@@ -2647,8 +2648,9 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
     }
 
 reconnect:
-    if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
-                          &s->interrupt_callback, &opts)) < 0) {
+    if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
+                                    &s->interrupt_callback, &opts,
+                                    s->protocol_whitelist)) < 0) {
         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
         goto fail;
     }
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index e0aa23e..538a7b2 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -380,7 +380,8 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
         build_udp_url(s, buf, sizeof(buf),
                       hostname, rtp_port, s->local_rtpport,
                       sources, block);
-        if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
+        if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
+                                 NULL, h->protocol_whitelist) < 0)
             goto fail;
         s->local_rtpport = ff_udp_get_local_port(s->rtp_hd);
         if(s->local_rtpport == 65535) {
@@ -392,7 +393,9 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
             build_udp_url(s, buf, sizeof(buf),
                           hostname, s->rtcp_port, s->local_rtcpport,
                           sources, block);
-            if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) {
+            if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags,
+                                     &h->interrupt_callback, NULL,
+                                     h->protocol_whitelist) < 0) {
                 s->local_rtpport = s->local_rtcpport = -1;
                 continue;
             }
@@ -401,7 +404,8 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
         build_udp_url(s, buf, sizeof(buf),
                       hostname, s->rtcp_port, s->local_rtcpport,
                       sources, block);
-        if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
+        if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags, &h->interrupt_callback,
+                                 NULL, h->protocol_whitelist) < 0)
             goto fail;
         break;
     }
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 39539e9..d710469 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -1468,8 +1468,8 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
                             "?localport=%d", j);
                 /* we will use two ports per rtp stream (rtp and rtcp) */
                 j += 2;
-                err = ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
-                                 &s->interrupt_callback, &opts);
+                err = ffurl_open_whitelist(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
+                                 &s->interrupt_callback, &opts, s->protocol_whitelist);
 
                 av_dict_free(&opts);
 
@@ -1611,8 +1611,8 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
                         namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
             ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
                         port, "%s", optbuf);
-            if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                           &s->interrupt_callback, NULL) < 0) {
+            if (ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
+                           &s->interrupt_callback, NULL, s->protocol_whitelist) < 0) {
                 err = AVERROR_INVALIDDATA;
                 goto fail;
             }
@@ -1800,8 +1800,8 @@ redirect:
         ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
                     host, port,
                     "?timeout=%d", rt->stimeout);
-        if ((ret = ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
-                       &s->interrupt_callback, NULL)) < 0) {
+        if ((ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
+                       &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
             err = ret;
             goto fail;
         }
@@ -2316,8 +2316,8 @@ static int sdp_read_header(AVFormatContext *s)
             append_source_addrs(url, sizeof(url), "block",
                                 rtsp_st->nb_exclude_source_addrs,
                                 rtsp_st->exclude_source_addrs);
-            err = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                           &s->interrupt_callback, &opts);
+            err = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
+                           &s->interrupt_callback, &opts, s->protocol_whitelist);
 
             av_dict_free(&opts);
 
@@ -2386,8 +2386,8 @@ static int rtp_read_header(AVFormatContext *s)
     if (!ff_network_init())
         return AVERROR(EIO);
 
-    ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ,
-                     &s->interrupt_callback, NULL);
+    ret = ffurl_open_whitelist(&in, s->filename, AVIO_FLAG_READ,
+                     &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret)
         goto fail;
 
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index 77389b6..17f04c0 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -294,8 +294,9 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
             av_dict_set(&opts, "buffer_size", buf, 0);
             ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL);
             av_log(s, AV_LOG_TRACE, "Opening: %s", url);
-            ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                             &s->interrupt_callback, &opts);
+            ret = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
+                                       &s->interrupt_callback, &opts,
+                                       s->protocol_whitelist);
             av_dict_free(&opts);
             if (ret)
                 localport += 2;
@@ -662,8 +663,9 @@ static int rtsp_listen(AVFormatContext *s)
     ff_url_join(tcpname, sizeof(tcpname), lower_proto, NULL, host, port,
                 "?listen&listen_timeout=%d", rt->initial_timeout * 1000);
 
-    if (ret = ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
-                         &s->interrupt_callback, NULL)) {
+    if (ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
+                                   &s->interrupt_callback, NULL,
+                                   s->protocol_whitelist)) {
         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 808ae14..926795b 100644
--- a/libavformat/sapdec.c
+++ b/libavformat/sapdec.c
@@ -85,8 +85,9 @@ static int sap_read_header(AVFormatContext *s)
 
     ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d",
                 port);
-    ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ,
-                     &s->interrupt_callback, NULL);
+    ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_READ,
+                               &s->interrupt_callback, NULL,
+                               s->protocol_whitelist);
     if (ret)
         goto fail;
 
diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c
index 07fbf48..b2f64b8 100644
--- a/libavformat/sapenc.c
+++ b/libavformat/sapenc.c
@@ -149,7 +149,9 @@ static int sap_write_header(AVFormatContext *s)
                     "?ttl=%d", ttl);
         if (!same_port)
             base_port += 2;
-        ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+        ret = ffurl_open_whitelist(&fd, url, AVIO_FLAG_WRITE,
+                                   &s->interrupt_callback, NULL,
+                                   s->protocol_whitelist);
         if (ret) {
             ret = AVERROR(EIO);
             goto fail;
@@ -167,8 +169,9 @@ static int sap_write_header(AVFormatContext *s)
 
     ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port,
                 "?ttl=%d&connect=1", ttl);
-    ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_WRITE,
+                               &s->interrupt_callback, NULL,
+                               s->protocol_whitelist);
     if (ret) {
         ret = AVERROR(EIO);
         goto fail;
diff --git a/libavformat/segment.c b/libavformat/segment.c
index 0c1f633..c13b91c 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -237,8 +237,8 @@ static int segment_start(AVFormatContext *s, int write_header)
     if ((err = set_segment_filename(s)) < 0)
         return err;
 
-    if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, NULL)) < 0) {
+    if ((err = avio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+                                   &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
         av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
         return err;
     }
@@ -263,8 +263,8 @@ static int segment_list_open(AVFormatContext *s)
     int ret;
 
     snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
-    ret = avio_open2(&seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE,
+                     &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
         return ret;
@@ -690,8 +690,8 @@ static int seg_write_header(AVFormatContext *s)
         goto fail;
 
     if (seg->write_header_trailer) {
-        if ((ret = avio_open2(&oc->pb, seg->header_filename ? seg->header_filename : oc->filename, AVIO_FLAG_WRITE,
-                              &s->interrupt_callback, NULL)) < 0) {
+        if ((ret = avio_open_whitelist(&oc->pb, seg->header_filename ? seg->header_filename : oc->filename, AVIO_FLAG_WRITE,
+                              &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
             av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
             goto fail;
         }
@@ -734,8 +734,8 @@ static int seg_write_header(AVFormatContext *s)
         } else {
             close_null_ctxp(&oc->pb);
         }
-        if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                              &s->interrupt_callback, NULL)) < 0)
+        if ((ret = avio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+                              &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0)
             goto fail;
         if (!seg->individual_header_trailer)
             oc->pb->seekable = 0;
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index a26f8fe..9b890e0 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -121,7 +121,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
             AVDictionary *opts = NULL;
             os->tail_out = os->out;
             av_dict_set(&opts, "truncate", "0", 0);
-            ret = ffurl_open(&os->out, frag->file, AVIO_FLAG_READ_WRITE, &os->ctx->interrupt_callback, &opts);
+            ret = ffurl_open_whitelist(&os->out, frag->file, AVIO_FLAG_READ_WRITE,
+                                       &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
             av_dict_free(&opts);
             if (ret < 0) {
                 os->out = os->tail_out;
@@ -129,7 +130,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
                 return ret;
             }
             av_dict_set(&opts, "truncate", "0", 0);
-            ffurl_open(&os->out2, frag->infofile, AVIO_FLAG_READ_WRITE, &os->ctx->interrupt_callback, &opts);
+            ffurl_open_whitelist(&os->out2, frag->infofile, AVIO_FLAG_READ_WRITE,
+                                 &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
             av_dict_free(&opts);
             ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
             if (os->out2)
@@ -220,7 +222,7 @@ static int write_manifest(AVFormatContext *s, int final)
 
     snprintf(filename, sizeof(filename), "%s/Manifest", s->filename);
     snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
         return ret;
@@ -329,7 +331,7 @@ static int ism_write_header(AVFormatContext *s)
         }
 
         ctx = avformat_alloc_context();
-        if (!ctx) {
+        if (!ctx || ff_copy_whitelists(ctx, s) < 0) {
             ret = AVERROR(ENOMEM);
             goto fail;
         }
@@ -409,7 +411,7 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta
     AVIOContext *in;
     int ret;
     uint32_t len;
-    if ((ret = avio_open2(&in, filename, AVIO_FLAG_READ, &s->interrupt_callback, NULL)) < 0)
+    if ((ret = avio_open_whitelist(&in, filename, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0)
         return ret;
     ret = AVERROR(EIO);
     *moof_size = avio_rb32(in);
@@ -486,9 +488,9 @@ static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile
 {
     AVIOContext *in, *out;
     int ret = 0;
-    if ((ret = avio_open2(&in, infile, AVIO_FLAG_READ, &s->interrupt_callback, NULL)) < 0)
+    if ((ret = avio_open_whitelist(&in, infile, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0)
         return ret;
-    if ((ret = avio_open2(&out, outfile, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL)) < 0) {
+    if ((ret = avio_open_whitelist(&out, outfile, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
         avio_close(in);
         return ret;
     }
@@ -523,7 +525,7 @@ static int ism_flush(AVFormatContext *s, int final)
             continue;
 
         snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
-        ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
         if (ret < 0)
             break;
         os->cur_start_pos = os->tail_pos;
diff --git a/libavformat/srtpproto.c b/libavformat/srtpproto.c
index 0124696..460799a 100644
--- a/libavformat/srtpproto.c
+++ b/libavformat/srtpproto.c
@@ -80,7 +80,8 @@ static int srtp_open(URLContext *h, const char *uri, int flags)
     av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
                  path, sizeof(path), uri);
     ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path);
-    if ((ret = ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL)) < 0)
+    if ((ret = ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
+                                    NULL, h->protocol_whitelist)) < 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 0e84384..a8baf14 100644
--- a/libavformat/subfile.c
+++ b/libavformat/subfile.c
@@ -77,7 +77,8 @@ static int subfile_open(URLContext *h, const char *filename, int flags,
         return AVERROR(EINVAL);
     }
     av_strstart(filename, "subfile:", &filename);
-    ret = ffurl_open(&c->h, filename, flags, &h->interrupt_callback, options);
+    ret = ffurl_open_whitelist(&c->h, filename, flags, &h->interrupt_callback,
+                               options, h->protocol_whitelist);
     if (ret < 0)
         return ret;
     c->pos = c->start;
diff --git a/libavformat/tee.c b/libavformat/tee.c
index 8c54d32..0e9f097 100644
--- a/libavformat/tee.c
+++ b/libavformat/tee.c
@@ -226,7 +226,9 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
     }
 
     if (!(avf2->oformat->flags & AVFMT_NOFILE)) {
-        if ((ret = avio_open(&avf2->pb, filename, AVIO_FLAG_WRITE)) < 0) {
+        if ((ret = avio_open_whitelist(&avf2->pb, filename, AVIO_FLAG_WRITE,
+                                       &avf->interrupt_callback, NULL,
+                                       avf->protocol_whitelist)) < 0) {
             av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n",
                    slave, av_err2str(ret));
             goto end;
diff --git a/libavformat/tls.c b/libavformat/tls.c
index 9802a70..c625983 100644
--- a/libavformat/tls.c
+++ b/libavformat/tls.c
@@ -104,6 +104,7 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
                     proxy_port, "/%s", dest);
     }
 
-    return ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
-                      &parent->interrupt_callback, options);
+    return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
+                                &parent->interrupt_callback, options,
+                                parent->protocol_whitelist);
 }
diff --git a/libavformat/tls_securetransport.c b/libavformat/tls_securetransport.c
index 6ad266a..6e0d497 100644
--- a/libavformat/tls_securetransport.c
+++ b/libavformat/tls_securetransport.c
@@ -80,8 +80,9 @@ static int import_pem(URLContext *h, char *path, CFArrayRef *array)
         goto end;
     }
 
-    if ((ret = avio_open2(&s, path, AVIO_FLAG_READ,
-                          &h->interrupt_callback, NULL)) < 0)
+    if ((ret = avio_open_whitelist(&s, path, AVIO_FLAG_READ,
+                                   &h->interrupt_callback, NULL,
+                                   h->protocol_whitelist)) < 0)
         goto end;
 
     if ((ret = avio_size(s)) < 0)
diff --git a/libavformat/url.h b/libavformat/url.h
index 391e3bc..6e5b218 100644
--- a/libavformat/url.h
+++ b/libavformat/url.h
@@ -47,6 +47,7 @@ typedef struct URLContext {
     int is_connected;
     AVIOInterruptCB interrupt_callback;
     int64_t rw_timeout;         /**< maximum time to wait for (network) read/write operation completion, in mcs */
+    char *protocol_whitelist;
 } URLContext;
 
 typedef struct URLProtocol {
@@ -138,6 +139,10 @@ int ffurl_connect(URLContext *uc, AVDictionary **options);
  * @return >= 0 in case of success, a negative value corresponding to an
  * AVERROR code in case of failure
  */
+int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
+               const AVIOInterruptCB *int_cb, AVDictionary **options,
+               const char *whitelist);
+
 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 b6457b0..7f30829 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -139,11 +139,15 @@ void av_format_inject_global_side_data(AVFormatContext *s)
 
 int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src)
 {
-    av_assert0(!dst->codec_whitelist && !dst->format_whitelist);
+    av_assert0(!dst->codec_whitelist &&
+               !dst->format_whitelist &&
+               !dst->protocol_whitelist);
     dst-> codec_whitelist = av_strdup(src->codec_whitelist);
     dst->format_whitelist = av_strdup(src->format_whitelist);
+    dst->protocol_whitelist = av_strdup(src->protocol_whitelist);
     if (   (src-> codec_whitelist && !dst-> codec_whitelist)
-        || (src->format_whitelist && !dst->format_whitelist)) {
+        || (src->  format_whitelist && !dst->  format_whitelist)
+        || (src->protocol_whitelist && !dst->protocol_whitelist)) {
         av_log(dst, AV_LOG_ERROR, "Failed to duplicate whitelist\n");
         return AVERROR(ENOMEM);
     }
@@ -352,8 +356,9 @@ static int init_input(AVFormatContext *s, const char *filename,
         (!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
         return score;
 
-    if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags,
-                          &s->interrupt_callback, options)) < 0)
+    if ((ret = avio_open_whitelist(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags,
+                                   &s->interrupt_callback, options,
+                                   s->protocol_whitelist)) < 0)
         return ret;
     if (s->iformat)
         return 0;
diff --git a/libavformat/webm_chunk.c b/libavformat/webm_chunk.c
index 3dfef4b..8188219 100644
--- a/libavformat/webm_chunk.c
+++ b/libavformat/webm_chunk.c
@@ -125,8 +125,8 @@ static int webm_chunk_write_header(AVFormatContext *s)
     ret = get_chunk_filename(s, 1, oc->filename);
     if (ret < 0)
         return ret;
-    ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+                              &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0)
         return ret;
 
@@ -169,7 +169,8 @@ static int chunk_end(AVFormatContext *s)
     ret = get_chunk_filename(s, 0, filename);
     if (ret < 0)
         goto fail;
-    ret = avio_open2(&pb, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+    ret = avio_open_whitelist(&pb, filename, AVIO_FLAG_WRITE,
+                              &s->interrupt_callback, NULL, s->protocol_whitelist);
     if (ret < 0)
         goto fail;
     avio_write(pb, buffer, buffer_size);
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list