Index: scp.c
--- scp.c.orig	2008-11-03 09:23:45 +0100
+++ scp.c	2009-10-02 13:10:45 +0200
@@ -140,6 +140,11 @@
 /* This is the program to execute for the secured connection. ("ssh" or -S) */
 char *ssh_program = _PATH_SSH_PROGRAM;
 
+/* The directory to perform a chroot(2) to before operation (intended for server-side only) */
+#ifdef USE_CHROOT
+char *chrootdir  = NULL;
+#endif
+
 /* This is used to store the pid of ssh_program */
 pid_t do_cmd_pid = -1;
 
@@ -323,7 +328,11 @@
 	addargs(&args, "-oClearAllForwardings yes");
 
 	fflag = tflag = 0;
+#ifdef USE_CHROOT
+	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:R:")) != -1)
+#else
 	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
+#endif
 		switch (ch) {
 		/* User-visible flags. */
 		case '1':
@@ -384,6 +393,11 @@
 			setmode(0, O_BINARY);
 #endif
 			break;
+#ifdef USE_CHROOT
+		case 'R':
+			chrootdir = xstrdup(optarg);
+			break;
+#endif
 		default:
 			usage();
 		}
@@ -399,6 +413,19 @@
 	remin = STDIN_FILENO;
 	remout = STDOUT_FILENO;
 
+#ifdef USE_CHROOT
+	if (chrootdir != NULL) {
+		if (geteuid() != 0)
+			fatal("chroot(2) not possible: euid %ld != 0", (long)geteuid());
+		if (chroot(chrootdir) == -1)
+			fatal("couldn't chroot(2) to directory \"%s\": %s", chrootdir, strerror(errno));
+		if (setuid(getuid()) == -1)
+			fatal("couldn't drop privileges with setuid(2): %s", strerror(errno));
+		if (chdir("/") == -1)
+			fatal("couldn't change to root directory: %s", strerror(errno));
+	}
+#endif
+
 	if (fflag) {
 		/* Follow "protocol", send data. */
 		(void) response();
Index: session.c
--- session.c.orig	2009-08-20 08:20:50 +0200
+++ session.c	2009-10-02 13:10:45 +0200
@@ -1532,6 +1532,25 @@
 			free(tmp);
 			free(chroot_path);
 		}
+# ifdef USE_CHROOT
+		{
+			char *user_dir;
+			char *new_root;
+			user_dir = xstrdup(pw->pw_dir);
+			new_root = user_dir + 1;
+			while ((new_root = strchr(new_root, '.')) != NULL) {
+			    new_root--;
+			    if (strncmp(new_root, "/./", 3) == 0) {
+			        *new_root = '\0';
+			        new_root += 2;
+			        safely_chroot(user_dir, pw->pw_uid);
+			        pw->pw_dir = new_root;
+			        break;
+			    }
+			    new_root += 2;
+			}
+		}
+# endif /* USE_CHROOT */
 
 #ifdef HAVE_SETPCRED
 		if (setpcred(pw->pw_name, (char **)NULL) == -1)
Index: sftp-server.c
--- sftp-server.c.orig	2009-08-28 02:43:13 +0200
+++ sftp-server.c	2009-10-02 13:10:45 +0200
@@ -1387,6 +1387,38 @@
 	logit("session opened for local user %s from [%s]",
 	    pw->pw_name, client_addr);
 
+#ifdef USE_CHROOT
+{
+	char *user_dir;
+	char *new_root;
+	user_dir = getenv("HOME");
+	if (user_dir == NULL)
+		fatal("HOME variable not found in environment");
+	new_root = user_dir + 1;
+	while ((new_root = strchr(new_root, '.')) != NULL) {
+		new_root--;
+		if (strncmp(new_root, "/./", 3) == 0) {
+			*new_root = '\0';
+			new_root += 2;
+			if (geteuid() == 0) {
+				/* chroot to subdir and adjust HOME for remaining path */
+				if (chroot(user_dir) == -1)
+					fatal("Couldn't chroot to user directory \"%s\": %s", user_dir, strerror(errno));
+				if (setuid(getuid()) == -1)
+					fatal("Couldn't drop privileges: %s", strerror(errno));
+				setenv("HOME", new_root, 1);
+			}
+			else {
+				/* ignore chroot request and adjust HOME for preceeding path */
+				setenv("HOME", user_dir, 1);
+			}
+			break;
+		}
+		new_root += 2;
+	}
+}
+#endif /* USE_CHROOT */
+
 	in = dup(STDIN_FILENO);
 	out = dup(STDOUT_FILENO);
 
