Original patch by Ricardo Cerqueira Updated by James Dennis for openssh-3.5 Updated by KANAI Makoto for FreeBSD 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. cd /usr/ports/security/openssh-portable make patch ( cd $WRKDIRPREFIX/usr/ports/security/openssh-portable/work; patch -p0 #include @@ -1355,7 +1357,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 { #ifdef HAVE_CYGWIN if (is_winnt) { @@ -1370,10 +1376,32 @@ setpgid(0, 0); # endif if (setusercontext(lc, pw, pw->pw_uid, - (LOGIN_SETALL & ~(LOGIN_SETENV|LOGIN_SETPATH))) < 0) { + (LOGIN_SETALL & ~(LOGIN_SETENV|LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { perror("unable to set user context"); exit(1); } + +#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 */ + permanently_set_uid(pw); + #else # if defined(HAVE_GETLUID) && defined(HAVE_SETLUID) /* Sets login uid for accounting */ @@ -1451,6 +1479,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(); @@ -1473,7 +1506,11 @@ 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.5p1/session.h openssh-3.5p1-chroot/session.h --- openssh-3.5p1/session.h Wed Jul 3 19:14:18 2002 +++ openssh-3.5p1-chroot/session.h Wed Oct 16 03:21:28 2002 @@ -26,6 +26,8 @@ #ifndef SESSION_H #define SESSION_H +#define CHROOT + #define TTYSZ 64 typedef struct Session Session; struct Session { @@ -67,5 +69,10 @@ 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.5p1/sshd.c openssh-3.5p1-chroot/sshd.c --- openssh-3.5p1/sshd.c Sun Sep 29 20:59:23 2002 +++ openssh-3.5p1-chroot/sshd.c Wed Oct 16 15:25:37 2002 @@ -96,6 +96,8 @@ #define O_NOCTTY 0 #endif +#define CHROOT + #ifdef HAVE___PROGNAME extern char *__progname; #else @@ -674,7 +676,11 @@ demote_sensitive_data(); /* Drop privileges */ +#ifdef CHROOT + do_setusercontext(authctxt->pw, NULL, NULL, 0); +#else do_setusercontext(authctxt->pw); +#endif /* It is safe now to apply the key state */ monitor_apply_keystate(pmonitor);