*/
#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"
#include "uidswap.h"
#include "compat.h"
#include "channels.h"
-#include "nchan.h"
#include "bufaux.h"
#include "auth.h"
#include "auth-options.h"
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);
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;
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)
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;
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;
}
/* 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",
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);
}
}
-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();
/* 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
/*
}
#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
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",
}
}
+
+/*
+ * 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.
#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)
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"
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) {
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 */
#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 */
}
/* 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
* 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)
/* 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. */
session_pty_req(Session *s)
{
u_int len;
- char *term_modes; /* encoded terminal modes */
+ int n_bytes;
if (no_pty_flag)
return 0;
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);
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);
/* 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;
}
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;
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;
}
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",