diff -uNr openssh-3.5p1/auth.c openssh-3.5p1-chroot/auth.c
--- openssh-3.5p1/auth.c	2002-09-21 10:26:53.000000000 -0500
+++ openssh-3.5p1-chroot/auth.c	2003-01-01 21:08:36.000000000 -0600
@@ -359,6 +359,13 @@
 	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.5p1/auth.h openssh-3.5p1-chroot/auth.h
--- openssh-3.5p1/auth.h	2002-09-26 22:26:01.000000000 -0500
+++ openssh-3.5p1-chroot/auth.h	2003-01-01 21:08:37.000000000 -0600
@@ -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.5p1/configure.ac openssh-3.5p1-chroot/configure.ac
--- openssh-3.5p1/configure.ac	2002-09-25 19:38:47.000000000 -0500
+++ openssh-3.5p1-chroot/configure.ac	2003-01-01 21:08:45.000000000 -0600
@@ -682,6 +682,19 @@
 
 AC_FUNC_GETPGRP
 
+
+CHROOT_MSG="no"
+AC_ARG_WITH(chroot,
+	[  --with-chroot           Enable Chroot Support],
+	[
+		CHROOT_MSG="yes"
+	]
+)
+ 
+if test "x$CHROOT_MSG" = "xyes"; then
+	AC_DEFINE(CHROOT,1, Define if you want to enable CHROOT support)
+fi
+
 # Check for PAM libs
 PAM_MSG="no"
 AC_ARG_WITH(pam,
@@ -2463,6 +2476,7 @@
 fi
 echo "                    Manpage format: $MANTYPE"
 echo "                       PAM support: ${PAM_MSG}"
+echo "                    Chroot support: $CHROOT_MSG"
 echo "                KerberosIV support: $KRB4_MSG"
 echo "                 KerberosV support: $KRB5_MSG"
 echo "                 Smartcard support: $SCARD_MSG"
diff -uNr openssh-3.5p1/loginrec.c openssh-3.5p1-chroot/loginrec.c
--- openssh-3.5p1/loginrec.c	2002-09-25 19:38:49.000000000 -0500
+++ openssh-3.5p1-chroot/loginrec.c	2003-01-01 21:08:50.000000000 -0600
@@ -1320,6 +1320,7 @@
 static int
 syslogin_perform_logout(struct logininfo *li)
 {
+# ifndef CHROOT
 # ifdef HAVE_LOGOUT
 	char line[8];
 
@@ -1337,6 +1338,7 @@
 	 * routines are in libutil so they should all be there,
 	 * but... */
 # endif
+# endif
 	return 1;
 }
 
diff -uNr openssh-3.5p1/pathnames.h openssh-3.5p1-chroot/pathnames.h
--- openssh-3.5p1/pathnames.h	2002-06-06 14:57:34.000000000 -0500
+++ openssh-3.5p1-chroot/pathnames.h	2003-01-01 21:08:57.000000000 -0600
@@ -97,6 +97,9 @@
 /* backward compat for protocol v2 */
 #define _PATH_SSH_USER_PERMITTED_KEYS2	".ssh/authorized_keys2"
 
+/* default user chroot dir */
+#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.5p1/servconf.c openssh-3.5p1-chroot/servconf.c
--- openssh-3.5p1/servconf.c	2002-09-04 23:35:15.000000000 -0500
+++ openssh-3.5p1-chroot/servconf.c	2003-01-02 00:15:21.000000000 -0600
@@ -109,6 +109,8 @@
 	options->num_deny_users = 0;
 	options->num_allow_groups = 0;
 	options->num_deny_groups = 0;
+	options->num_chroot_users = 0;
+	options->num_nochroot_users = 0;
 	options->ciphers = NULL;
 	options->macs = NULL;
 	options->protocol = SSH_PROTO_UNKNOWN;
@@ -121,8 +123,10 @@
 	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;
+	options->chroot_all = -1;
 
 	/* Needs to be accessable in many places */
 	use_privsep = -1;
@@ -255,7 +259,10 @@
 	}
 	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;
+	if (options->chroot_all == -1  ) 
+		options->chroot_dir = NULL;
 	/* Turn privilege separation on by default */
 	if (use_privsep == -1)
 		use_privsep = 1;
@@ -295,12 +302,12 @@
 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
 	sStrictModes, sEmptyPasswd, sKeepAlives,
 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
