summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c181
1 files changed, 105 insertions, 76 deletions
diff --git a/ssh.c b/ssh.c
index 8d73e61e3..21147f7e8 100644
--- a/ssh.c
+++ b/ssh.c
@@ -11,7 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$Id: ssh.c,v 1.11 1999/11/24 13:26:23 damien Exp $"); 14RCSID("$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. */
31int debug_flag = 0; 31int 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. */
35int tty_flag = 0; 33int 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 */
39int stdin_null_flag = 0; 39int 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 */
44int fork_after_authentication_flag = 0; 46int 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 */
48Options options; 52Options 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 */
53char *host; 59char *host;
54 60
55/* socket address the host resolves to */ 61/* socket address the host resolves to */
56struct sockaddr_in hostaddr; 62struct 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 */
62volatile int received_window_change_signal = 0; 70volatile 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)