chroot howto for sftp-server

MH - Entwicklung entwicklung at heubach-edv.de
Tue Dec 18 23:27:28 EST 2001


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);



More information about the openssh-unix-dev mailing list