diff options
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 279 |
1 files changed, 246 insertions, 33 deletions
@@ -42,7 +42,7 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include "includes.h" | 44 | #include "includes.h" |
45 | RCSID("$OpenBSD: sshd.c,v 1.290 2004/03/11 10:21:17 markus Exp $"); | 45 | RCSID("$OpenBSD: sshd.c,v 1.301 2004/08/11 11:50:09 dtucker Exp $"); |
46 | 46 | ||
47 | #include <openssl/dh.h> | 47 | #include <openssl/dh.h> |
48 | #include <openssl/bn.h> | 48 | #include <openssl/bn.h> |
@@ -60,12 +60,12 @@ RCSID("$OpenBSD: sshd.c,v 1.290 2004/03/11 10:21:17 markus Exp $"); | |||
60 | #include "rsa.h" | 60 | #include "rsa.h" |
61 | #include "sshpty.h" | 61 | #include "sshpty.h" |
62 | #include "packet.h" | 62 | #include "packet.h" |
63 | #include "mpaux.h" | ||
64 | #include "log.h" | 63 | #include "log.h" |
65 | #include "servconf.h" | 64 | #include "servconf.h" |
66 | #include "uidswap.h" | 65 | #include "uidswap.h" |
67 | #include "compat.h" | 66 | #include "compat.h" |
68 | #include "buffer.h" | 67 | #include "buffer.h" |
68 | #include "bufaux.h" | ||
69 | #include "cipher.h" | 69 | #include "cipher.h" |
70 | #include "kex.h" | 70 | #include "kex.h" |
71 | #include "key.h" | 71 | #include "key.h" |
@@ -77,6 +77,7 @@ RCSID("$OpenBSD: sshd.c,v 1.290 2004/03/11 10:21:17 markus Exp $"); | |||
77 | #include "canohost.h" | 77 | #include "canohost.h" |
78 | #include "auth.h" | 78 | #include "auth.h" |
79 | #include "misc.h" | 79 | #include "misc.h" |
80 | #include "msg.h" | ||
80 | #include "dispatch.h" | 81 | #include "dispatch.h" |
81 | #include "channels.h" | 82 | #include "channels.h" |
82 | #include "session.h" | 83 | #include "session.h" |
@@ -96,11 +97,13 @@ int deny_severity = LOG_WARNING; | |||
96 | #define O_NOCTTY 0 | 97 | #define O_NOCTTY 0 |
97 | #endif | 98 | #endif |
98 | 99 | ||
99 | #ifdef HAVE___PROGNAME | 100 | /* Re-exec fds */ |
101 | #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) | ||
102 | #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) | ||
103 | #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) | ||
104 | #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) | ||
105 | |||
100 | extern char *__progname; | 106 | extern char *__progname; |
101 | #else | ||
102 | char *__progname; | ||
103 | #endif | ||
104 | 107 | ||
105 | /* Server configuration options. */ | 108 | /* Server configuration options. */ |
106 | ServerOptions options; | 109 | ServerOptions options; |
@@ -138,6 +141,12 @@ int log_stderr = 0; | |||
138 | char **saved_argv; | 141 | char **saved_argv; |
139 | int saved_argc; | 142 | int saved_argc; |
140 | 143 | ||
144 | /* re-exec */ | ||
145 | int rexeced_flag = 0; | ||
146 | int rexec_flag = 1; | ||
147 | int rexec_argc = 0; | ||
148 | char **rexec_argv; | ||
149 | |||
141 | /* | 150 | /* |
142 | * The sockets that the server is listening; this is used in the SIGHUP | 151 | * The sockets that the server is listening; this is used in the SIGHUP |
143 | * signal handler. | 152 | * signal handler. |
@@ -201,12 +210,12 @@ int startup_pipe; /* in child */ | |||
201 | int use_privsep; | 210 | int use_privsep; |
202 | struct monitor *pmonitor = NULL; | 211 | struct monitor *pmonitor = NULL; |
203 | 212 | ||
204 | /* message to be displayed after login */ | ||
205 | Buffer loginmsg; | ||
206 | |||
207 | /* global authentication context */ | 213 | /* global authentication context */ |
208 | Authctxt *the_authctxt = NULL; | 214 | Authctxt *the_authctxt = NULL; |
209 | 215 | ||
216 | /* message to be displayed after login */ | ||
217 | Buffer loginmsg; | ||
218 | |||
210 | /* Prototypes for various functions defined later in this file. */ | 219 | /* Prototypes for various functions defined later in this file. */ |
211 | void destroy_sensitive_data(void); | 220 | void destroy_sensitive_data(void); |
212 | void demote_sensitive_data(void); | 221 | void demote_sensitive_data(void); |
@@ -650,6 +659,7 @@ privsep_postauth(Authctxt *authctxt) | |||
650 | else if (pmonitor->m_pid != 0) { | 659 | else if (pmonitor->m_pid != 0) { |
651 | debug2("User child is on pid %ld", (long)pmonitor->m_pid); | 660 | debug2("User child is on pid %ld", (long)pmonitor->m_pid); |
652 | close(pmonitor->m_recvfd); | 661 | close(pmonitor->m_recvfd); |
662 | buffer_clear(&loginmsg); | ||
653 | monitor_child_postauth(pmonitor); | 663 | monitor_child_postauth(pmonitor); |
654 | 664 | ||
655 | /* NEVERREACHED */ | 665 | /* NEVERREACHED */ |
@@ -772,6 +782,87 @@ usage(void) | |||
772 | exit(1); | 782 | exit(1); |
773 | } | 783 | } |
774 | 784 | ||
785 | static void | ||
786 | send_rexec_state(int fd, Buffer *conf) | ||
787 | { | ||
788 | Buffer m; | ||
789 | |||
790 | debug3("%s: entering fd = %d config len %d", __func__, fd, | ||
791 | buffer_len(conf)); | ||
792 | |||
793 | /* | ||
794 | * Protocol from reexec master to child: | ||
795 | * string configuration | ||
796 | * u_int ephemeral_key_follows | ||
797 | * bignum e (only if ephemeral_key_follows == 1) | ||
798 | * bignum n " | ||
799 | * bignum d " | ||
800 | * bignum iqmp " | ||
801 | * bignum p " | ||
802 | * bignum q " | ||
803 | */ | ||
804 | buffer_init(&m); | ||
805 | buffer_put_cstring(&m, buffer_ptr(conf)); | ||
806 | |||
807 | if (sensitive_data.server_key != NULL && | ||
808 | sensitive_data.server_key->type == KEY_RSA1) { | ||
809 | buffer_put_int(&m, 1); | ||
810 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->e); | ||
811 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->n); | ||
812 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->d); | ||
813 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp); | ||
814 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); | ||
815 | buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); | ||
816 | } else | ||
817 | buffer_put_int(&m, 0); | ||
818 | |||
819 | if (ssh_msg_send(fd, 0, &m) == -1) | ||
820 | fatal("%s: ssh_msg_send failed", __func__); | ||
821 | |||
822 | buffer_free(&m); | ||
823 | |||
824 | debug3("%s: done", __func__); | ||
825 | } | ||
826 | |||
827 | static void | ||
828 | recv_rexec_state(int fd, Buffer *conf) | ||
829 | { | ||
830 | Buffer m; | ||
831 | char *cp; | ||
832 | u_int len; | ||
833 | |||
834 | debug3("%s: entering fd = %d", __func__, fd); | ||
835 | |||
836 | buffer_init(&m); | ||
837 | |||
838 | if (ssh_msg_recv(fd, &m) == -1) | ||
839 | fatal("%s: ssh_msg_recv failed", __func__); | ||
840 | if (buffer_get_char(&m) != 0) | ||
841 | fatal("%s: rexec version mismatch", __func__); | ||
842 | |||
843 | cp = buffer_get_string(&m, &len); | ||
844 | if (conf != NULL) | ||
845 | buffer_append(conf, cp, len + 1); | ||
846 | xfree(cp); | ||
847 | |||
848 | if (buffer_get_int(&m)) { | ||
849 | if (sensitive_data.server_key != NULL) | ||
850 | key_free(sensitive_data.server_key); | ||
851 | sensitive_data.server_key = key_new_private(KEY_RSA1); | ||
852 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->e); | ||
853 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->n); | ||
854 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->d); | ||
855 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); | ||
856 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); | ||
857 | buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); | ||
858 | rsa_generate_additional_parameters( | ||
859 | sensitive_data.server_key->rsa); | ||
860 | } | ||
861 | buffer_free(&m); | ||
862 | |||
863 | debug3("%s: done", __func__); | ||
864 | } | ||
865 | |||
775 | /* | 866 | /* |
776 | * Main program for the daemon. | 867 | * Main program for the daemon. |
777 | */ | 868 | */ |
@@ -780,7 +871,8 @@ main(int ac, char **av) | |||
780 | { | 871 | { |
781 | extern char *optarg; | 872 | extern char *optarg; |
782 | extern int optind; | 873 | extern int optind; |
783 | int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1; | 874 | int opt, j, i, fdsetsz, on = 1; |
875 | int sock_in = -1, sock_out = -1, newsock = -1; | ||
784 | pid_t pid; | 876 | pid_t pid; |
785 | socklen_t fromlen; | 877 | socklen_t fromlen; |
786 | fd_set *fdset; | 878 | fd_set *fdset; |
@@ -792,11 +884,12 @@ main(int ac, char **av) | |||
792 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 884 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
793 | char *line; | 885 | char *line; |
794 | int listen_sock, maxfd; | 886 | int listen_sock, maxfd; |
795 | int startup_p[2]; | 887 | int startup_p[2], config_s[2]; |
796 | int startups = 0; | 888 | int startups = 0; |
797 | Key *key; | 889 | Key *key; |
798 | Authctxt *authctxt; | 890 | Authctxt *authctxt; |
799 | int ret, key_used = 0; | 891 | int ret, key_used = 0; |
892 | Buffer cfg; | ||
800 | 893 | ||
801 | #ifdef HAVE_SECUREWARE | 894 | #ifdef HAVE_SECUREWARE |
802 | (void)set_auth_parameters(ac, av); | 895 | (void)set_auth_parameters(ac, av); |
@@ -806,6 +899,7 @@ main(int ac, char **av) | |||
806 | 899 | ||
807 | /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ | 900 | /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ |
808 | saved_argc = ac; | 901 | saved_argc = ac; |
902 | rexec_argc = ac; | ||
809 | saved_argv = xmalloc(sizeof(*saved_argv) * (ac + 1)); | 903 | saved_argv = xmalloc(sizeof(*saved_argv) * (ac + 1)); |
810 | for (i = 0; i < ac; i++) | 904 | for (i = 0; i < ac; i++) |
811 | saved_argv[i] = xstrdup(av[i]); | 905 | saved_argv[i] = xstrdup(av[i]); |
@@ -824,7 +918,7 @@ main(int ac, char **av) | |||
824 | initialize_server_options(&options); | 918 | initialize_server_options(&options); |
825 | 919 | ||
826 | /* Parse command-line arguments. */ | 920 | /* Parse command-line arguments. */ |
827 | while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqtQ46")) != -1) { | 921 | while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqrtQR46")) != -1) { |
828 | switch (opt) { | 922 | switch (opt) { |
829 | case '4': | 923 | case '4': |
830 | IPv4or6 = AF_INET; | 924 | IPv4or6 = AF_INET; |
@@ -851,6 +945,13 @@ main(int ac, char **av) | |||
851 | case 'i': | 945 | case 'i': |
852 | inetd_flag = 1; | 946 | inetd_flag = 1; |
853 | break; | 947 | break; |
948 | case 'r': | ||
949 | rexec_flag = 0; | ||
950 | break; | ||
951 | case 'R': | ||
952 | rexeced_flag = 1; | ||
953 | inetd_flag = 1; | ||
954 | break; | ||
854 | case 'Q': | 955 | case 'Q': |
855 | /* ignored */ | 956 | /* ignored */ |
856 | break; | 957 | break; |
@@ -919,6 +1020,15 @@ main(int ac, char **av) | |||
919 | break; | 1020 | break; |
920 | } | 1021 | } |
921 | } | 1022 | } |
1023 | if (rexeced_flag || inetd_flag) | ||
1024 | rexec_flag = 0; | ||
1025 | if (rexec_flag && (av[0] == NULL || *av[0] != '/')) | ||
1026 | fatal("sshd re-exec requires execution with an absolute path"); | ||
1027 | if (rexeced_flag) | ||
1028 | closefrom(REEXEC_MIN_FREE_FD); | ||
1029 | else | ||
1030 | closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); | ||
1031 | |||
922 | SSLeay_add_all_algorithms(); | 1032 | SSLeay_add_all_algorithms(); |
923 | channel_set_af(IPv4or6); | 1033 | channel_set_af(IPv4or6); |
924 | 1034 | ||
@@ -941,7 +1051,7 @@ main(int ac, char **av) | |||
941 | unsetenv("KRB5CCNAME"); | 1051 | unsetenv("KRB5CCNAME"); |
942 | #endif /* _AIX */ | 1052 | #endif /* _AIX */ |
943 | #ifdef _UNICOS | 1053 | #ifdef _UNICOS |
944 | /* Cray can define user privs drop all prives now! | 1054 | /* Cray can define user privs drop all privs now! |
945 | * Not needed on PRIV_SU systems! | 1055 | * Not needed on PRIV_SU systems! |
946 | */ | 1056 | */ |
947 | drop_cray_privs(); | 1057 | drop_cray_privs(); |
@@ -949,8 +1059,23 @@ main(int ac, char **av) | |||
949 | 1059 | ||
950 | seed_rng(); | 1060 | seed_rng(); |
951 | 1061 | ||
952 | /* Read server configuration options from the configuration file. */ | 1062 | sensitive_data.server_key = NULL; |
953 | read_server_config(&options, config_file_name); | 1063 | sensitive_data.ssh1_host_key = NULL; |
1064 | sensitive_data.have_ssh1_key = 0; | ||
1065 | sensitive_data.have_ssh2_key = 0; | ||
1066 | |||
1067 | /* Fetch our configuration */ | ||
1068 | buffer_init(&cfg); | ||
1069 | if (rexeced_flag) | ||
1070 | recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg); | ||
1071 | else | ||
1072 | load_server_config(config_file_name, &cfg); | ||
1073 | |||
1074 | parse_server_config(&options, | ||
1075 | rexeced_flag ? "rexec" : config_file_name, &cfg); | ||
1076 | |||
1077 | if (!rexec_flag) | ||
1078 | buffer_free(&cfg); | ||
954 | 1079 | ||
955 | /* Fill in default values for those options not explicitly set. */ | 1080 | /* Fill in default values for those options not explicitly set. */ |
956 | fill_default_server_options(&options); | 1081 | fill_default_server_options(&options); |
@@ -968,10 +1093,6 @@ main(int ac, char **av) | |||
968 | sizeof(Key *)); | 1093 | sizeof(Key *)); |
969 | for (i = 0; i < options.num_host_key_files; i++) | 1094 | for (i = 0; i < options.num_host_key_files; i++) |
970 | sensitive_data.host_keys[i] = NULL; | 1095 | sensitive_data.host_keys[i] = NULL; |
971 | sensitive_data.server_key = NULL; | ||
972 | sensitive_data.ssh1_host_key = NULL; | ||
973 | sensitive_data.have_ssh1_key = 0; | ||
974 | sensitive_data.have_ssh2_key = 0; | ||
975 | 1096 | ||
976 | for (i = 0; i < options.num_host_key_files; i++) { | 1097 | for (i = 0; i < options.num_host_key_files; i++) { |
977 | key = key_load_private(options.host_key_files[i], "", NULL); | 1098 | key = key_load_private(options.host_key_files[i], "", NULL); |
@@ -1070,6 +1191,16 @@ main(int ac, char **av) | |||
1070 | if (setgroups(0, NULL) < 0) | 1191 | if (setgroups(0, NULL) < 0) |
1071 | debug("setgroups() failed: %.200s", strerror(errno)); | 1192 | debug("setgroups() failed: %.200s", strerror(errno)); |
1072 | 1193 | ||
1194 | if (rexec_flag) { | ||
1195 | rexec_argv = xmalloc(sizeof(char *) * (rexec_argc + 2)); | ||
1196 | for (i = 0; i < rexec_argc; i++) { | ||
1197 | debug("rexec_argv[%d]='%s'", i, saved_argv[i]); | ||
1198 | rexec_argv[i] = saved_argv[i]; | ||
1199 | } | ||
1200 | rexec_argv[rexec_argc] = "-R"; | ||
1201 | rexec_argv[rexec_argc + 1] = NULL; | ||
1202 | } | ||
1203 | |||
1073 | /* Initialize the log (it is reinitialized below in case we forked). */ | 1204 | /* Initialize the log (it is reinitialized below in case we forked). */ |
1074 | if (debug_flag && !inetd_flag) | 1205 | if (debug_flag && !inetd_flag) |
1075 | log_stderr = 1; | 1206 | log_stderr = 1; |
@@ -1111,19 +1242,34 @@ main(int ac, char **av) | |||
1111 | 1242 | ||
1112 | /* Start listening for a socket, unless started from inetd. */ | 1243 | /* Start listening for a socket, unless started from inetd. */ |
1113 | if (inetd_flag) { | 1244 | if (inetd_flag) { |
1114 | int s1; | 1245 | int fd; |
1115 | s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */ | 1246 | |
1116 | dup(s1); | ||
1117 | sock_in = dup(0); | ||
1118 | sock_out = dup(1); | ||
1119 | startup_pipe = -1; | 1247 | startup_pipe = -1; |
1248 | if (rexeced_flag) { | ||
1249 | close(REEXEC_CONFIG_PASS_FD); | ||
1250 | sock_in = sock_out = dup(STDIN_FILENO); | ||
1251 | if (!debug_flag) { | ||
1252 | startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); | ||
1253 | close(REEXEC_STARTUP_PIPE_FD); | ||
1254 | } | ||
1255 | } else { | ||
1256 | sock_in = dup(STDIN_FILENO); | ||
1257 | sock_out = dup(STDOUT_FILENO); | ||
1258 | } | ||
1120 | /* | 1259 | /* |
1121 | * We intentionally do not close the descriptors 0, 1, and 2 | 1260 | * We intentionally do not close the descriptors 0, 1, and 2 |
1122 | * as our code for setting the descriptors won\'t work if | 1261 | * as our code for setting the descriptors won't work if |
1123 | * ttyfd happens to be one of those. | 1262 | * ttyfd happens to be one of those. |
1124 | */ | 1263 | */ |
1264 | if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { | ||
1265 | dup2(fd, STDIN_FILENO); | ||
1266 | dup2(fd, STDOUT_FILENO); | ||
1267 | if (fd > STDOUT_FILENO) | ||
1268 | close(fd); | ||
1269 | } | ||
1125 | debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); | 1270 | debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); |
1126 | if (options.protocol & SSH_PROTO_1) | 1271 | if ((options.protocol & SSH_PROTO_1) && |
1272 | sensitive_data.server_key == NULL) | ||
1127 | generate_ephemeral_server_key(); | 1273 | generate_ephemeral_server_key(); |
1128 | } else { | 1274 | } else { |
1129 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { | 1275 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { |
@@ -1146,8 +1292,7 @@ main(int ac, char **av) | |||
1146 | verbose("socket: %.100s", strerror(errno)); | 1292 | verbose("socket: %.100s", strerror(errno)); |
1147 | continue; | 1293 | continue; |
1148 | } | 1294 | } |
1149 | if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) { | 1295 | if (set_nonblock(listen_sock) == -1) { |
1150 | error("listen_sock O_NONBLOCK: %s", strerror(errno)); | ||
1151 | close(listen_sock); | 1296 | close(listen_sock); |
1152 | continue; | 1297 | continue; |
1153 | } | 1298 | } |
@@ -1290,8 +1435,7 @@ main(int ac, char **av) | |||
1290 | error("accept: %.100s", strerror(errno)); | 1435 | error("accept: %.100s", strerror(errno)); |
1291 | continue; | 1436 | continue; |
1292 | } | 1437 | } |
1293 | if (fcntl(newsock, F_SETFL, 0) < 0) { | 1438 | if (unset_nonblock(newsock) == -1) { |
1294 | error("newsock del O_NONBLOCK: %s", strerror(errno)); | ||
1295 | close(newsock); | 1439 | close(newsock); |
1296 | continue; | 1440 | continue; |
1297 | } | 1441 | } |
@@ -1305,6 +1449,16 @@ main(int ac, char **av) | |||
1305 | continue; | 1449 | continue; |
1306 | } | 1450 | } |
1307 | 1451 | ||
1452 | if (rexec_flag && socketpair(AF_UNIX, | ||
1453 | SOCK_STREAM, 0, config_s) == -1) { | ||
1454 | error("reexec socketpair: %s", | ||
1455 | strerror(errno)); | ||
1456 | close(newsock); | ||
1457 | close(startup_p[0]); | ||
1458 | close(startup_p[1]); | ||
1459 | continue; | ||
1460 | } | ||
1461 | |||
1308 | for (j = 0; j < options.max_startups; j++) | 1462 | for (j = 0; j < options.max_startups; j++) |
1309 | if (startup_pipes[j] == -1) { | 1463 | if (startup_pipes[j] == -1) { |
1310 | startup_pipes[j] = startup_p[0]; | 1464 | startup_pipes[j] = startup_p[0]; |
@@ -1328,8 +1482,15 @@ main(int ac, char **av) | |||
1328 | close_listen_socks(); | 1482 | close_listen_socks(); |
1329 | sock_in = newsock; | 1483 | sock_in = newsock; |
1330 | sock_out = newsock; | 1484 | sock_out = newsock; |
1485 | close(startup_p[0]); | ||
1486 | close(startup_p[1]); | ||
1331 | startup_pipe = -1; | 1487 | startup_pipe = -1; |
1332 | pid = getpid(); | 1488 | pid = getpid(); |
1489 | if (rexec_flag) { | ||
1490 | send_rexec_state(config_s[0], | ||
1491 | &cfg); | ||
1492 | close(config_s[0]); | ||
1493 | } | ||
1333 | break; | 1494 | break; |
1334 | } else { | 1495 | } else { |
1335 | /* | 1496 | /* |
@@ -1351,6 +1512,7 @@ main(int ac, char **av) | |||
1351 | sock_in = newsock; | 1512 | sock_in = newsock; |
1352 | sock_out = newsock; | 1513 | sock_out = newsock; |
1353 | log_init(__progname, options.log_level, options.log_facility, log_stderr); | 1514 | log_init(__progname, options.log_level, options.log_facility, log_stderr); |
1515 | close(config_s[0]); | ||
1354 | break; | 1516 | break; |
1355 | } | 1517 | } |
1356 | } | 1518 | } |
@@ -1363,6 +1525,12 @@ main(int ac, char **av) | |||
1363 | 1525 | ||
1364 | close(startup_p[1]); | 1526 | close(startup_p[1]); |
1365 | 1527 | ||
1528 | if (rexec_flag) { | ||
1529 | send_rexec_state(config_s[0], &cfg); | ||
1530 | close(config_s[0]); | ||
1531 | close(config_s[1]); | ||
1532 | } | ||
1533 | |||
1366 | /* Mark that the key has been used (it was "given" to the child). */ | 1534 | /* Mark that the key has been used (it was "given" to the child). */ |
1367 | if ((options.protocol & SSH_PROTO_1) && | 1535 | if ((options.protocol & SSH_PROTO_1) && |
1368 | key_used == 0) { | 1536 | key_used == 0) { |
@@ -1401,6 +1569,46 @@ main(int ac, char **av) | |||
1401 | error("setsid: %.100s", strerror(errno)); | 1569 | error("setsid: %.100s", strerror(errno)); |
1402 | #endif | 1570 | #endif |
1403 | 1571 | ||
1572 | if (rexec_flag) { | ||
1573 | int fd; | ||
1574 | |||
1575 | debug("rexec start in %d out %d newsock %d pipe %d sock %d", | ||
1576 | sock_in, sock_out, newsock, startup_pipe, config_s[0]); | ||
1577 | dup2(newsock, STDIN_FILENO); | ||
1578 | dup2(STDIN_FILENO, STDOUT_FILENO); | ||
1579 | if (startup_pipe == -1) | ||
1580 | close(REEXEC_STARTUP_PIPE_FD); | ||
1581 | else | ||
1582 | dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD); | ||
1583 | |||
1584 | dup2(config_s[1], REEXEC_CONFIG_PASS_FD); | ||
1585 | close(config_s[1]); | ||
1586 | if (startup_pipe != -1) | ||
1587 | close(startup_pipe); | ||
1588 | |||
1589 | execv(rexec_argv[0], rexec_argv); | ||
1590 | |||
1591 | /* Reexec has failed, fall back and continue */ | ||
1592 | error("rexec of %s failed: %s", rexec_argv[0], strerror(errno)); | ||
1593 | recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL); | ||
1594 | log_init(__progname, options.log_level, | ||
1595 | options.log_facility, log_stderr); | ||
1596 | |||
1597 | /* Clean up fds */ | ||
1598 | startup_pipe = REEXEC_STARTUP_PIPE_FD; | ||
1599 | close(config_s[1]); | ||
1600 | close(REEXEC_CONFIG_PASS_FD); | ||
1601 | newsock = sock_out = sock_in = dup(STDIN_FILENO); | ||
1602 | if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { | ||
1603 | dup2(fd, STDIN_FILENO); | ||
1604 | dup2(fd, STDOUT_FILENO); | ||
1605 | if (fd > STDERR_FILENO) | ||
1606 | close(fd); | ||
1607 | } | ||
1608 | debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d", | ||
1609 | sock_in, sock_out, newsock, startup_pipe, config_s[0]); | ||
1610 | } | ||
1611 | |||
1404 | /* | 1612 | /* |
1405 | * Disable the key regeneration alarm. We will not regenerate the | 1613 | * Disable the key regeneration alarm. We will not regenerate the |
1406 | * key since we are no longer in a position to give it to anyone. We | 1614 | * key since we are no longer in a position to give it to anyone. We |
@@ -1431,7 +1639,7 @@ main(int ac, char **av) | |||
1431 | 1639 | ||
1432 | #ifdef LIBWRAP | 1640 | #ifdef LIBWRAP |
1433 | /* Check whether logins are denied from this host. */ | 1641 | /* Check whether logins are denied from this host. */ |
1434 | { | 1642 | if (packet_connection_is_on_socket()) { |
1435 | struct request_info req; | 1643 | struct request_info req; |
1436 | 1644 | ||
1437 | request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); | 1645 | request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); |
@@ -1479,6 +1687,9 @@ main(int ac, char **av) | |||
1479 | if (privsep_preauth(authctxt) == 1) | 1687 | if (privsep_preauth(authctxt) == 1) |
1480 | goto authenticated; | 1688 | goto authenticated; |
1481 | 1689 | ||
1690 | /* prepare buffer to collect messages to display to user after login */ | ||
1691 | buffer_init(&loginmsg); | ||
1692 | |||
1482 | /* perform the key exchange */ | 1693 | /* perform the key exchange */ |
1483 | /* authenticate user and start session */ | 1694 | /* authenticate user and start session */ |
1484 | if (compat20) { | 1695 | if (compat20) { |
@@ -1694,9 +1905,10 @@ do_ssh1_kex(void) | |||
1694 | BN_bn2bin(session_key_int, | 1905 | BN_bn2bin(session_key_int, |
1695 | session_key + sizeof(session_key) - len); | 1906 | session_key + sizeof(session_key) - len); |
1696 | 1907 | ||
1697 | compute_session_id(session_id, cookie, | 1908 | derive_ssh1_session_id( |
1698 | sensitive_data.ssh1_host_key->rsa->n, | 1909 | sensitive_data.ssh1_host_key->rsa->n, |
1699 | sensitive_data.server_key->rsa->n); | 1910 | sensitive_data.server_key->rsa->n, |
1911 | cookie, session_id); | ||
1700 | /* | 1912 | /* |
1701 | * Xor the first 16 bytes of the session key with the | 1913 | * Xor the first 16 bytes of the session key with the |
1702 | * session id. | 1914 | * session id. |
@@ -1779,6 +1991,7 @@ do_ssh2_kex(void) | |||
1779 | /* start key exchange */ | 1991 | /* start key exchange */ |
1780 | kex = kex_setup(myproposal); | 1992 | kex = kex_setup(myproposal); |
1781 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; | 1993 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; |
1994 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | ||
1782 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 1995 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
1783 | kex->server = 1; | 1996 | kex->server = 1; |
1784 | kex->client_version_string=client_version_string; | 1997 | kex->client_version_string=client_version_string; |