diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 93 |
1 files changed, 50 insertions, 43 deletions
@@ -42,7 +42,7 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include "includes.h" | 44 | #include "includes.h" |
45 | RCSID("$OpenBSD: sshd.c,v 1.251 2002/06/25 18:51:04 markus Exp $"); | 45 | RCSID("$OpenBSD: sshd.c,v 1.260 2002/09/27 10:42:09 mickey Exp $"); |
46 | 46 | ||
47 | #include <openssl/dh.h> | 47 | #include <openssl/dh.h> |
48 | #include <openssl/bn.h> | 48 | #include <openssl/bn.h> |
@@ -303,11 +303,8 @@ grace_alarm_handler(int sig) | |||
303 | { | 303 | { |
304 | /* XXX no idea how fix this signal handler */ | 304 | /* XXX no idea how fix this signal handler */ |
305 | 305 | ||
306 | /* Close the connection. */ | ||
307 | packet_close(); | ||
308 | |||
309 | /* Log error and exit. */ | 306 | /* Log error and exit. */ |
310 | fatal("Timeout before authentication for %s.", get_remote_ipaddr()); | 307 | fatal("Timeout before authentication for %s", get_remote_ipaddr()); |
311 | } | 308 | } |
312 | 309 | ||
313 | /* | 310 | /* |
@@ -320,7 +317,7 @@ grace_alarm_handler(int sig) | |||
320 | static void | 317 | static void |
321 | generate_ephemeral_server_key(void) | 318 | generate_ephemeral_server_key(void) |
322 | { | 319 | { |
323 | u_int32_t rand = 0; | 320 | u_int32_t rnd = 0; |
324 | int i; | 321 | int i; |
325 | 322 | ||
326 | verbose("Generating %s%d bit RSA key.", | 323 | verbose("Generating %s%d bit RSA key.", |
@@ -333,9 +330,9 @@ generate_ephemeral_server_key(void) | |||
333 | 330 | ||
334 | for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { | 331 | for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { |
335 | if (i % 4 == 0) | 332 | if (i % 4 == 0) |
336 | rand = arc4random(); | 333 | rnd = arc4random(); |
337 | sensitive_data.ssh1_cookie[i] = rand & 0xff; | 334 | sensitive_data.ssh1_cookie[i] = rnd & 0xff; |
338 | rand >>= 8; | 335 | rnd >>= 8; |
339 | } | 336 | } |
340 | arc4random_stir(); | 337 | arc4random_stir(); |
341 | } | 338 | } |
@@ -427,6 +424,12 @@ sshd_exchange_identification(int sock_in, int sock_out) | |||
427 | 424 | ||
428 | compat_datafellows(remote_version); | 425 | compat_datafellows(remote_version); |
429 | 426 | ||
427 | if (datafellows & SSH_BUG_PROBE) { | ||
428 | log("probed from %s with %s. Don't panic.", | ||
429 | get_remote_ipaddr(), client_version_string); | ||
430 | fatal_cleanup(); | ||
431 | } | ||
432 | |||
430 | if (datafellows & SSH_BUG_SCANNER) { | 433 | if (datafellows & SSH_BUG_SCANNER) { |
431 | log("scanned from %s with %s. Don't panic.", | 434 | log("scanned from %s with %s. Don't panic.", |
432 | get_remote_ipaddr(), client_version_string); | 435 | get_remote_ipaddr(), client_version_string); |
@@ -529,8 +532,8 @@ demote_sensitive_data(void) | |||
529 | static void | 532 | static void |
530 | privsep_preauth_child(void) | 533 | privsep_preauth_child(void) |
531 | { | 534 | { |
532 | u_int32_t rand[256]; | 535 | u_int32_t rnd[256]; |
533 | gid_t gidset[2]; | 536 | gid_t gidset[1]; |
534 | struct passwd *pw; | 537 | struct passwd *pw; |
535 | int i; | 538 | int i; |
536 | 539 | ||
@@ -538,8 +541,8 @@ privsep_preauth_child(void) | |||
538 | privsep_challenge_enable(); | 541 | privsep_challenge_enable(); |
539 | 542 | ||
540 | for (i = 0; i < 256; i++) | 543 | for (i = 0; i < 256; i++) |
541 | rand[i] = arc4random(); | 544 | rnd[i] = arc4random(); |
542 | RAND_seed(rand, sizeof(rand)); | 545 | RAND_seed(rnd, sizeof(rnd)); |
543 | 546 | ||
544 | /* Demote the private keys to public keys. */ | 547 | /* Demote the private keys to public keys. */ |
545 | demote_sensitive_data(); | 548 | demote_sensitive_data(); |
@@ -550,7 +553,7 @@ privsep_preauth_child(void) | |||
550 | memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); | 553 | memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); |
551 | endpwent(); | 554 | endpwent(); |
552 | 555 | ||
553 | /* Change our root directory*/ | 556 | /* Change our root directory */ |
554 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) | 557 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) |
555 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, | 558 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, |
556 | strerror(errno)); | 559 | strerror(errno)); |
@@ -573,7 +576,7 @@ privsep_preauth_child(void) | |||
573 | #endif | 576 | #endif |
574 | } | 577 | } |
575 | 578 | ||
576 | static Authctxt* | 579 | static Authctxt * |
577 | privsep_preauth(void) | 580 | privsep_preauth(void) |
578 | { | 581 | { |
579 | Authctxt *authctxt = NULL; | 582 | Authctxt *authctxt = NULL; |
@@ -589,6 +592,8 @@ privsep_preauth(void) | |||
589 | if (pid == -1) { | 592 | if (pid == -1) { |
590 | fatal("fork of unprivileged child failed"); | 593 | fatal("fork of unprivileged child failed"); |
591 | } else if (pid != 0) { | 594 | } else if (pid != 0) { |
595 | fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); | ||
596 | |||
592 | debug2("Network child is on pid %ld", (long)pid); | 597 | debug2("Network child is on pid %ld", (long)pid); |
593 | 598 | ||
594 | close(pmonitor->m_recvfd); | 599 | close(pmonitor->m_recvfd); |
@@ -602,6 +607,10 @@ privsep_preauth(void) | |||
602 | while (waitpid(pid, &status, 0) < 0) | 607 | while (waitpid(pid, &status, 0) < 0) |
603 | if (errno != EINTR) | 608 | if (errno != EINTR) |
604 | break; | 609 | break; |
610 | |||
611 | /* Reinstall, since the child has finished */ | ||
612 | fatal_add_cleanup((void (*) (void *)) packet_close, NULL); | ||
613 | |||
605 | return (authctxt); | 614 | return (authctxt); |
606 | } else { | 615 | } else { |
607 | /* child */ | 616 | /* child */ |
@@ -624,7 +633,7 @@ privsep_postauth(Authctxt *authctxt) | |||
624 | /* XXX - Remote port forwarding */ | 633 | /* XXX - Remote port forwarding */ |
625 | x_authctxt = authctxt; | 634 | x_authctxt = authctxt; |
626 | 635 | ||
627 | #ifdef BROKEN_FD_PASSING | 636 | #ifdef DISABLE_FD_PASSING |
628 | if (1) { | 637 | if (1) { |
629 | #else | 638 | #else |
630 | if (authctxt->pw->pw_uid == 0 || options.use_login) { | 639 | if (authctxt->pw->pw_uid == 0 || options.use_login) { |
@@ -649,6 +658,8 @@ privsep_postauth(Authctxt *authctxt) | |||
649 | if (pmonitor->m_pid == -1) | 658 | if (pmonitor->m_pid == -1) |
650 | fatal("fork of unprivileged child failed"); | 659 | fatal("fork of unprivileged child failed"); |
651 | else if (pmonitor->m_pid != 0) { | 660 | else if (pmonitor->m_pid != 0) { |
661 | fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); | ||
662 | |||
652 | debug2("User child is on pid %ld", (long)pmonitor->m_pid); | 663 | debug2("User child is on pid %ld", (long)pmonitor->m_pid); |
653 | close(pmonitor->m_recvfd); | 664 | close(pmonitor->m_recvfd); |
654 | monitor_child_postauth(pmonitor); | 665 | monitor_child_postauth(pmonitor); |
@@ -801,7 +812,6 @@ main(int ac, char **av) | |||
801 | const char *remote_ip; | 812 | const char *remote_ip; |
802 | int remote_port; | 813 | int remote_port; |
803 | FILE *f; | 814 | FILE *f; |
804 | struct linger linger; | ||
805 | struct addrinfo *ai; | 815 | struct addrinfo *ai; |
806 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 816 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
807 | int listen_sock, maxfd; | 817 | int listen_sock, maxfd; |
@@ -906,6 +916,10 @@ main(int ac, char **av) | |||
906 | break; | 916 | break; |
907 | case 'u': | 917 | case 'u': |
908 | utmp_len = atoi(optarg); | 918 | utmp_len = atoi(optarg); |
919 | if (utmp_len > MAXHOSTNAMELEN) { | ||
920 | fprintf(stderr, "Invalid utmp length.\n"); | ||
921 | exit(1); | ||
922 | } | ||
909 | break; | 923 | break; |
910 | case 'o': | 924 | case 'o': |
911 | if (process_server_config_line(&options, optarg, | 925 | if (process_server_config_line(&options, optarg, |
@@ -932,7 +946,7 @@ main(int ac, char **av) | |||
932 | SYSLOG_FACILITY_AUTH : options.log_facility, | 946 | SYSLOG_FACILITY_AUTH : options.log_facility, |
933 | !inetd_flag); | 947 | !inetd_flag); |
934 | 948 | ||
935 | #ifdef _CRAY | 949 | #ifdef _UNICOS |
936 | /* Cray can define user privs drop all prives now! | 950 | /* Cray can define user privs drop all prives now! |
937 | * Not needed on PRIV_SU systems! | 951 | * Not needed on PRIV_SU systems! |
938 | */ | 952 | */ |
@@ -956,7 +970,8 @@ main(int ac, char **av) | |||
956 | debug("sshd version %.100s", SSH_VERSION); | 970 | debug("sshd version %.100s", SSH_VERSION); |
957 | 971 | ||
958 | /* load private host keys */ | 972 | /* load private host keys */ |
959 | sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*)); | 973 | sensitive_data.host_keys = xmalloc(options.num_host_key_files * |
974 | sizeof(Key *)); | ||
960 | for (i = 0; i < options.num_host_key_files; i++) | 975 | for (i = 0; i < options.num_host_key_files; i++) |
961 | sensitive_data.host_keys[i] = NULL; | 976 | sensitive_data.host_keys[i] = NULL; |
962 | sensitive_data.server_key = NULL; | 977 | sensitive_data.server_key = NULL; |
@@ -1035,7 +1050,14 @@ main(int ac, char **av) | |||
1035 | (S_ISDIR(st.st_mode) == 0)) | 1050 | (S_ISDIR(st.st_mode) == 0)) |
1036 | fatal("Missing privilege separation directory: %s", | 1051 | fatal("Missing privilege separation directory: %s", |
1037 | _PATH_PRIVSEP_CHROOT_DIR); | 1052 | _PATH_PRIVSEP_CHROOT_DIR); |
1053 | |||
1054 | #ifdef HAVE_CYGWIN | ||
1055 | if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) && | ||
1056 | (st.st_uid != getuid () || | ||
1057 | (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)) | ||
1058 | #else | ||
1038 | if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) | 1059 | if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) |
1060 | #endif | ||
1039 | fatal("Bad owner or mode for %s", | 1061 | fatal("Bad owner or mode for %s", |
1040 | _PATH_PRIVSEP_CHROOT_DIR); | 1062 | _PATH_PRIVSEP_CHROOT_DIR); |
1041 | } | 1063 | } |
@@ -1135,17 +1157,12 @@ main(int ac, char **av) | |||
1135 | continue; | 1157 | continue; |
1136 | } | 1158 | } |
1137 | /* | 1159 | /* |
1138 | * Set socket options. We try to make the port | 1160 | * Set socket options. |
1139 | * reusable and have it close as fast as possible | 1161 | * Allow local port reuse in TIME_WAIT. |
1140 | * without waiting in unnecessary wait states on | ||
1141 | * close. | ||
1142 | */ | 1162 | */ |
1143 | setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, | 1163 | if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, |
1144 | &on, sizeof(on)); | 1164 | &on, sizeof(on)) == -1) |
1145 | linger.l_onoff = 1; | 1165 | error("setsockopt SO_REUSEADDR: %s", strerror(errno)); |
1146 | linger.l_linger = 5; | ||
1147 | setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, | ||
1148 | &linger, sizeof(linger)); | ||
1149 | 1166 | ||
1150 | debug("Bind to port %s on %s.", strport, ntop); | 1167 | debug("Bind to port %s on %s.", strport, ntop); |
1151 | 1168 | ||
@@ -1394,16 +1411,6 @@ main(int ac, char **av) | |||
1394 | signal(SIGCHLD, SIG_DFL); | 1411 | signal(SIGCHLD, SIG_DFL); |
1395 | signal(SIGINT, SIG_DFL); | 1412 | signal(SIGINT, SIG_DFL); |
1396 | 1413 | ||
1397 | /* | ||
1398 | * Set socket options for the connection. We want the socket to | ||
1399 | * close as fast as possible without waiting for anything. If the | ||
1400 | * connection is not a socket, these will do nothing. | ||
1401 | */ | ||
1402 | /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ | ||
1403 | linger.l_onoff = 1; | ||
1404 | linger.l_linger = 5; | ||
1405 | setsockopt(sock_in, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); | ||
1406 | |||
1407 | /* Set keepalives if requested. */ | 1414 | /* Set keepalives if requested. */ |
1408 | if (options.keepalives && | 1415 | if (options.keepalives && |
1409 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, | 1416 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, |
@@ -1591,7 +1598,7 @@ do_ssh1_kex(void) | |||
1591 | u_char session_key[SSH_SESSION_KEY_LENGTH]; | 1598 | u_char session_key[SSH_SESSION_KEY_LENGTH]; |
1592 | u_char cookie[8]; | 1599 | u_char cookie[8]; |
1593 | u_int cipher_type, auth_mask, protocol_flags; | 1600 | u_int cipher_type, auth_mask, protocol_flags; |
1594 | u_int32_t rand = 0; | 1601 | u_int32_t rnd = 0; |
1595 | 1602 | ||
1596 | /* | 1603 | /* |
1597 | * Generate check bytes that the client must send back in the user | 1604 | * Generate check bytes that the client must send back in the user |
@@ -1604,9 +1611,9 @@ do_ssh1_kex(void) | |||
1604 | */ | 1611 | */ |
1605 | for (i = 0; i < 8; i++) { | 1612 | for (i = 0; i < 8; i++) { |
1606 | if (i % 4 == 0) | 1613 | if (i % 4 == 0) |
1607 | rand = arc4random(); | 1614 | rnd = arc4random(); |
1608 | cookie[i] = rand & 0xff; | 1615 | cookie[i] = rnd & 0xff; |
1609 | rand >>= 8; | 1616 | rnd >>= 8; |
1610 | } | 1617 | } |
1611 | 1618 | ||
1612 | /* | 1619 | /* |