Original patch by Ricardo Cerqueira <rmcc@clix.pt>

Updated by James Dennis <james@firstaidmusic.com> for openssh-3.4

A patch to cause sshd to chroot when it encounters the magic token
'/./' in a users home directory. The directory portion before the
token is the directory to chroot() to, the portion after the
token is the user's home directory relative to the new root.

Patch source using: patch -p0 < /path/to/patch

================================================================================
diff -uNr openssh-3.4p1/session.c openssh-3.4p1-chroot/session.c
--- openssh-3.4p1/session.c	Wed Jun 26 08:51:06 2002
+++ openssh-3.4p1-chroot/session.c	Sat Jun 29 03:42:24 2002
@@ -58,6 +58,8 @@
 #include "session.h"
 #include "monitor_wrap.h"
 
+#define CHROOT
+
 #ifdef HAVE_CYGWIN
 #include <windows.h>
 #include <sys/cygwin.h>
@@ -1157,7 +1159,11 @@
 
 /* Set login name, uid, gid, and groups. */
 void
+#ifdef CHROOT
+do_setusercontext(struct passwd *pw, char *user_dir, char *new_root, int dochroot)
+#else
 do_setusercontext(struct passwd *pw)
+#endif
 {
 	char tty='\0';
 
@@ -1197,6 +1203,27 @@
 			exit(1);
 		}
 		endgrent();
+
+#ifdef CHROOT
+                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;
+
+                                if(chroot(user_dir) != 0)
+                                        fatal("Couldn't chroot to user directory %s", user_dir);
+
+                                pw->pw_dir = new_root;
+                                break;
+                        }
+                        new_root += 2;
+                }
+#endif /* CHROOT */
+
 # ifdef USE_PAM
 		/*
 		 * PAM credentials may take the form of supplementary groups. 
@@ -1256,6 +1283,11 @@
 	struct passwd *pw = s->pw;
 	u_int i;
 
+#ifdef CHROOT
+	char *user_dir;
+	char *new_root;
+#endif /* CHROOT */
+
 	/* remove hostkey from the child's memory */
 	destroy_sensitive_data();
 
@@ -1274,7 +1306,13 @@
 			do_motd();
 #else /* HAVE_OSF_SIA */
 		do_nologin(pw);
+
+#ifdef CHROOT
+		do_setusercontext(pw, user_dir, new_root, 1);
+#else
 		do_setusercontext(pw);
+#endif
+
 #endif /* HAVE_OSF_SIA */
 	}
 
diff -uNr openssh-3.4p1/session.h openssh-3.4p1-chroot/session.h
--- openssh-3.4p1/session.h	Sun Jun 23 16:48:29 2002
+++ openssh-3.4p1-chroot/session.h	Sat Jun 29 03:44:49 2002
@@ -25,6 +25,7 @@
  */
 #ifndef SESSION_H
 #define SESSION_H
+#define CHROOT
 
 #define TTYSZ 64
 typedef struct Session Session;
@@ -67,5 +68,11 @@
 Session	*session_new(void);
 Session	*session_by_tty(char *);
 void	 session_close(Session *);
+
+#ifdef CHROOT
+void	 do_setusercontext(struct passwd *, char *user_dir, char *new_root, int dochroot);
+#else
 void	 do_setusercontext(struct passwd *);
 #endif
+
+#endif
diff -uNr openssh-3.4p1/sshd.c openssh-3.4p1-chroot/sshd.c
--- openssh-3.4p1/sshd.c	Tue Jun 25 18:24:19 2002
+++ openssh-3.4p1-chroot/sshd.c	Sat Jun 29 03:55:01 2002
@@ -96,6 +96,8 @@
 #define O_NOCTTY	0
 #endif
 
+#define CHROOT
+
 #ifdef HAVE___PROGNAME
 extern char *__progname;
 #else
@@ -562,7 +564,13 @@
 	    (u_int)pw->pw_gid);
 #if 0
 	/* XXX not ready, to heavy after chroot */
+
+#ifdef CHROOT
+	do_setusercontext(pw, pw->pw_dir, NULL, 0);
+#else
 	do_setusercontext(pw);
+#endif
+
 #else
 	gidset[0] = pw->pw_gid;
 	if (setgid(pw->pw_gid) < 0)
@@ -663,7 +671,11 @@
 	demote_sensitive_data();
 
 	/* Drop privileges */
+#ifdef CHROOT
+	do_setusercontext(authctxt->pw, authctxt->pw->pw_dir, NULL, 0);
+#else
 	do_setusercontext(authctxt->pw);
+#endif
 
 	/* It is safe now to apply the key state */
 	monitor_apply_keystate(pmonitor);
