]> andersk Git - gssapi-openssh.git/commitdiff
session hook patch from Olle Mulmo: OPENSSH_3_6_1P1_GSSAPI_20030425
authorjbasney <jbasney>
Fri, 25 Apr 2003 18:18:04 +0000 (18:18 +0000)
committerjbasney <jbasney>
Fri, 25 Apr 2003 18:18:04 +0000 (18:18 +0000)
http://www-unix.globus.org/mail_archive/gsi-openssh/2003/04/msg00003.html

openssh/acconfig.h
openssh/auth.h
openssh/configure.ac
openssh/misc.c
openssh/servconf.c
openssh/servconf.h
openssh/session.c
openssh/sshd_config

index b8055754d8928af27d8c3f918277ae6b18bb7bd2..68c393f07fed42eeb4d406ed1d781d6aecd8d890 100644 (file)
 /* Define if you want GSI/Globus authentication support */
 #undef GSI
 
+/* Define this if you want support for startup/shutdown hooks */
+#undef SESSION_HOOKS
+
 /* Define if you want S/Key support */
 #undef SKEY
 
index 8e63132c92df6307a1f0f062237ea17b6278a600..2e351d6d15c92a40f507c97039c15b32af62181b 100644 (file)
@@ -69,6 +69,9 @@ struct Authctxt {
        krb5_ccache      krb5_fwd_ccache;
        krb5_principal   krb5_user;
        char            *krb5_ticket_file;
+#endif
+#ifdef SESSION_HOOKS
+        char            *session_env_file;
 #endif
        void *methoddata;
 };
index 7214d4dff3d7f8a2dc2eb2a0cca3a8eaa0e82e94..a6abd942b84d58d9d7baad49ae52e7015ff483ee 100644 (file)
@@ -2109,6 +2109,11 @@ AC_ARG_WITH(afs,
 )
 LIBS="$LIBS $KLIBS $K5LIBS"
 
+AC_ARG_WITH(session-hooks,
+        [  --with-session-hooks    Enable hooks for executing external commands                                       before/after a session],
+        [ AC_DEFINE(SESSION_HOOKS) ]
+)
+
 # Looking for programs, paths and files
 
 PRIVSEP_PATH=/var/empty
index 620121fdca29f7e2fbf915c764a2e4bfb73e7949..eac6ccd5802fc95e318a54f8e7abd6ed5f6c2f02 100644 (file)
@@ -1,5 +1,3 @@
-/*     $OpenBSD: misc.c,v 1.12 2001/06/26 17:27:24 markus Exp $        */
-
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -25,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: misc.c,v 1.12 2001/06/26 17:27:24 markus Exp $");
+RCSID("$OpenBSD: misc.c,v 1.20 2002/12/13 10:03:15 markus Exp $");
 
 #include "misc.h"
 #include "log.h"
@@ -37,7 +35,7 @@ chop(char *s)
 {
        char *t = s;
        while (*t) {
-               if(*t == '\n' || *t == '\r') {
+               if (*t == '\n' || *t == '\r') {
                        *t = '\0';
                        return s;
                }
@@ -65,9 +63,8 @@ set_nonblock(int fd)
        debug("fd %d setting O_NONBLOCK", fd);
        val |= O_NONBLOCK;
        if (fcntl(fd, F_SETFL, val) == -1)
-               if (errno != ENODEV)
-                       error("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
-                           fd, strerror(errno));
+               debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
+                   fd, strerror(errno));
 }
 
 void
@@ -87,19 +84,43 @@ unset_nonblock(int fd)
        debug("fd %d clearing O_NONBLOCK", fd);
        val &= ~O_NONBLOCK;
        if (fcntl(fd, F_SETFL, val) == -1)
-               if (errno != ENODEV)
-                       error("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
-                           fd, strerror(errno));
+               debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
+                   fd, strerror(errno));
+}
+
+/* disable nagle on socket */
+void
+set_nodelay(int fd)
+{
+       int opt;
+       socklen_t optlen;
+
+       optlen = sizeof opt;
+       if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
+               error("getsockopt TCP_NODELAY: %.100s", strerror(errno));
+               return;
+       }
+       if (opt == 1) {
+               debug2("fd %d is TCP_NODELAY", fd);
+               return;
+       }
+       opt = 1;
+       debug2("fd %d setting TCP_NODELAY", fd);
+       if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
+               error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
 }
 
 /* Characters considered whitespace in strsep calls. */
 #define WHITESPACE " \t\r\n"
 
