Skip to content

Instantly share code, notes, and snippets.

@z80oolong
Last active May 29, 2019 07:58
Show Gist options
  • Save z80oolong/3e353bd8f0b44f415880d047b4dad4af to your computer and use it in GitHub Desktop.
Save z80oolong/3e353bd8f0b44f415880d047b4dad4af to your computer and use it in GitHub Desktop.
Debian noroot 環境において dropbear の動作に不具合が生じる問題を修正するための差分ファイル

Debian noroot 環境において dropbear の動作に不具合が生じる問題を修正するための差分ファイル

概要

これらの差分ファイルは、軽量な SSH サーバである dropbear のうち、安定版の dropbear 及び github 上の dropbear において、一部 bug fix を行い、 Debian noroot 環境において正常に動作させる為の差分ファイルです。

これらの差分ファイルでは、 Android OS 5.0 以降 における Debian noroot 環境において、擬似端末デバイスファイルである /dev/pts/* の所有権及び権限の変更が出来ない制約を回避し、また、システムコール link(2) の実行を回避しています。

差分ファイルの適用とコンパイル

dropbear のソースコードに差分ファイルを適用するには、安定版の dropbear には、差分ファイル dropbear-x.y-fix.diff (ここに、 x.y は安定版のバージョン番号) を、github 上の dropbear には、差分ファイル dropbear-HEAD-xxxxxxxx-fix.diff (ここに、 xxxxxxxx は、リビジョン番号) をそれぞれ適用して下さい。

例えば、安定版の dropbear のソースコードに dropbear-x.y-fix.diff を適用するには、安定版の dropbear のソースコードが置かれているディレクトリより、以下のようにして差分ファイル dropbear-x.y-fix.diff を適用します。

 $ patch -p1 < /path/to/dropbear-x.y-fix.diff
 (ここに、/path/to/diff は、 dropbear-x.y-fix.diff が置かれたディレクトリのパス名)

そして、 github 上の dropbear のソースコードに dropbear-HEAD-xxxxxxxx.diff を適用するには、 github 上の dropbear のソースコードが置かれているディレクトリより、以下のようにして差分ファイル dropbear-HEAD-xxxxxxxx.diff を適用します。

 $ patch -p1 < /path/to/dropbear-HEAD-xxxxxxxx.diff
 (ここに、/path/to/diff は、 dropbear-HEAD-xxxxxxxx.diff が置かれたディレクトリのパス名)

なお、これらの差分ファイルを適用した dropbear のソースコードを Debian noroot 環境においてコンパイルするには、./configure コマンドの実行時に以下のようにして、環境変数 CFLAGS-DDEBIAN_NOROOT を設定する必要があります。

 $ CFLAGS="-DDEBIAN_NOROOT" ./configure --prefix=...  # (以下、適宜オプションを設定すること。)

謝辞

なお、これらの差分ファイルの作成に当たっては、 termux の開発コミュニティ による差分ファイルを参考にしました。 termux の開発コミュニティの皆様には心より感謝致します。

追記

2017/08/27 の追記

安定版の dropbear である dropbear-2017.75 の差分ファイルに誤りがありましたので、訂正を行いました。

2018/02/03 の追記

github 上の dropbear の HEAD の commit である 8ffa8f72 に対応した差分ファイル dropbear-HEAD-8ffa8f72-fix.diff を追加し、 obsolute となった差分ファイル dropbear-HEAD-a5ec3aca-fix.diffを削除しました。どうか御了承下さい。

2018/03/23 の追記

github 上の dropbear の HEAD の commit である d740dc54 に対応した差分ファイル dropbear-HEAD-d740dc54-fix.diff を追加しました。これに伴い、差分ファイル dropbear-HEAD-8ffa8f72-fix.diffを削除しました。どうか御了承下さい。

2017/04/13 の追記

安定版の dropbear である dropbear-2018.76 に対応した差分ファイル dropbear-2018.76-fix.diff を追加しました。

2018/10/06 の追記

github 上の dropbear の HEAD の commit である 6f6ef483 に対応した差分ファイル dropbear-HEAD-6f6ef483-fix.diff を追加しました。これに伴い、差分ファイル dropbear-HEAD-d740dc54-fix.diffを削除しました。どうか御了承下さい。

2019/03/19 の追記

github 上の dropbear の HEAD の commit である cb945f9f に対応した差分ファイル dropbear-HEAD-cb945f9f-fix.diff を追加しました。これに伴い、差分ファイル dropbear-2017.75-fix.diff, dropbear-HEAD-6f6ef483-fix.diffを削除しました。どうか御了承下さい。

2019/04/19 の追記

github 上の dropbear の HEAD の commit である cb945f9f に対応した差分ファイル dropbear-HEAD-cae6e6af-fix.diff を追加しました。これに伴い、差分ファイル dropbear-HEAD-cb945f9f-fix.diffを削除しました。どうか御了承下さい。

2019/04/20 の追記

安定版の dropbear である dropbear-2019.78 に対応した差分ファイル dropbear-2018.76-fix.diff を追加しました。これに伴い、差分ファイル dropbear-2018.76-fix.diffを削除しました。どうか御了承下さい。

diff --git a/default_options.h b/default_options.h
index 9000fcc..34ef067 100644
--- a/default_options.h
+++ b/default_options.h
@@ -13,7 +13,13 @@ Options can also be defined with -DDROPBEAR_XXX=[0,1] in Makefile CFLAGS
IMPORTANT: Some options will require "make clean" after changes */
+#ifndef DROPBEAR_DEFPORT
+#ifdef DEBIAN_NOROOT
+#define DROPBEAR_DEFPORT "8022"
+#else
#define DROPBEAR_DEFPORT "22"
+#endif
+#endif
/* Listen on all interfaces */
#define DROPBEAR_DEFADDRESS ""
@@ -44,7 +50,9 @@ IMPORTANT: Some options will require "make clean" after changes */
* several kB in binary size however will make the symmetrical ciphers and hashes
* slower, perhaps by 50%. Recommended for small systems that aren't doing
* much traffic. */
+#ifndef DROPBEAR_SMALL_CODE
#define DROPBEAR_SMALL_CODE 1
+#endif
/* Enable X11 Forwarding - server only */
#define DROPBEAR_X11FWD 1
@@ -187,7 +195,21 @@ group1 in Dropbear server too */
* but there's an interface via a PAM module. It won't work for more complex
* PAM challenge/response.
* You can't enable both PASSWORD and PAM. */
+
+/* This requires crypt() */
+#ifdef HAVE_CRYPT
+#ifndef DROPBEAR_SVR_PASSWORD_AUTH
+#define DROPBEAR_SVR_PASSWORD_AUTH 1
+#endif
+#else
+#ifndef DROPBEAR_SVR_PASSWORD_AUTH
+#define DROPBEAR_SVR_PASSWORD_AUTH 0
+#endif
+#endif
+/* PAM requires ./configure --enable-pam */
+#ifndef DROPBEAR_SVR_PAM_AUTH
#define DROPBEAR_SVR_PAM_AUTH 0
+#endif
/* ~/.ssh/authorized_keys authentication */
#define DROPBEAR_SVR_PUBKEY_AUTH 1
diff --git a/gensignkey.c b/gensignkey.c
index 8317fea..4006e60 100644
--- a/gensignkey.c
+++ b/gensignkey.c
@@ -140,6 +140,16 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename,
goto out;
}
+#ifdef DEBIAN_NOROOT
+ /* Hard links are not possible and renam. */
+ if (skip_exist && access(filename, F_OK) == 0) {
+ /* Ok. */
+ } else if (rename(fn_temp, filename) < 0) {
+ dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename,
+ strerror(errno));
+ ret = DROPBEAR_FAILURE;
+ }
+#else
if (link(fn_temp, filename) < 0) {
/* If generating keys on connection (skipexist) it's OK to get EEXIST
- we probably just lost a race with another connection to generate the key */
@@ -151,6 +161,7 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename,
goto out;
}
}
+#endif
out:
if (buf) {
diff --git a/signkey.c b/signkey.c
index 88f06c7..150be82 100644
--- a/signkey.c
+++ b/signkey.c
@@ -624,6 +624,7 @@ int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
out:
buf_free(decodekey);
decodekey = NULL;
+ TRACE(("cmp_base64_key: ret=%d",ret))
return ret;
}
#endif
diff --git a/sshpty.c b/sshpty.c
index fceb7fd..eff9758 100644
--- a/sshpty.c
+++ b/sshpty.c
@@ -17,6 +17,17 @@
/*RCSID("OpenBSD: sshpty.c,v 1.7 2002/06/24 17:57:20 deraadt Exp ");*/
+#ifdef DEBIAN_NOROOT
+#undef HAVE__GETPTY
+#undef HAVE_OPENPTY
+#define HAVE_DEV_PTMX
+#define USE_DEV_PTMX 1
+#endif
+
+#if defined(USE_DEV_PTMX)
+#define _XOPEN_SOURCE
+#endif
+
#include "includes.h"
#include "dbutil.h"
#include "errno.h"
@@ -133,6 +144,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
close(*ptyfd);
return 0;
}
+#ifndef DEBIAN_NOROOT
#if !defined(HAVE_CYGWIN) && defined(I_PUSH)
/*
* Push the appropriate streams modules, as described in Solaris pts(7).
@@ -153,6 +165,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
}
#endif
#endif
+#endif /* DEBIAN_NOROOT */
return 1;
#else /* USE_DEV_PTMX */
#ifdef HAVE_DEV_PTS_AND_PTC
@@ -247,6 +260,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
void
pty_release(const char *tty_name)
{
+#ifndef DEBIAN_NOROOT
if (chown(tty_name, (uid_t) 0, (gid_t) 0) < 0
&& (errno != ENOENT)) {
dropbear_log(LOG_ERR,
@@ -257,6 +271,7 @@ pty_release(const char *tty_name)
dropbear_log(LOG_ERR,
"chmod %.100s 0666 failed: %.100s", tty_name, strerror(errno));
}
+#endif
}
/* Makes the tty the processes controlling tty and sets it to sane modes. */
@@ -380,6 +395,7 @@ pty_setowner(struct passwd *pw, const char *tty_name)
tty_name, strerror(errno));
}
+#ifndef DEBIAN_NOROOT
if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
if (chown(tty_name, pw->pw_uid, gid) < 0) {
if (errno == EROFS &&
@@ -409,4 +425,5 @@ pty_setowner(struct passwd *pw, const char *tty_name)
}
}
}
+#endif /* DEBIAN_NOROOT */
}
diff --git a/svr-agentfwd.c b/svr-agentfwd.c
index ac9475f..ff605e5 100644
--- a/svr-agentfwd.c
+++ b/svr-agentfwd.c
@@ -224,10 +224,12 @@ static int bindagent(int fd, struct ChanSess * chansess) {
/* drop to user privs to make the dir/file */
uid = getuid();
gid = getgid();
+#ifndef DEBIAN_NOROOT
if ((setegid(ses.authstate.pw_gid)) < 0 ||
(seteuid(ses.authstate.pw_uid)) < 0) {
dropbear_exit("Failed to set euid");
}
+#endif /* DEBIAN_NOROOT */
#endif
memset((void*)&addr, 0x0, sizeof(addr));
diff --git a/svr-authpubkey.c b/svr-authpubkey.c
index 4f27986..3500fe3 100644
--- a/svr-authpubkey.c
+++ b/svr-authpubkey.c
@@ -385,6 +385,7 @@ static int checkpubkey(const char* algo, unsigned int algolen,
ret = checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen);
if (ret == DROPBEAR_SUCCESS) {
+ TRACE(("checkpubkey: pubkey auth OK."))
break;
}
diff --git a/default_options.h b/default_options.h
index 9000fcc..34ef067 100644
--- a/default_options.h
+++ b/default_options.h
@@ -13,7 +13,13 @@ Options can also be defined with -DDROPBEAR_XXX=[0,1] in Makefile CFLAGS
IMPORTANT: Some options will require "make clean" after changes */
+#ifndef DROPBEAR_DEFPORT
+#ifdef DEBIAN_NOROOT
+#define DROPBEAR_DEFPORT "8022"
+#else
#define DROPBEAR_DEFPORT "22"
+#endif
+#endif
/* Listen on all interfaces */
#define DROPBEAR_DEFADDRESS ""
@@ -44,7 +50,9 @@ IMPORTANT: Some options will require "make clean" after changes */
* several kB in binary size however will make the symmetrical ciphers and hashes
* slower, perhaps by 50%. Recommended for small systems that aren't doing
* much traffic. */
+#ifndef DROPBEAR_SMALL_CODE
#define DROPBEAR_SMALL_CODE 1
+#endif
/* Enable X11 Forwarding - server only */
#define DROPBEAR_X11FWD 1
@@ -187,7 +195,21 @@ group1 in Dropbear server too */
* but there's an interface via a PAM module. It won't work for more complex
* PAM challenge/response.
* You can't enable both PASSWORD and PAM. */
+
+/* This requires crypt() */
+#ifdef HAVE_CRYPT
+#ifndef DROPBEAR_SVR_PASSWORD_AUTH
+#define DROPBEAR_SVR_PASSWORD_AUTH 1
+#endif
+#else
+#ifndef DROPBEAR_SVR_PASSWORD_AUTH
+#define DROPBEAR_SVR_PASSWORD_AUTH 0
+#endif
+#endif
+/* PAM requires ./configure --enable-pam */
+#ifndef DROPBEAR_SVR_PAM_AUTH
#define DROPBEAR_SVR_PAM_AUTH 0
+#endif
/* ~/.ssh/authorized_keys authentication */
#define DROPBEAR_SVR_PUBKEY_AUTH 1
diff --git a/gensignkey.c b/gensignkey.c
index 8317fea..4006e60 100644
--- a/gensignkey.c
+++ b/gensignkey.c
@@ -140,6 +140,16 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename,
goto out;
}
+#ifdef DEBIAN_NOROOT
+ /* Hard links are not possible and renam. */
+ if (skip_exist && access(filename, F_OK) == 0) {
+ /* Ok. */
+ } else if (rename(fn_temp, filename) < 0) {
+ dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename,
+ strerror(errno));
+ ret = DROPBEAR_FAILURE;
+ }
+#else
if (link(fn_temp, filename) < 0) {
/* If generating keys on connection (skipexist) it's OK to get EEXIST
- we probably just lost a race with another connection to generate the key */
@@ -151,6 +161,7 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename,
goto out;
}
}
+#endif
out:
if (buf) {
diff --git a/signkey.c b/signkey.c
index 88f06c7..150be82 100644
--- a/signkey.c
+++ b/signkey.c
@@ -624,6 +624,7 @@ int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
out:
buf_free(decodekey);
decodekey = NULL;
+ TRACE(("cmp_base64_key: ret=%d",ret))
return ret;
}
#endif
diff --git a/sshpty.c b/sshpty.c
index fceb7fd..eff9758 100644
--- a/sshpty.c
+++ b/sshpty.c
@@ -17,6 +17,17 @@
/*RCSID("OpenBSD: sshpty.c,v 1.7 2002/06/24 17:57:20 deraadt Exp ");*/
+#ifdef DEBIAN_NOROOT
+#undef HAVE__GETPTY
+#undef HAVE_OPENPTY
+#define HAVE_DEV_PTMX
+#define USE_DEV_PTMX 1
+#endif
+
+#if defined(USE_DEV_PTMX)
+#define _XOPEN_SOURCE
+#endif
+
#include "includes.h"
#include "dbutil.h"
#include "errno.h"
@@ -133,6 +144,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
close(*ptyfd);
return 0;
}
+#ifndef DEBIAN_NOROOT
#if !defined(HAVE_CYGWIN) && defined(I_PUSH)
/*
* Push the appropriate streams modules, as described in Solaris pts(7).
@@ -153,6 +165,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
}
#endif
#endif
+#endif /* DEBIAN_NOROOT */
return 1;
#else /* USE_DEV_PTMX */
#ifdef HAVE_DEV_PTS_AND_PTC
@@ -247,6 +260,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
void
pty_release(const char *tty_name)
{
+#ifndef DEBIAN_NOROOT
if (chown(tty_name, (uid_t) 0, (gid_t) 0) < 0
&& (errno != ENOENT)) {
dropbear_log(LOG_ERR,
@@ -257,6 +271,7 @@ pty_release(const char *tty_name)
dropbear_log(LOG_ERR,
"chmod %.100s 0666 failed: %.100s", tty_name, strerror(errno));
}
+#endif
}
/* Makes the tty the processes controlling tty and sets it to sane modes. */
@@ -380,6 +395,7 @@ pty_setowner(struct passwd *pw, const char *tty_name)
tty_name, strerror(errno));
}
+#ifndef DEBIAN_NOROOT
if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
if (chown(tty_name, pw->pw_uid, gid) < 0) {
if (errno == EROFS &&
@@ -409,4 +425,5 @@ pty_setowner(struct passwd *pw, const char *tty_name)
}
}
}
+#endif /* DEBIAN_NOROOT */
}
diff --git a/svr-agentfwd.c b/svr-agentfwd.c
index ac9475f..ff605e5 100644
--- a/svr-agentfwd.c
+++ b/svr-agentfwd.c
@@ -224,10 +224,12 @@ static int bindagent(int fd, struct ChanSess * chansess) {
/* drop to user privs to make the dir/file */
uid = getuid();
gid = getgid();
+#ifndef DEBIAN_NOROOT
if ((setegid(ses.authstate.pw_gid)) < 0 ||
(seteuid(ses.authstate.pw_uid)) < 0) {
dropbear_exit("Failed to set euid");
}
+#endif /* DEBIAN_NOROOT */
#endif
memset((void*)&addr, 0x0, sizeof(addr));
diff --git a/svr-authpubkey.c b/svr-authpubkey.c
index 4f27986..3500fe3 100644
--- a/svr-authpubkey.c
+++ b/svr-authpubkey.c
@@ -385,6 +385,7 @@ static int checkpubkey(const char* algo, unsigned int algolen,
ret = checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen);
if (ret == DROPBEAR_SUCCESS) {
+ TRACE(("checkpubkey: pubkey auth OK."))
break;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment