Pārlūkot izejas kodu

Ports: Add preliminary dropbear port

This is very basic and doesn't support many features. Instead
of describing what it *doesn't* support, I'll describe what I
have tested:
1. Public key authentication (password is not supported)
2. Single command execution
3. PTY-less interactive bash shell (/bin/sh doesn't work)
4. Multi-user (i.e you can ssh as 'anon' as well as root)
Yonatan Goldschmidt 5 gadi atpakaļ
vecāks
revīzija
c377e6af29

+ 1 - 0
Kernel/build-root-filesystem.sh

@@ -86,6 +86,7 @@ chmod 400 mnt/res/kernel.map
 
 chmod 660 mnt/etc/WindowServer/WindowServer.ini
 chown $window_uid:$window_gid mnt/etc/WindowServer/WindowServer.ini
+echo "/bin/sh" > mnt/etc/shells
 
 echo "done"
 

+ 1 - 1
Kernel/run

@@ -116,7 +116,7 @@ else
         $SERENITY_COMMON_QEMU_ARGS \
         $SERENITY_KVM_ARG \
         $SERENITY_PACKET_LOGGING_ARG \
-        -netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-10.0.2.15:8888,hostfwd=tcp:127.0.0.1:8823-10.0.2.15:23,hostfwd=tcp:127.0.0.1:8000-10.0.2.15:8000 \
+        -netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-10.0.2.15:8888,hostfwd=tcp:127.0.0.1:8823-10.0.2.15:23,hostfwd=tcp:127.0.0.1:8000-10.0.2.15:8000,hostfwd=tcp:127.0.0.1:2222-10.0.2.15:22 \
         -device e1000,netdev=breh \
         -kernel kernel \
         -append "${SERENITY_KERNEL_CMDLINE}"

+ 16 - 0
Ports/dropbear/package.sh

@@ -0,0 +1,16 @@
+#!/bin/bash ../.port_include.sh
+port=dropbear
+version=2019.78
+files="https://matt.ucc.asn.au/dropbear/releases/dropbear-${version}.tar.bz2 dropbear-${version}.tar.bz2
+https://matt.ucc.asn.au/dropbear/releases/dropbear-${version}.tar.bz2.asc dropbear-${version}.tar.bz2.asc
+https://matt.ucc.asn.au/dropbear/releases/dropbear-key-2015.asc dropbear-key-2015.asc"
+
+auth_type="sig"
+auth_opts="--keyring ./dropbear-key-2015.asc dropbear-${version}.tar.bz2.asc"
+useconfigure=true
+# don't care about zlib, less deps is better
+configopts="--disable-zlib "
+# Serenity's utmp is not fully compatible with what dropbear expects.
+configopts+="--disable-utmp --disable-wtmp --disable-login --disable-lastlog "
+# not added automatically
+configopts+="--enable-static"

+ 22 - 0
Ports/dropbear/patches/default-options.patch

@@ -0,0 +1,22 @@
+--- a/default_options.h.orig
++++ b/default_options.h
+@@ -59,8 +59,8 @@
+ #define DROPBEAR_SVR_REMOTETCPFWD 1
+ 
+ /* Enable Authentication Agent Forwarding */
+-#define DROPBEAR_SVR_AGENTFWD 1
+-#define DROPBEAR_CLI_AGENTFWD 1
++#define DROPBEAR_SVR_AGENTFWD 0
++#define DROPBEAR_CLI_AGENTFWD 0
+ 
+ /* Note: Both DROPBEAR_CLI_PROXYCMD and DROPBEAR_CLI_NETCAT must be set to
+  * allow multihop dbclient connections */
+@@ -179,7 +179,7 @@
+ 
+ /* Authentication Types - at least one required.
+    RFC Draft requires pubkey auth, and recommends password */
+-#define DROPBEAR_SVR_PASSWORD_AUTH 1
++#define DROPBEAR_SVR_PASSWORD_AUTH 0
+ 
+ /* Note: PAM auth is quite simple and only works for PAM modules which just do
+  * a simple "Login: " "Password: " (you can edit the strings in svr-authpam.c).

+ 84 - 0
Ports/dropbear/patches/disable-ssp.patch

@@ -0,0 +1,84 @@
+I patch both configure.ac and configure itself (though only configure is required for the build)
+Serenity's GCC doesn't support SSP, so this is disabled.
+--- a/configure.ac.orig
++++ b/configure.ac
+@@ -99,22 +99,7 @@
+ 			[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="$OLDCFLAGS"
+-			TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4"
+-			CFLAGS="$CFLAGS $TESTFLAGS"
+-			AC_COMPILE_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])
+ 
+--- a/configure.orig
++++ b/configure
+@@ -3357,53 +3357,7 @@
+ rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+ 	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"
+-	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+ 
+-int
+-main ()
+-{
+-
+-  ;
+-  return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_compile "$LINENO"; then :
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: Setting $TESTFLAGS" >&5
+-$as_echo "$as_me: Setting $TESTFLAGS" >&6;}
+-else
+-
+-			CFLAGS="$OLDCFLAGS"
+-			TESTFLAGS="-fstack-protector --param=ssp-buffer-size=4"
+-			CFLAGS="$CFLAGS $TESTFLAGS"
+-			cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-
+-int
+-main ()
+-{
+-
+-  ;
+-  return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_compile "$LINENO"; then :
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: Setting $TESTFLAGS" >&5
+-$as_echo "$as_me: Setting $TESTFLAGS" >&6;}
+-else
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: Not setting $TESTFLAGS" >&5
+-$as_echo "$as_me: Not setting $TESTFLAGS" >&6;}; CFLAGS="$OLDCFLAGS"
+-
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+-
+-
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ 	# FORTIFY_SOURCE
+ 	{
+ 		OLDFLAGS="$CFLAGS"

+ 10 - 0
Ports/dropbear/patches/fix-autoconf.patch

@@ -0,0 +1,10 @@
+--- a/config.sub.orig
++++ b/config.sub
+@@ -1339,6 +1339,7 @@
+ 	# Each alternative MUST end in a * to match a version number.
+ 	# sysv* is not here because it comes later, after sysvr4.
+ 	gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
++	     | serenity* \
+ 	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
+ 	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ 	     | sym* | kopensolaris* | plan9* \

+ 11 - 0
Ports/dropbear/patches/fix-includes.patch

@@ -0,0 +1,11 @@
+Not sure why this is missing, but okay.
+--- a/includes.h.orig
++++ b/includes.h
+@@ -38,6 +38,7 @@
+ #include <sys/un.h>
+ #include <sys/wait.h>
+ #include <sys/resource.h>
++#include <sys/select.h>
+ 
+ #include <stdio.h>
+ #include <errno.h>

+ 11 - 0
Ports/dropbear/patches/fopen-c.patch

@@ -0,0 +1,11 @@
+--- a/compat.c
++++ b/compat.c
+@@ -244,7 +244,7 @@
+ 	if (strings != NULL)
+ 		free(strings);
+ 	strings = NULL;
+-	if ((fp = fopen("/etc/shells", "rc")) == NULL)
++	if ((fp = fopen("/etc/shells", "r")) == NULL)
+ 		return (char **) okshells;
+ 	if (fstat(fileno(fp), &statb) == -1) {
+ 		(void)fclose(fp);

+ 12 - 0
Ports/dropbear/patches/install-in-bin.patch

@@ -0,0 +1,12 @@
+Serenity doesn't use /sbin.
+--- a/Makefile.in.orig
++++ b/Makefile.in
+@@ -87,7 +87,7 @@
+ exec_prefix=@exec_prefix@
+ datarootdir = @datarootdir@
+ bindir=@bindir@
+-sbindir=@sbindir@
++sbindir=$(bindir)
+ mandir=@mandir@
+ 
+ .DELETE_ON_ERROR:

+ 42 - 0
Ports/dropbear/patches/netio.patch

@@ -0,0 +1,42 @@
+--- b/netio.c.orig
++++ b/netio.c
+@@ -294,7 +294,7 @@
+ 	buffer *writebuf;
+ 
+ 	#ifndef IOV_MAX
+-		#if defined(__CYGWIN__) && !defined(UIO_MAXIOV)
++		#if !defined(UIO_MAXIOV)
+ 		#define IOV_MAX 1024
+ 		#else
+ 		#define IOV_MAX UIO_MAXIOV
+@@ -334,11 +334,7 @@
+ }
+ 
+ void set_sock_nodelay(int sock) {
+-	int val;
+-
+-	/* disable nagle */
+-	val = 1;
+-	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val));
++	(void)sock;
+ }
+ 
+ #if DROPBEAR_SERVER_TCP_FAST_OPEN
+@@ -448,7 +444,6 @@
+ 	struct addrinfo hints, *res = NULL, *res0 = NULL;
+ 	int err;
+ 	unsigned int nsock;
+-	struct linger linger;
+ 	int val;
+ 	int sock;
+ 
+@@ -527,9 +522,6 @@
+ 		val = 1;
+ 		/* set to reuse, quick timeout */
+ 		setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val));
+-		linger.l_onoff = 1;
+-		linger.l_linger = 5;
+-		setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger));
+ 
+ #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
+ 		if (res->ai_family == AF_INET6) {

+ 11 - 0
Ports/dropbear/patches/remove-nanosleep.patch

@@ -0,0 +1,11 @@
+Hinders security by a little, but I guess we'll just have nanosleep soon enough.
+--- a/svr-auth.c.orig
++++ b/svr-auth.c
+@@ -424,7 +424,6 @@
+ 		if (!fuzz.fuzzing)
+ #endif
+ 		{
+-			while (nanosleep(&delay, &delay) == -1 && errno == EINTR) { /* Go back to sleep */ }
+ 		}
+ 
+ 		ses.authstate.failcount++;

+ 14 - 0
Ports/dropbear/patches/remove-reserved-ports.patch

@@ -0,0 +1,14 @@
+--- a/svr-tcpfwd.c.orig
++++ b/svr-tcpfwd.c
+@@ -186,11 +186,6 @@
+ 			TRACE(("invalid port: %d", port))
+ 			goto out;
+ 		}
+-
+-		if (!ses.allowprivport && port < IPPORT_RESERVED) {
+-			TRACE(("can't assign port < 1024 for non-root"))
+-			goto out;
+-		}
+ 	}
+ 
+ 	tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));

