]> andersk Git - openssh.git/blobdiff - session.c
[NOTE: Next patch will sync nchan.c, channels.c and channels.h and all this
[openssh.git] / session.c
index ac026e4fdb7e83b3c695c34260b5242dd378adb0..0625bf81f10d2ca25d27aa629fc44a913845825f 100644 (file)
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.69 2001/03/25 13:16:11 stevesk Exp $");
+RCSID("$OpenBSD: session.c,v 1.78 2001/05/31 10:30:16 markus Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -46,7 +46,6 @@ RCSID("$OpenBSD: session.c,v 1.69 2001/03/25 13:16:11 stevesk Exp $");
 #include "uidswap.h"
 #include "compat.h"
 #include "channels.h"
-#include "nchan.h"
 #include "bufaux.h"
 #include "auth.h"
 #include "auth-options.h"
@@ -127,7 +126,12 @@ void       session_proctitle(Session *s);
 void   do_exec_pty(Session *s, const char *command);
 void   do_exec_no_pty(Session *s, const char *command);
 void   do_login(Session *s, const char *command);
+#ifdef LOGIN_NEEDS_UTMPX
+void   do_pre_login(Session *s);
+#endif
 void   do_child(Session *s, const char *command);
+void   do_motd(void);
+int    check_quietlogin(Session *s, const char *command);
 
 void   do_authenticated1(Authctxt *authctxt);
 void   do_authenticated2(Authctxt *authctxt);
@@ -138,8 +142,8 @@ extern char *__progname;
 extern int log_stderr;
 extern int debug_flag;
 extern u_int utmp_len;
-
 extern int startup_pipe;
+extern void destroy_sensitive_data(void);
 
 /* Local Xauthority file. */
 static char *xauthfile;
@@ -177,6 +181,12 @@ do_authenticated(Authctxt *authctxt)
                error("unable to get login class");
                return;
        }
+#ifdef BSD_AUTH
+       if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) {
+               packet_disconnect("Approval failure for %s",
+                   authctxt->pw->pw_name);
+       }
+#endif
 #endif
        /* setup the channel layer */
        if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
@@ -244,6 +254,7 @@ do_authenticated1(Authctxt *authctxt)
        int success, type, fd, n_bytes, plen, screen_flag, have_pty = 0;
        int compression_level = 0, enable_compression_after_reply = 0;
        u_int proto_len, data_len, dlen;
+       struct stat st;
 
        s = session_new();
        s->pw = authctxt->pw;
@@ -326,7 +337,8 @@ do_authenticated1(Authctxt *authctxt)
                                packet_send_debug("X11 forwarding disabled in server configuration file.");
                                break;
                        }
-                       if (!options.xauth_location) {
+                       if (!options.xauth_location ||
+                           (stat(options.xauth_location, &st) == -1)) {
                                packet_send_debug("No xauth program; cannot forward with spoofing.");
                                break;
                        }
@@ -365,7 +377,7 @@ do_authenticated1(Authctxt *authctxt)
                        /* Setup to always have a local .Xauthority. */
                        xauthfile = xmalloc(MAXPATHLEN);
                        strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
-                       temporarily_use_uid(s->pw->pw_uid);
+                       temporarily_use_uid(s->pw);
                        if (mkdtemp(xauthfile) == NULL) {
                                restore_uid();
                                error("private X11 dir: mkdtemp %s failed: %s",
@@ -633,8 +645,14 @@ do_exec_pty(Session *s, const char *command)
                close(ttyfd);
 
                /* record login, etc. similar to login(1) */
+#ifndef HAVE_OSF_SIA
                if (!(options.use_login && command == NULL))
                        do_login(s, command);
+# ifdef LOGIN_NEEDS_UTMPX
+               else
+                       do_pre_login(s);
+# endif
+#endif
 
                /* Do common processing for the child, such as execing the command. */
                do_child(s, command);
@@ -677,28 +695,42 @@ do_exec_pty(Session *s, const char *command)
        }
 }
 
-const char *
-get_remote_name_or_ip(void)
+#ifdef LOGIN_NEEDS_UTMPX
+void
+do_pre_login(Session *s)
 {
-       static const char *remote = "";
-       if (utmp_len > 0)
-               remote = get_canonical_hostname(options.reverse_mapping_check);
-       if (utmp_len == 0 || strlen(remote) > utmp_len)
-               remote = get_remote_ipaddr();
-       return remote;
+       socklen_t fromlen;
+       struct sockaddr_storage from;
+       pid_t pid = getpid();
+
+       /*
+        * Get IP address of client. If the connection is not a socket, let
+        * the address be 0.0.0.0.
+        */
+       memset(&from, 0, sizeof(from));
+       if (packet_connection_is_on_socket()) {
+               fromlen = sizeof(from);
+               if (getpeername(packet_get_connection_in(),
+                    (struct sockaddr *) & from, &fromlen) < 0) {
+                       debug("getpeername: %.100s", strerror(errno));
+                       fatal_cleanup();
+               }
+       }
+
+       record_utmp_only(pid, s->tty, s->pw->pw_name,
+           get_remote_name_or_ip(utmp_len, options.reverse_mapping_check),
+           (struct sockaddr *)&from);
 }
+#endif
 
 /* administrative, login(1)-like work */
 void
 do_login(Session *s, const char *command)
 {
-       FILE *f;
        char *time_string;
-       char buf[256];
        char hostname[MAXHOSTNAMELEN];
        socklen_t fromlen;
        struct sockaddr_storage from;
-       struct stat st;
        time_t last_login_time;
        struct passwd * pw = s->pw;
        pid_t pid = getpid();
@@ -726,7 +758,8 @@ do_login(Session *s, const char *command)
 
        /* Record that there was a login on that tty from the remote host. */
        record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
-           get_remote_name_or_ip(), (struct sockaddr *)&from);
+           get_remote_name_or_ip(utmp_len, options.reverse_mapping_check),
+           (struct sockaddr *)&from);
 
 #ifdef USE_PAM
        /*
@@ -739,15 +772,7 @@ do_login(Session *s, const char *command)
        }
 #endif
 
-       /* Done if .hushlogin exists or a command given. */
-       if (command != NULL)
-               return;
-       snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
-#ifdef HAVE_LOGIN_CAP
-       if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
-#else
-       if (stat(buf, &st) >= 0)
-#endif
+       if (check_quietlogin(s, command))
                return;
 
 #ifdef USE_PAM
