diff --git a/patches/0086-dropbear-update-to-latest-upstream-version.patch b/patches/0086-dropbear-update-to-latest-upstream-version.patch new file mode 100644 index 000000000..454274580 --- /dev/null +++ b/patches/0086-dropbear-update-to-latest-upstream-version.patch @@ -0,0 +1,1456 @@ +From 65bcd8f407790333d31cd5515232a19dbdbff9f1 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 14 Mar 2025 08:39:12 +0100 +Subject: [PATCH] dropbear: update to latest upstream version + +Fixes a mitm attack. + +Fixes: WIFI-14466 +Signed-off-by: John Crispin +--- + package/network/services/dropbear/Config.in | 119 ++++-- + package/network/services/dropbear/Makefile | 115 +++--- + .../services/dropbear/files/dropbear.config | 4 +- + .../services/dropbear/files/dropbear.defaults | 20 + + .../services/dropbear/files/dropbear.failsafe | 58 ++- + .../services/dropbear/files/dropbear.init | 344 ++++++++++++++---- + ...01-fix-MAX_UNAUTH_CLIENTS-regression.patch | 134 ------- + .../dropbear/patches/100-pubkey_path.patch | 10 +- + .../dropbear/patches/110-change_user.patch | 6 +- + .../patches/130-ssh_ignore_x_args.patch | 10 +- + .../dropbear/patches/140-disable_assert.patch | 4 +- + .../dropbear/patches/160-lto-jobserver.patch | 4 +- + .../600-allow-blank-root-password.patch | 4 +- + .../patches/900-configure-hardening.patch | 35 +- + .../patches/901-bundled-libs-cflags.patch | 71 ++-- + ...nkey-fix-use-of-rsa-sha2-256-pubkeys.patch | 20 +- + 16 files changed, 587 insertions(+), 371 deletions(-) + create mode 100644 package/network/services/dropbear/files/dropbear.defaults + delete mode 100644 package/network/services/dropbear/patches/001-fix-MAX_UNAUTH_CLIENTS-regression.patch + +diff --git a/package/network/services/dropbear/Config.in b/package/network/services/dropbear/Config.in +index d4644fc88f..0d012b21b0 100644 +--- a/package/network/services/dropbear/Config.in ++++ b/package/network/services/dropbear/Config.in +@@ -12,7 +12,6 @@ config DROPBEAR_CURVE25519 + + config DROPBEAR_ECC + bool "Elliptic curve cryptography (ECC)" +- default n + help + Enables basic support for elliptic curve cryptography (ECC) + in key exchange and public key authentication. +@@ -25,11 +24,10 @@ config DROPBEAR_ECC + + Increases binary size by about 24 kB (MIPS). + +- If full ECC support is required, also select DROPBEAR_ECC_FULL. ++ Note: select DROPBEAR_ECC_FULL if full ECC support is required. + + config DROPBEAR_ECC_FULL + bool "Elliptic curve cryptography (ECC), full support" +- default n + depends on DROPBEAR_ECC + help + Enables full support for elliptic curve cryptography (ECC) +@@ -67,46 +65,62 @@ config DROPBEAR_CHACHA20POLY1305 + + Increases binary size by about 4 kB (MIPS). + ++config DROPBEAR_U2F ++ bool "U2F/FIDO support" ++ default y ++ help ++ This option itself doesn't enable any support for U2F/FIDO ++ but subordinate options do: ++ ++ - DROPBEAR_ECDSA_SK - ecdsa-sk keys support ++ depends on DROPBEAR_ECC ("Elliptic curve cryptography (ECC)") ++ - DROPBEAR_ED25519_SK - ed25519-sk keys support ++ depends on DROPBEAR_ED25519 ("Ed25519 support") ++ ++config DROPBEAR_ECDSA_SK ++ bool "ECDSA-SK support" ++ default y ++ depends on DROPBEAR_U2F && DROPBEAR_ECC ++ help ++ This enables the following public key algorithm: ++ sk-ecdsa-sha2-nistp256@openssh.com ++ ++config DROPBEAR_ED25519_SK ++ bool "Ed25519-SK support" ++ default y ++ depends on DROPBEAR_U2F && DROPBEAR_ED25519 ++ help ++ This enables the following public key algorithm: ++ sk-ssh-ed25519@openssh.com ++ + config DROPBEAR_ZLIB + bool "Enable compression" +- default n + help + Enables compression using shared zlib library. + +- Increases binary size by about 0.1 kB (MIPS) and requires additional 62 kB (MIPS) +- for a shared zlib library. ++ Increases binary size by about 0.1 kB (MIPS) and requires ++ additional 62 kB (MIPS) for a shared zlib library. + + config DROPBEAR_UTMP + bool "Utmp support" +- default n + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help +- This enables dropbear utmp support, the file /var/run/utmp is used to +- track who is currently logged in. ++ This enables dropbear utmp support, the file /var/run/utmp is ++ used to track who is currently logged in. + + config DROPBEAR_PUTUTLINE + bool "Pututline support" +- default n + depends on DROPBEAR_UTMP + help +- Dropbear will use pututline() to write the utmp structure into the utmp file. ++ Dropbear will use pututline() to write the utmp structure into ++ the utmp file. + + config DROPBEAR_DBCLIENT + bool "Build dropbear with dbclient" + default y + +-config DROPBEAR_DBCLIENT_AGENTFORWARD +- bool "Enable agent forwarding in dbclient" +- default y +- depends on DROPBEAR_DBCLIENT +- +-config DROPBEAR_SCP +- bool "Build dropbear with scp" +- default y +- + config DROPBEAR_ASKPASS + bool "Enable askpass helper support" +- default n + depends on DROPBEAR_DBCLIENT + help + This enables support for ssh-askpass helper in dropbear client +@@ -114,8 +128,69 @@ config DROPBEAR_ASKPASS + + Increases binary size by about 0.1 kB (MIPS). + ++config DROPBEAR_DBCLIENT_AGENTFORWARD ++ bool "Enable agent forwarding in dbclient [LEGACY/SECURITY]" ++ default y ++ depends on DROPBEAR_DBCLIENT ++ help ++ Increases binary size by about 0.1 kB (MIPS). ++ ++ Security notes: ++ ++ SSH agent forwarding might cause security issues (locally and ++ on the jump machine). ++ ++ Hovewer, it's enabled by default for compatibility with ++ previous OpenWrt/dropbear releases. ++ ++ Consider DISABLING this option if you're building own OpenWrt ++ image. ++ ++ Also see DROPBEAR_AGENTFORWARD (agent forwarding in dropbear ++ server itself). ++ ++config DROPBEAR_SCP ++ bool "Build dropbear with scp" ++ default y ++ + config DROPBEAR_AGENTFORWARD +- bool "Enable agent forwarding" ++ bool "Enable agent forwarding [LEGACY/SECURITY]" + default y ++ help ++ Increases binary size by about 0.1 kB (MIPS). ++ ++ Security notes: ++ ++ SSH agent forwarding might cause security issues (locally and ++ on the jump machine). ++ ++ Hovewer, it's enabled by default for compatibility with ++ previous OpenWrt/dropbear releases. ++ ++ Consider DISABLING this option if you're building own OpenWrt ++ image. ++ ++ Also see DROPBEAR_DBCLIENT_AGENTFORWARD (agent forwarding in ++ dropbear client) if DROPBEAR_DBCLIENT is selected. ++ ++config DROPBEAR_MODERN_ONLY ++ bool "Use modern crypto only [BREAKS COMPATIBILITY]" ++ select DROPBEAR_ED25519 ++ select DROPBEAR_CURVE25519 ++ select DROPBEAR_CHACHA20POLY1305 ++ help ++ This option enables: ++ - Chacha20-Poly1305 ++ - Curve25519 ++ - Ed25519 ++ and disables: ++ - AES ++ - RSA ++ ++ Reduces binary size by about 64 kB (MIPS) from default ++ configuration. ++ ++ Consider enabling this option if you're building own OpenWrt ++ image and using modern SSH software everywhere. + + endmenu +diff --git a/package/network/services/dropbear/Makefile b/package/network/services/dropbear/Makefile +index e98e995ba7..e13b6c2145 100644 +--- a/package/network/services/dropbear/Makefile ++++ b/package/network/services/dropbear/Makefile +@@ -8,18 +8,18 @@ + include $(TOPDIR)/rules.mk + + PKG_NAME:=dropbear +-PKG_VERSION:=2022.82 +-PKG_RELEASE:=5 ++PKG_VERSION:=2024.86 ++PKG_RELEASE:=1 + + PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 + PKG_SOURCE_URL:= \ + https://matt.ucc.asn.au/dropbear/releases/ \ + https://dropbear.nl/mirror/releases/ +-PKG_HASH:=3a038d2bbc02bf28bbdd20c012091f741a3ec5cbe460691811d714876aad75d1 ++PKG_HASH:=e78936dffc395f2e0db099321d6be659190966b99712b55c530dd0a1822e0a5e + + PKG_LICENSE:=MIT + PKG_LICENSE_FILES:=LICENSE libtomcrypt/LICENSE libtommath/LICENSE +-PKG_CPE_ID:=cpe:/a:matt_johnston:dropbear_ssh_server ++PKG_CPE_ID:=cpe:/a:dropbear_ssh_project:dropbear_ssh + + PKG_BUILD_PARALLEL:=1 + PKG_ASLR_PIE_REGULAR:=1 +@@ -31,9 +31,11 @@ PKG_CONFIG_DEPENDS:= \ + CONFIG_TARGET_INIT_PATH CONFIG_DROPBEAR_ECC CONFIG_DROPBEAR_ECC_FULL \ + CONFIG_DROPBEAR_CURVE25519 CONFIG_DROPBEAR_ZLIB \ + CONFIG_DROPBEAR_ED25519 CONFIG_DROPBEAR_CHACHA20POLY1305 \ ++ CONFIG_DROPBEAR_U2F CONFIG_DROPBEAR_ECDSA_SK CONFIG_DROPBEAR_ED25519_SK \ + CONFIG_DROPBEAR_UTMP CONFIG_DROPBEAR_PUTUTLINE \ + CONFIG_DROPBEAR_DBCLIENT CONFIG_DROPBEAR_SCP CONFIG_DROPBEAR_ASKPASS \ +- CONFIG_DROPBEAR_DBCLIENT_AGENTFORWARD CONFIG_DROPBEAR_AGENTFORWARD ++ CONFIG_DROPBEAR_DBCLIENT_AGENTFORWARD CONFIG_DROPBEAR_AGENTFORWARD \ ++ CONFIG_DROPBEAR_MODERN_ONLY + + include $(INCLUDE_DIR)/package.mk + +@@ -55,7 +57,7 @@ define Package/dropbear + CATEGORY:=Base system + TITLE:=Small SSH2 client/server + DEPENDS:= +DROPBEAR_ZLIB:zlib +- ALTERNATIVES:= ++ ALTERNATIVES:=100:/usr/bin/ssh-keygen:/usr/sbin/dropbear + $(if $(CONFIG_DROPBEAR_SCP),ALTERNATIVES+= \ + 100:/usr/bin/scp:/usr/sbin/dropbear,) + $(if $(CONFIG_DROPBEAR_DBCLIENT),ALTERNATIVES+= \ +@@ -68,10 +70,11 @@ define Package/dropbear/description + endef + + define Package/dropbear/conffiles +-$(if $(CONFIG_DROPBEAR_ED25519),/etc/dropbear/dropbear_ed25519_host_key) +-$(if $(CONFIG_DROPBEAR_ECC),/etc/dropbear/dropbear_ecdsa_host_key) +-/etc/dropbear/dropbear_rsa_host_key + /etc/config/dropbear ++/etc/dropbear/authorized_keys ++/etc/dropbear/dropbear_ecdsa_host_key ++/etc/dropbear/dropbear_ed25519_host_key ++/etc/dropbear/dropbear_rsa_host_key + endef + + define Package/dropbearconvert +@@ -99,79 +102,100 @@ CONFIGURE_ARGS += \ + + ############################################################################## + # +-# option|value - add option to localoptions.h +-# !!option|value - replace option in sysoptions.h ++# option,value - add option to localoptions.h ++# !!option,value - replace option in src/sysoptions.h + # + ############################################################################## + ++# adjust allowed shell list (if getusershell(3) is missing): ++# - COMPAT_USER_SHELLS + # remove protocol idented software version number: + # - LOCAL_IDENT + # disable legacy/unsafe methods and unused functionality: + # - DROPBEAR_CLI_NETCAT + # - DROPBEAR_DSS + # - DO_MOTD ++# - DROPBEAR_DH_GROUP14_SHA1 ++# - DROPBEAR_SHA1_HMAC + DB_OPT_COMMON = \ +- DEFAULT_PATH|"$(TARGET_INIT_PATH)" \ +- !!LOCAL_IDENT|"SSH-2.0-dropbear" \ +- DROPBEAR_CLI_NETCAT|0 \ +- DROPBEAR_DSS|0 \ +- DO_MOTD|0 \ ++ !!LOCAL_IDENT,"SSH-2.0-dropbear" \ ++ COMPAT_USER_SHELLS,"/bin/ash","/bin/sh" \ ++ DEFAULT_PATH,"$(TARGET_INIT_PATH)" \ ++ DEFAULT_ROOT_PATH,"$(TARGET_INIT_PATH)" \ ++ DROPBEAR_DSS,0 \ ++ DROPBEAR_CLI_NETCAT,0 \ ++ DO_MOTD,0 \ ++ DROPBEAR_DH_GROUP14_SHA1,0 \ ++ DROPBEAR_SHA1_HMAC,0 \ + + + ############################################################################## + # +-# option|config|enabled|disabled = add option to localoptions.h +-# !!option|config|enabled|disabled = replace option in sysoptions.h ++# option,config,enabled,disabled = add option to localoptions.h ++# !!option,config,enabled,disabled = replace option in src/sysoptions.h + # + # option := (config) ? enabled : disabled + # + ############################################################################## + + DB_OPT_CONFIG = \ +- DROPBEAR_CURVE25519|CONFIG_DROPBEAR_CURVE25519|1|0 \ +- DROPBEAR_ED25519|CONFIG_DROPBEAR_ED25519|1|0 \ +- DROPBEAR_SK_ED25519|CONFIG_DROPBEAR_ED25519|1|0 \ +- DROPBEAR_CHACHA20POLY1305|CONFIG_DROPBEAR_CHACHA20POLY1305|1|0 \ +- DROPBEAR_ECDSA|CONFIG_DROPBEAR_ECC|1|0 \ +- DROPBEAR_SK_ECDSA|CONFIG_DROPBEAR_ECC|1|0 \ +- DROPBEAR_ECDH|CONFIG_DROPBEAR_ECC|1|0 \ +- !!DROPBEAR_ECC_384|CONFIG_DROPBEAR_ECC_FULL|1|0 \ +- !!DROPBEAR_ECC_521|CONFIG_DROPBEAR_ECC_FULL|1|0 \ +- DROPBEAR_CLI_ASKPASS_HELPER|CONFIG_DROPBEAR_ASKPASS|1|0 \ +- DROPBEAR_CLI_AGENTFWD|CONFIG_DROPBEAR_DBCLIENT_AGENTFORWARD|1|0 \ +- DROPBEAR_SVR_AGENTFWD|CONFIG_DROPBEAR_AGENTFORWARD|1|0 \ ++ !!DROPBEAR_ECC_384,CONFIG_DROPBEAR_ECC_FULL,1,0 \ ++ !!DROPBEAR_ECC_521,CONFIG_DROPBEAR_ECC_FULL,1,0 \ ++ DROPBEAR_CURVE25519,CONFIG_DROPBEAR_CURVE25519,1,0 \ ++ DROPBEAR_CHACHA20POLY1305,CONFIG_DROPBEAR_CHACHA20POLY1305,1,0 \ ++ DROPBEAR_ED25519,CONFIG_DROPBEAR_ED25519,1,0 \ ++ DROPBEAR_ECDSA,CONFIG_DROPBEAR_ECC,1,0 \ ++ DROPBEAR_ECDH,CONFIG_DROPBEAR_ECC,1,0 \ ++ DROPBEAR_SK_KEYS,CONFIG_DROPBEAR_U2F,1,0 \ ++ DROPBEAR_SK_ECDSA,CONFIG_DROPBEAR_ECDSA_SK,1,0 \ ++ DROPBEAR_SK_ED25519,CONFIG_DROPBEAR_ED25519_SK,1,0 \ ++ DROPBEAR_CLI_ASKPASS_HELPER,CONFIG_DROPBEAR_ASKPASS,1,0 \ ++ DROPBEAR_CLI_AGENTFWD,CONFIG_DROPBEAR_DBCLIENT_AGENTFORWARD,1,0 \ ++ DROPBEAR_SVR_AGENTFWD,CONFIG_DROPBEAR_AGENTFORWARD,1,0 \ ++ DROPBEAR_AES128,CONFIG_DROPBEAR_MODERN_ONLY,0,1 \ ++ DROPBEAR_AES256,CONFIG_DROPBEAR_MODERN_ONLY,0,1 \ ++ DROPBEAR_ENABLE_CTR_MODE,CONFIG_DROPBEAR_MODERN_ONLY,0,1 \ ++ DROPBEAR_RSA,CONFIG_DROPBEAR_MODERN_ONLY,0,1 \ ++ DROPBEAR_RSA_SHA1,CONFIG_DROPBEAR_MODERN_ONLY,0,1 \ + + + TARGET_CFLAGS += -DARGTYPE=3 + ++xsedx:=$(shell printf '\027') ++ + db_opt_add =echo '\#define $(1) $(2)' >> $(PKG_BUILD_DIR)/localoptions.h +-db_opt_replace =$(ESED) 's,^(\#define $(1)) .*$$$$,\1 $(2),g' $(PKG_BUILD_DIR)/sysoptions.h ++db_opt_replace =$(ESED) '/^\#define $(1) .*$$$$/{h;:a;$$$$!n;/^\#.+$$$$/bb;/^$$$$/bb;H;ba;:b;x;s$(xsedx)^.+$$$$$(xsedx)\#define $(1) $(2)$(xsedx)p;x};p' -n $(PKG_BUILD_DIR)/src/sysoptions.h + + define Build/Configure/dropbear_headers + $(strip $(foreach s,$(DB_OPT_COMMON), \ +- $(if $(filter !!%,$(word 1,$(subst |, ,$(s)))), \ +- $(call db_opt_replace,$(patsubst !!%,%,$(word 1,$(subst |, ,$(s)))),$(word 2,$(subst |, ,$(s)))), \ +- $(call db_opt_add,$(word 1,$(subst |, ,$(s))),$(word 2,$(subst |, ,$(s)))) \ ++ $(if $(filter !!%,$(word 1,$(subst $(comma),$(space),$(s)))), \ ++ $(call db_opt_replace,$(patsubst !!%,%,$(word 1,$(subst $(comma),$(space),$(s)))),$(subst $(space),$(comma),$(wordlist 2,$(words $(subst $(comma),$(space),$(s))),$(subst $(comma),$(space),$(s))))), \ ++ $(call db_opt_add,$(word 1,$(subst $(comma),$(space),$(s))),$(subst $(space),$(comma),$(wordlist 2,$(words $(subst $(comma),$(space),$(s))),$(subst $(comma),$(space),$(s))))) \ + ) ; \ + )) + + $(strip $(foreach s,$(DB_OPT_CONFIG), \ +- $(if $(filter !!%,$(word 1,$(subst |, ,$(s)))), \ +- $(call db_opt_replace,$(patsubst !!%,%,$(word 1,$(subst |, ,$(s)))),$(if $($(word 2,$(subst |, ,$(s)))),$(word 3,$(subst |, ,$(s))),$(word 4,$(subst |, ,$(s))))), \ +- $(call db_opt_add,$(word 1,$(subst |, ,$(s))),$(if $($(word 2,$(subst |, ,$(s)))),$(word 3,$(subst |, ,$(s))),$(word 4,$(subst |, ,$(s))))) \ ++ $(if $(filter !!%,$(word 1,$(subst $(comma),$(space),$(s)))), \ ++ $(call db_opt_replace,$(patsubst !!%,%,$(word 1,$(subst $(comma),$(space),$(s)))),$(if $($(word 2,$(subst $(comma),$(space),$(s)))),$(word 3,$(subst $(comma),$(space),$(s))),$(word 4,$(subst $(comma),$(space),$(s))))), \ ++ $(call db_opt_add,$(word 1,$(subst $(comma),$(space),$(s))),$(if $($(word 2,$(subst $(comma),$(space),$(s)))),$(word 3,$(subst $(comma),$(space),$(s))),$(word 4,$(subst $(comma),$(space),$(s))))) \ + ) ; \ + )) + endef + +-define Build/Configure +- : > $(PKG_BUILD_DIR)/localoptions.h ++define Build/Configure/dropbear_objects ++ grep -ERZl -e '($(subst $(space),|,$(strip $(sort $(patsubst !!%,%,$(foreach s,$(DB_OPT_COMMON) $(DB_OPT_CONFIG),$(word 1,$(subst $(comma),$(space),$(s)))))))))' \ ++ $(PKG_BUILD_DIR)/ | sed -zE 's/^(.+)\.[^.]+$$$$/\1.o/' | sort -uV | xargs -0 -r rm -fv || : ++endef + ++define Build/Configure ++ rm -f $(PKG_BUILD_DIR)/localoptions.h + $(Build/Configure/Default) + ++ : > $(PKG_BUILD_DIR)/localoptions.h + $(Build/Configure/dropbear_headers) + +- # Enforce rebuild of svr-chansession.c +- rm -f $(PKG_BUILD_DIR)/svr-chansession.o ++ # Enforce rebuild of files depending on configured options ++ $(Build/Configure/dropbear_objects) + + # Rebuild them on config change + +$(MAKE) -C $(PKG_BUILD_DIR)/libtomcrypt clean +@@ -181,10 +205,12 @@ endef + define Build/Compile + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ ++ IGNORE_SPEED=1 \ + PROGRAMS="dropbear $(if $(CONFIG_DROPBEAR_DBCLIENT),dbclient,) dropbearkey $(if $(CONFIG_DROPBEAR_SCP),scp,)" \ + MULTI=1 SCPPROGRESS=1 + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ ++ IGNORE_SPEED=1 \ + PROGRAMS="dropbearconvert" + endef + +@@ -198,13 +224,12 @@ define Package/dropbear/install + $(INSTALL_CONF) ./files/dropbear.config $(1)/etc/config/dropbear + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/dropbear.init $(1)/etc/init.d/dropbear +- $(INSTALL_DIR) $(1)/usr/lib/opkg/info + $(INSTALL_DIR) $(1)/etc/dropbear + $(INSTALL_DIR) $(1)/lib/preinit + $(INSTALL_DATA) ./files/dropbear.failsafe $(1)/lib/preinit/99_10_failsafe_dropbear +- $(if $(CONFIG_DROPBEAR_ED25519),touch $(1)/etc/dropbear/dropbear_ed25519_host_key) +- $(if $(CONFIG_DROPBEAR_ECC),touch $(1)/etc/dropbear/dropbear_ecdsa_host_key) +- touch $(1)/etc/dropbear/dropbear_rsa_host_key ++ $(INSTALL_DIR) $(1)/etc/uci-defaults ++ $(INSTALL_DATA) ./files/dropbear.defaults $(1)/etc/uci-defaults/50-dropbear ++ $(foreach f,$(filter /etc/dropbear/%,$(Package/dropbear/conffiles)),$(if $(wildcard $(TOPDIR)/files/$(f)),chmod 0600 $(TOPDIR)/files/$(f) || :; )) + endef + + define Package/dropbearconvert/install +diff --git a/package/network/services/dropbear/files/dropbear.config b/package/network/services/dropbear/files/dropbear.config +index 2139ba0bbe..7eb5975449 100644 +--- a/package/network/services/dropbear/files/dropbear.config ++++ b/package/network/services/dropbear/files/dropbear.config +@@ -1,4 +1,6 @@ +-config dropbear ++# See https://openwrt.org/docs/guide-user/base-system/dropbear ++config dropbear main ++ option enable '1' + option PasswordAuth 'on' + option RootPasswordAuth 'on' + option Port '22' +diff --git a/package/network/services/dropbear/files/dropbear.defaults b/package/network/services/dropbear/files/dropbear.defaults +new file mode 100644 +index 0000000000..e679bee5db +--- /dev/null ++++ b/package/network/services/dropbear/files/dropbear.defaults +@@ -0,0 +1,20 @@ ++[ ! -s /etc/dropbear/authorized_keys ] || exit 0 ++ ++. /usr/share/libubox/jshn.sh ++ ++json_init ++json_load "$(cat /etc/board.json)" ++json_select credentials ++ json_get_keys keys ssh_authorized_keys ++ [ -z "$keys" ] || { ++ touch /etc/dropbear/authorized_keys ++ uci set dropbear.@dropbear[-1].PasswordAuth='off' ++ uci set dropbear.@dropbear[-1].RootPasswordAuth='off' ++ } ++ json_select ssh_authorized_keys ++ for key in $keys; do ++ json_get_var val "$key" ++ echo "$val" >> /etc/dropbear/authorized_keys ++ done ++ json_select .. ++json_select .. +diff --git a/package/network/services/dropbear/files/dropbear.failsafe b/package/network/services/dropbear/files/dropbear.failsafe +index 97bd12d58a..417265babe 100755 +--- a/package/network/services/dropbear/files/dropbear.failsafe ++++ b/package/network/services/dropbear/files/dropbear.failsafe +@@ -1,9 +1,61 @@ + #!/bin/sh + ++_dropbear() ++{ ++ /usr/sbin/dropbear "$@" /dev/null 2>&1 ++} ++ ++_dropbearkey() ++{ ++ /usr/bin/dropbearkey "$@" /dev/null 2>&1 ++} ++ ++_ensurekey() ++{ ++ _dropbearkey -y -f "$1" && return ++ rm -f "$1" ++ _dropbearkey -f "$@" || { ++ rm -f "$1" ++ return 1 ++ } ++} ++ ++ktype_all='ed25519 ecdsa rsa' ++ + failsafe_dropbear () { +- dropbearkey -t rsa -s 1024 -f /tmp/dropbear_rsa_failsafe_host_key +- dropbearkey -t ed25519 -f /tmp/dropbear_ed25519_failsafe_host_key +- dropbear -r /tmp/dropbear_rsa_failsafe_host_key -r /tmp/dropbear_ed25519_failsafe_host_key <> /dev/null 2>&1 ++ local kargs kcount ktype tkey ++ ++ kargs= ++ kcount=0 ++ for ktype in ${ktype_all} ; do ++ tkey="/tmp/dropbear_failsafe_${ktype}_host_key" ++ ++ case "${ktype}" in ++ ed25519) _ensurekey "${tkey}" -t ed25519 ;; ++ ecdsa) _ensurekey "${tkey}" -t ecdsa -s 256 ;; ++ rsa) _ensurekey "${tkey}" -t rsa -s 1024 ;; ++ *) ++ echo "unknown key type: ${ktype}" >&2 ++ continue ++ ;; ++ esac ++ ++ [ -s "${tkey}" ] || { ++ rm -f "${tkey}" ++ continue ++ } ++ ++ chmod 0400 "${tkey}" ++ kargs="${kargs}${kargs:+ }-r ${tkey}" ++ kcount=$((kcount+1)) ++ done ++ ++ [ "${kcount}" != 0 ] || { ++ echo 'DROPBEAR IS BROKEN' >&2 ++ return 1 ++ } ++ ++ _dropbear ${kargs} + } + + boot_hook_add failsafe failsafe_dropbear +diff --git a/package/network/services/dropbear/files/dropbear.init b/package/network/services/dropbear/files/dropbear.init +index b82e967cbc..11e89340db 100755 +--- a/package/network/services/dropbear/files/dropbear.init ++++ b/package/network/services/dropbear/files/dropbear.init +@@ -8,32 +8,55 @@ STOP=50 + USE_PROCD=1 + PROG=/usr/sbin/dropbear + NAME=dropbear +-PIDCOUNT=0 + + extra_command "killclients" "Kill ${NAME} processes except servers and yourself" + ++# most of time real_stat() will be failing ++# due to missing "stat" binary (by default) ++real_stat() { env stat -L "$@" 2>/dev/null ; } ++dumb_stat() { ls -Ldln "$1" | tr -s '\t ' ' ' ; } ++stat_perm() { real_stat -c '%A' "$1" || dumb_stat "$1" | cut -d ' ' -f 1 ; } ++stat_owner() { real_stat -c '%u' "$1" || dumb_stat "$1" | cut -d ' ' -f 3 ; } ++ + _dropbearkey() + { +- /usr/bin/dropbearkey "$@" 0<&- 1>&- 2>&- ++ /usr/bin/dropbearkey "$@" /dev/null 2>&1 + } + +-# $1 - host key file name +-hk_verify() ++# $1 - file name (host key or config) ++file_verify() + { + [ -f "$1" ] || return 1 +- [ -s "$1" ] || return 2 +- _dropbearkey -y -f "$1" || return 3 ++ # checking file ownership ++ [ "$(stat_owner "$1")" = "0" ] || { ++ chown 0 "$1" ++ [ "$(stat_owner "$1")" = "0" ] || return 2 ++ } ++ # checking file permissions ++ [ "$(stat_perm "$1")" = "-rw-------" ] || { ++ chmod 0600 "$1" ++ [ "$(stat_perm "$1")" = "-rw-------" ] || return 3 ++ } ++ # file is host key or not? ++ # if $2 is empty string - file is "host key" ++ # if $2 is non-empty string - file is "config" ++ [ -z "$2" ] || return 0 ++ # checking file contents (finally) ++ [ -s "$1" ] || return 4 ++ _dropbearkey -y -f "$1" || return 5 + return 0 + } + +-# $1 - hk_verify() return code +-hk_errmsg() ++# $1 - file_verify() return code ++file_errmsg() + { + case "$1" in + 0) ;; + 1) echo "file does not exist" ;; +- 2) echo "file has zero length" ;; +- 3) echo "file is not valid host key or not supported" ;; ++ 2) echo "file has wrong owner (must be owned by root)" ;; ++ 3) echo "file has wrong permissions (must not have group/other write bit)" ;; ++ 4) echo "file has zero length" ;; ++ 5) echo "file is not valid host key or not supported" ;; + *) echo "unknown error" ;; + esac + } +@@ -43,73 +66,97 @@ hk_errmsg() + hk_config() + { + local x m +- hk_verify "$2"; x=$? +- case "$x" in +- 0) procd_append_param command -r "$2" +- ;; +- *) m=$(hk_errmsg "$x") +- logger -t "${NAME}" -p daemon.warn \ +- "option '$1', value '$2': $m, skipping" +- ;; +- esac ++ file_verify "$2" ; x=$? ++ if [ "$x" = 0 ] ; then ++ procd_append_param command -r "$2" ++ return ++ fi ++ m=$(file_errmsg "$x") ++ logger -s -t "${NAME}" -p daemon.warn \ ++ "Option '$1', skipping '$2': $m" + } + + # $1 - host key file name +-hk_config__keyfile() +-{ +- hk_config 'keyfile' "$1" +-} ++hk_config__keyfile() { hk_config keyfile "$1" ; } ++ ++ktype_all='ed25519 ecdsa rsa' + + hk_generate_as_needed() + { +- local kdir kgen ktype tdir kcount tfile +- kdir='/etc/dropbear' ++ local hk_cfg_dir kgen ktype kfile hk_tmp_dir ++ hk_cfg_dir='/etc/dropbear' ++ ++ [ -d "${hk_cfg_dir}" ] || mkdir -p "${hk_cfg_dir}" ++ ++ kgen= ++ for ktype in ${ktype_all} ; do ++ kfile="${hk_cfg_dir}/dropbear_${ktype}_host_key" + +- kgen='' +- for ktype in ed25519 ecdsa rsa; do +- hk_verify "${kdir}/dropbear_${ktype}_host_key" && continue ++ if file_verify "${kfile}" ; then continue ; fi + +- kgen="${kgen} ${ktype}" ++ kgen="${kgen}${kgen:+ }${ktype}" + done + +- [ -z "${kgen}" ] && return ++ # all keys are sane? ++ [ -n "${kgen}" ] || return 0 + +- tdir=$(mktemp -d); chmod 0700 "${tdir}" ++ hk_tmp_dir=$(mktemp -d) ++ # system in bad state? ++ [ -n "${hk_tmp_dir}" ] || return 1 + +- kcount=0 +- for ktype in ${kgen}; do +- tfile="${tdir}/dropbear_${ktype}_host_key" ++ chmod 0700 "${hk_tmp_dir}" + +- if ! _dropbearkey -t ${ktype} -f "${tfile}"; then ++ for ktype in ${kgen} ; do ++ kfile="${hk_tmp_dir}/dropbear_${ktype}_host_key" ++ ++ if ! _dropbearkey -t ${ktype} -f "${kfile}" ; then + # unsupported key type +- rm -f "${tfile}" ++ rm -f "${kfile}" + continue + fi + +- kcount=$((kcount+1)) ++ chmod 0600 "${kfile}" + done + +- if [ ${kcount} -ne 0 ]; then +- mkdir -p "${kdir}"; chmod 0700 "${kdir}"; chown root "${kdir}" +- mv -f "${tdir}/"* "${kdir}/" ++ kgen= ++ for ktype in ${ktype_all} ; do ++ kfile="${hk_tmp_dir}/dropbear_${ktype}_host_key" ++ ++ [ -s "${kfile}" ] || continue ++ ++ kgen="${kgen}${kgen:+ }${ktype}" ++ done ++ ++ if [ -n "${kgen}" ] ; then ++ for ktype in ${kgen} ; do ++ kfile="${hk_tmp_dir}/dropbear_${ktype}_host_key" ++ [ -s "${kfile}" ] || continue ++ mv -f "${kfile}" "${hk_cfg_dir}/" ++ done + fi + +- rm -rf "${tdir}" ++ rm -rf "${hk_tmp_dir}" ++ ++ # cleanup empty files ++ for ktype in ${ktype_all} ; do ++ kfile="${hk_cfg_dir}/dropbear_${ktype}_host_key" ++ ++ [ -s "${kfile}" ] || rm -f "${kfile}" ++ done + } + +-append_ports() ++# $1 - list with whitespace-separated elements ++normalize_list() + { +- local ipaddrs="$1" +- local port="$2" +- +- [ -z "$ipaddrs" ] && { +- procd_append_param command -p "$port" +- return +- } ++ printf '%s' "$1" | tr -s ' \r\n\t' ' ' | sed -E 's/^ //;s/ $//' ++} + +- for addr in $ipaddrs; do +- procd_append_param command -p "$addr:$port" +- done ++warn_multiple_interfaces() ++{ ++ logger -t "${NAME}" -p daemon.warn \ ++ "Option '$1' should specify SINGLE interface but instead it lists interfaces: $2" ++ logger -t "${NAME}" -p daemon.warn \ ++ "Consider creating per-interface instances instead!" + } + + validate_section_dropbear() +@@ -117,6 +164,7 @@ validate_section_dropbear() + uci_load_validate dropbear dropbear "$1" "$2" \ + 'PasswordAuth:bool:1' \ + 'enable:bool:1' \ ++ 'DirectInterface:string' \ + 'Interface:string' \ + 'GatewayPorts:bool:0' \ + 'ForceCommand:string' \ +@@ -129,53 +177,180 @@ validate_section_dropbear() + 'SSHKeepAlive:uinteger:300' \ + 'IdleTimeout:uinteger:0' \ + 'MaxAuthTries:uinteger:3' \ +- 'RecvWindowSize:uinteger:0' \ ++ 'RecvWindowSize:uinteger:262144' \ + 'mdns:bool:1' + } + + dropbear_instance() + { +- local ipaddrs +- + [ "$2" = 0 ] || { + echo "validation failed" + return 1 + } + +- [ -n "${Interface}" ] && { +- [ -n "${BOOT}" ] && return 0 ++ [ "${enable}" = "1" ] || return 1 + +- network_get_ipaddrs_all ipaddrs "${Interface}" || { +- echo "interface ${Interface} has no physdev or physdev has no suitable ip" +- return 1 +- } +- } ++ local iface ndev ipaddrs ++ ++ # 'DirectInterface' should specify single interface ++ # but end users may misinterpret this setting ++ DirectInterface=$(normalize_list "${DirectInterface}") ++ ++ # 'Interface' should specify single interface ++ # but end users are often misinterpret this setting ++ Interface=$(normalize_list "${Interface}") ++ ++ if [ -n "${Interface}" ] ; then ++ if [ -n "${DirectInterface}" ] ; then ++ logger -t "${NAME}" -p daemon.warn \ ++ "Option 'DirectInterface' takes precedence over 'Interface'" ++ else ++ logger -t "${NAME}" -p daemon.info \ ++ "Option 'Interface' binds to address(es) but not to interface" ++ logger -t "${NAME}" -p daemon.info \ ++ "Consider using option 'DirectInterface' to bind directly to interface" ++ fi ++ fi ++ ++ # handle 'DirectInterface' ++ iface=$(echo "${DirectInterface}" | awk '{print $1}') ++ case "${DirectInterface}" in ++ *\ *) ++ warn_multiple_interfaces DirectInterface "${DirectInterface}" ++ logger -t "${NAME}" -p daemon.warn \ ++ "Using network interface '${iface}' for direct binding" ++ ;; ++ esac ++ while [ -n "${iface}" ] ; do ++ # if network is available (even during boot) - proceed ++ if network_is_up "${iface}" ; then break ; fi ++ # skip during boot ++ [ -z "${BOOT}" ] || return 0 ++ ++ logger -t "${NAME}" -p daemon.crit \ ++ "Network interface '${iface}' is not available!" ++ return 1 ++ done ++ while [ -n "${iface}" ] ; do ++ # ${iface} is logical (higher level) interface name ++ # ${ndev} is 'real' interface name ++ # e.g.: if ${iface} is 'lan' (default LAN interface) then ${ndev} is 'br-lan' ++ network_get_device ndev "${iface}" ++ [ -z "${ndev}" ] || break ++ ++ logger -t "${NAME}" -p daemon.crit \ ++ "Missing network device for network interface '${iface}'!" ++ return 1 ++ done ++ if [ -n "${iface}" ] ; then ++ logger -t "${NAME}" -p daemon.info \ ++ "Using network interface '${iface}' (network device '${ndev}') for direct binding" ++ fi ++ # handle 'Interface' ++ while [ -z "${iface}" ] ; do ++ [ -n "${Interface}" ] || break ++ ++ # skip during boot ++ [ -z "${BOOT}" ] || return 0 ++ ++ case "${Interface}" in ++ *\ *) ++ warn_multiple_interfaces Interface "${Interface}" ++ ;; ++ esac ++ ++ local c=0 ++ # src/sysoptions.h ++ local DROPBEAR_MAX_PORTS=10 ++ ++ local a n if_ipaddrs ++ for n in ${Interface} ; do ++ [ -n "$n" ] || continue ++ ++ if_ipaddrs= ++ network_get_ipaddrs_all if_ipaddrs "$n" ++ [ -n "${if_ipaddrs}" ] || { ++ logger -s -t "${NAME}" -p daemon.err \ ++ "Network interface '$n' has no suitable IP address(es)!" ++ continue ++ } ++ ++ [ $c -le ${DROPBEAR_MAX_PORTS} ] || { ++ logger -s -t "${NAME}" -p daemon.err \ ++ "Network interface '$n' is NOT listened due to option limit exceed!" ++ continue ++ } ++ ++ for a in ${if_ipaddrs} ; do ++ [ -n "$a" ] || continue ++ ++ c=$((c+1)) ++ if [ $c -le ${DROPBEAR_MAX_PORTS} ] ; then ++ ipaddrs="${ipaddrs} $a" ++ continue ++ fi ++ ++ logger -t "${NAME}" -p daemon.err \ ++ "Endpoint '$a:${Port}' on network interface '$n' is NOT listened due to option limit exceed!" ++ done ++ done ++ break ++ done + +- [ "${enable}" = "0" ] && return 1 +- PIDCOUNT="$(( ${PIDCOUNT} + 1))" +- local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid" ++ local pid_file="/var/run/${NAME}.${1}.pid" + + procd_open_instance + procd_set_param command "$PROG" -F -P "$pid_file" ++ if [ -n "${iface}" ] ; then ++ # if ${iface} is non-empty then ${ndev} is non-empty too ++ procd_append_param command -l "${ndev}" -p "${Port}" ++ else ++ if [ -z "${ipaddrs}" ] ; then ++ procd_append_param command -p "${Port}" ++ else ++ local a ++ for a in ${ipaddrs} ; do ++ [ -n "$a" ] || continue ++ procd_append_param command -p "$a:${Port}" ++ done ++ fi ++ fi + [ "${PasswordAuth}" -eq 0 ] && procd_append_param command -s + [ "${GatewayPorts}" -eq 1 ] && procd_append_param command -a + [ -n "${ForceCommand}" ] && procd_append_param command -c "${ForceCommand}" + [ "${RootPasswordAuth}" -eq 0 ] && procd_append_param command -g + [ "${RootLogin}" -eq 0 ] && procd_append_param command -w ++ config_list_foreach "$1" 'keyfile' hk_config__keyfile + if [ -n "${rsakeyfile}" ]; then +- logger -t ${NAME} -p daemon.warn \ +- "option 'rsakeyfile' is considered to be deprecated and" \ +- "will be removed in future releases, use 'keyfile' instead" ++ logger -s -t "${NAME}" -p daemon.crit \ ++ "Option 'rsakeyfile' is considered to be DEPRECATED and will be REMOVED in future releases, use 'keyfile' list instead" ++ sed -i.before-upgrade -E -e 's/option(\s+)rsakeyfile/list keyfile/' \ ++ "/etc/config/${NAME}" ++ logger -s -t "${NAME}" -p daemon.crit \ ++ "Auto-transition 'option rsakeyfile' => 'list keyfile' in /etc/config/${NAME} is done, please verify your configuration" + hk_config 'rsakeyfile' "${rsakeyfile}" + fi +- config_list_foreach "$1" "keyfile" hk_config__keyfile + [ -n "${BannerFile}" ] && procd_append_param command -b "${BannerFile}" +- append_ports "${ipaddrs}" "${Port}" + [ "${IdleTimeout}" -ne 0 ] && procd_append_param command -I "${IdleTimeout}" + [ "${SSHKeepAlive}" -ne 0 ] && procd_append_param command -K "${SSHKeepAlive}" + [ "${MaxAuthTries}" -ne 0 ] && procd_append_param command -T "${MaxAuthTries}" +- [ "${RecvWindowSize}" -gt 0 -a "${RecvWindowSize}" -le 1048576 ] && \ ++ [ "${RecvWindowSize}" -gt 0 ] && { ++ # NB: OpenWrt increases receive window size to increase throughput on high latency links ++ # ref: validate_section_dropbear() ++ # default receive window size is 24576 (DEFAULT_RECV_WINDOW in default_options.h) ++ ++ # src/sysoptions.h ++ local MAX_RECV_WINDOW=10485760 ++ if [ "${RecvWindowSize}" -gt ${MAX_RECV_WINDOW} ] ; then ++ # separate logging is required because syslog misses dropbear's message ++ # Bad recv window '${RecvWindowSize}', using ${MAX_RECV_WINDOW} ++ # it's probably dropbear issue but we should handle this and notify user ++ logger -s -t "${NAME}" -p daemon.warn \ ++ "Option 'RecvWindowSize' is too high (${RecvWindowSize}), limiting to ${MAX_RECV_WINDOW}" ++ RecvWindowSize=${MAX_RECV_WINDOW} ++ fi + procd_append_param command -W "${RecvWindowSize}" ++ } + [ "${mdns}" -ne 0 ] && procd_add_mdns "ssh" "tcp" "$Port" "daemon=dropbear" + procd_set_param respawn + procd_close_instance +@@ -183,10 +358,21 @@ dropbear_instance() + + load_interfaces() + { +- config_get interface "$1" Interface +- config_get enable "$1" enable 1 +- +- [ "${enable}" = "1" ] && interfaces=" ${interface} ${interfaces}" ++ local enable ++ config_get_bool enable "$1" enable 1 ++ [ "${enable}" = "1" ] || return 0 ++ ++ local direct_iface iface ++ config_get direct_iface "$1" DirectInterface ++ direct_iface=$(normalize_list "${direct_iface}") ++ # 'DirectInterface' takes precedence over 'Interface' ++ if [ -n "${direct_iface}" ] ; then ++ iface=$(echo "${direct_iface}" | awk '{print $1}') ++ else ++ config_get iface "$1" Interface ++ iface=$(normalize_list "${iface}") ++ fi ++ interfaces="${interfaces} ${iface}" + } + + boot() +@@ -198,6 +384,7 @@ boot() + start_service() + { + hk_generate_as_needed ++ file_verify /etc/dropbear/authorized_keys config + + . /lib/functions.sh + . /lib/functions/network.sh +@@ -210,13 +397,14 @@ service_triggers() + { + local interfaces + +- procd_add_config_trigger "config.change" "dropbear" /etc/init.d/dropbear reload ++ procd_add_config_trigger "config.change" "${NAME}" /etc/init.d/dropbear reload + + config_load "${NAME}" +- config_foreach load_interfaces dropbear ++ config_foreach load_interfaces "${NAME}" + + [ -n "${interfaces}" ] && { +- for n in $interfaces ; do ++ local n ++ for n in $(printf '%s\n' ${interfaces} | sort -u) ; do + procd_add_interface_trigger "interface.*" $n /etc/init.d/dropbear reload + done + } +diff --git a/package/network/services/dropbear/patches/001-fix-MAX_UNAUTH_CLIENTS-regression.patch b/package/network/services/dropbear/patches/001-fix-MAX_UNAUTH_CLIENTS-regression.patch +deleted file mode 100644 +index e0dca544ec..0000000000 +--- a/package/network/services/dropbear/patches/001-fix-MAX_UNAUTH_CLIENTS-regression.patch ++++ /dev/null +@@ -1,134 +0,0 @@ +-From: Matt Johnston +-Date: Wed, 8 Jun 2022 21:26:20 +0800 +-Subject: Fix MAX_UNAUTH_CLIENTS regression +- +-Since re-exec change in 2022.82 Dropbear count +-treat authenticated sessions towards the unauthenticated +-session limit. This is fixed by passing the childpipe FD +-through to the re-execed process. +---- +- runopts.h | 5 +++-- +- svr-main.c | 21 +++++++++++---------- +- svr-runopts.c | 15 ++++++++++++--- +- 3 files changed, 26 insertions(+), 15 deletions(-) +- +---- a/runopts.h +-+++ b/runopts.h +-@@ -79,8 +79,9 @@ typedef struct svr_runopts { +- char *addresses[DROPBEAR_MAX_PORTS]; +- +- int inetdmode; +-- /* Hidden "-2" flag indicates it's re-executing itself */ +-- int reexec_child; +-+ /* Hidden "-2 childpipe_fd" flag indicates it's re-executing itself, +-+ stores the childpipe preauth file descriptor. Set to -1 otherwise. */ +-+ int reexec_childpipe; +- +- /* Flags indicating whether to use ipv4 and ipv6 */ +- /* not used yet +---- a/svr-main.c +-+++ b/svr-main.c +-@@ -71,7 +71,7 @@ int main(int argc, char ** argv) +- #endif +- +- #if DROPBEAR_DO_REEXEC +-- if (svr_opts.reexec_child) { +-+ if (svr_opts.reexec_childpipe >= 0) { +- #ifdef PR_SET_NAME +- /* Fix the "Name:" in /proc/pid/status, otherwise it's +- a FD number from fexecve. +-@@ -102,7 +102,7 @@ static void main_inetd() { +- +- seedrandom(); +- +-- if (!svr_opts.reexec_child) { +-+ if (svr_opts.reexec_childpipe < 0) { +- /* In case our inetd was lax in logging source addresses */ +- get_socket_address(0, NULL, NULL, &host, &port, 0); +- dropbear_log(LOG_INFO, "Child connection from %s:%s", host, port); +-@@ -115,10 +115,8 @@ static void main_inetd() { +- setsid(); +- } +- +-- /* Start service program +-- * -1 is a dummy childpipe, just something we can close() without +-- * mattering. */ +-- svr_session(0, -1); +-+ /* -1 for childpipe in the inetd case is discarded */ +-+ svr_session(0, svr_opts.reexec_childpipe); +- +- /* notreached */ +- } +-@@ -347,9 +345,10 @@ static void main_noinetd(int argc, char +- +- if (execfd >= 0) { +- #if DROPBEAR_DO_REEXEC +-- /* Add "-2" to the args and re-execute ourself. */ +-- char **new_argv = m_malloc(sizeof(char*) * (argc+3)); +-- int pos0 = 0, new_argc = argc+1; +-+ /* Add "-2 childpipe[1]" to the args and re-execute ourself. */ +-+ char **new_argv = m_malloc(sizeof(char*) * (argc+4)); +-+ char buf[10]; +-+ int pos0 = 0, new_argc = argc+2; +- +- /* We need to specially handle "dropbearmulti dropbear". */ +- if (multipath) { +-@@ -359,7 +358,9 @@ static void main_noinetd(int argc, char +- } +- +- memcpy(&new_argv[pos0], argv, sizeof(char*) * argc); +-- new_argv[new_argc-1] = "-2"; +-+ new_argv[new_argc-2] = "-2"; +-+ snprintf(buf, sizeof(buf), "%d", childpipe[1]); +-+ new_argv[new_argc-1] = buf; +- new_argv[new_argc] = NULL; +- +- if ((dup2(childsock, STDIN_FILENO) < 0)) { +---- a/svr-runopts.c +-+++ b/svr-runopts.c +-@@ -138,6 +138,7 @@ void svr_getopts(int argc, char ** argv) +- char* keepalive_arg = NULL; +- char* idle_timeout_arg = NULL; +- char* maxauthtries_arg = NULL; +-+ char* reexec_fd_arg = NULL; +- char* keyfile = NULL; +- char c; +- #if DROPBEAR_PLUGIN +-@@ -175,6 +176,7 @@ void svr_getopts(int argc, char ** argv) +- svr_opts.pubkey_plugin_options = NULL; +- #endif +- svr_opts.pass_on_env = 0; +-+ svr_opts.reexec_childpipe = -1; +- +- #ifndef DISABLE_ZLIB +- opts.compress_mode = DROPBEAR_COMPRESS_DELAYED; +-@@ -250,12 +252,12 @@ void svr_getopts(int argc, char ** argv) +- #if DROPBEAR_DO_REEXEC && NON_INETD_MODE +- /* For internal use by re-exec */ +- case '2': +-- svr_opts.reexec_child = 1; +-+ next = &reexec_fd_arg; +- break; +- #endif +- case 'p': +-- nextisport = 1; +-- break; +-+ nextisport = 1; +-+ break; +- case 'P': +- next = &svr_opts.pidfile; +- break; +-@@ -426,6 +428,13 @@ void svr_getopts(int argc, char ** argv) +- dropbear_log(LOG_INFO, "Forced command set to '%s'", svr_opts.forced_command); +- } +- +-+ if (reexec_fd_arg) { +-+ if (m_str_to_uint(reexec_fd_arg, &svr_opts.reexec_childpipe) == DROPBEAR_FAILURE +-+ || svr_opts.reexec_childpipe < 0) { +-+ dropbear_exit("Bad -2"); +-+ } +-+ } +-+ +- #if INETD_MODE +- if (svr_opts.inetdmode && ( +- opts.usingsyslog == 0 +diff --git a/package/network/services/dropbear/patches/100-pubkey_path.patch b/package/network/services/dropbear/patches/100-pubkey_path.patch +index 0403198062..0ecca900b4 100644 +--- a/package/network/services/dropbear/patches/100-pubkey_path.patch ++++ b/package/network/services/dropbear/patches/100-pubkey_path.patch +@@ -1,6 +1,6 @@ +---- a/svr-authpubkey.c +-+++ b/svr-authpubkey.c +-@@ -77,6 +77,13 @@ static void send_msg_userauth_pk_ok(cons ++--- a/src/svr-authpubkey.c +++++ b/src/svr-authpubkey.c ++@@ -78,6 +78,13 @@ static void send_msg_userauth_pk_ok(cons + const unsigned char* keyblob, unsigned int keybloblen); + static int checkfileperm(char * filename); + +@@ -14,7 +14,7 @@ + /* process a pubkey auth request, sending success or failure message as + * appropriate */ + void svr_auth_pubkey(int valid_user) { +-@@ -439,14 +446,21 @@ static int checkpubkey(const char* keyal ++@@ -462,14 +469,21 @@ static int checkpubkey(const char* keyal + if (checkpubkeyperms() == DROPBEAR_FAILURE) { + TRACE(("bad authorized_keys permissions, or file doesn't exist")) + } else { +@@ -44,7 +44,7 @@ + + authfile = fopen(filename, "r"); + if (!authfile) { +-@@ -520,27 +534,41 @@ static int checkpubkeyperms() { ++@@ -543,27 +557,41 @@ static int checkpubkeyperms() { + goto out; + } + +diff --git a/package/network/services/dropbear/patches/110-change_user.patch b/package/network/services/dropbear/patches/110-change_user.patch +index 04d1df3fde..9ef8f0cfbc 100644 +--- a/package/network/services/dropbear/patches/110-change_user.patch ++++ b/package/network/services/dropbear/patches/110-change_user.patch +@@ -1,6 +1,6 @@ +---- a/svr-chansession.c +-+++ b/svr-chansession.c +-@@ -985,12 +985,12 @@ static void execchild(const void *user_d ++--- a/src/svr-chansession.c +++++ b/src/svr-chansession.c ++@@ -984,12 +984,12 @@ static void execchild(const void *user_d + /* We can only change uid/gid as root ... */ + if (getuid() == 0) { + +diff --git a/package/network/services/dropbear/patches/130-ssh_ignore_x_args.patch b/package/network/services/dropbear/patches/130-ssh_ignore_x_args.patch +index d7f589801d..de0e5f2725 100644 +--- a/package/network/services/dropbear/patches/130-ssh_ignore_x_args.patch ++++ b/package/network/services/dropbear/patches/130-ssh_ignore_x_args.patch +@@ -1,8 +1,8 @@ +---- a/cli-runopts.c +-+++ b/cli-runopts.c +-@@ -325,6 +325,10 @@ void cli_getopts(int argc, char ** argv) +- case 'b': +- next = &bind_arg; ++--- a/src/cli-runopts.c +++++ b/src/cli-runopts.c ++@@ -340,6 +340,10 @@ void cli_getopts(int argc, char ** argv) ++ case 'z': ++ opts.disable_ip_tos = 1; + break; + + case 'x': + + /* compatibility with openssh cli +diff --git a/package/network/services/dropbear/patches/140-disable_assert.patch b/package/network/services/dropbear/patches/140-disable_assert.patch +index af01573dee..eb590a3895 100644 +--- a/package/network/services/dropbear/patches/140-disable_assert.patch ++++ b/package/network/services/dropbear/patches/140-disable_assert.patch +@@ -1,5 +1,5 @@ +---- a/dbutil.h +-+++ b/dbutil.h ++--- a/src/dbutil.h +++++ b/src/dbutil.h + @@ -80,7 +80,11 @@ int m_snprintf(char *str, size_t size, c + #define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL} + +diff --git a/package/network/services/dropbear/patches/160-lto-jobserver.patch b/package/network/services/dropbear/patches/160-lto-jobserver.patch +index fd80b986ae..1f3b298f35 100644 +--- a/package/network/services/dropbear/patches/160-lto-jobserver.patch ++++ b/package/network/services/dropbear/patches/160-lto-jobserver.patch +@@ -1,6 +1,6 @@ + --- a/Makefile.in + +++ b/Makefile.in +-@@ -200,17 +200,17 @@ dropbearkey: $(dropbearkeyobjs) ++@@ -220,17 +220,17 @@ dropbearkey: $(dropbearkeyobjs) + dropbearconvert: $(dropbearconvertobjs) + + dropbear: $(HEADERS) $(LIBTOM_DEPS) Makefile +@@ -22,7 +22,7 @@ + + + # multi-binary compilation. +-@@ -221,7 +221,7 @@ ifeq ($(MULTI),1) ++@@ -241,7 +241,7 @@ ifeq ($(MULTI),1) + endif + + dropbearmulti$(EXEEXT): $(HEADERS) $(MULTIOBJS) $(LIBTOM_DEPS) Makefile +diff --git a/package/network/services/dropbear/patches/600-allow-blank-root-password.patch b/package/network/services/dropbear/patches/600-allow-blank-root-password.patch +index 07ae022763..e72458dd6e 100644 +--- a/package/network/services/dropbear/patches/600-allow-blank-root-password.patch ++++ b/package/network/services/dropbear/patches/600-allow-blank-root-password.patch +@@ -1,5 +1,5 @@ +---- a/svr-auth.c +-+++ b/svr-auth.c ++--- a/src/svr-auth.c +++++ b/src/svr-auth.c + @@ -124,7 +124,7 @@ void recv_msg_userauth_request() { + AUTH_METHOD_NONE_LEN) == 0) { + TRACE(("recv_msg_userauth_request: 'none' request")) +diff --git a/package/network/services/dropbear/patches/900-configure-hardening.patch b/package/network/services/dropbear/patches/900-configure-hardening.patch +index 4f806f8b25..746694f48d 100644 +--- a/package/network/services/dropbear/patches/900-configure-hardening.patch ++++ b/package/network/services/dropbear/patches/900-configure-hardening.patch +@@ -1,6 +1,6 @@ + --- a/configure.ac + +++ b/configure.ac +-@@ -74,53 +74,6 @@ AC_ARG_ENABLE(harden, ++@@ -86,54 +86,6 @@ AC_ARG_ENABLE(harden, + + if test "$hardenbuild" -eq 1; then + AC_MSG_NOTICE(Checking for available hardened build flags:) +@@ -11,15 +11,15 @@ + - + - OLDLDFLAGS="$LDFLAGS" + - TESTFLAGS="-Wl,-pie" +-- LDFLAGS="$LDFLAGS $TESTFLAGS" +-- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], +-- [AC_MSG_NOTICE([Setting $TESTFLAGS])], ++- LDFLAGS="$TESTFLAGS $LDFLAGS" ++- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], ++- [AC_MSG_NOTICE([Setting $TESTFLAGS])], + - [ + - LDFLAGS="$OLDLDFLAGS" + - TESTFLAGS="-pie" +-- LDFLAGS="$LDFLAGS $TESTFLAGS" +-- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], +-- [AC_MSG_NOTICE([Setting $TESTFLAGS])], ++- LDFLAGS="$TESTFLAGS $LDFLAGS" ++- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], ++- [AC_MSG_NOTICE([Setting $TESTFLAGS])], + - [AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ] + - ) + - ] +@@ -27,30 +27,31 @@ + - # readonly elf relocation sections (relro) + - OLDLDFLAGS="$LDFLAGS" + - TESTFLAGS="-Wl,-z,now -Wl,-z,relro" +-- LDFLAGS="$LDFLAGS $TESTFLAGS" +-- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], +-- [AC_MSG_NOTICE([Setting $TESTFLAGS])], ++- LDFLAGS="$TESTFLAGS $LDFLAGS" ++- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], ++- [AC_MSG_NOTICE([Setting $TESTFLAGS])], + - [AC_MSG_NOTICE([Not setting $TESTFLAGS]); LDFLAGS="$OLDLDFLAGS" ] + - ) + - fi # non-static + - # stack protector. -strong is good but only in gcc 4.9 or later + - OLDCFLAGS="$CFLAGS" + - TESTFLAGS="-fstack-protector-strong" +-- CFLAGS="$CFLAGS $TESTFLAGS" +-- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], +-- [AC_MSG_NOTICE([Setting $TESTFLAGS])], ++- CFLAGS="$TESTFLAGS $CFLAGS" ++- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], ++- [AC_MSG_NOTICE([Setting $TESTFLAGS])], + - [ + - CFLAGS="$OLDCFLAGS" + - TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4" +-- CFLAGS="$CFLAGS $TESTFLAGS" +-- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], +-- [AC_MSG_NOTICE([Setting $TESTFLAGS])], ++- CFLAGS="$TESTFLAGS $CFLAGS" ++- AC_LINK_IFELSE([AC_LANG_PROGRAM([])], ++- [AC_MSG_NOTICE([Setting $TESTFLAGS])], + - [AC_MSG_NOTICE([Not setting $TESTFLAGS]); CFLAGS="$OLDCFLAGS" ] + - ) + - ] + - ) + - # FORTIFY_SOURCE + - DB_TRYADDCFLAGS([-D_FORTIFY_SOURCE=2]) +- ++- + # Spectre v2 mitigations + DB_TRYADDCFLAGS([-mfunction-return=thunk]) ++ DB_TRYADDCFLAGS([-mindirect-branch=thunk]) +diff --git a/package/network/services/dropbear/patches/901-bundled-libs-cflags.patch b/package/network/services/dropbear/patches/901-bundled-libs-cflags.patch +index 2432b4ef72..4da01c9edb 100644 +--- a/package/network/services/dropbear/patches/901-bundled-libs-cflags.patch ++++ b/package/network/services/dropbear/patches/901-bundled-libs-cflags.patch +@@ -1,48 +1,29 @@ +---- a/libtomcrypt/makefile_include.mk +-+++ b/libtomcrypt/makefile_include.mk +-@@ -94,6 +94,13 @@ endif ++--- a/configure.ac +++++ b/configure.ac ++@@ -44,11 +44,8 @@ fi ++ # LTM_CFLAGS is given to ./configure by the user, ++ # DROPBEAR_LTM_CFLAGS is substituted in the LTM Makefile.in ++ DROPBEAR_LTM_CFLAGS="$LTM_CFLAGS" ++-if test -z "$DROPBEAR_LTM_CFLAGS"; then ++- DROPBEAR_LTM_CFLAGS="-O3 -funroll-loops -fomit-frame-pointer" ++-fi ++-AC_MSG_NOTICE(Setting LTM_CFLAGS to $DROPBEAR_LTM_CFLAGS) ++-AC_ARG_VAR(LTM_CFLAGS, CFLAGS for bundled libtommath. Default -O3 -funroll-loops -fomit-frame-pointer) +++AC_MSG_NOTICE(Setting LTM_CFLAGS to '$DROPBEAR_LTM_CFLAGS') +++AC_ARG_VAR(LTM_CFLAGS, CFLAGS for bundled libtommath. Defaults to empty string) ++ AC_SUBST(DROPBEAR_LTM_CFLAGS) + +- LTC_CFLAGS += -Wno-type-limits ++ AC_MSG_NOTICE([Checking if compiler '$CC' supports -Wno-pointer-sign]) ++--- a/libtomcrypt/src/headers/tomcrypt_dropbear.h +++++ b/libtomcrypt/src/headers/tomcrypt_dropbear.h ++@@ -7,8 +7,10 @@ + +-+ifdef OPENWRT_BUILD +-+ ifeq (-Os,$(filter -Os,$(CFLAGS))) +-+ LTC_CFLAGS += -DLTC_SMALL_CODE +-+ endif +-+else +-+ ### ! OPENWRT_BUILD +-+ +- ifdef LTC_DEBUG +- $(info Debug build) +- # compile for DEBUGGING (required for ccmalloc checking!!!) +-@@ -121,6 +128,9 @@ endif +- endif # COMPILE_SMALL +- endif # COMPILE_DEBUG ++ /* Use small code where possible */ ++ #if DROPBEAR_SMALL_CODE +++#ifndef LTC_SMALL_CODE ++ #define LTC_SMALL_CODE ++ #endif +++#endif + +-+ ### ! OPENWRT_BUILD +-+endif +-+ +- +- ifneq ($(findstring clang,$(CC)),) +- LTC_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header -Wno-missing-field-initializers +---- a/libtommath/makefile_include.mk +-+++ b/libtommath/makefile_include.mk +-@@ -70,6 +70,9 @@ else +- LTM_CFLAGS += -Wsystem-headers +- endif +- +-+ifndef OPENWRT_BUILD +-+ ### ! OPENWRT_BUILD +-+ +- ifdef COMPILE_DEBUG +- #debug +- LTM_CFLAGS += -g3 +-@@ -90,6 +93,9 @@ endif +- +- endif # COMPILE_SIZE +- +-+ ### ! OPENWRT_BUILD +-+endif +-+ +- ifneq ($(findstring clang,$(CC)),) +- LTM_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header +- endif ++ /* Fewer entries needed */ ++ #define TAB_SIZE 5 +diff --git a/package/network/services/dropbear/patches/910-signkey-fix-use-of-rsa-sha2-256-pubkeys.patch b/package/network/services/dropbear/patches/910-signkey-fix-use-of-rsa-sha2-256-pubkeys.patch +index f078814403..43dd1426b1 100644 +--- a/package/network/services/dropbear/patches/910-signkey-fix-use-of-rsa-sha2-256-pubkeys.patch ++++ b/package/network/services/dropbear/patches/910-signkey-fix-use-of-rsa-sha2-256-pubkeys.patch +@@ -19,9 +19,9 @@ Signed-off-by: Petr Štetiar + signkey.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +---- a/signkey.c +-+++ b/signkey.c +-@@ -646,8 +646,12 @@ int buf_verify(buffer * buf, sign_key *k ++--- a/src/signkey.c +++++ b/src/signkey.c ++@@ -652,10 +652,18 @@ int buf_verify(buffer * buf, sign_key *k + sigtype = signature_type_from_name(type_name, type_name_len); + m_free(type_name); + +@@ -29,10 +29,16 @@ Signed-off-by: Petr Štetiar + - dropbear_exit("Non-matching signing type"); + + if (sigtype == DROPBEAR_SIGNATURE_NONE) { + + dropbear_exit("No signature type"); +-+ } +-+ +-+ if ((expect_sigtype != DROPBEAR_SIGNATURE_RSA_SHA256) && (expect_sigtype != sigtype)) { +-+ dropbear_exit("Non-matching signing type"); + } + +++#if DROPBEAR_RSA +++#if DROPBEAR_RSA_SHA256 +++ if ((expect_sigtype != DROPBEAR_SIGNATURE_RSA_SHA256) && (expect_sigtype != sigtype)) { +++ dropbear_exit("Non-matching signing type"); +++ } +++#endif +++#endif +++ + keytype = signkey_type_from_signature(sigtype); ++ #if DROPBEAR_DSS ++ if (keytype == DROPBEAR_SIGNKEY_DSS) { +-- +2.34.1 +