+ 96 - 0
Ports/dropbear/patches/remove-seteuid-setegid.patch

@@ -0,0 +1,96 @@
+Dropbear temporarily drops privilliges to make sure the user has access
+to do various actions (e.g access its authorized_keys file).
+Serenity doesn't implement seteuid/setegid, so we can't drop privilliges and
+regain them this way (at least, not that I know it's possible).
+--- a/svr-authpubkey.c.orig
++++ b/svr-authpubkey.c
+@@ -347,25 +347,8 @@
+ 	snprintf(filename, len + 22, "%s/.ssh/authorized_keys", 
+ 				ses.authstate.pw_dir);
+ 
+-#if DROPBEAR_SVR_MULTIUSER
+-	/* open the file as the authenticating user. */
+-	origuid = getuid();
+-	origgid = getgid();
+-	if ((setegid(ses.authstate.pw_gid)) < 0 ||
+-		(seteuid(ses.authstate.pw_uid)) < 0) {
+-		dropbear_exit("Failed to set euid");
+-	}
+-#endif
+-
+ 	authfile = fopen(filename, "r");
+ 
+-#if DROPBEAR_SVR_MULTIUSER
+-	if ((seteuid(origuid)) < 0 ||
+-		(setegid(origgid)) < 0) {
+-		dropbear_exit("Failed to revert euid");
+-	}
+-#endif
+-
+ 	if (authfile == NULL) {
+ 		goto out;
+ 	}
+--- a/svr-agentfwd.c.orig
++++ b/svr-agentfwd.c
+@@ -151,17 +151,6 @@
+ 
+ 	if (chansess->agentfile != NULL && chansess->agentdir != NULL) {
+ 
+-#if DROPBEAR_SVR_MULTIUSER
+-		/* Remove the dir as the user. That way they can't cause problems except
+-		 * for themselves */
+-		uid = getuid();
+-		gid = getgid();
+-		if ((setegid(ses.authstate.pw_gid)) < 0 ||
+-			(seteuid(ses.authstate.pw_uid)) < 0) {
+-			dropbear_exit("Failed to set euid");
+-		}
+-#endif
+-
+ 		/* 2 for "/" and "\0" */
+ 		len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2;
+ 
+@@ -172,13 +161,6 @@
+ 
+ 		rmdir(chansess->agentdir);
+ 
+-#if DROPBEAR_SVR_MULTIUSER
+-		if ((seteuid(uid)) < 0 ||
+-			(setegid(gid)) < 0) {
+-			dropbear_exit("Failed to revert euid");
+-		}
+-#endif
+-
+ 		m_free(chansess->agentfile);
+ 		m_free(chansess->agentdir);
+ 	}
+@@ -220,16 +202,6 @@
+ 	gid_t gid;
+ 	int ret = DROPBEAR_FAILURE;
+ 
+-#if DROPBEAR_SVR_MULTIUSER
+-	/* drop to user privs to make the dir/file */
+-	uid = getuid();
+-	gid = getgid();
+-	if ((setegid(ses.authstate.pw_gid)) < 0 ||
+-		(seteuid(ses.authstate.pw_uid)) < 0) {
+-		dropbear_exit("Failed to set euid");
+-	}
+-#endif
+-
+ 	memset((void*)&addr, 0x0, sizeof(addr));
+ 	addr.sun_family = AF_UNIX;
+ 
+@@ -268,12 +240,6 @@
+ 
+ 
+ out:
+-#if DROPBEAR_SVR_MULTIUSER
+-	if ((seteuid(uid)) < 0 ||
+-		(setegid(gid)) < 0) {
+-		dropbear_exit("Failed to revert euid");
+-	}
+-#endif
+ 	return ret;
+ }
+ 