@@ -768,6 +793,19 @@ do_login(Session *s, const char *command)
                else
                        printf("Last login: %s from %s\r\n", time_string, hostname);
        }
+
+       do_motd();
+}
+
+/*
+ * Display the message of the day.
+ */
+void
+do_motd(void)
+{
+       FILE *f;
+       char buf[256];
+
        if (options.print_motd) {
 #ifdef HAVE_LOGIN_CAP
                f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
@@ -783,6 +821,31 @@ do_login(Session *s, const char *command)
        }
 }
 
+
+/*
+ * Check for quiet login, either .hushlogin or command given.
+ */
+int
+check_quietlogin(Session *s, const char *command)
+{
+       char buf[256];
+       struct passwd * pw = s->pw;
+       struct stat st;
+
+       /* Return 1 if .hushlogin exists or a command given. */
+       if (command != NULL)
+               return 1;
+       snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
+#ifdef HAVE_LOGIN_CAP
+       if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
+               return 1;
+#else
+       if (stat(buf, &st) >= 0)
+               return 1;
+#endif
+       return 0;
+}
+
 /*
  * Sets the value of the given variable in the environment.  If the variable
  * already exists, its value is overriden.
@@ -1029,11 +1092,14 @@ do_child(Session *s, const char *command)
 #endif /* WITH_IRIX_ARRAY */
 #endif /* WITH_IRIX_JOBS */
 
+       /* remove hostkey from the child's memory */
+       destroy_sensitive_data();
+
        /* login(1) is only called if we execute the login shell */
        if (options.use_login && command != NULL)
                options.use_login = 0;
 
-#ifndef USE_PAM /* pam_nologin handles this */
+#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
        if (!options.use_login) {
 # ifdef HAVE_LOGIN_CAP
                if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
@@ -1051,7 +1117,7 @@ do_child(Session *s, const char *command)
                        exit(254);
                }
        }
-#endif /* USE_PAM */
+#endif /* USE_PAM || HAVE_OSF_SIA */
 
        /* Set login name, uid, gid, and groups. */
        /* Login(1) does this as well, and it needs uid 0 for the "-h"
@@ -1059,6 +1125,8 @@ do_child(Session *s, const char *command)
        if (!options.use_login) {
 #ifdef HAVE_OSF_SIA
                session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty);
+               if (!check_quietlogin(s, command))
+                       do_motd();
 #else /* HAVE_OSF_SIA */
 #ifdef HAVE_CYGWIN
                if (is_winnt) {
@@ -1074,13 +1142,6 @@ do_child(Session *s, const char *command)
                                perror("unable to set user context");
                                exit(1);
                        }
-#ifdef BSD_AUTH
-                       if (auth_approval(NULL, lc, pw->pw_name, "ssh") <= 0) {
-                               error("approval failure for %s", pw->pw_name);
-                               fprintf(stderr, "Approval failure");
-                               exit(1);
-                       }
-#endif
 # else /* HAVE_LOGIN_CAP */
 #if defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
                        /* Sets login uid for accounting */
