diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 441 |
1 files changed, 205 insertions, 236 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 |
@@ -151,45 +151,38 @@ int debug_flag = 0; | |||
151 | * configuration, optionally using connection information provided by the | 151 | * configuration, optionally using connection information provided by the |
152 | * "-C" flag. | 152 | * "-C" flag. |
153 | */ | 153 | */ |
154 | int test_flag = 0; | 154 | static int test_flag = 0; |
155 | 155 | ||
156 | /* Flag indicating that the daemon is being started from inetd. */ | 156 | /* Flag indicating that the daemon is being started from inetd. */ |
157 | int inetd_flag = 0; | 157 | static int inetd_flag = 0; |
158 | 158 | ||
159 | /* Flag indicating that sshd should not detach and become a daemon. */ | 159 | /* Flag indicating that sshd should not detach and become a daemon. */ |
160 | int no_daemon_flag = 0; | 160 | static int no_daemon_flag = 0; |
161 | 161 | ||
162 | /* debug goes to stderr unless inetd_flag is set */ | 162 | /* debug goes to stderr unless inetd_flag is set */ |
163 | int log_stderr = 0; | 163 | static int log_stderr = 0; |
164 | 164 | ||
165 | /* Saved arguments to main(). */ | 165 | /* Saved arguments to main(). */ |
166 | char **saved_argv; | 166 | static char **saved_argv; |
167 | int saved_argc; | 167 | static int saved_argc; |
168 | 168 | ||
169 | /* re-exec */ | 169 | /* re-exec */ |
170 | int rexeced_flag = 0; | 170 | static int rexeced_flag = 0; |
171 | int rexec_flag = 1; | 171 | static int rexec_flag = 1; |
172 | int rexec_argc = 0; | 172 | static int rexec_argc = 0; |
173 | char **rexec_argv; | 173 | static char **rexec_argv; |
174 | 174 | ||
175 | /* | 175 | /* |
176 | * The sockets that the server is listening; this is used in the SIGHUP | 176 | * The sockets that the server is listening; this is used in the SIGHUP |
177 | * signal handler. | 177 | * signal handler. |
178 | */ | 178 | */ |
179 | #define MAX_LISTEN_SOCKS 16 | 179 | #define MAX_LISTEN_SOCKS 16 |
180 | int listen_socks[MAX_LISTEN_SOCKS]; | 180 | static int listen_socks[MAX_LISTEN_SOCKS]; |
181 | int num_listen_socks = 0; | 181 | static int num_listen_socks = 0; |
182 | |||
183 | /* | ||
184 | * the client's version string, passed by sshd2 in compat mode. if != NULL, | ||
185 | * sshd will skip the version-number exchange | ||
186 | */ | ||
187 | char *client_version_string = NULL; | ||
188 | char *server_version_string = NULL; | ||
189 | 182 | ||
190 | /* Daemon's agent connection */ | 183 | /* Daemon's agent connection */ |
191 | int auth_sock = -1; | 184 | int auth_sock = -1; |
192 | int have_agent = 0; | 185 | static int have_agent = 0; |
193 | 186 | ||
194 | /* | 187 | /* |
195 | * Any really sensitive data in the application is contained in this | 188 | * Any really sensitive data in the application is contained in this |
@@ -220,9 +213,26 @@ u_int session_id2_len = 0; | |||
220 | /* record remote hostname or ip */ | 213 | /* record remote hostname or ip */ |
221 | u_int utmp_len = HOST_NAME_MAX+1; | 214 | u_int utmp_len = HOST_NAME_MAX+1; |
222 | 215 | ||
223 | /* options.max_startup sized array of fd ints */ | 216 | /* |
224 | int *startup_pipes = NULL; | 217 | * startup_pipes/flags are used for tracking children of the listening sshd |
225 | int startup_pipe; /* in child */ | 218 | * process early in their lifespans. This tracking is needed for three things: |
219 | * | ||
220 | * 1) Implementing the MaxStartups limit of concurrent unauthenticated | ||
221 | * connections. | ||
222 | * 2) Avoiding a race condition for SIGHUP processing, where child processes | ||
223 | * may have listen_socks open that could collide with main listener process | ||
224 | * after it restarts. | ||
225 | * 3) Ensuring that rexec'd sshd processes have received their initial state | ||
226 | * from the parent listen process before handling SIGHUP. | ||
227 | * | ||
228 | * Child processes signal that they have completed closure of the listen_socks | ||
229 | * and (if applicable) received their rexec state by sending a char over their | ||
230 | * sock. Child processes signal that authentication has completed by closing | ||
231 | * the sock (or by exiting). | ||
232 | */ | ||
233 | static int *startup_pipes = NULL; | ||
234 | static int *startup_flags = NULL; /* Indicates child closed listener */ | ||
235 | static int startup_pipe = -1; /* in child */ | ||
226 | 236 | ||
227 | /* variables used for privilege separation */ | 237 | /* variables used for privilege separation */ |
228 | int use_privsep = -1; | 238 | int use_privsep = -1; |
@@ -230,8 +240,9 @@ struct monitor *pmonitor = NULL; | |||
230 | int privsep_is_preauth = 1; | 240 | int privsep_is_preauth = 1; |
231 | static int privsep_chroot = 1; | 241 | static int privsep_chroot = 1; |
232 | 242 | ||
233 | /* global authentication context */ | 243 | /* global connection state and authentication contexts */ |
234 | Authctxt *the_authctxt = NULL; | 244 | Authctxt *the_authctxt = NULL; |
245 | struct ssh *the_active_state; | ||
235 | 246 | ||
236 | /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ | 247 | /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ |
237 | struct sshauthopt *auth_opts = NULL; | 248 | struct sshauthopt *auth_opts = NULL; |
@@ -248,7 +259,7 @@ struct passwd *privsep_pw = NULL; | |||
248 | /* Prototypes for various functions defined later in this file. */ | 259 | /* Prototypes for various functions defined later in this file. */ |
249 | void destroy_sensitive_data(void); | 260 | void destroy_sensitive_data(void); |
250 | void demote_sensitive_data(void); | 261 | void demote_sensitive_data(void); |
251 | static void do_ssh2_kex(void); | 262 | static void do_ssh2_kex(struct ssh *); |
252 | 263 | ||
253 | /* | 264 | /* |
254 | * Close all listening sockets | 265 | * Close all listening sockets |
@@ -358,111 +369,11 @@ grace_alarm_handler(int sig) | |||
358 | kill(0, SIGTERM); | 369 | kill(0, SIGTERM); |
359 | } | 370 | } |
360 | 371 | ||
372 | /* XXX pre-format ipaddr/port so we don't need to access active_state */ | ||
361 | /* Log error and exit. */ | 373 | /* Log error and exit. */ |
362 | sigdie("Timeout before authentication for %s port %d", | 374 | sigdie("Timeout before authentication for %s port %d", |
363 | ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); | 375 | ssh_remote_ipaddr(the_active_state), |
364 | } | 376 | ssh_remote_port(the_active_state)); |
365 | |||
366 | static void | ||
367 | sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) | ||
368 | { | ||
369 | u_int i; | ||
370 | int remote_major, remote_minor; | ||
371 | char *s; | ||
372 | char buf[256]; /* Must not be larger than remote_version. */ | ||
373 | char remote_version[256]; /* Must be at least as big as buf. */ | ||
374 | |||
375 | xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n", | ||
376 | PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, | ||
377 | *options.version_addendum == '\0' ? "" : " ", | ||
378 | options.version_addendum); | ||
379 | |||
380 | /* Send our protocol version identification. */ | ||
381 | if (atomicio(vwrite, sock_out, server_version_string, | ||
382 | strlen(server_version_string)) | ||
383 | != strlen(server_version_string)) { | ||
384 | logit("Could not write ident string to %s port %d", | ||
385 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
386 | cleanup_exit(255); | ||
387 | } | ||
388 | |||
389 | /* Read other sides version identification. */ | ||
390 | memset(buf, 0, sizeof(buf)); | ||
391 | for (i = 0; i < sizeof(buf) - 1; i++) { | ||
392 | if (atomicio(read, sock_in, &buf[i], 1) != 1) { | ||
393 | logit("Did not receive identification string " | ||
394 | "from %s port %d", | ||
395 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
396 | cleanup_exit(255); | ||
397 | } | ||
398 | if (buf[i] == '\r') { | ||
399 | buf[i] = 0; | ||
400 | /* Kludge for F-Secure Macintosh < 1.0.2 */ | ||
401 | if (i == 12 && | ||
402 | strncmp(buf, "SSH-1.5-W1.0", 12) == 0) | ||
403 | break; | ||
404 | continue; | ||
405 | } | ||
406 | if (buf[i] == '\n') { | ||
407 | buf[i] = 0; | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | buf[sizeof(buf) - 1] = 0; | ||
412 | client_version_string = xstrdup(buf); | ||
413 | |||
414 | /* | ||
415 | * Check that the versions match. In future this might accept | ||
416 | * several versions and set appropriate flags to handle them. | ||
417 | */ | ||
418 | if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", | ||
419 | &remote_major, &remote_minor, remote_version) != 3) { | ||
420 | s = "Protocol mismatch.\n"; | ||
421 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | ||
422 | logit("Bad protocol version identification '%.100s' " | ||
423 | "from %s port %d", client_version_string, | ||
424 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
425 | close(sock_in); | ||
426 | close(sock_out); | ||
427 | cleanup_exit(255); | ||
428 | } | ||
429 | debug("Client protocol version %d.%d; client software version %.100s", | ||
430 | remote_major, remote_minor, remote_version); | ||
431 | |||
432 | ssh->compat = compat_datafellows(remote_version); | ||
433 | |||
434 | if ((ssh->compat & SSH_BUG_PROBE) != 0) { | ||
435 | logit("probed from %s port %d with %s. Don't panic.", | ||
436 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
437 | client_version_string); | ||
438 | cleanup_exit(255); | ||
439 | } | ||
440 | if ((ssh->compat & SSH_BUG_SCANNER) != 0) { | ||
441 | logit("scanned from %s port %d with %s. Don't panic.", | ||
442 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
443 | client_version_string); | ||
444 | cleanup_exit(255); | ||
445 | } | ||
446 | if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { | ||
447 | logit("Client version \"%.100s\" uses unsafe RSA signature " | ||
448 | "scheme; disabling use of RSA keys", remote_version); | ||
449 | } | ||
450 | |||
451 | chop(server_version_string); | ||
452 | debug("Local version string %.200s", server_version_string); | ||
453 | |||
454 | if (remote_major != 2 && | ||
455 | !(remote_major == 1 && remote_minor == 99)) { | ||
456 | s = "Protocol major versions differ.\n"; | ||
457 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | ||
458 | close(sock_in); | ||
459 | close(sock_out); | ||
460 | logit("Protocol major versions differ for %s port %d: " | ||
461 | "%.200s vs. %.200s", | ||
462 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
463 | server_version_string, client_version_string); | ||
464 | cleanup_exit(255); | ||
465 | } | ||
466 | } | 377 | } |
467 | 378 | ||
468 | /* Destroy the host and server keys. They will no longer be needed. */ | 379 | /* Destroy the host and server keys. They will no longer be needed. */ |
@@ -564,7 +475,7 @@ privsep_preauth_child(void) | |||
564 | } | 475 | } |
565 | 476 | ||
566 | static int | 477 | static int |
567 | privsep_preauth(Authctxt *authctxt) | 478 | privsep_preauth(struct ssh *ssh) |
568 | { | 479 | { |
569 | int status, r; | 480 | int status, r; |
570 | pid_t pid; | 481 | pid_t pid; |
@@ -573,7 +484,7 @@ privsep_preauth(Authctxt *authctxt) | |||
573 | /* Set up unprivileged child process to deal with network data */ | 484 | /* Set up unprivileged child process to deal with network data */ |
574 | pmonitor = monitor_init(); | 485 | pmonitor = monitor_init(); |
575 | /* Store a pointer to the kex for later rekeying */ | 486 | /* Store a pointer to the kex for later rekeying */ |
576 | pmonitor->m_pkex = &active_state->kex; | 487 | pmonitor->m_pkex = &ssh->kex; |
577 | 488 | ||
578 | if (use_privsep == PRIVSEP_ON) | 489 | if (use_privsep == PRIVSEP_ON) |
579 | box = ssh_sandbox_init(pmonitor); | 490 | box = ssh_sandbox_init(pmonitor); |
@@ -594,7 +505,7 @@ privsep_preauth(Authctxt *authctxt) | |||
594 | } | 505 | } |
595 | if (box != NULL) | 506 | if (box != NULL) |
596 | ssh_sandbox_parent_preauth(box, pid); | 507 | ssh_sandbox_parent_preauth(box, pid); |
597 | monitor_child_preauth(authctxt, pmonitor); | 508 | monitor_child_preauth(ssh, pmonitor); |
598 | 509 | ||
599 | /* Wait for the child's exit status */ | 510 | /* Wait for the child's exit status */ |
600 | while (waitpid(pid, &status, 0) < 0) { | 511 | while (waitpid(pid, &status, 0) < 0) { |
@@ -633,7 +544,7 @@ privsep_preauth(Authctxt *authctxt) | |||
633 | } | 544 | } |
634 | 545 | ||
635 | static void | 546 | static void |
636 | privsep_postauth(Authctxt *authctxt) | 547 | privsep_postauth(struct ssh *ssh, Authctxt *authctxt) |
637 | { | 548 | { |
638 | #ifdef DISABLE_FD_PASSING | 549 | #ifdef DISABLE_FD_PASSING |
639 | if (1) { | 550 | if (1) { |
@@ -654,8 +565,8 @@ privsep_postauth(Authctxt *authctxt) | |||
654 | else if (pmonitor->m_pid != 0) { | 565 | else if (pmonitor->m_pid != 0) { |
655 | verbose("User child is on pid %ld", (long)pmonitor->m_pid); | 566 | verbose("User child is on pid %ld", (long)pmonitor->m_pid); |
656 | sshbuf_reset(loginmsg); | 567 | sshbuf_reset(loginmsg); |
657 | monitor_clear_keystate(pmonitor); | 568 | monitor_clear_keystate(ssh, pmonitor); |
658 | monitor_child_postauth(pmonitor); | 569 | monitor_child_postauth(ssh, pmonitor); |
659 | 570 | ||
660 | /* NEVERREACHED */ | 571 | /* NEVERREACHED */ |
661 | exit(0); | 572 | exit(0); |
@@ -676,13 +587,13 @@ privsep_postauth(Authctxt *authctxt) | |||
676 | 587 | ||
677 | skip: | 588 | skip: |
678 | /* It is safe now to apply the key state */ | 589 | /* It is safe now to apply the key state */ |
679 | monitor_apply_keystate(pmonitor); | 590 | monitor_apply_keystate(ssh, pmonitor); |
680 | 591 | ||
681 | /* | 592 | /* |
682 | * Tell the packet layer that authentication was successful, since | 593 | * Tell the packet layer that authentication was successful, since |
683 | * this information is not part of the key state. | 594 | * this information is not part of the key state. |
684 | */ | 595 | */ |
685 | packet_set_authenticated(); | 596 | ssh_packet_set_authenticated(ssh); |
686 | } | 597 | } |
687 | 598 | ||
688 | static void | 599 | static void |
@@ -849,7 +760,7 @@ notify_hostkeys(struct ssh *ssh) | |||
849 | char *fp; | 760 | char *fp; |
850 | 761 | ||
851 | /* Some clients cannot cope with the hostkeys message, skip those. */ | 762 | /* Some clients cannot cope with the hostkeys message, skip those. */ |
852 | if (datafellows & SSH_BUG_HOSTKEYS) | 763 | if (ssh->compat & SSH_BUG_HOSTKEYS) |
853 | return; | 764 | return; |
854 | 765 | ||
855 | if ((buf = sshbuf_new()) == NULL) | 766 | if ((buf = sshbuf_new()) == NULL) |
@@ -865,21 +776,29 @@ notify_hostkeys(struct ssh *ssh) | |||
865 | sshkey_ssh_name(key), fp); | 776 | sshkey_ssh_name(key), fp); |
866 | free(fp); | 777 | free(fp); |
867 | if (nkeys == 0) { | 778 | if (nkeys == 0) { |
868 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 779 | /* |
869 | packet_put_cstring("hostkeys-00@openssh.com"); | 780 | * Start building the request when we find the |
870 | packet_put_char(0); /* want-reply */ | 781 | * first usable key. |
782 | */ | ||
783 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || | ||
784 | (r = sshpkt_put_cstring(ssh, "hostkeys-00@openssh.com")) != 0 || | ||
785 | (r = sshpkt_put_u8(ssh, 0)) != 0) /* want reply */ | ||
786 | sshpkt_fatal(ssh, r, "%s: start request", __func__); | ||
871 | } | 787 | } |
788 | /* Append the key to the request */ | ||
872 | sshbuf_reset(buf); | 789 | sshbuf_reset(buf); |
873 | if ((r = sshkey_putb(key, buf)) != 0) | 790 | if ((r = sshkey_putb(key, buf)) != 0) |
874 | fatal("%s: couldn't put hostkey %d: %s", | 791 | fatal("%s: couldn't put hostkey %d: %s", |
875 | __func__, i, ssh_err(r)); | 792 | __func__, i, ssh_err(r)); |
876 | packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf)); | 793 | if ((r = sshpkt_put_stringb(ssh, buf)) != 0) |
794 | sshpkt_fatal(ssh, r, "%s: append key", __func__); | ||
877 | nkeys++; | 795 | nkeys++; |
878 | } | 796 | } |
879 | debug3("%s: sent %u hostkeys", __func__, nkeys); | 797 | debug3("%s: sent %u hostkeys", __func__, nkeys); |
880 | if (nkeys == 0) | 798 | if (nkeys == 0) |
881 | fatal("%s: no hostkeys", __func__); | 799 | fatal("%s: no hostkeys", __func__); |
882 | packet_send(); | 800 | if ((r = sshpkt_send(ssh)) != 0) |
801 | sshpkt_fatal(ssh, r, "%s: send", __func__); | ||
883 | sshbuf_free(buf); | 802 | sshbuf_free(buf); |
884 | } | 803 | } |
885 | 804 | ||
@@ -917,7 +836,7 @@ usage(void) | |||
917 | fprintf(stderr, "%s, %s\n", | 836 | fprintf(stderr, "%s, %s\n", |
918 | SSH_RELEASE, | 837 | SSH_RELEASE, |
919 | #ifdef WITH_OPENSSL | 838 | #ifdef WITH_OPENSSL |
920 | SSLeay_version(SSLEAY_VERSION) | 839 | OpenSSL_version(OPENSSL_VERSION) |
921 | #else | 840 | #else |
922 | "without OpenSSL" | 841 | "without OpenSSL" |
923 | #endif | 842 | #endif |
@@ -999,14 +918,9 @@ server_accept_inetd(int *sock_in, int *sock_out) | |||
999 | { | 918 | { |
1000 | int fd; | 919 | int fd; |
1001 | 920 | ||
1002 | startup_pipe = -1; | ||
1003 | if (rexeced_flag) { | 921 | if (rexeced_flag) { |
1004 | close(REEXEC_CONFIG_PASS_FD); | 922 | close(REEXEC_CONFIG_PASS_FD); |
1005 | *sock_in = *sock_out = dup(STDIN_FILENO); | 923 | *sock_in = *sock_out = dup(STDIN_FILENO); |
1006 | if (!debug_flag) { | ||
1007 | startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); | ||
1008 | close(REEXEC_STARTUP_PIPE_FD); | ||
1009 | } | ||
1010 | } else { | 924 | } else { |
1011 | *sock_in = dup(STDIN_FILENO); | 925 | *sock_in = dup(STDIN_FILENO); |
1012 | *sock_out = dup(STDOUT_FILENO); | 926 | *sock_out = dup(STDOUT_FILENO); |
@@ -1131,8 +1045,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1131 | { | 1045 | { |
1132 | fd_set *fdset; | 1046 | fd_set *fdset; |
1133 | int i, j, ret, maxfd; | 1047 | int i, j, ret, maxfd; |
1134 | int startups = 0; | 1048 | int startups = 0, listening = 0, lameduck = 0; |
1135 | int startup_p[2] = { -1 , -1 }; | 1049 | int startup_p[2] = { -1 , -1 }; |
1050 | char c = 0; | ||
1136 | struct sockaddr_storage from; | 1051 | struct sockaddr_storage from; |
1137 | socklen_t fromlen; | 1052 | socklen_t fromlen; |
1138 | pid_t pid; | 1053 | pid_t pid; |
@@ -1146,6 +1061,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1146 | maxfd = listen_socks[i]; | 1061 | maxfd = listen_socks[i]; |
1147 | /* pipes connected to unauthenticated childs */ | 1062 | /* pipes connected to unauthenticated childs */ |
1148 | startup_pipes = xcalloc(options.max_startups, sizeof(int)); | 1063 | startup_pipes = xcalloc(options.max_startups, sizeof(int)); |
1064 | startup_flags = xcalloc(options.max_startups, sizeof(int)); | ||
1149 | for (i = 0; i < options.max_startups; i++) | 1065 | for (i = 0; i < options.max_startups; i++) |
1150 | startup_pipes[i] = -1; | 1066 | startup_pipes[i] = -1; |
1151 | 1067 | ||
@@ -1154,8 +1070,15 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1154 | * the daemon is killed with a signal. | 1070 | * the daemon is killed with a signal. |
1155 | */ | 1071 | */ |
1156 | for (;;) { | 1072 | for (;;) { |
1157 | if (received_sighup) | 1073 | if (received_sighup) { |
1158 | sighup_restart(); | 1074 | if (!lameduck) { |
1075 | debug("Received SIGHUP; waiting for children"); | ||
1076 | close_listen_socks(); | ||
1077 | lameduck = 1; | ||
1078 | } | ||
1079 | if (listening <= 0) | ||
1080 | sighup_restart(); | ||
1081 | } | ||
1159 | free(fdset); | 1082 | free(fdset); |
1160 | fdset = xcalloc(howmany(maxfd + 1, NFDBITS), | 1083 | fdset = xcalloc(howmany(maxfd + 1, NFDBITS), |
1161 | sizeof(fd_mask)); | 1084 | sizeof(fd_mask)); |
@@ -1181,19 +1104,37 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1181 | if (ret < 0) | 1104 | if (ret < 0) |
1182 | continue; | 1105 | continue; |
1183 | 1106 | ||
1184 | for (i = 0; i < options.max_startups; i++) | 1107 | for (i = 0; i < options.max_startups; i++) { |
1185 | if (startup_pipes[i] != -1 && | 1108 | if (startup_pipes[i] == -1 || |
1186 | FD_ISSET(startup_pipes[i], fdset)) { | 1109 | !FD_ISSET(startup_pipes[i], fdset)) |
1187 | /* | 1110 | continue; |
1188 | * the read end of the pipe is ready | 1111 | switch (read(startup_pipes[i], &c, sizeof(c))) { |
1189 | * if the child has closed the pipe | 1112 | case -1: |
1190 | * after successful authentication | 1113 | if (errno == EINTR || errno == EAGAIN) |
1191 | * or if the child has died | 1114 | continue; |
1192 | */ | 1115 | if (errno != EPIPE) { |
1116 | error("%s: startup pipe %d (fd=%d): " | ||
1117 | "read %s", __func__, i, | ||
1118 | startup_pipes[i], strerror(errno)); | ||
1119 | } | ||
1120 | /* FALLTHROUGH */ | ||
1121 | case 0: | ||
1122 | /* child exited or completed auth */ | ||
1193 | close(startup_pipes[i]); | 1123 | close(startup_pipes[i]); |
1194 | startup_pipes[i] = -1; | 1124 | startup_pipes[i] = -1; |
1195 | startups--; | 1125 | startups--; |
1126 | if (startup_flags[i]) | ||
1127 | listening--; | ||
1128 | break; | ||
1129 | case 1: | ||
1130 | /* child has finished preliminaries */ | ||
1131 | if (startup_flags[i]) { | ||
1132 | listening--; | ||
1133 | startup_flags[i] = 0; | ||
1134 | } | ||
1135 | break; | ||
1196 | } | 1136 | } |
1137 | } | ||
1197 | for (i = 0; i < num_listen_socks; i++) { | 1138 | for (i = 0; i < num_listen_socks; i++) { |
1198 | if (!FD_ISSET(listen_socks[i], fdset)) | 1139 | if (!FD_ISSET(listen_socks[i], fdset)) |
1199 | continue; | 1140 | continue; |
@@ -1247,6 +1188,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1247 | if (maxfd < startup_p[0]) | 1188 | if (maxfd < startup_p[0]) |
1248 | maxfd = startup_p[0]; | 1189 | maxfd = startup_p[0]; |
1249 | startups++; | 1190 | startups++; |
1191 | startup_flags[j] = 1; | ||
1250 | break; | 1192 | break; |
1251 | } | 1193 | } |
1252 | 1194 | ||
@@ -1272,7 +1214,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1272 | send_rexec_state(config_s[0], cfg); | 1214 | send_rexec_state(config_s[0], cfg); |
1273 | close(config_s[0]); | 1215 | close(config_s[0]); |
1274 | } | 1216 | } |
1275 | break; | 1217 | return; |
1276 | } | 1218 | } |
1277 | 1219 | ||
1278 | /* | 1220 | /* |
@@ -1281,13 +1223,14 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1281 | * parent continues listening. | 1223 | * parent continues listening. |
1282 | */ | 1224 | */ |
1283 | platform_pre_fork(); | 1225 | platform_pre_fork(); |
1226 | listening++; | ||
1284 | if ((pid = fork()) == 0) { | 1227 | if ((pid = fork()) == 0) { |
1285 | /* | 1228 | /* |
1286 | * Child. Close the listening and | 1229 | * Child. Close the listening and |
1287 | * max_startup sockets. Start using | 1230 | * max_startup sockets. Start using |
1288 | * the accepted socket. Reinitialize | 1231 | * the accepted socket. Reinitialize |
1289 | * logging (since our pid has changed). | 1232 | * logging (since our pid has changed). |
1290 | * We break out of the loop to handle | 1233 | * We return from this function to handle |
1291 | * the connection. | 1234 | * the connection. |
1292 | */ | 1235 | */ |
1293 | platform_post_fork_child(); | 1236 | platform_post_fork_child(); |
@@ -1302,7 +1245,18 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1302 | log_stderr); | 1245 | log_stderr); |
1303 | if (rexec_flag) | 1246 | if (rexec_flag) |
1304 | close(config_s[0]); | 1247 | close(config_s[0]); |
1305 | break; | 1248 | else { |
1249 | /* | ||
1250 | * Signal parent that the preliminaries | ||
1251 | * for this child are complete. For the | ||
1252 | * re-exec case, this happens after the | ||
1253 | * child has received the rexec state | ||
1254 | * from the server. | ||
1255 | */ | ||
1256 | (void)atomicio(vwrite, startup_pipe, | ||
1257 | "\0", 1); | ||
1258 | } | ||
1259 | return; | ||
1306 | } | 1260 | } |
1307 | 1261 | ||
1308 | /* Parent. Stay in the loop. */ | 1262 | /* Parent. Stay in the loop. */ |
@@ -1334,10 +1288,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) | |||
1334 | #endif | 1288 | #endif |
1335 | explicit_bzero(rnd, sizeof(rnd)); | 1289 | explicit_bzero(rnd, sizeof(rnd)); |
1336 | } | 1290 | } |
1337 | |||
1338 | /* child process check (or debug mode) */ | ||
1339 | if (num_listen_socks < 0) | ||
1340 | break; | ||
1341 | } | 1291 | } |
1342 | } | 1292 | } |
1343 | 1293 | ||
@@ -1510,6 +1460,8 @@ main(int ac, char **av) | |||
1510 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 1460 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
1511 | sanitise_stdfd(); | 1461 | sanitise_stdfd(); |
1512 | 1462 | ||
1463 | seed_rng(); | ||
1464 | |||
1513 | /* Initialize configuration options to their default values. */ | 1465 | /* Initialize configuration options to their default values. */ |
1514 | initialize_server_options(&options); | 1466 | initialize_server_options(&options); |
1515 | 1467 | ||
@@ -1588,7 +1540,7 @@ main(int ac, char **av) | |||
1588 | break; | 1540 | break; |
1589 | case 'h': | 1541 | case 'h': |
1590 | servconf_add_hostkey("[command-line]", 0, | 1542 | servconf_add_hostkey("[command-line]", 0, |
1591 | &options, optarg); | 1543 | &options, optarg, 1); |
1592 | break; | 1544 | break; |
1593 | case 't': | 1545 | case 't': |
1594 | test_flag = 1; | 1546 | test_flag = 1; |
@@ -1597,7 +1549,7 @@ main(int ac, char **av) | |||
1597 | test_flag = 2; | 1549 | test_flag = 2; |
1598 | break; | 1550 | break; |
1599 | case 'C': | 1551 | case 'C': |
1600 | connection_info = get_connection_info(0, 0); | 1552 | connection_info = get_connection_info(ssh, 0, 0); |
1601 | if (parse_server_match_testspec(connection_info, | 1553 | if (parse_server_match_testspec(connection_info, |
1602 | optarg) == -1) | 1554 | optarg) == -1) |
1603 | exit(1); | 1555 | exit(1); |
@@ -1624,17 +1576,13 @@ main(int ac, char **av) | |||
1624 | } | 1576 | } |
1625 | if (rexeced_flag || inetd_flag) | 1577 | if (rexeced_flag || inetd_flag) |
1626 | rexec_flag = 0; | 1578 | rexec_flag = 0; |
1627 | if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/'))) | 1579 | if (!test_flag && rexec_flag && !path_absolute(av[0])) |
1628 | fatal("sshd re-exec requires execution with an absolute path"); | 1580 | fatal("sshd re-exec requires execution with an absolute path"); |
1629 | if (rexeced_flag) | 1581 | if (rexeced_flag) |
1630 | closefrom(REEXEC_MIN_FREE_FD); | 1582 | closefrom(REEXEC_MIN_FREE_FD); |
1631 | else | 1583 | else |
1632 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); | 1584 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); |
1633 | 1585 | ||
1634 | #ifdef WITH_OPENSSL | ||
1635 | OpenSSL_add_all_algorithms(); | ||
1636 | #endif | ||
1637 | |||
1638 | /* If requested, redirect the logs to the specified logfile. */ | 1586 | /* If requested, redirect the logs to the specified logfile. */ |
1639 | if (logfile != NULL) | 1587 | if (logfile != NULL) |
1640 | log_redirect_stderr_to(logfile); | 1588 | log_redirect_stderr_to(logfile); |
@@ -1669,16 +1617,24 @@ main(int ac, char **av) | |||
1669 | /* Fetch our configuration */ | 1617 | /* Fetch our configuration */ |
1670 | if ((cfg = sshbuf_new()) == NULL) | 1618 | if ((cfg = sshbuf_new()) == NULL) |
1671 | fatal("%s: sshbuf_new failed", __func__); | 1619 | fatal("%s: sshbuf_new failed", __func__); |
1672 | if (rexeced_flag) | 1620 | if (rexeced_flag) { |
1673 | recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); | 1621 | recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); |
1622 | if (!debug_flag) { | ||
1623 | startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); | ||
1624 | close(REEXEC_STARTUP_PIPE_FD); | ||
1625 | /* | ||
1626 | * Signal parent that this child is at a point where | ||
1627 | * they can go away if they have a SIGHUP pending. | ||
1628 | */ | ||
1629 | (void)atomicio(vwrite, startup_pipe, "\0", 1); | ||
1630 | } | ||
1631 | } | ||
1674 | else if (strcasecmp(config_file_name, "none") != 0) | 1632 | else if (strcasecmp(config_file_name, "none") != 0) |
1675 | load_server_config(config_file_name, cfg); | 1633 | load_server_config(config_file_name, cfg); |
1676 | 1634 | ||
1677 | parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, | 1635 | parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, |
1678 | cfg, NULL); | 1636 | cfg, NULL); |
1679 | 1637 | ||
1680 | seed_rng(); | ||
1681 | |||
1682 | /* Fill in default values for those options not explicitly set. */ | 1638 | /* Fill in default values for those options not explicitly set. */ |
1683 | fill_default_server_options(&options); | 1639 | fill_default_server_options(&options); |
1684 | 1640 | ||
@@ -1723,7 +1679,7 @@ main(int ac, char **av) | |||
1723 | 1679 | ||
1724 | debug("sshd version %s, %s", SSH_VERSION, | 1680 | debug("sshd version %s, %s", SSH_VERSION, |
1725 | #ifdef WITH_OPENSSL | 1681 | #ifdef WITH_OPENSSL |
1726 | SSLeay_version(SSLEAY_VERSION) | 1682 | OpenSSL_version(OPENSSL_VERSION) |
1727 | #else | 1683 | #else |
1728 | "without OpenSSL" | 1684 | "without OpenSSL" |
1729 | #endif | 1685 | #endif |
@@ -1760,15 +1716,18 @@ main(int ac, char **av) | |||
1760 | } | 1716 | } |
1761 | 1717 | ||
1762 | for (i = 0; i < options.num_host_key_files; i++) { | 1718 | for (i = 0; i < options.num_host_key_files; i++) { |
1719 | int ll = options.host_key_file_userprovided[i] ? | ||
1720 | SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_DEBUG1; | ||
1721 | |||
1763 | if (options.host_key_files[i] == NULL) | 1722 | if (options.host_key_files[i] == NULL) |
1764 | continue; | 1723 | continue; |
1765 | if ((r = sshkey_load_private(options.host_key_files[i], "", | 1724 | if ((r = sshkey_load_private(options.host_key_files[i], "", |
1766 | &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) | 1725 | &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) |
1767 | error("Error loading host key \"%s\": %s", | 1726 | do_log2(ll, "Unable to load host key \"%s\": %s", |
1768 | options.host_key_files[i], ssh_err(r)); | 1727 | options.host_key_files[i], ssh_err(r)); |
1769 | if ((r = sshkey_load_public(options.host_key_files[i], | 1728 | if ((r = sshkey_load_public(options.host_key_files[i], |
1770 | &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) | 1729 | &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) |
1771 | error("Error loading host key \"%s\": %s", | 1730 | do_log2(ll, "Unable to load host key \"%s\": %s", |
1772 | options.host_key_files[i], ssh_err(r)); | 1731 | options.host_key_files[i], ssh_err(r)); |
1773 | if (pubkey == NULL && key != NULL) | 1732 | if (pubkey == NULL && key != NULL) |
1774 | if ((r = sshkey_from_private(key, &pubkey)) != 0) | 1733 | if ((r = sshkey_from_private(key, &pubkey)) != 0) |
@@ -1785,7 +1744,7 @@ main(int ac, char **av) | |||
1785 | keytype = key->type; | 1744 | keytype = key->type; |
1786 | accumulate_host_timing_secret(cfg, key); | 1745 | accumulate_host_timing_secret(cfg, key); |
1787 | } else { | 1746 | } else { |
1788 | error("Could not load host key: %s", | 1747 | do_log2(ll, "Unable to load host key: %s", |
1789 | options.host_key_files[i]); | 1748 | options.host_key_files[i]); |
1790 | sensitive_data.host_keys[i] = NULL; | 1749 | sensitive_data.host_keys[i] = NULL; |
1791 | sensitive_data.host_pubkeys[i] = NULL; | 1750 | sensitive_data.host_pubkeys[i] = NULL; |
@@ -1883,7 +1842,7 @@ main(int ac, char **av) | |||
1883 | * use a blank one that will cause no predicate to match. | 1842 | * use a blank one that will cause no predicate to match. |
1884 | */ | 1843 | */ |
1885 | if (connection_info == NULL) | 1844 | if (connection_info == NULL) |
1886 | connection_info = get_connection_info(0, 0); | 1845 | connection_info = get_connection_info(ssh, 0, 0); |
1887 | parse_server_match_config(&options, connection_info); | 1846 | parse_server_match_config(&options, connection_info); |
1888 | dump_config(&options); | 1847 | dump_config(&options); |
1889 | } | 1848 | } |
@@ -2058,9 +2017,10 @@ main(int ac, char **av) | |||
2058 | * Register our connection. This turns encryption off because we do | 2017 | * Register our connection. This turns encryption off because we do |
2059 | * not have a key. | 2018 | * not have a key. |
2060 | */ | 2019 | */ |
2061 | packet_set_connection(sock_in, sock_out); | 2020 | if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) |
2062 | packet_set_server(); | 2021 | fatal("Unable to create connection"); |
2063 | ssh = active_state; /* XXX */ | 2022 | the_active_state = ssh; |
2023 | ssh_packet_set_server(ssh); | ||
2064 | 2024 | ||
2065 | check_ip_options(ssh); | 2025 | check_ip_options(ssh); |
2066 | 2026 | ||
@@ -2070,7 +2030,7 @@ main(int ac, char **av) | |||
2070 | process_permitopen(ssh, &options); | 2030 | process_permitopen(ssh, &options); |
2071 | 2031 | ||
2072 | /* Set SO_KEEPALIVE if requested. */ | 2032 | /* Set SO_KEEPALIVE if requested. */ |
2073 | if (options.tcp_keep_alive && packet_connection_is_on_socket() && | 2033 | if (options.tcp_keep_alive && ssh_packet_connection_is_on_socket(ssh) && |
2074 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) | 2034 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) |
2075 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 2035 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
2076 | 2036 | ||
@@ -2116,11 +2076,14 @@ main(int ac, char **av) | |||
2116 | if (!debug_flag) | 2076 | if (!debug_flag) |
2117 | alarm(options.login_grace_time); | 2077 | alarm(options.login_grace_time); |
2118 | 2078 | ||
2119 | sshd_exchange_identification(ssh, sock_in, sock_out); | 2079 | if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0) |
2120 | packet_set_nonblocking(); | 2080 | cleanup_exit(255); /* error already logged */ |
2081 | |||
2082 | ssh_packet_set_nonblocking(ssh); | ||
2121 | 2083 | ||
2122 | /* allocate authentication context */ | 2084 | /* allocate authentication context */ |
2123 | authctxt = xcalloc(1, sizeof(*authctxt)); | 2085 | authctxt = xcalloc(1, sizeof(*authctxt)); |
2086 | ssh->authctxt = authctxt; | ||
2124 | 2087 | ||
2125 | authctxt->loginmsg = loginmsg; | 2088 | authctxt->loginmsg = loginmsg; |
2126 | 2089 | ||
@@ -2137,7 +2100,7 @@ main(int ac, char **av) | |||
2137 | auth_debug_reset(); | 2100 | auth_debug_reset(); |
2138 | 2101 | ||
2139 | if (use_privsep) { | 2102 | if (use_privsep) { |
2140 | if (privsep_preauth(authctxt) == 1) | 2103 | if (privsep_preauth(ssh) == 1) |
2141 | goto authenticated; | 2104 | goto authenticated; |
2142 | } else if (have_agent) { | 2105 | } else if (have_agent) { |
2143 | if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { | 2106 | if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { |
@@ -2148,16 +2111,16 @@ main(int ac, char **av) | |||
2148 | 2111 | ||
2149 | /* perform the key exchange */ | 2112 | /* perform the key exchange */ |
2150 | /* authenticate user and start session */ | 2113 | /* authenticate user and start session */ |
2151 | do_ssh2_kex(); | 2114 | do_ssh2_kex(ssh); |
2152 | do_authentication2(authctxt); | 2115 | do_authentication2(ssh); |
2153 | 2116 | ||
2154 | /* | 2117 | /* |
2155 | * If we use privilege separation, the unprivileged child transfers | 2118 | * If we use privilege separation, the unprivileged child transfers |
2156 | * the current keystate and exits | 2119 | * the current keystate and exits |
2157 | */ | 2120 | */ |
2158 | if (use_privsep) { | 2121 | if (use_privsep) { |
2159 | mm_send_keystate(pmonitor); | 2122 | mm_send_keystate(ssh, pmonitor); |
2160 | packet_clear_keys(); | 2123 | ssh_packet_clear_keys(ssh); |
2161 | exit(0); | 2124 | exit(0); |
2162 | } | 2125 | } |
2163 | 2126 | ||
@@ -2175,7 +2138,7 @@ main(int ac, char **av) | |||
2175 | } | 2138 | } |
2176 | 2139 | ||
2177 | #ifdef SSH_AUDIT_EVENTS | 2140 | #ifdef SSH_AUDIT_EVENTS |
2178 | audit_event(SSH_AUTH_SUCCESS); | 2141 | audit_event(ssh, SSH_AUTH_SUCCESS); |
2179 | #endif | 2142 | #endif |
2180 | 2143 | ||
2181 | #ifdef GSSAPI | 2144 | #ifdef GSSAPI |
@@ -2197,11 +2160,11 @@ main(int ac, char **av) | |||
2197 | * file descriptor passing. | 2160 | * file descriptor passing. |
2198 | */ | 2161 | */ |
2199 | if (use_privsep) { | 2162 | if (use_privsep) { |
2200 | privsep_postauth(authctxt); | 2163 | privsep_postauth(ssh, authctxt); |
2201 | /* the monitor process [priv] will not return */ | 2164 | /* the monitor process [priv] will not return */ |
2202 | } | 2165 | } |
2203 | 2166 | ||
2204 | packet_set_timeout(options.client_alive_interval, | 2167 | ssh_packet_set_timeout(ssh, options.client_alive_interval, |
2205 | options.client_alive_count_max); | 2168 | options.client_alive_count_max); |
2206 | 2169 | ||
2207 | /* Try to send all our hostkeys to the client */ | 2170 | /* Try to send all our hostkeys to the client */ |
@@ -2211,7 +2174,7 @@ main(int ac, char **av) | |||
2211 | do_authenticated(ssh, authctxt); | 2174 | do_authenticated(ssh, authctxt); |
2212 | 2175 | ||
2213 | /* The connection has been terminated. */ | 2176 | /* The connection has been terminated. */ |
2214 | packet_get_bytes(&ibytes, &obytes); | 2177 | ssh_packet_get_bytes(ssh, &ibytes, &obytes); |
2215 | verbose("Transferred: sent %llu, received %llu bytes", | 2178 | verbose("Transferred: sent %llu, received %llu bytes", |
2216 | (unsigned long long)obytes, (unsigned long long)ibytes); | 2179 | (unsigned long long)obytes, (unsigned long long)ibytes); |
2217 | 2180 | ||
@@ -2223,10 +2186,10 @@ main(int ac, char **av) | |||
2223 | #endif /* USE_PAM */ | 2186 | #endif /* USE_PAM */ |
2224 | 2187 | ||
2225 | #ifdef SSH_AUDIT_EVENTS | 2188 | #ifdef SSH_AUDIT_EVENTS |
2226 | PRIVSEP(audit_event(SSH_CONNECTION_CLOSE)); | 2189 | PRIVSEP(audit_event(ssh, SSH_CONNECTION_CLOSE)); |
2227 | #endif | 2190 | #endif |
2228 | 2191 | ||
2229 | packet_close(); | 2192 | ssh_packet_close(ssh); |
2230 | 2193 | ||
2231 | if (use_privsep) | 2194 | if (use_privsep) |
2232 | mm_terminate(); | 2195 | mm_terminate(); |
@@ -2235,32 +2198,42 @@ main(int ac, char **av) | |||
2235 | } | 2198 | } |
2236 | 2199 | ||
2237 | int | 2200 | int |
2238 | sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, | 2201 | sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, |
2239 | u_char **signature, size_t *slenp, const u_char *data, size_t dlen, | 2202 | struct sshkey *pubkey, u_char **signature, size_t *slenp, |
2240 | const char *alg, u_int flag) | 2203 | const u_char *data, size_t dlen, const char *alg) |
2241 | { | 2204 | { |
2242 | int r; | 2205 | int r; |
2243 | 2206 | ||
2244 | if (privkey) { | 2207 | if (use_privsep) { |
2245 | if (PRIVSEP(sshkey_sign(privkey, signature, slenp, data, dlen, | 2208 | if (privkey) { |
2246 | alg, datafellows)) < 0) | 2209 | if (mm_sshkey_sign(ssh, privkey, signature, slenp, |
2247 | fatal("%s: key_sign failed", __func__); | 2210 | data, dlen, alg, ssh->compat) < 0) |
2248 | } else if (use_privsep) { | 2211 | fatal("%s: privkey sign failed", __func__); |
2249 | if (mm_sshkey_sign(pubkey, signature, slenp, data, dlen, | 2212 | } else { |
2250 | alg, datafellows) < 0) | 2213 | if (mm_sshkey_sign(ssh, pubkey, signature, slenp, |
2251 | fatal("%s: pubkey_sign failed", __func__); | 2214 | data, dlen, alg, ssh->compat) < 0) |
2215 | fatal("%s: pubkey sign failed", __func__); | ||
2216 | } | ||
2252 | } else { | 2217 | } else { |
2253 | if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slenp, | 2218 | if (privkey) { |
2254 | data, dlen, alg, datafellows)) != 0) | 2219 | if (sshkey_sign(privkey, signature, slenp, data, dlen, |
2255 | fatal("%s: ssh_agent_sign failed: %s", | 2220 | alg, ssh->compat) < 0) |
2256 | __func__, ssh_err(r)); | 2221 | fatal("%s: privkey sign failed", __func__); |
2222 | } else { | ||
2223 | if ((r = ssh_agent_sign(auth_sock, pubkey, | ||
2224 | signature, slenp, data, dlen, alg, | ||
2225 | ssh->compat)) != 0) { | ||
2226 | fatal("%s: agent sign failed: %s", | ||
2227 | __func__, ssh_err(r)); | ||
2228 | } | ||
2229 | } | ||
2257 | } | 2230 | } |
2258 | return 0; | 2231 | return 0; |
2259 | } | 2232 | } |
2260 | 2233 | ||
2261 | /* SSH2 key exchange */ | 2234 | /* SSH2 key exchange */ |
2262 | static void | 2235 | static void |
2263 | do_ssh2_kex(void) | 2236 | do_ssh2_kex(struct ssh *ssh) |
2264 | { | 2237 | { |
2265 | char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; | 2238 | char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; |
2266 | struct kex *kex; | 2239 | struct kex *kex; |
@@ -2281,38 +2254,36 @@ do_ssh2_kex(void) | |||
2281 | } | 2254 | } |
2282 | 2255 | ||
2283 | if (options.rekey_limit || options.rekey_interval) | 2256 | if (options.rekey_limit || options.rekey_interval) |
2284 | packet_set_rekey_limits(options.rekey_limit, | 2257 | ssh_packet_set_rekey_limits(ssh, options.rekey_limit, |
2285 | options.rekey_interval); | 2258 | options.rekey_interval); |
2286 | 2259 | ||
2287 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( | 2260 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( |
2288 | list_hostkey_types()); | 2261 | list_hostkey_types()); |
2289 | 2262 | ||
2290 | /* start key exchange */ | 2263 | /* start key exchange */ |
2291 | if ((r = kex_setup(active_state, myproposal)) != 0) | 2264 | if ((r = kex_setup(ssh, myproposal)) != 0) |
2292 | fatal("kex_setup: %s", ssh_err(r)); | 2265 | fatal("kex_setup: %s", ssh_err(r)); |
2293 | kex = active_state->kex; | 2266 | kex = ssh->kex; |
2294 | #ifdef WITH_OPENSSL | 2267 | #ifdef WITH_OPENSSL |
2295 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 2268 | kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; |
2296 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 2269 | kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; |
2297 | kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; | 2270 | kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; |
2298 | kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; | 2271 | kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; |
2299 | kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; | 2272 | kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; |
2300 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 2273 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
2301 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 2274 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
2302 | # ifdef OPENSSL_HAS_ECC | 2275 | # ifdef OPENSSL_HAS_ECC |
2303 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | 2276 | kex->kex[KEX_ECDH_SHA2] = kex_gen_server; |
2304 | # endif | 2277 | # endif |
2305 | #endif | 2278 | #endif |
2306 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 2279 | kex->kex[KEX_C25519_SHA256] = kex_gen_server; |
2307 | kex->server = 1; | 2280 | kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; |
2308 | kex->client_version_string=client_version_string; | ||
2309 | kex->server_version_string=server_version_string; | ||
2310 | kex->load_host_public_key=&get_hostkey_public_by_type; | 2281 | kex->load_host_public_key=&get_hostkey_public_by_type; |
2311 | kex->load_host_private_key=&get_hostkey_private_by_type; | 2282 | kex->load_host_private_key=&get_hostkey_private_by_type; |
2312 | kex->host_key_index=&get_hostkey_index; | 2283 | kex->host_key_index=&get_hostkey_index; |
2313 | kex->sign = sshd_hostkey_sign; | 2284 | kex->sign = sshd_hostkey_sign; |
2314 | 2285 | ||
2315 | ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); | 2286 | ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); |
2316 | 2287 | ||
2317 | session_id2 = kex->session_id; | 2288 | session_id2 = kex->session_id; |
2318 | session_id2_len = kex->session_id_len; | 2289 | session_id2_len = kex->session_id_len; |
@@ -2331,10 +2302,8 @@ do_ssh2_kex(void) | |||
2331 | void | 2302 | void |
2332 | cleanup_exit(int i) | 2303 | cleanup_exit(int i) |
2333 | { | 2304 | { |
2334 | struct ssh *ssh = active_state; /* XXX */ | 2305 | if (the_active_state != NULL && the_authctxt != NULL) { |
2335 | 2306 | do_cleanup(the_active_state, the_authctxt); | |
2336 | if (the_authctxt) { | ||
2337 | do_cleanup(ssh, the_authctxt); | ||
2338 | if (use_privsep && privsep_is_preauth && | 2307 | if (use_privsep && privsep_is_preauth && |
2339 | pmonitor != NULL && pmonitor->m_pid > 1) { | 2308 | pmonitor != NULL && pmonitor->m_pid > 1) { |
2340 | debug("Killing privsep child %d", pmonitor->m_pid); | 2309 | debug("Killing privsep child %d", pmonitor->m_pid); |
@@ -2346,8 +2315,8 @@ cleanup_exit(int i) | |||
2346 | } | 2315 | } |
2347 | #ifdef SSH_AUDIT_EVENTS | 2316 | #ifdef SSH_AUDIT_EVENTS |
2348 | /* done after do_cleanup so it can cancel the PAM auth 'thread' */ | 2317 | /* done after do_cleanup so it can cancel the PAM auth 'thread' */ |
2349 | if (!use_privsep || mm_is_monitor()) | 2318 | if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) |
2350 | audit_event(SSH_CONNECTION_ABANDON); | 2319 | audit_event(the_active_state, SSH_CONNECTION_ABANDON); |
2351 | #endif | 2320 | #endif |
2352 | _exit(i); | 2321 | _exit(i); |
2353 | } | 2322 | } |