diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 471 |
1 files changed, 221 insertions, 250 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.516 2018/09/21 12:23:17 djm Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.533 2019/03/01 02:32:39 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -166,45 +166,38 @@ int debug_flag = 0; | |||
166 | * configuration, optionally using connection information provided by the | 166 | * configuration, optionally using connection information provided by the |
167 | * "-C" flag. | 167 | * "-C" flag. |
168 | */ | 168 | */ |
169 | int test_flag = 0; | 169 | static int test_flag = 0; |
170 | 170 | ||
171 | /* Flag indicating that the daemon is being started from inetd. */ | 171 | /* Flag indicating that the daemon is being started from inetd. */ |
172 | int inetd_flag = 0; | 172 | static int inetd_flag = 0; |
173 | 173 | ||
174 | /* Flag indicating that sshd should not detach and become a daemon. */ | 174 | /* Flag indicating that sshd should not detach and become a daemon. */ |
175 | int no_daemon_flag = 0; | 175 | static int no_daemon_flag = 0; |
176 | 176 | ||
177 | /* debug goes to stderr unless inetd_flag is set */ | 177 | /* debug goes to stderr unless inetd_flag is set */ |
178 | int log_stderr = 0; | 178 | static int log_stderr = 0; |
179 | 179 | ||
180 | /* Saved arguments to main(). */ | 180 | /* Saved arguments to main(). */ |
181 | char **saved_argv; | 181 | static char **saved_argv; |
182 | int saved_argc; | 182 | static int saved_argc; |
183 | 183 | ||
184 | /* re-exec */ | 184 | /* re-exec */ |
185 | int rexeced_flag = 0; | 185 | static int rexeced_flag = 0; |
186 | int rexec_flag = 1; | 186 | static int rexec_flag = 1; |
187 | int rexec_argc = 0; | 187 | static int rexec_argc = 0; |
188 | char **rexec_argv; | 188 | static char **rexec_argv; |
189 | 189 | ||
190 | /* | 190 | /* |
191 | * The sockets that the server is listening; this is used in the SIGHUP | 191 | * The sockets that the server is listening; this is used in the SIGHUP |
192 | * signal handler. | 192 | * signal handler. |
193 | */ | 193 | */ |
194 | #define MAX_LISTEN_SOCKS 16 | 194 | #define MAX_LISTEN_SOCKS 16 |
195 | int listen_socks[MAX_LISTEN_SOCKS]; | 195 | static int listen_socks[MAX_LISTEN_SOCKS]; |
196 | int num_listen_socks = 0; | 196 | static int num_listen_socks = 0; |
197 | |||
198 | /* | ||
199 | * the client's version string, passed by sshd2 in compat mode. if != NULL, | ||
200 | * sshd will skip the version-number exchange | ||
201 | */ | ||
202 | char *client_version_string = NULL; | ||
203 | char *server_version_string = NULL; | ||
204 | 197 | ||
205 | /* Daemon's agent connection */ | 198 | /* Daemon's agent connection */ |
206 | int auth_sock = -1; | 199 | int auth_sock = -1; |
207 | int have_agent = 0; | 200 | static int have_agent = 0; |
208 | 201 | ||
209 | /* | 202 | /* |
210 | * Any really sensitive data in the application is contained in this | 203 | * Any really sensitive data in the application is contained in this |
@@ -235,9 +228,26 @@ u_int session_id2_len = 0; | |||
235 | /* record remote hostname or ip */ | 228 | /* record remote hostname or ip */ |
236 | u_int utmp_len = HOST_NAME_MAX+1; | 229 | u_int utmp_len = HOST_NAME_MAX+1; |
237 | 230 | ||
238 | /* options.max_startup sized array of fd ints */ | 231 | /* |
239 | int *startup_pipes = NULL; | 232 | * startup_pipes/flags are used for tracking children of the listening sshd |
240 | int startup_pipe; /* in child */ | 233 | * process early in their lifespans. This tracking is needed for three things: |
234 | * | ||
235 | * 1) Implementing the MaxStartups limit of concurrent unauthenticated | ||
236 | * connections. | ||
237 | * 2) Avoiding a race condition for SIGHUP processing, where child processes | ||
238 | * may have listen_socks open that could collide with main listener process | ||
239 | * after it restarts. | ||
240 | * 3) Ensuring that rexec'd sshd processes have received their initial state | ||
241 | * from the parent listen process before handling SIGHUP. | ||
242 | * | ||
243 | * Child processes signal that they have completed closure of the listen_socks | ||
244 | * and (if applicable) received their rexec state by sending a char over their | ||
245 | * sock. Child processes signal that authentication has completed by closing | ||
246 | * the sock (or by exiting). | ||
247 | */ | ||
248 | static int *startup_pipes = NULL; | ||
249 | static int *startup_flags = NULL; /* Indicates child closed listener */ | ||
250 | static int startup_pipe = -1; /* in child */ | ||
241 | 251 | ||
242 | /* variables used for privilege separation */ | 252 | /* variables used for privilege separation */ |
243 | int use_privsep = -1; | 253 | int use_privsep = -1; |
@@ -245,8 +255,9 @@ struct monitor *pmonitor = NULL; | |||
245 | int privsep_is_preauth = 1; | 255 | int privsep_is_preauth = 1; |
246 | static int privsep_chroot = 1; | 256 | static int privsep_chroot = 1; |
247 | 257 | ||
248 | /* global authentication context */ | 258 | /* global connection state and authentication contexts */ |
249 | Authctxt *the_authctxt = NULL; | 259 | Authctxt *the_authctxt = NULL; |
260 | struct ssh *the_active_state; | ||
250 | 261 | ||
251 | /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ | 262 | /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ |
252 | struct sshauthopt *auth_opts = NULL; | 263 | struct sshauthopt *auth_opts = NULL; |
@@ -263,7 +274,7 @@ struct passwd *privsep_pw = NULL; | |||
263 | /* Prototypes for various functions defined later in this file. */ | 274 | /* Prototypes for various functions defined later in this file. */ |
264 | void destroy_sensitive_data(void); | 275 | void destroy_sensitive_data(void); |
265 | void demote_sensitive_data(void); | 276 | void demote_sensitive_data(void); |
266 | static void do_ssh2_kex(void); | 277 | static void do_ssh2_kex(struct ssh *); |
267 | 278 | ||
268 | /* | 279 | /* |
269 | * Close all listening sockets | 280 | * Close all listening sockets |
@@ -373,112 +384,11 @@ grace_alarm_handler(int sig) | |||
373 | kill(0, SIGTERM); | 384 | kill(0, SIGTERM); |
374 | } | 385 | } |
375 | 386 | ||
387 | /* XXX pre-format ipaddr/port so we don't need to access active_state */ | ||
376 | /* Log error and exit. */ | 388 | /* Log error and exit. */ |
377 | sigdie("Timeout before authentication for %s port %d", | 389 | sigdie("Timeout before authentication for %s port %d", |
378 | ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); | 390 | ssh_remote_ipaddr(the_active_state), |
379 | } | 391 | ssh_remote_port(the_active_state)); |
380 | |||
381 | static void | ||
382 | sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) | ||
383 | { | ||
384 | u_int i; | ||
385 | int remote_major, remote_minor; | ||
386 | char *s; | ||
387 | char buf[256]; /* Must not be larger than remote_version. */ | ||
388 | char remote_version[256]; /* Must be at least as big as buf. */ | ||
389 | |||
390 | xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n", | ||
391 | PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, | ||
392 | options.debian_banner ? SSH_RELEASE : SSH_RELEASE_MINIMUM, | ||
393 | *options.version_addendum == '\0' ? "" : " ", | ||
394 | options.version_addendum); | ||
395 | |||
396 | /* Send our protocol version identification. */ | ||
397 | if (atomicio(vwrite, sock_out, server_version_string, | ||
398 | strlen(server_version_string)) | ||
399 | != strlen(server_version_string)) { | ||
400 | logit("Could not write ident string to %s port %d", | ||
401 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
402 | cleanup_exit(255); | ||
403 | } | ||
404 | |||
405 | /* Read other sides version identification. */ | ||
406 | memset(buf, 0, sizeof(buf)); | ||
407 | for (i = 0; i < sizeof(buf) - 1; i++) { | ||
408 | if (atomicio(read, sock_in, &buf[i], 1) != 1) { | ||
409 | logit("Did not receive identification string " | ||
410 | "from %s port %d", | ||
411 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
412 | cleanup_exit(255); | ||
413 | } | ||
414 | if (buf[i] == '\r') { | ||
415 | buf[i] = 0; | ||
416 | /* Kludge for F-Secure Macintosh < 1.0.2 */ | ||
417 | if (i == 12 && | ||
418 | strncmp(buf, "SSH-1.5-W1.0", 12) == 0) | ||
419 | break; | ||
420 | continue; | ||
421 | } | ||
422 | if (buf[i] == '\n') { | ||
423 | buf[i] = 0; | ||
424 | break; | ||
425 | } | ||
426 | } | ||
427 | buf[sizeof(buf) - 1] = 0; | ||
428 | client_version_string = xstrdup(buf); | ||
429 | |||
430 | /* | ||
431 | * Check that the versions match. In future this might accept | ||
432 | * several versions and set appropriate flags to handle them. | ||
433 | */ | ||
434 | if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", | ||
435 | &remote_major, &remote_minor, remote_version) != 3) { | ||
436 | s = "Protocol mismatch.\n"; | ||
437 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | ||
438 | logit("Bad protocol version identification '%.100s' " | ||
439 | "from %s port %d", client_version_string, | ||
440 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
441 | close(sock_in); | ||
442 | close(sock_out); | ||
443 | cleanup_exit(255); | ||
444 | } | ||
445 | debug("Client protocol version %d.%d; client software version %.100s", | ||
446 | remote_major, remote_minor, remote_version); | ||
447 | |||
448 | ssh->compat = compat_datafellows(remote_version); | ||
449 | |||
450 | if ((ssh->compat & SSH_BUG_PROBE) != 0) { | ||
451 | logit("probed from %s port %d with %s. Don't panic.", | ||
452 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
453 | client_version_string); | ||
454 | cleanup_exit(255); | ||
455 | } | ||
456 | if ((ssh->compat & SSH_BUG_SCANNER) != 0) { | ||
457 | logit("scanned from %s port %d with %s. Don't panic.", | ||
458 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
459 | client_version_string); | ||
460 | cleanup_exit(255); | ||
461 | } | ||
462 | if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { | ||
463 | logit("Client version \"%.100s\" uses unsafe RSA signature " | ||
464 | "scheme; disabling use of RSA keys", remote_version); | ||
465 | } | ||
466 | |||
467 | chop(server_version_string); | ||
468 | debug("Local version string %.200s", server_version_string); | ||
469 | |||
470 | if (remote_major != 2 && | ||
471 | !(remote_major == 1 && remote_minor == 99)) { | ||
472 | s = "Protocol major versions differ.\n"; | ||
473 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | ||
474 | close(sock_in); | ||
475 | close(sock_out); | ||
476 | logit("Protocol major versions differ for %s port %d: " | ||
477 | "%.200s vs. %.200s", | ||
478 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
479 | server_version_string, client_version_string); | ||
480 | cleanup_exit(255); | ||
481 | } | ||
482 | } | 392 | } |
483 | 393 | ||
484 | /* Destroy the host and server keys. They will no longer be needed. */ | 394 | /* Destroy the host and server keys. They will no longer be needed. */ |
@@ -580,7 +490,7 @@ privsep_preauth_child(void) | |||
580 | } | 490 | } |
581 | 491 | ||
582 | static int | 492 | static int |
583 | privsep_preauth(Authctxt *authctxt) | 493 | privsep_preauth(struct ssh *ssh) |
584 | { | 494 | { |
585 | int status, r; | 495 | int status, r; |
586 | pid_t pid; | 496 | pid_t pid; |
@@ -589,7 +499,7 @@ privsep_preauth(Authctxt *authctxt) | |||
589 | /* Set up unprivileged child process to deal with network data */ | 499 | /* Set up unprivileged child process to deal with network data */ |
590 | pmonitor = monitor_init(); | 500 | pmonitor = monitor_init(); |
591 | /* Store a pointer to the kex for later rekeying */ | 501 | /* Store a pointer to the kex for later rekeying */ |
592 | pmonitor->m_pkex = &active_state->kex; | 502 | pmonitor->m_pkex = &ssh->kex; |
593 | 503 | ||
594 | if (use_privsep == PRIVSEP_ON) | 504 | if (use_privsep == PRIVSEP_ON) |
595 | box = ssh_sandbox_init(pmonitor); | 505 | box = ssh_sandbox_init(pmonitor); |
@@ -610,7 +520,7 @@ privsep_preauth(Authctxt *authctxt) | |||
610 | } | 520 | } |
611 | if (box != NULL) | 521 | if (box != NULL) |
612 | ssh_sandbox_parent_preauth(box, pid); | 522 | ssh_sandbox_parent_preauth(box, pid); |
613 | monitor_child_preauth(authctxt, pmonitor); | 523 | monitor_child_preauth(ssh, pmonitor); |
614 | 524 | ||
615 | /* Wait for the child's exit status */ | 525 | /* Wait for the child's exit status */ |
616 | while (waitpid(pid, &status, 0) < 0) { | 526 | while (waitpid(pid, &status, 0) < 0) { |
@@ -649,7 +559,7 @@ privsep_preauth(Authctxt *authctxt) | |||
649 | } | 559 | } |
650 | 560 | ||
651 | static void | 561 | static void |
652 | privsep_postauth(Authctxt *authctxt) | 562 | privsep_postauth(struct ssh *ssh, Authctxt *authctxt) |
653 | { | 563 | { |
654 | #ifdef DISABLE_FD_PASSING | 564 | #ifdef DISABLE_FD_PASSING |
655 | if (1) { | 565 | if (1) { |
@@ -670,8 +580,8 @@ privsep_postauth(Authctxt *authctxt) | |||
670 | else if (pmonitor->m_pid != 0) { | 580 | else if (pmonitor->m_pid != 0) { |
671 | verbose("User child is on pid %ld", (long)pmonitor->m_pid); | 581 | verbose("User child is on pid %ld", (long)pmonitor->m_pid); |
672 | sshbuf_reset(loginmsg); | 582 | sshbuf_reset(loginmsg); |
673 | monitor_clear_keystate(pmonitor); | 583 | monitor_clear_keystate(ssh, pmonitor); |
674 | monitor_child_postauth(pmonitor); | 584 | monitor_child_postauth(ssh, pmonitor); |
675 | 585 | ||
676 | /* NEVERREACHED */ | 586 | /* NEVERREACHED */ |
677 | exit(0); | 587 | exit(0); |
@@ -692,13 +602,13 @@ privsep_postauth(Authctxt *authctxt) | |||
692 | 602 | ||
693 | skip: | 603 | skip: |
694 | /* It is safe now to apply the key state */ | 604 | /* It is safe now to apply the key state */ |
695 | monitor_apply_keystate(pmonitor); | 605 | monitor_apply_keystate(ssh, pmonitor); |
696 | 606 | ||
697 | /* | 607 | /* |
698 | * Tell the packet layer that authentication was successful, since | 608 | * Tell the packet layer that authentication was successful, since |
699 | * this information is not part of the key state. | 609 | * this information is not part of the key state. |
700 | */ | 610 | */ |
701 | packet_set_authenticated(); | 611 | ssh_packet_set_authenticated(ssh); |
702 | } | 612 | } |
703 | 613 | ||
704 | static void | 614 | static void |
@@ -865,7 +775,7 @@ notify_hostkeys(struct ssh *ssh) | |||
865 | char *fp; | 775 | char *fp; |
866 | 776 | ||
867 | /* Some clients cannot cope with the hostkeys message, skip those. */ | 777 | /* Some clients cannot cope with the hostkeys message, skip those. */ |
868 | if (datafellows & SSH_BUG_HOSTKEYS) | 778 | if (ssh->compat & SSH_BUG_HOSTKEYS) |
869 | return; | 779 | return; |
870 | 780 | ||
871 | if ((buf = sshbuf_new()) == NULL) | 781 | if ((buf = sshbuf_new()) == NULL) |
@@ -881,21 +791,29 @@ notify_hostkeys(struct ssh *ssh) | |||
881 | sshkey_ssh_name(key), fp); | 791 | sshkey_ssh_name(key), fp); |
882 | free(fp); | 792 | free(fp); |
883 | if (nkeys == 0) { | 793 | if (nkeys == 0) { |
884 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 794 | /* |
885 | packet_put_cstring("hostkeys-00@openssh.com"); | 795 | * Start building the request when we find the |
886 | packet_put_char(0); /* want-reply */ | 796 | * first usable key. |
797 | */ | ||
798 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || | ||
799 | (r = sshpkt_put_cstring(ssh, "hostkeys-00@openssh.com")) != 0 || | ||
800 | (r = sshpkt_put_u8(ssh, 0)) != 0) /* want reply */ | ||
801 | sshpkt_fatal(ssh, r, "%s: start request", __func__); | ||
887 | } | 802 | } |
803 | /* Append the key to the request */ | ||
888 | sshbuf_reset(buf); | 804 | sshbuf_reset(buf); |
889 | if ((r = sshkey_putb(key, buf)) != 0) | 805 | if ((r = sshkey_putb(key, buf)) != 0) |
890 | fatal("%s: couldn't put hostkey %d: %s", | 806 | fatal("%s: couldn't put hostkey %d: %s", |
891 | __func__, i, ssh_err(r)); | 807 | __func__, i, ssh_err(r)); |
892 | packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf)); | 808 | if ((r = sshpkt_put_stringb(ssh, buf)) != 0) |
809 | sshpkt_fatal(ssh, r, "%s: append key", __func__); | ||
893 | nkeys++; | 810 | nkeys++; |
894 | } | 811 | } |
895 | debug3("%s: sent %u hostkeys", __func__, nkeys); | 812 | debug3("%s: sent %u hostkeys", __func__, nkeys); |
896 | if (nkeys == 0) | 813 | if (nkeys == 0) |
897 | fatal("%s: no hostkeys", __func__); | 814 | debug3("%s: no hostkeys", __func__); |
898 | packet_send(); | 815 | else if ((r = sshpkt_send(ssh)) != 0) |
816 | sshpkt_fatal(ssh, r, "%s: send", __func__); | ||
899 | sshbuf_free(buf); | 817 | sshbuf_free(buf); |
900 | } | 818 | } |
901 | 819 | ||
@@ -933,7 +851,7 @@ usage(void) | |||
933 | fprintf(stderr, "%s, %s\n", | 851 | fprintf(stderr, "%s, %s\n", |
934 | SSH_RELEASE, | 852 | SSH_RELEASE, |
935 | #ifdef WITH_OPENSSL | 853 | #ifdef WITH_OPENSSL |
936 | SSLeay_version(SSLEAY_VERSION) | 854 | OpenSSL_version(OPENSSL_VERSION) |
937 | #else | 855 | #else |
938 | "without OpenSSL" | 856 | "without OpenSSL" |
939 | #endif | 857 | #endif |
@@ -1015,14 +933,9 @@ server_accept_inetd(int *sock_in, int *sock_out) | |||
1015 | { | 933 | { |
1016 | int fd; | 934 | int fd; |
1017 | 935 | ||
1018 | startup_pipe = -1; | ||
1019 | if (rexeced_flag) { | 936 | if (rexeced_flag) { |
1020 | close(REEXEC_CONFIG_PASS_FD); | 937 | close(REEXEC_CONFIG_PASS_FD); |
1021 | *sock_in = *sock_out = dup(STDIN_FILENO); | 938 | *sock_in = *sock_out = dup(STDIN_FILENO); |
1022 | if (!debug_flag) { | ||
1023 | startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); | ||
1024 | close(REEXEC_STARTUP_PIPE_FD); | ||
1025 | } | ||
1026 | } else { | 939 | } else { |
1027 | *sock_in = dup(STDIN_FILENO); | 940 | *sock_in = dup(STDIN_FILENO); |
1028 | *sock_out = dup(STDOUT_FILENO); | 941 | *sock_out = dup(STDOUT_FILENO); |
@@ -1147,8 +1060,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1147 | { | 1060 | { |
1148 | fd_set *fdset; | 1061 | fd_set *fdset; |
1149 | int i, j, ret, maxfd; | 1062 | int i, j, ret, maxfd; |
1150 | int startups = 0; | 1063 | int startups = 0, listening = 0, lameduck = 0; |
1151 | int startup_p[2] = { -1 , -1 }; | 1064 | int startup_p[2] = { -1 , -1 }; |
1065 | char c = 0; | ||
1152 | struct sockaddr_storage from; | 1066 | struct sockaddr_storage from; |
1153 | socklen_t fromlen; | 1067 | socklen_t fromlen; |
1154 | pid_t pid; | 1068 | pid_t pid; |
@@ -1162,6 +1076,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1162 | maxfd = listen_socks[i]; | 1076 | maxfd = listen_socks[i]; |
1163 | /* pipes connected to unauthenticated childs */ | 1077 | /* pipes connected to unauthenticated childs */ |
1164 | startup_pipes = xcalloc(options.max_startups, sizeof(int)); | 1078 | startup_pipes = xcalloc(options.max_startups, sizeof(int)); |
1079 | startup_flags = xcalloc(options.max_startups, sizeof(int)); | ||
1165 | for (i = 0; i < options.max_startups; i++) | 1080 | for (i = 0; i < options.max_startups; i++) |
1166 | startup_pipes[i] = -1; | 1081 | startup_pipes[i] = -1; |
1167 | 1082 | ||
@@ -1170,8 +1085,15 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1170 | * the daemon is killed with a signal. | 1085 | * the daemon is killed with a signal. |
1171 | */ | 1086 | */ |
1172 | for (;;) { | 1087 | for (;;) { |
1173 | if (received_sighup) | 1088 | if (received_sighup) { |
1174 | sighup_restart(); | 1089 | if (!lameduck) { |
1090 | debug("Received SIGHUP; waiting for children"); | ||
1091 | close_listen_socks(); | ||
1092 | lameduck = 1; | ||
1093 | } | ||
1094 | if (listening <= 0) | ||
1095 | sighup_restart(); | ||
1096 | } | ||
1175 | free(fdset); | 1097 | free(fdset); |
1176 | fdset = xcalloc(howmany(maxfd + 1, NFDBITS), | 1098 | fdset = xcalloc(howmany(maxfd + 1, NFDBITS), |
1177 | sizeof(fd_mask)); | 1099 | sizeof(fd_mask)); |
@@ -1197,19 +1119,37 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1197 | if (ret < 0) | 1119 | if (ret < 0) |
1198 | continue; | 1120 | continue; |
1199 | 1121 | ||
1200 | for (i = 0; i < options.max_startups; i++) | 1122 | for (i = 0; i < options.max_startups; i++) { |
1201 | if (startup_pipes[i] != -1 && | 1123 | if (startup_pipes[i] == -1 || |
1202 | FD_ISSET(startup_pipes[i], fdset)) { | 1124 | !FD_ISSET(startup_pipes[i], fdset)) |
1203 | /* | 1125 | continue; |
1204 | * the read end of the pipe is ready | 1126 | switch (read(startup_pipes[i], &c, sizeof(c))) { |
1205 | * if the child has closed the pipe | 1127 | case -1: |
1206 | * after successful authentication | 1128 | if (errno == EINTR || errno == EAGAIN) |
1207 | * or if the child has died | 1129 | continue; |
1208 | */ | 1130 | if (errno != EPIPE) { |
1131 | error("%s: startup pipe %d (fd=%d): " | ||
1132 | "read %s", __func__, i, | ||
1133 | startup_pipes[i], strerror(errno)); | ||
1134 | } | ||
1135 | /* FALLTHROUGH */ | ||
1136 | case 0: | ||
1137 | /* child exited or completed auth */ | ||
1209 | close(startup_pipes[i]); | 1138 | close(startup_pipes[i]); |
1210 | startup_pipes[i] = -1; | 1139 | startup_pipes[i] = -1; |
1211 | startups--; | 1140 | startups--; |
1141 | if (startup_flags[i]) | ||
1142 | listening--; | ||
1143 | break; | ||
1144 | case 1: | ||
1145 | /* child has finished preliminaries */ | ||
1146 | if (startup_flags[i]) { | ||
1147 | listening--; | ||
1148 | startup_flags[i] = 0; | ||
1149 | } | ||
1150 | break; | ||
1212 | } | 1151 | } |
1152 | } | ||
1213 | for (i = 0; i < num_listen_socks; i++) { | 1153 | for (i = 0; i < num_listen_socks; i++) { |
1214 | if (!FD_ISSET(listen_socks[i], fdset)) | 1154 | if (!FD_ISSET(listen_socks[i], fdset)) |
1215 | continue; | 1155 | continue; |
@@ -1263,6 +1203,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1263 | if (maxfd < startup_p[0]) | 1203 | if (maxfd < startup_p[0]) |
1264 | maxfd = startup_p[0]; | 1204 | maxfd = startup_p[0]; |
1265 | startups++; | 1205 | startups++; |
1206 | startup_flags[j] = 1; | ||
1266 | break; | 1207 | break; |
1267 | } | 1208 | } |
1268 | 1209 | ||
@@ -1288,7 +1229,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1288 | send_rexec_state(config_s[0], cfg); | 1229 | send_rexec_state(config_s[0], cfg); |
1289 | close(config_s[0]); | 1230 | close(config_s[0]); |
1290 | } | 1231 | } |
1291 | break; | 1232 | return; |
1292 | } | 1233 | } |
1293 | 1234 | ||
1294 | /* | 1235 | /* |
@@ -1297,13 +1238,14 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1297 | * parent continues listening. | 1238 | * parent continues listening. |
1298 | */ | 1239 | */ |
1299 | platform_pre_fork(); | 1240 | platform_pre_fork(); |
1241 | listening++; | ||
1300 | if ((pid = fork()) == 0) { | 1242 | if ((pid = fork()) == 0) { |
1301 | /* | 1243 | /* |
1302 | * Child. Close the listening and | 1244 | * Child. Close the listening and |
1303 | * max_startup sockets. Start using | 1245 | * max_startup sockets. Start using |
1304 | * the accepted socket. Reinitialize | 1246 | * the accepted socket. Reinitialize |
1305 | * logging (since our pid has changed). | 1247 | * logging (since our pid has changed). |
1306 | * We break out of the loop to handle | 1248 | * We return from this function to handle |
1307 | * the connection. | 1249 | * the connection. |
1308 | */ | 1250 | */ |
1309 | platform_post_fork_child(); | 1251 | platform_post_fork_child(); |
@@ -1318,7 +1260,18 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1318 | log_stderr); | 1260 | log_stderr); |
1319 | if (rexec_flag) | 1261 | if (rexec_flag) |
1320 | close(config_s[0]); | 1262 | close(config_s[0]); |
1321 | break; | 1263 | else { |
1264 | /* | ||
1265 | * Signal parent that the preliminaries | ||
1266 | * for this child are complete. For the | ||
1267 | * re-exec case, this happens after the | ||
1268 | * child has received the rexec state | ||
1269 | * from the server. | ||
1270 | */ | ||
1271 | (void)atomicio(vwrite, startup_pipe, | ||
1272 | "\0", 1); | ||
1273 | } | ||
1274 | return; | ||
1322 | } | 1275 | } |
1323 | 1276 | ||
1324 | /* Parent. Stay in the loop. */ | 1277 | /* Parent. Stay in the loop. */ |
@@ -1350,10 +1303,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1350 | #endif | 1303 | #endif |
1351 | explicit_bzero(rnd, sizeof(rnd)); | 1304 | explicit_bzero(rnd, sizeof(rnd)); |
1352 | } | 1305 | } |
1353 | |||
1354 | /* child process check (or debug mode) */ | ||
1355 | if (num_listen_socks < 0) | ||
1356 | break; | ||
1357 | } | 1306 | } |
1358 | } | 1307 | } |
1359 | 1308 | ||
@@ -1526,6 +1475,8 @@ main(int ac, char **av) | |||
1526 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 1475 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
1527 | sanitise_stdfd(); | 1476 | sanitise_stdfd(); |
1528 | 1477 | ||
1478 | seed_rng(); | ||
1479 | |||
1529 | /* Initialize configuration options to their default values. */ | 1480 | /* Initialize configuration options to their default values. */ |
1530 | initialize_server_options(&options); | 1481 | initialize_server_options(&options); |
1531 | 1482 | ||
@@ -1604,7 +1555,7 @@ main(int ac, char **av) | |||
1604 | break; | 1555 | break; |
1605 | case 'h': | 1556 | case 'h': |
1606 | servconf_add_hostkey("[command-line]", 0, | 1557 | servconf_add_hostkey("[command-line]", 0, |
1607 | &options, optarg); | 1558 | &options, optarg, 1); |
1608 | break; | 1559 | break; |
1609 | case 't': | 1560 | case 't': |
1610 | test_flag = 1; | 1561 | test_flag = 1; |
@@ -1613,7 +1564,7 @@ main(int ac, char **av) | |||
1613 | test_flag = 2; | 1564 | test_flag = 2; |
1614 | break; | 1565 | break; |
1615 | case 'C': | 1566 | case 'C': |
1616 | connection_info = get_connection_info(0, 0); | 1567 | connection_info = get_connection_info(ssh, 0, 0); |
1617 | if (parse_server_match_testspec(connection_info, | 1568 | if (parse_server_match_testspec(connection_info, |
1618 | optarg) == -1) | 1569 | optarg) == -1) |
1619 | exit(1); | 1570 | exit(1); |
@@ -1640,17 +1591,13 @@ main(int ac, char **av) | |||
1640 | } | 1591 | } |
1641 | if (rexeced_flag || inetd_flag) | 1592 | if (rexeced_flag || inetd_flag) |
1642 | rexec_flag = 0; | 1593 | rexec_flag = 0; |
1643 | if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/'))) | 1594 | if (!test_flag && rexec_flag && !path_absolute(av[0])) |
1644 | fatal("sshd re-exec requires execution with an absolute path"); | 1595 | fatal("sshd re-exec requires execution with an absolute path"); |
1645 | if (rexeced_flag) | 1596 | if (rexeced_flag) |
1646 | closefrom(REEXEC_MIN_FREE_FD); | 1597 | closefrom(REEXEC_MIN_FREE_FD); |
1647 | else | 1598 | else |
1648 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); | 1599 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); |
1649 | 1600 | ||
1650 | #ifdef WITH_OPENSSL | ||
1651 | OpenSSL_add_all_algorithms(); | ||
1652 | #endif | ||
1653 | |||
1654 | /* If requested, redirect the logs to the specified logfile. */ | 1601 | /* If requested, redirect the logs to the specified logfile. */ |
1655 | if (logfile != NULL) | 1602 | if (logfile != NULL) |
1656 | log_redirect_stderr_to(logfile); | 1603 | log_redirect_stderr_to(logfile); |
@@ -1685,16 +1632,24 @@ main(int ac, char **av) | |||
1685 | /* Fetch our configuration */ | 1632 | /* Fetch our configuration */ |
1686 | if ((cfg = sshbuf_new()) == NULL) | 1633 | if ((cfg = sshbuf_new()) == NULL) |
1687 | fatal("%s: sshbuf_new failed", __func__); | 1634 | fatal("%s: sshbuf_new failed", __func__); |
1688 | if (rexeced_flag) | 1635 | if (rexeced_flag) { |
1689 | recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); | 1636 | recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); |
1637 | if (!debug_flag) { | ||
1638 | startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); | ||
1639 | close(REEXEC_STARTUP_PIPE_FD); | ||
1640 | /* | ||
1641 | * Signal parent that this child is at a point where | ||
1642 | * they can go away if they have a SIGHUP pending. | ||
1643 | */ | ||
1644 | (void)atomicio(vwrite, startup_pipe, "\0", 1); | ||
1645 | } | ||
1646 | } | ||
1690 | else if (strcasecmp(config_file_name, "none") != 0) | 1647 | else if (strcasecmp(config_file_name, "none") != 0) |
1691 | load_server_config(config_file_name, cfg); | 1648 | load_server_config(config_file_name, cfg); |
1692 | 1649 | ||
1693 | parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, | 1650 | parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, |
1694 | cfg, NULL); | 1651 | cfg, NULL); |
1695 | 1652 | ||
1696 | seed_rng(); | ||
1697 | |||
1698 | /* Fill in default values for those options not explicitly set. */ | 1653 | /* Fill in default values for those options not explicitly set. */ |
1699 | fill_default_server_options(&options); | 1654 | fill_default_server_options(&options); |
1700 | 1655 | ||
@@ -1739,7 +1694,7 @@ main(int ac, char **av) | |||
1739 | 1694 | ||
1740 | debug("sshd version %s, %s", SSH_VERSION, | 1695 | debug("sshd version %s, %s", SSH_VERSION, |
1741 | #ifdef WITH_OPENSSL | 1696 | #ifdef WITH_OPENSSL |
1742 | SSLeay_version(SSLEAY_VERSION) | 1697 | OpenSSL_version(OPENSSL_VERSION) |
1743 | #else | 1698 | #else |
1744 | "without OpenSSL" | 1699 | "without OpenSSL" |
1745 | #endif | 1700 | #endif |
@@ -1776,15 +1731,18 @@ main(int ac, char **av) | |||
1776 | } | 1731 | } |
1777 | 1732 | ||
1778 | for (i = 0; i < options.num_host_key_files; i++) { | 1733 | for (i = 0; i < options.num_host_key_files; i++) { |
1734 | int ll = options.host_key_file_userprovided[i] ? | ||
1735 | SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_DEBUG1; | ||
1736 | |||
1779 | if (options.host_key_files[i] == NULL) | 1737 | if (options.host_key_files[i] == NULL) |
1780 | continue; | 1738 | continue; |
1781 | if ((r = sshkey_load_private(options.host_key_files[i], "", | 1739 | if ((r = sshkey_load_private(options.host_key_files[i], "", |
1782 | &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) | 1740 | &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) |
1783 | error("Error loading host key \"%s\": %s", | 1741 | do_log2(ll, "Unable to load host key \"%s\": %s", |
1784 | options.host_key_files[i], ssh_err(r)); | 1742 | options.host_key_files[i], ssh_err(r)); |
1785 | if ((r = sshkey_load_public(options.host_key_files[i], | 1743 | if ((r = sshkey_load_public(options.host_key_files[i], |
1786 | &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) | 1744 | &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) |
1787 | error("Error loading host key \"%s\": %s", | 1745 | do_log2(ll, "Unable to load host key \"%s\": %s", |
1788 | options.host_key_files[i], ssh_err(r)); | 1746 | options.host_key_files[i], ssh_err(r)); |
1789 | if (pubkey == NULL && key != NULL) | 1747 | if (pubkey == NULL && key != NULL) |
1790 | if ((r = sshkey_from_private(key, &pubkey)) != 0) | 1748 | if ((r = sshkey_from_private(key, &pubkey)) != 0) |
@@ -1801,7 +1759,7 @@ main(int ac, char **av) | |||
1801 | keytype = key->type; | 1759 | keytype = key->type; |
1802 | accumulate_host_timing_secret(cfg, key); | 1760 | accumulate_host_timing_secret(cfg, key); |
1803 | } else { | 1761 | } else { |
1804 | error("Could not load host key: %s", | 1762 | do_log2(ll, "Unable to load host key: %s", |
1805 | options.host_key_files[i]); | 1763 | options.host_key_files[i]); |
1806 | sensitive_data.host_keys[i] = NULL; | 1764 | sensitive_data.host_keys[i] = NULL; |
1807 | sensitive_data.host_pubkeys[i] = NULL; | 1765 | sensitive_data.host_pubkeys[i] = NULL; |
@@ -1826,13 +1784,11 @@ main(int ac, char **av) | |||
1826 | free(fp); | 1784 | free(fp); |
1827 | } | 1785 | } |
1828 | accumulate_host_timing_secret(cfg, NULL); | 1786 | accumulate_host_timing_secret(cfg, NULL); |
1829 | #ifndef GSSAPI | ||
1830 | /* The GSSAPI key exchange can run without a host key */ | 1787 | /* The GSSAPI key exchange can run without a host key */ |
1831 | if (!sensitive_data.have_ssh2_key) { | 1788 | if (!sensitive_data.have_ssh2_key && !options.gss_keyex) { |
1832 | logit("sshd: no hostkeys available -- exiting."); | 1789 | logit("sshd: no hostkeys available -- exiting."); |
1833 | exit(1); | 1790 | exit(1); |
1834 | } | 1791 | } |
1835 | #endif | ||
1836 | 1792 | ||
1837 | /* | 1793 | /* |
1838 | * Load certificates. They are stored in an array at identical | 1794 | * Load certificates. They are stored in an array at identical |
@@ -1902,7 +1858,7 @@ main(int ac, char **av) | |||
1902 | * use a blank one that will cause no predicate to match. | 1858 | * use a blank one that will cause no predicate to match. |
1903 | */ | 1859 | */ |
1904 | if (connection_info == NULL) | 1860 | if (connection_info == NULL) |
1905 | connection_info = get_connection_info(0, 0); | 1861 | connection_info = get_connection_info(ssh, 0, 0); |
1906 | parse_server_match_config(&options, connection_info); | 1862 | parse_server_match_config(&options, connection_info); |
1907 | dump_config(&options); | 1863 | dump_config(&options); |
1908 | } | 1864 | } |
@@ -2082,9 +2038,10 @@ main(int ac, char **av) | |||
2082 | * Register our connection. This turns encryption off because we do | 2038 | * Register our connection. This turns encryption off because we do |
2083 | * not have a key. | 2039 | * not have a key. |
2084 | */ | 2040 | */ |
2085 | packet_set_connection(sock_in, sock_out); | 2041 | if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) |
2086 | packet_set_server(); | 2042 | fatal("Unable to create connection"); |
2087 | ssh = active_state; /* XXX */ | 2043 | the_active_state = ssh; |
2044 | ssh_packet_set_server(ssh); | ||
2088 | 2045 | ||
2089 | check_ip_options(ssh); | 2046 | check_ip_options(ssh); |
2090 | 2047 | ||
@@ -2094,7 +2051,7 @@ main(int ac, char **av) | |||
2094 | process_permitopen(ssh, &options); | 2051 | process_permitopen(ssh, &options); |
2095 | 2052 | ||
2096 | /* Set SO_KEEPALIVE if requested. */ | 2053 | /* Set SO_KEEPALIVE if requested. */ |
2097 | if (options.tcp_keep_alive && packet_connection_is_on_socket() && | 2054 | if (options.tcp_keep_alive && ssh_packet_connection_is_on_socket(ssh) && |
2098 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) | 2055 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) |
2099 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 2056 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
2100 | 2057 | ||
@@ -2120,7 +2077,7 @@ main(int ac, char **av) | |||
2120 | allow_severity = options.log_facility|LOG_INFO; | 2077 | allow_severity = options.log_facility|LOG_INFO; |
2121 | deny_severity = options.log_facility|LOG_WARNING; | 2078 | deny_severity = options.log_facility|LOG_WARNING; |
2122 | /* Check whether logins are denied from this host. */ | 2079 | /* Check whether logins are denied from this host. */ |
2123 | if (packet_connection_is_on_socket()) { | 2080 | if (ssh_packet_connection_is_on_socket(ssh)) { |
2124 | struct request_info req; | 2081 | struct request_info req; |
2125 | 2082 | ||
2126 | request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); | 2083 | request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); |
@@ -2212,11 +2169,15 @@ main(int ac, char **av) | |||
2212 | if (!debug_flag) | 2169 | if (!debug_flag) |
2213 | alarm(options.login_grace_time); | 2170 | alarm(options.login_grace_time); |
2214 | 2171 | ||
2215 | sshd_exchange_identification(ssh, sock_in, sock_out); | 2172 | if (kex_exchange_identification(ssh, -1, options.debian_banner, |
2216 | packet_set_nonblocking(); | 2173 | options.version_addendum) != 0) |
2174 | cleanup_exit(255); /* error already logged */ | ||
2175 | |||
2176 | ssh_packet_set_nonblocking(ssh); | ||
2217 | 2177 | ||
2218 | /* allocate authentication context */ | 2178 | /* allocate authentication context */ |
2219 | authctxt = xcalloc(1, sizeof(*authctxt)); | 2179 | authctxt = xcalloc(1, sizeof(*authctxt)); |
2180 | ssh->authctxt = authctxt; | ||
2220 | 2181 | ||
2221 | authctxt->loginmsg = loginmsg; | 2182 | authctxt->loginmsg = loginmsg; |
2222 | 2183 | ||
@@ -2233,7 +2194,7 @@ main(int ac, char **av) | |||
2233 | auth_debug_reset(); | 2194 | auth_debug_reset(); |
2234 | 2195 | ||
2235 | if (use_privsep) { | 2196 | if (use_privsep) { |
2236 | if (privsep_preauth(authctxt) == 1) | 2197 | if (privsep_preauth(ssh) == 1) |
2237 | goto authenticated; | 2198 | goto authenticated; |
2238 | } else if (have_agent) { | 2199 | } else if (have_agent) { |
2239 | if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { | 2200 | if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { |
@@ -2244,16 +2205,16 @@ main(int ac, char **av) | |||
2244 | 2205 | ||
2245 | /* perform the key exchange */ | 2206 | /* perform the key exchange */ |
2246 | /* authenticate user and start session */ | 2207 | /* authenticate user and start session */ |
2247 | do_ssh2_kex(); | 2208 | do_ssh2_kex(ssh); |
2248 | do_authentication2(authctxt); | 2209 | do_authentication2(ssh); |
2249 | 2210 | ||
2250 | /* | 2211 | /* |
2251 | * If we use privilege separation, the unprivileged child transfers | 2212 | * If we use privilege separation, the unprivileged child transfers |
2252 | * the current keystate and exits | 2213 | * the current keystate and exits |
2253 | */ | 2214 | */ |
2254 | if (use_privsep) { | 2215 | if (use_privsep) { |
2255 | mm_send_keystate(pmonitor); | 2216 | mm_send_keystate(ssh, pmonitor); |
2256 | packet_clear_keys(); | 2217 | ssh_packet_clear_keys(ssh); |
2257 | exit(0); | 2218 | exit(0); |
2258 | } | 2219 | } |
2259 | 2220 | ||
@@ -2271,7 +2232,7 @@ main(int ac, char **av) | |||
2271 | } | 2232 | } |
2272 | 2233 | ||
2273 | #ifdef SSH_AUDIT_EVENTS | 2234 | #ifdef SSH_AUDIT_EVENTS |
2274 | audit_event(SSH_AUTH_SUCCESS); | 2235 | audit_event(ssh, SSH_AUTH_SUCCESS); |
2275 | #endif | 2236 | #endif |
2276 | 2237 | ||
2277 | #ifdef GSSAPI | 2238 | #ifdef GSSAPI |
@@ -2293,11 +2254,11 @@ main(int ac, char **av) | |||
2293 | * file descriptor passing. | 2254 | * file descriptor passing. |
2294 | */ | 2255 | */ |
2295 | if (use_privsep) { | 2256 | if (use_privsep) { |
2296 | privsep_postauth(authctxt); | 2257 | privsep_postauth(ssh, authctxt); |
2297 | /* the monitor process [priv] will not return */ | 2258 | /* the monitor process [priv] will not return */ |
2298 | } | 2259 | } |
2299 | 2260 | ||
2300 | packet_set_timeout(options.client_alive_interval, | 2261 | ssh_packet_set_timeout(ssh, options.client_alive_interval, |
2301 | options.client_alive_count_max); | 2262 | options.client_alive_count_max); |
2302 | 2263 | ||
2303 | /* Try to send all our hostkeys to the client */ | 2264 | /* Try to send all our hostkeys to the client */ |
@@ -2307,7 +2268,7 @@ main(int ac, char **av) | |||
2307 | do_authenticated(ssh, authctxt); | 2268 | do_authenticated(ssh, authctxt); |
2308 | 2269 | ||
2309 | /* The connection has been terminated. */ | 2270 | /* The connection has been terminated. */ |
2310 | packet_get_bytes(&ibytes, &obytes); | 2271 | ssh_packet_get_bytes(ssh, &ibytes, &obytes); |
2311 | verbose("Transferred: sent %llu, received %llu bytes", | 2272 | verbose("Transferred: sent %llu, received %llu bytes", |
2312 | (unsigned long long)obytes, (unsigned long long)ibytes); | 2273 | (unsigned long long)obytes, (unsigned long long)ibytes); |
2313 | 2274 | ||
@@ -2319,10 +2280,10 @@ main(int ac, char **av) | |||
2319 | #endif /* USE_PAM */ | 2280 | #endif /* USE_PAM */ |
2320 | 2281 | ||
2321 | #ifdef SSH_AUDIT_EVENTS | 2282 | #ifdef SSH_AUDIT_EVENTS |
2322 | PRIVSEP(audit_event(SSH_CONNECTION_CLOSE)); | 2283 | PRIVSEP(audit_event(ssh, SSH_CONNECTION_CLOSE)); |
2323 | #endif | 2284 | #endif |
2324 | 2285 | ||
2325 | packet_close(); | 2286 | ssh_packet_close(ssh); |
2326 | 2287 | ||
2327 | if (use_privsep) | 2288 | if (use_privsep) |
2328 | mm_terminate(); | 2289 | mm_terminate(); |
@@ -2331,32 +2292,42 @@ main(int ac, char **av) | |||
2331 | } | 2292 | } |
2332 | 2293 | ||
2333 | int | 2294 | int |
2334 | sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, | 2295 | sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, |
2335 | u_char **signature, size_t *slenp, const u_char *data, size_t dlen, | 2296 | struct sshkey *pubkey, u_char **signature, size_t *slenp, |
2336 | const char *alg, u_int flag) | 2297 | const u_char *data, size_t dlen, const char *alg) |
2337 | { | 2298 | { |
2338 | int r; | 2299 | int r; |
2339 | 2300 | ||
2340 | if (privkey) { | 2301 | if (use_privsep) { |
2341 | if (PRIVSEP(sshkey_sign(privkey, signature, slenp, data, dlen, | 2302 | if (privkey) { |
2342 | alg, datafellows)) < 0) | 2303 | if (mm_sshkey_sign(ssh, privkey, signature, slenp, |
2343 | fatal("%s: key_sign failed", __func__); | 2304 | data, dlen, alg, ssh->compat) < 0) |
2344 | } else if (use_privsep) { | 2305 | fatal("%s: privkey sign failed", __func__); |
2345 | if (mm_sshkey_sign(pubkey, signature, slenp, data, dlen, | 2306 | } else { |
2346 | alg, datafellows) < 0) | 2307 | if (mm_sshkey_sign(ssh, pubkey, signature, slenp, |
2347 | fatal("%s: pubkey_sign failed", __func__); | 2308 | data, dlen, alg, ssh->compat) < 0) |
2309 | fatal("%s: pubkey sign failed", __func__); | ||
2310 | } | ||
2348 | } else { | 2311 | } else { |
2349 | if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slenp, | 2312 | if (privkey) { |
2350 | data, dlen, alg, datafellows)) != 0) | 2313 | if (sshkey_sign(privkey, signature, slenp, data, dlen, |
2351 | fatal("%s: ssh_agent_sign failed: %s", | 2314 | alg, ssh->compat) < 0) |
2352 | __func__, ssh_err(r)); | 2315 | fatal("%s: privkey sign failed", __func__); |
2316 | } else { | ||
2317 | if ((r = ssh_agent_sign(auth_sock, pubkey, | ||
2318 | signature, slenp, data, dlen, alg, | ||
2319 | ssh->compat)) != 0) { | ||
2320 | fatal("%s: agent sign failed: %s", | ||
2321 | __func__, ssh_err(r)); | ||
2322 | } | ||
2323 | } | ||
2353 | } | 2324 | } |
2354 | return 0; | 2325 | return 0; |
2355 | } | 2326 | } |
2356 | 2327 | ||
2357 | /* SSH2 key exchange */ | 2328 | /* SSH2 key exchange */ |
2358 | static void | 2329 | static void |
2359 | do_ssh2_kex(void) | 2330 | do_ssh2_kex(struct ssh *ssh) |
2360 | { | 2331 | { |
2361 | char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; | 2332 | char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; |
2362 | struct kex *kex; | 2333 | struct kex *kex; |
@@ -2377,20 +2348,20 @@ do_ssh2_kex(void) | |||
2377 | } | 2348 | } |
2378 | 2349 | ||
2379 | if (options.rekey_limit || options.rekey_interval) | 2350 | if (options.rekey_limit || options.rekey_interval) |
2380 | packet_set_rekey_limits(options.rekey_limit, | 2351 | ssh_packet_set_rekey_limits(ssh, options.rekey_limit, |
2381 | options.rekey_interval); | 2352 | options.rekey_interval); |
2382 | 2353 | ||
2383 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( | 2354 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( |
2384 | list_hostkey_types()); | 2355 | list_hostkey_types()); |
2385 | 2356 | ||
2386 | #ifdef GSSAPI | 2357 | #if defined(GSSAPI) && defined(WITH_OPENSSL) |
2387 | { | 2358 | { |
2388 | char *orig; | 2359 | char *orig; |
2389 | char *gss = NULL; | 2360 | char *gss = NULL; |
2390 | char *newstr = NULL; | 2361 | char *newstr = NULL; |
2391 | orig = myproposal[PROPOSAL_KEX_ALGS]; | 2362 | orig = myproposal[PROPOSAL_KEX_ALGS]; |
2392 | 2363 | ||
2393 | /* | 2364 | /* |
2394 | * If we don't have a host key, then there's no point advertising | 2365 | * If we don't have a host key, then there's no point advertising |
2395 | * the other key exchange algorithms | 2366 | * the other key exchange algorithms |
2396 | */ | 2367 | */ |
@@ -2410,10 +2381,10 @@ do_ssh2_kex(void) | |||
2410 | else if (orig) | 2381 | else if (orig) |
2411 | newstr = orig; | 2382 | newstr = orig; |
2412 | 2383 | ||
2413 | /* | 2384 | /* |
2414 | * If we've got GSSAPI mechanisms, then we've got the 'null' host | 2385 | * If we've got GSSAPI mechanisms, then we've got the 'null' host |
2415 | * key alg, but we can't tell people about it unless its the only | 2386 | * key alg, but we can't tell people about it unless its the only |
2416 | * host key algorithm we support | 2387 | * host key algorithm we support |
2417 | */ | 2388 | */ |
2418 | if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) | 2389 | if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) |
2419 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; | 2390 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; |
@@ -2426,38 +2397,40 @@ do_ssh2_kex(void) | |||
2426 | #endif | 2397 | #endif |
2427 | 2398 | ||
2428 | /* start key exchange */ | 2399 | /* start key exchange */ |
2429 | if ((r = kex_setup(active_state, myproposal)) != 0) | 2400 | if ((r = kex_setup(ssh, myproposal)) != 0) |
2430 | fatal("kex_setup: %s", ssh_err(r)); | 2401 | fatal("kex_setup: %s", ssh_err(r)); |
2431 | kex = active_state->kex; | 2402 | kex = ssh->kex; |
2432 | #ifdef WITH_OPENSSL | 2403 | #ifdef WITH_OPENSSL |
2433 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 2404 | kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; |
2434 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 2405 | kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; |
2435 | kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; | 2406 | kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; |
2436 | kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; | 2407 | kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; |
2437 | kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; | 2408 | kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; |
2438 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 2409 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
2439 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 2410 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
2440 | # ifdef OPENSSL_HAS_ECC | 2411 | # ifdef OPENSSL_HAS_ECC |
2441 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 2412 | kex->kex[KEX_ECDH_SHA2] = kex_gen_server; |
2442 | # endif | 2413 | # endif |
2443 | #endif | 2414 | # ifdef GSSAPI |
2444 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | ||
2445 | #ifdef GSSAPI | ||
2446 | if (options.gss_keyex) { | 2415 | if (options.gss_keyex) { |
2447 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; | 2416 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; |
2448 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; | 2417 | kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; |
2449 | kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; | 2418 | kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; |
2419 | kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; | ||
2420 | kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; | ||
2421 | kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; | ||
2422 | kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; | ||
2450 | } | 2423 | } |
2451 | #endif | 2424 | # endif |
2452 | kex->server = 1; | 2425 | #endif /* WITH_OPENSSL */ |
2453 | kex->client_version_string=client_version_string; | 2426 | kex->kex[KEX_C25519_SHA256] = kex_gen_server; |
2454 | kex->server_version_string=server_version_string; | 2427 | kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; |
2455 | kex->load_host_public_key=&get_hostkey_public_by_type; | 2428 | kex->load_host_public_key=&get_hostkey_public_by_type; |
2456 | kex->load_host_private_key=&get_hostkey_private_by_type; | 2429 | kex->load_host_private_key=&get_hostkey_private_by_type; |
2457 | kex->host_key_index=&get_hostkey_index; | 2430 | kex->host_key_index=&get_hostkey_index; |
2458 | kex->sign = sshd_hostkey_sign; | 2431 | kex->sign = sshd_hostkey_sign; |
2459 | 2432 | ||
2460 | ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); | 2433 | ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); |
2461 | 2434 | ||
2462 | session_id2 = kex->session_id; | 2435 | session_id2 = kex->session_id; |
2463 | session_id2_len = kex->session_id_len; | 2436 | session_id2_len = kex->session_id_len; |
@@ -2476,10 +2449,8 @@ do_ssh2_kex(void) | |||
2476 | void | 2449 | void |
2477 | cleanup_exit(int i) | 2450 | cleanup_exit(int i) |
2478 | { | 2451 | { |
2479 | struct ssh *ssh = active_state; /* XXX */ | 2452 | if (the_active_state != NULL && the_authctxt != NULL) { |
2480 | 2453 | do_cleanup(the_active_state, the_authctxt); | |
2481 | if (the_authctxt) { | ||
2482 | do_cleanup(ssh, the_authctxt); | ||
2483 | if (use_privsep && privsep_is_preauth && | 2454 | if (use_privsep && privsep_is_preauth && |
2484 | pmonitor != NULL && pmonitor->m_pid > 1) { | 2455 | pmonitor != NULL && pmonitor->m_pid > 1) { |
2485 | debug("Killing privsep child %d", pmonitor->m_pid); | 2456 | debug("Killing privsep child %d", pmonitor->m_pid); |
@@ -2491,8 +2462,8 @@ cleanup_exit(int i) | |||
2491 | } | 2462 | } |
2492 | #ifdef SSH_AUDIT_EVENTS | 2463 | #ifdef SSH_AUDIT_EVENTS |
2493 | /* done after do_cleanup so it can cancel the PAM auth 'thread' */ | 2464 | /* done after do_cleanup so it can cancel the PAM auth 'thread' */ |
2494 | if (!use_privsep || mm_is_monitor()) | 2465 | if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) |
2495 | audit_event(SSH_CONNECTION_ABANDON); | 2466 | audit_event(the_active_state, SSH_CONNECTION_ABANDON); |
2496 | #endif | 2467 | #endif |
2497 | _exit(i); | 2468 | _exit(i); |
2498 | } | 2469 | } |