version 1.12, 2013/11/08 19:18:25 |
version 1.13, 2014/10/19 16:30:58 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
/* $OpenBSD: session.c,v 1.266 2013/07/19 07:37:48 markus Exp $ */ |
/* $OpenBSD: session.c,v 1.274 2014/07/15 15:54:14 millert Exp $ */ |
/* |
/* |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
* All rights reserved |
* All rights reserved |
Line 48 __RCSID("$NetBSD$"); |
|
Line 48 __RCSID("$NetBSD$"); |
|
#include <fcntl.h> |
#include <fcntl.h> |
#include <grp.h> |
#include <grp.h> |
#include <login_cap.h> |
#include <login_cap.h> |
|
#include <netdb.h> |
#include <paths.h> |
#include <paths.h> |
#include <pwd.h> |
#include <pwd.h> |
#include <signal.h> |
#include <signal.h> |
Line 76 __RCSID("$NetBSD$"); |
|
Line 77 __RCSID("$NetBSD$"); |
|
#include "authfd.h" |
#include "authfd.h" |
#include "pathnames.h" |
#include "pathnames.h" |
#include "log.h" |
#include "log.h" |
|
#include "misc.h" |
#include "servconf.h" |
#include "servconf.h" |
#include "sshlogin.h" |
#include "sshlogin.h" |
#include "serverloop.h" |
#include "serverloop.h" |
#include "canohost.h" |
#include "canohost.h" |
#include "misc.h" |
|
#include "session.h" |
#include "session.h" |
#ifdef GSSAPI |
#ifdef GSSAPI |
#include "ssh-gss.h" |
#include "ssh-gss.h" |
Line 170 auth_input_request_forwarding(struct pas |
|
Line 171 auth_input_request_forwarding(struct pas |
|
{ |
{ |
Channel *nc; |
Channel *nc; |
int sock = -1; |
int sock = -1; |
struct sockaddr_un sunaddr; |
|
|
|
if (auth_sock_name != NULL) { |
if (auth_sock_name != NULL) { |
error("authentication forwarding requested twice."); |
error("authentication forwarding requested twice."); |
Line 196 auth_input_request_forwarding(struct pas |
|
Line 196 auth_input_request_forwarding(struct pas |
|
xasprintf(&auth_sock_name, "%s/agent.%ld", |
xasprintf(&auth_sock_name, "%s/agent.%ld", |
auth_sock_dir, (long) getpid()); |
auth_sock_dir, (long) getpid()); |
|
|
/* Create the socket. */ |
/* Start a Unix listener on auth_sock_name. */ |
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0); |
if (sock < 0) { |
|
error("socket: %.100s", strerror(errno)); |
|
restore_uid(); |
|
goto authsock_err; |
|
} |
|
|
|
/* Bind it to the name. */ |
|
memset(&sunaddr, 0, sizeof(sunaddr)); |
|
sunaddr.sun_family = AF_UNIX; |
|
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); |
|
|
|
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { |
|
error("bind: %.100s", strerror(errno)); |
|
restore_uid(); |
|
goto authsock_err; |
|
} |
|
|
|
/* Restore the privileged uid. */ |
/* Restore the privileged uid. */ |
restore_uid(); |
restore_uid(); |
|
|
/* Start listening on the socket. */ |
/* Check for socket/bind/listen failure. */ |
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { |
if (sock < 0) |
error("listen: %.100s", strerror(errno)); |
|
goto authsock_err; |
goto authsock_err; |
} |
|
|
|
/* Allocate a channel for the authentication agent socket. */ |
/* Allocate a channel for the authentication agent socket. */ |
/* this shouldn't matter if its hpn or not - cjr */ |
/* this shouldn't matter if its hpn or not - cjr */ |
Line 262 do_authenticated(Authctxt *authctxt) |
|
Line 244 do_authenticated(Authctxt *authctxt) |
|
setproctitle("%s", authctxt->pw->pw_name); |
setproctitle("%s", authctxt->pw->pw_name); |
|
|
/* setup the channel layer */ |
/* setup the channel layer */ |
|
/* XXX - streamlocal? */ |
if (no_port_forwarding_flag || |
if (no_port_forwarding_flag || |
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) |
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) |
channel_disable_adm_local_opens(); |
channel_disable_adm_local_opens(); |
Line 381 do_authenticated1(Authctxt *authctxt) |
|
Line 364 do_authenticated1(Authctxt *authctxt) |
|
} |
} |
debug("Received TCP/IP port forwarding request."); |
debug("Received TCP/IP port forwarding request."); |
if (channel_input_port_forward_request(s->pw->pw_uid == 0, |
if (channel_input_port_forward_request(s->pw->pw_uid == 0, |
options.gateway_ports) < 0) { |
&options.fwd_opts) < 0) { |
debug("Port forwarding failed."); |
debug("Port forwarding failed."); |
break; |
break; |
} |
} |
Line 482 do_authenticated1(Authctxt *authctxt) |
|
Line 465 do_authenticated1(Authctxt *authctxt) |
|
} |
} |
} |
} |
|
|
#define USE_PIPES |
#define USE_PIPES 1 |
/* |
/* |
* This is called to fork and execute a command when we have no tty. This |
* This is called to fork and execute a command when we have no tty. This |
* will call do_child from the child, and server_loop from the parent after |
* will call do_child from the child, and server_loop from the parent after |
|
|
do_exec(Session *s, const char *command) |
do_exec(Session *s, const char *command) |
{ |
{ |
int ret; |
int ret; |
|
const char *forced = NULL; |
|
char session_type[1024], *tty = NULL; |
|
|
if (options.adm_forced_command) { |
if (options.adm_forced_command) { |
original_command = command; |
original_command = command; |
command = options.adm_forced_command; |
command = options.adm_forced_command; |
if (IS_INTERNAL_SFTP(command)) { |
forced = "(config)"; |
s->is_subsystem = s->is_subsystem ? |
|
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR; |
|
} else if (s->is_subsystem) |
|
s->is_subsystem = SUBSYSTEM_EXT; |
|
debug("Forced command (config) '%.900s'", command); |
|
} else if (forced_command) { |
} else if (forced_command) { |
original_command = command; |
original_command = command; |
command = forced_command; |
command = forced_command; |
|
forced = "(key-option)"; |
|
} |
|
if (forced != NULL) { |
if (IS_INTERNAL_SFTP(command)) { |
if (IS_INTERNAL_SFTP(command)) { |
s->is_subsystem = s->is_subsystem ? |
s->is_subsystem = s->is_subsystem ? |
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR; |
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR; |
} else if (s->is_subsystem) |
} else if (s->is_subsystem) |
s->is_subsystem = SUBSYSTEM_EXT; |
s->is_subsystem = SUBSYSTEM_EXT; |
debug("Forced command (key option) '%.900s'", command); |
snprintf(session_type, sizeof(session_type), |
|
"forced-command %s '%.900s'", forced, command); |
|
} else if (s->is_subsystem) { |
|
snprintf(session_type, sizeof(session_type), |
|
"subsystem '%.900s'", s->subsys); |
|
} else if (command == NULL) { |
|
snprintf(session_type, sizeof(session_type), "shell"); |
|
} else { |
|
/* NB. we don't log unforced commands to preserve privacy */ |
|
snprintf(session_type, sizeof(session_type), "command"); |
|
} |
|
|
|
if (s->ttyfd != -1) { |
|
tty = s->tty; |
|
if (strncmp(tty, "/dev/", 5) == 0) |
|
tty += 5; |
} |
} |
|
|
|
verbose("Starting session: %s%s%s for %s from %.200s port %d", |
|
session_type, |
|
tty == NULL ? "" : " on ", |
|
tty == NULL ? "" : tty, |
|
s->pw->pw_name, |
|
get_remote_ipaddr(), |
|
get_remote_port()); |
|
|
#ifdef GSSAPI |
#ifdef GSSAPI |
if (options.gss_authentication) { |
if (options.gss_authentication) { |
temporarily_use_uid(s->pw); |
temporarily_use_uid(s->pw); |
Line 943 child_set_env(char ***envp, u_int *envsi |
|
Line 949 child_set_env(char ***envp, u_int *envsi |
|
u_int envsize; |
u_int envsize; |
u_int i, namelen; |
u_int i, namelen; |
|
|
|
if (strchr(name, '=') != NULL) { |
|
error("Invalid environment variable \"%.100s\"", name); |
|
return; |
|
} |
|
|
/* |
/* |
* Find the slot where the value should be stored. If the variable |
* Find the slot where the value should be stored. If the variable |
* already exists, we reuse the slot; otherwise we append a new slot |
* already exists, we reuse the slot; otherwise we append a new slot |
Line 1261 do_rc_files(Session *s, const char *shel |
|
Line 1272 do_rc_files(Session *s, const char *shel |
|
|
|
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ |
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ |
if (!s->is_subsystem && options.adm_forced_command == NULL && |
if (!s->is_subsystem && options.adm_forced_command == NULL && |
!no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) { |
!no_user_rc && options.permit_user_rc && |
|
stat(_PATH_SSH_USER_RC, &st) >= 0) { |
snprintf(cmd, sizeof cmd, "%s -c '%s %s'", |
snprintf(cmd, sizeof cmd, "%s -c '%s %s'", |
shell, _PATH_BSHELL, _PATH_SSH_USER_RC); |
shell, _PATH_BSHELL, _PATH_SSH_USER_RC); |
if (debug_flag) |
if (debug_flag) |
Line 1766 session_unused(int id) |
|
Line 1778 session_unused(int id) |
|
fatal("%s: insane session id %d (max %d nalloc %d)", |
fatal("%s: insane session id %d (max %d nalloc %d)", |
__func__, id, options.max_sessions, sessions_nalloc); |
__func__, id, options.max_sessions, sessions_nalloc); |
} |
} |
bzero(&sessions[id], sizeof(*sessions)); |
memset(&sessions[id], 0, sizeof(*sessions)); |
sessions[id].self = id; |
sessions[id].self = id; |
sessions[id].used = 0; |
sessions[id].used = 0; |
sessions[id].chanid = -1; |
sessions[id].chanid = -1; |
Line 1944 session_pty_req(Session *s) |
|
Line 1956 session_pty_req(Session *s) |
|
u_int len; |
u_int len; |
int n_bytes; |
int n_bytes; |
|
|
if (no_pty_flag) { |
if (no_pty_flag || !options.permit_tty) { |
debug("Allocating a pty not permitted for this authentication."); |
debug("Allocating a pty not permitted for this authentication."); |
return 0; |
return 0; |
} |
} |
Line 2005 session_subsystem_req(Session *s) |
|
Line 2017 session_subsystem_req(Session *s) |
|
struct stat st; |
struct stat st; |
u_int len; |
u_int len; |
int success = 0; |
int success = 0; |
char *prog, *cmd, *subsys = packet_get_string(&len); |
char *prog, *cmd; |
u_int i; |
u_int i; |
|
|
|
s->subsys = packet_get_string(&len); |
packet_check_eom(); |
packet_check_eom(); |
logit("subsystem request for %.100s by user %s", subsys, |
debug2("subsystem request for %.100s by user %s", s->subsys, |
s->pw->pw_name); |
s->pw->pw_name); |
|
|
for (i = 0; i < options.num_subsystems; i++) { |
for (i = 0; i < options.num_subsystems; i++) { |
if (strcmp(subsys, options.subsystem_name[i]) == 0) { |
if (strcmp(s->subsys, options.subsystem_name[i]) == 0) { |
prog = options.subsystem_command[i]; |
prog = options.subsystem_command[i]; |
cmd = options.subsystem_args[i]; |
cmd = options.subsystem_args[i]; |
if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) { |
if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) { |
Line 2032 session_subsystem_req(Session *s) |
|
Line 2045 session_subsystem_req(Session *s) |
|
} |
} |
|
|
if (!success) |
if (!success) |
logit("subsystem request for %.100s failed, subsystem not found", |
logit("subsystem request for %.100s by user %s failed, " |
subsys); |
"subsystem not found", s->subsys, s->pw->pw_name); |
|
|
free(subsys); |
|
return success; |
return success; |
} |
} |
|
|
Line 2102 session_env_req(Session *s) |
|
Line 2114 session_env_req(Session *s) |
|
char *name, *val; |
char *name, *val; |
u_int name_len, val_len, i; |
u_int name_len, val_len, i; |
|
|
name = packet_get_string(&name_len); |
name = packet_get_cstring(&name_len); |
val = packet_get_string(&val_len); |
val = packet_get_cstring(&val_len); |
packet_check_eom(); |
packet_check_eom(); |
|
|
/* Don't set too many environment variables */ |
/* Don't set too many environment variables */ |
Line 2388 session_close(Session *s) |
|
Line 2400 session_close(Session *s) |
|
free(s->auth_display); |
free(s->auth_display); |
free(s->auth_data); |
free(s->auth_data); |
free(s->auth_proto); |
free(s->auth_proto); |
|
free(s->subsys); |
if (s->env != NULL) { |
if (s->env != NULL) { |
for (i = 0; i < s->num_env; i++) { |
for (i = 0; i < s->num_env; i++) { |
free(s->env[i].name); |
free(s->env[i].name); |
Line 2513 session_setup_x11fwd(Session *s) |
|
Line 2526 session_setup_x11fwd(Session *s) |
|
{ |
{ |
struct stat st; |
struct stat st; |
char display[512], auth_display[512]; |
char display[512], auth_display[512]; |
char hostname[MAXHOSTNAMELEN]; |
char hostname[NI_MAXHOST]; |
u_int i; |
u_int i; |
|
|
if (no_x11_forwarding_flag) { |
if (no_x11_forwarding_flag) { |