+/* Characters considered as quotations. */
+#define QUOTES "'\""
+
 /* return next token in configuration line */
 char *
 strdelim(char **s)
 {
-       char *old;
+       char *old, *p, *q;
        int wspace = 0;
 
        if (*s == NULL)
@@ -107,7 +128,22 @@ strdelim(char **s)
 
        old = *s;
 
-       *s = strpbrk(*s, WHITESPACE "=");
+        if ((q=strchr(QUOTES, (int) *old)) && *q)
+        {
+            /* find next quote character, point old to start of quoted
+             * string */
+            for (p = ++old;*p && *p!=*q; p++)
+                 ;
+            
+            /* find start of next token */
+            *s = (*p) ? p + strspn(p + 1, WHITESPACE) + 1 : NULL;
+            
+            /* terminate 'old' token */
+            *p = '\0';
+            return (old);
+        }
+
+        *s = strpbrk(*s, WHITESPACE "=");
        if (*s == NULL)
                return (old);
 
@@ -298,7 +334,7 @@ addargs(arglist *args, char *fmt, ...)
        if (args->list == NULL) {
                args->nalloc = 32;
                args->num = 0;
-       } else if (args->num+2 >= args->nalloc) 
+       } else if (args->num+2 >= args->nalloc)
                args->nalloc *= 2;
 
        args->list = xrealloc(args->list, args->nalloc * sizeof(char *));
index 7aa0c73e9c45bb88260c9252c0843f182d0948a9..12b7b835d63d96cc84027599be5e5e61c931745c 100644 (file)
@@ -101,6 +101,11 @@ initialize_server_options(ServerOptions *options)
 #endif
 #ifdef AFS
        options->afs_token_passing = -1;
+#endif
+#ifdef  SESSION_HOOKS
+        options->session_hooks_allow = -1;
+        options->session_hooks_startup_cmd = NULL;
+        options->session_hooks_shutdown_cmd = NULL;
 #endif
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
@@ -230,6 +235,14 @@ fill_default_server_options(ServerOptions *options)
 #ifdef AFS
        if (options->afs_token_passing == -1)
                options->afs_token_passing = 0;
+#endif
+#ifdef SESSION_HOOKS
+        if (options->session_hooks_allow == -1)
+        {
+            options->session_hooks_allow = 0;
+            options->session_hooks_startup_cmd = NULL;
+            options->session_hooks_shutdown_cmd = NULL;
+        }
 #endif
        if (options->password_authentication == -1)
                options->password_authentication = 1;
