Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP4:GA
openssh
openssh-7.2p2-sftp_homechroot.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File openssh-7.2p2-sftp_homechroot.patch of Package openssh
# HG changeset patch # Parent 61f84e53558b040bb7f91d5eed9e8566fae866c2 run sftp sessions inside a chroot diff --git a/openssh-7.2p2/session.c b/openssh-7.2p2/session.c --- a/openssh-7.2p2/session.c +++ b/openssh-7.2p2/session.c @@ -123,16 +123,18 @@ int do_exec(Session *, const char *); void do_login(Session *, const char *); #ifdef LOGIN_NEEDS_UTMPX static void do_pre_login(Session *s); #endif void do_child(Session *, const char *); void do_motd(void); int check_quietlogin(Session *, const char *); +int chroot_no_tree = 0; + static void do_authenticated1(Authctxt *); static void do_authenticated2(Authctxt *); static int session_pty_req(Session *); /* import */ extern ServerOptions options; extern char *__progname; @@ -838,16 +840,21 @@ do_exec(Session *s, const char *command) "subsystem '%.900s'", s->subsys); } else if (command == NULL) { snprintf(session_type, sizeof(session_type), "shell"); } else { /* NB. we don't log unforced commands to preserve privacy */ snprintf(session_type, sizeof(session_type), "command"); } + if ((s->is_subsystem != SUBSYSTEM_INT_SFTP) && chroot_no_tree) { + logit("You aren't welcomed, go away!"); + exit (1); + } + if (s->ttyfd != -1) { tty = s->tty; if (strncmp(tty, "/dev/", 5) == 0) tty += 5; } verbose("Starting session: %s%s%s for %s from %.200s port %d id %d", session_type, @@ -1492,58 +1499,123 @@ do_nologin(struct passwd *pw) while (fgets(buf, sizeof(buf), f)) fputs(buf, stderr); fclose(f); } exit(254); } /* + * Test if filesystem is mounted nosuid and nodev + */ + +static void +test_nosuid (char * path, dev_t fs) +{ + FILE *f; + struct stat st; + char buf[4096], *s, *on, *mountpoint, *opt; + int nodev, nosuid; + + if (!(f = popen ("/bin/mount", "r"))) + fatal ("%s: popen(\"/bin/mount\", \"r\"): %s", + __func__, strerror (errno)); + for (;;) { + s = fgets (buf, sizeof (buf), f); + if (ferror (f)) + fatal ("%s: read from popen: %s", __func__, + strerror (errno)); + if (!s) { + pclose (f); + fatal ("cannot find filesystem with the chroot directory"); + } + (void) strtok (buf, " "); + on = strtok (NULL, " "); + if (strcmp (on, "on")) { + pclose (f); + fatal ("bad format of mount output"); + } + mountpoint = strtok (NULL, " "); + if (memcmp (path, mountpoint, strlen (mountpoint))) + continue; + if (stat(mountpoint, &st) != 0) { + pclose (f); + fatal("%s: stat(\"%s\"): %s", __func__, + mountpoint, strerror(errno)); + } + if (fs != st.st_dev) + continue; + nodev = nosuid = 0; + for (opt = strtok (NULL, "("); opt; opt = strtok (NULL, " ,)")) { + if (!strcmp (opt, "nodev")) + nodev = 1; + else if (!strcmp (opt, "nosuid")) + nosuid = 1; + else if (!strcmp (opt, "noexec")) + nosuid = 1; + if (nodev && nosuid) { + pclose (f); + return; + } + } + fatal ("chroot into directory without nodev and either noexec or nosuid"); + } +} + +/* * Chroot into a directory after checking it for safety: all path components * must be root-owned directories with strict permissions. */ static void safely_chroot(const char *path, uid_t uid) { const char *cp; char component[PATH_MAX]; struct stat st; + int last; if (*path != '/') fatal("chroot path does not begin at root"); if (strlen(path) >= sizeof(component)) fatal("chroot path too long"); /* * Descend the path, checking that each component is a * root-owned directory with strict permissions. */ for (cp = path; cp != NULL;) { - if ((cp = strchr(cp, '/')) == NULL) + if (last = ((cp = strchr(cp, '/')) == NULL)) strlcpy(component, path, sizeof(component)); else { cp++; memcpy(component, path, cp - path); component[cp - path] = '\0'; } debug3("%s: checking '%s'", __func__, component); if (stat(component, &st) != 0) fatal("%s: stat(\"%s\"): %s", __func__, component, strerror(errno)); - if (st.st_uid != 0 || (st.st_mode & 022) != 0) + if ((st.st_uid != 0 || (st.st_mode & 022) != 0) && !(last && st.st_uid == uid)) fatal("bad ownership or modes for chroot " "directory %s\"%s\"", cp == NULL ? "" : "component ", component); if (!S_ISDIR(st.st_mode)) fatal("chroot path %s\"%s\" is not a directory", cp == NULL ? "" : "component ", component); } + setenv ("TZ", "/etc/localtime", 0); + tzset(); + + if (st.st_uid) { + test_nosuid(path, st.st_dev); + ++chroot_no_tree; + } if (chdir(path) == -1) fatal("Unable to chdir to chroot path \"%s\": " "%s", path, strerror(errno)); if (chroot(path) == -1) fatal("chroot(\"%s\"): %s", path, strerror(errno)); if (chdir("/") == -1) fatal("%s: chdir(/) after chroot: %s", diff --git a/openssh-7.2p2/sftp-chrootenv.h b/openssh-7.2p2/sftp-chrootenv.h new file mode 100644 --- /dev/null +++ b/openssh-7.2p2/sftp-chrootenv.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2009 Jan F Chadima. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CHROOTENV_H +#define CHROOTENV_H + +extern int chroot_no_tree; + +#endif + diff --git a/openssh-7.2p2/sftp-common.c b/openssh-7.2p2/sftp-common.c --- a/openssh-7.2p2/sftp-common.c +++ b/openssh-7.2p2/sftp-common.c @@ -43,16 +43,17 @@ #include "xmalloc.h" #include "ssherr.h" #include "sshbuf.h" #include "log.h" #include "sftp.h" #include "sftp-common.h" +#include "sftp-chrootenv.h" /* Clear contents of attributes structure */ void attrib_clear(Attrib *a) { a->flags = 0; a->size = 0; a->uid = 0; @@ -216,23 +217,23 @@ ls_file(const char *name, const struct s int ulen, glen, sz = 0; struct tm *ltime = localtime(&st->st_mtime); char *user, *group; char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1]; char sbuf[FMT_SCALED_STRSIZE]; time_t now; strmode(st->st_mode, mode); - if (!remote) { + if (!remote && !chroot_no_tree) { user = user_from_uid(st->st_uid, 0); } else { snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); user = ubuf; } - if (!remote) { + if (!remote && !chroot_no_tree) { group = group_from_gid(st->st_gid, 0); } else { snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); group = gbuf; } if (ltime != NULL) { now = time(NULL); if (now - (365*24*60*60)/2 < st->st_mtime && diff --git a/openssh-7.2p2/sftp-server-main.c b/openssh-7.2p2/sftp-server-main.c --- a/openssh-7.2p2/sftp-server-main.c +++ b/openssh-7.2p2/sftp-server-main.c @@ -17,22 +17,25 @@ #include "includes.h" #include <sys/types.h> #include <pwd.h> #include <stdarg.h> #include <stdio.h> #include <unistd.h> +//#include <time.h> #include "log.h" #include "sftp.h" #include "misc.h" #include "xmalloc.h" +int chroot_no_tree = 0; + void cleanup_exit(int i) { sftp_server_cleanup_exit(i); } int main(int argc, char **argv) diff --git a/openssh-7.2p2/sftp.c b/openssh-7.2p2/sftp.c --- a/openssh-7.2p2/sftp.c +++ b/openssh-7.2p2/sftp.c @@ -112,16 +112,18 @@ struct complete_ctx { char **remote_pathp; }; int remote_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ extern char *__progname; +int chroot_no_tree = 0; + /* Separators for interactive commands */ #define WHITESPACE " \t\r\n" /* ls flags */ #define LS_LONG_VIEW 0x0001 /* Full view ala ls -l */ #define LS_SHORT_VIEW 0x0002 /* Single row view ala ls -1 */ #define LS_NUMERIC_VIEW 0x0004 /* Long view with numeric uid/gid */ #define LS_NAME_SORT 0x0008 /* Sort by name (default) */ diff --git a/openssh-7.2p2/sshd_config.0 b/openssh-7.2p2/sshd_config.0 --- a/openssh-7.2p2/sshd_config.0 +++ b/openssh-7.2p2/sshd_config.0 @@ -251,16 +251,24 @@ DESCRIPTION directory on some operating systems (see sftp-server(8) for details). For safety, it is very important that the directory hierarchy be prevented from modification by other processes on the system (especially those outside the jail). Misconfiguration can lead to unsafe environments which sshd(8) cannot detect. + In the special case when only sftp is used, not ssh nor scp, it + is possible to use ChrootDirectory %h or ChrootDirectory + /some/path/%u. The file system containing this directory must be + mounted with options nodev and either nosuid or noexec. The owner + of the directory should be the user. The ownership of the other + components of the path must fulfill the usual conditions. No adi- + tional files are required to be present in the directory. + The default is M-bM-^@M-^\noneM-bM-^@M-^], indicating not to chroot(2). Ciphers Specifies the ciphers allowed. Multiple ciphers must be comma- separated. If the specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified ciphers will be appended to the default set instead of replacing them. diff --git a/openssh-7.2p2/sshd_config.5 b/openssh-7.2p2/sshd_config.5 --- a/openssh-7.2p2/sshd_config.5 +++ b/openssh-7.2p2/sshd_config.5 @@ -424,16 +424,27 @@ for details). .Pp For safety, it is very important that the directory hierarchy be prevented from modification by other processes on the system (especially those outside the jail). Misconfiguration can lead to unsafe environments which .Xr sshd 8 cannot detect. .Pp +In the special case when only sftp is used, not ssh nor scp, +it is possible to use +.Cm ChrootDirectory +%h or +.Cm ChrootDirectory +/some/path/%u. The file system containing this directory must be +mounted with options nodev and either nosuid or noexec. The owner of the +directory should be the user. The ownership of the other components of the path +must fulfill the usual conditions. No aditional files are required to be present +in the directory. +.Pp The default is .Dq none , indicating not to .Xr chroot 2 . .It Cm Ciphers Specifies the ciphers allowed. Multiple ciphers must be comma-separated. If the specified value begins with a
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor