Using OpenSSH SFTP with chroot ============================= Several people have been asking now for some kind of documentation on how to use the chroot-patch for the sftp-server. So here it comes. I hope nobody minds that i post this in the developer list. The patch has been provided to the list some time ago. I'm sorry not giving credit to the author, but I really don't know who posted it in the first place. Anyway many thanks to all people developing OpenSSH. You are doing a great job! A little note on myself: I'm not very used to programming anymore. I coded a lot in the end of the 80s on a Motorola 68000 running on a good old ATARI ST. But that's long ago. So better don't ask me about in depth details. Im just starting to get back to programming. The machine on which I made the tests with SFTP CHROOT is running SuSE LINUX 7.2 with a 2.4.10 kernel. But the following step by step guide should apply to all LINUX variants. Thanks to Ben and Paulius for the feedback. -------------- Applying the patch doesn't need much programming skills. But you should be used to compiling and reading a little bit of C. 1 Obtaining the sources: =======================Get yourself a copy of the sources of OpenSSH. You can find links for downloading them on www.openssh.org. The patch can be found at the end of this document. 2 Applying the patch: ====================Apply the patch to sftp-server.c, compile and install it. The patch does the following: 1. It checks if the HOME directory of the user ends with a "/./" 2. If it finds a "/./" it makes a chroot into this HOME directory. If there is no "/./" chroot won't be done. This allows you to set up a chroot jail only for certain users. The rest of your users has normal access. (if chroot into the homedir should be done for every user, you can simply comment out the portion of the patch which checks for the "/./".) SSHD calls sftp-server in the context of the authenticated user. So you have to make sure sftp-server is SUID and owned by root: chown root .../sftp-server chmod u+s .../sftp-server (or chmod 4755) 3 Setting up a user for chroot: ==============================In /etc/passwd add a "/./" to the users homedir. e.g. (from passwd): test:x:502:100::/home/test/./:/chroot/test/sftp-server ^^^^^^^^^^^^^ Now you can start sshd and try sftp: sftp test at localhost test at localhost's password: xxxxxxxx pwd Remote working directory: / exit Before exiting the sftp session you should check that the sftp-server has dropped root priviledges. If not, something went wrong when applying the patch. ps ef|grep sftp-server ================!!! Attention !!! ================So far sftp-server is doing chroot correctly. But your users can still access your host by ssh and scp. In order to prevent this simply give them sftp- server as a loginshell. Whenever they try ssh or scp they will fail. You can also write a dummy shell. But you have to provide a login shell in any case otherwise sshd will not invoke sftp-server for your users. /bin/false as a login shell will not work. 4 Security concerns: ===================In order to prevent your sftp user from playing around with the .ssh directory you should chown root:root and then chmod 766 the .ssh directory. You can also chmod it to 000 but this forbids using keys for authentication. If you don't trust these users you should only give read access to the .ssh and any file in it. Keep all files owned by root! In my environment I also have the homedirs owned by root and I gave only read access to the users. There are several subdirs in the homedirs which are writeable for the users. I'm not sure if it's possible to do something nasty if you give sftp-server as a login shell. So maybe it's better to use a dummy shell. 5 The Patch: ===========(diff against 3.0.1) --- sftp-server.c Tue Jul 31 14:42:50 2001 +++ sftp-server.c~ Fri Nov 23 10:56:48 2001 @@ -33,6 +33,8 @@ #include "sftp.h" #include "sftp-common.h" +#define CHROOT + /* helper */ #define get_int64() buffer_get_int64(&iqueue); #define get_int() buffer_get_int(&iqueue); @@ -1008,6 +1010,36 @@ } } +#ifdef CHROOT +void +chroot_init(void) +{ + char *user_dir, *new_root; + + user_dir = getenv("HOME"); + + if (!user_dir) + fatal("HOME isn't 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 (chroot(user_dir) != 0) + fatal("Couldn't chroot to user directory %s: %s",user_dir, strerror(errno)); + + setenv("HOME", new_root, 1); + break; + } + new_root += 2; + } +} +#endif /* CHROOT */ + int main(int ac, char **av) { @@ -1022,6 +1054,13 @@ #ifdef DEBUG_SFTP_SERVER log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); #endif + +#ifdef CHROOT + chroot_init(); +#endif /* CHROOT */ + + if (setuid(getuid()) != 0) + fatal("Couldn't drop privileges: %s", strerror(errno)); in = dup(STDIN_FILENO); out = dup(STDOUT_FILENO); -- manfred heubach edv und neue medien Hindenburgstr. 47 D-73728 Esslingen Tel. +49 711 9315824 Fax +49 711 9315825 www.heubach-edv.de Informationstechnologie und Telekommunikation f?r Unternehmen -------------- next part -------------- Using OpenSSH SFTP with chroot ============================= Several people have been asking now for some kind of documentation on how to use the chroot-patch for the sftp-server. So here it comes ... The patch has been provided to the list some time ago. I?m sorry not giving credit to the author, but I really don?t know who posted it in the first place. Anyway many thanks to all people developing OpenSSH. You are doing a great job! A little note on myself: I'm not very used to programming anymore. I coded a lot in the end of the 80s on a Motorola 68000 running on a good old ATARI ST. But that's long ago. So better don't ask me about in depth details. Im just starting to get back to programming. The machine on which I made the tests with SFTP CHROOT is running SuSE LINUX 7.2 with a 2.4.10 kernel. But the following step by step guide should apply to all LINUX variants. Thanks to Ben and Paulius for the feedback. -------------- Applying the patch doesn't need much programming skills. But you should be used to compiling and reading a little bit of C. 1 Obtaining the sources: =======================Get yourself a copy of the sources of OpenSSH. You can find links for downloading them on www.openssh.org. The patch can be found at the end of this document. 2 Applying the patch: ====================Apply the patch to sftp-server.c, compile and install it. The patch does the following: 1. It checks if the HOME directory of the user ends with a "/./" 2. If it finds a "/./" it makes a chroot into this HOME directory. If there is no "/./" chroot won't be done. This allows you to set up a chroot jail only for certain users. The rest of your users has normal access. (if chroot into the homedir should be done for every user, you can simply comment out the portion of the patch which checks for the "/./".) SSHD calls sftp-server in the context of the authenticated user. So you have to make sure sftp-server is SUID and owned by root: chown root .../sftp-server chmod u+s .../sftp-server (or chmod 4755) 3 Setting up a user for chroot: ==============================In /etc/passwd add a "/./" to the users homedir. e.g. (from passwd): test:x:502:100::/home/test/./:/chroot/test/sftp-server ^^^^^^^^^^^^^ Now you can start sshd and try sftp: sftp test at localhost test at localhost?s password: xxxxxxxx pwd Remote working directory: / exit Before exiting the sftp session you should check that the sftp-server has dropped root priviledges. If not, something went wrong when applying the patch. ps ef|grep sftp-server ================!!! Attention !!! ================So far sftp-server is doing chroot correctly. But your users can still access your host by ssh and scp. In order to prevent this simply give them sftp- server as a loginshell. Whenever they try ssh or scp they will fail. You can also write a dummy shell. But you have to provide a login shell in any case otherwise sshd will not invoke sftp-server for your users. /bin/false as a login shell will not work. 4 Security concerns: ===================In order to prevent your sftp user from playing around with the .ssh directory you should chown root:root and then chmod 766 the .ssh directory. You can also chmod it to 000 but this forbids using keys for authentication. If you don?t trust these users you should only give read access to the .ssh and any file in it. Keep all files owned by root! In my environment I also have the homedirs owned by root and I gave only read access to the users. There are several subdirs in the homedirs which are writeable for the users. I?m not sure if it?s possible to do something nasty if you give sftp-server as a login shell. So maybe it?s better to use a dummy shell. 5 The Patch: ===========(diff against 3.0.1) --- sftp-server.c Tue Jul 31 14:42:50 2001 +++ sftp-server.c~ Fri Nov 23 10:56:48 2001 @@ -33,6 +33,8 @@ #include "sftp.h" #include "sftp-common.h" +#define CHROOT + /* helper */ #define get_int64() buffer_get_int64(&iqueue); #define get_int() buffer_get_int(&iqueue); @@ -1008,6 +1010,36 @@ } } +#ifdef CHROOT +void +chroot_init(void) +{ + char *user_dir, *new_root; + + user_dir = getenv("HOME"); + + if (!user_dir) + fatal("HOME isn't 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 (chroot(user_dir) != 0) + fatal("Couldn't chroot to user directory %s: %s",user_dir, strerror(errno)); + + setenv("HOME", new_root, 1); + break; + } + new_root += 2; + } +} +#endif /* CHROOT */ + int main(int ac, char **av) { @@ -1022,6 +1054,13 @@ #ifdef DEBUG_SFTP_SERVER log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); #endif + +#ifdef CHROOT + chroot_init(); +#endif /* CHROOT */ + + if (setuid(getuid()) != 0) + fatal("Couldn't drop privileges: %s", strerror(errno)); in = dup(STDIN_FILENO); out = dup(STDOUT_FILENO);