Skip to content

Commit

Permalink
dropbear: YourFritz specific patches
Browse files Browse the repository at this point in the history
- adjust patches to 2019.78 version
- add dependency on 'privatekeypassword'
  • Loading branch information
PeterPawn committed Apr 1, 2021
1 parent 8206a2c commit 8d34175
Show file tree
Hide file tree
Showing 5 changed files with 482 additions and 4 deletions.
9 changes: 9 additions & 0 deletions make/dropbear/Config.in
Expand Up @@ -104,3 +104,12 @@ config FREETZ_PACKAGE_DROPBEAR_NONFREETZ
on non freetz boxes.
(Fix for missing devfs and changes to default paths)
Will select "static" on firmwares not supporting dynamically linked freetz binaries.

config FREETZ_PACKAGE_DROPBEAR_YOURFRITZ
bool "build for YourFritz environment"
depends on FREETZ_PACKAGE_DROPBEAR && FREETZ_PACKAGE_DROPBEAR_NONFREETZ
select FREETZ_PACKAGE_PRIVATEKEYPASSWORD
select FREETZ_LIB_libprivatekeypassword
default n
help
build the special version for YourFritz images
33 changes: 29 additions & 4 deletions make/dropbear/dropbear.mk
Expand Up @@ -13,11 +13,19 @@ ifeq ($(strip $(FREETZ_PACKAGE_DROPBEAR_WITH_ZLIB)),y)
$(PKG)_DEPENDS_ON += zlib
endif

$(PKG)_PROGRAMS:=dropbear
$(PKG)_MAKE_OPTIONS:=MULTI=1

ifeq ($(strip $(FREETZ_PACKAGE_DROPBEAR_SERVER_ONLY)),y)
$(PKG)_MAKE_OPTIONS:=PROGRAMS="dropbear dropbearkey" MULTI=1
$(PKG)_PROGRAMS += dropbearkey
$(PKG)_EXCLUDED += $(patsubst %,$($(PKG)_DEST_DIR)/usr/bin/%,ssh scp)
else
$(PKG)_MAKE_OPTIONS:=PROGRAMS="dropbear dbclient dropbearkey scp" MULTI=1 SCPPROGRESS=1
$(PKG)_PROGRAMS += dbclient
$(PKG)_PROGRAMS += scp
ifneq ($(strip $(FREETZ_PACKAGE_DROPBEAR_YOURFRITZ)),y)
$(PKG)_PROGRAMS += dropbearkey
endif
$(PKG)_MAKE_OPTIONS += SCPPROGRESS=1
endif

# disable argument null checking (libtomcrypt)
Expand All @@ -29,6 +37,15 @@ $(PKG)_CPPFLAGS += -DDROPBEAR_X11FWD=0
# enable/disable reverse DNS lookups
$(PKG)_CPPFLAGS += -DDO_HOST_LOOKUP=$(if $(FREETZ_PACKAGE_DROPBEAR_DISABLE_HOST_LOOKUP),0,1)

$(PKG)_EXTRA_LDFLAGS += -Wl,--gc-sections

ifeq ($(strip $(FREETZ_PACKAGE_DROPBEAR_YOURFRITZ)),y)
$(PKG)_CPPFLAGS+=-DDROPBEAR_YOURFRITZ
$(PKG)_CONDITIONAL_PATCHES+=yourfritz
$(PKG)_EXTRA_LIBS += -lprivatekeypassword -lcrypto
$(PKG)_DEPENDS_ON += privatekeypassword
endif

ifeq ($(strip $(FREETZ_PACKAGE_DROPBEAR_NONFREETZ)),y)
$(PKG)_CPPFLAGS += -DDB_NONFREETZ
endif
Expand All @@ -37,6 +54,10 @@ ifeq ($(strip $(FREETZ_PACKAGE_DROPBEAR_SFTP_SERVER)),y)
$(PKG)_CPPFLAGS += -DDROPBEAR_SFTPSERVER
endif

ifeq ($(strip $(FREETZ_PACKAGE_DROPBEAR_STATIC)),y)
$(PKG)_MAKE_OPTIONS += STATIC=1
endif

