diff options
author | Damien Miller <djm@mindrot.org> | 1999-11-25 11:54:57 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-11-25 11:54:57 +1100 |
commit | 5428f646ad32da88ddd04a8c287d595524674fbf (patch) | |
tree | cc1f1e5d7852e1f44d41077f776abf7dab7ac06d /ssh.c | |
parent | 9072e1889648988da38b7b81bce95291c1dc3a23 (diff) |
- More reformatting merged from OpenBSD CVS
- Merged OpenBSD CVS changes:
- [channels.c]
report from mrwizard@psu.edu via djm@ibs.com.au
- [channels.c]
set SO_REUSEADDR and SO_LINGER for forwarded ports.
chip@valinux.com via damien@ibs.com.au
- [nchan.c]
it's not an error() if shutdown_write failes in nchan.
- [readconf.c]
remove dead #ifdef-0-code
- [readconf.c servconf.c]
strcasecmp instead of tolower
- [scp.c]
progress meter overflow fix from damien@ibs.com.au
- [ssh-add.1 ssh-add.c]
SSH_ASKPASS support
- [ssh.1 ssh.c]
postpone fork_after_authentication until command execution,
request/patch from jahakala@cc.jyu.fi via damien@ibs.com.au
plus: use daemon() for backgrounding
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 181 |
1 files changed, 105 insertions, 76 deletions
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "includes.h" | 13 | #include "includes.h" |
14 | RCSID("$Id: ssh.c,v 1.11 1999/11/24 13:26:23 damien Exp $"); | 14 | RCSID("$Id: ssh.c,v 1.12 1999/11/25 00:54:59 damien Exp $"); |
15 | 15 | ||
16 | #include "xmalloc.h" | 16 | #include "xmalloc.h" |
17 | #include "ssh.h" | 17 | #include "ssh.h" |
@@ -30,35 +30,43 @@ const char *__progname = "ssh"; | |||
30 | /* Flag indicating whether debug mode is on. This can be set on the command line. */ | 30 | /* Flag indicating whether debug mode is on. This can be set on the command line. */ |
31 | int debug_flag = 0; | 31 | int debug_flag = 0; |
32 | 32 | ||
33 | /* Flag indicating whether to allocate a pseudo tty. This can be set on the command | ||
34 | line, and is automatically set if no command is given on the command line. */ | ||
35 | int tty_flag = 0; | 33 | int tty_flag = 0; |
36 | 34 | ||
37 | /* Flag indicating that nothing should be read from stdin. This can be set | 35 | /* |
38 | on the command line. */ | 36 | * Flag indicating that nothing should be read from stdin. This can be set |
37 | * on the command line. | ||
38 | */ | ||
39 | int stdin_null_flag = 0; | 39 | int stdin_null_flag = 0; |
40 | 40 | ||
41 | /* Flag indicating that ssh should fork after authentication. This is useful | 41 | /* |
42 | so that the pasphrase can be entered manually, and then ssh goes to the | 42 | * Flag indicating that ssh should fork after authentication. This is useful |
43 | background. */ | 43 | * so that the pasphrase can be entered manually, and then ssh goes to the |
44 | * background. | ||
45 | */ | ||
44 | int fork_after_authentication_flag = 0; | 46 | int fork_after_authentication_flag = 0; |
45 | 47 | ||
46 | /* General data structure for command line options and options configurable | 48 | /* |
47 | in configuration files. See readconf.h. */ | 49 | * General data structure for command line options and options configurable |
50 | * in configuration files. See readconf.h. | ||
51 | */ | ||
48 | Options options; | 52 | Options options; |
49 | 53 | ||
50 | /* Name of the host we are connecting to. This is the name given on the | 54 | /* |
51 | command line, or the HostName specified for the user-supplied name | 55 | * Name of the host we are connecting to. This is the name given on the |
52 | in a configuration file. */ | 56 | * command line, or the HostName specified for the user-supplied name in a |
57 | * configuration file. | ||
58 | */ | ||
53 | char *host; | 59 | char *host; |
54 | 60 | ||
55 | /* socket address the host resolves to */ | 61 | /* socket address the host resolves to */ |
56 | struct sockaddr_in hostaddr; | 62 | struct sockaddr_in hostaddr; |
57 | 63 | ||
58 | /* Flag to indicate that we have received a window change signal which has | 64 | /* |
59 | not yet been processed. This will cause a message indicating the new | 65 | * Flag to indicate that we have received a window change signal which has |
60 | window size to be sent to the server a little later. This is volatile | 66 | * not yet been processed. This will cause a message indicating the new |
61 | because this is updated in a signal handler. */ | 67 | * window size to be sent to the server a little later. This is volatile |
68 | * because this is updated in a signal handler. | ||
69 | */ | ||
62 | volatile int received_window_change_signal = 0; | 70 | volatile int received_window_change_signal = 0; |
63 | 71 | ||
64 | /* Value of argv[0] (set in the main program). */ | 72 | /* Value of argv[0] (set in the main program). */ |
@@ -165,8 +173,10 @@ main(int ac, char **av) | |||
165 | uid_t original_effective_uid; | 173 | uid_t original_effective_uid; |
166 | int plen; | 174 | int plen; |
167 | 175 | ||
168 | /* Save the original real uid. It will be needed later | 176 | /* |
169 | (uid-swapping may clobber the real uid). */ | 177 | * Save the original real uid. It will be needed later (uid-swapping |
178 | * may clobber the real uid). | ||
179 | */ | ||
170 | original_real_uid = getuid(); | 180 | original_real_uid = getuid(); |
171 | original_effective_uid = geteuid(); | 181 | original_effective_uid = geteuid(); |
172 | 182 | ||
@@ -177,18 +187,21 @@ main(int ac, char **av) | |||
177 | if (setrlimit(RLIMIT_CORE, &rlim) < 0) | 187 | if (setrlimit(RLIMIT_CORE, &rlim) < 0) |
178 | fatal("setrlimit failed: %.100s", strerror(errno)); | 188 | fatal("setrlimit failed: %.100s", strerror(errno)); |
179 | } | 189 | } |
180 | /* Use uid-swapping to give up root privileges for the duration of | 190 | /* |
181 | option processing. We will re-instantiate the rights when we | 191 | * Use uid-swapping to give up root privileges for the duration of |
182 | are ready to create the privileged port, and will permanently | 192 | * option processing. We will re-instantiate the rights when we are |
183 | drop them when the port has been created (actually, when the | 193 | * ready to create the privileged port, and will permanently drop |
184 | connection has been made, as we may need to create the port | 194 | * them when the port has been created (actually, when the connection |
185 | several times). */ | 195 | * has been made, as we may need to create the port several times). |
196 | */ | ||
186 | temporarily_use_uid(original_real_uid); | 197 | temporarily_use_uid(original_real_uid); |
187 | 198 | ||
188 | /* Set our umask to something reasonable, as some files are | 199 | /* |
189 | created with the default umask. This will make them | 200 | * Set our umask to something reasonable, as some files are created |
190 | world-readable but writable only by the owner, which is ok for | 201 | * with the default umask. This will make them world-readable but |
191 | all files for which we don't set the modes explicitly. */ | 202 | * writable only by the owner, which is ok for all files for which we |
203 | * don't set the modes explicitly. | ||
204 | */ | ||
192 | umask(022); | 205 | umask(022); |
193 | 206 | ||
194 | /* Save our own name. */ | 207 | /* Save our own name. */ |
@@ -387,10 +400,11 @@ main(int ac, char **av) | |||
387 | /* Initialize the command to execute on remote host. */ | 400 | /* Initialize the command to execute on remote host. */ |
388 | buffer_init(&command); | 401 | buffer_init(&command); |
389 | 402 | ||
390 | /* Save the command to execute on the remote host in a buffer. | 403 | /* |
391 | There is no limit on the length of the command, except by the | 404 | * Save the command to execute on the remote host in a buffer. There |
392 | maximum packet size. Also sets the tty flag if there is no | 405 | * is no limit on the length of the command, except by the maximum |
393 | command. */ | 406 | * packet size. Also sets the tty flag if there is no command. |
407 | */ | ||
394 | if (optind == ac) { | 408 | if (optind == ac) { |
395 | /* No command specified - execute shell on a tty. */ | 409 | /* No command specified - execute shell on a tty. */ |
396 | tty_flag = 1; | 410 | tty_flag = 1; |
@@ -474,11 +488,15 @@ main(int ac, char **av) | |||
474 | options.rhosts_authentication = 0; | 488 | options.rhosts_authentication = 0; |
475 | options.rhosts_rsa_authentication = 0; | 489 | options.rhosts_rsa_authentication = 0; |
476 | } | 490 | } |
477 | /* If using rsh has been selected, exec it now (without trying | 491 | /* |
478 | anything else). Note that we must release privileges first. */ | 492 | * If using rsh has been selected, exec it now (without trying |
493 | * anything else). Note that we must release privileges first. | ||
494 | */ | ||
479 | if (options.use_rsh) { | 495 | if (options.use_rsh) { |
480 | /* Restore our superuser privileges. This must be done | 496 | /* |
481 | before permanently setting the uid. */ | 497 | * Restore our superuser privileges. This must be done |
498 | * before permanently setting the uid. | ||
499 | */ | ||
482 | restore_uid(); | 500 | restore_uid(); |
483 | 501 | ||
484 | /* Switch to the original uid permanently. */ | 502 | /* Switch to the original uid permanently. */ |
@@ -491,8 +509,10 @@ main(int ac, char **av) | |||
491 | /* Restore our superuser privileges. */ | 509 | /* Restore our superuser privileges. */ |
492 | restore_uid(); | 510 | restore_uid(); |
493 | 511 | ||
494 | /* Open a connection to the remote host. This needs root | 512 | /* |
495 | privileges if rhosts_{rsa_}authentication is enabled. */ | 513 | * Open a connection to the remote host. This needs root privileges |
514 | * if rhosts_{rsa_}authentication is enabled. | ||
515 | */ | ||
496 | 516 | ||
497 | ok = ssh_connect(host, &hostaddr, options.port, | 517 | ok = ssh_connect(host, &hostaddr, options.port, |
498 | options.connection_attempts, | 518 | options.connection_attempts, |
@@ -501,31 +521,38 @@ main(int ac, char **av) | |||
501 | original_real_uid, | 521 | original_real_uid, |
502 | options.proxy_command); | 522 | options.proxy_command); |
503 | 523 | ||
504 | /* If we successfully made the connection, load the host private | 524 | /* |
505 | key in case we will need it later for combined rsa-rhosts | 525 | * If we successfully made the connection, load the host private key |
506 | authentication. This must be done before releasing extra | 526 | * in case we will need it later for combined rsa-rhosts |
507 | privileges, because the file is only readable by root. */ | 527 | * authentication. This must be done before releasing extra |
528 | * privileges, because the file is only readable by root. | ||
529 | */ | ||
508 | if (ok) { | 530 | if (ok) { |
509 | host_private_key = RSA_new(); | 531 | host_private_key = RSA_new(); |
510 | if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL)) | 532 | if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL)) |
511 | host_private_key_loaded = 1; | 533 | host_private_key_loaded = 1; |
512 | } | 534 | } |
513 | /* Get rid of any extra privileges that we may have. We will no | 535 | /* |
514 | longer need them. Also, extra privileges could make it very | 536 | * Get rid of any extra privileges that we may have. We will no |
515 | hard to read identity files and other non-world-readable files | 537 | * longer need them. Also, extra privileges could make it very hard |
516 | from the user's home directory if it happens to be on a NFS | 538 | * to read identity files and other non-world-readable files from the |
517 | volume where root is mapped to nobody. */ | 539 | * user's home directory if it happens to be on a NFS volume where |
518 | 540 | * root is mapped to nobody. | |
519 | /* Note that some legacy systems need to postpone the following | 541 | */ |
520 | call to permanently_set_uid() until the private hostkey is | 542 | |
521 | destroyed with RSA_free(). Otherwise the calling user could | 543 | /* |
522 | ptrace() the process, read the private hostkey and impersonate | 544 | * Note that some legacy systems need to postpone the following call |
523 | the host. OpenBSD does not allow ptracing of setuid processes. */ | 545 | * to permanently_set_uid() until the private hostkey is destroyed |
524 | 546 | * with RSA_free(). Otherwise the calling user could ptrace() the | |
547 | * process, read the private hostkey and impersonate the host. | ||
548 | * OpenBSD does not allow ptracing of setuid processes. | ||
549 | */ | ||
525 | permanently_set_uid(original_real_uid); | 550 | permanently_set_uid(original_real_uid); |
526 | 551 | ||
527 | /* Now that we are back to our own permissions, create ~/.ssh | 552 | /* |
528 | directory if it doesn\'t already exist. */ | 553 | * Now that we are back to our own permissions, create ~/.ssh |
554 | * directory if it doesn\'t already exist. | ||
555 | */ | ||
529 | snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR); | 556 | snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR); |
530 | if (stat(buf, &st) < 0) | 557 | if (stat(buf, &st) < 0) |
531 | if (mkdir(buf, 0755) < 0) | 558 | if (mkdir(buf, 0755) < 0) |
@@ -569,15 +596,6 @@ main(int ac, char **av) | |||
569 | /* Close connection cleanly after attack. */ | 596 | /* Close connection cleanly after attack. */ |
570 | cipher_attack_detected = packet_disconnect; | 597 | cipher_attack_detected = packet_disconnect; |
571 | 598 | ||
572 | /* If requested, fork and let ssh continue in the background. */ | ||
573 | if (fork_after_authentication_flag) { | ||
574 | int ret = fork(); | ||
575 | if (ret == -1) | ||
576 | fatal("fork failed: %.100s", strerror(errno)); | ||
577 | if (ret != 0) | ||
578 | exit(0); | ||
579 | setsid(); | ||
580 | } | ||
581 | /* Enable compression if requested. */ | 599 | /* Enable compression if requested. */ |
582 | if (options.compression) { | 600 | if (options.compression) { |
583 | debug("Requesting compression at level %d.", options.compression_level); | 601 | debug("Requesting compression at level %d.", options.compression_level); |
@@ -653,12 +671,14 @@ main(int ac, char **av) | |||
653 | if (f) | 671 | if (f) |
654 | pclose(f); | 672 | pclose(f); |
655 | #endif /* XAUTH_PATH */ | 673 | #endif /* XAUTH_PATH */ |
656 | /* If we didn't get authentication data, just make up some | 674 | /* |
657 | data. The forwarding code will check the validity of | 675 | * If we didn't get authentication data, just make up some |
658 | the response anyway, and substitute this data. The X11 | 676 | * data. The forwarding code will check the validity of the |
659 | server, however, will ignore this fake data and use | 677 | * response anyway, and substitute this data. The X11 |
660 | whatever authentication mechanisms it was using | 678 | * server, however, will ignore this fake data and use |
661 | otherwise for the local connection. */ | 679 | * whatever authentication mechanisms it was using otherwise |
680 | * for the local connection. | ||
681 | */ | ||
662 | if (!got_data) { | 682 | if (!got_data) { |
663 | u_int32_t rand = 0; | 683 | u_int32_t rand = 0; |
664 | 684 | ||
@@ -670,8 +690,10 @@ main(int ac, char **av) | |||
670 | rand >>= 8; | 690 | rand >>= 8; |
671 | } | 691 | } |
672 | } | 692 | } |
673 | /* Got local authentication reasonable information. | 693 | /* |
674 | Request forwarding with authentication spoofing. */ | 694 | * Got local authentication reasonable information. Request |
695 | * forwarding with authentication spoofing. | ||
696 | */ | ||
675 | debug("Requesting X11 forwarding with authentication spoofing."); | 697 | debug("Requesting X11 forwarding with authentication spoofing."); |
676 | x11_request_forwarding_with_spoofing(proto, data); | 698 | x11_request_forwarding_with_spoofing(proto, data); |
677 | 699 | ||
@@ -728,8 +750,15 @@ main(int ac, char **av) | |||
728 | options.remote_forwards[i].host_port); | 750 | options.remote_forwards[i].host_port); |
729 | } | 751 | } |
730 | 752 | ||
731 | /* If a command was specified on the command line, execute the | 753 | /* If requested, let ssh continue in the background. */ |
732 | command now. Otherwise request the server to start a shell. */ | 754 | if (fork_after_authentication_flag) |
755 | if (daemon(1, 1) < 0) | ||
756 | fatal("daemon() failed: %.200s", strerror(errno)); | ||
757 | |||
758 | /* | ||
759 | * If a command was specified on the command line, execute the | ||
760 | * command now. Otherwise request the server to start a shell. | ||
761 | */ | ||
733 | if (buffer_len(&command) > 0) { | 762 | if (buffer_len(&command) > 0) { |
734 | int len = buffer_len(&command); | 763 | int len = buffer_len(&command); |
735 | if (len > 900) | 764 | if (len > 900) |