commit 7f23c5dc0f442de9fe07c076297c3a74f2a34e72
parent c364095c441d8891ac8d942261eccf3fd24b5423
Author: Daniel Barlow <dan@telent.net>
Date: Wed, 11 Mar 2026 18:22:39 +0000
update dropbear, simplify authorized_keys patch
Diffstat:
2 files changed, 33 insertions(+), 204 deletions(-)
diff --git a/overlay.nix b/overlay.nix
@@ -167,24 +167,9 @@ extraPkgs
dropbear = crossOnly prev.dropbear (
d:
d.overrideAttrs (o: rec {
- # nixpkgs 25.05 contains newer dropbear (2025.87) than this,
- # we can drop this override when that's ready
- version = "2024.85";
- src = final.fetchurl {
- url = "https://matt.ucc.asn.au/dropbear/releases/dropbear-${version}.tar.bz2";
- sha256 = "sha256-hrA2xDOmnYnOUeuuM11lxHc4zPkNE+XrD+qDLlVtpQI=";
- };
- patches =
- # in 24.11 we need to update nixpkgs patch for new version of dropbear
- let
- passPath = final.runCommand "pass-path" { } ''
- sed < ${builtins.head o.patches} -e 's,svr-chansession.c,src/svr-chansession.c,g' > $out
- '';
- in
- [
- (if (lib.versionOlder o.version "2024") then passPath else (builtins.head o.patches))
- ./pkgs/dropbear/add-authkeyfile-option.patch
- ];
+ patches = o.patches ++ [
+ ./pkgs/dropbear/add-authkeyfile-option.patch
+ ];
postPatch = ''
(echo '#define DSS_PRIV_FILENAME "/run/dropbear/dropbear_dss_host_key"'
echo '#define RSA_PRIV_FILENAME "/run/dropbear/dropbear_rsa_host_key"'
diff --git a/pkgs/dropbear/add-authkeyfile-option.patch b/pkgs/dropbear/add-authkeyfile-option.patch
@@ -1,31 +1,5 @@
-From 9c0ac9e41a393e0f16a57e36d9369d61d39e9aa5 Mon Sep 17 00:00:00 2001
-From: Daniel Barlow <dan@telent.net>
-Date: Fri, 23 Aug 2024 11:33:24 +0100
-Subject: [PATCH] add -U otion to set path to authorized_keys file
-
-based on https://github.com/mkj/dropbear/pull/35
-by Salvador Fandino sfandino@yahoo.com
-
-- Allow authorized keys inside dirs with the sticky bit set
-
-- Add option -U for customizing authorized_keys path
-
-- Updated for dropbear 2024.85 (source files moved to src/)
-
-- allow %u, %d, %n "format specifiers" in pathname so that the user's
- username/homedir/uid can be embedded into the path
----
- Makefile.in | 2 +-
- manpages/dropbear.8 | 3 +
- src/pathexpand.c | 149 +++++++++++++++++++++++++++++++++++++++++++
- src/runopts.h | 3 +-
- src/svr-authpubkey.c | 86 +++++++++++--------------
- src/svr-runopts.c | 10 +++
- 6 files changed, 203 insertions(+), 50 deletions(-)
- create mode 100644 src/pathexpand.c
-
diff --git a/Makefile.in b/Makefile.in
-index 5ebfca2..686fbfb 100644
+index fe63a80..b050be3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -51,7 +51,7 @@ COMMONOBJS = $(patsubst %,$(OBJ_DIR)/%,$(_COMMONOBJS))
@@ -38,7 +12,7 @@ index 5ebfca2..686fbfb 100644
_CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
diff --git a/manpages/dropbear.8 b/manpages/dropbear.8
-index bdb2ea0..c8d450d 100644
+index 72be0ae..78e0a99 100644
--- a/manpages/dropbear.8
+++ b/manpages/dropbear.8
@@ -29,6 +29,9 @@ or automatically with the '-R' option. See "Host Key Files" below.
@@ -207,171 +181,45 @@ index 0000000..07e6955
+ return filename; /* caller must free */
+}
diff --git a/src/runopts.h b/src/runopts.h
-index 1c88b5c..707008f 100644
+index c8072b3..73ffdb1 100644
--- a/src/runopts.h
+++ b/src/runopts.h
-@@ -128,7 +128,8 @@ typedef struct svr_runopts {
+@@ -124,6 +124,7 @@ typedef struct svr_runopts {
char * pidfile;
- char * forced_command;
-- char* interface;
-+ char * authkeysfile;
-+ char * interface;
+ char * authorized_keys_dir;
++ char * authorized_keys_file;
- #if DROPBEAR_PLUGIN
- /* malloced */
+ char * forced_command;
+ char* interface;
diff --git a/src/svr-authpubkey.c b/src/svr-authpubkey.c
-index 5d298cb..54502f4 100644
+index 94ae728..9da6654 100644
--- a/src/svr-authpubkey.c
+++ b/src/svr-authpubkey.c
-@@ -73,7 +73,7 @@
+@@ -72,6 +72,7 @@
+ #define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */
+ static char * authorized_keys_filepath(void);
++extern char * pathexpand(char *input);
static int checkpubkey(const char* keyalgo, unsigned int keyalgolen,
const unsigned char* keyblob, unsigned int keybloblen);
--static int checkpubkeyperms(void);
-+static int checkpubkeyperms(char *filename, char *base);
- static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen,
- const unsigned char* keyblob, unsigned int keybloblen);
- static int checkfileperm(char * filename);
-@@ -431,6 +431,7 @@ out:
- return ret;
- }
-
-+extern char *pathexpand(char *input);
+ static int checkpubkeyperms(void);
+@@ -441,6 +442,10 @@ static char *authorized_keys_filepath() {
+ char *pathname = NULL, *dir = NULL;
+ const char *filename = "authorized_keys";
- /* Checks whether a specified publickey (and associated algorithm) is an
- * acceptable key for authentication */
-@@ -458,19 +459,12 @@ static int checkpubkey(const char* keyalgo, unsigned int keyalgolen,
- dropbear_exit("Failed to set euid");
- }
- #endif
-+ filename = pathexpand(svr_opts.authkeysfile);
++ if(svr_opts.authorized_keys_file) {
++ return pathexpand(svr_opts.authorized_keys_file);
++ };
+
- /* check file permissions, also whether file exists */
-- if (checkpubkeyperms() == DROPBEAR_FAILURE) {
-- TRACE(("bad authorized_keys permissions, or file doesn't exist"))
-+ if (checkpubkeyperms(filename, ses.authstate.pw_dir) == DROPBEAR_FAILURE) {
-+ TRACE(("bad authorized keys permissions on %s, or file doesn't exist", filename))
- } else {
-- /* we don't need to check pw and pw_dir for validity, since
-- * its been done in checkpubkeyperms. */
-- len = strlen(ses.authstate.pw_dir);
-- /* allocate max required pathname storage,
-- * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
-- filename = m_malloc(len + 22);
-- snprintf(filename, len + 22, "%s/.ssh/authorized_keys",
-- ses.authstate.pw_dir);
--
- authfile = fopen(filename, "r");
- if (!authfile) {
- TRACE(("checkpubkey: failed opening %s: %s", filename, strerror(errno)))
-@@ -486,7 +480,7 @@ static int checkpubkey(const char* keyalgo, unsigned int keyalgolen,
- if (authfile == NULL) {
- goto out;
- }
-- TRACE(("checkpubkey: opened authorized_keys OK"))
-+ TRACE(("checkpubkey: opened %s OK", filename))
-
- line = buf_new(MAX_AUTHKEYS_LINE);
- line_num = 0;
-@@ -524,53 +518,47 @@ out:
-
- /* Returns DROPBEAR_SUCCESS if file permissions for pubkeys are ok,
- * DROPBEAR_FAILURE otherwise.
-- * Checks that the user's homedir, ~/.ssh, and
-- * ~/.ssh/authorized_keys are all owned by either root or the user, and are
-+ * Checks filename and its parent directories recursively until the
-+ * base directory (usually ~/) or one of its ancestors (up to /) is
-+ * reached.
-+ * The files and directories must be all owned by root or the user, and be
- * g-w, o-w */
--static int checkpubkeyperms() {
--
-- char* filename = NULL;
-+static int checkpubkeyperms(char *filename, char *base) {
-+ char* path = NULL;
- int ret = DROPBEAR_FAILURE;
- unsigned int len;
-
-- TRACE(("enter checkpubkeyperms"))
--
-- if (ses.authstate.pw_dir == NULL) {
-- goto out;
-- }
-+ TRACE(("enter checkpubkeyperms(%s, %s)", filename, base))
+ dir = expand_homedir_path_home(svr_opts.authorized_keys_dir,
+ ses.authstate.pw_dir);
-- if ((len = strlen(ses.authstate.pw_dir)) == 0) {
-+ if ((base == NULL) || (base[0] != '/') ||
-+ (filename == NULL) || (filename[0] != '/')) {
-+ /* both filename and base must be absolute paths */
- goto out;
- }
-
-- /* allocate max required pathname storage,
-- * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
-- len += 22;
-- filename = m_malloc(len);
-- strlcpy(filename, ses.authstate.pw_dir, len);
-+ len = strlen(filename);
-+ path = m_strdup(filename);
-
-- /* check ~ */
-- if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
-- goto out;
-- }
--
-- /* check ~/.ssh */
-- strlcat(filename, "/.ssh", len);
-- if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
-- goto out;
-- }
-+ while (checkfileperm(len ? path : "/") == DROPBEAR_SUCCESS) {
-+ /* check if we are on base trail and if this is the
-+ * case, return success */
-+ if ((strncmp(base, path, len) == 0) &&
-+ (!len || (base[len] == '\0') || (base[len] == '/'))) {
-+ ret = DROPBEAR_SUCCESS;
-+ break;
-+ }
-
-- /* now check ~/.ssh/authorized_keys */
-- strlcat(filename, "/authorized_keys", len);
-- if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
-- goto out;
-+ /* look for parent directory */
-+ while (--len) {
-+ if (path[len] == '/') {
-+ path[len] = '\0';
-+ break;
-+ }
-+ }
- }
-
-- /* file looks ok, return success */
-- ret = DROPBEAR_SUCCESS;
--
- out:
-- m_free(filename);
-+ m_free(path);
-
- TRACE(("leave checkpubkeyperms"))
- return ret;
-@@ -596,7 +584,9 @@ static int checkfileperm(char * filename) {
- TRACE(("wrong ownership"))
- }
- /* check permissions - don't want group or others +w */
-- if (filestat.st_mode & (S_IWGRP | S_IWOTH)) {
-+ /* (unless sticky dir, which is allowed) */
-+ if ((filestat.st_mode & (S_IWGRP | S_IWOTH)) &&
-+ !(S_ISDIR(filestat.st_mode) && (filestat.st_mode & S_ISVTX))) {
- badperm = 1;
- TRACE(("wrong perms"))
- }
diff --git a/src/svr-runopts.c b/src/svr-runopts.c
-index c4f83c1..faddfa2 100644
+index 8034c50..986c552 100644
--- a/src/svr-runopts.c
+++ b/src/svr-runopts.c
-@@ -147,6 +147,7 @@ void svr_getopts(int argc, char ** argv) {
+@@ -150,6 +150,7 @@ void svr_getopts(int argc, char ** argv) {
char* maxauthtries_arg = NULL;
char* reexec_fd_arg = NULL;
char* keyfile = NULL;
@@ -379,16 +227,15 @@ index c4f83c1..faddfa2 100644
char c;
#if DROPBEAR_PLUGIN
char* pubkey_plugin = NULL;
-@@ -173,6 +174,8 @@ void svr_getopts(int argc, char ** argv) {
- svr_opts.hostkey = NULL;
+@@ -177,6 +178,7 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.delay_hostkey = 0;
svr_opts.pidfile = expand_homedir_path(DROPBEAR_PIDFILE);
-+ svr_opts.authkeysfile = "%d/.ssh/authorized_keys";
-+
+ svr_opts.authorized_keys_dir = "~/.ssh";
++ svr_opts.authorized_keys_file = NULL;
#if DROPBEAR_SVR_LOCALANYFWD
svr_opts.nolocaltcp = 0;
#endif
-@@ -322,6 +325,9 @@ void svr_getopts(int argc, char ** argv) {
+@@ -344,6 +346,9 @@ void svr_getopts(int argc, char ** argv) {
case 'u':
/* backwards compatibility with old urandom option */
break;
@@ -398,17 +245,14 @@ index c4f83c1..faddfa2 100644
#if DROPBEAR_PLUGIN
case 'A':
next = &pubkey_plugin;
-@@ -372,6 +378,10 @@ void svr_getopts(int argc, char ** argv) {
+@@ -394,6 +399,10 @@ void svr_getopts(int argc, char ** argv) {
addhostkey(keyfile);
keyfile = NULL;
}
+ if (authkeysfile) {
-+ svr_opts.authkeysfile = m_strdup(authkeysfile);
++ svr_opts.authorized_keys_file = m_strdup(authkeysfile);
+ authkeysfile = NULL;
+ }
}
}
---
-2.47.0
-