*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.12 2000/05/03 18:03:07 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.22 2000/07/05 20:18:07 deraadt Exp $");
#include "xmalloc.h"
#include "ssh.h"
#include "bufaux.h"
#include "ssh2.h"
#include "auth.h"
+#include "auth-options.h"
+
+#ifdef WITH_IRIX_PROJECT
+#include <proj.h>
+#endif /* WITH_IRIX_PROJECT */
+
+#if defined(HAVE_USERSEC_H)
+#include <usersec.h>
+#endif
+
+#ifdef HAVE_OSF_SIA
+# include <sia.h>
+# include <siad.h>
+#endif
/* types */
extern int log_stderr;
extern int debug_flag;
+extern int startup_pipe;
+
/* Local Xauthority file. */
static char *xauthfile;
char *aixloginmsg;
#endif /* WITH_AIXAUTHENTICATE */
-/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */
-int no_port_forwarding_flag = 0;
-int no_agent_forwarding_flag = 0;
-int no_x11_forwarding_flag = 0;
-int no_pty_flag = 0;
-
-/* RSA authentication "command=" option. */
-char *forced_command = NULL;
-
-/* RSA authentication "environment=" options. */
-struct envstring *custom_environment = NULL;
-
/*
* Remove local Xauthority file.
*/
* authentication.
*/
alarm(0);
+ close(startup_pipe);
/*
* Inform the channel mechanism that we are the server side and that
packet_send_debug("X11 forwarding disabled in server configuration file.");
break;
}
-#ifdef XAUTH_PATH
+ if (!options.xauth_location) {
+ packet_send_debug("No xauth program; cannot forward with spoofing.");
+ break;
+ }
if (no_x11_forwarding_flag) {
packet_send_debug("X11 forwarding not permitted for this authentication.");
break;
fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
success = 1;
break;
-#else /* XAUTH_PATH */
- packet_send_debug("No xauth program; cannot forward with spoofing.");
- break;
-#endif /* XAUTH_PATH */
case SSH_CMSG_AGENT_REQUEST_FORWARDING:
if (no_agent_forwarding_flag || compat13) {
break;
}
debug("Received authentication agent forwarding request.");
- auth_input_request_forwarding(pw);
- success = 1;
+ success = auth_input_request_forwarding(pw);
break;
case SSH_CMSG_PORT_FORWARD_REQUEST:
}
#endif
/* Do common processing for the child, such as execing the command. */
- do_child(command, pw, s->term, s->display, s->auth_proto, s->auth_data, s->tty);
+ do_child(command, pw, s->term, s->display, s->auth_proto,
+ s->auth_data, s->tty);
/* NOTREACHED */
}
if (pid < 0)
fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
continue;
}
- /* Replace the equals sign by nul, and advance value to the value string. */
+ /*
+ * Replace the equals sign by nul, and advance value to
+ * the value string.
+ */
*value = '\0';
value++;
child_set_env(env, envsize, cp, value);
}
#endif /* USE_PAM */
+#if defined(HAVE_GETUSERATTR)
+/*
+ * AIX-specific login initialisation
+ */
+void set_limit(char *user, char *soft, char *hard, int resource, int mult)
+{
+ struct rlimit rlim;
+ int slim, hlim;
+
+ getrlimit(resource, &rlim);
+
+ slim = 0;
+ if (getuserattr(user, soft, &slim, SEC_INT) != -1) {
+ if (slim < 0) {
+ rlim.rlim_cur = RLIM_INFINITY;
+ } else if (slim != 0) {
+ /* See the wackiness below */
+ if (rlim.rlim_cur == slim * mult)
+ slim = 0;
+ else
+ rlim.rlim_cur = slim * mult;
+ }
+ }
+
+ hlim = 0;
+ if (getuserattr(user, hard, &hlim, SEC_INT) != -1) {
+ if (hlim < 0) {
+ rlim.rlim_max = RLIM_INFINITY;
+ } else if (hlim != 0) {
+ rlim.rlim_max = hlim * mult;
+ }
+ }
+
+ /*
+ * XXX For cpu and fsize the soft limit is set to the hard limit
+ * if the hard limit is left at its default value and the soft limit
+ * is changed from its default value, either by requesting it
+ * (slim == 0) or by setting it to the current default. At least
+ * that's how rlogind does it. If you're confused you're not alone.
+ * Bug or feature? AIX 4.3.1.2
+ */
+ if ((!strcmp(soft, "fsize") || !strcmp(soft, "cpu"))
+ && hlim == 0 && slim != 0)
+ rlim.rlim_max = rlim.rlim_cur;
+ /* A specified hard limit limits the soft limit */
+ else if (hlim > 0 && rlim.rlim_cur > rlim.rlim_max)
+ rlim.rlim_cur = rlim.rlim_max;
+ /* A soft limit can increase a hard limit */
+ else if (rlim.rlim_cur > rlim.rlim_max)
+ rlim.rlim_max = rlim.rlim_cur;
+
+ if (setrlimit(resource, &rlim) != 0)
+ error("setrlimit(%.10s) failed: %.100s", soft, strerror(errno));
+}
+
+void set_limits_from_userattr(char *user)
+{
+ int mask;
+ char buf[16];
+
+ set_limit(user, S_UFSIZE, S_UFSIZE_HARD, RLIMIT_FSIZE, 512);
+ set_limit(user, S_UCPU, S_UCPU_HARD, RLIMIT_CPU, 1);
+ set_limit(user, S_UDATA, S_UDATA_HARD, RLIMIT_DATA, 512);
+ set_limit(user, S_USTACK, S_USTACK_HARD, RLIMIT_STACK, 512);
+ set_limit(user, S_URSS, S_URSS_HARD, RLIMIT_RSS, 512);
+ set_limit(user, S_UCORE, S_UCORE_HARD, RLIMIT_CORE, 512);
+#if defined(S_UNOFILE)
+ set_limit(user, S_UNOFILE, S_UNOFILE_HARD, RLIMIT_NOFILE, 1);
+#endif
+
+ if (getuserattr(user, S_UMASK, &mask, SEC_INT) != -1) {
+ /* Convert decimal to octal */
+ (void) snprintf(buf, sizeof(buf), "%d", mask);
+ if (sscanf(buf, "%o", &mask) == 1)
+ umask(mask);
+ }
+}
+#endif /* defined(HAVE_GETUSERATTR) */
+
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
{
const char *shell, *cp = NULL;
char buf[256];
+ char cmd[1024];
FILE *f;
unsigned int envsize, i;
char **env;
extern char **environ;
struct stat st;
char *argv[10];
+#ifdef WITH_IRIX_PROJECT
+ prid_t projid;
+#endif /* WITH_IRIX_PROJECT */
+
+ /* 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 */
f = fopen("/etc/nologin", "r");
}
#endif /* USE_PAM */
+#ifndef HAVE_OSF_SIA
/* Set login name in the kernel. */
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
+#endif
/* Set uid, gid, and groups. */
/* Login(1) does this as well, and it needs uid 0 for the "-h"
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);
+ }
+#else /* HAVE_OSF_SIA */
if (getuid() == 0 || geteuid() == 0) {
+#if defined(HAVE_GETUSERATTR)
+ set_limits_from_userattr(pw->pw_name);
+#endif /* defined(HAVE_GETUSERATTR) */
+
if (setgid(pw->pw_gid) < 0) {
perror("setgid");
exit(1);
}
endgrent();
+#ifdef WITH_IRIX_ARRAY
+ /* initialize array session */
+ if (newarraysess() != 0)
+ fatal("Failed to set up new array session: %.100s",
+ strerror(errno));
+#endif /* WITH_IRIX_ARRAY */
+
+#ifdef WITH_IRIX_PROJECT
+ /* initialize irix project info */
+ if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
+ debug("Failed to get project id, using projid 0");
+ projid = 0;
+ }
+
+ if (setprid(projid))
+ fatal("Failed to initialize project %d for %s: %.100s",
+ (int)projid, pw->pw_name, strerror(errno));
+#endif /* WITH_IRIX_PROJECT */
+
/* Permanently switch to the desired uid. */
permanently_set_uid(pw->pw_uid);
}
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %d.", (int) pw->pw_uid);
+#endif /* HAVE_OSF_SIA */
}
/*
* Get the shell from the password data. An empty shell field is
/* read $HOME/.ssh/environment. */
if (!options.use_login) {
- snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir);
+ snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
+ pw->pw_dir);
read_environment_file(&env, &envsize, buf);
}
if (debug_flag) {
if (!options.use_login) {
if (stat(SSH_USER_RC, &st) >= 0) {
if (debug_flag)
- fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
+ fprintf(stderr, "Running "_PATH_BSHELL" %s\n", SSH_USER_RC);
- f = popen("/bin/sh " SSH_USER_RC, "w");
+ f = popen(_PATH_BSHELL " " SSH_USER_RC, "w");
if (f) {
if (auth_proto != NULL && auth_data != NULL)
fprintf(f, "%s %s\n", auth_proto, auth_data);
fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
} else if (stat(SSH_SYSTEM_RC, &st) >= 0) {
if (debug_flag)
- fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
+ fprintf(stderr, "Running "_PATH_BSHELL" %s\n", SSH_SYSTEM_RC);
- f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
+ f = popen(_PATH_BSHELL " " 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);
- }
-#ifdef XAUTH_PATH
- else {
+ } else if (options.xauth_location != NULL) {
/* Add authority data to .Xauthority if appropriate. */
if (auth_proto != NULL && auth_data != NULL) {
- if (debug_flag)
- fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
- XAUTH_PATH, display, auth_proto, auth_data);
-
- f = popen(XAUTH_PATH " -q -", "w");
+ char *screen = strchr(display, ':');
+ if (debug_flag) {
+ fprintf(stderr,
+ "Running %.100s add %.100s %.100s %.100s\n",
+ options.xauth_location, display,
+ auth_proto, auth_data);
+ if (screen != NULL)
+ fprintf(stderr,
+ "Adding %.*s/unix%s %s %s\n",
+ screen-display, display,
+ screen, auth_proto, auth_data);
+ }
+ snprintf(cmd, sizeof cmd, "%s -q -",
+ options.xauth_location);
+ f = popen(cmd, "w");
if (f) {
- fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data);
+ fprintf(f, "add %s %s %s\n", display,
+ auth_proto, auth_data);
+ if (screen != NULL)
+ fprintf(f, "add %.*s/unix%s %s %s\n",
+ screen-display, display,
+ screen, auth_proto, auth_data);
pclose(f);
- } else
- fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH);
+ } else {
+ fprintf(stderr, "Could not run %s\n",
+ cmd);
+ }
}
}
-#endif /* XAUTH_PATH */
-
/* Get the last component of the shell name. */
cp = strrchr(shell, '/');
if (cp)
struct stat mailstat;
mailbox = getenv("MAIL");
if (mailbox != NULL) {
- if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0)
+ if (stat(mailbox, &mailstat) != 0 ||
+ mailstat.st_size == 0)
printf("No mail.\n");
else if (mailstat.st_mtime < mailstat.st_atime)
printf("You have mail.\n");
} else {
/* Launch login(1). */
- execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(),
+ execl(LOGIN_PROGRAM, "login", "-h", get_remote_ipaddr(),
"-p", "-f", "--", pw->pw_name, NULL);
/* Login couldn't be executed, die. */
unsigned int len;
char *term_modes; /* encoded terminal modes */
+ if (no_pty_flag)
+ return 0;
if (s->ttyfd != -1)
return 0;
s->term = packet_get_string(&len);
unsigned int len;
int success = 0;
char *subsys = packet_get_string(&len);
+ int i;
packet_done();
log("subsystem request for %s", subsys);
+ for (i = 0; i < options.num_subsystems; i++) {
+ if(strcmp(subsys, options.subsystem_name[i]) == 0) {
+ debug("subsystem: exec() %s", options.subsystem_command[i]);
+ do_exec_no_pty(s, options.subsystem_command[i], s->pw);
+ success = 1;
+ }
+ }
+
+ if (!success)
+ log("subsystem request for %s failed, subsystem not found", subsys);
+
xfree(subsys);
return success;
}
int
session_x11_req(Session *s)
{
+ if (no_x11_forwarding_flag) {
+ debug("X11 forwarding disabled in user configuration file.");
+ return 0;
+ }
if (!options.x11_forwarding) {
debug("X11 forwarding disabled in server configuration file.");
return 0;
return 1;
}
+int
+session_shell_req(Session *s)
+{
+ /* if forced_command == NULL, the shell is execed */
+ char *shell = forced_command;
+ packet_done();
+ s->extended = 1;
+ if (s->ttyfd == -1)
+ do_exec_no_pty(s, shell, s->pw);
+ else
+ do_exec_pty(s, shell, s->pw);
+ return 1;
+}
+
+int
+session_exec_req(Session *s)
+{
+ unsigned int len;
+ char *command = packet_get_string(&len);
+ packet_done();
+ if (forced_command) {
+ xfree(command);
+ command = forced_command;
+ debug("Forced command '%.500s'", forced_command);
+ }
+ s->extended = 1;
+ if (s->ttyfd == -1)
+ do_exec_no_pty(s, command, s->pw);
+ else
+ do_exec_pty(s, command, s->pw);
+ if (forced_command == NULL)
+ xfree(command);
+ return 1;
+}
+
void
session_input_channel_req(int id, void *arg)
{
*/
if (c->type == SSH_CHANNEL_LARVAL) {
if (strcmp(rtype, "shell") == 0) {
- packet_done();
- s->extended = 1;
- if (s->ttyfd == -1)
- do_exec_no_pty(s, NULL, s->pw);
- else
- do_exec_pty(s, NULL, s->pw);
- success = 1;
+ success = session_shell_req(s);
} else if (strcmp(rtype, "exec") == 0) {
- char *command = packet_get_string(&len);
- packet_done();
- s->extended = 1;
- if (s->ttyfd == -1)
- do_exec_no_pty(s, command, s->pw);
- else
- do_exec_pty(s, command, s->pw);
- xfree(command);
- success = 1;
+ success = session_exec_req(s);
} else if (strcmp(rtype, "pty-req") == 0) {
success = session_pty_req(s);
} else if (strcmp(rtype, "x11-req") == 0) {
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));
* authentication.
*/
alarm(0);
+ close(startup_pipe);
server_loop2();
if (xauthfile)
xauthfile_cleanup_proc(NULL);