diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 814 |
1 files changed, 449 insertions, 365 deletions
@@ -1,3 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.349 2007/02/21 11:00:05 dtucker Exp $ */ | ||
1 | /* | 2 | /* |
2 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -42,7 +43,33 @@ | |||
42 | */ | 43 | */ |
43 | 44 | ||
44 | #include "includes.h" | 45 | #include "includes.h" |
45 | RCSID("$OpenBSD: sshd.c,v 1.318 2005/12/24 02:27:41 djm Exp $"); | 46 | |
47 | #include <sys/types.h> | ||
48 | #include <sys/ioctl.h> | ||
49 | #include <sys/socket.h> | ||
50 | #ifdef HAVE_SYS_STAT_H | ||
51 | # include <sys/stat.h> | ||
52 | #endif | ||
53 | #ifdef HAVE_SYS_TIME_H | ||
54 | # include <sys/time.h> | ||
55 | #endif | ||
56 | #include "openbsd-compat/sys-tree.h" | ||
57 | #include <sys/wait.h> | ||
58 | |||
59 | #include <errno.h> | ||
60 | #include <fcntl.h> | ||
61 | #include <netdb.h> | ||
62 | #ifdef HAVE_PATHS_H | ||
63 | #include <paths.h> | ||
64 | #endif | ||
65 | #include <grp.h> | ||
66 | #include <pwd.h> | ||
67 | #include <signal.h> | ||
68 | #include <stdarg.h> | ||
69 | #include <stdio.h> | ||
70 | #include <stdlib.h> | ||
71 | #include <string.h> | ||
72 | #include <unistd.h> | ||
46 | 73 | ||
47 | #include <openssl/dh.h> | 74 | #include <openssl/dh.h> |
48 | #include <openssl/bn.h> | 75 | #include <openssl/bn.h> |
@@ -53,28 +80,28 @@ RCSID("$OpenBSD: sshd.c,v 1.318 2005/12/24 02:27:41 djm Exp $"); | |||
53 | #include <prot.h> | 80 | #include <prot.h> |
54 | #endif | 81 | #endif |
55 | 82 | ||
83 | #include "xmalloc.h" | ||
56 | #include "ssh.h" | 84 | #include "ssh.h" |
57 | #include "ssh1.h" | 85 | #include "ssh1.h" |
58 | #include "ssh2.h" | 86 | #include "ssh2.h" |
59 | #include "xmalloc.h" | ||
60 | #include "rsa.h" | 87 | #include "rsa.h" |
61 | #include "sshpty.h" | 88 | #include "sshpty.h" |
62 | #include "packet.h" | 89 | #include "packet.h" |
63 | #include "log.h" | 90 | #include "log.h" |
91 | #include "buffer.h" | ||
64 | #include "servconf.h" | 92 | #include "servconf.h" |
65 | #include "uidswap.h" | 93 | #include "uidswap.h" |
66 | #include "compat.h" | 94 | #include "compat.h" |
67 | #include "buffer.h" | ||
68 | #include "bufaux.h" | ||
69 | #include "cipher.h" | 95 | #include "cipher.h" |
70 | #include "kex.h" | ||
71 | #include "key.h" | 96 | #include "key.h" |
97 | #include "kex.h" | ||
72 | #include "dh.h" | 98 | #include "dh.h" |
73 | #include "myproposal.h" | 99 | #include "myproposal.h" |
74 | #include "authfile.h" | 100 | #include "authfile.h" |
75 | #include "pathnames.h" | 101 | #include "pathnames.h" |
76 | #include "atomicio.h" | 102 | #include "atomicio.h" |
77 | #include "canohost.h" | 103 | #include "canohost.h" |
104 | #include "hostfile.h" | ||
78 | #include "auth.h" | 105 | #include "auth.h" |
79 | #include "misc.h" | 106 | #include "misc.h" |
80 | #include "msg.h" | 107 | #include "msg.h" |
@@ -83,8 +110,12 @@ RCSID("$OpenBSD: sshd.c,v 1.318 2005/12/24 02:27:41 djm Exp $"); | |||
83 | #include "session.h" | 110 | #include "session.h" |
84 | #include "monitor_mm.h" | 111 | #include "monitor_mm.h" |
85 | #include "monitor.h" | 112 | #include "monitor.h" |
113 | #ifdef GSSAPI | ||
114 | #include "ssh-gss.h" | ||
115 | #endif | ||
86 | #include "monitor_wrap.h" | 116 | #include "monitor_wrap.h" |
87 | #include "monitor_fdpass.h" | 117 | #include "monitor_fdpass.h" |
118 | #include "version.h" | ||
88 | 119 | ||
89 | #ifdef USE_SECURITY_SESSION_API | 120 | #ifdef USE_SECURITY_SESSION_API |
90 | #include <Security/AuthSession.h> | 121 | #include <Security/AuthSession.h> |
@@ -205,15 +236,21 @@ int *startup_pipes = NULL; | |||
205 | int startup_pipe; /* in child */ | 236 | int startup_pipe; /* in child */ |
206 | 237 | ||
207 | /* variables used for privilege separation */ | 238 | /* variables used for privilege separation */ |
208 | int use_privsep; | 239 | int use_privsep = -1; |
209 | struct monitor *pmonitor = NULL; | 240 | struct monitor *pmonitor = NULL; |
210 | 241 | ||
211 | /* global authentication context */ | 242 | /* global authentication context */ |
212 | Authctxt *the_authctxt = NULL; | 243 | Authctxt *the_authctxt = NULL; |
213 | 244 | ||
245 | /* sshd_config buffer */ | ||
246 | Buffer cfg; | ||
247 | |||
214 | /* message to be displayed after login */ | 248 | /* message to be displayed after login */ |
215 | Buffer loginmsg; | 249 | Buffer loginmsg; |
216 | 250 | ||
251 | /* Unprivileged user */ | ||
252 | struct passwd *privsep_pw = NULL; | ||
253 | |||
217 | /* Prototypes for various functions defined later in this file. */ | 254 | /* Prototypes for various functions defined later in this file. */ |
218 | void destroy_sensitive_data(void); | 255 | void destroy_sensitive_data(void); |
219 | void demote_sensitive_data(void); | 256 | void demote_sensitive_data(void); |
@@ -250,6 +287,8 @@ close_startup_pipes(void) | |||
250 | * the effect is to reread the configuration file (and to regenerate | 287 | * the effect is to reread the configuration file (and to regenerate |
251 | * the server key). | 288 | * the server key). |
252 | */ | 289 | */ |
290 | |||
291 | /*ARGSUSED*/ | ||
253 | static void | 292 | static void |
254 | sighup_handler(int sig) | 293 | sighup_handler(int sig) |
255 | { | 294 | { |
@@ -270,6 +309,7 @@ sighup_restart(void) | |||
270 | logit("Received SIGHUP; restarting."); | 309 | logit("Received SIGHUP; restarting."); |
271 | close_listen_socks(); | 310 | close_listen_socks(); |
272 | close_startup_pipes(); | 311 | close_startup_pipes(); |
312 | alarm(0); /* alarm timer persists across exec */ | ||
273 | execv(saved_argv[0], saved_argv); | 313 | execv(saved_argv[0], saved_argv); |
274 | logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], | 314 | logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], |
275 | strerror(errno)); | 315 | strerror(errno)); |
@@ -279,6 +319,7 @@ sighup_restart(void) | |||
279 | /* | 319 | /* |
280 | * Generic signal handler for terminating signals in the master daemon. | 320 | * Generic signal handler for terminating signals in the master daemon. |
281 | */ | 321 | */ |
322 | /*ARGSUSED*/ | ||
282 | static void | 323 | static void |
283 | sigterm_handler(int sig) | 324 | sigterm_handler(int sig) |
284 | { | 325 | { |
@@ -289,6 +330,7 @@ sigterm_handler(int sig) | |||
289 | * SIGCHLD handler. This is called whenever a child dies. This will then | 330 | * SIGCHLD handler. This is called whenever a child dies. This will then |
290 | * reap any zombies left by exited children. | 331 | * reap any zombies left by exited children. |
291 | */ | 332 | */ |
333 | /*ARGSUSED*/ | ||
292 | static void | 334 | static void |
293 | main_sigchld_handler(int sig) | 335 | main_sigchld_handler(int sig) |
294 | { | 336 | { |
@@ -307,16 +349,15 @@ main_sigchld_handler(int sig) | |||
307 | /* | 349 | /* |
308 | * Signal handler for the alarm after the login grace period has expired. | 350 | * Signal handler for the alarm after the login grace period has expired. |
309 | */ | 351 | */ |
352 | /*ARGSUSED*/ | ||
310 | static void | 353 | static void |
311 | grace_alarm_handler(int sig) | 354 | grace_alarm_handler(int sig) |
312 | { | 355 | { |
313 | /* XXX no idea how fix this signal handler */ | ||
314 | |||
315 | if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0) | 356 | if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0) |
316 | kill(pmonitor->m_pid, SIGALRM); | 357 | kill(pmonitor->m_pid, SIGALRM); |
317 | 358 | ||
318 | /* Log error and exit. */ | 359 | /* Log error and exit. */ |
319 | fatal("Timeout before authentication for %s", get_remote_ipaddr()); | 360 | sigdie("Timeout before authentication for %s", get_remote_ipaddr()); |
320 | } | 361 | } |
321 | 362 | ||
322 | /* | 363 | /* |
@@ -349,6 +390,7 @@ generate_ephemeral_server_key(void) | |||
349 | arc4random_stir(); | 390 | arc4random_stir(); |
350 | } | 391 | } |
351 | 392 | ||
393 | /*ARGSUSED*/ | ||
352 | static void | 394 | static void |
353 | key_regeneration_alarm(int sig) | 395 | key_regeneration_alarm(int sig) |
354 | { | 396 | { |
@@ -545,7 +587,6 @@ privsep_preauth_child(void) | |||
545 | { | 587 | { |
546 | u_int32_t rnd[256]; | 588 | u_int32_t rnd[256]; |
547 | gid_t gidset[1]; | 589 | gid_t gidset[1]; |
548 | struct passwd *pw; | ||
549 | int i; | 590 | int i; |
550 | 591 | ||
551 | /* Enable challenge-response authentication for privilege separation */ | 592 | /* Enable challenge-response authentication for privilege separation */ |
@@ -558,12 +599,6 @@ privsep_preauth_child(void) | |||
558 | /* Demote the private keys to public keys. */ | 599 | /* Demote the private keys to public keys. */ |
559 | demote_sensitive_data(); | 600 | demote_sensitive_data(); |
560 | 601 | ||
561 | if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) | ||
562 | fatal("Privilege separation user %s does not exist", | ||
563 | SSH_PRIVSEP_USER); | ||
564 | memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); | ||
565 | endpwent(); | ||
566 | |||
567 | /* Change our root directory */ | 602 | /* Change our root directory */ |
568 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) | 603 | if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) |
569 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, | 604 | fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, |
@@ -572,16 +607,16 @@ privsep_preauth_child(void) | |||
572 | fatal("chdir(\"/\"): %s", strerror(errno)); | 607 | fatal("chdir(\"/\"): %s", strerror(errno)); |
573 | 608 | ||
574 | /* Drop our privileges */ | 609 | /* Drop our privileges */ |
575 | debug3("privsep user:group %u:%u", (u_int)pw->pw_uid, | 610 | debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid, |
576 | (u_int)pw->pw_gid); | 611 | (u_int)privsep_pw->pw_gid); |
577 | #if 0 | 612 | #if 0 |
578 | /* XXX not ready, too heavy after chroot */ | 613 | /* XXX not ready, too heavy after chroot */ |
579 | do_setusercontext(pw); | 614 | do_setusercontext(privsep_pw); |
580 | #else | 615 | #else |
581 | gidset[0] = pw->pw_gid; | 616 | gidset[0] = privsep_pw->pw_gid; |
582 | if (setgroups(1, gidset) < 0) | 617 | if (setgroups(1, gidset) < 0) |
583 | fatal("setgroups: %.100s", strerror(errno)); | 618 | fatal("setgroups: %.100s", strerror(errno)); |
584 | permanently_set_uid(pw); | 619 | permanently_set_uid(privsep_pw); |
585 | #endif | 620 | #endif |
586 | } | 621 | } |
587 | 622 | ||
@@ -870,6 +905,325 @@ recv_rexec_state(int fd, Buffer *conf) | |||
870 | debug3("%s: done", __func__); | 905 | debug3("%s: done", __func__); |
871 | } | 906 | } |
872 | 907 | ||
908 | /* Accept a connection from inetd */ | ||
909 | static void | ||
910 | server_accept_inetd(int *sock_in, int *sock_out) | ||
911 | { | ||
912 | int fd; | ||
913 | |||
914 | startup_pipe = -1; | ||
915 | if (rexeced_flag) { | ||
916 | close(REEXEC_CONFIG_PASS_FD); | ||
917 | *sock_in = *sock_out = dup(STDIN_FILENO); | ||
918 | if (!debug_flag) { | ||
919 | startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); | ||
920 | close(REEXEC_STARTUP_PIPE_FD); | ||
921 | } | ||
922 | } else { | ||
923 | *sock_in = dup(STDIN_FILENO); | ||
924 | *sock_out = dup(STDOUT_FILENO); | ||
925 | } | ||
926 | /* | ||
927 | * We intentionally do not close the descriptors 0, 1, and 2 | ||
928 | * as our code for setting the descriptors won't work if | ||
929 | * ttyfd happens to be one of those. | ||
930 | */ | ||
931 | if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { | ||
932 | dup2(fd, STDIN_FILENO); | ||
933 | dup2(fd, STDOUT_FILENO); | ||
934 | if (fd > STDOUT_FILENO) | ||
935 | close(fd); | ||
936 | } | ||
937 | debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out); | ||
938 | } | ||
939 | |||
940 | /* | ||
941 | * Listen for TCP connections | ||
942 | */ | ||
943 | static void | ||
944 | server_listen(void) | ||
945 | { | ||
946 | int ret, listen_sock, on = 1; | ||
947 | struct addrinfo *ai; | ||
948 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | ||
949 | |||
950 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { | ||
951 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | ||
952 | continue; | ||
953 | if (num_listen_socks >= MAX_LISTEN_SOCKS) | ||
954 | fatal("Too many listen sockets. " | ||
955 | "Enlarge MAX_LISTEN_SOCKS"); | ||
956 | if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, | ||
957 | ntop, sizeof(ntop), strport, sizeof(strport), | ||
958 | NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { | ||
959 | error("getnameinfo failed: %.100s", | ||
960 | (ret != EAI_SYSTEM) ? gai_strerror(ret) : | ||
961 | strerror(errno)); | ||
962 | continue; | ||
963 | } | ||
964 | /* Create socket for listening. */ | ||
965 | listen_sock = socket(ai->ai_family, ai->ai_socktype, | ||
966 | ai->ai_protocol); | ||
967 | if (listen_sock < 0) { | ||
968 | /* kernel may not support ipv6 */ | ||
969 | verbose("socket: %.100s", strerror(errno)); | ||
970 | continue; | ||
971 | } | ||
972 | if (set_nonblock(listen_sock) == -1) { | ||
973 | close(listen_sock); | ||
974 | continue; | ||
975 | } | ||
976 | /* | ||
977 | * Set socket options. | ||
978 | * Allow local port reuse in TIME_WAIT. | ||
979 | */ | ||
980 | if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, | ||
981 | &on, sizeof(on)) == -1) | ||
982 | error("setsockopt SO_REUSEADDR: %s", strerror(errno)); | ||
983 | |||
984 | debug("Bind to port %s on %s.", strport, ntop); | ||
985 | |||
986 | /* Bind the socket to the desired port. */ | ||
987 | if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { | ||
988 | error("Bind to port %s on %s failed: %.200s.", | ||
989 | strport, ntop, strerror(errno)); | ||
990 | close(listen_sock); | ||
991 | continue; | ||
992 | } | ||
993 | listen_socks[num_listen_socks] = listen_sock; | ||
994 | num_listen_socks++; | ||
995 | |||
996 | /* Start listening on the port. */ | ||
997 | if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0) | ||
998 | fatal("listen on [%s]:%s: %.100s", | ||
999 | ntop, strport, strerror(errno)); | ||
1000 | logit("Server listening on %s port %s.", ntop, strport); | ||
1001 | } | ||
1002 | freeaddrinfo(options.listen_addrs); | ||
1003 | |||
1004 | if (!num_listen_socks) | ||
1005 | fatal("Cannot bind any address."); | ||
1006 | } | ||
1007 | |||
1008 | /* | ||
1009 | * The main TCP accept loop. Note that, for the non-debug case, returns | ||
1010 | * from this function are in a forked subprocess. | ||
1011 | */ | ||
1012 | static void | ||
1013 | server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | ||
1014 | { | ||
1015 | fd_set *fdset; | ||
1016 | int i, j, ret, maxfd; | ||
1017 | int key_used = 0, startups = 0; | ||
1018 | int startup_p[2] = { -1 , -1 }; | ||
1019 | struct sockaddr_storage from; | ||
1020 | socklen_t fromlen; | ||
1021 | pid_t pid; | ||
1022 | |||
1023 | /* setup fd set for accept */ | ||
1024 | fdset = NULL; | ||
1025 | maxfd = 0; | ||
1026 | for (i = 0; i < num_listen_socks; i++) | ||
1027 | if (listen_socks[i] > maxfd) | ||
1028 | maxfd = listen_socks[i]; | ||
1029 | /* pipes connected to unauthenticated childs */ | ||
1030 | startup_pipes = xcalloc(options.max_startups, sizeof(int)); | ||
1031 | for (i = 0; i < options.max_startups; i++) | ||
1032 | startup_pipes[i] = -1; | ||
1033 | |||
1034 | /* | ||
1035 | * Stay listening for connections until the system crashes or | ||
1036 | * the daemon is killed with a signal. | ||
1037 | */ | ||
1038 | for (;;) { | ||
1039 | if (received_sighup) | ||
1040 | sighup_restart(); | ||
1041 | if (fdset != NULL) | ||
1042 | xfree(fdset); | ||
1043 | fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS), | ||
1044 | sizeof(fd_mask)); | ||
1045 | |||
1046 | for (i = 0; i < num_listen_socks; i++) | ||
1047 | FD_SET(listen_socks[i], fdset); | ||
1048 | for (i = 0; i < options.max_startups; i++) | ||
1049 | if (startup_pipes[i] != -1) | ||
1050 | FD_SET(startup_pipes[i], fdset); | ||
1051 | |||
1052 | /* Wait in select until there is a connection. */ | ||
1053 | ret = select(maxfd+1, fdset, NULL, NULL, NULL); | ||
1054 | if (ret < 0 && errno != EINTR) | ||
1055 | error("select: %.100s", strerror(errno)); | ||
1056 | if (received_sigterm) { | ||
1057 | logit("Received signal %d; terminating.", | ||
1058 | (int) received_sigterm); | ||
1059 | close_listen_socks(); | ||
1060 | unlink(options.pid_file); | ||
1061 | exit(255); | ||
1062 | } | ||
1063 | if (key_used && key_do_regen) { | ||
1064 | generate_ephemeral_server_key(); | ||
1065 | key_used = 0; | ||
1066 | key_do_regen = 0; | ||
1067 | } | ||
1068 | if (ret < 0) | ||
1069 | continue; | ||
1070 | |||
1071 | for (i = 0; i < options.max_startups; i++) | ||
1072 | if (startup_pipes[i] != -1 && | ||
1073 | FD_ISSET(startup_pipes[i], fdset)) { | ||
1074 | /* | ||
1075 | * the read end of the pipe is ready | ||
1076 | * if the child has closed the pipe | ||
1077 | * after successful authentication | ||
1078 | * or if the child has died | ||
1079 | */ | ||
1080 | close(startup_pipes[i]); | ||
1081 | startup_pipes[i] = -1; | ||
1082 | startups--; | ||
1083 | } | ||
1084 | for (i = 0; i < num_listen_socks; i++) { | ||
1085 | if (!FD_ISSET(listen_socks[i], fdset)) | ||
1086 | continue; | ||
1087 | fromlen = sizeof(from); | ||
1088 | *newsock = accept(listen_socks[i], | ||
1089 | (struct sockaddr *)&from, &fromlen); | ||
1090 | if (*newsock < 0) { | ||
1091 | if (errno != EINTR && errno != EWOULDBLOCK) | ||
1092 | error("accept: %.100s", strerror(errno)); | ||
1093 | continue; | ||
1094 | } | ||
1095 | if (unset_nonblock(*newsock) == -1) { | ||
1096 | close(*newsock); | ||
1097 | continue; | ||
1098 | } | ||
1099 | if (drop_connection(startups) == 1) { | ||
1100 | debug("drop connection #%d", startups); | ||
1101 | close(*newsock); | ||
1102 | continue; | ||
1103 | } | ||
1104 | if (pipe(startup_p) == -1) { | ||
1105 | close(*newsock); | ||
1106 | continue; | ||
1107 | } | ||
1108 | |||
1109 | if (rexec_flag && socketpair(AF_UNIX, | ||
1110 | SOCK_STREAM, 0, config_s) == -1) { | ||
1111 | error("reexec socketpair: %s", | ||
1112 | strerror(errno)); | ||
1113 | close(*newsock); | ||
1114 | close(startup_p[0]); | ||
1115 | close(startup_p[1]); | ||
1116 | continue; | ||
1117 | } | ||
1118 | |||
1119 | for (j = 0; j < options.max_startups; j++) | ||
1120 | if (startup_pipes[j] == -1) { | ||
1121 | startup_pipes[j] = startup_p[0]; | ||
1122 | if (maxfd < startup_p[0]) | ||
1123 | maxfd = startup_p[0]; | ||
1124 | startups++; | ||
1125 | break; | ||
1126 | } | ||
1127 | |||
1128 | /* | ||
1129 | * Got connection. Fork a child to handle it, unless | ||
1130 | * we are in debugging mode. | ||
1131 | */ | ||
1132 | if (debug_flag) { | ||
1133 | /* | ||
1134 | * In debugging mode. Close the listening | ||
1135 | * socket, and start processing the | ||
1136 | * connection without forking. | ||
1137 | */ | ||
1138 | debug("Server will not fork when running in debugging mode."); | ||
1139 | close_listen_socks(); | ||
1140 | *sock_in = *newsock; | ||
1141 | *sock_out = *newsock; | ||
1142 | close(startup_p[0]); | ||
1143 | close(startup_p[1]); | ||
1144 | startup_pipe = -1; | ||
1145 | pid = getpid(); | ||
1146 | if (rexec_flag) { | ||
1147 | send_rexec_state(config_s[0], | ||
1148 | &cfg); | ||
1149 | close(config_s[0]); | ||
1150 | } | ||
1151 | break; | ||
1152 | } | ||
1153 | |||
1154 | /* | ||
1155 | * Normal production daemon. Fork, and have | ||
1156 | * the child process the connection. The | ||
1157 | * parent continues listening. | ||
1158 | */ | ||
1159 | platform_pre_fork(); | ||
1160 | if ((pid = fork()) == 0) { | ||
1161 | /* | ||
1162 | * Child. Close the listening and | ||
1163 | * max_startup sockets. Start using | ||
1164 | * the accepted socket. Reinitialize | ||
1165 | * logging (since our pid has changed). | ||
1166 | * We break out of the loop to handle | ||
1167 | * the connection. | ||
1168 | */ | ||
1169 | platform_post_fork_child(); | ||
1170 | startup_pipe = startup_p[1]; | ||
1171 | close_startup_pipes(); | ||
1172 | close_listen_socks(); | ||
1173 | *sock_in = *newsock; | ||
1174 | *sock_out = *newsock; | ||
1175 | log_init(__progname, | ||
1176 | options.log_level, | ||
1177 | options.log_facility, | ||
1178 | log_stderr); | ||
1179 | if (rexec_flag) | ||
1180 | close(config_s[0]); | ||
1181 | break; | ||
1182 | } | ||
1183 | |||
1184 | /* Parent. Stay in the loop. */ | ||
1185 | platform_post_fork_parent(pid); | ||
1186 | if (pid < 0) | ||
1187 | error("fork: %.100s", strerror(errno)); | ||
1188 | else | ||
1189 | debug("Forked child %ld.", (long)pid); | ||
1190 | |||
1191 | close(startup_p[1]); | ||
1192 | |||
1193 | if (rexec_flag) { | ||
1194 | send_rexec_state(config_s[0], &cfg); | ||
1195 | close(config_s[0]); | ||
1196 | close(config_s[1]); | ||
1197 | } | ||
1198 | |||
1199 | /* | ||
1200 | * Mark that the key has been used (it | ||
1201 | * was "given" to the child). | ||
1202 | */ | ||
1203 | if ((options.protocol & SSH_PROTO_1) && | ||
1204 | key_used == 0) { | ||
1205 | /* Schedule server key regeneration alarm. */ | ||
1206 | signal(SIGALRM, key_regeneration_alarm); | ||
1207 | alarm(options.key_regeneration_time); | ||
1208 | key_used = 1; | ||
1209 | } | ||
1210 | |||
1211 | close(*newsock); | ||
1212 | |||
1213 | /* | ||
1214 | * Ensure that our random state differs | ||
1215 | * from that of the child | ||
1216 | */ | ||
1217 | arc4random_stir(); | ||
1218 | } | ||
1219 | |||
1220 | /* child process check (or debug mode) */ | ||
1221 | if (num_listen_socks < 0) | ||
1222 | break; | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | |||
873 | /* | 1227 | /* |
874 | * Main program for the daemon. | 1228 | * Main program for the daemon. |
875 | */ | 1229 | */ |
@@ -878,25 +1232,14 @@ main(int ac, char **av) | |||
878 | { | 1232 | { |
879 | extern char *optarg; | 1233 | extern char *optarg; |
880 | extern int optind; | 1234 | extern int optind; |
881 | int opt, j, i, fdsetsz, on = 1; | 1235 | int opt, i, on = 1; |
882 | int sock_in = -1, sock_out = -1, newsock = -1; | 1236 | int sock_in = -1, sock_out = -1, newsock = -1; |
883 | pid_t pid; | ||
884 | socklen_t fromlen; | ||
885 | fd_set *fdset; | ||
886 | struct sockaddr_storage from; | ||
887 | const char *remote_ip; | 1237 | const char *remote_ip; |
888 | int remote_port; | 1238 | int remote_port; |
889 | FILE *f; | ||
890 | struct addrinfo *ai; | ||
891 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | ||
892 | char *line; | 1239 | char *line; |
893 | int listen_sock, maxfd; | 1240 | int config_s[2] = { -1 , -1 }; |
894 | int startup_p[2] = { -1 , -1 }, config_s[2] = { -1 , -1 }; | ||
895 | int startups = 0; | ||
896 | Key *key; | 1241 | Key *key; |
897 | Authctxt *authctxt; | 1242 | Authctxt *authctxt; |
898 | int ret, key_used = 0; | ||
899 | Buffer cfg; | ||
900 | 1243 | ||
901 | #ifdef HAVE_SECUREWARE | 1244 | #ifdef HAVE_SECUREWARE |
902 | (void)set_auth_parameters(ac, av); | 1245 | (void)set_auth_parameters(ac, av); |
@@ -907,7 +1250,7 @@ main(int ac, char **av) | |||
907 | /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ | 1250 | /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ |
908 | saved_argc = ac; | 1251 | saved_argc = ac; |
909 | rexec_argc = ac; | 1252 | rexec_argc = ac; |
910 | saved_argv = xmalloc(sizeof(*saved_argv) * (ac + 1)); | 1253 | saved_argv = xcalloc(ac + 1, sizeof(*saved_argv)); |
911 | for (i = 0; i < ac; i++) | 1254 | for (i = 0; i < ac; i++) |
912 | saved_argv[i] = xstrdup(av[i]); | 1255 | saved_argv[i] = xstrdup(av[i]); |
913 | saved_argv[i] = NULL; | 1256 | saved_argv[i] = NULL; |
@@ -969,7 +1312,8 @@ main(int ac, char **av) | |||
969 | options.log_level = SYSLOG_LEVEL_QUIET; | 1312 | options.log_level = SYSLOG_LEVEL_QUIET; |
970 | break; | 1313 | break; |
971 | case 'b': | 1314 | case 'b': |
972 | options.server_key_bits = atoi(optarg); | 1315 | options.server_key_bits = (int)strtonum(optarg, 256, |
1316 | 32768, NULL); | ||
973 | break; | 1317 | break; |
974 | case 'p': | 1318 | case 'p': |
975 | options.ports_from_cmdline = 1; | 1319 | options.ports_from_cmdline = 1; |
@@ -1006,7 +1350,7 @@ main(int ac, char **av) | |||
1006 | test_flag = 1; | 1350 | test_flag = 1; |
1007 | break; | 1351 | break; |
1008 | case 'u': | 1352 | case 'u': |
1009 | utmp_len = atoi(optarg); | 1353 | utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL); |
1010 | if (utmp_len > MAXHOSTNAMELEN) { | 1354 | if (utmp_len > MAXHOSTNAMELEN) { |
1011 | fprintf(stderr, "Invalid utmp length.\n"); | 1355 | fprintf(stderr, "Invalid utmp length.\n"); |
1012 | exit(1); | 1356 | exit(1); |
@@ -1015,7 +1359,7 @@ main(int ac, char **av) | |||
1015 | case 'o': | 1359 | case 'o': |
1016 | line = xstrdup(optarg); | 1360 | line = xstrdup(optarg); |
1017 | if (process_server_config_line(&options, line, | 1361 | if (process_server_config_line(&options, line, |
1018 | "command-line", 0) != 0) | 1362 | "command-line", 0, NULL, NULL, NULL, NULL) != 0) |
1019 | exit(1); | 1363 | exit(1); |
1020 | xfree(line); | 1364 | xfree(line); |
1021 | break; | 1365 | break; |
@@ -1073,11 +1417,8 @@ main(int ac, char **av) | |||
1073 | else | 1417 | else |
1074 | load_server_config(config_file_name, &cfg); | 1418 | load_server_config(config_file_name, &cfg); |
1075 | 1419 | ||
1076 | parse_server_config(&options, | 1420 | parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, |
1077 | rexeced_flag ? "rexec" : config_file_name, &cfg); | 1421 | &cfg, NULL, NULL, NULL); |
1078 | |||
1079 | if (!rexec_flag) | ||
1080 | buffer_free(&cfg); | ||
1081 | 1422 | ||
1082 | seed_rng(); | 1423 | seed_rng(); |
1083 | 1424 | ||
@@ -1095,8 +1436,21 @@ main(int ac, char **av) | |||
1095 | 1436 | ||
1096 | debug("sshd version %.100s", SSH_RELEASE); | 1437 | debug("sshd version %.100s", SSH_RELEASE); |
1097 | 1438 | ||
1439 | /* Store privilege separation user for later use if required. */ | ||
1440 | if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { | ||
1441 | if (use_privsep || options.kerberos_authentication) | ||
1442 | fatal("Privilege separation user %s does not exist", | ||
1443 | SSH_PRIVSEP_USER); | ||
1444 | } else { | ||
1445 | memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd)); | ||
1446 | privsep_pw = pwcopy(privsep_pw); | ||
1447 | xfree(privsep_pw->pw_passwd); | ||
1448 | privsep_pw->pw_passwd = xstrdup("*"); | ||
1449 | } | ||
1450 | endpwent(); | ||
1451 | |||
1098 | /* load private host keys */ | 1452 | /* load private host keys */ |
1099 | sensitive_data.host_keys = xmalloc(options.num_host_key_files * | 1453 | sensitive_data.host_keys = xcalloc(options.num_host_key_files, |
1100 | sizeof(Key *)); | 1454 | sizeof(Key *)); |
1101 | for (i = 0; i < options.num_host_key_files; i++) | 1455 | for (i = 0; i < options.num_host_key_files; i++) |
1102 | sensitive_data.host_keys[i] = NULL; | 1456 | sensitive_data.host_keys[i] = NULL; |
@@ -1165,12 +1519,8 @@ main(int ac, char **av) | |||
1165 | } | 1519 | } |
1166 | 1520 | ||
1167 | if (use_privsep) { | 1521 | if (use_privsep) { |
1168 | struct passwd *pw; | ||
1169 | struct stat st; | 1522 | struct stat st; |
1170 | 1523 | ||
1171 | if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) | ||
1172 | fatal("Privilege separation user %s does not exist", | ||
1173 | SSH_PRIVSEP_USER); | ||
1174 | if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || | 1524 | if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || |
1175 | (S_ISDIR(st.st_mode) == 0)) | 1525 | (S_ISDIR(st.st_mode) == 0)) |
1176 | fatal("Missing privilege separation directory: %s", | 1526 | fatal("Missing privilege separation directory: %s", |
@@ -1202,7 +1552,7 @@ main(int ac, char **av) | |||
1202 | debug("setgroups() failed: %.200s", strerror(errno)); | 1552 | debug("setgroups() failed: %.200s", strerror(errno)); |
1203 | 1553 | ||
1204 | if (rexec_flag) { | 1554 | if (rexec_flag) { |
1205 | rexec_argv = xmalloc(sizeof(char *) * (rexec_argc + 2)); | 1555 | rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *)); |
1206 | for (i = 0; i < rexec_argc; i++) { | 1556 | for (i = 0; i < rexec_argc; i++) { |
1207 | debug("rexec_argv[%d]='%s'", i, saved_argv[i]); | 1557 | debug("rexec_argv[%d]='%s'", i, saved_argv[i]); |
1208 | rexec_argv[i] = saved_argv[i]; | 1558 | rexec_argv[i] = saved_argv[i]; |
@@ -1250,121 +1600,31 @@ main(int ac, char **av) | |||
1250 | /* ignore SIGPIPE */ | 1600 | /* ignore SIGPIPE */ |
1251 | signal(SIGPIPE, SIG_IGN); | 1601 | signal(SIGPIPE, SIG_IGN); |
1252 | 1602 | ||
1253 | /* Start listening for a socket, unless started from inetd. */ | 1603 | /* Get a connection, either from inetd or a listening TCP socket */ |
1254 | if (inetd_flag) { | 1604 | if (inetd_flag) { |
1255 | int fd; | 1605 | server_accept_inetd(&sock_in, &sock_out); |
1256 | 1606 | ||
1257 | startup_pipe = -1; | ||
1258 | if (rexeced_flag) { | ||
1259 | close(REEXEC_CONFIG_PASS_FD); | ||
1260 | sock_in = sock_out = dup(STDIN_FILENO); | ||
1261 | if (!debug_flag) { | ||
1262 | startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); | ||
1263 | close(REEXEC_STARTUP_PIPE_FD); | ||
1264 | } | ||
1265 | } else { | ||
1266 | sock_in = dup(STDIN_FILENO); | ||
1267 | sock_out = dup(STDOUT_FILENO); | ||
1268 | } | ||
1269 | /* | ||
1270 | * We intentionally do not close the descriptors 0, 1, and 2 | ||
1271 | * as our code for setting the descriptors won't work if | ||
1272 | * ttyfd happens to be one of those. | ||
1273 | */ | ||
1274 | if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { | ||
1275 | dup2(fd, STDIN_FILENO); | ||
1276 | dup2(fd, STDOUT_FILENO); | ||
1277 | if (fd > STDOUT_FILENO) | ||
1278 | close(fd); | ||
1279 | } | ||
1280 | debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); | ||
1281 | if ((options.protocol & SSH_PROTO_1) && | 1607 | if ((options.protocol & SSH_PROTO_1) && |
1282 | sensitive_data.server_key == NULL) | 1608 | sensitive_data.server_key == NULL) |
1283 | generate_ephemeral_server_key(); | 1609 | generate_ephemeral_server_key(); |
1284 | } else { | 1610 | } else { |
1285 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { | 1611 | server_listen(); |
1286 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | ||
1287 | continue; | ||
1288 | if (num_listen_socks >= MAX_LISTEN_SOCKS) | ||
1289 | fatal("Too many listen sockets. " | ||
1290 | "Enlarge MAX_LISTEN_SOCKS"); | ||
1291 | if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, | ||
1292 | ntop, sizeof(ntop), strport, sizeof(strport), | ||
1293 | NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { | ||
1294 | error("getnameinfo failed: %.100s", | ||
1295 | (ret != EAI_SYSTEM) ? gai_strerror(ret) : | ||
1296 | strerror(errno)); | ||
1297 | continue; | ||
1298 | } | ||
1299 | /* Create socket for listening. */ | ||
1300 | listen_sock = socket(ai->ai_family, ai->ai_socktype, | ||
1301 | ai->ai_protocol); | ||
1302 | if (listen_sock < 0) { | ||
1303 | /* kernel may not support ipv6 */ | ||
1304 | verbose("socket: %.100s", strerror(errno)); | ||
1305 | continue; | ||
1306 | } | ||
1307 | if (set_nonblock(listen_sock) == -1) { | ||
1308 | close(listen_sock); | ||
1309 | continue; | ||
1310 | } | ||
1311 | /* | ||
1312 | * Set socket options. | ||
1313 | * Allow local port reuse in TIME_WAIT. | ||
1314 | */ | ||
1315 | if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, | ||
1316 | &on, sizeof(on)) == -1) | ||
1317 | error("setsockopt SO_REUSEADDR: %s", strerror(errno)); | ||
1318 | |||
1319 | debug("Bind to port %s on %s.", strport, ntop); | ||
1320 | |||
1321 | /* Bind the socket to the desired port. */ | ||
1322 | if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { | ||
1323 | if (!ai->ai_next) | ||
1324 | error("Bind to port %s on %s failed: %.200s.", | ||
1325 | strport, ntop, strerror(errno)); | ||
1326 | close(listen_sock); | ||
1327 | continue; | ||
1328 | } | ||
1329 | listen_socks[num_listen_socks] = listen_sock; | ||
1330 | num_listen_socks++; | ||
1331 | |||
1332 | /* Start listening on the port. */ | ||
1333 | logit("Server listening on %s port %s.", ntop, strport); | ||
1334 | if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0) | ||
1335 | fatal("listen: %.100s", strerror(errno)); | ||
1336 | |||
1337 | } | ||
1338 | freeaddrinfo(options.listen_addrs); | ||
1339 | |||
1340 | if (!num_listen_socks) | ||
1341 | fatal("Cannot bind any address."); | ||
1342 | 1612 | ||
1343 | if (options.protocol & SSH_PROTO_1) | 1613 | if (options.protocol & SSH_PROTO_1) |
1344 | generate_ephemeral_server_key(); | 1614 | generate_ephemeral_server_key(); |
1345 | 1615 | ||
1346 | /* | ||
1347 | * Arrange to restart on SIGHUP. The handler needs | ||
1348 | * listen_sock. | ||
1349 | */ | ||
1350 | signal(SIGHUP, sighup_handler); | 1616 | signal(SIGHUP, sighup_handler); |
1351 | 1617 | signal(SIGCHLD, main_sigchld_handler); | |
1352 | signal(SIGTERM, sigterm_handler); | 1618 | signal(SIGTERM, sigterm_handler); |
1353 | signal(SIGQUIT, sigterm_handler); | 1619 | signal(SIGQUIT, sigterm_handler); |
1354 | 1620 | ||
1355 | /* Arrange SIGCHLD to be caught. */ | 1621 | /* |
1356 | signal(SIGCHLD, main_sigchld_handler); | 1622 | * Write out the pid file after the sigterm handler |
1357 | 1623 | * is setup and the listen sockets are bound | |
1358 | /* Write out the pid file after the sigterm handler is setup */ | 1624 | */ |
1359 | if (!debug_flag) { | 1625 | if (!debug_flag) { |
1360 | /* | 1626 | FILE *f = fopen(options.pid_file, "w"); |
1361 | * Record our pid in /var/run/sshd.pid to make it | 1627 | |
1362 | * easier to kill the correct sshd. We don't want to | ||
1363 | * do this before the bind above because the bind will | ||
1364 | * fail if there already is a daemon, and this will | ||
1365 | * overwrite any old pid in the file. | ||
1366 | */ | ||
1367 | f = fopen(options.pid_file, "wb"); | ||
1368 | if (f == NULL) { | 1628 | if (f == NULL) { |
1369 | error("Couldn't create pid file \"%s\": %s", | 1629 | error("Couldn't create pid file \"%s\": %s", |
1370 | options.pid_file, strerror(errno)); | 1630 | options.pid_file, strerror(errno)); |
@@ -1374,194 +1634,9 @@ main(int ac, char **av) | |||
1374 | } | 1634 | } |
1375 | } | 1635 | } |
1376 | 1636 | ||
1377 | /* setup fd set for listen */ | 1637 | /* Accept a connection and return in a forked child */ |
1378 | fdset = NULL; | 1638 | server_accept_loop(&sock_in, &sock_out, |
1379 | maxfd = 0; | 1639 | &newsock, config_s); |
1380 | for (i = 0; i < num_listen_socks; i++) | ||
1381 | if (listen_socks[i] > maxfd) | ||
1382 | maxfd = listen_socks[i]; | ||
1383 | /* pipes connected to unauthenticated childs */ | ||
1384 | startup_pipes = xmalloc(options.max_startups * sizeof(int)); | ||
1385 | for (i = 0; i < options.max_startups; i++) | ||
1386 | startup_pipes[i] = -1; | ||
1387 | |||
1388 | /* | ||
1389 | * Stay listening for connections until the system crashes or | ||
1390 | * the daemon is killed with a signal. | ||
1391 | */ | ||
1392 | for (;;) { | ||
1393 | if (received_sighup) | ||
1394 | sighup_restart(); | ||
1395 | if (fdset != NULL) | ||
1396 | xfree(fdset); | ||
1397 | fdsetsz = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask); | ||
1398 | fdset = (fd_set *)xmalloc(fdsetsz); | ||
1399 | memset(fdset, 0, fdsetsz); | ||
1400 | |||
1401 | for (i = 0; i < num_listen_socks; i++) | ||
1402 | FD_SET(listen_socks[i], fdset); | ||
1403 | for (i = 0; i < options.max_startups; i++) | ||
1404 | if (startup_pipes[i] != -1) | ||
1405 | FD_SET(startup_pipes[i], fdset); | ||
1406 | |||
1407 | /* Wait in select until there is a connection. */ | ||
1408 | ret = select(maxfd+1, fdset, NULL, NULL, NULL); | ||
1409 | if (ret < 0 && errno != EINTR) | ||
1410 | error("select: %.100s", strerror(errno)); | ||
1411 | if (received_sigterm) { | ||
1412 | logit("Received signal %d; terminating.", | ||
1413 | (int) received_sigterm); | ||
1414 | close_listen_socks(); | ||
1415 | unlink(options.pid_file); | ||
1416 | exit(255); | ||
1417 | } | ||
1418 | if (key_used && key_do_regen) { | ||
1419 | generate_ephemeral_server_key(); | ||
1420 | key_used = 0; | ||
1421 | key_do_regen = 0; | ||
1422 | } | ||
1423 | if (ret < 0) | ||
1424 | continue; | ||
1425 | |||
1426 | for (i = 0; i < options.max_startups; i++) | ||
1427 | if (startup_pipes[i] != -1 && | ||
1428 | FD_ISSET(startup_pipes[i], fdset)) { | ||
1429 | /* | ||
1430 | * the read end of the pipe is ready | ||
1431 | * if the child has closed the pipe | ||
1432 | * after successful authentication | ||
1433 | * or if the child has died | ||
1434 | */ | ||
1435 | close(startup_pipes[i]); | ||
1436 | startup_pipes[i] = -1; | ||
1437 | startups--; | ||
1438 | } | ||
1439 | for (i = 0; i < num_listen_socks; i++) { | ||
1440 | if (!FD_ISSET(listen_socks[i], fdset)) | ||
1441 | continue; | ||
1442 | fromlen = sizeof(from); | ||
1443 | newsock = accept(listen_socks[i], (struct sockaddr *)&from, | ||
1444 | &fromlen); | ||
1445 | if (newsock < 0) { | ||
1446 | if (errno != EINTR && errno != EWOULDBLOCK) | ||
1447 | error("accept: %.100s", strerror(errno)); | ||
1448 | continue; | ||
1449 | } | ||
1450 | if (unset_nonblock(newsock) == -1) { | ||
1451 | close(newsock); | ||
1452 | continue; | ||
1453 | } | ||
1454 | if (drop_connection(startups) == 1) { | ||
1455 | debug("drop connection #%d", startups); | ||
1456 | close(newsock); | ||
1457 | continue; | ||
1458 | } | ||
1459 | if (pipe(startup_p) == -1) { | ||
1460 | close(newsock); | ||
1461 | continue; | ||
1462 | } | ||
1463 | |||
1464 | if (rexec_flag && socketpair(AF_UNIX, | ||
1465 | SOCK_STREAM, 0, config_s) == -1) { | ||
1466 | error("reexec socketpair: %s", | ||
1467 | strerror(errno)); | ||
1468 | close(newsock); | ||
1469 | close(startup_p[0]); | ||
1470 | close(startup_p[1]); | ||
1471 | continue; | ||
1472 | } | ||
1473 | |||
1474 | for (j = 0; j < options.max_startups; j++) | ||
1475 | if (startup_pipes[j] == -1) { | ||
1476 | startup_pipes[j] = startup_p[0]; | ||
1477 | if (maxfd < startup_p[0]) | ||
1478 | maxfd = startup_p[0]; | ||
1479 | startups++; | ||
1480 | break; | ||
1481 | } | ||
1482 | |||
1483 | /* | ||
1484 | * Got connection. Fork a child to handle it, unless | ||
1485 | * we are in debugging mode. | ||
1486 | */ | ||
1487 | if (debug_flag) { | ||
1488 | /* | ||
1489 | * In debugging mode. Close the listening | ||
1490 | * socket, and start processing the | ||
1491 | * connection without forking. | ||
1492 | */ | ||
1493 | debug("Server will not fork when running in debugging mode."); | ||
1494 | close_listen_socks(); | ||
1495 | sock_in = newsock; | ||
1496 | sock_out = newsock; | ||
1497 | close(startup_p[0]); | ||
1498 | close(startup_p[1]); | ||
1499 | startup_pipe = -1; | ||
1500 | pid = getpid(); | ||
1501 | if (rexec_flag) { | ||
1502 | send_rexec_state(config_s[0], | ||
1503 | &cfg); | ||
1504 | close(config_s[0]); | ||
1505 | } | ||
1506 | break; | ||
1507 | } else { | ||
1508 | /* | ||
1509 | * Normal production daemon. Fork, and have | ||
1510 | * the child process the connection. The | ||
1511 | * parent continues listening. | ||
1512 | */ | ||
1513 | if ((pid = fork()) == 0) { | ||
1514 | /* | ||
1515 | * Child. Close the listening and max_startup | ||
1516 | * sockets. Start using the accepted socket. | ||
1517 | * Reinitialize logging (since our pid has | ||
1518 | * changed). We break out of the loop to handle | ||
1519 | * the connection. | ||
1520 | */ | ||
1521 | startup_pipe = startup_p[1]; | ||
1522 | close_startup_pipes(); | ||
1523 | close_listen_socks(); | ||
1524 | sock_in = newsock; | ||
1525 | sock_out = newsock; | ||
1526 | log_init(__progname, options.log_level, options.log_facility, log_stderr); | ||
1527 | if (rexec_flag) | ||
1528 | close(config_s[0]); | ||
1529 | break; | ||
1530 | } | ||
1531 | } | ||
1532 | |||
1533 | /* Parent. Stay in the loop. */ | ||
1534 | if (pid < 0) | ||
1535 | error("fork: %.100s", strerror(errno)); | ||
1536 | else | ||
1537 | debug("Forked child %ld.", (long)pid); | ||
1538 | |||
1539 | close(startup_p[1]); | ||
1540 | |||
1541 | if (rexec_flag) { | ||
1542 | send_rexec_state(config_s[0], &cfg); | ||
1543 | close(config_s[0]); | ||
1544 | close(config_s[1]); | ||
1545 | } | ||
1546 | |||
1547 | /* Mark that the key has been used (it was "given" to the child). */ | ||
1548 | if ((options.protocol & SSH_PROTO_1) && | ||
1549 | key_used == 0) { | ||
1550 | /* Schedule server key regeneration alarm. */ | ||
1551 | signal(SIGALRM, key_regeneration_alarm); | ||
1552 | alarm(options.key_regeneration_time); | ||
1553 | key_used = 1; | ||
1554 | } | ||
1555 | |||
1556 | arc4random_stir(); | ||
1557 | |||
1558 | /* Close the new socket (the child is now taking care of it). */ | ||
1559 | close(newsock); | ||
1560 | } | ||
1561 | /* child process check (or debug mode) */ | ||
1562 | if (num_listen_socks < 0) | ||
1563 | break; | ||
1564 | } | ||
1565 | } | 1640 | } |
1566 | 1641 | ||
1567 | /* This is the child processing a new connection. */ | 1642 | /* This is the child processing a new connection. */ |
@@ -1656,7 +1731,13 @@ main(int ac, char **av) | |||
1656 | * We use get_canonical_hostname with usedns = 0 instead of | 1731 | * We use get_canonical_hostname with usedns = 0 instead of |
1657 | * get_remote_ipaddr here so IP options will be checked. | 1732 | * get_remote_ipaddr here so IP options will be checked. |
1658 | */ | 1733 | */ |
1659 | remote_ip = get_canonical_hostname(0); | 1734 | (void) get_canonical_hostname(0); |
1735 | /* | ||
1736 | * The rest of the code depends on the fact that | ||
1737 | * get_remote_ipaddr() caches the remote ip, even if | ||
1738 | * the socket goes away. | ||
1739 | */ | ||
1740 | remote_ip = get_remote_ipaddr(); | ||
1660 | 1741 | ||
1661 | #ifdef SSH_AUDIT_EVENTS | 1742 | #ifdef SSH_AUDIT_EVENTS |
1662 | audit_connection_from(remote_ip, remote_port); | 1743 | audit_connection_from(remote_ip, remote_port); |
@@ -1752,8 +1833,7 @@ main(int ac, char **av) | |||
1752 | packet_set_nonblocking(); | 1833 | packet_set_nonblocking(); |
1753 | 1834 | ||
1754 | /* allocate authentication context */ | 1835 | /* allocate authentication context */ |
1755 | authctxt = xmalloc(sizeof(*authctxt)); | 1836 | authctxt = xcalloc(1, sizeof(*authctxt)); |
1756 | memset(authctxt, 0, sizeof(*authctxt)); | ||
1757 | 1837 | ||
1758 | authctxt->loginmsg = &loginmsg; | 1838 | authctxt->loginmsg = &loginmsg; |
1759 | 1839 | ||
@@ -1792,6 +1872,7 @@ main(int ac, char **av) | |||
1792 | */ | 1872 | */ |
1793 | alarm(0); | 1873 | alarm(0); |
1794 | signal(SIGALRM, SIG_DFL); | 1874 | signal(SIGALRM, SIG_DFL); |
1875 | authctxt->authenticated = 1; | ||
1795 | if (startup_pipe != -1) { | 1876 | if (startup_pipe != -1) { |
1796 | close(startup_pipe); | 1877 | close(startup_pipe); |
1797 | startup_pipe = -1; | 1878 | startup_pipe = -1; |
@@ -1844,11 +1925,14 @@ ssh1_session_key(BIGNUM *session_key_int) | |||
1844 | { | 1925 | { |
1845 | int rsafail = 0; | 1926 | int rsafail = 0; |
1846 | 1927 | ||
1847 | if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { | 1928 | if (BN_cmp(sensitive_data.server_key->rsa->n, |
1929 | sensitive_data.ssh1_host_key->rsa->n) > 0) { | ||
1848 | /* Server key has bigger modulus. */ | 1930 | /* Server key has bigger modulus. */ |
1849 | if (BN_num_bits(sensitive_data.server_key->rsa->n) < | 1931 | if (BN_num_bits(sensitive_data.server_key->rsa->n) < |
1850 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { | 1932 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + |
1851 | fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", | 1933 | SSH_KEY_BITS_RESERVED) { |
1934 | fatal("do_connection: %s: " | ||
1935 | "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", | ||
1852 | get_remote_ipaddr(), | 1936 | get_remote_ipaddr(), |
1853 | BN_num_bits(sensitive_data.server_key->rsa->n), | 1937 | BN_num_bits(sensitive_data.server_key->rsa->n), |
1854 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), | 1938 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), |
@@ -1863,8 +1947,10 @@ ssh1_session_key(BIGNUM *session_key_int) | |||
1863 | } else { | 1947 | } else { |
1864 | /* Host key has bigger modulus (or they are equal). */ | 1948 | /* Host key has bigger modulus (or they are equal). */ |
1865 | if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < | 1949 | if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < |
1866 | BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { | 1950 | BN_num_bits(sensitive_data.server_key->rsa->n) + |
1867 | fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", | 1951 | SSH_KEY_BITS_RESERVED) { |
1952 | fatal("do_connection: %s: " | ||
1953 | "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", | ||
1868 | get_remote_ipaddr(), | 1954 | get_remote_ipaddr(), |
1869 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), | 1955 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), |
1870 | BN_num_bits(sensitive_data.server_key->rsa->n), | 1956 | BN_num_bits(sensitive_data.server_key->rsa->n), |
@@ -1989,10 +2075,10 @@ do_ssh1_kex(void) | |||
1989 | * key is in the highest bits. | 2075 | * key is in the highest bits. |
1990 | */ | 2076 | */ |
1991 | if (!rsafail) { | 2077 | if (!rsafail) { |
1992 | BN_mask_bits(session_key_int, sizeof(session_key) * 8); | 2078 | (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); |
1993 | len = BN_num_bytes(session_key_int); | 2079 | len = BN_num_bytes(session_key_int); |
1994 | if (len < 0 || (u_int)len > sizeof(session_key)) { | 2080 | if (len < 0 || (u_int)len > sizeof(session_key)) { |
1995 | error("do_connection: bad session key len from %s: " | 2081 | error("do_ssh1_kex: bad session key len from %s: " |
1996 | "session_key_int %d > sizeof(session_key) %lu", | 2082 | "session_key_int %d > sizeof(session_key) %lu", |
1997 | get_remote_ipaddr(), len, (u_long)sizeof(session_key)); | 2083 | get_remote_ipaddr(), len, (u_long)sizeof(session_key)); |
1998 | rsafail++; | 2084 | rsafail++; |
@@ -2085,11 +2171,9 @@ do_ssh2_kex(void) | |||
2085 | myproposal[PROPOSAL_COMP_ALGS_CTOS] = | 2171 | myproposal[PROPOSAL_COMP_ALGS_CTOS] = |
2086 | myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com"; | 2172 | myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com"; |
2087 | } | 2173 | } |
2088 | 2174 | ||
2089 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); | 2175 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); |
2090 | 2176 | ||
2091 | /* start key exchange */ | ||
2092 | |||
2093 | #ifdef GSSAPI | 2177 | #ifdef GSSAPI |
2094 | { | 2178 | { |
2095 | char *orig; | 2179 | char *orig; |
@@ -2098,8 +2182,8 @@ do_ssh2_kex(void) | |||
2098 | orig = myproposal[PROPOSAL_KEX_ALGS]; | 2182 | orig = myproposal[PROPOSAL_KEX_ALGS]; |
2099 | 2183 | ||
2100 | /* | 2184 | /* |
2101 | * If we don't have a host key, then there's no point advertising | 2185 | * If we don't have a host key, then there's no point advertising |
2102 | * the other key exchange algorithms | 2186 | * the other key exchange algorithms |
2103 | */ | 2187 | */ |
2104 | 2188 | ||
2105 | if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) | 2189 | if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) |
@@ -2110,15 +2194,13 @@ do_ssh2_kex(void) | |||
2110 | else | 2194 | else |
2111 | gss = NULL; | 2195 | gss = NULL; |
2112 | 2196 | ||
2113 | if (gss && orig) { | 2197 | if (gss && orig) |
2114 | int len = strlen(orig) + strlen(gss) + 2; | 2198 | xasprintf(&newstr, "%s,%s", gss, orig); |
2115 | newstr = xmalloc(len); | 2199 | else if (gss) |
2116 | snprintf(newstr, len, "%s,%s", gss, orig); | ||
2117 | } else if (gss) { | ||
2118 | newstr = gss; | 2200 | newstr = gss; |
2119 | } else if (orig) { | 2201 | else if (orig) |
2120 | newstr = orig; | 2202 | newstr = orig; |
2121 | } | 2203 | |
2122 | /* | 2204 | /* |
2123 | * If we've got GSSAPI mechanisms, then we've got the 'null' host | 2205 | * If we've got GSSAPI mechanisms, then we've got the 'null' host |
2124 | * key alg, but we can't tell people about it unless its the only | 2206 | * key alg, but we can't tell people about it unless its the only |
@@ -2134,18 +2216,20 @@ do_ssh2_kex(void) | |||
2134 | } | 2216 | } |
2135 | #endif | 2217 | #endif |
2136 | 2218 | ||
2137 | /* start key exchange */ | 2219 | /* start key exchange */ |
2138 | kex = kex_setup(myproposal); | 2220 | kex = kex_setup(myproposal); |
2139 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 2221 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
2140 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 2222 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
2141 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 2223 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
2224 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | ||
2142 | #ifdef GSSAPI | 2225 | #ifdef GSSAPI |
2143 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; | 2226 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; |
2227 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; | ||
2144 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; | 2228 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; |
2145 | #endif | 2229 | #endif |
2146 | kex->server = 1; | 2230 | kex->server = 1; |
2147 | kex->client_version_string=client_version_string; | 2231 | kex->client_version_string=client_version_string; |
2148 | kex->server_version_string=server_version_string; | 2232 | kex->server_version_string=server_version_string; |
2149 | kex->load_host_key=&get_hostkey_by_type; | 2233 | kex->load_host_key=&get_hostkey_by_type; |
2150 | kex->host_key_index=&get_hostkey_index; | 2234 | kex->host_key_index=&get_hostkey_index; |
2151 | 2235 | ||