diff options
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 117 |
1 files changed, 95 insertions, 22 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.343 2010/07/12 22:41:13 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.344 2010/07/19 09:15:12 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 |
@@ -128,6 +128,15 @@ int no_shell_flag = 0; | |||
128 | int stdin_null_flag = 0; | 128 | int stdin_null_flag = 0; |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Flag indicating that the current process should be backgrounded and | ||
132 | * a new slave launched in the foreground for ControlPersist. | ||
133 | */ | ||
134 | int need_controlpersist_detach = 0; | ||
135 | |||
136 | /* Copies of flags for ControlPersist foreground slave */ | ||
137 | int ostdin_null_flag, ono_shell_flag, ono_tty_flag, otty_flag; | ||
138 | |||
139 | /* | ||
131 | * Flag indicating that ssh should fork after authentication. This is useful | 140 | * Flag indicating that ssh should fork after authentication. This is useful |
132 | * so that the passphrase can be entered manually, and then ssh goes to the | 141 | * so that the passphrase can be entered manually, and then ssh goes to the |
133 | * background. | 142 | * background. |
@@ -877,6 +886,50 @@ main(int ac, char **av) | |||
877 | return exit_status; | 886 | return exit_status; |
878 | } | 887 | } |
879 | 888 | ||
889 | static void | ||
890 | control_persist_detach(void) | ||
891 | { | ||
892 | pid_t pid; | ||
893 | |||
894 | debug("%s: backgrounding master process", __func__); | ||
895 | |||
896 | /* | ||
897 | * master (current process) into the background, and make the | ||
898 | * foreground process a client of the backgrounded master. | ||
899 | */ | ||
900 | switch ((pid = fork())) { | ||
901 | case -1: | ||
902 | fatal("%s: fork: %s", __func__, strerror(errno)); | ||
903 | case 0: | ||
904 | /* Child: master process continues mainloop */ | ||
905 | break; | ||
906 | default: | ||
907 | /* Parent: set up mux slave to connect to backgrounded master */ | ||
908 | debug2("%s: background process is %ld", __func__, (long)pid); | ||
909 | stdin_null_flag = ostdin_null_flag; | ||
910 | no_shell_flag = ono_shell_flag; | ||
911 | no_tty_flag = ono_tty_flag; | ||
912 | tty_flag = otty_flag; | ||
913 | close(muxserver_sock); | ||
914 | muxserver_sock = -1; | ||
915 | muxclient(options.control_path); | ||
916 | /* muxclient() doesn't return on success. */ | ||
917 | fatal("Failed to connect to new control master"); | ||
918 | } | ||
919 | } | ||
920 | |||
921 | /* Do fork() after authentication. Used by "ssh -f" */ | ||
922 | static void | ||
923 | fork_postauth(void) | ||
924 | { | ||
925 | if (need_controlpersist_detach) | ||
926 | control_persist_detach(); | ||
927 | debug("forking to background"); | ||
928 | fork_after_authentication_flag = 0; | ||
929 | if (daemon(1, 1) < 0) | ||
930 | fatal("daemon() failed: %.200s", strerror(errno)); | ||
931 | } | ||
932 | |||
880 | /* Callback for remote forward global requests */ | 933 | /* Callback for remote forward global requests */ |
881 | static void | 934 | static void |
882 | ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | 935 | ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) |
@@ -904,12 +957,8 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
904 | } | 957 | } |
905 | if (++remote_forward_confirms_received == options.num_remote_forwards) { | 958 | if (++remote_forward_confirms_received == options.num_remote_forwards) { |
906 | debug("All remote forwarding requests processed"); | 959 | debug("All remote forwarding requests processed"); |
907 | if (fork_after_authentication_flag) { | 960 | if (fork_after_authentication_flag) |
908 | fork_after_authentication_flag = 0; | 961 | fork_postauth(); |
909 | if (daemon(1, 1) < 0) | ||
910 | fatal("daemon() failed: %.200s", | ||
911 | strerror(errno)); | ||
912 | } | ||
913 | } | 962 | } |
914 | } | 963 | } |
915 | 964 | ||
@@ -1153,12 +1202,13 @@ ssh_session(void) | |||
1153 | * If requested and we are not interested in replies to remote | 1202 | * If requested and we are not interested in replies to remote |
1154 | * forwarding requests, then let ssh continue in the background. | 1203 | * forwarding requests, then let ssh continue in the background. |
1155 | */ | 1204 | */ |
1156 | if (fork_after_authentication_flag && | 1205 | if (fork_after_authentication_flag) { |
1157 | (!options.exit_on_forward_failure || | 1206 | if (options.exit_on_forward_failure && |
1158 | options.num_remote_forwards == 0)) { | 1207 | options.num_remote_forwards > 0) { |
1159 | fork_after_authentication_flag = 0; | 1208 | debug("deferring postauth fork until remote forward " |
1160 | if (daemon(1, 1) < 0) | 1209 | "confirmation received"); |
1161 | fatal("daemon() failed: %.200s", strerror(errno)); | 1210 | } else |
1211 | fork_postauth(); | ||
1162 | } | 1212 | } |
1163 | 1213 | ||
1164 | /* | 1214 | /* |
@@ -1281,6 +1331,31 @@ ssh_session2(void) | |||
1281 | /* XXX should be pre-session */ | 1331 | /* XXX should be pre-session */ |
1282 | ssh_init_forwarding(); | 1332 | ssh_init_forwarding(); |
1283 | 1333 | ||
1334 | /* Start listening for multiplex clients */ | ||
1335 | muxserver_listen(); | ||
1336 | |||
1337 | /* | ||
1338 | * If we are in control persist mode, then prepare to background | ||
1339 | * ourselves and have a foreground client attach as a control | ||
1340 | * slave. NB. we must save copies of the flags that we override for | ||
1341 | * the backgrounding, since we defer attachment of the slave until | ||
1342 | * after the connection is fully established (in particular, | ||
1343 | * async rfwd replies have been received for ExitOnForwardFailure). | ||
1344 | */ | ||
1345 | if (options.control_persist && muxserver_sock != -1) { | ||
1346 | ostdin_null_flag = stdin_null_flag; | ||
1347 | ono_shell_flag = no_shell_flag; | ||
1348 | ono_tty_flag = no_tty_flag; | ||
1349 | otty_flag = tty_flag; | ||
1350 | stdin_null_flag = 1; | ||
1351 | no_shell_flag = 1; | ||
1352 | no_tty_flag = 1; | ||
1353 | tty_flag = 0; | ||
1354 | if (!fork_after_authentication_flag) | ||
1355 | need_controlpersist_detach = 1; | ||
1356 | fork_after_authentication_flag = 1; | ||
1357 | } | ||
1358 | |||
1284 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) | 1359 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
1285 | id = ssh_session2_open(); | 1360 | id = ssh_session2_open(); |
1286 | 1361 | ||
@@ -1299,19 +1374,17 @@ ssh_session2(void) | |||
1299 | options.permit_local_command) | 1374 | options.permit_local_command) |
1300 | ssh_local_cmd(options.local_command); | 1375 | ssh_local_cmd(options.local_command); |
1301 | 1376 | ||
1302 | /* Start listening for multiplex clients */ | ||
1303 | muxserver_listen(); | ||
1304 | |||
1305 | /* | 1377 | /* |
1306 | * If requested and we are not interested in replies to remote | 1378 | * If requested and we are not interested in replies to remote |
1307 | * forwarding requests, then let ssh continue in the background. | 1379 | * forwarding requests, then let ssh continue in the background. |
1308 | */ | 1380 | */ |
1309 | if (fork_after_authentication_flag && | 1381 | if (fork_after_authentication_flag) { |
1310 | (!options.exit_on_forward_failure || | 1382 | if (options.exit_on_forward_failure && |
1311 | options.num_remote_forwards == 0)) { | 1383 | options.num_remote_forwards > 0) { |
1312 | fork_after_authentication_flag = 0; | 1384 | debug("deferring postauth fork until remote forward " |
1313 | if (daemon(1, 1) < 0) | 1385 | "confirmation received"); |
1314 | fatal("daemon() failed: %.200s", strerror(errno)); | 1386 | } else |
1387 | fork_postauth(); | ||
1315 | } | 1388 | } |
1316 | 1389 | ||
1317 | if (options.use_roaming) | 1390 | if (options.use_roaming) |