diff --git a/DOCS/interface-changes/tls-verify-default.txt b/DOCS/interface-changes/tls-verify-default.txt new file mode 100644 index 0000000000000..86251d555075e --- /dev/null +++ b/DOCS/interface-changes/tls-verify-default.txt @@ -0,0 +1 @@ +change `--tls-verify` default to `yes` diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index e2cf9f0714c76..e0dc6e4ba3942 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -5666,9 +5666,16 @@ Network Certificate authority database file for use with TLS. (Silently fails with older FFmpeg versions.) -``--tls-verify`` - Verify peer certificates when using TLS (e.g. with ``https://...``). - (Silently fails with older FFmpeg versions.) +``--tls-verify=`` + Verify peer certificates when using TLS (e.g. with ``https://...``) + (default: yes*). Disabling this option allows man-in-the-middle attacks + to silently substitute the content of an HTTPS stream and is only + recommended as a per-stream override when verification fails for a + known-good reason (e.g. an outdated CA bundle, a corporate proxy, a + development server with a self-signed certificate). + + This is disabled by default, if mpv is built without libcurl and + libavformat is older than 63.0.100. ``--tls-cert-file`` A file containing a certificate to use in the handshake with the diff --git a/stream/network.c b/stream/network.c index b2c7ce90f0fe7..95a0735ba3952 100644 --- a/stream/network.c +++ b/stream/network.c @@ -17,6 +17,8 @@ #include +#include + #include "network.h" #include "options/m_option.h" @@ -41,5 +43,8 @@ const struct m_sub_options mp_network_conf = { .defaults = &(const struct mp_network_opts){ .useragent = "libmpv", .timeout = 60, +#if HAVE_LIBCURL || LIBAVFORMAT_VERSION_MAJOR >= 63 + .tls_verify = true, +#endif }, }; diff --git a/stream/stream_curl.c b/stream/stream_curl.c index f0e8dcedb634a..b466e271cef06 100644 --- a/stream/stream_curl.c +++ b/stream/stream_curl.c @@ -599,6 +599,20 @@ static void start_request(struct priv *p) curl_multi_add_handle(p->ctx->multi, p->curl); } +static void log_curl_error(struct priv *p, const char *what, CURLcode code) +{ + MP_ERR(p, "%s: %s\n", what, curl_easy_strerror(code)); + if (code == CURLE_PEER_FAILED_VERIFICATION || + code == CURLE_SSL_CACERT_BADFILE) + { + MP_ERR(p, + "TLS certificate verification failed.\n" + "This usually means an outdated CA bundle, a self-signed " + "certificate,\nor a MITM proxy on your network. To bypass at " + "your own risk, pass\n--tls-verify=no.\n"); + } +} + static void on_done(struct priv *p, CURLcode code) { bool aborted = atomic_load_explicit(&p->aborted, memory_order_relaxed); @@ -606,7 +620,7 @@ static void on_done(struct priv *p, CURLcode code) if (!p->probed) { // Connection died before any headers arrived. if (code != CURLE_OK && !aborted) - MP_ERR(p, "error: %s\n", curl_easy_strerror(code)); + log_curl_error(p, "error", code); mp_mutex_lock(&p->mtx); p->probed = true; mp_cond_broadcast(&p->cond); @@ -650,7 +664,7 @@ static void on_done(struct priv *p, CURLcode code) } if (!aborted) - MP_ERR(p, "transfer failed: %s\n", curl_easy_strerror(code)); + log_curl_error(p, "transfer failed", code); mp_mutex_lock(&p->mtx); p->stream_error = true; @@ -722,6 +736,7 @@ static void setup_curl(struct priv *p) if (p->net_opts->http_proxy && p->net_opts->http_proxy[0]) curl_easy_setopt(c, CURLOPT_PROXY, p->net_opts->http_proxy); + curl_easy_setopt(c, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NATIVE_CA); curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, p->net_opts->tls_verify ? 1L : 0L); curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, p->net_opts->tls_verify ? 2L : 0L); if (p->net_opts->tls_ca_file) {