Index: /home/eivind/src/crypto//openssh/session.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/session.c,v retrieving revision 1.10 diff -u -r1.10 session.c --- /home/eivind/src/crypto//openssh/session.c 2000/09/10 09:35:38 1.10 +++ /home/eivind/src/crypto//openssh/session.c 2000/10/03 17:35:37 @@ -1526,6 +1526,7 @@ int success = 0; char *subsys = packet_get_string(&len); int i; + char *oldshell; packet_done(); log("subsystem request for %s", subsys); @@ -1533,8 +1534,12 @@ for (i = 0; i < options.num_subsystems; i++) { if(strcmp(subsys, options.subsystem_name[i]) == 0) { debug("subsystem: exec() %s", options.subsystem_command[i]); + oldshell = s->pw->pw_shell; + s->pw->pw_shell = ""; do_exec_no_pty(s, options.subsystem_command[i], s->pw); + s->pw->pw_shell = oldshell; success = 1; + break; } } Index: /home/eivind/src/crypto//openssh/sftp-server.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-server.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 sftp-server.c --- /home/eivind/src/crypto//openssh/sftp-server.c 2000/09/10 08:27:27 1.1.1.1 +++ /home/eivind/src/crypto//openssh/sftp-server.c 2000/10/03 17:55:05 @@ -1002,12 +1002,150 @@ } } +/* + * Check if a user is in the file "fname" + */ +static int +checkuser(fname, pw) + char *fname; + struct passwd *pw; +{ + FILE *fd; + int found = 0; + char *p, line[BUFSIZ]; + char *name = pw->pw_name; + + if ((fd = fopen(fname, "r")) != NULL) { + while (!found && fgets(line, sizeof(line), fd) != NULL) + if ((p = strchr(line, '\n')) != NULL) { + *p = '\0'; + if (line[0] == '#') + continue; + /* + * if first chr is '@', check group membership + */ + if (line[0] == '@') { + int i = 0; + struct group *grp; + + if ((grp = getgrnam(line+1)) == NULL) + continue; + /* + * Check user's default group + */ + if (grp->gr_gid == pw->pw_gid) + found = 1; + /* + * Check supplementary groups + */ + while (!found && grp->gr_mem[i]) + found = strcmp(name, + grp->gr_mem[i++]) + == 0; + } + /* + * Otherwise, just check for username match + */ + else + found = strcmp(line, name) == 0; + } + (void) fclose(fd); + } + return (found); +} + int -main(int ac, char **av) +main(int argc, char **argv) { fd_set rset, wset; - int in, out, max; + int in, out, max, status, pipes[2]; ssize_t len, olen; + char chrootto[MAXPATHLEN+1]; + pid_t pid; + + if (pipe(pipes) != 0) + return 1; + /* + * Cannot portably be vfork() due to + * (1) Possibility of blocking on the pipe. + * (2) Re-use of the info buffer above. + */ + pid = fork(); + if (pid < 0) + return 1; + if (pid == 0) { + char *username; + struct passwd *pw; + + /* Lose privileges */ + if (setuid(getuid()) != 0) + _exit(1); + /* Close read end of pipe */ + if (close(pipes[0]) != 0) + _exit(1); + username = getenv("USER"); + if (username == NULL) { + log("No $USER set for sftp-server"); + _exit(1); + } + pw = getpwnam(username); + if (pw == NULL) { + log("User %s does not exist", + username); + _exit(1); + } + if (pw->pw_uid != getuid()) { + log("User %s does not match uid %d", + username, getuid()); + _exit(1); + } + if (checkuser(_PATH_FTPUSERS, pw)) { + log("User %s is in /etc/ftpusers", + username); + _exit(1); + } + if (checkuser("/etc/ftpchroot", pw)) { + strncpy(chrootto, pw->pw_dir, sizeof(chrootto)); + if (chrootto[sizeof(chrootto) - 1]) { + chrootto[sizeof(chrootto) - 1] = '\0'; + if (strlen(chrootto) == sizeof(chrootto)-1) { + log("User %s - too long homedir name", + username); + _exit(1); + } + } + } else + chrootto[0] = '\0'; + if (write(pipes[1], chrootto, sizeof(chrootto)) != + sizeof(chrootto)) { + log("Can't communicate sftp-server chroot info"); + _exit(1); + } + _exit(0); + } + /* Close write end of pipe */ + if (close(pipes[1]) != 0) + return 1; + + /* Get information from child */ + if (read(pipes[0], chrootto, sizeof(chrootto)) != + sizeof(chrootto)) + return 1; + waitpid(pid, &status, 0); + if (!WIFEXITED(status) || + WEXITSTATUS(status) != 0) + return 1; + if (close(pipes[0]) != 0) + return 1; + /* Child ran OK */ + if (chrootto[0]) + if (seteuid(getuid()) != 0 || + chdir(chrootto) != 0 || + seteuid(0) != 0 || + chroot(".") != 0) + return 1; + if (setuid(getuid()) != 0) + return 1; handle_init();