@@ -1162,7 +1223,7 @@ do_child(Session *s, const char *command)
 #endif
 
                        /* Permanently switch to the desired uid. */
-                       permanently_set_uid(pw->pw_uid);
+                       permanently_set_uid(pw);
 # endif /* HAVE_LOGIN_CAP */
                }
 #endif /* HAVE_OSF_SIA */
@@ -1308,7 +1369,8 @@ do_child(Session *s, const char *command)
        }
        /* we have to stash the hostname before we close our socket. */
        if (options.use_login)
-               hostname = get_remote_name_or_ip();
+               hostname = get_remote_name_or_ip(utmp_len,
+                   options.reverse_mapping_check);
        /*
         * Close the connection descriptors; note that this is the child, and
         * the server will still have the socket open, and it is important
@@ -1365,24 +1427,25 @@ do_child(Session *s, const char *command)
         * in this order).
         */
        if (!options.use_login) {
-               if (stat(_PATH_SSH_USER_RC, &st) >= 0) {
+               /* ignore _PATH_SSH_USER_RC for subsystems */
+               if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
+                       snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
+                           shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
                        if (debug_flag)
-                               fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
-                                   _PATH_SSH_USER_RC);
-                       f = popen(_PATH_BSHELL " " _PATH_SSH_USER_RC, "w");
+                               fprintf(stderr, "Running %s\n", cmd);
+                       f = popen(cmd, "w");
                        if (f) {
                                if (do_xauth)
                                        fprintf(f, "%s %s\n", s->auth_proto,
                                            s->auth_data);
                                pclose(f);
                        } else
-                               fprintf(stderr, "Could not run %s\n", 
+                               fprintf(stderr, "Could not run %s\n",
                                    _PATH_SSH_USER_RC);
                } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
                        if (debug_flag)
                                fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
                                    _PATH_SSH_SYSTEM_RC);
-
                        f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
                        if (f) {
                                if (do_xauth)
@@ -1484,6 +1547,9 @@ do_child(Session *s, const char *command)
                        /* Launch login(1). */
 
                        execl(LOGIN_PROGRAM, "login", "-h", hostname,
+#ifdef LOGIN_NEEDS_TERM
+                            s->term? s->term : "unknown",
+#endif
                             "-p", "-f", "--", pw->pw_name, NULL);
 
                        /* Login couldn't be executed, die. */
@@ -1612,7 +1678,7 @@ int
 session_pty_req(Session *s)
 {
        u_int len;
-       char *term_modes;       /* encoded terminal modes */
+       int n_bytes;
 
        if (no_pty_flag)
                return 0;
@@ -1623,8 +1689,6 @@ session_pty_req(Session *s)
        s->row = packet_get_int();
        s->xpixel = packet_get_int();
        s->ypixel = packet_get_int();
-       term_modes = packet_get_string(&len);
-       packet_done();
 
        if (strcmp(s->term, "") == 0) {
                xfree(s->term);
@@ -1637,7 +1701,6 @@ session_pty_req(Session *s)
                s->ptyfd = -1;
                s->ttyfd = -1;
                error("session_pty_req: session %d alloc failed", s->self);
-               xfree(term_modes);
                return 0;
        }
        debug("session_pty_req: session %d alloc %s", s->self, s->tty);
@@ -1650,10 +1713,12 @@ session_pty_req(Session *s)
        /* Get window size from the packet. */
        pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
 
+       /* Get tty modes from the packet. */
+       tty_parse_modes(s->ttyfd, &n_bytes);
+       packet_done();
+
        session_proctitle(s);
 
-       /* XXX parse and set terminal modes */
-       xfree(term_modes);
        return 1;
 }
 
@@ -1688,6 +1753,7 @@ int
 session_x11_req(Session *s)
 {
        int fd;
+       struct stat st;
        if (no_x11_forwarding_flag) {
                debug("X11 forwarding disabled in user configuration file.");
                return 0;
@@ -1696,6 +1762,11 @@ session_x11_req(Session *s)
                debug("X11 forwarding disabled in server configuration file.");
                return 0;
        }
+       if (!options.xauth_location ||
+           (stat(options.xauth_location, &st) == -1)) {
+               packet_send_debug("No xauth program; cannot forward with spoofing.");
+               return 0;
+       }
        if (xauthfile != NULL) {
                debug("X11 fwd already started.");
                return 0;
@@ -1719,7 +1790,7 @@ session_x11_req(Session *s)
        }
        xauthfile = xmalloc(MAXPATHLEN);
        strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
-       temporarily_use_uid(s->pw->pw_uid);
+       temporarily_use_uid(s->pw);
        if (mkdtemp(xauthfile) == NULL) {
                restore_uid();
                error("private X11 dir: mkdtemp %s failed: %s",
This page took 0.12741 seconds and 4 git commands to generate.