About sftp-server root path

Damien Miller djm at mindrot.org
Tue Oct 10 09:50:40 EST 2006


On Sun, 8 Oct 2006, Bruno Cesar Ribas wrote:

> Hi,
> 
> I saw in archive that some people made a patch to sftp-server, and
> that patch sets a root path. I'd like to know if there's an ideia to
> apply that patch in main tree of openssh?
>
> With the use of SSHFS [wich uses sftp-server], it would be interesting
> to have someting like that, because as we have netboot workstations,
> the access to devices [such as, floppy, cdrom and usb data] are
> becoming to be used by sshfs, but we don't want that users can make an
> sftp tunnell and mount others directories besides those pre-determined
> [i.e /mnt].

Here is my current sftp-server chroot diff for OpenBSD. It should
apply to portable too, but it will be up to you to make a change
that corresponds to the sftp-server/Makefile hunk.

Chroot is enabled using commandline options to sftp-server much 
like the new logging options. 

I think the patch is safe, but haven't run through the extra code it
exposes with root privileges or fully considered what new attacks it
might enable - so don't apply it unless you are willing to do so.

I don't know when I'll have time to come back to this, but maybe some
lurkers on this mailing list feel like analysing/auditing it.

-d

diff -urp ssh/sftp-server/Makefile ssh-x/sftp-server/Makefile
--- sftp-server/Makefile	Tue Jun 13 11:22:55 2006
+++ sftp-server/Makefile	Sat Apr 22 09:41:18 2006
@@ -5,7 +5,7 @@
 PROG=	sftp-server
 BINOWN=	root
 
-BINMODE?=555
+BINMODE?=4555
 
 BINDIR=	/usr/libexec
 MAN=	sftp-server.8
diff -urp ssh/sftp-server.8 ssh-x/sftp-server.8
--- sftp-server.8	Tue Jun 13 11:23:10 2006
+++ sftp-server.8	Tue Apr 25 18:16:06 2006
@@ -30,6 +30,7 @@
 .Nd SFTP server subsystem
 .Sh SYNOPSIS
 .Nm sftp-server
+.Op Fl C Ar chroot_path
 .Op Fl f Ar log_facility
 .Op Fl l Ar log_level
 .Sh DESCRIPTION
@@ -54,6 +55,25 @@ for more information.
 .Pp
 Valid options are:
 .Bl -tag -width Ds
+.It Fl C Ar chroot_path
+Requests that
+.Nm
+.Xr chroot 2
+itself to the specified path prior to processing requests from the user.
+The
+.Ar chroot_path
+use the tilde syntax to refer to a user's home directory or one of the
+following
+escape characters:
+.Ql %d
+(local user's home directory) or
+.Ql %g
+(local user's primary group name).
+Note that
+.Xr chroot 2
+support requires
+.Nm
+to be installed setuid root.
 .It Fl f Ar log_facility
 Specifies the facility code that is used when logging messages from
 .Nm .
diff -urp ssh/sftp-server.c ssh-x/sftp-server.c
--- sftp-server.c	Tue Jun 13 11:23:42 2006
+++ sftp-server.c	Tue Jun 13 11:24:35 2006
@@ -1154,6 +1154,35 @@ process(void)
 		buffer_consume(&iqueue, msg_len - consumed);
 }
 
+static void
+do_chroot(const char *chroot_path_template)
+{
+	char *cp, *chroot_path;
+	struct group *gr;
+
+	if ((gr = getgrgid(pw->pw_gid)) == NULL)
+		fatal("No group found for gid %lu", (u_long)pw->pw_gid);
+
+	cp = percent_expand(chroot_path_template, "d", pw->pw_dir,
+	    "u", pw->pw_name, "g", gr->gr_name, (char *)NULL);
+	chroot_path = tilde_expand_filename(cp, getuid());
+	xfree(cp);
+
+	logit("chroot to %s", chroot_path);
+
+	/* Ensure the user has rights to access the chroot path first */
+	temporarily_use_uid(pw);
+	if (chdir(chroot_path) == -1)
+		fatal("chdir(\"%s\"): %s", chroot_path, strerror(errno));
+	restore_uid();
+
+	if (chroot(chroot_path) == -1)
+		fatal("chroot(\"%s\"): %s", chroot_path, strerror(errno));
+	if (chdir("/") == -1)
+		fatal("chdir(\"/\"): %s", strerror(errno));
+	xfree(chroot_path);
+}
+
 /* Cleanup handler that logs active handles upon normal exit */
 void
 cleanup_exit(int i)
@@ -1179,7 +1208,7 @@ main(int argc, char **argv)
 	int in, out, max, ch, skipargs = 0, log_stderr = 0;
 	ssize_t len, olen, set_size;
 	SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
-	char *cp;
+	char *cp, *chroot_path = NULL;
 
 	extern int optind;
 	extern char *optarg;
@@ -1192,6 +1221,9 @@ main(int argc, char **argv)
 
 	while (!skipargs && (ch = getopt(argc, argv, "C:f:l:che")) != -1) {
 		switch (ch) {
+		case 'C':
+			chroot_path = optarg;
+			break;
 		case 'c':
 			/*
 			 * Ignore all arguments if we are invoked as a
@@ -1236,6 +1268,11 @@ main(int argc, char **argv)
 	logit("session opened for client %s local user %s",
 	    client_addr, pw->pw_name);
 
+	if (chroot_path != NULL)
+		do_chroot(chroot_path);
+	if (getuid() != geteuid())
+		permanently_set_uid(pw);
+		
 	handle_init();
 
 	in = dup(STDIN_FILENO);



More information about the openssh-unix-dev mailing list