Merge #15993: net: Drop support of the insecure miniUPnPc versions

59cb722fd0 Update configure to reject unsafe miniUPnPc API ver (Hennadii Stepanov)
ab2190557e doc: Add release notes for 15993 (Hennadii Stepanov)
02709e9560 Align formatting with clang-format (Hennadii Stepanov)
91a1b85083 Use PACKAGE_NAME in UPnP description (Hennadii Stepanov)
9f76e45b9d Drop support of insecure miniUPnPc versions (Hennadii Stepanov)

Pull request description:

  1. Minimum supported miniUPnPc API version is set to 10:
  - https://packages.ubuntu.com/xenial/libminiupnpc-dev
  - https://packages.debian.org/jessie/libminiupnpc-dev

  Refs:
  - #6583
  - #6789
  - #10414

  2. The hardcoded "Bitcoin" replaced with `PACKAGE_NAME`:
  ![Screenshot from 2019-05-06 23-10-29](https://user-images.githubusercontent.com/32963518/57253178-afc60780-7056-11e9-83c9-e85670c58c1e.png)

  3. Also style-only commit applied.

  Pardon: could not reopen my previous PR #15966.

ACKs for top commit:
  ryanofsky:
    utACK 59cb722fd0. Changes since last review: adding a new commit which updates configure script to fall back to disabling upnp if version is too old, adding a requested comment explaining static_assert condition, and fixing a spelling (jessy/jessie)

Tree-SHA512: 42ed11bc2fb2ec83d5dd58e2383da5444a24fd572707f6cf10b622cb8943e28adfcca4750d06801024c4472625b5ea9279516fbd9d2ccebc9bbaafe1d148e80d
This commit is contained in:
Wladimir J. van der Laan 2019-07-29 16:41:54 +02:00
commit b21acab82f
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
4 changed files with 43 additions and 33 deletions

View file

@ -144,7 +144,7 @@ jobs:
env: >- env: >-
HOST=x86_64-unknown-linux-gnu HOST=x86_64-unknown-linux-gnu
DOCKER_NAME_TAG=ubuntu:14.04 DOCKER_NAME_TAG=ubuntu:14.04
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev" PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
NO_DEPENDS=1 NO_DEPENDS=1
RUN_FUNCTIONAL_TESTS=false RUN_FUNCTIONAL_TESTS=false
GOAL="install" GOAL="install"

View file

@ -994,6 +994,26 @@ if test x$use_upnp != xno; then
[AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])], [AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])],
[have_miniupnpc=no] [have_miniupnpc=no]
) )
dnl The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
dnl with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
if test x$have_miniupnpc != xno; then
AC_MSG_CHECKING([whether miniUPnPc API version is supported])
AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
@%:@include <miniupnpc/miniupnpc.h>
]], [[
#if MINIUPNPC_API_VERSION >= 10
// Everything is okay
#else
# error miniUPnPc API version is too old
#endif
]])],[
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_WARN([miniUPnPc API version < 10 is unsupported, disabling UPnP support.])
have_miniupnpc=no
])
fi
fi fi
if test x$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononononono; then if test x$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononononono; then
@ -1387,9 +1407,10 @@ dnl enable upnp support
AC_MSG_CHECKING([whether to build with support for UPnP]) AC_MSG_CHECKING([whether to build with support for UPnP])
if test x$have_miniupnpc = xno; then if test x$have_miniupnpc = xno; then
if test x$use_upnp = xyes; then if test x$use_upnp = xyes; then
AC_MSG_ERROR("UPnP requested but cannot be built. use --without-miniupnpc") AC_MSG_ERROR("UPnP requested but cannot be built. Use --without-miniupnpc.")
fi fi
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
use_upnp=no
else else
if test x$use_upnp != xno; then if test x$use_upnp != xno; then
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)

View file

@ -0,0 +1,3 @@
Build system changes
--------------------
The minimum supported miniUPnPc API version is set to 10. This keeps compatibility with Ubuntu 16.04 LTS and Debian 8 `libminiupnpc-dev` packages. Please note, on Debian this package is still vulnerable to [CVE-2017-8798](https://security-tracker.debian.org/tracker/CVE-2017-8798) (in jessie only) and [CVE-2017-1000494](https://security-tracker.debian.org/tracker/CVE-2017-1000494) (both in jessie and in stretch).

View file

@ -37,6 +37,9 @@
#include <miniupnpc/miniwget.h> #include <miniupnpc/miniwget.h>
#include <miniupnpc/upnpcommands.h> #include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h> #include <miniupnpc/upnperrors.h>
// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
// with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed");
#endif #endif
#include <unordered_map> #include <unordered_map>
@ -1404,16 +1407,10 @@ static void ThreadMapPort()
struct UPNPDev * devlist = nullptr; struct UPNPDev * devlist = nullptr;
char lanaddr[64]; char lanaddr[64];
#ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
#elif MINIUPNPC_API_VERSION < 14
/* miniupnpc 1.6 */
int error = 0; int error = 0;
#if MINIUPNPC_API_VERSION < 14
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
#else #else
/* miniupnpc 1.9.20150730 */
int error = 0;
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
#endif #endif
@ -1427,43 +1424,32 @@ static void ThreadMapPort()
if (fDiscover) { if (fDiscover) {
char externalIPAddress[40]; char externalIPAddress[40];
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS) if (r != UPNPCOMMAND_SUCCESS) {
LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
else } else {
{ if (externalIPAddress[0]) {
if(externalIPAddress[0])
{
CNetAddr resolved; CNetAddr resolved;
if(LookupHost(externalIPAddress, resolved, false)) { if (LookupHost(externalIPAddress, resolved, false)) {
LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str()); LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str());
AddLocal(resolved, LOCAL_UPNP); AddLocal(resolved, LOCAL_UPNP);
} }
} } else {
else
LogPrintf("UPnP: GetExternalIPAddress failed.\n"); LogPrintf("UPnP: GetExternalIPAddress failed.\n");
}
} }
} }
std::string strDesc = "Bitcoin " + FormatFullVersion(); std::string strDesc = PACKAGE_NAME " " + FormatFullVersion();
do { do {
#ifndef UPNPDISCOVER_SUCCESS r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
/* miniupnpc 1.5 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
#else
/* miniupnpc 1.6 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
#endif
if(r!=UPNPCOMMAND_SUCCESS) if (r != UPNPCOMMAND_SUCCESS) {
LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r));
port, port, lanaddr, r, strupnperror(r)); } else {
else
LogPrintf("UPnP Port Mapping successful.\n"); LogPrintf("UPnP Port Mapping successful.\n");
} }
while(g_upnp_interrupt.sleep_for(std::chrono::minutes(20))); } while (g_upnp_interrupt.sleep_for(std::chrono::minutes(20)));
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);