version 1.263, 2003/02/16 17:09:57 |
version 1.263.2.1, 2003/09/16 20:50:44 |
|
|
|
|
/* same for ssh2 */ |
/* same for ssh2 */ |
u_char *session_id2 = NULL; |
u_char *session_id2 = NULL; |
int session_id2_len = 0; |
u_int session_id2_len = 0; |
|
|
/* record remote hostname or ip */ |
/* record remote hostname or ip */ |
u_int utmp_len = MAXHOSTNAMELEN; |
u_int utmp_len = MAXHOSTNAMELEN; |
|
|
static void |
static void |
sighup_restart(void) |
sighup_restart(void) |
{ |
{ |
log("Received SIGHUP; restarting."); |
logit("Received SIGHUP; restarting."); |
close_listen_socks(); |
close_listen_socks(); |
close_startup_pipes(); |
close_startup_pipes(); |
execv(saved_argv[0], saved_argv); |
execv(saved_argv[0], saved_argv); |
log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], |
logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], |
strerror(errno)); |
strerror(errno)); |
exit(1); |
exit(1); |
} |
} |
|
|
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); |
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); |
server_version_string = xstrdup(buf); |
server_version_string = xstrdup(buf); |
|
|
if (client_version_string == NULL) { |
/* Send our protocol version identification. */ |
/* Send our protocol version identification. */ |
if (atomicio(vwrite, sock_out, server_version_string, |
if (atomicio(write, sock_out, server_version_string, |
strlen(server_version_string)) |
strlen(server_version_string)) |
!= strlen(server_version_string)) { |
!= strlen(server_version_string)) { |
logit("Could not write ident string to %s", get_remote_ipaddr()); |
log("Could not write ident string to %s", get_remote_ipaddr()); |
fatal_cleanup(); |
|
} |
|
|
|
/* 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) { |
|
logit("Did not receive identification string from %s", |
|
get_remote_ipaddr()); |
fatal_cleanup(); |
fatal_cleanup(); |
} |
} |
|
if (buf[i] == '\r') { |
/* Read other sides version identification. */ |
buf[i] = 0; |
memset(buf, 0, sizeof(buf)); |
/* Kludge for F-Secure Macintosh < 1.0.2 */ |
for (i = 0; i < sizeof(buf) - 1; i++) { |
if (i == 12 && |
if (atomicio(read, sock_in, &buf[i], 1) != 1) { |
strncmp(buf, "SSH-1.5-W1.0", 12) == 0) |
log("Did not receive identification string from %s", |
|
get_remote_ipaddr()); |
|
fatal_cleanup(); |
|
} |
|
if (buf[i] == '\r') { |
|
buf[i] = 0; |
|
/* Kludge for F-Secure Macintosh < 1.0.2 */ |
|
if (i == 12 && |
|
strncmp(buf, "SSH-1.5-W1.0", 12) == 0) |
|
break; |
|
continue; |
|
} |
|
if (buf[i] == '\n') { |
|
buf[i] = 0; |
|
break; |
break; |
} |
continue; |
} |
} |
buf[sizeof(buf) - 1] = 0; |
if (buf[i] == '\n') { |
client_version_string = xstrdup(buf); |
buf[i] = 0; |
|
break; |
|
} |
} |
} |
|
buf[sizeof(buf) - 1] = 0; |
|
client_version_string = xstrdup(buf); |
|
|
/* |
/* |
* Check that the versions match. In future this might accept |
* Check that the versions match. In future this might accept |
|
|
if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", |
if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", |
&remote_major, &remote_minor, remote_version) != 3) { |
&remote_major, &remote_minor, remote_version) != 3) { |
s = "Protocol mismatch.\n"; |
s = "Protocol mismatch.\n"; |
(void) atomicio(write, sock_out, s, strlen(s)); |
(void) atomicio(vwrite, sock_out, s, strlen(s)); |
close(sock_in); |
close(sock_in); |
close(sock_out); |
close(sock_out); |
log("Bad protocol version identification '%.100s' from %s", |
logit("Bad protocol version identification '%.100s' from %s", |
client_version_string, get_remote_ipaddr()); |
client_version_string, get_remote_ipaddr()); |
fatal_cleanup(); |
fatal_cleanup(); |
} |
} |
|
|
compat_datafellows(remote_version); |
compat_datafellows(remote_version); |
|
|
if (datafellows & SSH_BUG_PROBE) { |
if (datafellows & SSH_BUG_PROBE) { |
log("probed from %s with %s. Don't panic.", |
logit("probed from %s with %s. Don't panic.", |
get_remote_ipaddr(), client_version_string); |
get_remote_ipaddr(), client_version_string); |
fatal_cleanup(); |
fatal_cleanup(); |
} |
} |
|
|
if (datafellows & SSH_BUG_SCANNER) { |
if (datafellows & SSH_BUG_SCANNER) { |
log("scanned from %s with %s. Don't panic.", |
logit("scanned from %s with %s. Don't panic.", |
get_remote_ipaddr(), client_version_string); |
get_remote_ipaddr(), client_version_string); |
fatal_cleanup(); |
fatal_cleanup(); |
} |
} |
|
|
|
|
if (mismatch) { |
if (mismatch) { |
s = "Protocol major versions differ.\n"; |
s = "Protocol major versions differ.\n"; |
(void) atomicio(write, sock_out, s, strlen(s)); |
(void) atomicio(vwrite, sock_out, s, strlen(s)); |
close(sock_in); |
close(sock_in); |
close(sock_out); |
close(sock_out); |
log("Protocol major versions differ for %s: %.200s vs. %.200s", |
logit("Protocol major versions differ for %s: %.200s vs. %.200s", |
get_remote_ipaddr(), |
get_remote_ipaddr(), |
server_version_string, client_version_string); |
server_version_string, client_version_string); |
fatal_cleanup(); |
fatal_cleanup(); |
|
|
do_setusercontext(pw); |
do_setusercontext(pw); |
#else |
#else |
gidset[0] = pw->pw_gid; |
gidset[0] = pw->pw_gid; |
if (setgid(pw->pw_gid) < 0) |
|
fatal("setgid failed for %u", pw->pw_gid ); |
|
if (setgroups(1, gidset) < 0) |
if (setgroups(1, gidset) < 0) |
fatal("setgroups: %.100s", strerror(errno)); |
fatal("setgroups: %.100s", strerror(errno)); |
permanently_set_uid(pw); |
permanently_set_uid(pw); |
|
|
initialize_server_options(&options); |
initialize_server_options(&options); |
|
|
/* Parse command-line arguments. */ |
/* Parse command-line arguments. */ |
while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) { |
while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqtQ46")) != -1) { |
switch (opt) { |
switch (opt) { |
case '4': |
case '4': |
IPv4or6 = AF_INET; |
IPv4or6 = AF_INET; |
|
|
config_file_name = optarg; |
config_file_name = optarg; |
break; |
break; |
case 'd': |
case 'd': |
if (0 == debug_flag) { |
if (debug_flag == 0) { |
debug_flag = 1; |
debug_flag = 1; |
options.log_level = SYSLOG_LEVEL_DEBUG1; |
options.log_level = SYSLOG_LEVEL_DEBUG1; |
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { |
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) |
options.log_level++; |
options.log_level++; |
} else { |
|
fprintf(stderr, "Too high debugging level.\n"); |
|
exit(1); |
|
} |
|
break; |
break; |
case 'D': |
case 'D': |
no_daemon_flag = 1; |
no_daemon_flag = 1; |
|
|
} |
} |
options.host_key_files[options.num_host_key_files++] = optarg; |
options.host_key_files[options.num_host_key_files++] = optarg; |
break; |
break; |
case 'V': |
|
client_version_string = optarg; |
|
/* only makes sense with inetd_flag, i.e. no listen() */ |
|
inetd_flag = 1; |
|
break; |
|
case 't': |
case 't': |
test_flag = 1; |
test_flag = 1; |
break; |
break; |
|
|
key_type(key)); |
key_type(key)); |
} |
} |
if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { |
if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { |
log("Disabling protocol version 1. Could not load host key"); |
logit("Disabling protocol version 1. Could not load host key"); |
options.protocol &= ~SSH_PROTO_1; |
options.protocol &= ~SSH_PROTO_1; |
} |
} |
if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { |
if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { |
log("Disabling protocol version 2. Could not load host key"); |
logit("Disabling protocol version 2. Could not load host key"); |
options.protocol &= ~SSH_PROTO_2; |
options.protocol &= ~SSH_PROTO_2; |
} |
} |
if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { |
if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { |
log("sshd: no hostkeys available -- exiting."); |
logit("sshd: no hostkeys available -- exiting."); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
continue; |
continue; |
} |
} |
/* Create socket for listening. */ |
/* Create socket for listening. */ |
listen_sock = socket(ai->ai_family, SOCK_STREAM, 0); |
listen_sock = socket(ai->ai_family, ai->ai_socktype, |
|
ai->ai_protocol); |
if (listen_sock < 0) { |
if (listen_sock < 0) { |
/* kernel may not support ipv6 */ |
/* kernel may not support ipv6 */ |
verbose("socket: %.100s", strerror(errno)); |
verbose("socket: %.100s", strerror(errno)); |
|
|
num_listen_socks++; |
num_listen_socks++; |
|
|
/* Start listening on the port. */ |
/* Start listening on the port. */ |
log("Server listening on %s port %s.", ntop, strport); |
logit("Server listening on %s port %s.", ntop, strport); |
if (listen(listen_sock, 5) < 0) |
if (listen(listen_sock, 5) < 0) |
fatal("listen: %.100s", strerror(errno)); |
fatal("listen: %.100s", strerror(errno)); |
|
|
|
|
* overwrite any old pid in the file. |
* overwrite any old pid in the file. |
*/ |
*/ |
f = fopen(options.pid_file, "w"); |
f = fopen(options.pid_file, "w"); |
if (f) { |
if (f == NULL) { |
|
error("Couldn't create pid file \"%s\": %s", |
|
options.pid_file, strerror(errno)); |
|
} else { |
fprintf(f, "%ld\n", (long) getpid()); |
fprintf(f, "%ld\n", (long) getpid()); |
fclose(f); |
fclose(f); |
} |
} |
|
|
if (ret < 0 && errno != EINTR) |
if (ret < 0 && errno != EINTR) |
error("select: %.100s", strerror(errno)); |
error("select: %.100s", strerror(errno)); |
if (received_sigterm) { |
if (received_sigterm) { |
log("Received signal %d; terminating.", |
logit("Received signal %d; terminating.", |
(int) received_sigterm); |
(int) received_sigterm); |
close_listen_socks(); |
close_listen_socks(); |
unlink(options.pid_file); |
unlink(options.pid_file); |
|
|
alarm(options.login_grace_time); |
alarm(options.login_grace_time); |
|
|
sshd_exchange_identification(sock_in, sock_out); |
sshd_exchange_identification(sock_in, sock_out); |
/* |
|
* Check that the connection comes from a privileged port. |
|
* Rhosts-Authentication only makes sense from privileged |
|
* programs. Of course, if the intruder has root access on his local |
|
* machine, he can connect from any port. So do not use these |
|
* authentication methods from machines that you do not trust. |
|
*/ |
|
if (options.rhosts_authentication && |
|
(remote_port >= IPPORT_RESERVED || |
|
remote_port < IPPORT_RESERVED / 2)) { |
|
debug("Rhosts Authentication disabled, " |
|
"originating port %d not trusted.", remote_port); |
|
options.rhosts_authentication = 0; |
|
} |
|
#if defined(KRB4) && !defined(KRB5) |
|
if (!packet_connection_is_ipv4() && |
|
options.kerberos_authentication) { |
|
debug("Kerberos Authentication disabled, only available for IPv4."); |
|
options.kerberos_authentication = 0; |
|
} |
|
#endif /* KRB4 && !KRB5 */ |
|
#ifdef AFS |
|
/* If machine has AFS, set process authentication group. */ |
|
if (k_hasafs()) { |
|
k_setpag(); |
|
k_unlog(); |
|
} |
|
#endif /* AFS */ |
|
|
|
packet_set_nonblocking(); |
packet_set_nonblocking(); |
|
|
|
|
|
|
/* Declare supported authentication types. */ |
/* Declare supported authentication types. */ |
auth_mask = 0; |
auth_mask = 0; |
if (options.rhosts_authentication) |
|
auth_mask |= 1 << SSH_AUTH_RHOSTS; |
|
if (options.rhosts_rsa_authentication) |
if (options.rhosts_rsa_authentication) |
auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA; |
auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA; |
if (options.rsa_authentication) |
if (options.rsa_authentication) |
auth_mask |= 1 << SSH_AUTH_RSA; |
auth_mask |= 1 << SSH_AUTH_RSA; |
#if defined(KRB4) || defined(KRB5) |
|
if (options.kerberos_authentication) |
|
auth_mask |= 1 << SSH_AUTH_KERBEROS; |
|
#endif |
|
#if defined(AFS) || defined(KRB5) |
|
if (options.kerberos_tgt_passing) |
|
auth_mask |= 1 << SSH_PASS_KERBEROS_TGT; |
|
#endif |
|
#ifdef AFS |
|
if (options.afs_token_passing) |
|
auth_mask |= 1 << SSH_PASS_AFS_TOKEN; |
|
#endif |
|
if (options.challenge_response_authentication == 1) |
if (options.challenge_response_authentication == 1) |
auth_mask |= 1 << SSH_AUTH_TIS; |
auth_mask |= 1 << SSH_AUTH_TIS; |
if (options.password_authentication) |
if (options.password_authentication) |
|
|
u_char *buf = xmalloc(bytes); |
u_char *buf = xmalloc(bytes); |
MD5_CTX md; |
MD5_CTX md; |
|
|
log("do_connection: generating a fake encryption key"); |
logit("do_connection: generating a fake encryption key"); |
BN_bn2bin(session_key_int, buf); |
BN_bn2bin(session_key_int, buf); |
MD5_Init(&md); |
MD5_Init(&md); |
MD5_Update(&md, buf, bytes); |
MD5_Update(&md, buf, bytes); |