@@ -306,6 +319,9 @@ typedef enum {
 #endif
 #ifdef AFS
        sAFSTokenPassing,
+#endif
+#ifdef SESSION_HOOKS
+        sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
 #endif
        sChallengeResponseAuthentication,
        sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
@@ -366,6 +382,11 @@ static struct {
 #ifdef AFS
        { "afstokenpassing", sAFSTokenPassing },
 #endif
+#ifdef SESSION_HOOKS
+        { "allowsessionhooks", sAllowSessionHooks },
+        { "sessionhookstartupcmd", sSessionHookStartupCmd },
+        { "sessionhookshutdowncmd", sSessionHookShutdownCmd },
+#endif        
        { "passwordauthentication", sPasswordAuthentication },
        { "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
        { "challengeresponseauthentication", sChallengeResponseAuthentication },
@@ -707,7 +728,22 @@ parse_flag:
                intptr = &options->afs_token_passing;
                goto parse_flag;
 #endif
-
+#ifdef SESSION_HOOKS
+        case sAllowSessionHooks:
+                intptr = &options->session_hooks_allow;
+                goto parse_flag;
+        case sSessionHookStartupCmd:
+        case sSessionHookShutdownCmd:
+                arg = strdelim(&cp);
+                if (!arg || *arg == '\0')
+                    fatal("%s line %d: empty session hook command",
+                          filename, linenum);
+                if (opcode==sSessionHookStartupCmd)
+                    options->session_hooks_startup_cmd = strdup(arg);
+                else
+                    options->session_hooks_shutdown_cmd = strdup(arg);
+                break;
+#endif                  
        case sPasswordAuthentication:
                intptr = &options->password_authentication;
                goto parse_flag;
index 1c947da6ce03b1794bc5cd83572b62b6e4015d27..98cdda4c7a12db815f5693473ac7bf4fdc8ba2d7 100644 (file)
@@ -97,6 +97,11 @@ typedef struct {
 #endif
 #ifdef AFS
        int     afs_token_passing;      /* If true, permit AFS token passing. */
+#endif
+#ifdef SESSION_HOOKS
+        int     session_hooks_allow;        /* If true, permit user hooks */
+        char*   session_hooks_startup_cmd;  /* cmd to be executed before */
+        char*   session_hooks_shutdown_cmd; /* cmd to be executed after */
 #endif
        int     password_authentication;        /* If true, permit password
                                                 * authentication. */
index e697e0812a1c6232efc75a2db65fb159e8de257b..97c0c0a436a0dc04272773f7b4fa6739b274af62 100644 (file)
@@ -91,6 +91,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;
@@ -229,6 +234,21 @@ do_authenticated(Authctxt *authctxt)
        /* remove agent socket */
        if (auth_sock_name != NULL)
                auth_sock_cleanup_proc(authctxt->pw);
+
+#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
 #ifdef KRB4
        if (options.kerberos_ticket_cleanup)
                krb4_cleanup_proc(authctxt);
@@ -718,6 +738,25 @@ do_pre_login(Session *s)
 void
 do_exec(Session *s, const char *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
        if (forced_command) {
                original_command = command;
                command = forced_command;
@@ -939,6 +978,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
+
 void copy_environment(char **source, char ***env, u_int *envsize)
 {
        char *var_name, *var_val;
@@ -1450,6 +1600,16 @@ do_child(Session *s, const char *command)
        }
 #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
 #ifdef AFS
        /* Try to get AFS tokens for the local cell. */
        if (k_hasafs()) {
index e1a052a169a523c329d7259d4d4021d4d5e566d7..b9dda87b9fa6234734a5d35d52d3e4a3f30c0fc0 100644 (file)
@@ -1,80 +1,98 @@
-#      $OpenBSD: sshd_config,v 1.42 2001/09/20 20:57:51 mouring Exp $
+#      $OpenBSD: sshd_config,v 1.59 2002/09/25 11:17:16 markus Exp $
+
+# This is the sshd server system-wide configuration file.  See
+# sshd_config(5) for more information.
 
 # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
 
-# This is the sshd server system-wide configuration file.  See sshd(8)
-# for more information.
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented.  Uncommented options change a
+# default value.
 
-Port 22
+#Port 22
 #Protocol 2,1
 #ListenAddress 0.0.0.0
 #ListenAddress ::
 
 # HostKey for protocol version 1
-HostKey /etc/ssh_host_key
+#HostKey /etc/ssh/ssh_host_key
 # HostKeys for protocol version 2
-HostKey /etc/ssh_host_rsa_key
-HostKey /etc/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
 
 # Lifetime and size of ephemeral version 1 server key
-KeyRegenerationInterval 3600
-ServerKeyBits 768
+#KeyRegenerationInterval 3600
+#ServerKeyBits 768
 
 # Logging
-SyslogFacility AUTH
-LogLevel INFO
 #obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
 
 # Authentication:
 
-LoginGraceTime 600
-PermitRootLogin yes
-StrictModes yes
+#LoginGraceTime 120
+#PermitRootLogin yes
+#StrictModes yes
 
-RSAAuthentication yes
-PubkeyAuthentication yes
-#AuthorizedKeysFile    %h/.ssh/authorized_keys
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+#AuthorizedKeysFile    .ssh/authorized_keys
 
 # rhosts authentication should not be used
-RhostsAuthentication no
+#RhostsAuthentication no
 # Don't read the user's ~/.rhosts and ~/.shosts files
-IgnoreRhosts yes
-# For this to work you will also need host keys in /etc/ssh_known_hosts
-RhostsRSAAuthentication no
+#IgnoreRhosts yes
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
 # similar for protocol version 2
-HostbasedAuthentication no
-# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
-#IgnoreUserKnownHosts yes
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
 
 # To disable tunneled clear text passwords, change to no here!
-PasswordAuthentication yes
-PermitEmptyPasswords no
-
-# Uncomment to disable s/key passwords 
-#ChallengeResponseAuthentication no
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
 
-# Uncomment to enable PAM keyboard-interactive authentication 
-# Warning: enabling this may bypass the setting of 'PasswordAuthentication'
-#PAMAuthenticationViaKbdInt yes
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
 
-# To change Kerberos options
+# Kerberos options
 #KerberosAuthentication no
 #KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+
 #AFSTokenPassing no
-#KerberosTicketCleanup no
 
-# Kerberos TGT Passing does only work with the AFS kaserver
-#KerberosTgtPassing yes
+# Kerberos TGT Passing only works with the AFS kaserver
+#KerberosTgtPassing no
+
+# Session hooks: if allowed, specify the commands to execute
+#AllowSessionHooks yes
+#SessionHookStartupCmd /bin/true
+#SessionHookShutdownCmd /bin/true
 
-X11Forwarding no
-X11DisplayOffset 10
-PrintMotd yes
-#PrintLastLog no
-KeepAlive yes
+# Set this to 'yes' to enable PAM keyboard-interactive authentication 
+# Warning: enabling this may bypass the setting of 'PasswordAuthentication'
+#PAMAuthenticationViaKbdInt no
+
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#KeepAlive yes
 #UseLogin no
+#UsePrivilegeSeparation yes
+#PermitUserEnvironment no
+#Compression yes
 
-#MaxStartups 10:30:60
-#Banner /etc/issue.net
-#ReverseMappingCheck yes
+#MaxStartups 10
+# no default banner path
+#Banner /some/path
+#VerifyReverseMapping no
 
+# override default of no subsystems
 Subsystem      sftp    /usr/libexec/sftp-server
This page took 0.062992 seconds and 5 git commands to generate.