-	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+	sAllowUsers, sDenyUsers, sChrootUsers, sNoChrootUsers, sAllowGroups, sDenyGroups,
 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
 	sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
-	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
+	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,sChrootDir,sChrootAll,
 	sUsePrivilegeSeparation,
 	sDeprecated
 } ServerOpCodes;
@@ -364,6 +371,8 @@
 	{ "allowtcpforwarding", sAllowTcpForwarding },
 	{ "allowusers", sAllowUsers },
 	{ "denyusers", sDenyUsers },
+	{ "chrootusers", sChrootUsers },
+	{ "nochrootusers", sNoChrootUsers },
 	{ "allowgroups", sAllowGroups },
 	{ "denygroups", sDenyGroups },
 	{ "ciphers", sCiphers },
@@ -379,6 +388,8 @@
 	{ "clientalivecountmax", sClientAliveCountMax },
 	{ "authorizedkeysfile", sAuthorizedKeysFile },
 	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+	{ "chrootdir", sChrootDir },
+	{ "chrootall", sChrootAll },
 	{ "useprivilegeseparation", sUsePrivilegeSeparation},
 	{ NULL, sBadOption }
 };
@@ -787,6 +798,24 @@
 		}
 		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 sNoChrootUsers:
+		while ((arg = strdelim(&cp)) && *arg != '\0') {
+			if (options->num_nochroot_users >= MAX_CHROOT_USERS)
+				fatal( "%s line %d: too many NonChroot'ed users.",
+				    filename, linenum);
+			options->nochroot_users[options->num_nochroot_users++] =
+			    xstrdup(arg);
+                }
+		break;
 	case sAllowGroups:
 		while ((arg = strdelim(&cp)) && *arg != '\0') {
 			if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
@@ -901,6 +930,13 @@
 		    &options->authorized_keys_file2;
 		goto parse_filename;
 
+	case sChrootDir:
+		charptr = &options->chroot_dir;
+		goto parse_filename;
+	case sChrootAll:
+		intptr = &options->chroot_all;
+		goto parse_flag;
+
 	case sClientAliveInterval:
 		intptr = &options->client_alive_interval;
 		goto parse_time;
diff -uNr openssh-3.5p1/servconf.h openssh-3.5p1-chroot/servconf.h
--- openssh-3.5p1/servconf.h	2002-07-31 20:28:39.000000000 -0500
+++ openssh-3.5p1-chroot/servconf.h	2003-01-01 21:09:01.000000000 -0600
@@ -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 # of Chroot Users, fairly useless, no? */
 #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. */
@@ -105,6 +106,10 @@
 	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_nochroot_users;
+	char   * nochroot_users[MAX_CHROOT_USERS];
 	u_int num_allow_groups;
 	char   *allow_groups[MAX_ALLOW_GROUPS];
 	u_int num_deny_groups;
@@ -131,6 +136,8 @@
 
 	char   *authorized_keys_file;	/* File containing public keys */
 	char   *authorized_keys_file2;
+	int     chroot_all;
+	char   *chroot_dir;
 	int	pam_authentication_via_kbd_int;
 }       ServerOptions;
 
diff -uNr openssh-3.5p1/session.c openssh-3.5p1-chroot/session.c
--- openssh-3.5p1/session.c	2003-01-03 04:29:19.000000000 -0600
+++ openssh-3.5p1-chroot/session.c	2003-01-03 04:30:11.000000000 -0600
@@ -57,11 +57,15 @@
 #include "canohost.h"
 #include "session.h"
 #include "monitor_wrap.h"
+#include "match.h"
+#include "readconf.h"
+
 
 #ifdef HAVE_CYGWIN
 #include <windows.h>
 #include <sys/cygwin.h>
 #define is_winnt       (GetVersion() < 0x80000000)
+#undef CHROOT
 #endif
 
 /* func */
@@ -87,6 +91,11 @@
 
 static int session_pty_req(Session *);
 
+#ifdef CHROOT
+int chroot_ok (struct passwd *pw);
+#endif
+
+
 /* import */
 extern ServerOptions options;
 extern char *__progname;
@@ -1191,10 +1200,51 @@
 	}
 }
 