+ 12 - 0
Ports/dropbear/patches/remove-setrlimit.patch

@@ -0,0 +1,12 @@
+--- a/dbutil.c.orig
++++ b/dbutil.c
+@@ -553,9 +553,6 @@
+ }
+ 
+ void disallow_core() {
+-	struct rlimit lim;
+-	lim.rlim_cur = lim.rlim_max = 0;
+-	setrlimit(RLIMIT_CORE, &lim);
+ }
+ 
+ /* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */

+ 11 - 0
Ports/dropbear/patches/use-dev-random.patch

@@ -0,0 +1,11 @@
+--- a/sysoptions.h
++++ b/sysoptions.h
+@@ -256,7 +256,7 @@
+ /* Source for randomness. This must be able to provide hundreds of bytes per SSH
+  * connection without blocking. */
+ #ifndef DROPBEAR_URANDOM_DEV
+-#define DROPBEAR_URANDOM_DEV "/dev/urandom"
++#define DROPBEAR_URANDOM_DEV "/dev/random"
+ #endif
+ 
+ /* client keyboard interactive authentication is often used for password auth.

+ 30 - 0
Ports/dropbear/patches/winsize-remove-pixels.patch

@@ -0,0 +1,30 @@
+--- a/sshpty.c.orig
++++ b/sshpty.c
+@@ -347,8 +347,6 @@
+ 
+ 	w.ws_row = row;
+ 	w.ws_col = col;
+-	w.ws_xpixel = xpixel;
+-	w.ws_ypixel = ypixel;
+ 	(void) ioctl(ptyfd, TIOCSWINSZ, &w);
+ }
+ 
+--- a/cli-chansession.c.orig
++++ b/cli-chansession.c
+@@ -234,14 +234,12 @@
+ 		/* Some sane defaults */
+ 		ws.ws_row = 25;
+ 		ws.ws_col = 80;
+-		ws.ws_xpixel = 0;
+-		ws.ws_ypixel = 0;
+ 	}
+ 
+ 	buf_putint(ses.writepayload, ws.ws_col); /* Cols */
+ 	buf_putint(ses.writepayload, ws.ws_row); /* Rows */
+-	buf_putint(ses.writepayload, ws.ws_xpixel); /* Width */
+-	buf_putint(ses.writepayload, ws.ws_ypixel); /* Height */
++	buf_putint(ses.writepayload, 0); /* Width */
++	buf_putint(ses.writepayload, 0); /* Height */
+ 
+ }
+