Hi Cygwin Developers,

In the source code for the session.c Cygwin is using the standard OpenSSH 
source code, which checks for both the user ID of 0 and a permissions for who 
can write to the new folder.
Chroot mounting test that I can't get Cygwin to pass
if (st.st_uid != 0 || (st.st_mode & 022) != 0)

I have tried mapping the SYSTEM user and Group via the \etc\passwd and 
\etc\group files, but I am unable to get a successful setting that will allow 
Chroot.exe or \etc\sshd_config directive for rehoming an SFTP connection to 
work.

Match User username
  ChrootDirectory F:\sftproot
  ForceCommand internal-sftp
In the MS OpenSSH source code, they have switched Windows to just doing a basic 
directory exists check. Would it be possible to implement the same check in the 
Cygwin source code so that sftp root rehoming works again? I believe it was 
broken after OpenSSH 8.6 from my research, I have an older Cygwin setup based 
on OpenSSH 8.3 and the Chroot directive for SFTP root rehoming works fine.
session.c source code

/*
 * 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;

      if (!path_absolute(path))
            fatal("chroot path does not begin at root");
      if (strlen(path) >= sizeof(component))
            fatal("chroot path too long");

#ifdef WINDOWS
      /* ensure chroot path exists and is a directory */
      if (stat(path, &st) != 0)
            fatal("%s: stat(\"%s\"): %s", __func__,
                  path, strerror(errno));
      if (!S_ISDIR(st.st_mode))
            fatal("chroot path %s is not a directory",
                  path);
#else
      /*
       * 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)
                  strlcpy(component, path, sizeof(component));
            else {
                  cp++;
                  memcpy(component, path, cp - path);
                  component[cp - path] = '\0';
            }

            debug3_f("checking '%s'", component);

            if (stat(component, &st) != 0)
                  fatal_f("stat(\"%s\"): %s",
                      component, strerror(errno));
            if (st.st_uid != 0 || (st.st_mode & 022) != 0)
                  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);

      }
#endif
      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_f("chdir(/) after chroot: %s", strerror(errno));
      verbose("Changed root directory to \"%s\"", path);
}

Regards,

Peter Board

-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to