*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.108 2001/10/11 13:45:21 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.124 2002/02/06 14:37:22 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
int row, col, xpixel, ypixel;
char tty[TTYSZ];
/* X11 */
+ int display_number;
char *display;
int screen;
+ char *auth_display;
char *auth_proto;
char *auth_data;
int single_connection;
#ifdef WITH_AIXAUTHENTICATE
/* We don't have a pty yet, so just label the line as "ssh" */
if (loginsuccess(authctxt->user,
- get_canonical_hostname(options.reverse_mapping_check),
+ get_canonical_hostname(options.verify_reverse_mapping),
"ssh", &aixloginmsg) < 0)
aixloginmsg = NULL;
#endif /* WITH_AIXAUTHENTICATE */
{
Session *s;
char *command;
- int success, type, plen, screen_flag;
+ int success, type, screen_flag;
int compression_level = 0, enable_compression_after_reply = 0;
u_int proto_len, data_len, dlen;
success = 0;
/* Get a packet from the client. */
- type = packet_read(&plen);
+ type = packet_read();
/* Process the packet. */
switch (type) {
case SSH_CMSG_REQUEST_COMPRESSION:
- packet_integrity_check(plen, 4, type);
compression_level = packet_get_int();
+ packet_check_eom();
if (compression_level < 1 || compression_level > 9) {
packet_send_debug("Received illegal compression level %d.",
- compression_level);
+ compression_level);
break;
}
/* Enable compression after we have responded with SUCCESS. */
} else {
s->screen = 0;
}
- packet_done();
+ packet_check_eom();
success = session_setup_x11fwd(s);
if (!success) {
xfree(s->auth_proto);
if (packet_set_maxsize(packet_get_int()) > 0)
success = 1;
break;
-
+
#if defined(AFS) || defined(KRB5)
case SSH_CMSG_HAVE_KERBEROS_TGT:
if (!options.kerberos_tgt_passing) {
verbose("Kerberos TGT passing disabled.");
} else {
char *kdata = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
-
+ packet_check_eom();
+
/* XXX - 0x41, see creds_to_radix version */
if (kdata[0] != 0x41) {
#ifdef KRB5
krb5_data tgt;
tgt.data = kdata;
tgt.length = dlen;
-
+
if (auth_krb5_tgt(s->authctxt, &tgt))
success = 1;
else
}
break;
#endif /* AFS || KRB5 */
-
+
#ifdef AFS
case SSH_CMSG_HAVE_AFS_TOKEN:
if (!options.afs_token_passing || !k_hasafs()) {
} else {
/* Accept AFS token. */
char *token = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
-
+ packet_check_eom();
+
if (auth_afs_token(s->authctxt, token))
success = 1;
else
} else {
do_exec(s, NULL);
}
- packet_done();
+ packet_check_eom();
session_close(s);
return;
if (packet_connection_is_on_socket()) {
fromlen = sizeof(from);
if (getpeername(packet_get_connection_in(),
- (struct sockaddr *) & from, &fromlen) < 0) {
+ (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),
+ get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
(struct sockaddr *)&from);
}
#endif
/* 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(utmp_len, options.reverse_mapping_check),
+ get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
(struct sockaddr *)&from);
#ifdef USE_PAM
*/
static void
child_set_env(char ***envp, u_int *envsizep, const char *name,
- const char *value)
+ const char *value)
{
u_int i, namelen;
char **env;
*/
static void
read_environment_file(char ***env, u_int *envsize,
- const char *filename)
+ const char *filename)
{
FILE *f;
char buf[4096];
fclose(f);
}
-#ifdef USE_PAM
-/*
- * Sets any environment variables which have been specified by PAM
- */
-void do_pam_environment(char ***env, u_int *envsize)
+void copy_environment(char **source, char ***env, u_int *envsize)
{
- char *equals, var_name[512], var_val[512];
- char **pam_env;
+ char *var_name, *var_val;
int i;
- if ((pam_env = fetch_pam_environment()) == NULL)
+ if (source == NULL)
return;
- for(i = 0; pam_env[i] != NULL; i++) {
- if ((equals = strstr(pam_env[i], "=")) == NULL)
+ for(i = 0; source[i] != NULL; i++) {
+ var_name = xstrdup(source[i]);
+ if ((var_val = strstr(var_name, "=")) == NULL) {
+ xfree(var_name);
continue;
-
- if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) {
- memset(var_name, '\0', sizeof(var_name));
- memset(var_val, '\0', sizeof(var_val));
-
- strncpy(var_name, pam_env[i], equals - pam_env[i]);
- strcpy(var_val, equals + 1);
-
- debug3("PAM environment: %s=%s", var_name, var_val);
-
- child_set_env(env, envsize, var_name, var_val);
}
- }
-}
-#endif /* USE_PAM */
+ *var_val++ = '\0';
-#ifdef HAVE_CYGWIN
-void copy_environment(char ***env, u_int *envsize)
-{
- char *equals, var_name[512], var_val[512];
- int i;
-
- 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));
-
- strncpy(var_name, environ[i], equals - environ[i]);
- strcpy(var_val, equals + 1);
-
- debug3("Copy environment: %s=%s", var_name, var_val);
-
- child_set_env(env, envsize, var_name, var_val);
- }
+ debug3("Copy environment: %s=%s", var_name, var_val);
+ child_set_env(env, envsize, var_name, var_val);
+
+ xfree(var_name);
}
}
-#endif
#if defined(HAVE_GETUSERATTR)
/*
* The Windows environment contains some setting which are
* important for a running system. They must not be dropped.
*/
- copy_environment(&env, &envsize);
+ copy_environment(environ, &env, &envsize);
#endif
if (!options.use_login) {
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
/* Set custom environment options from RSA authentication. */
- while (custom_environment) {
- struct envstring *ce = custom_environment;
- char *s = ce->s;
- int i;
- for (i = 0; s[i] != '=' && s[i]; i++);
- if (s[i] == '=') {
- s[i] = 0;
- child_set_env(&env, &envsize, s, s + i + 1);
+ if (!options.use_login) {
+ while (custom_environment) {
+ struct envstring *ce = custom_environment;
+ char *s = ce->s;
+ int i;
+ for (i = 0; s[i] != '=' && s[i]; i++)
+ ;
+ if (s[i] == '=') {
+ s[i] = 0;
+ child_set_env(&env, &envsize, s, s + i + 1);
+ }
+ custom_environment = ce->next;
+ xfree(ce->s);
+ xfree(ce);
}
- custom_environment = ce->next;
- xfree(ce->s);
- xfree(ce);
}
snprintf(buf, sizeof buf, "%.50s %d %d",
#endif
#ifdef USE_PAM
/* Pull in any environment variables that may have been set by PAM. */
- do_pam_environment(&env, &envsize);
+ copy_environment(fetch_pam_environment(), &env, &envsize);
#endif /* USE_PAM */
if (auth_get_socket_name() != NULL)
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
- auth_get_socket_name());
+ auth_get_socket_name());
/* read $HOME/.ssh/environment. */
if (!options.use_login) {
/* we have to stash the hostname before we close our socket. */
if (options.use_login)
hostname = get_remote_name_or_ip(utmp_len,
- options.reverse_mapping_check);
+ options.verify_reverse_mapping);
/*
* Close the connection descriptors; note that this is the child, and
* the server will still have the socket open, and it is important
/* Try to get AFS tokens for the local cell. */
if (k_hasafs()) {
char cell[64];
-
+
if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
krb_afslog(cell, 0);
-
+
krb_afslog(0, 0);
}
#endif /* AFS */
_PATH_SSH_SYSTEM_RC);
} else if (do_xauth && options.xauth_location != NULL) {
/* Add authority data to .Xauthority if appropriate. */
- char *screen = strchr(s->display, ':');
-
if (debug_flag) {
fprintf(stderr,
"Running %.100s add "
"%.100s %.100s %.100s\n",
- options.xauth_location, s->display,
+ options.xauth_location, s->auth_display,
s->auth_proto, s->auth_data);
- if (screen != NULL)
- fprintf(stderr,
- "Adding %.*s/unix%s %s %s\n",
- (int)(screen - s->display),
- s->display, screen,
- s->auth_proto, s->auth_data);
}
snprintf(cmd, sizeof cmd, "%s -q -",
options.xauth_location);
f = popen(cmd, "w");
if (f) {
- fprintf(f, "add %s %s %s\n", s->display,
- s->auth_proto, s->auth_data);
- if (screen != NULL)
- fprintf(f, "add %.*s/unix%s %s %s\n",
- (int)(screen - s->display),
- s->display, screen,
- s->auth_proto,
- s->auth_data);
+ fprintf(f, "add %s %s %s\n",
+ s->auth_display, s->auth_proto,
+ s->auth_data);
pclose(f);
} else {
fprintf(stderr, "Could not run %s\n",
/* Start the shell. Set initial character to '-'. */
buf[0] = '-';
- strncpy(buf + 1, cp, sizeof(buf) - 1);
- buf[sizeof(buf) - 1] = 0;
+ strlcpy(buf + 1, cp, sizeof(buf) - 1);
/* Execute the shell. */
argv[0] = buf;
execl(LOGIN_PROGRAM, "login", "-h", hostname,
#ifdef LOGIN_NEEDS_TERM
- s->term? s->term : "unknown",
+ s->term? s->term : "unknown",
#endif
- "-p", "-f", "--", pw->pw_name, (char *)NULL);
+ "-p", "-f", "--", pw->pw_name, (char *)NULL);
/* Login couldn't be executed, die. */
static int did_init = 0;
if (!did_init) {
debug("session_new: init");
- for(i = 0; i < MAX_SESSIONS; i++) {
+ for (i = 0; i < MAX_SESSIONS; i++) {
sessions[i].used = 0;
}
did_init = 1;
}
- for(i = 0; i < MAX_SESSIONS; i++) {
+ for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (! s->used) {
memset(s, 0, sizeof(*s));
session_dump(void)
{
int i;
- for(i = 0; i < MAX_SESSIONS; i++) {
+ for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
debug("dump: used %d session %d %p channel %d pid %d",
s->used,
session_by_channel(int id)
{
int i;
- for(i = 0; i < MAX_SESSIONS; i++) {
+ for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->chanid == id) {
debug("session_by_channel: session %d channel %d", i, id);
{
int i;
debug("session_by_pid: pid %d", pid);
- for(i = 0; i < MAX_SESSIONS; i++) {
+ for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->pid == pid)
return s;
s->row = packet_get_int();
s->xpixel = packet_get_int();
s->ypixel = packet_get_int();
- packet_done();
+ packet_check_eom();
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
return 1;
}
/* Set window size from the packet. */
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
- packet_done();
+ packet_check_eom();
session_proctitle(s);
return 1;
}
char *cmd, *subsys = packet_get_string(&len);
int i;
- packet_done();
- log("subsystem request for %s", subsys);
+ packet_check_eom();
+ log("subsystem request for %.100s", subsys);
for (i = 0; i < options.num_subsystems; i++) {
if (strcmp(subsys, options.subsystem_name[i]) == 0) {
s->is_subsystem = 1;
do_exec(s, cmd);
success = 1;
+ break;
}
}
if (!success)
- log("subsystem request for %s failed, subsystem not found",
+ log("subsystem request for %.100s failed, subsystem not found",
subsys);
xfree(subsys);
s->auth_proto = packet_get_string(NULL);
s->auth_data = packet_get_string(NULL);
s->screen = packet_get_int();
- packet_done();
+ packet_check_eom();
success = session_setup_x11fwd(s);
if (!success) {
static int
session_shell_req(Session *s)
{
- packet_done();
+ packet_check_eom();
do_exec(s, NULL);
return 1;
}
{
u_int len;
char *command = packet_get_string(&len);
- packet_done();
+ packet_check_eom();
do_exec(s, command);
xfree(command);
return 1;
session_auth_agent_req(Session *s)
{
static int called = 0;
- packet_done();
+ packet_check_eom();
if (no_agent_forwarding_flag) {
debug("session_auth_agent_req: no_agent_forwarding_flag");
return 0;
}
}
-void
-session_input_channel_req(int id, void *arg)
+int
+session_input_channel_req(Channel *c, const char *rtype)
{
- u_int len;
- int reply;
int success = 0;
- char *rtype;
Session *s;
- Channel *c;
-
- rtype = packet_get_string(&len);
- reply = packet_get_char();
-
- s = session_by_channel(id);
- if (s == NULL)
- fatal("session_input_channel_req: channel %d: no session", id);
- c = channel_lookup(id);
- if (c == NULL)
- fatal("session_input_channel_req: channel %d: bad channel", id);
- debug("session_input_channel_req: session %d channel %d request %s reply %d",
- s->self, id, rtype, reply);
+ if ((s = session_by_channel(c->self)) == NULL) {
+ log("session_input_channel_req: no session %d req %.100s",
+ c->self, rtype);
+ return 0;
+ }
+ debug("session_input_channel_req: session %d req %s", s->self, rtype);
/*
* a session is in LARVAL state until a shell, a command
if (strcmp(rtype, "window-change") == 0) {
success = session_window_change_req(s);
}
-
- if (reply) {
- packet_start(success ?
- SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
- packet_put_int(c->remote_id);
- packet_send();
- }
- xfree(rtype);
+ return success;
}
void
session_exit_message(Session *s, int status)
{
Channel *c;
- if (s == NULL)
- fatal("session_close: no session");
- c = channel_lookup(s->chanid);
- if (c == NULL)
+
+ if ((c = channel_lookup(s->chanid)) == NULL)
fatal("session_exit_message: session %d: no channel %d",
s->self, s->chanid);
debug("session_exit_message: session %d channel %d pid %d",
s->self, s->chanid, s->pid);
if (WIFEXITED(status)) {
- channel_request_start(s->chanid,
- "exit-status", 0);
+ channel_request_start(s->chanid, "exit-status", 0);
packet_put_int(WEXITSTATUS(status));
packet_send();
} else if (WIFSIGNALED(status)) {
- channel_request_start(s->chanid,
- "exit-signal", 0);
+ channel_request_start(s->chanid, "exit-signal", 0);
packet_put_int(WTERMSIG(status));
#ifdef WCOREDUMP
packet_put_char(WCOREDUMP(status));
xfree(s->term);
if (s->display)
xfree(s->display);
+ if (s->auth_display)
+ xfree(s->auth_display);
if (s->auth_data)
xfree(s->auth_data);
if (s->auth_proto)
session_destroy_all(void)
{
int i;
- for(i = 0; i < MAX_SESSIONS; i++) {
+ for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
- if (s->used)
+ if (s->used)
session_close(s);
}
}
static char buf[1024];
int i;
buf[0] = '\0';
- for(i = 0; i < MAX_SESSIONS; i++) {
+ for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->ttyfd != -1) {
if (buf[0] != '\0')
session_setup_x11fwd(Session *s)
{
struct stat st;
+ char display[512], auth_display[512];
+ char hostname[MAXHOSTNAMELEN];
if (no_x11_forwarding_flag) {
packet_send_debug("X11 forwarding disabled in user configuration file.");
debug("X11 display already set.");
return 0;
}
- s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
- if (s->display == NULL) {
+ s->display_number = x11_create_display_inet(options.x11_display_offset,
+ options.x11_use_localhost, s->single_connection);
+ if (s->display_number == -1) {
debug("x11_create_display_inet failed.");
return 0;
}
+
+ /* Set up a suitable value for the DISPLAY variable. */
+ if (gethostname(hostname, sizeof(hostname)) < 0)
+ fatal("gethostname: %.100s", strerror(errno));
+ /*
+ * auth_display must be used as the displayname when the
+ * authorization entry is added with xauth(1). This will be
+ * different than the DISPLAY string for localhost displays.
+ */
+ if (options.x11_use_localhost) {
+ snprintf(display, sizeof display, "localhost:%d.%d",
+ s->display_number, s->screen);
+ snprintf(auth_display, sizeof auth_display, "unix:%d.%d",
+ s->display_number, s->screen);
+ s->display = xstrdup(display);
+ s->auth_display = xstrdup(auth_display);
+ } else {
+#ifdef IPADDR_IN_DISPLAY
+ struct hostent *he;
+ struct in_addr my_addr;
+
+ he = gethostbyname(hostname);
+ if (he == NULL) {
+ error("Can't get IP address for X11 DISPLAY.");
+ packet_send_debug("Can't get IP address for X11 DISPLAY.");
+ return 0;
+ }
+ memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
+ snprintf(display, sizeof display, "%.50s:%d.%d", inet_ntoa(my_addr),
+ s->display_number, s->screen);
+#else
+ snprintf(display, sizeof display, "%.400s:%d.%d", hostname,
+ s->display_number, s->screen);
+#endif
+ s->display = xstrdup(display);
+ s->auth_display = xstrdup(display);
+ }
+
return 1;
}