*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.44 2000/11/14 23:44:19 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.57 2001/02/23 15:37:45 markus Exp $");
-#include "xmalloc.h"
#include "ssh.h"
-#include "pty.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "sshpty.h"
#include "packet.h"
#include "buffer.h"
#include "mpaux.h"
-#include "servconf.h"
#include "uidswap.h"
#include "compat.h"
#include "channels.h"
#include "nchan.h"
-
#include "bufaux.h"
-#include "ssh2.h"
#include "auth.h"
#include "auth-options.h"
+#include "pathnames.h"
+#include "log.h"
+#include "servconf.h"
+#include "sshlogin.h"
+#include "serverloop.h"
+#include "canohost.h"
+#include "session.h"
#ifdef WITH_IRIX_PROJECT
#include <proj.h>
#endif /* WITH_IRIX_PROJECT */
#ifdef WITH_IRIX_JOBS
#include <sys/resource.h>
-#endif
+#endif
#ifdef WITH_IRIX_AUDIT
#include <sat.h>
#endif /* WITH_IRIX_AUDIT */
#include <usersec.h>
#endif
-#ifdef HAVE_OSF_SIA
-# include <sia.h>
-# include <siad.h>
-#endif
-
#ifdef HAVE_CYGWIN
#include <windows.h>
#include <sys/cygwin.h>
# define S_UNOFILE_HARD S_UNOFILE "_hard"
#endif
-#ifdef HAVE_LOGIN_CAP
-#include <login_cap.h>
-#endif
-
/* types */
#define TTYSZ 64
extern char *__progname;
extern int log_stderr;
extern int debug_flag;
-extern unsigned int utmp_len;
+extern u_int utmp_len;
extern int startup_pipe;
static char *xauthfile;
/* original command from peer. */
-char *original_command = NULL;
+char *original_command = NULL;
/* data */
#define MAX_SESSIONS 10
char *command;
int n_bytes;
int plen;
- unsigned int proto_len, data_len, dlen;
+ u_int proto_len, data_len, dlen;
+ int screen_flag;
/*
* Cancel the alarm we set to limit the time taken for
s->auth_proto = packet_get_string(&proto_len);
s->auth_data = packet_get_string(&data_len);
- packet_integrity_check(plen, 4 + proto_len + 4 + data_len + 4, type);
- if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
+ screen_flag = packet_get_protocol_flags() &
+ SSH_PROTOFLAG_SCREEN_NUMBER;
+ debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
+
+ if (packet_remaining() == 4) {
+ if (!screen_flag)
+ debug2("Buggy client: "
+ "X11 screen flag missing");
+ packet_integrity_check(plen,
+ 4 + proto_len + 4 + data_len + 4, type);
s->screen = packet_get_int();
- else
+ } else {
+ packet_integrity_check(plen,
+ 4 + proto_len + 4 + data_len, type);
s->screen = 0;
+ }
s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
if (s->display == NULL)
case SSH_CMSG_EXEC_SHELL:
case SSH_CMSG_EXEC_CMD:
- /* Set interactive/non-interactive mode. */
- packet_set_interactive(have_pty || s->display != NULL,
- options.keepalives);
-
if (type == SSH_CMSG_EXEC_CMD) {
command = packet_get_string(&dlen);
debug("Exec command '%.500s'", command);
if (s == NULL)
fatal("do_exec_no_pty: no session");
- signal(SIGPIPE, SIG_DFL);
-
session_proctitle(s);
-#ifdef USE_PAM
- do_pam_setcred();
+#if defined(USE_PAM)
+ do_pam_setcred();
#endif /* USE_PAM */
/* Fork the child. */
/* Child. Reinitialize the log since the pid has changed. */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
+ signal(SIGPIPE, SIG_DFL);
+
/*
* Create a new session and process group since the 4.4BSD
* setlogin() affects the entire process group.
if (pid < 0)
packet_disconnect("fork failed: %.100s", strerror(errno));
s->pid = pid;
+ /* Set interactive/non-interactive mode. */
+ packet_set_interactive(s->display != NULL);
#ifdef USE_PIPES
/* We are the parent. Close the child sides of the pipes. */
close(pin[0]);
ptyfd = s->ptyfd;
ttyfd = s->ttyfd;
-#ifdef USE_PAM
- do_pam_session(pw->pw_name, s->tty);
- do_pam_setcred();
-#endif /* USE_PAM */
+#if defined(USE_PAM)
+ do_pam_session(pw->pw_name, s->tty);
+ do_pam_setcred();
+#endif
/* Fork the child. */
if ((pid = fork()) == 0) {
/* Child. Reinitialize the log because the pid has changed. */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
+ signal(SIGPIPE, SIG_DFL);
+
/* Close the master side of the pseudo tty. */
close(ptyfd);
s->ptymaster = ptymaster;
/* Enter interactive session. */
+ packet_set_interactive(1);
if (compat20) {
session_set_fds(s, ptyfd, fdout, -1);
} else {
{
static const char *remote = "";
if (utmp_len > 0)
- remote = get_canonical_hostname();
+ remote = get_canonical_hostname(options.reverse_mapping_check);
if (utmp_len == 0 || strlen(remote) > utmp_len)
remote = get_remote_ipaddr();
return remote;
* If password change is needed, do it now.
* This needs to occur before the ~/.hushlogin check.
*/
- if (pam_password_change_required()) {
+ if (is_pam_password_change_required()) {
print_pam_messages();
do_pam_chauthtok();
}
return;
#ifdef USE_PAM
- if (!pam_password_change_required())
+ if (!is_pam_password_change_required())
print_pam_messages();
#endif /* USE_PAM */
#ifdef WITH_AIXAUTHENTICATE
* already exists, its value is overriden.
*/
void
-child_set_env(char ***envp, unsigned int *envsizep, const char *name,
+child_set_env(char ***envp, u_int *envsizep, const char *name,
const char *value)
{
- unsigned int i, namelen;
+ u_int i, namelen;
char **env;
/*
* and assignments of the form name=value. No other forms are allowed.
*/
void
-read_environment_file(char ***env, unsigned int *envsize,
+read_environment_file(char ***env, u_int *envsize,
const char *filename)
{
FILE *f;
if ((pam_env = fetch_pam_environment()) == NULL)
return;
-
+
for(i = 0; pam_env[i] != NULL; i++) {
if ((equals = strstr(pam_env[i], "=")) == NULL)
continue;
-
+
if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) {
memset(var_name, '\0', sizeof(var_name));
memset(var_val, '\0', sizeof(var_val));
}
#endif /* USE_PAM */
-
#ifdef HAVE_CYGWIN
void copy_environment(char ***env, int *envsize)
{
for(i = 0; environ[i] != NULL; i++) {
if ((equals = strstr(environ[i], "=")) == NULL)
continue;
-
+
if (strlen(environ[i]) < (sizeof(var_name) - 1)) {
memset(var_name, '\0', sizeof(var_name));
memset(var_val, '\0', sizeof(var_val));
char buf[256];
char cmd[1024];
FILE *f = NULL;
- unsigned int envsize, i;
+ u_int envsize, i;
char **env;
extern char **environ;
struct stat st;
#endif /* WITH_IRIX_ARRAY */
#endif /* WITH_IRIX_JOBS */
-
/* login(1) is only called if we execute the login shell */
if (options.use_login && command != NULL)
options.use_login = 0;
switch, so we let login(1) to this for us. */
if (!options.use_login) {
#ifdef HAVE_OSF_SIA
- extern char **saved_argv;
- extern int saved_argc;
- char *host = get_canonical_hostname ();
-
- if (sia_become_user(NULL, saved_argc, saved_argv, host,
- pw->pw_name, ttyname, 0, NULL, NULL, SIA_BEU_SETLUID) !=
- SIASUCCESS) {
- perror("sia_become_user");
- exit(1);
- }
- if (setreuid(geteuid(), geteuid()) < 0) {
- perror("setreuid");
- exit(1);
- }
+ session_setup_sia(pw->pw_name, ttyname);
#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 */
+ if (getluid() == -1 && setluid(pw->pw_uid) == -1)
+ error("setluid: %s", strerror(errno));
+#endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */
+
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
if (setgid(pw->pw_gid) < 0) {
if (jid == -1) {
fatal("Failed to create job container: %.100s",
strerror(errno));
- }
+ }
# endif /* WITH_IRIX_JOBS */
# ifdef WITH_IRIX_ARRAY
/* initialize array session */
* in this order).
*/
if (!options.use_login) {
- if (stat(SSH_USER_RC, &st) >= 0) {
+ if (stat(_PATH_SSH_USER_RC, &st) >= 0) {
if (debug_flag)
- fprintf(stderr, "Running "_PATH_BSHELL" %s\n", SSH_USER_RC);
+ fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, _PATH_SSH_USER_RC);
- f = popen(_PATH_BSHELL " " SSH_USER_RC, "w");
+ f = popen(_PATH_BSHELL " " _PATH_SSH_USER_RC, "w");
if (f) {
if (auth_proto != NULL && auth_data != NULL)
fprintf(f, "%s %s\n", auth_proto, auth_data);
pclose(f);
} else
- fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
- } else if (stat(SSH_SYSTEM_RC, &st) >= 0) {
+ 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 "_PATH_BSHELL" %s\n", SSH_SYSTEM_RC);
+ fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, _PATH_SSH_SYSTEM_RC);
- f = popen(_PATH_BSHELL " " SSH_SYSTEM_RC, "w");
+ f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
if (f) {
if (auth_proto != NULL && auth_data != NULL)
fprintf(f, "%s %s\n", auth_proto, auth_data);
pclose(f);
} else
- fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
+ fprintf(stderr, "Could not run %s\n", _PATH_SSH_SYSTEM_RC);
} else if (options.xauth_location != NULL) {
/* Add authority data to .Xauthority if appropriate. */
if (auth_proto != NULL && auth_data != NULL) {
"Running %.100s add %.100s %.100s %.100s\n",
options.xauth_location, display,
auth_proto, auth_data);
-#ifndef HAVE_CYGWIN /* Unix sockets are not supported */
+#ifndef NO_X11_UNIX_SOCKETS
if (screen != NULL)
fprintf(stderr,
"Adding %.*s/unix%s %s %s\n",
(int)(screen-display), display,
screen, auth_proto, auth_data);
-#endif
+#endif /* NO_X11_UNIX_SOCKETS */
}
snprintf(cmd, sizeof cmd, "%s -q -",
options.xauth_location);
if (f) {
fprintf(f, "add %s %s %s\n", display,
auth_proto, auth_data);
-#ifndef HAVE_CYGWIN /* Unix sockets are not supported */
- if (screen != NULL)
+#ifndef NO_X11_UNIX_SOCKETS
+ if (screen != NULL)
fprintf(f, "add %.*s/unix%s %s %s\n",
(int)(screen-display), display,
screen, auth_proto, auth_data);
-#endif
+#endif /* NO_X11_UNIX_SOCKETS */
pclose(f);
} else {
fprintf(stderr, "Could not run %s\n",
}
s->pw = auth_get_user();
if (s->pw == NULL)
- fatal("no user for session %i", s->self);
+ fatal("no user for session %d", s->self);
debug("session_open: session %d: link with channel %d", s->self, chanid);
s->chanid = chanid;
return 1;
int
session_pty_req(Session *s)
{
- unsigned int len;
+ u_int len;
char *term_modes; /* encoded terminal modes */
if (no_pty_flag)
int
session_subsystem_req(Session *s)
{
- unsigned int len;
+ u_int len;
int success = 0;
char *subsys = packet_get_string(&len);
int i;
int
session_exec_req(Session *s)
{
- unsigned int len;
+ u_int len;
char *command = packet_get_string(&len);
packet_done();
if (forced_command) {
void
session_input_channel_req(int id, void *arg)
{
- unsigned int len;
+ u_int len;
int reply;
int success = 0;
char *rtype;
if (s == NULL || s->ttyfd == -1)
return;
- debug("session_pty_cleanup: session %i release %s", s->self, s->tty);
+ debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
/* Cancel the cleanup function. */
fatal_remove_cleanup(pty_cleanup_proc, (void *)s);
* interested in data we write.
* Note that we must not call 'chan_read_failed', since there could
* be some more data waiting in the pipe.
- * djm - This is no longer true as we have allowed one pass through
- * the select loop before killing the connection
*/
if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_write_failed(c);
- if (c->istate != CHAN_INPUT_CLOSED)
- chan_read_failed(c);
s->chanid = -1;
}
session_close(s);
} else {
/* notify child, delay session cleanup */
- if (s->pid <= 1)
- fatal("session_close_by_channel: Unsafe s->pid = %d", s->pid);
if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0)
error("session_close_by_channel: kill %d: %s",
s->pid, strerror(errno));
}
void
-do_authenticated2(void)
+do_authenticated2(Authctxt *authctxt)
{
-#ifdef HAVE_LOGIN_CAP
- struct passwd *pw;
-#endif
-
/*
* Cancel the alarm we set to limit the time taken for
* authentication.
startup_pipe = -1;
}
#if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD)
- pw = auth_get_user();
- if ((lc = login_getclass(pw->pw_class)) == NULL) {
+ if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) {
error("unable to get login class");
return;
}