+#ifdef CHROOT
+int
+chroot_ok (struct passwd *pw)
+{
+
+  int i,rv=0;
+  const char *hostname = NULL;
+  const char *ipaddr = NULL;
+
+  hostname = get_canonical_hostname (options.verify_reverse_mapping);
+  ipaddr = get_remote_ipaddr ();
+  if (options.chroot_all){
+      rv = 1;
+      for (i = 0; i < options.num_nochroot_users; i++){
+         if (match_user (pw->pw_name, hostname, ipaddr, options.nochroot_users[i])){
+             debug ("Match found for %s@%s[%s]:%s", pw->pw_name, ipaddr,
+                    hostname, options.nochroot_users[i]);
+             return 0;
+           }
+       }
+  }
+  else if (options.num_chroot_users > 0){
+      for (i = 0; i < options.num_chroot_users; i++){
+         if (match_user (pw->pw_name, hostname, ipaddr, options.chroot_users[i])){
+             debug ("Match found for %s@%s[%s]:%s", pw->pw_name, ipaddr,
+                    hostname, options.chroot_users[i]);
+             return 1;
+         }
+      }
+  }
+  debug ("No Match found for %s@%s[%s]", pw->pw_name, ipaddr, hostname);
+  return rv;
+}
+#endif
+								
+
 /* Set login name, uid, gid, and groups. */
 void
 do_setusercontext(struct passwd *pw)
 {
+#ifdef CHROOT
+  char *new_home = NULL;
+  struct passwd *tpw;          //After Chroot,chdir to the homedir
+  struct stat   st_root;
+#endif
 #ifdef HAVE_CYGWIN
 	if (is_winnt) {
 #else /* HAVE_CYGWIN */
@@ -1203,6 +1253,36 @@
 #ifdef HAVE_SETPCRED
 		setpcred(pw->pw_name);
 #endif /* HAVE_SETPCRED */
+#ifdef CHROOT
+      if (chroot_ok (pw)) {
+         new_home = chroot_dir (pw);
+         debug ("My new home is '%s'", new_home);
+	 if ((stat(new_home,&st_root)) != 0) {
+ 	   fatal("can't stat %s: %s",new_home,strerror(errno));
+ 	 }
+ 	 if (!S_ISDIR(st_root.st_mode)) {
+ 	   fatal("%s not a directory",new_home);
+	 }
+	 if (st_root.st_uid != 0 || st_root.st_gid != 0) {
+	   fatal("owner of %s is uid %d and gid %d, not root's uid or gid",new_home,st_root.st_uid,st_root.st_gid);
+	 }
+         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 {
+           if (chdir ("/") == -1)
+             fatal ("chdir to %s failed: %s", "/", strerror (errno));
+           //Post CHROOT, need to try and get a new homedir for user
+           tpw = getpwuid (pw->pw_uid);
+           pw->pw_dir = tpw->pw_dir;
+           debug ("New Home dir is %s", pw->pw_dir);
+           //Shouldn't this be freed @ somepoint?
+         }
+         xfree (new_home);
+       }
+#endif /* CHROOT */
 #ifdef HAVE_LOGIN_CAP
 # ifdef __bsdi__
 		setpgid(0, 0);
@@ -1650,13 +1730,12 @@
 	int success = 0;
 	char *cmd, *subsys = packet_get_string(&len);
 	int i;
-
 	packet_check_eom();
 	log("subsystem request for %.100s", subsys);
 
 	for (i = 0; i < options.num_subsystems; i++) {
 		if (strcmp(subsys, options.subsystem_name[i]) == 0) {
-			cmd = options.subsystem_command[i];
+			cmd = options.subsystem_command[i]; 
 			if (stat(cmd, &st) < 0) {
 				error("subsystem: cannot stat %s: %s", cmd,
 				    strerror(errno));
diff -uNr openssh-3.5p1/sshd_config openssh-3.5p1-chroot/sshd_config
--- openssh-3.5p1/sshd_config	2002-09-26 22:21:58.000000000 -0500
+++ openssh-3.5p1-chroot/sshd_config	2003-01-03 04:26:11.000000000 -0600
@@ -89,5 +89,13 @@
 #Banner /some/path
 #VerifyReverseMapping no
 
+#Chroot Additions
+#ChrootDir %h/chome/
+#ChrootAll yes
+#List of Usernames space separated below, ignored if ChrootAll is set.
+#ChrootUsers 
+#NoChrootUsers root
+
+
 # override default of no subsystems
 Subsystem	sftp	/usr/libexec/sftp-server
