version 1.12, 2000/05/03 18:03:07 |
version 1.12.2.2, 2000/09/01 18:23:22 |
|
|
#include "bufaux.h" |
#include "bufaux.h" |
#include "ssh2.h" |
#include "ssh2.h" |
#include "auth.h" |
#include "auth.h" |
|
#include "auth-options.h" |
|
|
|
#ifdef HAVE_LOGIN_CAP |
|
#include <login_cap.h> |
|
#endif |
|
|
/* types */ |
/* types */ |
|
|
#define TTYSZ 64 |
#define TTYSZ 64 |
|
|
void session_proctitle(Session *s); |
void session_proctitle(Session *s); |
void do_exec_pty(Session *s, const char *command, struct passwd * pw); |
void do_exec_pty(Session *s, const char *command, struct passwd * pw); |
void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); |
void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); |
|
void do_login(Session *s); |
|
|
void |
void |
do_child(const char *command, struct passwd * pw, const char *term, |
do_child(const char *command, struct passwd * pw, const char *term, |
|
|
extern char *__progname; |
extern char *__progname; |
extern int log_stderr; |
extern int log_stderr; |
extern int debug_flag; |
extern int debug_flag; |
|
extern unsigned int utmp_len; |
|
|
|
extern int startup_pipe; |
|
|
/* Local Xauthority file. */ |
/* Local Xauthority file. */ |
static char *xauthfile; |
static char *xauthfile; |
|
|
|
|
#define MAX_SESSIONS 10 |
#define MAX_SESSIONS 10 |
Session sessions[MAX_SESSIONS]; |
Session sessions[MAX_SESSIONS]; |
|
|
/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */ |
#ifdef HAVE_LOGIN_CAP |
int no_port_forwarding_flag = 0; |
static login_cap_t *lc; |
int no_agent_forwarding_flag = 0; |
#endif |
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. |
* Remove local Xauthority file. |
*/ |
*/ |
|
|
* authentication. |
* authentication. |
*/ |
*/ |
alarm(0); |
alarm(0); |
|
if (startup_pipe != -1) { |
|
close(startup_pipe); |
|
startup_pipe = -1; |
|
} |
|
|
/* |
/* |
* Inform the channel mechanism that we are the server side and that |
* Inform the channel mechanism that we are the server side and that |
|
|
s = session_new(); |
s = session_new(); |
s->pw = pw; |
s->pw = pw; |
|
|
|
#ifdef HAVE_LOGIN_CAP |
|
if ((lc = login_getclass(pw->pw_class)) == NULL) { |
|
error("unable to get login class"); |
|
return; |
|
} |
|
#endif |
|
|
/* |
/* |
* We stay in this loop until the client requests to execute a shell |
* We stay in this loop until the client requests to execute a shell |
* or a command. |
* or a command. |
|
|
packet_send_debug("X11 forwarding disabled in server configuration file."); |
packet_send_debug("X11 forwarding disabled in server configuration file."); |
break; |
break; |
} |
} |
#ifdef XAUTH_PATH |
if (!options.xauth_location) { |
|
packet_send_debug("No xauth program; cannot forward with spoofing."); |
|
break; |
|
} |
if (no_x11_forwarding_flag) { |
if (no_x11_forwarding_flag) { |
packet_send_debug("X11 forwarding not permitted for this authentication."); |
packet_send_debug("X11 forwarding not permitted for this authentication."); |
break; |
break; |
|
|
fatal_add_cleanup(xauthfile_cleanup_proc, NULL); |
fatal_add_cleanup(xauthfile_cleanup_proc, NULL); |
success = 1; |
success = 1; |
break; |
break; |
#else /* XAUTH_PATH */ |
|
packet_send_debug("No xauth program; cannot forward with spoofing."); |
|
break; |
|
#endif /* XAUTH_PATH */ |
|
|
|
case SSH_CMSG_AGENT_REQUEST_FORWARDING: |
case SSH_CMSG_AGENT_REQUEST_FORWARDING: |
if (no_agent_forwarding_flag || compat13) { |
if (no_agent_forwarding_flag || compat13) { |
|
|
break; |
break; |
} |
} |
debug("Received authentication agent forwarding request."); |
debug("Received authentication agent forwarding request."); |
auth_input_request_forwarding(pw); |
success = auth_input_request_forwarding(pw); |
success = 1; |
|
break; |
break; |
|
|
case SSH_CMSG_PORT_FORWARD_REQUEST: |
case SSH_CMSG_PORT_FORWARD_REQUEST: |
|
|
void |
void |
do_exec_pty(Session *s, const char *command, struct passwd * pw) |
do_exec_pty(Session *s, const char *command, struct passwd * pw) |
{ |
{ |
FILE *f; |
|
char buf[100], *time_string; |
|
char line[256]; |
|
const char *hostname; |
|
int fdout, ptyfd, ttyfd, ptymaster; |
int fdout, ptyfd, ttyfd, ptymaster; |
int quiet_login; |
|
pid_t pid; |
pid_t pid; |
socklen_t fromlen; |
|
struct sockaddr_storage from; |
|
struct stat st; |
|
time_t last_login_time; |
|
|
|
if (s == NULL) |
if (s == NULL) |
fatal("do_exec_pty: no session"); |
fatal("do_exec_pty: no session"); |
ptyfd = s->ptyfd; |
ptyfd = s->ptyfd; |
ttyfd = s->ttyfd; |
ttyfd = s->ttyfd; |
|
|
/* Get remote host name. */ |
|
hostname = get_canonical_hostname(); |
|
|
|
/* |
|
* Get the time when the user last logged in. Buf will be set to |
|
* contain the hostname the last login was from. |
|
*/ |
|
if (!options.use_login) { |
|
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, |
|
buf, sizeof(buf)); |
|
} |
|
|
|
/* Fork the child. */ |
/* Fork the child. */ |
if ((pid = fork()) == 0) { |
if ((pid = fork()) == 0) { |
pid = getpid(); |
/* Child. Reinitialize the log because the pid has changed. */ |
|
|
/* Child. Reinitialize the log because the pid has |
|
changed. */ |
|
log_init(__progname, options.log_level, options.log_facility, log_stderr); |
log_init(__progname, options.log_level, options.log_facility, log_stderr); |
|
|
/* Close the master side of the pseudo tty. */ |
/* Close the master side of the pseudo tty. */ |
|
|
/* Close the extra descriptor for the pseudo tty. */ |
/* Close the extra descriptor for the pseudo tty. */ |
close(ttyfd); |
close(ttyfd); |
|
|
/* XXXX ? move to do_child() ??*/ |
/* record login, etc. similar to login(1) */ |
/* |
if (command == NULL && !options.use_login) |
* Get IP address of client. This is needed because we want |
do_login(s); |
* to record where the user logged in from. If the |
|
* connection is not a socket, let the ip 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 that there was a login on that terminal. */ |
|
record_login(pid, s->tty, pw->pw_name, pw->pw_uid, hostname, |
|
(struct sockaddr *)&from); |
|
|
|
/* Check if .hushlogin exists. */ |
|
snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); |
|
quiet_login = stat(line, &st) >= 0; |
|
|
|
/* |
|
* If the user has logged in before, display the time of last |
|
* login. However, don't display anything extra if a command |
|
* has been specified (so that ssh can be used to execute |
|
* commands on a remote machine without users knowing they |
|
* are going to another machine). Login(1) will do this for |
|
* us as well, so check if login(1) is used |
|
*/ |
|
if (command == NULL && last_login_time != 0 && !quiet_login && |
|
!options.use_login) { |
|
/* Convert the date to a string. */ |
|
time_string = ctime(&last_login_time); |
|
/* Remove the trailing newline. */ |
|
if (strchr(time_string, '\n')) |
|
*strchr(time_string, '\n') = 0; |
|
/* Display the last login time. Host if displayed |
|
if known. */ |
|
if (strcmp(buf, "") == 0) |
|
printf("Last login: %s\r\n", time_string); |
|
else |
|
printf("Last login: %s from %s\r\n", time_string, buf); |
|
} |
|
/* |
|
* Print /etc/motd unless a command was specified or printing |
|
* it was disabled in server options or login(1) will be |
|
* used. Note that some machines appear to print it in |
|
* /etc/profile or similar. |
|
*/ |
|
if (command == NULL && options.print_motd && !quiet_login && |
|
!options.use_login) { |
|
/* Print /etc/motd if it exists. */ |
|
f = fopen("/etc/motd", "r"); |
|
if (f) { |
|
while (fgets(line, sizeof(line), f)) |
|
fputs(line, stdout); |
|
fclose(f); |
|
} |
|
} |
|
/* Do common processing for the child, such as execing the command. */ |
/* 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 */ |
/* NOTREACHED */ |
} |
} |
if (pid < 0) |
if (pid < 0) |
|
|
} |
} |
} |
} |
|
|
|
const char * |
|
get_remote_name_or_ip(void) |
|
{ |
|
static const char *remote = ""; |
|
if (utmp_len > 0) |
|
remote = get_canonical_hostname(); |
|
if (utmp_len == 0 || strlen(remote) > utmp_len) |
|
remote = get_remote_ipaddr(); |
|
return remote; |
|
} |
|
|
|
/* administrative, login(1)-like work */ |
|
void |
|
do_login(Session *s) |
|
{ |
|
FILE *f; |
|
char *time_string; |
|
char buf[256]; |
|
socklen_t fromlen; |
|
struct sockaddr_storage from; |
|
struct stat st; |
|
time_t last_login_time; |
|
struct passwd * pw = s->pw; |
|
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 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); |
|
|
|
/* Done if .hushlogin exists. */ |
|
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 |
|
return; |
|
/* |
|
* Get the time when the user last logged in. 'buf' will be set |
|
* to contain the hostname the last login was from. |
|
*/ |
|
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, |
|
buf, sizeof(buf)); |
|
if (last_login_time != 0) { |
|
time_string = ctime(&last_login_time); |
|
if (strchr(time_string, '\n')) |
|
*strchr(time_string, '\n') = 0; |
|
if (strcmp(buf, "") == 0) |
|
printf("Last login: %s\r\n", time_string); |
|
else |
|
printf("Last login: %s from %s\r\n", time_string, buf); |
|
} |
|
if (options.print_motd) { |
|
#ifdef HAVE_LOGIN_CAP |
|
f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", |
|
"/etc/motd"), "r"); |
|
#else |
|
f = fopen("/etc/motd", "r"); |
|
#endif |
|
if (f) { |
|
while (fgets(buf, sizeof(buf), f)) |
|
fputs(buf, stdout); |
|
fclose(f); |
|
} |
|
} |
|
} |
|
|
/* |
/* |
* Sets the value of the given variable in the environment. If the variable |
* Sets the value of the given variable in the environment. If the variable |
* already exists, its value is overriden. |
* already exists, its value is overriden. |
|
|
fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf); |
fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf); |
continue; |
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 = '\0'; |
value++; |
value++; |
child_set_env(env, envsize, cp, value); |
child_set_env(env, envsize, cp, value); |
|
|
const char *display, const char *auth_proto, |
const char *display, const char *auth_proto, |
const char *auth_data, const char *ttyname) |
const char *auth_data, const char *ttyname) |
{ |
{ |
const char *shell, *cp = NULL; |
const char *shell, *hostname, *cp = NULL; |
char buf[256]; |
char buf[256]; |
FILE *f; |
char cmd[1024]; |
|
FILE *f = NULL; |
unsigned int envsize, i; |
unsigned int envsize, i; |
char **env; |
char **env; |
extern char **environ; |
extern char **environ; |
struct stat st; |
struct stat st; |
char *argv[10]; |
char *argv[10]; |
|
|
f = fopen("/etc/nologin", "r"); |
/* login(1) is only called if we execute the login shell */ |
if (f) { |
if (options.use_login && command != NULL) |
/* /etc/nologin exists. Print its contents and exit. */ |
options.use_login = 0; |
while (fgets(buf, sizeof(buf), f)) |
|
fputs(buf, stderr); |
if (!options.use_login) { |
fclose(f); |
#ifdef HAVE_LOGIN_CAP |
if (pw->pw_uid != 0) |
if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) |
|
f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, |
|
_PATH_NOLOGIN), "r"); |
|
#else |
|
if (pw->pw_uid) |
|
f = fopen(_PATH_NOLOGIN, "r"); |
|
#endif |
|
if (f) { |
|
/* /etc/nologin exists. Print its contents and exit. */ |
|
while (fgets(buf, sizeof(buf), f)) |
|
fputs(buf, stderr); |
|
fclose(f); |
exit(254); |
exit(254); |
|
} |
} |
} |
/* Set login name in the kernel. */ |
/* Set login name, uid, gid, and groups. */ |
if (setlogin(pw->pw_name) < 0) |
|
error("setlogin failed: %s", strerror(errno)); |
|
|
|
/* Set uid, gid, and groups. */ |
|
/* Login(1) does this as well, and it needs uid 0 for the "-h" |
/* Login(1) does this as well, and it needs uid 0 for the "-h" |
switch, so we let login(1) to this for us. */ |
switch, so we let login(1) to this for us. */ |
if (!options.use_login) { |
if (!options.use_login) { |
if (getuid() == 0 || geteuid() == 0) { |
if (getuid() == 0 || geteuid() == 0) { |
|
#ifdef HAVE_LOGIN_CAP |
|
if (setusercontext(lc, pw, pw->pw_uid, |
|
(LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { |
|
perror("unable to set user context"); |
|
exit(1); |
|
|
|
} |
|
#else |
|
if (setlogin(pw->pw_name) < 0) |
|
error("setlogin failed: %s", strerror(errno)); |
if (setgid(pw->pw_gid) < 0) { |
if (setgid(pw->pw_gid) < 0) { |
perror("setgid"); |
perror("setgid"); |
exit(1); |
exit(1); |
|
|
|
|
/* Permanently switch to the desired uid. */ |
/* Permanently switch to the desired uid. */ |
permanently_set_uid(pw->pw_uid); |
permanently_set_uid(pw->pw_uid); |
|
#endif |
} |
} |
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) |
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) |
fatal("Failed to set uids to %d.", (int) pw->pw_uid); |
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); |
} |
} |
/* |
/* |
* Get the shell from the password data. An empty shell field is |
* Get the shell from the password data. An empty shell field is |
* legal, and means /bin/sh. |
* legal, and means /bin/sh. |
*/ |
*/ |
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; |
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; |
|
#ifdef HAVE_LOGIN_CAP |
|
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); |
|
#endif |
|
|
#ifdef AFS |
#ifdef AFS |
/* Try to get AFS tokens for the local cell. */ |
/* Try to get AFS tokens for the local cell. */ |
|
|
child_set_env(&env, &envsize, "USER", pw->pw_name); |
child_set_env(&env, &envsize, "USER", pw->pw_name); |
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); |
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); |
child_set_env(&env, &envsize, "HOME", pw->pw_dir); |
child_set_env(&env, &envsize, "HOME", pw->pw_dir); |
|
#ifdef HAVE_LOGIN_CAP |
|
(void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH); |
|
child_set_env(&env, &envsize, "PATH", getenv("PATH")); |
|
#else |
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); |
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); |
|
#endif |
|
|
snprintf(buf, sizeof buf, "%.200s/%.50s", |
snprintf(buf, sizeof buf, "%.200s/%.50s", |
_PATH_MAILDIR, pw->pw_name); |
_PATH_MAILDIR, pw->pw_name); |
|
|
|
|
/* read $HOME/.ssh/environment. */ |
/* read $HOME/.ssh/environment. */ |
if (!options.use_login) { |
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); |
read_environment_file(&env, &envsize, buf); |
} |
} |
if (debug_flag) { |
if (debug_flag) { |
|
|
for (i = 0; env[i]; i++) |
for (i = 0; env[i]; i++) |
fprintf(stderr, " %.200s\n", env[i]); |
fprintf(stderr, " %.200s\n", env[i]); |
} |
} |
|
/* we have to stash the hostname before we close our socket. */ |
|
if (options.use_login) |
|
hostname = get_remote_name_or_ip(); |
/* |
/* |
* Close the connection descriptors; note that this is the child, and |
* Close the connection descriptors; note that this is the child, and |
* the server will still have the socket open, and it is important |
* the server will still have the socket open, and it is important |
|
|
close(i); |
close(i); |
|
|
/* Change current directory to the user\'s home directory. */ |
/* Change current directory to the user\'s home directory. */ |
if (chdir(pw->pw_dir) < 0) |
if (chdir(pw->pw_dir) < 0) { |
fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
pw->pw_dir, strerror(errno)); |
pw->pw_dir, strerror(errno)); |
|
#ifdef HAVE_LOGIN_CAP |
|
if (login_getcapbool(lc, "requirehome", 0)) |
|
exit(1); |
|
#endif |
|
} |
|
|
/* |
/* |
* Must take new environment into use so that .ssh/rc, /etc/sshrc and |
* Must take new environment into use so that .ssh/rc, /etc/sshrc and |
|
|
pclose(f); |
pclose(f); |
} else |
} else |
fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC); |
fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC); |
} |
} else if (options.xauth_location != NULL) { |
#ifdef XAUTH_PATH |
|
else { |
|
/* Add authority data to .Xauthority if appropriate. */ |
/* Add authority data to .Xauthority if appropriate. */ |
if (auth_proto != NULL && auth_data != NULL) { |
if (auth_proto != NULL && auth_data != NULL) { |
if (debug_flag) |
char *screen = strchr(display, ':'); |
fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n", |
if (debug_flag) { |
XAUTH_PATH, display, auth_proto, auth_data); |
fprintf(stderr, |
|
"Running %.100s add %.100s %.100s %.100s\n", |
f = popen(XAUTH_PATH " -q -", "w"); |
options.xauth_location, display, |
|
auth_proto, auth_data); |
|
if (screen != NULL) |
|
fprintf(stderr, |
|
"Adding %.*s/unix%s %s %s\n", |
|
(int)(screen-display), display, |
|
screen, auth_proto, auth_data); |
|
} |
|
snprintf(cmd, sizeof cmd, "%s -q -", |
|
options.xauth_location); |
|
f = popen(cmd, "w"); |
if (f) { |
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", |
|
(int)(screen-display), display, |
|
screen, auth_proto, auth_data); |
pclose(f); |
pclose(f); |
} else |
} else { |
fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH); |
fprintf(stderr, "Could not run %s\n", |
|
cmd); |
|
} |
} |
} |
} |
} |
#endif /* XAUTH_PATH */ |
|
|
|
/* Get the last component of the shell name. */ |
/* Get the last component of the shell name. */ |
cp = strrchr(shell, '/'); |
cp = strrchr(shell, '/'); |
if (cp) |
if (cp) |
|
|
struct stat mailstat; |
struct stat mailstat; |
mailbox = getenv("MAIL"); |
mailbox = getenv("MAIL"); |
if (mailbox != NULL) { |
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"); |
printf("No mail.\n"); |
else if (mailstat.st_mtime < mailstat.st_atime) |
else if (mailstat.st_mtime < mailstat.st_atime) |
printf("You have mail.\n"); |
printf("You have mail.\n"); |
|
|
} else { |
} else { |
/* Launch login(1). */ |
/* Launch login(1). */ |
|
|
execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(), |
execl("/usr/bin/login", "login", "-h", hostname, |
"-p", "-f", "--", pw->pw_name, NULL); |
"-p", "-f", "--", pw->pw_name, NULL); |
|
|
/* Login couldn't be executed, die. */ |
/* Login couldn't be executed, die. */ |
|
|
|
|
unsigned int len; |
unsigned int len; |
char *term_modes; /* encoded terminal modes */ |
char *term_modes; /* encoded terminal modes */ |
|
|
|
if (no_pty_flag) |
|
return 0; |
if (s->ttyfd != -1) |
if (s->ttyfd != -1) |
return 0; |
return 0; |
s->term = packet_get_string(&len); |
s->term = packet_get_string(&len); |
|
|
unsigned int len; |
unsigned int len; |
int success = 0; |
int success = 0; |
char *subsys = packet_get_string(&len); |
char *subsys = packet_get_string(&len); |
|
int i; |
|
|
packet_done(); |
packet_done(); |
log("subsystem request for %s", subsys); |
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); |
xfree(subsys); |
return success; |
return success; |
} |
} |
|
|
int |
int |
session_x11_req(Session *s) |
session_x11_req(Session *s) |
{ |
{ |
|
if (no_x11_forwarding_flag) { |
|
debug("X11 forwarding disabled in user configuration file."); |
|
return 0; |
|
} |
if (!options.x11_forwarding) { |
if (!options.x11_forwarding) { |
debug("X11 forwarding disabled in server configuration file."); |
debug("X11 forwarding disabled in server configuration file."); |
return 0; |
return 0; |
|
|
return 1; |
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 |
void |
session_input_channel_req(int id, void *arg) |
session_input_channel_req(int id, void *arg) |
{ |
{ |
|
|
*/ |
*/ |
if (c->type == SSH_CHANNEL_LARVAL) { |
if (c->type == SSH_CHANNEL_LARVAL) { |
if (strcmp(rtype, "shell") == 0) { |
if (strcmp(rtype, "shell") == 0) { |
packet_done(); |
success = session_shell_req(s); |
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; |
|
} else if (strcmp(rtype, "exec") == 0) { |
} else if (strcmp(rtype, "exec") == 0) { |
char *command = packet_get_string(&len); |
success = session_exec_req(s); |
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; |
|
} else if (strcmp(rtype, "pty-req") == 0) { |
} else if (strcmp(rtype, "pty-req") == 0) { |
success = session_pty_req(s); |
success = session_pty_req(s); |
} else if (strcmp(rtype, "x11-req") == 0) { |
} else if (strcmp(rtype, "x11-req") == 0) { |
|
|
void |
void |
do_authenticated2(void) |
do_authenticated2(void) |
{ |
{ |
|
struct passwd *pw; |
|
|
/* |
/* |
* Cancel the alarm we set to limit the time taken for |
* Cancel the alarm we set to limit the time taken for |
* authentication. |
* authentication. |
*/ |
*/ |
alarm(0); |
alarm(0); |
|
if (startup_pipe != -1) { |
|
close(startup_pipe); |
|
startup_pipe = -1; |
|
} |
|
#ifdef HAVE_LOGIN_CAP |
|
pw = auth_get_user(); |
|
if ((lc = login_getclass(pw->pw_class)) == NULL) { |
|
error("unable to get login class"); |
|
return; |
|
} |
|
#endif |
server_loop2(); |
server_loop2(); |
if (xauthfile) |
if (xauthfile) |
xauthfile_cleanup_proc(NULL); |
xauthfile_cleanup_proc(NULL); |