X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/91d9cdd3ca06d1809bc05a285dafdea2954850b2..352b92931a9b3d49170acfe3e7758f6f6a27f1bb:/openssh/session.c diff --git a/openssh/session.c b/openssh/session.c index f2549e0..52a8a0b 100644 --- a/openssh/session.c +++ b/openssh/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.245 2009/01/22 09:46:01 djm Exp $ */ +/* $OpenBSD: session.c,v 1.246 2009/04/17 19:23:06 stevesk Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -124,6 +124,11 @@ static void do_authenticated2(Authctxt *); 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; @@ -230,6 +235,7 @@ auth_input_request_forwarding(struct passwd * pw) } /* 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, @@ -275,6 +281,21 @@ do_authenticated(Authctxt *authctxt) 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); } @@ -381,7 +402,7 @@ do_authenticated1(Authctxt *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; } @@ -571,8 +592,7 @@ do_exec_no_pty(Session *s, const char *command) 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; @@ -716,8 +736,8 @@ do_exec_pty(Session *s, const char *command) * Do common processing for the child, such as execing * the command. */ - do_child(s, command); - /* NOTREACHED */ + do_child(s, command); + /* NOTREACHED */ default: break; } @@ -726,8 +746,7 @@ do_exec_pty(Session *s, const char *command) 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; @@ -802,6 +821,26 @@ do_exec(Session *s, const char *command) 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)); @@ -847,7 +886,7 @@ do_login(Session *s, const char *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); } @@ -1030,6 +1069,117 @@ read_environment_file(char ***env, u_int *envsize, 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. @@ -1116,7 +1266,7 @@ do_setup_env(Session *s, const char *shell) 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 @@ -1193,6 +1343,23 @@ do_setup_env(Session *s, const char *shell) 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) { @@ -1468,11 +1635,6 @@ do_setusercontext(struct passwd *pw) 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); @@ -1540,6 +1702,10 @@ do_setusercontext(struct passwd *pw) 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)"); @@ -1551,9 +1717,6 @@ do_setusercontext(struct passwd *pw) #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); @@ -1655,6 +1818,18 @@ do_child(Session *s, const char *command) 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(); @@ -1767,6 +1942,41 @@ do_child(Session *s, const char *command) } #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 */ @@ -1794,7 +2004,7 @@ do_child(Session *s, const char *command) int i; char *p, *args; - setproctitle("%s@internal-sftp-server", s->pw->pw_name); + 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) @@ -1837,7 +2047,7 @@ do_child(Session *s, const char *command) /* Execute the shell. */ argv[0] = argv0; argv[1] = NULL; - execve(shell, argv, env); + execve(shell, argv, environ); /* Executing the shell failed. */ perror(shell); @@ -1851,7 +2061,7 @@ do_child(Session *s, const char *command) argv[1] = "-c"; argv[2] = (char *) command; argv[3] = NULL; - execve(shell, argv, env); + execve(shell, argv, environ); perror(shell); exit(1); } @@ -2301,10 +2511,16 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr, int is_tty) */ 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); } /*