################################################################################ ################################################################################ # # # Original patch by Ricardo Cerqueira # # # # Updated by *** *** <***@***.***> for openssh-3.9p1 # # # # Updated by KANAI Makoto for FreeBSD ports # # # # 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 #endif +#define CHROOT + #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -1375,8 +1377,18 @@ /* 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 CHROOT + char *user_dir; + char *new_root; +#endif /* CHROOT */ + #ifndef HAVE_CYGWIN if (getuid() == 0 || geteuid() == 0) #endif /* HAVE_CYGWIN */ @@ -1397,10 +1409,30 @@ } # endif /* USE_PAM */ 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 */ @@ -1420,6 +1452,8 @@ exit(1); } endgrent(); + + # ifdef USE_PAM /* * PAM credentials may take the form of supplementary groups. @@ -1544,12 +1578,21 @@ const char *shell, *shell0, *hostname = NULL; struct passwd *pw = s->pw; +#ifdef CHROOT + char *user_dir; + char *new_root; +#endif /* CHROOT */ + /* remove hostkey from the child's memory */ destroy_sensitive_data(); /* Force a password change */ if (s->authctxt->force_pwchange) { +#ifdef CHROOT + do_setusercontext(pw, user_dir, new_root, 1); +#else do_setusercontext(pw); +#endif child_close_fds(); do_pwchange(s); exit(1); @@ -1574,7 +1617,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 /* * PAM session modules in do_setusercontext may have * generated messages, so if this in an interactive diff -ur openssh-3.9p1.orig/session.h openssh-3.9p1/session.h --- openssh-3.9p1.orig/session.h Sat Jul 17 16:05:14 2004 +++ openssh-3.9p1/session.h Thu Aug 19 09:33:10 2004 @@ -26,6 +26,8 @@ #ifndef SESSION_H #define SESSION_H +#define CHROOT + #define TTYSZ 64 typedef struct Session Session; struct Session { @@ -70,7 +72,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 void child_set_env(char ***envp, u_int *envsizep, const char *name, const char *value); diff -ur openssh-3.9p1.orig/sshd.c openssh-3.9p1/sshd.c --- openssh-3.9p1.orig/sshd.c Thu Aug 19 09:48:37 2004 +++ openssh-3.9p1/sshd.c Thu Aug 19 09:45:34 2004 @@ -101,6 +101,8 @@ #define O_NOCTTY 0 #endif +#define CHROOT + /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) @@ -676,7 +678,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);