Skip to content

Commit

Permalink
avformat: Add a protocol blacklisting API
Browse files Browse the repository at this point in the history
Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
  • Loading branch information
dwbuiten committed Mar 4, 2016
1 parent 500cb98 commit 9362973
Show file tree
Hide file tree
Showing 42 changed files with 116 additions and 64 deletions.
1 change: 1 addition & 0 deletions Changelog
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ version <next>:
- datascope filter
- bench and abench filters
- ciescope filter
- protocol blacklisting API


version 3.0:
Expand Down
3 changes: 3 additions & 0 deletions doc/APIchanges
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libavformat/async.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 9 additions & 2 deletions libavformat/avformat.h
Original file line number Diff line number Diff line change
Expand Up @@ -1832,11 +1832,11 @@ typedef struct AVFormatContext {
#endif

/**
* ',' separated list of allowed protocols.
* ',' separated list of disallowed protocols.
* - encoding: unused
* - decoding: set by user through AVOptions (NO direct access)
*/
char *protocol_whitelist;
char *protocol_blacklist;

/*
* A callback for opening new IO streams.
Expand Down Expand Up @@ -1865,6 +1865,13 @@ typedef struct AVFormatContext {
* A callback for closing the streams opened with AVFormatContext.io_open().
*/
void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);

/**
* ',' separated list of disallowed protocols.
* - encoding: unused
* - decoding: set by user through AVOptions (NO direct access)
*/
char *protocol_blacklist;
} AVFormatContext;

int av_format_get_probe_score(const AVFormatContext *s);
Expand Down
2 changes: 1 addition & 1 deletion libavformat/avidec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
22 changes: 20 additions & 2 deletions libavformat/avio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
};

Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions libavformat/avio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion libavformat/avio_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
13 changes: 9 additions & 4 deletions libavformat/aviobuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion libavformat/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion libavformat/concat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion libavformat/concatdec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down
2 changes: 1 addition & 1 deletion libavformat/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions libavformat/ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion libavformat/gopher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion libavformat/hls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions libavformat/hlsproto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -307,7 +307,7 @@ static int hls_read(URLContext *h, uint8_t *buf, int size)
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;
Expand Down
6 changes: 3 additions & 3 deletions libavformat/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion libavformat/icecast.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion libavformat/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion libavformat/md5proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion libavformat/mmst.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion libavformat/mpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion libavformat/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions libavformat/options_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -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},
};

Expand Down
2 changes: 1 addition & 1 deletion libavformat/rdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 9362973

Please sign in to comment.