version 1.225, 2008/02/04 21:53:00 |
version 1.226, 2008/02/08 23:24:07 |
|
|
#include "sshlogin.h" |
#include "sshlogin.h" |
#include "serverloop.h" |
#include "serverloop.h" |
#include "canohost.h" |
#include "canohost.h" |
|
#include "misc.h" |
#include "session.h" |
#include "session.h" |
#ifdef GSSAPI |
#ifdef GSSAPI |
#include "ssh-gss.h" |
#include "ssh-gss.h" |
|
|
#include <kafs.h> |
#include <kafs.h> |
#endif |
#endif |
|
|
|
/* Magic name for internal sftp-server */ |
|
#define INTERNAL_SFTP_NAME "internal-sftp" |
|
|
/* func */ |
/* func */ |
|
|
Session *session_new(void); |
Session *session_new(void); |
|
|
if (options.adm_forced_command) { |
if (options.adm_forced_command) { |
original_command = command; |
original_command = command; |
command = options.adm_forced_command; |
command = options.adm_forced_command; |
if (s->is_subsystem) |
if (strcmp(INTERNAL_SFTP_NAME, command) == 0) |
|
s->is_subsystem = SUBSYSTEM_INT_SFTP; |
|
else if (s->is_subsystem) |
s->is_subsystem = SUBSYSTEM_EXT; |
s->is_subsystem = SUBSYSTEM_EXT; |
debug("Forced command (config) '%.900s'", command); |
debug("Forced command (config) '%.900s'", command); |
} else if (forced_command) { |
} else if (forced_command) { |
original_command = command; |
original_command = command; |
command = forced_command; |
command = forced_command; |
if (s->is_subsystem) |
if (strcmp(INTERNAL_SFTP_NAME, command) == 0) |
|
s->is_subsystem = SUBSYSTEM_INT_SFTP; |
|
else if (s->is_subsystem) |
s->is_subsystem = SUBSYSTEM_EXT; |
s->is_subsystem = SUBSYSTEM_EXT; |
debug("Forced command (key option) '%.900s'", command); |
debug("Forced command (key option) '%.900s'", command); |
} |
} |
|
|
restore_uid(); |
restore_uid(); |
} |
} |
#endif |
#endif |
|
|
if (s->ttyfd != -1) |
if (s->ttyfd != -1) |
do_exec_pty(s, command); |
do_exec_pty(s, command); |
else |
else |
|
|
} |
} |
} |
} |
|
|
|
/* |
|
* 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[MAXPATHLEN]; |
|
struct stat st; |
|
|
|
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) |
|
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) |
|
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); |
|
|
|
} |
|
|
|
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", |
|
__func__, strerror(errno)); |
|
verbose("Changed root directory to \"%s\"", path); |
|
} |
|
|
/* Set login name, uid, gid, and groups. */ |
/* Set login name, uid, gid, and groups. */ |
void |
void |
do_setusercontext(struct passwd *pw) |
do_setusercontext(struct passwd *pw) |
{ |
{ |
if (getuid() == 0 || geteuid() == 0) { |
if (getuid() == 0 || geteuid() == 0) { |
|
/* Prepare groups */ |
if (setusercontext(lc, pw, pw->pw_uid, |
if (setusercontext(lc, pw, pw->pw_uid, |
(LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { |
(LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { |
perror("unable to set user context"); |
perror("unable to set user context"); |
exit(1); |
exit(1); |
} |
} |
|
|
|
if (options.chroot_directory != NULL && |
|
strcasecmp(options.chroot_directory, "none") != 0) { |
|
char *chroot_path; |
|
|
|
chroot_path = percent_expand(options.chroot_directory, |
|
"h", pw->pw_dir, "u", pw->pw_name, (char *)NULL); |
|
safely_chroot(chroot_path, pw->pw_uid); |
|
free(chroot_path); |
|
} |
|
|
|
/* Set UID */ |
|
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) { |
|
perror("unable to set user context (setuser)"); |
|
exit(1); |
|
} |
} |
} |
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) |
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) |
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); |
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); |
|
|
argv[i] = NULL; |
argv[i] = NULL; |
optind = optreset = 1; |
optind = optreset = 1; |
__progname = argv[0]; |
__progname = argv[0]; |
exit(sftp_server_main(i, argv)); |
exit(sftp_server_main(i, argv, s->pw)); |
} |
} |
|
|
if (options.use_login) { |
if (options.use_login) { |
|
|
if (strcmp(subsys, options.subsystem_name[i]) == 0) { |
if (strcmp(subsys, options.subsystem_name[i]) == 0) { |
prog = options.subsystem_command[i]; |
prog = options.subsystem_command[i]; |
cmd = options.subsystem_args[i]; |
cmd = options.subsystem_args[i]; |
if (!strcmp("internal-sftp", prog)) { |
if (!strcmp(INTERNAL_SFTP_NAME, prog)) { |
s->is_subsystem = SUBSYSTEM_INT_SFTP; |
s->is_subsystem = SUBSYSTEM_INT_SFTP; |
} else if (stat(prog, &st) < 0) { |
} else if (stat(prog, &st) < 0) { |
error("subsystem: cannot stat %s: %s", prog, |
error("subsystem: cannot stat %s: %s", prog, |