Chroot patch (v3.4p1)

John Furman john at furman.net
Sat Jul 13 10:49:13 EST 2002


To: openssh-unix-dev at mindrot.org
Subject: Re: Chroot patch (v3.4p1)

On 4 Jul 2002 12:32:36 -0400 Hank Leininger <openssh-unix-dev at progressive-comp.com> wrote:

>> The following is a patch I've been working on to support a "ChrootUser"
>> option in the sshd_config file.

[snip]

>Note that this like every(?) other chroot patch for openssh floating around
>(including the one I maintain) does not work on *BSD, that is, any system
>which has HAVE_LOGIN_CAP defined.  All the chroot patches chroot between
[snip]

>fix.  I'm not sure if moving the chroot calls above the block in question,
>or simply replicating the chroot code inside both code paths is
>appropriate.

>--
>Hank Leininger <hlein at progressive-comp.com>

Your supposition is correct, Hank.  I have moved the 'chroot' code above the HAVE_LOGIN_CAP/setusercontext call and corrected the issue you mention.  (Took some doin' as I had to free up an OpenBSD 3.x box to test on. ;-)  I have created a patch for OpenSSH-v3.4 that I will post as well.  Below is a patch for v3.4p1.

It supports two additional options in the sshd_config.

ChrootDir  - Configured as with AuthorizedKeysFile %T tokens etc...
    Defaults to a subdir named 'chome' relative to users home dir.
    
ChrootUser - Configured as with AllowUsers. 
    user1 user2 at 10.10.2.20 user3 at some.host.com

----------------------------------------------

diff -uNr openssh-3.4p1.vanilla/auth.c openssh-3.4p1/auth.c
--- openssh-3.4p1.vanilla/auth.c	Wed May 22 01:06:28 2002
+++ openssh-3.4p1/auth.c	Wed Jul 10 23:48:11 2002
@@ -351,6 +351,12 @@
	return expand_filename(options.authorized_keys_file2, pw);
 }
 
+char *
+chroot_dir(struct passwd *pw)
+{
+	return expand_filename(options.chroot_dir, pw);
+}
+
 /* return ok if key exists in sysfile or userfile */
 HostStatus
 check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
diff -uNr openssh-3.4p1.vanilla/auth.h openssh-3.4p1/auth.h
--- openssh-3.4p1.vanilla/auth.h	Thu Jun  6 16:52:37 2002
+++ openssh-3.4p1/auth.h	Wed Jul 10 23:48:11 2002
@@ -165,6 +165,7 @@
 char	*expand_filename(const char *, struct passwd *);
 char	*authorized_keys_file(struct passwd *);
 char	*authorized_keys_file2(struct passwd *);
+char	*chroot_dir(struct passwd *);
 
 int
 secure_filename(FILE *, const char *, struct passwd *, char *, size_t);
diff -uNr openssh-3.4p1.vanilla/pathnames.h openssh-3.4p1/pathnames.h
--- openssh-3.4p1.vanilla/pathnames.h	Thu Jun  6 15:57:34 2002
+++ openssh-3.4p1/pathnames.h	Wed Jul 10 23:48:11 2002
@@ -97,6 +97,9 @@
 /* backward compat for protocol v2 */
 #define _PATH_SSH_USER_PERMITTED_KEYS2	".ssh/authorized_keys2"
 
+/* default user chroot directory */
+#define _SSH_USER_CHROOT_DIR	"chome"
+
 /*
  * Per-user and system-wide ssh "rc" files.  These files are executed with
  * /bin/sh before starting the shell or command if they exist.  They will be
diff -uNr openssh-3.4p1.vanilla/servconf.c openssh-3.4p1/servconf.c
--- openssh-3.4p1.vanilla/servconf.c	Mon Jun 24 23:22:04 2002
+++ openssh-3.4p1/servconf.c	Wed Jul 10 23:48:11 2002
@@ -120,6 +120,7 @@
	options->verify_reverse_mapping = -1;
	options->client_alive_interval = -1;
	options->client_alive_count_max = -1;
+	options->chroot_dir = NULL;
	options->authorized_keys_file = NULL;
	options->authorized_keys_file2 = NULL;
 
@@ -252,6 +253,8 @@
	}
	if (options->authorized_keys_file == NULL)
		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
+	if (options->chroot_dir == NULL)
+		options->chroot_dir = _SSH_USER_CHROOT_DIR;
 
	/* Turn privilege separation on by default */
	if (use_privsep == -1)
@@ -292,12 +295,12 @@
	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
	sStrictModes, sEmptyPasswd, sKeepAlives,
	sUseLogin, sAllowTcpForwarding, sCompression,
-	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+	sAllowUsers, sDenyUsers, sChrootUsers, sAllowGroups, sDenyGroups,
	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
	sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
-	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
+	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, sChrootDir,
	sUsePrivilegeSeparation,
	sDeprecated
 } ServerOpCodes;
@@ -360,6 +363,7 @@
	{ "allowtcpforwarding", sAllowTcpForwarding },
	{ "allowusers", sAllowUsers },
	{ "denyusers", sDenyUsers },
