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