$(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_SERVER_ONLY
$(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_WITH_ZLIB
$(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_UTMP
Expand All @@ -45,6 +66,7 @@ $(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_SFTP_SERVER
$(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_DISABLE_HOST_LOOKUP
$(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_STATIC
$(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_NONFREETZ
$(PKG)_REBUILD_SUBOPTS += FREETZ_PACKAGE_DROPBEAR_YOURFRITZ

#$(PKG)_CONFIGURE_PRE_CMDS += $(AUTORECONF)

Expand All @@ -65,6 +87,8 @@ $(PKG)_CONFIGURE_OPTIONS += $(if $(FREETZ_PACKAGE_DROPBEAR_UTMP),,--disable-putu
$(PKG)_CONFIGURE_OPTIONS += --disable-pututxline
$(PKG)_CONFIGURE_OPTIONS += --enable-bundled-libtom

$(PKG)_MAKE_OPTIONS += PROGRAMS="$($(PKG)_PROGRAMS)"

$(PKG_SOURCE_DOWNLOAD)
$(PKG_UNPACKED)
$(PKG_CONFIGURED_CONFIGURE)
Expand All @@ -73,8 +97,9 @@ $($(PKG)_BINARY): $($(PKG)_DIR)/.configured
$(SUBMAKE) -C $(DROPBEAR_DIR) \
$(DROPBEAR_MAKE_OPTIONS) \
EXTRA_CFLAGS="-ffunction-sections -fdata-sections" \
EXTRA_CPPFLAGS="$(DROPBEAR_CPPFLAGS)" \
EXTRA_LDFLAGS="-Wl,--gc-sections"
CPPFLAGS="$(DROPBEAR_CPPFLAGS)" \
EXTRA_LDFLAGS="$(DROPBEAR_EXTRA_LDFLAGS)" \
EXTRA_LIBS="$(DROPBEAR_EXTRA_LIBS)"

$($(PKG)_TARGET_BINARY): $($(PKG)_BINARY)
$(INSTALL_BINARY_STRIP)
Expand Down
280 changes: 280 additions & 0 deletions make/dropbear/patches/yourfritz/900-boxcert.patch
@@ -0,0 +1,280 @@
--- cli-runopts.c
+++ cli-runopts.c
@@ -67,8 +67,10 @@
"-s Request a subsystem (use by external sftp)\n"
"-o option Set option in OpenSSH-like format ('-o help' to list options)\n"
#if DROPBEAR_CLI_PUBKEY_AUTH
+#ifndef DROPBEAR_YOURFRITZ
"-i <identityfile> (multiple allowed, default %s)\n"
#endif
+#endif
#if DROPBEAR_CLI_AGENTFWD
"-A Enable agent auth forwarding\n"
#endif
@@ -97,6 +99,20 @@
#if DEBUG_TRACE
"-v verbose (compiled with DEBUG_TRACE)\n"
#endif
+#ifdef DROPBEAR_YOURFRITZ
+ "\nThis is a special version created from the Freetz trunk and it's\n"
+ "stripped down to the really needed functions to be usable on a FRITZ!Box\n"
+ "device with the RSA key stored there. It supports only a limited set of\n"
+ "KEX and CIPHER algorithms and isn't backward compatible to older SSH\n"
+ "clients (by intention). It allows only root user logins with public key\n"
+ "authentication, no other user(s) and/or methods will be accepted.\n"
+ "It's not optimized for size and the usually disabled TRACE output option\n"
+ "is explicitly enabled.\n"
+ "The FRITZ!Box key (" DROPBEAR_DEFAULT_CLI_AUTHKEY ") is the only supported\n"
+ "RSA key file for both server and client usage and it will be read only\n"
+ "from this location with automatic decryption.\n\n"
+#endif
+
,DROPBEAR_VERSION, cli_opts.progname,
#if DROPBEAR_CLI_PUBKEY_AUTH
DROPBEAR_DEFAULT_CLI_AUTHKEY,
--- common-runopts.c
+++ common-runopts.c
@@ -31,8 +31,128 @@
#include "algo.h"
#include "dbrandom.h"

+#ifdef DROPBEAR_YOURFRITZ
+
+// it's possible to use OpenSSL libraries here, because we're on an AVM
+// router, where the OpenSSL library libcrypto.so is almost ever available
+// and it's even used to store the encrypted RSA key file ... so we can
+// use it without any scruple for the "lean SSH server" too
+
+// libtomcrypt contains own versions of the SHAx defines, we don't need them
+// here really and so we'll simply remove the previous definitions
+#undef SHA1
+#undef SHA256
+#undef SHA512
+
+// OpenSSL definitions and reading of device-specific password for the key file
+#include <openssl/pem.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <privatekeypassword/privatekeypassword.h>
+
+#endif
+
runopts opts; /* GLOBAL */

+int buf_readdevicekey(buffer* buf, const char* filename) {
+ int ret = DROPBEAR_FAILURE;
+
+ char *password = getPrivateKeyPassword();
+ if (password == NULL) {
+ TRACE(("error reading device specific password"))
+ return ret;
+ }
+
+ FILE *fp = fopen(filename, "rb");
+ if (fp == NULL) {
+ TRACE(("error opening RSA key file %s", filename))
+ return ret;
+ }
+
+ OpenSSL_add_all_algorithms();
+
+ RSA *boxRSA = RSA_new();
+ if (boxRSA == NULL) {
+ fclose(fp);
+ TRACE(("error allocating RSA structure"))
+ EVP_cleanup();
+ return ret;
+ }
+
+ if (PEM_read_RSAPrivateKey(fp, &boxRSA, NULL, (void *) password) == NULL) {
+ unsigned long osslErr = ERR_get_error();
+ RSA_free(boxRSA);
+ fclose(fp);
+ TRACE(("error reading RSA key\n%s", ERR_error_string(osslErr, NULL)))
+ EVP_cleanup();
+ return ret;
+ }
+
+ fclose(fp);
+ TRACE2(("box key read successfully, extracting key components"))
+
+// copy RSA key components to buffer, it's the simplest way to exchange data
+// we need e, n, d, p, q in this order, preceded by a "ssh-rsa" string
+ buf_putstring(buf, "ssh-rsa", 7);
+
+ BIGNUM ** numbers[6];
+ int len = 0, i = 0;
+ unsigned char * p;
+ BIGNUM *** current;
+
+// this list is the source of components and the order to copy them
+ numbers[0] = &boxRSA->e;
+ numbers[1] = &boxRSA->n;
+ numbers[2] = &boxRSA->d;
+ numbers[3] = &boxRSA->p;
+ numbers[4] = &boxRSA->q;
+ numbers[5] = NULL;
+
+// determine needed conversion buffer size
+ current = numbers;
+ while (*current != NULL) {
+ int newlen = BN_bn2mpi(**current, NULL);
+ if (newlen > len) len = newlen;
+ current++;
+ }
+
+// allocate a structure able to contain a serialized mp_int
+ struct {
+ int len;
+ unsigned char data[];
+ } * mp = malloc(len);
+ if (mp == NULL) {
+ TRACE(("unable to allocate memory to convert from BIGNUM to buffer"))
+ RSA_free(boxRSA);
+ EVP_cleanup();
+ return ret;
+ }
+
+// we use a temporary buffer, because both BIGNUM implementations want an unsigned
+// char pointer and the internal structures of "mp_int" and "BIGNUM" are different
+// ... so we'll convert BIGNUM to mpi (4 byte length + variable size data) and write
+// the result to our buffer
+ current = numbers;
+ while (*current != NULL) {
+ BN_bn2mpi(**current, (unsigned char *) mp);
+ buf_putstring(buf, mp->data, mp->len);
+ current++;
+ }
+ for (i = 0, p = (unsigned char *) mp; i < len; i++, p++) *p = '\0';
+ free(mp);
+
+// shutdown OpenSSL routines
+ TRACE2(("freeing OpenSSL RSA structure"))
+ RSA_free(boxRSA);
+ TRACE2(("calling EVP_cleanup"))
+ EVP_cleanup();
+
+ ret = DROPBEAR_SUCCESS;
+ TRACE(("using device key file from %s", filename))
+ return ret;
+}
+
/* returns success or failure, and the keytype in *type. If we want
* to restrict the type, type can contain a type to return */
int readhostkey(const char * filename, sign_key * hostkey,
@@ -43,7 +163,11 @@

buf = buf_new(MAX_PRIVKEY_SIZE);

+#ifdef DROPBEAR_YOURFRITZ
+ if (buf_readdevicekey(buf, filename) == DROPBEAR_FAILURE) {
+#else
if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
+#endif
goto out;
}
buf_setpos(buf, 0);
--- svr-runopts.c
+++ svr-runopts.c
@@ -43,6 +43,7 @@

fprintf(stderr, "Dropbear server v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
"Usage: %s [options]\n"
+#ifndef DROPBEAR_YOURFRITZ
"-b bannerfile Display the contents of bannerfile"
" before user login\n"
" (default: none)\n"
@@ -60,6 +61,7 @@
#if DROPBEAR_DELAY_HOSTKEY
"-R Create hostkeys as required\n"
#endif
+#endif
#ifdef DROPBEAR_SFTPSERVER
"-S sftpserver Set path to sftp server\n"
" (default: %s)\n"
@@ -73,8 +75,10 @@
#if DO_MOTD
"-m Don't display the motd on login\n"
#endif
+#ifndef DROPBEAR_YOURFRITZ
"-w Disallow root logins\n"
"-0 Allow only root logins\n"
+#endif
#ifdef HAVE_GETGROUPLIST
"-G Restrict logins to members of specified group\n"
#endif
@@ -110,7 +114,21 @@
#if DEBUG_TRACE
"-v verbose (compiled with DEBUG_TRACE)\n"
#endif
+#ifdef DROPBEAR_YOURFRITZ
+ "\nThis is a special version created from the Freetz trunk and it's\n"
+ "stripped down to the really needed functions to be usable on a FRITZ!Box\n"
+ "device with the RSA key stored there. It supports only a limited set of\n"
+ "KEX and CIPHER algorithms and isn't backward compatible to older SSH\n"
+ "clients (by intention). It allows only root user logins with public key\n"
+ "authentication, no other user(s) and/or methods will be accepted.\n"
+ "It's not optimized for size and the usually disabled TRACE output option\n"
+ "is explicitly enabled.\n"
+ "The FRITZ!Box key (" RSA_PRIV_FILENAME ") is the only supported\n"
+ "RSA key file for both server and client usage and it will be read only\n"
+ "from this location with automatic decryption.\n\n"
+#endif
,DROPBEAR_VERSION, progname,
+#ifndef DROPBEAR_YOURFRITZ
#if DROPBEAR_DSS
DSS_PRIV_FILENAME,
#endif
@@ -120,6 +138,7 @@
#if DROPBEAR_ECDSA
ECDSA_PRIV_FILENAME,
#endif
+#endif
#ifdef DROPBEAR_SFTPSERVER
SFTPSERVER_PATH,
#endif
@@ -191,6 +210,11 @@
opts.keepalive_secs = DEFAULT_KEEPALIVE;
opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;

+#ifdef DROPBEAR_YOURFRITZ
+ svr_opts.rootonlylogin = 1;
+ svr_opts.noauthpass = 1;
+#endif
+
#if DROPBEAR_SVR_REMOTETCPFWD
opts.listen_fwd_all = 0;
#endif
@@ -201,6 +225,7 @@

for (j = 1; (c = argv[i][j]) != '\0' && !next && !nextisport; j++) {
switch (c) {
+#ifndef DROPBEAR_YOURFRITZ
case 'b':
next = &svr_opts.bannerfile;
break;
@@ -214,6 +239,7 @@
case 'R':
svr_opts.delay_hostkey = 1;
break;
+#endif
#ifdef DROPBEAR_SFTPSERVER
case 'S':
next = &svr_opts.sftppath;
@@ -260,6 +286,7 @@
svr_opts.domotd = 0;
break;
#endif
+#ifndef DROPBEAR_YOURFRITZ
case 'w':
svr_opts.norootlogin = 1;
break;
@@ -271,6 +298,7 @@
next = &svr_opts.restrict_group;
break;
#endif
+#endif
case 'W':
next = &recv_window_arg;
break;

0 comments on commit 8d34175

Please sign in to comment.