+	{ "chrootusers", sChrootUsers },
	{ "allowgroups", sAllowGroups },
	{ "denygroups", sDenyGroups },
	{ "ciphers", sCiphers },
@@ -375,6 +379,7 @@
	{ "clientalivecountmax", sClientAliveCountMax },
	{ "authorizedkeysfile", sAuthorizedKeysFile },
	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+	{ "chrootdir", sChrootDir },
	{ "useprivilegeseparation", sUsePrivilegeSeparation},
	{ NULL, sBadOption }
 };
@@ -779,6 +784,16 @@
		}
		break;
 
+	case sChrootUsers:
+		while ((arg = strdelim(&cp)) && *arg != '\0') {
+			if (options->num_chroot_users >= MAX_CHROOT_USERS)
+				fatal( "%s line %d: too many chroot users.",
+				    filename, linenum);
+			options->chroot_users[options->num_chroot_users++] =
+			    xstrdup(arg);
+                }
+		break;
+
	case sAllowGroups:
		while ((arg = strdelim(&cp)) && *arg != '\0') {
			if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
@@ -893,6 +908,10 @@
		    &options->authorized_keys_file2;
		goto parse_filename;
 
+	case sChrootDir:
+		charptr = &options->chroot_dir;
+		goto parse_filename;
+
	case sClientAliveInterval:
		intptr = &options->client_alive_interval;
		goto parse_time;
diff -uNr openssh-3.4p1.vanilla/servconf.h openssh-3.4p1/servconf.h
--- openssh-3.4p1.vanilla/servconf.h	Thu Jun 20 21:09:47 2002
+++ openssh-3.4p1/servconf.h	Wed Jul 10 23:48:11 2002
@@ -20,6 +20,7 @@
 
 #define MAX_ALLOW_USERS		256	/* Max # users on allow list. */
 #define MAX_DENY_USERS		256	/* Max # users on deny list. */
+#define MAX_CHROOT_USERS	256     /* Max # users on chroot list. */
 #define MAX_ALLOW_GROUPS	256	/* Max # groups on allow list. */
 #define MAX_DENY_GROUPS		256	/* Max # groups on deny list. */
 #define MAX_SUBSYSTEMS		256	/* Max # subsystems. */
@@ -104,6 +105,8 @@
	char   *allow_users[MAX_ALLOW_USERS];
	u_int num_deny_users;
	char   *deny_users[MAX_DENY_USERS];
+       u_int num_chroot_users;
+       char   *chroot_users[MAX_CHROOT_USERS];
	u_int num_allow_groups;
	char   *allow_groups[MAX_ALLOW_GROUPS];
	u_int num_deny_groups;
@@ -130,6 +133,7 @@
 
	char   *authorized_keys_file;	/* File containing public keys */
	char   *authorized_keys_file2;
+	char   *chroot_dir;
	int	pam_authentication_via_kbd_int;
 }       ServerOptions;
 
diff -uNr openssh-3.4p1.vanilla/session.c openssh-3.4p1/session.c
--- openssh-3.4p1.vanilla/session.c	Wed Jun 26 09:51:06 2002
+++ openssh-3.4p1/session.c	Fri Jul 12 15:37:58 2002
@@ -57,6 +57,8 @@
 #include "canohost.h"
 #include "session.h"
 #include "monitor_wrap.h"
+#include "match.h"
+#include "readconf.h"
 
 #ifdef HAVE_CYGWIN
 #include <windows.h>
@@ -64,6 +66,10 @@
 #define is_winnt       (GetVersion() < 0x80000000)
 #endif
 
+#ifndef HAVE_CYGWIN
+#define CHROOT
+#endif
+
 /* func */
 
 Session *session_new(void);
@@ -1169,6 +1175,38 @@
 #ifdef HAVE_SETPCRED
		setpcred(pw->pw_name);
 #endif /* HAVE_SETPCRED */
+#ifdef CHROOT
+	int i;
+	char *new_root = "/";
+	char *new_home = NULL;
+	char *dir = NULL;
+	const char *hostname = NULL;
+	const char *ipaddr = NULL;
+
+		if (options.num_chroot_users > 0) {
+		        hostname = get_canonical_hostname(options.verify_reverse_mapping);
+		        ipaddr = get_remote_ipaddr();
+		    for (i = 0; i < options.num_chroot_users; i++) {
+			if (match_user(pw->pw_name, hostname, ipaddr, 
+			    options.chroot_users[i])) {
+		                dir = chroot_dir(pw);
+		                new_home = dir;
+		                xfree(dir);
+			    if(chdir(new_home) == -1)
+				fatal("chdir to %s failed: %s",
+				new_home, strerror(errno)); 
+			    if(chroot(new_home) == -1) {
+				fatal("chroot to %s failed: %s", 
+				new_home, strerror(errno));
+			    }
+			    else
+			    pw->pw_dir = new_root;
+			}
+		    }
+		}
+
+
+#endif /* CHROOT */
 #ifdef HAVE_LOGIN_CAP
 #ifdef __bsdi__
		setpgid(0, 0);

--------------------------------

Regards,
--
John Furman <john at furna.net>




More information about the openssh-unix-dev mailing list