| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: sshd.c,v 1.8 2011/09/16 15:36:18 joerg Exp $ */ | | 1 | /* $NetBSD: sshd.c,v 1.9 2012/03/05 20:13:36 tls Exp $ */ |
2 | /* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */ | | 2 | /* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */ |
3 | /* | | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
5 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | | 5 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
6 | * All rights reserved | | 6 | * All rights reserved |
7 | * This program is the ssh daemon. It listens for connections from clients, | | 7 | * This program is the ssh daemon. It listens for connections from clients, |
8 | * and performs authentication, executes use commands or shell, and forwards | | 8 | * and performs authentication, executes use commands or shell, and forwards |
9 | * information to/from the application to the user client over an encrypted | | 9 | * information to/from the application to the user client over an encrypted |
10 | * connection. This can also handle forwarding of X11, TCP/IP, and | | 10 | * connection. This can also handle forwarding of X11, TCP/IP, and |
11 | * authentication agent connections. | | 11 | * authentication agent connections. |
12 | * | | 12 | * |
13 | * As far as I am concerned, the code I have written for this software | | 13 | * As far as I am concerned, the code I have written for this software |
14 | * can be used freely for any purpose. Any derived versions of this | | 14 | * can be used freely for any purpose. Any derived versions of this |
| @@ -34,27 +34,27 @@ | | | @@ -34,27 +34,27 @@ |
34 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 34 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
35 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 35 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
36 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 36 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
37 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 37 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
38 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 38 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
39 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 39 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
40 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 40 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
41 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 41 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
42 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 42 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
43 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 43 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
44 | */ | | 44 | */ |
45 | | | 45 | |
46 | #include "includes.h" | | 46 | #include "includes.h" |
47 | __RCSID("$NetBSD: sshd.c,v 1.8 2011/09/16 15:36:18 joerg Exp $"); | | 47 | __RCSID("$NetBSD: sshd.c,v 1.9 2012/03/05 20:13:36 tls Exp $"); |
48 | #include <sys/types.h> | | 48 | #include <sys/types.h> |
49 | #include <sys/param.h> | | 49 | #include <sys/param.h> |
50 | #include <sys/ioctl.h> | | 50 | #include <sys/ioctl.h> |
51 | #include <sys/wait.h> | | 51 | #include <sys/wait.h> |
52 | #include <sys/tree.h> | | 52 | #include <sys/tree.h> |
53 | #include <sys/stat.h> | | 53 | #include <sys/stat.h> |
54 | #include <sys/socket.h> | | 54 | #include <sys/socket.h> |
55 | #include <sys/time.h> | | 55 | #include <sys/time.h> |
56 | #include <sys/queue.h> | | 56 | #include <sys/queue.h> |
57 | | | 57 | |
58 | #include <errno.h> | | 58 | #include <errno.h> |
59 | #include <fcntl.h> | | 59 | #include <fcntl.h> |
60 | #include <netdb.h> | | 60 | #include <netdb.h> |
| @@ -119,27 +119,30 @@ int deny_severity = LOG_WARNING; | | | @@ -119,27 +119,30 @@ int deny_severity = LOG_WARNING; |
119 | | | 119 | |
120 | #ifdef WITH_LDAP_PUBKEY | | 120 | #ifdef WITH_LDAP_PUBKEY |
121 | #include "ldapauth.h" | | 121 | #include "ldapauth.h" |
122 | #endif | | 122 | #endif |
123 | | | 123 | |
124 | #ifndef O_NOCTTY | | 124 | #ifndef O_NOCTTY |
125 | #define O_NOCTTY 0 | | 125 | #define O_NOCTTY 0 |
126 | #endif | | 126 | #endif |
127 | | | 127 | |
128 | /* Re-exec fds */ | | 128 | /* Re-exec fds */ |
129 | #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) | | 129 | #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) |
130 | #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) | | 130 | #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) |
131 | #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) | | 131 | #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) |
132 | #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) | | 132 | #define REEXEC_DEVURANDOM_FD (STDERR_FILENO + 4) |
| | | 133 | #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 5) |
| | | 134 | |
| | | 135 | int urandom_fd = -1; |
133 | | | 136 | |
134 | int myflag = 0; | | 137 | int myflag = 0; |
135 | | | 138 | |
136 | | | 139 | |
137 | extern char *__progname; | | 140 | extern char *__progname; |
138 | | | 141 | |
139 | /* Server configuration options. */ | | 142 | /* Server configuration options. */ |
140 | ServerOptions options; | | 143 | ServerOptions options; |
141 | | | 144 | |
142 | /* Name of the server configuration file. */ | | 145 | /* Name of the server configuration file. */ |
143 | const char *config_file_name = _PATH_SERVER_CONFIG_FILE; | | 146 | const char *config_file_name = _PATH_SERVER_CONFIG_FILE; |
144 | | | 147 | |
145 | /* | | 148 | /* |
| @@ -572,37 +575,40 @@ demote_sensitive_data(void) | | | @@ -572,37 +575,40 @@ demote_sensitive_data(void) |
572 | sensitive_data.host_keys[i] = tmp; | | 575 | sensitive_data.host_keys[i] = tmp; |
573 | if (tmp->type == KEY_RSA1) | | 576 | if (tmp->type == KEY_RSA1) |
574 | sensitive_data.ssh1_host_key = tmp; | | 577 | sensitive_data.ssh1_host_key = tmp; |
575 | } | | 578 | } |
576 | /* Certs do not need demotion */ | | 579 | /* Certs do not need demotion */ |
577 | } | | 580 | } |
578 | | | 581 | |
579 | /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ | | 582 | /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ |
580 | } | | 583 | } |
581 | | | 584 | |
582 | static void | | 585 | static void |
583 | privsep_preauth_child(void) | | 586 | privsep_preauth_child(void) |
584 | { | | 587 | { |
585 | u_int32_t rnd[256]; | | 588 | u_int32_t rnd[32]; |
586 | gid_t gidset[1]; | | 589 | gid_t gidset[1]; |
587 | struct passwd *pw; | | 590 | struct passwd *pw; |
588 | | | 591 | |
589 | /* Enable challenge-response authentication for privilege separation */ | | 592 | /* Enable challenge-response authentication for privilege separation */ |
590 | privsep_challenge_enable(); | | 593 | privsep_challenge_enable(); |
591 | | | 594 | |
592 | arc4random_stir(); | | 595 | if (read(urandom_fd, rnd, sizeof(rnd)) != sizeof(rnd)) { |
593 | arc4random_buf(rnd, sizeof(rnd)); | | 596 | fatal("privsep_preauth_child: entropy read failed"); |
| | | 597 | } |
594 | RAND_seed(rnd, sizeof(rnd)); | | 598 | RAND_seed(rnd, sizeof(rnd)); |
595 | | | 599 | |
| | | 600 | arc4random_stir(); |
| | | 601 | |
596 | /* Demote the private keys to public keys. */ | | 602 | /* Demote the private keys to public keys. */ |
597 | demote_sensitive_data(); | | 603 | demote_sensitive_data(); |
598 | | | 604 | |
599 | if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) | | 605 | if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) |
600 | fatal("Privilege separation user %s does not exist", | | 606 | fatal("Privilege separation user %s does not exist", |
601 | SSH_PRIVSEP_USER); | | 607 | SSH_PRIVSEP_USER); |
602 | memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); | | 608 | memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); |
603 | endpwent(); | | 609 | endpwent(); |
604 | | | 610 | |
605 | /* Change our root directory */ | | 611 | /* Change our root directory */ |
606 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) | | 612 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) |
607 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, | | 613 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, |
608 | strerror(errno)); | | 614 | strerror(errno)); |
| @@ -679,27 +685,27 @@ privsep_preauth(Authctxt *authctxt) | | | @@ -679,27 +685,27 @@ privsep_preauth(Authctxt *authctxt) |
679 | if (getuid() == 0 || geteuid() == 0) | | 685 | if (getuid() == 0 || geteuid() == 0) |
680 | privsep_preauth_child(); | | 686 | privsep_preauth_child(); |
681 | setproctitle("%s", "[net]"); | | 687 | setproctitle("%s", "[net]"); |
682 | if (box != NULL) | | 688 | if (box != NULL) |
683 | ssh_sandbox_child(box); | | 689 | ssh_sandbox_child(box); |
684 | | | 690 | |
685 | return 0; | | 691 | return 0; |
686 | } | | 692 | } |
687 | } | | 693 | } |
688 | | | 694 | |
689 | static void | | 695 | static void |
690 | privsep_postauth(Authctxt *authctxt) | | 696 | privsep_postauth(Authctxt *authctxt) |
691 | { | | 697 | { |
692 | u_int32_t rnd[256]; | | 698 | u_int32_t rnd[32]; |
693 | | | 699 | |
694 | if (authctxt->pw->pw_uid == 0 || options.use_login) { | | 700 | if (authctxt->pw->pw_uid == 0 || options.use_login) { |
695 | /* File descriptor passing is broken or root login */ | | 701 | /* File descriptor passing is broken or root login */ |
696 | use_privsep = 0; | | 702 | use_privsep = 0; |
697 | goto skip; | | 703 | goto skip; |
698 | } | | 704 | } |
699 | | | 705 | |
700 | /* New socket pair */ | | 706 | /* New socket pair */ |
701 | monitor_reinit(pmonitor); | | 707 | monitor_reinit(pmonitor); |
702 | | | 708 | |
703 | pmonitor->m_pid = fork(); | | 709 | pmonitor->m_pid = fork(); |
704 | if (pmonitor->m_pid == -1) | | 710 | if (pmonitor->m_pid == -1) |
705 | fatal("fork of unprivileged child failed"); | | 711 | fatal("fork of unprivileged child failed"); |
| @@ -710,30 +716,33 @@ privsep_postauth(Authctxt *authctxt) | | | @@ -710,30 +716,33 @@ privsep_postauth(Authctxt *authctxt) |
710 | | | 716 | |
711 | /* NEVERREACHED */ | | 717 | /* NEVERREACHED */ |
712 | exit(0); | | 718 | exit(0); |
713 | } | | 719 | } |
714 | | | 720 | |
715 | /* child */ | | 721 | /* child */ |
716 | | | 722 | |
717 | close(pmonitor->m_sendfd); | | 723 | close(pmonitor->m_sendfd); |
718 | pmonitor->m_sendfd = -1; | | 724 | pmonitor->m_sendfd = -1; |
719 | | | 725 | |
720 | /* Demote the private keys to public keys. */ | | 726 | /* Demote the private keys to public keys. */ |
721 | demote_sensitive_data(); | | 727 | demote_sensitive_data(); |
722 | | | 728 | |
723 | arc4random_stir(); | | 729 | if (read(urandom_fd, rnd, sizeof(rnd)) != sizeof(rnd)) { |
724 | arc4random_buf(rnd, sizeof(rnd)); | | 730 | fatal("privsep_postauth: entropy read failed"); |
| | | 731 | } |
725 | RAND_seed(rnd, sizeof(rnd)); | | 732 | RAND_seed(rnd, sizeof(rnd)); |
726 | | | 733 | |
| | | 734 | arc4random_stir(); |
| | | 735 | |
727 | /* Drop privileges */ | | 736 | /* Drop privileges */ |
728 | do_setusercontext(authctxt->pw); | | 737 | do_setusercontext(authctxt->pw); |
729 | | | 738 | |
730 | skip: | | 739 | skip: |
731 | /* It is safe now to apply the key state */ | | 740 | /* It is safe now to apply the key state */ |
732 | monitor_apply_keystate(pmonitor); | | 741 | monitor_apply_keystate(pmonitor); |
733 | | | 742 | |
734 | /* | | 743 | /* |
735 | * Tell the packet layer that authentication was successful, since | | 744 | * Tell the packet layer that authentication was successful, since |
736 | * this information is not part of the key state. | | 745 | * this information is not part of the key state. |
737 | */ | | 746 | */ |
738 | packet_set_authenticated(); | | 747 | packet_set_authenticated(); |
739 | } | | 748 | } |
| @@ -1081,26 +1090,27 @@ server_listen(void) | | | @@ -1081,26 +1090,27 @@ server_listen(void) |
1081 | * The main TCP accept loop. Note that, for the non-debug case, returns | | 1090 | * The main TCP accept loop. Note that, for the non-debug case, returns |
1082 | * from this function are in a forked subprocess. | | 1091 | * from this function are in a forked subprocess. |
1083 | */ | | 1092 | */ |
1084 | static void | | 1093 | static void |
1085 | server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | | 1094 | server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) |
1086 | { | | 1095 | { |
1087 | fd_set *fdset; | | 1096 | fd_set *fdset; |
1088 | int i, j, ret, maxfd; | | 1097 | int i, j, ret, maxfd; |
1089 | int key_used = 0, startups = 0; | | 1098 | int key_used = 0, startups = 0; |
1090 | int startup_p[2] = { -1 , -1 }; | | 1099 | int startup_p[2] = { -1 , -1 }; |
1091 | struct sockaddr_storage from; | | 1100 | struct sockaddr_storage from; |
1092 | socklen_t fromlen; | | 1101 | socklen_t fromlen; |
1093 | pid_t pid; | | 1102 | pid_t pid; |
| | | 1103 | uint8_t rnd[32]; |
1094 | | | 1104 | |
1095 | /* setup fd set for accept */ | | 1105 | /* setup fd set for accept */ |
1096 | fdset = NULL; | | 1106 | fdset = NULL; |
1097 | maxfd = 0; | | 1107 | maxfd = 0; |
1098 | for (i = 0; i < num_listen_socks; i++) | | 1108 | for (i = 0; i < num_listen_socks; i++) |
1099 | if (listen_socks[i] > maxfd) | | 1109 | if (listen_socks[i] > maxfd) |
1100 | maxfd = listen_socks[i]; | | 1110 | maxfd = listen_socks[i]; |
1101 | /* pipes connected to unauthenticated childs */ | | 1111 | /* pipes connected to unauthenticated childs */ |
1102 | startup_pipes = xcalloc(options.max_startups, sizeof(int)); | | 1112 | startup_pipes = xcalloc(options.max_startups, sizeof(int)); |
1103 | for (i = 0; i < options.max_startups; i++) | | 1113 | for (i = 0; i < options.max_startups; i++) |
1104 | startup_pipes[i] = -1; | | 1114 | startup_pipes[i] = -1; |
1105 | | | 1115 | |
1106 | /* | | 1116 | /* |
| @@ -1273,26 +1283,32 @@ server_accept_loop(int *sock_in, int *so | | | @@ -1273,26 +1283,32 @@ server_accept_loop(int *sock_in, int *so |
1273 | key_used == 0) { | | 1283 | key_used == 0) { |
1274 | /* Schedule server key regeneration alarm. */ | | 1284 | /* Schedule server key regeneration alarm. */ |
1275 | signal(SIGALRM, key_regeneration_alarm); | | 1285 | signal(SIGALRM, key_regeneration_alarm); |
1276 | alarm(options.key_regeneration_time); | | 1286 | alarm(options.key_regeneration_time); |
1277 | key_used = 1; | | 1287 | key_used = 1; |
1278 | } | | 1288 | } |
1279 | | | 1289 | |
1280 | close(*newsock); | | 1290 | close(*newsock); |
1281 | | | 1291 | |
1282 | /* | | 1292 | /* |
1283 | * Ensure that our random state differs | | 1293 | * Ensure that our random state differs |
1284 | * from that of the child | | 1294 | * from that of the child |
1285 | */ | | 1295 | */ |
| | | 1296 | if (read(urandom_fd, rnd, sizeof(rnd)) != |
| | | 1297 | sizeof(rnd)) { |
| | | 1298 | fatal("server_accept_loop: " |
| | | 1299 | "entropy read failed"); |
| | | 1300 | } |
| | | 1301 | RAND_seed(rnd, sizeof(rnd)); |
1286 | arc4random_stir(); | | 1302 | arc4random_stir(); |
1287 | } | | 1303 | } |
1288 | | | 1304 | |
1289 | /* child process check (or debug mode) */ | | 1305 | /* child process check (or debug mode) */ |
1290 | if (num_listen_socks < 0) | | 1306 | if (num_listen_socks < 0) |
1291 | break; | | 1307 | break; |
1292 | } | | 1308 | } |
1293 | } | | 1309 | } |
1294 | | | 1310 | |
1295 | | | 1311 | |
1296 | /* | | 1312 | /* |
1297 | * Main program for the daemon. | | 1313 | * Main program for the daemon. |
1298 | */ | | 1314 | */ |
| @@ -1302,26 +1318,27 @@ main(int ac, char **av) | | | @@ -1302,26 +1318,27 @@ main(int ac, char **av) |
1302 | extern char *optarg; | | 1318 | extern char *optarg; |
1303 | extern int optind; | | 1319 | extern int optind; |
1304 | int opt, i, j, on = 1; | | 1320 | int opt, i, j, on = 1; |
1305 | int sock_in = -1, sock_out = -1, newsock = -1; | | 1321 | int sock_in = -1, sock_out = -1, newsock = -1; |
1306 | const char *remote_ip; | | 1322 | const char *remote_ip; |
1307 | char *test_user = NULL, *test_host = NULL, *test_addr = NULL; | | 1323 | char *test_user = NULL, *test_host = NULL, *test_addr = NULL; |
1308 | int remote_port; | | 1324 | int remote_port; |
1309 | char *line, *p, *cp; | | 1325 | char *line, *p, *cp; |
1310 | int config_s[2] = { -1 , -1 }; | | 1326 | int config_s[2] = { -1 , -1 }; |
1311 | u_int64_t ibytes, obytes; | | 1327 | u_int64_t ibytes, obytes; |
1312 | mode_t new_umask; | | 1328 | mode_t new_umask; |
1313 | Key *key; | | 1329 | Key *key; |
1314 | Authctxt *authctxt; | | 1330 | Authctxt *authctxt; |
| | | 1331 | uint8_t rnd[32]; |
1315 | | | 1332 | |
1316 | /* Save argv. */ | | 1333 | /* Save argv. */ |
1317 | saved_argv = av; | | 1334 | saved_argv = av; |
1318 | rexec_argc = ac; | | 1335 | rexec_argc = ac; |
1319 | | | 1336 | |
1320 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | | 1337 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
1321 | sanitise_stdfd(); | | 1338 | sanitise_stdfd(); |
1322 | | | 1339 | |
1323 | /* Initialize configuration options to their default values. */ | | 1340 | /* Initialize configuration options to their default values. */ |
1324 | initialize_server_options(&options); | | 1341 | initialize_server_options(&options); |
1325 | | | 1342 | |
1326 | /* Parse command-line arguments. */ | | 1343 | /* Parse command-line arguments. */ |
1327 | while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) { | | 1344 | while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) { |
| @@ -1452,26 +1469,55 @@ main(int ac, char **av) | | | @@ -1452,26 +1469,55 @@ main(int ac, char **av) |
1452 | } | | 1469 | } |
1453 | if (rexeced_flag || inetd_flag) | | 1470 | if (rexeced_flag || inetd_flag) |
1454 | rexec_flag = 0; | | 1471 | rexec_flag = 0; |
1455 | if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/'))) | | 1472 | if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/'))) |
1456 | fatal("sshd re-exec requires execution with an absolute path"); | | 1473 | fatal("sshd re-exec requires execution with an absolute path"); |
1457 | if (rexeced_flag) | | 1474 | if (rexeced_flag) |
1458 | closefrom(REEXEC_MIN_FREE_FD); | | 1475 | closefrom(REEXEC_MIN_FREE_FD); |
1459 | else | | 1476 | else |
1460 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); | | 1477 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); |
1461 | | | 1478 | |
1462 | OpenSSL_add_all_algorithms(); | | 1479 | OpenSSL_add_all_algorithms(); |
1463 | | | 1480 | |
1464 | /* | | 1481 | /* |
| | | 1482 | * The OpenSSL PRNG is used by key-generation functions we |
| | | 1483 | * rely on for security. Seed it ourselves, so that: |
| | | 1484 | * |
| | | 1485 | * A) it does not seed itself from somewhere questionable, |
| | | 1486 | * such as the libc arc4random or, worse, getpid(). |
| | | 1487 | * B) it does not reopen /dev/urandom on systems where |
| | | 1488 | * this is expensive (generator keyed on open, etc). |
| | | 1489 | * |
| | | 1490 | * Note that /dev/urandom will never return the same data to |
| | | 1491 | * two callers, even if they have the same dup'd reference to it. |
| | | 1492 | */ |
| | | 1493 | if (rexeced_flag) { |
| | | 1494 | urandom_fd = REEXEC_DEVURANDOM_FD; |
| | | 1495 | } else { |
| | | 1496 | urandom_fd = open("/dev/urandom", O_RDONLY); |
| | | 1497 | if (urandom_fd == -1) { |
| | | 1498 | fatal("sshd requires random device"); |
| | | 1499 | } |
| | | 1500 | /* Might as well do this here; why do it later? */ |
| | | 1501 | dup2(urandom_fd, REEXEC_DEVURANDOM_FD); |
| | | 1502 | close(urandom_fd); |
| | | 1503 | urandom_fd = REEXEC_DEVURANDOM_FD; |
| | | 1504 | } |
| | | 1505 | if (read(urandom_fd, rnd, sizeof(rnd)) != sizeof(rnd)) { |
| | | 1506 | fatal("entropy read failed"); |
| | | 1507 | } |
| | | 1508 | RAND_seed(rnd, sizeof(rnd)); |
| | | 1509 | |
| | | 1510 | /* |
1465 | * Force logging to stderr until we have loaded the private host | | 1511 | * Force logging to stderr until we have loaded the private host |
1466 | * key (unless started from inetd) | | 1512 | * key (unless started from inetd) |
1467 | */ | | 1513 | */ |
1468 | log_init(__progname, | | 1514 | log_init(__progname, |
1469 | options.log_level == SYSLOG_LEVEL_NOT_SET ? | | 1515 | options.log_level == SYSLOG_LEVEL_NOT_SET ? |
1470 | SYSLOG_LEVEL_INFO : options.log_level, | | 1516 | SYSLOG_LEVEL_INFO : options.log_level, |
1471 | options.log_facility == SYSLOG_FACILITY_NOT_SET ? | | 1517 | options.log_facility == SYSLOG_FACILITY_NOT_SET ? |
1472 | SYSLOG_FACILITY_AUTH : options.log_facility, | | 1518 | SYSLOG_FACILITY_AUTH : options.log_facility, |
1473 | log_stderr || !inetd_flag); | | 1519 | log_stderr || !inetd_flag); |
1474 | | | 1520 | |
1475 | sensitive_data.server_key = NULL; | | 1521 | sensitive_data.server_key = NULL; |
1476 | sensitive_data.ssh1_host_key = NULL; | | 1522 | sensitive_data.ssh1_host_key = NULL; |
1477 | sensitive_data.have_ssh1_key = 0; | | 1523 | sensitive_data.have_ssh1_key = 0; |
| @@ -1693,27 +1739,27 @@ main(int ac, char **av) | | | @@ -1693,27 +1739,27 @@ main(int ac, char **av) |
1693 | if (daemon(0, 0) < 0) | | 1739 | if (daemon(0, 0) < 0) |
1694 | fatal("daemon() failed: %.200s", strerror(errno)); | | 1740 | fatal("daemon() failed: %.200s", strerror(errno)); |
1695 | | | 1741 | |
1696 | /* Disconnect from the controlling tty. */ | | 1742 | /* Disconnect from the controlling tty. */ |
1697 | fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); | | 1743 | fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); |
1698 | if (fd >= 0) { | | 1744 | if (fd >= 0) { |
1699 | (void) ioctl(fd, TIOCNOTTY, NULL); | | 1745 | (void) ioctl(fd, TIOCNOTTY, NULL); |
1700 | close(fd); | | 1746 | close(fd); |
1701 | } | | 1747 | } |
1702 | } | | 1748 | } |
1703 | /* Reinitialize the log (because of the fork above). */ | | 1749 | /* Reinitialize the log (because of the fork above). */ |
1704 | log_init(__progname, options.log_level, options.log_facility, log_stderr); | | 1750 | log_init(__progname, options.log_level, options.log_facility, log_stderr); |
1705 | | | 1751 | |
1706 | /* Initialize the random number generator. */ | | 1752 | /* Initialize the fast random number generator. */ |
1707 | arc4random_stir(); | | 1753 | arc4random_stir(); |
1708 | | | 1754 | |
1709 | /* Chdir to the root directory so that the current disk can be | | 1755 | /* Chdir to the root directory so that the current disk can be |
1710 | unmounted if desired. */ | | 1756 | unmounted if desired. */ |
1711 | chdir("/"); | | 1757 | chdir("/"); |
1712 | | | 1758 | |
1713 | /* ignore SIGPIPE */ | | 1759 | /* ignore SIGPIPE */ |
1714 | signal(SIGPIPE, SIG_IGN); | | 1760 | signal(SIGPIPE, SIG_IGN); |
1715 | | | 1761 | |
1716 | /* Get a connection, either from inetd or a listening TCP socket */ | | 1762 | /* Get a connection, either from inetd or a listening TCP socket */ |
1717 | if (inetd_flag) { | | 1763 | if (inetd_flag) { |
1718 | server_accept_inetd(&sock_in, &sock_out); | | 1764 | server_accept_inetd(&sock_in, &sock_out); |
1719 | } else { | | 1765 | } else { |