chroot sftp-server [PATCH]
Andrew Bartlett
abartlet at pcug.org.au
Fri May 25 00:17:16 EST 2001
Is there any way of making this work? This is the method I much prefer,
and was looking at implementing a while ago. I'm glad sombodies taken a
stab at it.
I run SFTP specificly becouse it does not require a ROOT deamon (apart
from OpenSSH, which I run already) nor does it require a set-uid
binary. Hence my interest in this patch.
Andrew Bartlett
mouring at etoh.eviladmin.org wrote:
>
> Outside the fact that realpath() requires the file aspect of the path to
> exist which breaks 'rename' and 'symlink' =)
>
> - Ben
>
> On Wed, 23 May 2001 mouring at etoh.eviladmin.org wrote:
>
> >
> >
> > On 23 May 2001, Patrick Higgins wrote:
> >
> > > I'm working on setting up a semi-trusted sftp service, and to get it
> > > working, I need chroot capability.
> > >
> > Actually I was looking at it from a different point of view.
> >
> > Instead of requiring setuid sftp-sever and the use of chroot(). Carefully
> > crafted realpath() usage and strncmp() should do the same thing.
> >
> > This is a VERY VERY limited test. (As in.. compiles.. and looks like it
> > works.=)
> >
> > I know it can be cleaned up.. but it's where I left off in my testing.
> >
> > Markus, is there anything else I should worry about using this method?
> >
> > - Ben
> >
> >
> > --- ../cvs/OpenSSH/src/usr.bin/ssh/sftp-server.c Thu Apr 5 05:42:53 2001
> > +++ sftp-server.c Wed May 23 19:54:06 2001
> > @@ -357,6 +357,33 @@
> >
> > /* parse incoming */
> >
> > +char *jailpath;
> > +
> > +char*
> > +getpath(u_int32_t id)
> > +{
> > + char resolvedpath[MAXPATHLEN];
> > + char *path;
> > +
> > + path = get_string(NULL);
> > +
> > + if (realpath(path, resolvedpath) == NULL) {
> > + send_status(id, errno_to_portable(errno));
> > + xfree(path);
> > + return(NULL);
> > + }
> > + xfree(path);
> > +
> > + if (jailpath) {
> > + if (strncmp(resolvedpath, jailpath, strlen(jailpath))) {
> > + send_status(id,SSH2_FX_PERMISSION_DENIED);
> > + return(NULL);
> > + }
> > + }
> > +
> > + return(xstrdup(resolvedpath));
> > +}
> > +
> > void
> > process_init(void)
> > {
> > @@ -380,7 +407,10 @@
> > int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
> >
> > id = get_int();
> > - name = get_string(NULL);
> > + name = getpath(id);
> > + if (name == NULL)
> > + return;
> > +
> > pflags = get_int(); /* portable flags */
> > a = get_attrib();
> > flags = flags_from_portable(pflags);
> > @@ -505,7 +535,10 @@
> > int ret, status = SSH2_FX_FAILURE;
> >
> > id = get_int();
> > - name = get_string(NULL);
> > + name = getpath(id);
> > + if (name == NULL)
> > + return;
> > +
> > TRACE("%sstat id %d name %s", do_lstat ? "l" : "", id, name);
> > ret = do_lstat ? lstat(name, &st) : stat(name, &st);
> > if (ret < 0) {
> > @@ -580,7 +613,10 @@
> > int status = SSH2_FX_OK;
> >
> > id = get_int();
> > - name = get_string(NULL);
> > + name = getpath(id);
> > + if (name == NULL)
> > + return;
> > +
> > a = get_attrib();
> > TRACE("setstat id %d name %s", id, name);
> > if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
> > @@ -646,7 +682,10 @@
> > u_int32_t id;
> >
> > id = get_int();
> > - path = get_string(NULL);
> > + path = getpath(id);
> > + if (path == NULL)
> > + return;
> > +
> > TRACE("opendir id %d path %s", id, path);
> > dirp = opendir(path);
> > if (dirp == NULL) {
> > @@ -768,7 +807,10 @@
> > int ret;
> >
> > id = get_int();
> > - name = get_string(NULL);
> > + name = getpath(id);
> > + if (name == NULL)
> > + return;
> > +
> > TRACE("remove id %d name %s", id, name);
> > ret = unlink(name);
> > status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
> > @@ -785,7 +827,10 @@
> > int ret, mode, status = SSH2_FX_FAILURE;
> >
> > id = get_int();
> > - name = get_string(NULL);
> > + name = getpath(id);
> > + if (name == NULL)
> > + return;
> > +
> > a = get_attrib();
> > mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
> > a->perm & 0777 : 0777;
> > @@ -804,7 +849,10 @@
> > int ret, status;
> >
> > id = get_int();
> > - name = get_string(NULL);
> > + name = getpath(id);
> > + if (name == NULL)
> > + return;
> > +
> > TRACE("rmdir id %d name %s", id, name);
> > ret = rmdir(name);
> > status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
> > @@ -820,7 +868,10 @@
> > char *path;
> >
> > id = get_int();
> > - path = get_string(NULL);
> > + path = getpath(id);
> > + if (path == NULL)
> > + return;
> > +
> > if (path[0] == '\0') {
> > xfree(path);
> > path = xstrdup(".");
> > @@ -846,8 +897,14 @@
> > int ret, status = SSH2_FX_FAILURE;
> >
> > id = get_int();
> > - oldpath = get_string(NULL);
> > - newpath = get_string(NULL);
> > + oldpath = getpath(id);
> > + if (oldpath == NULL)
> > + return;
> > +
> > + newpath = getpath(id);
> > + if (newpath == NULL)
> > + return;
> > +
> > TRACE("rename id %d old %s new %s", id, oldpath, newpath);
> > /* fail if 'newpath' exists */
> > if (stat(newpath, &st) == -1) {
> > @@ -867,7 +924,10 @@
> > char *path;
> >
> > id = get_int();
> > - path = get_string(NULL);
> > + path = getpath(id);
> > + if (path == NULL)
> > + return;
> > +
> > TRACE("readlink id %d path %s", id, path);
> > if (readlink(path, link, sizeof(link) - 1) == -1)
> > send_status(id, errno_to_portable(errno));
> > @@ -891,8 +951,14 @@
> > int ret, status = SSH2_FX_FAILURE;
> >
> > id = get_int();
> > - oldpath = get_string(NULL);
> > - newpath = get_string(NULL);
> > + oldpath = getpath(id);
> > + if (oldpath == NULL)
> > + return;
> > +
> > + newpath = getpath(id);
> > + if (newpath == NULL)
> > + return;
> > +
> > TRACE("symlink id %d old %s new %s", id, oldpath, newpath);
> > /* fail if 'newpath' exists */
> > if (stat(newpath, &st) == -1) {
> > @@ -1004,6 +1070,32 @@
> > }
> > }
> >
> > +char*
> > +jail_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;
> > +
> > + return(xstrdup(user_dir));
> > + /*setenv("HOME", new_root, 1);*/
> > + break;
> > + }
> > + new_root += 2;
> > + }
> > + return NULL;
> > +}
> > +
> > int
> > main(int ac, char **av)
> > {
> > @@ -1018,6 +1110,8 @@
> > #ifdef DEBUG_SFTP_SERVER
> > log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0);
> > #endif
> > +
> > + jailpath = jail_init();
> >
> > in = dup(STDIN_FILENO);
> > out = dup(STDOUT_FILENO);
> >
> >
--
Andrew Bartlett
abartlet at pcug.org.au
More information about the openssh-unix-dev
mailing list