-/* $OpenBSD: session.c,v 1.241 2008/06/16 13:22:53 dtucker Exp $ */
+/* $OpenBSD: session.c,v 1.246 2009/04/17 19:23:06 stevesk Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
#include <kafs.h>
#endif
+#define IS_INTERNAL_SFTP(c) \
+ (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
+ (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
+ c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \
+ c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t'))
+
/* func */
Session *session_new(void);
static int session_pty_req(Session *);
+#ifdef SESSION_HOOKS
+static void execute_session_hook(char* prog, Authctxt *authctxt,
+ int startup, int save);
+#endif
+
/* import */
extern ServerOptions options;
extern char *__progname;
}
/* Allocate a channel for the authentication agent socket. */
+ /* this shouldn't matter if its hpn or not - cjr */
nc = channel_new("auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, "auth socket", 1);
- strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
+ nc->path = xstrdup(auth_sock_name);
return 1;
authsock_err:
else
do_authenticated1(authctxt);
+#ifdef SESSION_HOOKS
+ if (options.session_hooks_allow &&
+ options.session_hooks_shutdown_cmd)
+ {
+ execute_session_hook(options.session_hooks_shutdown_cmd,
+ authctxt,
+ /* startup = */ 0, /* save = */ 0);
+
+ if (authctxt->session_env_file)
+ {
+ free(authctxt->session_env_file);
+ }
+ }
+#endif
+
do_cleanup(authctxt);
}
}
debug("Received TCP/IP port forwarding request.");
if (channel_input_port_forward_request(s->pw->pw_uid == 0,
- options.gateway_ports) < 0) {
+ options.gateway_ports) < 0) {
debug("Port forwarding failed.");
break;
}
signal(WJSIGNAL, cray_job_termination_handler);
#endif /* _UNICOS */
#ifdef HAVE_CYGWIN
- if (is_winnt)
- cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
+ cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
s->pid = pid;
* Do common processing for the child, such as execing
* the command.
*/
- do_child(s, command);
- /* NOTREACHED */
+ do_child(s, command);
+ /* NOTREACHED */
default:
break;
}
signal(WJSIGNAL, cray_job_termination_handler);
#endif /* _UNICOS */
#ifdef HAVE_CYGWIN
- if (is_winnt)
- cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
+ cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
s->pid = pid;
if (options.adm_forced_command) {
original_command = command;
command = options.adm_forced_command;
- if (strcmp(INTERNAL_SFTP_NAME, command) == 0)
+ if (IS_INTERNAL_SFTP(command))
s->is_subsystem = SUBSYSTEM_INT_SFTP;
else if (s->is_subsystem)
s->is_subsystem = SUBSYSTEM_EXT;
} else if (forced_command) {
original_command = command;
command = forced_command;
- if (strcmp(INTERNAL_SFTP_NAME, command) == 0)
+ if (IS_INTERNAL_SFTP(command))
s->is_subsystem = SUBSYSTEM_INT_SFTP;
else if (s->is_subsystem)
s->is_subsystem = SUBSYSTEM_EXT;
debug("Forced command (key option) '%.900s'", command);
}
+#if defined(SESSION_HOOKS)
+ if (options.session_hooks_allow &&
+ (options.session_hooks_startup_cmd ||
+ options.session_hooks_shutdown_cmd))
+ {
+ char env_file[1000];
+ struct stat st;
+ do
+ {
+ snprintf(env_file,
+ sizeof(env_file),
+ "/tmp/ssh_env_%d%d%d",
+ getuid(),
+ getpid(),
+ rand());
+ } while (stat(env_file, &st)==0);
+ s->authctxt->session_env_file = strdup(env_file);
+ }
+#endif
+
#ifdef SSH_AUDIT_EVENTS
if (command != NULL)
PRIVSEP(audit_run_command(command));
fromlen = sizeof(from);
if (packet_connection_is_on_socket()) {
if (getpeername(packet_get_connection_in(),
- (struct sockaddr *) & from, &fromlen) < 0) {
+ (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
cleanup_exit(255);
}
/*
* Sets the value of the given variable in the environment. If the variable
- * already exists, its value is overriden.
+ * already exists, its value is overridden.
*/
void
child_set_env(char ***envp, u_int *envsizep, const char *name,
fclose(f);
}
+#ifdef SESSION_HOOKS
+#define SSH_SESSION_ENV_FILE "SSH_SESSION_ENV_FILE"
+
+typedef enum { no_op, execute, clear_env, restore_env,
+ read_env, save_or_rm_env } session_action_t;
+
+static session_action_t action_order[2][5] = {
+ { clear_env, read_env, execute, save_or_rm_env, restore_env }, /*shutdown*/
+ { execute, read_env, save_or_rm_env, no_op, no_op } /*startup */
+};
+
+static
+void execute_session_hook(char* prog, Authctxt *authctxt,
+ int startup, int save)
+{
+ extern char **environ;
+
+ struct stat st;
+ char **saved_env, **tmpenv;
+ char *env_file = authctxt->session_env_file;
+ int i, status = 0;
+
+ for (i=0; i<5; i++)
+ {
+ switch (action_order[startup][i])
+ {
+ case no_op:
+ break;
+
+ case execute:
+ {
+ FILE* fp;
+ char buf[1000];
+
+ snprintf(buf,
+ sizeof(buf),
+ "%s -c '%s'",
+ authctxt->pw->pw_shell,
+ prog);
+
+ debug("executing session hook: [%s]", buf);
+ setenv(SSH_SESSION_ENV_FILE, env_file, /* overwrite = */ 1);
+
+ /* flusing is recommended in the popen(3) man page, to avoid
+ intermingling of output */
+ fflush(stdout);
+ fflush(stderr);
+ if ((fp=popen(buf, "w")) == NULL)
+ {
+ perror("Unable to run session hook");
+ return;
+ }
+ status = pclose(fp);
+ debug2("session hook executed, status=%d", status);
+ unsetenv(SSH_SESSION_ENV_FILE);
+ }
+ break;
+
+ case clear_env:
+ saved_env = environ;
+ tmpenv = (char**) malloc(sizeof(char*));
+ tmpenv[0] = NULL;
+ environ = tmpenv;
+ break;
+
+ case restore_env:
+ environ = saved_env;
+ free(tmpenv);
+ break;
+
+ case read_env:
+ if (status==0 && stat(env_file, &st)==0)
+ {
+ int envsize = 0;
+
+ debug("reading environment from %s", env_file);
+ while (environ[envsize++]) ;
+ read_environment_file(&environ, &envsize, env_file);
+ }
+ break;
+
+ case save_or_rm_env:
+ if (status==0 && save)
+ {
+ FILE* fp;
+ int envcount=0;
+
+ debug2("saving environment to %s", env_file);
+ if ((fp = fopen(env_file, "w")) == NULL) /* hmm: file perms? */
+ {
+ perror("Unable to save session hook info");
+ }
+ while (environ[envcount])
+ {
+ fprintf(fp, "%s\n", environ[envcount++]);
+ }
+ fflush(fp);
+ fclose(fp);
+ }
+ else if (stat(env_file, &st)==0)
+ {
+ debug2("removing environment file %s", env_file);
+ remove(env_file);
+ }
+ break;
+ }
+ }
+
+}
+#endif
+
#ifdef HAVE_ETC_DEFAULT_LOGIN
/*
* Return named variable from specified environment, or NULL if not present.
u_int i, envsize;
char **env, *laddr;
struct passwd *pw = s->pw;
-#ifndef HAVE_LOGIN_CAP
+#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
char *path = NULL;
#endif
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+#ifdef GSI /* GSI shared libs typically installed in non-system locations. */
+ {
+ char *cp;
+
+ if ((cp = getenv("LD_LIBRARY_PATH")) != NULL)
+ child_set_env(&env, &envsize, "LD_LIBRARY_PATH", cp);
+ if ((cp = getenv("LIBPATH")) != NULL)
+ child_set_env(&env, &envsize, "LIBPATH", cp);
+ if ((cp = getenv("SHLIB_PATH")) != NULL)
+ child_set_env(&env, &envsize, "SHLIB_PATH", cp);
+ if ((cp = getenv("LD_LIBRARYN32_PATH")) != NULL)
+ child_set_env(&env, &envsize, "LD_LIBRARYN32_PATH",cp);
+ if ((cp = getenv("LD_LIBRARY64_PATH")) != NULL)
+ child_set_env(&env, &envsize, "LD_LIBRARY64_PATH",cp);
+ }
+#endif
+
/* Set custom environment options from RSA authentication. */
if (!options.use_login) {
while (custom_environment) {
if (getuid() == 0 || geteuid() == 0)
#endif /* HAVE_CYGWIN */
{
-
-#ifdef HAVE_SETPCRED
- if (setpcred(pw->pw_name, (char **)NULL) == -1)
- fatal("Failed to set process credentials");
-#endif /* HAVE_SETPCRED */
#ifdef HAVE_LOGIN_CAP
# ifdef __bsdi__
setpgid(0, 0);
free(chroot_path);
}
+#ifdef HAVE_SETPCRED
+ if (setpcred(pw->pw_name, (char **)NULL) == -1)
+ fatal("Failed to set process credentials");
+#endif /* HAVE_SETPCRED */
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
perror("unable to set user context (setuser)");
#endif
}
-#ifdef HAVE_CYGWIN
- if (is_winnt)
-#endif
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
struct passwd *pw = s->pw;
int r = 0;
+#ifdef AFS_KRB5
+/* Default place to look for aklog. */
+#ifdef AKLOG_PATH
+#define KPROGDIR AKLOG_PATH
+#else
+#define KPROGDIR "/usr/bin/aklog"
+#endif /* AKLOG_PATH */
+
+ struct stat st;
+ char *aklog_path;
+#endif /* AFS_KRB5 */
+
/* remove hostkey from the child's memory */
destroy_sensitive_data();
}
#endif
+#ifdef AFS_KRB5
+
+ /* User has authenticated, and if a ticket was going to be
+ * passed we would have it. KRB5CCNAME should already be set.
+ * Now try to get an AFS token using aklog.
+ */
+ if (k_hasafs()) { /* Do we have AFS? */
+
+ aklog_path = xstrdup(KPROGDIR);
+
+ /*
+ * Make sure it exists before we try to run it
+ */
+ if (stat(aklog_path, &st) == 0) {
+ debug("Running %s to get afs token.",aklog_path);
+ system(aklog_path);
+ } else {
+ debug("%s does not exist.",aklog_path);
+ }
+
+ xfree(aklog_path);
+ }
+#endif /* AFS_KRB5 */
+
+#ifdef SESSION_HOOKS
+ if (options.session_hooks_allow &&
+ options.session_hooks_startup_cmd)
+ {
+ execute_session_hook(options.session_hooks_startup_cmd,
+ s->authctxt,
+ /* startup = */ 1,
+ options.session_hooks_shutdown_cmd != NULL);
+ }
+#endif
+
/* Change current directory to the user's home directory. */
if (chdir(pw->pw_dir) < 0) {
/* Suppress missing homedir warning for chroot case */
int i;
char *p, *args;
- setproctitle("%s@internal-sftp-server", s->pw->pw_name);
- args = strdup(command ? command : "sftp-server");
+ setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME);
+ args = xstrdup(command ? command : "sftp-server");
for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
if (i < ARGV_MAX - 1)
argv[i++] = p;
/* Execute the shell. */
argv[0] = argv0;
argv[1] = NULL;
- execve(shell, argv, env);
+ execve(shell, argv, environ);
/* Executing the shell failed. */
perror(shell);
argv[1] = "-c";
argv[2] = (char *) command;
argv[3] = NULL;
- execve(shell, argv, env);
+ execve(shell, argv, environ);
perror(shell);
exit(1);
}
*/
if (s->chanid == -1)
fatal("no channel for session %d", s->self);
+ if (options.hpn_disabled)
channel_set_fds(s->chanid,
fdout, fdin, fderr,
fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1, is_tty, CHAN_SES_WINDOW_DEFAULT);
+ else
+ channel_set_fds(s->chanid,
+ fdout, fdin, fderr,
+ fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+ 1, is_tty, options.hpn_buffer_size);
}
/*