--- Makefile.in.orig	2003-11-17 15:52:22.000000000 -0700
+++ Makefile.in	2003-09-21 19:00:12.000000000 -0600
@@ -154,8 +154,8 @@
 ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
 	$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) 
 
-sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o
-	$(LD) -o $@ sftp-server.o sftp-common.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o groupaccess.o
+	$(LD) -o $@ sftp-server.o sftp-common.o groupaccess.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 
 
 sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o progressmeter.o
 	$(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
--- sftp-server.c.orig	2003-11-11 22:31:36.000000000 -0700
+++ sftp-server.c	2003-08-21 17:34:41.000000000 -0600
@@ -52,12 +52,6 @@
 /* Version of client */
 int version;
 
+#define __CHROOT_HACK__ 1
+
+#ifdef __CHROOT_HACK__
+char *chroot_path;
+#endif
+
 /* portable attributes, etc. */
 
 typedef struct Stat Stat;
@@ -68,61 +62,6 @@
 	Attrib attrib;
 };
 
+
+#ifdef __CHROOT_HACK__
+
+#include "groupaccess.h"
+
+static void
+chroot_init_path()
+{
+	struct passwd *pw;
+	char *uname;
+
+	// Should change this to read using glibc function call...
+	uname = getenv("USER");
+
+	if (!uname) {
+		// For some reason we can't read the username from the environment.
+		//	Let's just set the "jail" directory to "/var/empty" and be done with it...
+		strcpy(chroot_path, "/var/empty");
+		return;
+	}
+
+	// Get the info from the "passwd" file...
+	pw = getpwnam(uname);
+
+	if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+		// This shouldn't ever happen, but handle it gracefully anyway...
+		chroot_path = malloc(11);
+		strcpy(chroot_path, "/var/empty");
+	} else {
+		char *nojail_groups[1];
+		nojail_groups[0] = "wheel";
+
+		// Check to see if the user is in the wheel group.
+		if (ga_match(nojail_groups, 1)) {
+			chroot_path = malloc(2);
+			strcpy(chroot_path, "/");
+		} else {
+			// If not, jail them in their respective home directory...
+			chroot_path = malloc(strlen(pw->pw_dir) + 1);
+			strcpy(chroot_path, pw->pw_dir);
+		}
+	}
+	ga_free();
+}
+
+static int
+chroot_check_path(char *path)
+{
+	if (path && path[0] == '/') {
+		return (strstr(path, chroot_path) != NULL);
+	} else 
+		return 1;
+}
+#endif
+
 static int
 errno_to_portable(int unixerrno)
 {
@@ -455,14 +394,6 @@
 	flags = flags_from_portable(pflags);
 	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
 	TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(name)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(name);
+		return;
+	}
+#endif
 	fd = open(name, flags, mode);
 	if (fd < 0) {
 		status = errno_to_portable(errno);
@@ -584,14 +515,6 @@
 	id = get_int();
 	name = get_string(NULL);
 	TRACE("%sstat id %u name %s", do_lstat ? "l" : "", id, name);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(name)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(name);
+		return;
+	}
+#endif
 	ret = do_lstat ? lstat(name, &st) : stat(name, &st);
 	if (ret < 0) {
 		status = errno_to_portable(errno);
@@ -667,14 +590,6 @@
 	name = get_string(NULL);
 	a = get_attrib();
 	TRACE("setstat id %u name %s", id, name);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(name)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(name);
+		return;
+	}
+#endif
 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
 		ret = truncate(name, a->size);
 		if (ret == -1)
@@ -764,14 +679,6 @@
 	id = get_int();
 	path = get_string(NULL);
 	TRACE("opendir id %u path %s", id, path);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(path)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(path);
+		return;
+	}
+#endif
 	dirp = opendir(path);
 	if (dirp == NULL) {
 		status = errno_to_portable(errno);
@@ -856,14 +763,6 @@
 	id = get_int();
 	name = get_string(NULL);
 	TRACE("remove id %u name %s", id, name);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(name)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(name);
+		return;
+	}
+#endif
 	ret = unlink(name);
 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
 	send_status(id, status);
@@ -884,14 +783,6 @@
 	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
 	    a->perm & 0777 : 0777;
 	TRACE("mkdir id %u name %s mode 0%o", id, name, mode);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(name)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(name);
+		return;
+	}
+#endif
 	ret = mkdir(name, mode);
 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
 	send_status(id, status);
@@ -907,19 +798,9 @@
 
 	id = get_int();
 	name = get_string(NULL);
-
 	TRACE("rmdir id %u name %s", id, name);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(name)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+	} else {
+		ret = rmdir(name);
+		status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+	}
+#else
 	ret = rmdir(name);
 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+#endif
 	send_status(id, status);
 	xfree(name);
 }
@@ -962,15 +843,6 @@
 	newpath = get_string(NULL);
 	TRACE("rename id %u old %s new %s", id, oldpath, newpath);
 	status = SSH2_FX_FAILURE;
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(oldpath) || !chroot_check_path(newpath)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(oldpath);
+		xfree(newpath);
+		return;
+	}
+#endif
 	if (lstat(oldpath, &sb) == -1)
 		status = errno_to_portable(errno);
 	else if (S_ISREG(sb.st_mode)) {
@@ -1005,13 +877,6 @@
 	id = get_int();
 	path = get_string(NULL);
 	TRACE("readlink id %u path %s", id, path);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(path)) {
+		send_status(id, SSH2_FX_PERMISSION_DENIED);
+		xfree(path);
+		return;
+	}
+#endif
 	if ((len = readlink(path, link, sizeof(link) - 1)) == -1)
 		send_status(id, errno_to_portable(errno));
 	else {
@@ -1036,15 +901,6 @@
 	oldpath = get_string(NULL);
 	newpath = get_string(NULL);
 	TRACE("symlink id %u old %s new %s", id, oldpath, newpath);
+#ifdef __CHROOT_HACK__
+	if (!chroot_check_path(oldpath) || !chroot_check_path(newpath)) {
+		status = SSH2_FX_PERMISSION_DENIED;
+		send_status(id, status);
+		xfree(oldpath);
+		xfree(newpath);
+		return;
+	}
+#endif
 	/* this will fail if 'newpath' exists */
 	ret = symlink(oldpath, newpath);
 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
@@ -1172,10 +1028,6 @@
 	int in, out, max;
 	ssize_t len, olen, set_size;
 
+#ifdef __CHROOT_HACK__
+	chroot_init_path();
+#endif
+
 	/* XXX should use getopt */
 
 	__progname = ssh_get_progname(av[0]);
