-/* $OpenBSD: sshd.c,v 1.360 2008/06/12 20:38:28 dtucker Exp $ */
+/* $OpenBSD: sshd.c,v 1.369 2010/01/09 11:17:56 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
-#include "monitor_fdpass.h"
+#include "roaming.h"
#include "version.h"
#ifdef LIBWRAP
close_listen_socks();
close_startup_pipes();
alarm(0); /* alarm timer persists across exec */
+ signal(SIGHUP, SIG_IGN); /* will be restored after exec */
execv(saved_argv[0], saved_argv);
logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
strerror(errno));
int mismatch;
int remote_major, remote_minor;
int major, minor;
- char *s;
+ char *s, *newline = "\n";
char buf[256]; /* Must not be larger than remote_version. */
char remote_version[256]; /* Must be at least as big as buf. */
} else if (options.protocol & SSH_PROTO_2) {
major = PROTOCOL_MAJOR_2;
minor = PROTOCOL_MINOR_2;
+ newline = "\r\n";
} else {
major = PROTOCOL_MAJOR_1;
minor = PROTOCOL_MINOR_1;
}
- snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION);
+ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+ SSH_VERSION, newline);
server_version_string = xstrdup(buf);
/* Send our protocol version identification. */
- if (atomicio(vwrite, sock_out, server_version_string,
+ if (roaming_atomicio(vwrite, sock_out, server_version_string,
strlen(server_version_string))
!= strlen(server_version_string)) {
logit("Could not write ident string to %s", get_remote_ipaddr());
/* Read other sides version identification. */
memset(buf, 0, sizeof(buf));
for (i = 0; i < sizeof(buf) - 1; i++) {
- if (atomicio(read, sock_in, &buf[i], 1) != 1) {
+ if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {
logit("Did not receive identification string from %s",
get_remote_ipaddr());
cleanup_exit(255);
static void
privsep_preauth_child(void)
{
- u_int32_t rnd[256];
+ u_int32_t rnd[256];
gid_t gidset[1];
/* Enable challenge-response authentication for privilege separation */
if (pmonitor->m_pid == -1)
fatal("fork of unprivileged child failed");
else if (pmonitor->m_pid != 0) {
- debug2("User child is on pid %ld", (long)pmonitor->m_pid);
+ verbose("User child is on pid %ld", (long)pmonitor->m_pid);
close(pmonitor->m_recvfd);
buffer_clear(&loginmsg);
monitor_child_postauth(pmonitor);
continue;
}
/* Create socket for listening. */
- listen_sock = socket(ai->ai_family, ai->ai_socktype,
- ai->ai_protocol);
+ listen_sock = socket_rdomain(ai->ai_family, ai->ai_socktype,
+ ai->ai_protocol, options.rdomain);
if (listen_sock < 0) {
/* kernel may not support ipv6 */
verbose("socket: %.100s", strerror(errno));
&on, sizeof(on)) == -1)
error("setsockopt SO_REUSEADDR: %s", strerror(errno));
-#ifdef IPV6_V6ONLY
/* Only communicate in IPv6 over AF_INET6 sockets. */
- if (ai->ai_family == AF_INET6) {
- if (setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY,
- &on, sizeof(on)) == -1)
- error("setsockopt IPV6_V6ONLY: %s",
- strerror(errno));
- }
-#endif
+ if (ai->ai_family == AF_INET6)
+ sock_set_v6only(listen_sock);
debug("Bind to port %s on %s.", strport, ntop);
*newsock = accept(listen_socks[i],
(struct sockaddr *)&from, &fromlen);
if (*newsock < 0) {
- if (errno != EINTR && errno != EWOULDBLOCK)
+ if (errno != EINTR && errno != EAGAIN &&
+ errno != EWOULDBLOCK)
error("accept: %.100s", strerror(errno));
continue;
}
int remote_port;
char *line, *p, *cp;
int config_s[2] = { -1 , -1 };
+ u_int64_t ibytes, obytes;
+ mode_t new_umask;
Key *key;
Authctxt *authctxt;
exit(1);
}
options.ports[options.num_ports++] = a2port(optarg);
- if (options.ports[options.num_ports-1] == 0) {
+ if (options.ports[options.num_ports-1] <= 0) {
fprintf(stderr, "Bad port number.\n");
exit(1);
}
* the parameters we need. If we're not doing an extended test,
* do not silently ignore connection test params.
*/
- if (test_flag >= 2 && (test_user != NULL || test_host != NULL || test_addr != NULL)
+ if (test_flag >= 2 &&
+ (test_user != NULL || test_host != NULL || test_addr != NULL)
&& (test_user == NULL || test_host == NULL || test_addr == NULL))
fatal("user, host and addr are all required when testing "
"Match configs");
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
- /* set default channel AF */
+ /* set default channel AF and routing domain */
channel_set_af(options.address_family);
+ channel_set_rdomain(options.rdomain);
/* Check that there are no remaining arguments. */
if (optind < ac) {
rexec_argv[rexec_argc + 1] = NULL;
}
+ /* Ensure that umask disallows at least group and world write */
+ new_umask = umask(0077) | 0022;
+ (void) umask(new_umask);
+
/* Initialize the log (it is reinitialized below in case we forked). */
if (debug_flag && (!inetd_flag || rexeced_flag))
log_stderr = 1;
if (inetd_flag) {
server_accept_inetd(&sock_in, &sock_out);
} else {
+ platform_pre_listen();
server_listen();
if (options.protocol & SSH_PROTO_1)
do_authenticated(authctxt);
/* The connection has been terminated. */
- verbose("Closing connection to %.100s", remote_ip);
+ packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+ packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+ verbose("Transferred: sent %llu, received %llu bytes", obytes, ibytes);
+
+ verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
#ifdef USE_PAM
if (options.use_pam)