Changeset View
Changeset View
Standalone View
Standalone View
crypto/openssh/sshd.c
Show All 37 Lines | |||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
*/ | */ | ||||
#include "includes.h" | #include "includes.h" | ||||
__RCSID("$FreeBSD$"); | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <sys/mman.h> | |||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#ifdef HAVE_SYS_STAT_H | #ifdef HAVE_SYS_STAT_H | ||||
# include <sys/stat.h> | # include <sys/stat.h> | ||||
#endif | #endif | ||||
#ifdef HAVE_SYS_TIME_H | #ifdef HAVE_SYS_TIME_H | ||||
# include <sys/time.h> | # include <sys/time.h> | ||||
#endif | #endif | ||||
#include "openbsd-compat/sys-tree.h" | #include "openbsd-compat/sys-tree.h" | ||||
Show All 23 Lines | |||||
#include "openbsd-compat/openssl-compat.h" | #include "openbsd-compat/openssl-compat.h" | ||||
#endif | #endif | ||||
#ifdef HAVE_SECUREWARE | #ifdef HAVE_SECUREWARE | ||||
#include <sys/security.h> | #include <sys/security.h> | ||||
#include <prot.h> | #include <prot.h> | ||||
#endif | #endif | ||||
#ifdef __FreeBSD__ | |||||
#include <resolv.h> | |||||
#if defined(GSSAPI) && defined(HAVE_GSSAPI_GSSAPI_H) | |||||
#include <gssapi/gssapi.h> | |||||
#elif defined(GSSAPI) && defined(HAVE_GSSAPI_H) | |||||
#include <gssapi.h> | |||||
#endif | |||||
#endif | |||||
#include "xmalloc.h" | #include "xmalloc.h" | ||||
#include "ssh.h" | #include "ssh.h" | ||||
#include "ssh2.h" | #include "ssh2.h" | ||||
#include "sshpty.h" | #include "sshpty.h" | ||||
#include "packet.h" | #include "packet.h" | ||||
#include "log.h" | #include "log.h" | ||||
#include "sshbuf.h" | #include "sshbuf.h" | ||||
#include "misc.h" | #include "misc.h" | ||||
Show All 21 Lines | |||||
#ifdef GSSAPI | #ifdef GSSAPI | ||||
#include "ssh-gss.h" | #include "ssh-gss.h" | ||||
#endif | #endif | ||||
#include "monitor_wrap.h" | #include "monitor_wrap.h" | ||||
#include "ssh-sandbox.h" | #include "ssh-sandbox.h" | ||||
#include "auth-options.h" | #include "auth-options.h" | ||||
#include "version.h" | #include "version.h" | ||||
#include "ssherr.h" | #include "ssherr.h" | ||||
#include "blacklist_client.h" | |||||
#ifdef LIBWRAP | |||||
#include <tcpd.h> | |||||
#include <syslog.h> | |||||
int allow_severity; | |||||
int deny_severity; | |||||
#endif /* LIBWRAP */ | |||||
/* Re-exec fds */ | /* Re-exec fds */ | ||||
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) | #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) | ||||
#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) | #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) | ||||
#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) | #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) | ||||
#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) | #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) | ||||
extern char *__progname; | extern char *__progname; | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | grace_alarm_handler(int sig) | ||||
* Try to kill any processes that we have spawned, E.g. authorized | * Try to kill any processes that we have spawned, E.g. authorized | ||||
* keys command helpers. | * keys command helpers. | ||||
*/ | */ | ||||
if (getpgid(0) == getpid()) { | if (getpgid(0) == getpid()) { | ||||
signal(SIGTERM, SIG_IGN); | signal(SIGTERM, SIG_IGN); | ||||
kill(0, SIGTERM); | kill(0, SIGTERM); | ||||
} | } | ||||
BLACKLIST_NOTIFY(the_active_state, BLACKLIST_AUTH_FAIL, "ssh"); | |||||
/* XXX pre-format ipaddr/port so we don't need to access active_state */ | /* XXX pre-format ipaddr/port so we don't need to access active_state */ | ||||
/* Log error and exit. */ | /* Log error and exit. */ | ||||
sigdie("Timeout before authentication for %s port %d", | sigdie("Timeout before authentication for %s port %d", | ||||
ssh_remote_ipaddr(the_active_state), | ssh_remote_ipaddr(the_active_state), | ||||
ssh_remote_port(the_active_state)); | ssh_remote_port(the_active_state)); | ||||
} | } | ||||
/* Destroy the host and server keys. They will no longer be needed. */ | /* Destroy the host and server keys. They will no longer be needed. */ | ||||
void | void | ||||
▲ Show 20 Lines • Show All 447 Lines • ▼ Show 20 Lines | drop_connection(int startups) | ||||
debug("drop_connection: p %d, r %d", p, r); | debug("drop_connection: p %d, r %d", p, r); | ||||
return (r < p) ? 1 : 0; | return (r < p) ? 1 : 0; | ||||
} | } | ||||
static void | static void | ||||
usage(void) | usage(void) | ||||
{ | { | ||||
fprintf(stderr, "%s, %s\n", | if (options.version_addendum && *options.version_addendum != '\0') | ||||
fprintf(stderr, "%s %s, %s\n", | |||||
SSH_RELEASE, | SSH_RELEASE, | ||||
#ifdef WITH_OPENSSL | options.version_addendum, OPENSSL_VERSION_STRING); | ||||
OpenSSL_version(OPENSSL_VERSION) | else | ||||
#else | fprintf(stderr, "%s, %s\n", | ||||
"without OpenSSL" | SSH_RELEASE, OPENSSL_VERSION_STRING); | ||||
#endif | |||||
); | |||||
fprintf(stderr, | fprintf(stderr, | ||||
"usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n" | "usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n" | ||||
" [-E log_file] [-f config_file] [-g login_grace_time]\n" | " [-E log_file] [-f config_file] [-g login_grace_time]\n" | ||||
" [-h host_key_file] [-o option] [-p port] [-u len]\n" | " [-h host_key_file] [-o option] [-p port] [-u len]\n" | ||||
); | ); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
* Listen for TCP connections | * Listen for TCP connections | ||||
*/ | */ | ||||
static void | static void | ||||
listen_on_addrs(struct listenaddr *la) | listen_on_addrs(struct listenaddr *la) | ||||
{ | { | ||||
int ret, listen_sock; | int ret, listen_sock; | ||||
struct addrinfo *ai; | struct addrinfo *ai; | ||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | ||||
int socksize; | |||||
socklen_t len; | |||||
for (ai = la->addrs; ai; ai = ai->ai_next) { | for (ai = la->addrs; ai; ai = ai->ai_next) { | ||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | ||||
continue; | continue; | ||||
if (num_listen_socks >= MAX_LISTEN_SOCKS) | if (num_listen_socks >= MAX_LISTEN_SOCKS) | ||||
fatal("Too many listen sockets. " | fatal("Too many listen sockets. " | ||||
"Enlarge MAX_LISTEN_SOCKS"); | "Enlarge MAX_LISTEN_SOCKS"); | ||||
if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, | if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, | ||||
Show All 29 Lines | for (ai = la->addrs; ai; ai = ai->ai_next) { | ||||
} | } | ||||
/* Only communicate in IPv6 over AF_INET6 sockets. */ | /* Only communicate in IPv6 over AF_INET6 sockets. */ | ||||
if (ai->ai_family == AF_INET6) | if (ai->ai_family == AF_INET6) | ||||
sock_set_v6only(listen_sock); | sock_set_v6only(listen_sock); | ||||
debug("Bind to port %s on %s.", strport, ntop); | debug("Bind to port %s on %s.", strport, ntop); | ||||
len = sizeof(socksize); | |||||
getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, &socksize, &len); | |||||
debug("Server TCP RWIN socket size: %d", socksize); | |||||
/* Bind the socket to the desired port. */ | /* Bind the socket to the desired port. */ | ||||
if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { | if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { | ||||
error("Bind to port %s on %s failed: %.200s.", | error("Bind to port %s on %s failed: %.200s.", | ||||
strport, ntop, strerror(errno)); | strport, ntop, strerror(errno)); | ||||
close(listen_sock); | close(listen_sock); | ||||
continue; | continue; | ||||
} | } | ||||
listen_socks[num_listen_socks] = listen_sock; | listen_socks[num_listen_socks] = listen_sock; | ||||
▲ Show 20 Lines • Show All 887 Lines • ▼ Show 20 Lines | if (!(debug_flag || inetd_flag || no_daemon_flag || already_daemon)) { | ||||
if (daemon(0, 0) < 0) | if (daemon(0, 0) < 0) | ||||
fatal("daemon() failed: %.200s", strerror(errno)); | fatal("daemon() failed: %.200s", strerror(errno)); | ||||
disconnect_controlling_tty(); | disconnect_controlling_tty(); | ||||
} | } | ||||
/* Reinitialize the log (because of the fork above). */ | /* Reinitialize the log (because of the fork above). */ | ||||
log_init(__progname, options.log_level, options.log_facility, log_stderr); | log_init(__progname, options.log_level, options.log_facility, log_stderr); | ||||
/* Avoid killing the process in high-pressure swapping environments. */ | |||||
if (!inetd_flag && madvise(NULL, 0, MADV_PROTECT) != 0) | |||||
debug("madvise(): %.200s", strerror(errno)); | |||||
/* Chdir to the root directory so that the current disk can be | /* Chdir to the root directory so that the current disk can be | ||||
unmounted if desired. */ | unmounted if desired. */ | ||||
if (chdir("/") == -1) | if (chdir("/") == -1) | ||||
error("chdir(\"/\"): %s", strerror(errno)); | error("chdir(\"/\"): %s", strerror(errno)); | ||||
/* ignore SIGPIPE */ | /* ignore SIGPIPE */ | ||||
signal(SIGPIPE, SIG_IGN); | signal(SIGPIPE, SIG_IGN); | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | #endif | ||||
alarm(0); | alarm(0); | ||||
signal(SIGALRM, SIG_DFL); | signal(SIGALRM, SIG_DFL); | ||||
signal(SIGHUP, SIG_DFL); | signal(SIGHUP, SIG_DFL); | ||||
signal(SIGTERM, SIG_DFL); | signal(SIGTERM, SIG_DFL); | ||||
signal(SIGQUIT, SIG_DFL); | signal(SIGQUIT, SIG_DFL); | ||||
signal(SIGCHLD, SIG_DFL); | signal(SIGCHLD, SIG_DFL); | ||||
signal(SIGINT, SIG_DFL); | signal(SIGINT, SIG_DFL); | ||||
#ifdef __FreeBSD__ | |||||
/* | /* | ||||
* Initialize the resolver. This may not happen automatically | |||||
* before privsep chroot(). | |||||
*/ | |||||
if ((_res.options & RES_INIT) == 0) { | |||||
debug("res_init()"); | |||||
res_init(); | |||||
} | |||||
#ifdef GSSAPI | |||||
/* | |||||
* Force GSS-API to parse its configuration and load any | |||||
* mechanism plugins. | |||||
*/ | |||||
{ | |||||
gss_OID_set mechs; | |||||
OM_uint32 minor_status; | |||||
gss_indicate_mechs(&minor_status, &mechs); | |||||
gss_release_oid_set(&minor_status, &mechs); | |||||
} | |||||
#endif | |||||
#endif | |||||
/* | |||||
* Register our connection. This turns encryption off because we do | * Register our connection. This turns encryption off because we do | ||||
* not have a key. | * not have a key. | ||||
*/ | */ | ||||
if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) | if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) | ||||
fatal("Unable to create connection"); | fatal("Unable to create connection"); | ||||
the_active_state = ssh; | the_active_state = ssh; | ||||
ssh_packet_set_server(ssh); | ssh_packet_set_server(ssh); | ||||
Show All 19 Lines | #endif | ||||
/* | /* | ||||
* The rest of the code depends on the fact that | * The rest of the code depends on the fact that | ||||
* ssh_remote_ipaddr() caches the remote ip, even if | * ssh_remote_ipaddr() caches the remote ip, even if | ||||
* the socket goes away. | * the socket goes away. | ||||
*/ | */ | ||||
remote_ip = ssh_remote_ipaddr(ssh); | remote_ip = ssh_remote_ipaddr(ssh); | ||||
#ifdef HAVE_LOGIN_CAP | |||||
/* Also caches remote hostname for sandboxed child. */ | |||||
auth_get_canonical_hostname(ssh, options.use_dns); | |||||
#endif | |||||
#ifdef SSH_AUDIT_EVENTS | #ifdef SSH_AUDIT_EVENTS | ||||
audit_connection_from(remote_ip, remote_port); | audit_connection_from(remote_ip, remote_port); | ||||
#endif | #endif | ||||
#ifdef LIBWRAP | |||||
allow_severity = options.log_facility|LOG_INFO; | |||||
deny_severity = options.log_facility|LOG_WARNING; | |||||
/* Check whether logins are denied from this host. */ | |||||
if (ssh_packet_connection_is_on_socket(ssh)) { | |||||
struct request_info req; | |||||
request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); | |||||
fromhost(&req); | |||||
if (!hosts_access(&req)) { | |||||
debug("Connection refused by tcp wrapper"); | |||||
refuse(&req); | |||||
/* NOTREACHED */ | |||||
fatal("libwrap refuse returns"); | |||||
} | |||||
} | |||||
#endif /* LIBWRAP */ | |||||
rdomain = ssh_packet_rdomain_in(ssh); | rdomain = ssh_packet_rdomain_in(ssh); | ||||
/* Log the connection. */ | /* Log the connection. */ | ||||
laddr = get_local_ipaddr(sock_in); | laddr = get_local_ipaddr(sock_in); | ||||
verbose("Connection from %s port %d on %s port %d%s%s%s", | verbose("Connection from %s port %d on %s port %d%s%s%s", | ||||
remote_ip, remote_port, laddr, ssh_local_port(ssh), | remote_ip, remote_port, laddr, ssh_local_port(ssh), | ||||
rdomain == NULL ? "" : " rdomain \"", | rdomain == NULL ? "" : " rdomain \"", | ||||
rdomain == NULL ? "" : rdomain, | rdomain == NULL ? "" : rdomain, | ||||
Show All 29 Lines | #endif /* LIBWRAP */ | ||||
/* Set default key authentication options */ | /* Set default key authentication options */ | ||||
if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL) | if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL) | ||||
fatal("allocation failed"); | fatal("allocation failed"); | ||||
/* prepare buffer to collect messages to display to user after login */ | /* prepare buffer to collect messages to display to user after login */ | ||||
if ((loginmsg = sshbuf_new()) == NULL) | if ((loginmsg = sshbuf_new()) == NULL) | ||||
fatal("%s: sshbuf_new failed", __func__); | fatal("%s: sshbuf_new failed", __func__); | ||||
auth_debug_reset(); | auth_debug_reset(); | ||||
BLACKLIST_INIT(); | |||||
if (use_privsep) { | if (use_privsep) { | ||||
if (privsep_preauth(ssh) == 1) | if (privsep_preauth(ssh) == 1) | ||||
goto authenticated; | goto authenticated; | ||||
} else if (have_agent) { | } else if (have_agent) { | ||||
if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { | if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { | ||||
error("Unable to get agent socket: %s", ssh_err(r)); | error("Unable to get agent socket: %s", ssh_err(r)); | ||||
have_agent = 0; | have_agent = 0; | ||||
▲ Show 20 Lines • Show All 214 Lines • Show Last 20 Lines |