| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 1 | /* | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 2 |  * Author: Tatu Ylonen <ylo@cs.hut.fi> | 
 | 3 |  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 
 | 4 |  *                    All rights reserved | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 5 |  * Ssh client program.  This program can be used to log into a remote machine. | 
 | 6 |  * The software supports strong authentication, encryption, and forwarding | 
 | 7 |  * of X11, TCP/IP, and authentication connections. | 
 | 8 |  * | 
| Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 9 |  * As far as I am concerned, the code I have written for this software | 
 | 10 |  * can be used freely for any purpose.  Any derived versions of this | 
 | 11 |  * software must be clearly marked as such, and if the derived work is | 
 | 12 |  * incompatible with the protocol description in the RFC file, it must be | 
 | 13 |  * called by a name other than "ssh" or "Secure Shell". | 
 | 14 |  * | 
 | 15 |  * Copyright (c) 1999 Niels Provos.  All rights reserved. | 
| Ben Lindstrom | eb041dc | 2002-03-27 17:20:38 +0000 | [diff] [blame] | 16 |  * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved. | 
| Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 17 |  * | 
 | 18 |  * Modified to work with SSL by Niels Provos <provos@citi.umich.edu> | 
 | 19 |  * in Canada (German citizen). | 
 | 20 |  * | 
 | 21 |  * Redistribution and use in source and binary forms, with or without | 
 | 22 |  * modification, are permitted provided that the following conditions | 
 | 23 |  * are met: | 
 | 24 |  * 1. Redistributions of source code must retain the above copyright | 
 | 25 |  *    notice, this list of conditions and the following disclaimer. | 
 | 26 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 | 27 |  *    notice, this list of conditions and the following disclaimer in the | 
 | 28 |  *    documentation and/or other materials provided with the distribution. | 
 | 29 |  * | 
 | 30 |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 
 | 31 |  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
 | 32 |  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
 | 33 |  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
 | 34 |  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
 | 35 |  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
 | 36 |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
 | 37 |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
 | 38 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
 | 39 |  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 40 |  */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 41 |  | 
 | 42 | #include "includes.h" | 
| Ben Lindstrom | 2415757 | 2002-06-12 16:09:39 +0000 | [diff] [blame^] | 43 | RCSID("$OpenBSD: ssh.c,v 1.178 2002/06/11 23:03:54 markus Exp $"); | 
| Damien Miller | eba71ba | 2000-04-29 23:57:08 +1000 | [diff] [blame] | 44 |  | 
 | 45 | #include <openssl/evp.h> | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 46 | #include <openssl/err.h> | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 47 |  | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 48 | #include "ssh.h" | 
| Ben Lindstrom | 226cfa0 | 2001-01-22 05:34:40 +0000 | [diff] [blame] | 49 | #include "ssh1.h" | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 50 | #include "ssh2.h" | 
 | 51 | #include "compat.h" | 
| Ben Lindstrom | 226cfa0 | 2001-01-22 05:34:40 +0000 | [diff] [blame] | 52 | #include "cipher.h" | 
 | 53 | #include "xmalloc.h" | 
 | 54 | #include "packet.h" | 
 | 55 | #include "buffer.h" | 
| Ben Lindstrom | c763767 | 2001-06-09 00:36:26 +0000 | [diff] [blame] | 56 | #include "channels.h" | 
| Damien Miller | eba71ba | 2000-04-29 23:57:08 +1000 | [diff] [blame] | 57 | #include "key.h" | 
| Damien Miller | 994cf14 | 2000-07-21 10:19:44 +1000 | [diff] [blame] | 58 | #include "authfd.h" | 
| Damien Miller | eba71ba | 2000-04-29 23:57:08 +1000 | [diff] [blame] | 59 | #include "authfile.h" | 
| Ben Lindstrom | 226cfa0 | 2001-01-22 05:34:40 +0000 | [diff] [blame] | 60 | #include "pathnames.h" | 
| Ben Lindstrom | bf555ba | 2001-01-18 02:04:35 +0000 | [diff] [blame] | 61 | #include "clientloop.h" | 
| Ben Lindstrom | 226cfa0 | 2001-01-22 05:34:40 +0000 | [diff] [blame] | 62 | #include "log.h" | 
 | 63 | #include "readconf.h" | 
 | 64 | #include "sshconnect.h" | 
 | 65 | #include "tildexpand.h" | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 66 | #include "dispatch.h" | 
| Ben Lindstrom | 226cfa0 | 2001-01-22 05:34:40 +0000 | [diff] [blame] | 67 | #include "misc.h" | 
| Ben Lindstrom | 06b33aa | 2001-02-15 03:01:59 +0000 | [diff] [blame] | 68 | #include "kex.h" | 
 | 69 | #include "mac.h" | 
| Ben Lindstrom | ae8e2d3 | 2001-04-14 23:13:02 +0000 | [diff] [blame] | 70 | #include "sshtty.h" | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 71 |  | 
| Ben Lindstrom | c5b6800 | 2001-07-04 04:52:03 +0000 | [diff] [blame] | 72 | #ifdef SMARTCARD | 
| Ben Lindstrom | c5b6800 | 2001-07-04 04:52:03 +0000 | [diff] [blame] | 73 | #include "scard.h" | 
| Ben Lindstrom | bcc1808 | 2001-08-06 21:59:25 +0000 | [diff] [blame] | 74 | #endif | 
| Ben Lindstrom | c5b6800 | 2001-07-04 04:52:03 +0000 | [diff] [blame] | 75 |  | 
| Damien Miller | 3f90587 | 1999-11-15 17:10:57 +1100 | [diff] [blame] | 76 | #ifdef HAVE___PROGNAME | 
 | 77 | extern char *__progname; | 
| Ben Lindstrom | 49a79c0 | 2000-11-17 03:47:20 +0000 | [diff] [blame] | 78 | #else | 
 | 79 | char *__progname; | 
 | 80 | #endif | 
| Damien Miller | 3f90587 | 1999-11-15 17:10:57 +1100 | [diff] [blame] | 81 |  | 
| Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 82 | /* Flag indicating whether IPv4 or IPv6.  This can be set on the command line. | 
 | 83 |    Default value is AF_UNSPEC means both IPv4 and IPv6. */ | 
| Damien Miller | 7d80e34 | 2000-01-19 14:36:49 +1100 | [diff] [blame] | 84 | #ifdef IPV4_DEFAULT | 
 | 85 | int IPv4or6 = AF_INET; | 
 | 86 | #else | 
| Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 87 | int IPv4or6 = AF_UNSPEC; | 
| Damien Miller | 7d80e34 | 2000-01-19 14:36:49 +1100 | [diff] [blame] | 88 | #endif | 
| Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 89 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 90 | /* Flag indicating whether debug mode is on.  This can be set on the command line. */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 91 | int debug_flag = 0; | 
 | 92 |  | 
| Damien Miller | 7892879 | 2000-04-12 20:17:38 +1000 | [diff] [blame] | 93 | /* Flag indicating whether a tty should be allocated */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 94 | int tty_flag = 0; | 
| Ben Lindstrom | 4dccfa5 | 2000-12-28 16:40:05 +0000 | [diff] [blame] | 95 | int no_tty_flag = 0; | 
 | 96 | int force_tty_flag = 0; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 97 |  | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 98 | /* don't exec a shell */ | 
 | 99 | int no_shell_flag = 0; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 100 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 101 | /* | 
 | 102 |  * Flag indicating that nothing should be read from stdin.  This can be set | 
 | 103 |  * on the command line. | 
 | 104 |  */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 105 | int stdin_null_flag = 0; | 
 | 106 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 107 | /* | 
 | 108 |  * Flag indicating that ssh should fork after authentication.  This is useful | 
| Ben Lindstrom | f666fec | 2002-06-06 19:51:58 +0000 | [diff] [blame] | 109 |  * so that the passphrase can be entered manually, and then ssh goes to the | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 110 |  * background. | 
 | 111 |  */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 112 | int fork_after_authentication_flag = 0; | 
 | 113 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 114 | /* | 
 | 115 |  * General data structure for command line options and options configurable | 
 | 116 |  * in configuration files.  See readconf.h. | 
 | 117 |  */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 118 | Options options; | 
 | 119 |  | 
| Ben Lindstrom | 14f31ab | 2001-09-12 17:48:04 +0000 | [diff] [blame] | 120 | /* optional user configfile */ | 
 | 121 | char *config = NULL; | 
 | 122 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 123 | /* | 
 | 124 |  * Name of the host we are connecting to.  This is the name given on the | 
 | 125 |  * command line, or the HostName specified for the user-supplied name in a | 
 | 126 |  * configuration file. | 
 | 127 |  */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 128 | char *host; | 
 | 129 |  | 
 | 130 | /* socket address the host resolves to */ | 
| Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 131 | struct sockaddr_storage hostaddr; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 132 |  | 
| Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 133 | /* Private host keys. */ | 
| Ben Lindstrom | 1bad256 | 2002-06-06 19:57:33 +0000 | [diff] [blame] | 134 | Sensitive sensitive_data; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 135 |  | 
 | 136 | /* Original real UID. */ | 
 | 137 | uid_t original_real_uid; | 
| Ben Lindstrom | f9c4884 | 2002-06-11 16:37:51 +0000 | [diff] [blame] | 138 | uid_t original_effective_uid; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 139 |  | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 140 | /* command to be executed */ | 
 | 141 | Buffer command; | 
 | 142 |  | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 143 | /* Should we execute a command or invoke a subsystem? */ | 
 | 144 | int subsystem_flag = 0; | 
 | 145 |  | 
| Damien Miller | 2797f7f | 2002-04-23 21:09:44 +1000 | [diff] [blame] | 146 | /* # of replies received for global requests */ | 
 | 147 | static int client_global_request_id = 0; | 
 | 148 |  | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 149 | /* Prints a help message to the user.  This function never returns. */ | 
 | 150 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 151 | static void | 
| Ben Lindstrom | 31ca54a | 2001-02-09 02:11:24 +0000 | [diff] [blame] | 152 | usage(void) | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 153 | { | 
| Kevin Steves | ec84dc1 | 2000-12-13 17:45:15 +0000 | [diff] [blame] | 154 | 	fprintf(stderr, "Usage: %s [options] host [command]\n", __progname); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 155 | 	fprintf(stderr, "Options:\n"); | 
 | 156 | 	fprintf(stderr, "  -l user     Log in using this user name.\n"); | 
| Ben Lindstrom | 31ca54a | 2001-02-09 02:11:24 +0000 | [diff] [blame] | 157 | 	fprintf(stderr, "  -n          Redirect input from " _PATH_DEVNULL ".\n"); | 
| Ben Lindstrom | 14f31ab | 2001-09-12 17:48:04 +0000 | [diff] [blame] | 158 | 	fprintf(stderr, "  -F config   Config file (default: ~/%s).\n", | 
 | 159 | 	     _PATH_SSH_USER_CONFFILE); | 
| Damien Miller | b1715dc | 2000-05-30 13:44:51 +1000 | [diff] [blame] | 160 | 	fprintf(stderr, "  -A          Enable authentication agent forwarding.\n"); | 
| Ben Lindstrom | 3b89c5e | 2001-06-05 20:44:16 +0000 | [diff] [blame] | 161 | 	fprintf(stderr, "  -a          Disable authentication agent forwarding (default).\n"); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 162 | #ifdef AFS | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 163 | 	fprintf(stderr, "  -k          Disable Kerberos ticket and AFS token forwarding.\n"); | 
 | 164 | #endif				/* AFS */ | 
| Kevin Steves | ef4eea9 | 2001-02-05 12:42:17 +0000 | [diff] [blame] | 165 | 	fprintf(stderr, "  -X          Enable X11 connection forwarding.\n"); | 
| Ben Lindstrom | 3b89c5e | 2001-06-05 20:44:16 +0000 | [diff] [blame] | 166 | 	fprintf(stderr, "  -x          Disable X11 connection forwarding (default).\n"); | 
| Ben Lindstrom | 0ab2a01 | 2001-03-05 06:45:21 +0000 | [diff] [blame] | 167 | 	fprintf(stderr, "  -i file     Identity for public key authentication " | 
 | 168 | 	    "(default: ~/.ssh/identity)\n"); | 
| Ben Lindstrom | 61eb956 | 2001-08-06 21:53:42 +0000 | [diff] [blame] | 169 | #ifdef SMARTCARD | 
 | 170 | 	fprintf(stderr, "  -I reader   Set smartcard reader.\n"); | 
| Ben Lindstrom | bcc1808 | 2001-08-06 21:59:25 +0000 | [diff] [blame] | 171 | #endif | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 172 | 	fprintf(stderr, "  -t          Tty; allocate a tty even if command is given.\n"); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 173 | 	fprintf(stderr, "  -T          Do not allocate a tty.\n"); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 174 | 	fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n"); | 
| Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 175 | 	fprintf(stderr, "              Multiple -v increases verbosity.\n"); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 176 | 	fprintf(stderr, "  -V          Display version number only.\n"); | 
 | 177 | 	fprintf(stderr, "  -P          Don't allocate a privileged port.\n"); | 
 | 178 | 	fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n"); | 
 | 179 | 	fprintf(stderr, "  -f          Fork into background after authentication.\n"); | 
 | 180 | 	fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n"); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 181 |  | 
| Ben Lindstrom | 3b89c5e | 2001-06-05 20:44:16 +0000 | [diff] [blame] | 182 | 	fprintf(stderr, "  -c cipher   Select encryption algorithm\n"); | 
| Ben Lindstrom | 3d73a34 | 2001-03-05 07:39:01 +0000 | [diff] [blame] | 183 | 	fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\n"); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 184 | 	fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n"); | 
 | 185 | 	fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n"); | 
 | 186 | 	fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n"); | 
| Kevin Steves | ec84dc1 | 2000-12-13 17:45:15 +0000 | [diff] [blame] | 187 | 	fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 188 | 	fprintf(stderr, "              forward them to the other side by connecting to host:port.\n"); | 
| Ben Lindstrom | 19ceb17 | 2001-09-12 17:54:24 +0000 | [diff] [blame] | 189 | 	fprintf(stderr, "  -D port     Enable dynamic application-level port forwarding.\n"); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 190 | 	fprintf(stderr, "  -C          Enable compression.\n"); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 191 | 	fprintf(stderr, "  -N          Do not execute a shell or command.\n"); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 192 | 	fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n"); | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 193 | 	fprintf(stderr, "  -1          Force protocol version 1.\n"); | 
 | 194 | 	fprintf(stderr, "  -2          Force protocol version 2.\n"); | 
| Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 195 | 	fprintf(stderr, "  -4          Use IPv4 only.\n"); | 
 | 196 | 	fprintf(stderr, "  -6          Use IPv6 only.\n"); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 197 | 	fprintf(stderr, "  -o 'option' Process the option as if it was read from a configuration file.\n"); | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 198 | 	fprintf(stderr, "  -s          Invoke command (mandatory) as SSH2 subsystem.\n"); | 
| Ben Lindstrom | 3b89c5e | 2001-06-05 20:44:16 +0000 | [diff] [blame] | 199 | 	fprintf(stderr, "  -b addr     Local IP address.\n"); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 200 | 	exit(1); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 201 | } | 
 | 202 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 203 | static int ssh_session(void); | 
 | 204 | static int ssh_session2(void); | 
 | 205 | static void load_public_identity_files(void); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 206 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 207 | /* | 
 | 208 |  * Main program for the ssh client. | 
 | 209 |  */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 210 | int | 
 | 211 | main(int ac, char **av) | 
 | 212 | { | 
| Ben Lindstrom | 2415757 | 2002-06-12 16:09:39 +0000 | [diff] [blame^] | 213 | 	int i, opt, exit_status; | 
| Damien Miller | aae6c61 | 1999-12-06 11:47:28 +1100 | [diff] [blame] | 214 | 	u_short fwd_port, fwd_host_port; | 
| Ben Lindstrom | 1a17471 | 2001-09-12 17:56:15 +0000 | [diff] [blame] | 215 | 	char sfwd_port[6], sfwd_host_port[6]; | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 216 | 	char *p, *cp, buf[256]; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 217 | 	struct stat st; | 
| Ben Lindstrom | 086cf21 | 2001-03-05 05:56:40 +0000 | [diff] [blame] | 218 | 	struct passwd *pw; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 219 | 	int dummy; | 
| Ben Lindstrom | 5ccf63a | 2001-09-24 20:00:10 +0000 | [diff] [blame] | 220 | 	extern int optind, optreset; | 
| Damien Miller | 4f8e669 | 2001-07-14 13:22:53 +1000 | [diff] [blame] | 221 | 	extern char *optarg; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 222 |  | 
| Ben Lindstrom | 49a79c0 | 2000-11-17 03:47:20 +0000 | [diff] [blame] | 223 | 	__progname = get_progname(av[0]); | 
| Damien Miller | f9b625c | 2000-07-09 22:42:32 +1000 | [diff] [blame] | 224 | 	init_rng(); | 
 | 225 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 226 | 	/* | 
 | 227 | 	 * Save the original real uid.  It will be needed later (uid-swapping | 
 | 228 | 	 * may clobber the real uid). | 
 | 229 | 	 */ | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 230 | 	original_real_uid = getuid(); | 
 | 231 | 	original_effective_uid = geteuid(); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 232 |  | 
| Damien Miller | 05dd795 | 2000-10-01 00:42:48 +1100 | [diff] [blame] | 233 | #ifdef HAVE_SETRLIMIT | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 234 | 	/* If we are installed setuid root be careful to not drop core. */ | 
 | 235 | 	if (original_real_uid != original_effective_uid) { | 
 | 236 | 		struct rlimit rlim; | 
 | 237 | 		rlim.rlim_cur = rlim.rlim_max = 0; | 
 | 238 | 		if (setrlimit(RLIMIT_CORE, &rlim) < 0) | 
 | 239 | 			fatal("setrlimit failed: %.100s", strerror(errno)); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 240 | 	} | 
| Damien Miller | bac2d8a | 2000-09-05 16:13:06 +1100 | [diff] [blame] | 241 | #endif | 
| Ben Lindstrom | 3fcf1a2 | 2001-04-08 18:26:59 +0000 | [diff] [blame] | 242 | 	/* Get user data. */ | 
 | 243 | 	pw = getpwuid(original_real_uid); | 
 | 244 | 	if (!pw) { | 
 | 245 | 		log("You don't exist, go away!"); | 
 | 246 | 		exit(1); | 
 | 247 | 	} | 
 | 248 | 	/* Take a copy of the returned structure. */ | 
 | 249 | 	pw = pwcopy(pw); | 
 | 250 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 251 | 	/* | 
 | 252 | 	 * Use uid-swapping to give up root privileges for the duration of | 
 | 253 | 	 * option processing.  We will re-instantiate the rights when we are | 
 | 254 | 	 * ready to create the privileged port, and will permanently drop | 
 | 255 | 	 * them when the port has been created (actually, when the connection | 
 | 256 | 	 * has been made, as we may need to create the port several times). | 
 | 257 | 	 */ | 
| Ben Lindstrom | f9c4884 | 2002-06-11 16:37:51 +0000 | [diff] [blame] | 258 | 	PRIV_END; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 259 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 260 | 	/* | 
 | 261 | 	 * Set our umask to something reasonable, as some files are created | 
 | 262 | 	 * with the default umask.  This will make them world-readable but | 
 | 263 | 	 * writable only by the owner, which is ok for all files for which we | 
 | 264 | 	 * don't set the modes explicitly. | 
 | 265 | 	 */ | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 266 | 	umask(022); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 267 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 268 | 	/* Initialize option structure to indicate that no values have been set. */ | 
 | 269 | 	initialize_options(&options); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 270 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 271 | 	/* Parse command-line arguments. */ | 
 | 272 | 	host = NULL; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 273 |  | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 274 | again: | 
 | 275 | 	while ((opt = getopt(ac, av, | 
| Ben Lindstrom | 14f31ab | 2001-09-12 17:48:04 +0000 | [diff] [blame] | 276 | 	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 277 | 		switch (opt) { | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 278 | 		case '1': | 
 | 279 | 			options.protocol = SSH_PROTO_1; | 
 | 280 | 			break; | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 281 | 		case '2': | 
 | 282 | 			options.protocol = SSH_PROTO_2; | 
 | 283 | 			break; | 
| Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 284 | 		case '4': | 
 | 285 | 			IPv4or6 = AF_INET; | 
 | 286 | 			break; | 
| Damien Miller | 34132e5 | 2000-01-14 15:45:46 +1100 | [diff] [blame] | 287 | 		case '6': | 
 | 288 | 			IPv4or6 = AF_INET6; | 
 | 289 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 290 | 		case 'n': | 
 | 291 | 			stdin_null_flag = 1; | 
 | 292 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 293 | 		case 'f': | 
 | 294 | 			fork_after_authentication_flag = 1; | 
 | 295 | 			stdin_null_flag = 1; | 
 | 296 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 297 | 		case 'x': | 
 | 298 | 			options.forward_x11 = 0; | 
 | 299 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 300 | 		case 'X': | 
 | 301 | 			options.forward_x11 = 1; | 
 | 302 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 303 | 		case 'g': | 
 | 304 | 			options.gateway_ports = 1; | 
 | 305 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 306 | 		case 'P': | 
 | 307 | 			options.use_privileged_port = 0; | 
 | 308 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 309 | 		case 'a': | 
 | 310 | 			options.forward_agent = 0; | 
 | 311 | 			break; | 
| Damien Miller | b1715dc | 2000-05-30 13:44:51 +1000 | [diff] [blame] | 312 | 		case 'A': | 
 | 313 | 			options.forward_agent = 1; | 
 | 314 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 315 | #ifdef AFS | 
 | 316 | 		case 'k': | 
 | 317 | 			options.kerberos_tgt_passing = 0; | 
 | 318 | 			options.afs_token_passing = 0; | 
 | 319 | 			break; | 
 | 320 | #endif | 
 | 321 | 		case 'i': | 
 | 322 | 			if (stat(optarg, &st) < 0) { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 323 | 				fprintf(stderr, "Warning: Identity file %s " | 
 | 324 | 				    "does not exist.\n", optarg); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 325 | 				break; | 
 | 326 | 			} | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 327 | 			if (options.num_identity_files >= | 
 | 328 | 			    SSH_MAX_IDENTITY_FILES) | 
 | 329 | 				fatal("Too many identity files specified " | 
 | 330 | 				    "(max %d)", SSH_MAX_IDENTITY_FILES); | 
 | 331 | 			options.identity_files[options.num_identity_files++] = | 
 | 332 | 			    xstrdup(optarg); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 333 | 			break; | 
| Ben Lindstrom | c5b6800 | 2001-07-04 04:52:03 +0000 | [diff] [blame] | 334 | 		case 'I': | 
 | 335 | #ifdef SMARTCARD | 
| Ben Lindstrom | f7db3bb | 2001-08-06 21:35:51 +0000 | [diff] [blame] | 336 | 			options.smartcard_device = xstrdup(optarg); | 
| Ben Lindstrom | bcc1808 | 2001-08-06 21:59:25 +0000 | [diff] [blame] | 337 | #else | 
| Ben Lindstrom | c5b6800 | 2001-07-04 04:52:03 +0000 | [diff] [blame] | 338 | 			fprintf(stderr, "no support for smartcards.\n"); | 
| Ben Lindstrom | bcc1808 | 2001-08-06 21:59:25 +0000 | [diff] [blame] | 339 | #endif | 
| Ben Lindstrom | c5b6800 | 2001-07-04 04:52:03 +0000 | [diff] [blame] | 340 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 341 | 		case 't': | 
| Ben Lindstrom | 4dccfa5 | 2000-12-28 16:40:05 +0000 | [diff] [blame] | 342 | 			if (tty_flag) | 
 | 343 | 				force_tty_flag = 1; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 344 | 			tty_flag = 1; | 
 | 345 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 346 | 		case 'v': | 
| Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 347 | 			if (0 == debug_flag) { | 
 | 348 | 				debug_flag = 1; | 
 | 349 | 				options.log_level = SYSLOG_LEVEL_DEBUG1; | 
 | 350 | 			} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { | 
 | 351 | 				options.log_level++; | 
 | 352 | 				break; | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 353 | 			} else | 
| Ben Lindstrom | 6df8ef4 | 2001-03-05 07:47:23 +0000 | [diff] [blame] | 354 | 				fatal("Too high debugging level."); | 
| Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 355 | 			/* fallthrough */ | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 356 | 		case 'V': | 
| Damien Miller | 225736c | 2001-02-19 21:51:08 +1100 | [diff] [blame] | 357 | 			fprintf(stderr, | 
 | 358 | 			    "%s, SSH protocols %d.%d/%d.%d, OpenSSL 0x%8.8lx\n", | 
| Damien Miller | 7892879 | 2000-04-12 20:17:38 +1000 | [diff] [blame] | 359 | 			    SSH_VERSION, | 
 | 360 | 			    PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1, | 
| Damien Miller | 225736c | 2001-02-19 21:51:08 +1100 | [diff] [blame] | 361 | 			    PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, | 
 | 362 | 			    SSLeay()); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 363 | 			if (opt == 'V') | 
 | 364 | 				exit(0); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 365 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 366 | 		case 'q': | 
 | 367 | 			options.log_level = SYSLOG_LEVEL_QUIET; | 
 | 368 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 369 | 		case 'e': | 
 | 370 | 			if (optarg[0] == '^' && optarg[2] == 0 && | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 371 | 			    (u_char) optarg[1] >= 64 && | 
 | 372 | 			    (u_char) optarg[1] < 128) | 
| Ben Lindstrom | 46c1622 | 2000-12-22 01:43:59 +0000 | [diff] [blame] | 373 | 				options.escape_char = (u_char) optarg[1] & 31; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 374 | 			else if (strlen(optarg) == 1) | 
| Ben Lindstrom | 46c1622 | 2000-12-22 01:43:59 +0000 | [diff] [blame] | 375 | 				options.escape_char = (u_char) optarg[0]; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 376 | 			else if (strcmp(optarg, "none") == 0) | 
| Ben Lindstrom | 2b1f71b | 2001-06-05 20:32:21 +0000 | [diff] [blame] | 377 | 				options.escape_char = SSH_ESCAPECHAR_NONE; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 378 | 			else { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 379 | 				fprintf(stderr, "Bad escape character '%s'.\n", | 
 | 380 | 				    optarg); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 381 | 				exit(1); | 
 | 382 | 			} | 
 | 383 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 384 | 		case 'c': | 
| Damien Miller | eba71ba | 2000-04-29 23:57:08 +1000 | [diff] [blame] | 385 | 			if (ciphers_valid(optarg)) { | 
 | 386 | 				/* SSH2 only */ | 
 | 387 | 				options.ciphers = xstrdup(optarg); | 
| Damien Miller | 30c3d42 | 2000-05-09 11:02:59 +1000 | [diff] [blame] | 388 | 				options.cipher = SSH_CIPHER_ILLEGAL; | 
| Damien Miller | eba71ba | 2000-04-29 23:57:08 +1000 | [diff] [blame] | 389 | 			} else { | 
 | 390 | 				/* SSH1 only */ | 
| Damien Miller | e39cacc | 2000-11-29 12:18:44 +1100 | [diff] [blame] | 391 | 				options.cipher = cipher_number(optarg); | 
 | 392 | 				if (options.cipher == -1) { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 393 | 					fprintf(stderr, | 
 | 394 | 					    "Unknown cipher type '%s'\n", | 
 | 395 | 					    optarg); | 
| Damien Miller | eba71ba | 2000-04-29 23:57:08 +1000 | [diff] [blame] | 396 | 					exit(1); | 
 | 397 | 				} | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 398 | 				if (options.cipher == SSH_CIPHER_3DES) | 
| Damien Miller | e39cacc | 2000-11-29 12:18:44 +1100 | [diff] [blame] | 399 | 					options.ciphers = "3des-cbc"; | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 400 | 				else if (options.cipher == SSH_CIPHER_BLOWFISH) | 
| Damien Miller | e39cacc | 2000-11-29 12:18:44 +1100 | [diff] [blame] | 401 | 					options.ciphers = "blowfish-cbc"; | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 402 | 				else | 
| Damien Miller | e39cacc | 2000-11-29 12:18:44 +1100 | [diff] [blame] | 403 | 					options.ciphers = (char *)-1; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 404 | 			} | 
 | 405 | 			break; | 
| Ben Lindstrom | 06b33aa | 2001-02-15 03:01:59 +0000 | [diff] [blame] | 406 | 		case 'm': | 
 | 407 | 			if (mac_valid(optarg)) | 
 | 408 | 				options.macs = xstrdup(optarg); | 
 | 409 | 			else { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 410 | 				fprintf(stderr, "Unknown mac type '%s'\n", | 
 | 411 | 				    optarg); | 
| Ben Lindstrom | 06b33aa | 2001-02-15 03:01:59 +0000 | [diff] [blame] | 412 | 				exit(1); | 
 | 413 | 			} | 
 | 414 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 415 | 		case 'p': | 
| Ben Lindstrom | 19066a1 | 2001-04-12 23:39:26 +0000 | [diff] [blame] | 416 | 			options.port = a2port(optarg); | 
 | 417 | 			if (options.port == 0) { | 
| Ben Lindstrom | 146edb9 | 2001-04-11 23:06:28 +0000 | [diff] [blame] | 418 | 				fprintf(stderr, "Bad port '%s'\n", optarg); | 
 | 419 | 				exit(1); | 
 | 420 | 			} | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 421 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 422 | 		case 'l': | 
 | 423 | 			options.user = optarg; | 
 | 424 | 			break; | 
| Ben Lindstrom | 1a17471 | 2001-09-12 17:56:15 +0000 | [diff] [blame] | 425 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 426 | 		case 'L': | 
| Ben Lindstrom | 1a17471 | 2001-09-12 17:56:15 +0000 | [diff] [blame] | 427 | 		case 'R': | 
 | 428 | 			if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]", | 
 | 429 | 			    sfwd_port, buf, sfwd_host_port) != 3 && | 
 | 430 | 			    sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]", | 
 | 431 | 			    sfwd_port, buf, sfwd_host_port) != 3) { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 432 | 				fprintf(stderr, | 
| Ben Lindstrom | 1a17471 | 2001-09-12 17:56:15 +0000 | [diff] [blame] | 433 | 				    "Bad forwarding specification '%s'\n", | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 434 | 				    optarg); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 435 | 				usage(); | 
 | 436 | 				/* NOTREACHED */ | 
 | 437 | 			} | 
| Ben Lindstrom | 1a17471 | 2001-09-12 17:56:15 +0000 | [diff] [blame] | 438 | 			if ((fwd_port = a2port(sfwd_port)) == 0 || | 
| Ben Lindstrom | 6328ab3 | 2002-03-22 02:54:23 +0000 | [diff] [blame] | 439 | 			    (fwd_host_port = a2port(sfwd_host_port)) == 0) { | 
| Ben Lindstrom | 1a17471 | 2001-09-12 17:56:15 +0000 | [diff] [blame] | 440 | 				fprintf(stderr, | 
 | 441 | 				    "Bad forwarding port(s) '%s'\n", optarg); | 
 | 442 | 				exit(1); | 
 | 443 | 			} | 
 | 444 | 			if (opt == 'L') | 
 | 445 | 				add_local_forward(&options, fwd_port, buf, | 
 | 446 | 				    fwd_host_port); | 
 | 447 | 			else if (opt == 'R') | 
 | 448 | 				add_remote_forward(&options, fwd_port, buf, | 
| Damien Miller | 9f0f5c6 | 2001-12-21 14:45:46 +1100 | [diff] [blame] | 449 | 				    fwd_host_port); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 450 | 			break; | 
| Ben Lindstrom | 3bb4f9d | 2001-04-08 18:30:26 +0000 | [diff] [blame] | 451 |  | 
 | 452 | 		case 'D': | 
| Ben Lindstrom | 19066a1 | 2001-04-12 23:39:26 +0000 | [diff] [blame] | 453 | 			fwd_port = a2port(optarg); | 
 | 454 | 			if (fwd_port == 0) { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 455 | 				fprintf(stderr, "Bad dynamic port '%s'\n", | 
 | 456 | 				    optarg); | 
| Ben Lindstrom | 146edb9 | 2001-04-11 23:06:28 +0000 | [diff] [blame] | 457 | 				exit(1); | 
 | 458 | 			} | 
| Ben Lindstrom | 3bb4f9d | 2001-04-08 18:30:26 +0000 | [diff] [blame] | 459 | 			add_local_forward(&options, fwd_port, "socks4", 0); | 
 | 460 | 			break; | 
 | 461 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 462 | 		case 'C': | 
 | 463 | 			options.compression = 1; | 
 | 464 | 			break; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 465 | 		case 'N': | 
 | 466 | 			no_shell_flag = 1; | 
 | 467 | 			no_tty_flag = 1; | 
 | 468 | 			break; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 469 | 		case 'T': | 
 | 470 | 			no_tty_flag = 1; | 
 | 471 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 472 | 		case 'o': | 
 | 473 | 			dummy = 1; | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 474 | 			if (process_config_line(&options, host ? host : "", | 
 | 475 | 			    optarg, "command-line", 0, &dummy) != 0) | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 476 | 				exit(1); | 
 | 477 | 			break; | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 478 | 		case 's': | 
 | 479 | 			subsystem_flag = 1; | 
 | 480 | 			break; | 
| Ben Lindstrom | e0f8804 | 2001-04-30 13:06:24 +0000 | [diff] [blame] | 481 | 		case 'b': | 
 | 482 | 			options.bind_address = optarg; | 
 | 483 | 			break; | 
| Ben Lindstrom | 14f31ab | 2001-09-12 17:48:04 +0000 | [diff] [blame] | 484 | 		case 'F': | 
 | 485 | 			config = optarg; | 
 | 486 | 			break; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 487 | 		default: | 
 | 488 | 			usage(); | 
 | 489 | 		} | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 490 | 	} | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 491 |  | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 492 | 	ac -= optind; | 
 | 493 | 	av += optind; | 
 | 494 |  | 
 | 495 | 	if (ac > 0 && !host && **av != '-') { | 
 | 496 | 		if (strchr(*av, '@')) { | 
 | 497 | 			p = xstrdup(*av); | 
 | 498 | 			cp = strchr(p, '@'); | 
 | 499 | 			if (cp == NULL || cp == p) | 
 | 500 | 				usage(); | 
 | 501 | 			options.user = p; | 
 | 502 | 			*cp = '\0'; | 
 | 503 | 			host = ++cp; | 
 | 504 | 		} else | 
 | 505 | 			host = *av; | 
 | 506 | 		ac--, av++; | 
 | 507 | 		if (ac > 0) { | 
 | 508 | 			optind = 0; | 
 | 509 | 			optreset = 1; | 
 | 510 | 			goto again; | 
 | 511 | 		} | 
 | 512 | 	} | 
 | 513 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 514 | 	/* Check that we got a host name. */ | 
 | 515 | 	if (!host) | 
 | 516 | 		usage(); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 517 |  | 
| Damien Miller | cb5e44a | 2000-09-29 12:12:36 +1100 | [diff] [blame] | 518 | 	SSLeay_add_all_algorithms(); | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 519 | 	ERR_load_crypto_strings(); | 
| Ben Lindstrom | 908afed | 2001-10-03 17:34:59 +0000 | [diff] [blame] | 520 | 	channel_set_af(IPv4or6); | 
| Damien Miller | cb5e44a | 2000-09-29 12:12:36 +1100 | [diff] [blame] | 521 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 522 | 	/* Initialize the command to execute on remote host. */ | 
 | 523 | 	buffer_init(&command); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 524 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 525 | 	/* | 
 | 526 | 	 * Save the command to execute on the remote host in a buffer. There | 
 | 527 | 	 * is no limit on the length of the command, except by the maximum | 
 | 528 | 	 * packet size.  Also sets the tty flag if there is no command. | 
 | 529 | 	 */ | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 530 | 	if (!ac) { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 531 | 		/* No command specified - execute shell on a tty. */ | 
 | 532 | 		tty_flag = 1; | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 533 | 		if (subsystem_flag) { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 534 | 			fprintf(stderr, | 
 | 535 | 			    "You must specify a subsystem to invoke.\n"); | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 536 | 			usage(); | 
 | 537 | 		} | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 538 | 	} else { | 
| Damien Miller | f461445 | 2001-07-14 12:18:10 +1000 | [diff] [blame] | 539 | 		/* A command has been specified.  Store it into the buffer. */ | 
 | 540 | 		for (i = 0; i < ac; i++) { | 
 | 541 | 			if (i) | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 542 | 				buffer_append(&command, " ", 1); | 
 | 543 | 			buffer_append(&command, av[i], strlen(av[i])); | 
 | 544 | 		} | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 545 | 	} | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 546 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 547 | 	/* Cannot fork to background if no command. */ | 
| Damien Miller | caf6dd6 | 2000-08-29 11:33:50 +1100 | [diff] [blame] | 548 | 	if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag) | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 549 | 		fatal("Cannot fork into background without a command to execute."); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 550 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 551 | 	/* Allocate a tty by default if no command specified. */ | 
 | 552 | 	if (buffer_len(&command) == 0) | 
 | 553 | 		tty_flag = 1; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 554 |  | 
| Ben Lindstrom | c72745a | 2000-12-02 19:03:54 +0000 | [diff] [blame] | 555 | 	/* Force no tty*/ | 
 | 556 | 	if (no_tty_flag) | 
 | 557 | 		tty_flag = 0; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 558 | 	/* Do not allocate a tty if stdin is not a tty. */ | 
| Ben Lindstrom | 4dccfa5 | 2000-12-28 16:40:05 +0000 | [diff] [blame] | 559 | 	if (!isatty(fileno(stdin)) && !force_tty_flag) { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 560 | 		if (tty_flag) | 
| Ben Lindstrom | 6df8ef4 | 2001-03-05 07:47:23 +0000 | [diff] [blame] | 561 | 			log("Pseudo-terminal will not be allocated because stdin is not a terminal."); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 562 | 		tty_flag = 0; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 563 | 	} | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 564 |  | 
| Ben Lindstrom | 8a432f5 | 2001-03-05 07:24:46 +0000 | [diff] [blame] | 565 | 	/* | 
 | 566 | 	 * Initialize "log" output.  Since we are the client all output | 
 | 567 | 	 * actually goes to stderr. | 
 | 568 | 	 */ | 
| Ben Lindstrom | 2b64652 | 2001-04-12 16:16:57 +0000 | [diff] [blame] | 569 | 	log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, | 
 | 570 | 	    SYSLOG_FACILITY_USER, 1); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 571 |  | 
| Ben Lindstrom | 14f31ab | 2001-09-12 17:48:04 +0000 | [diff] [blame] | 572 | 	/* | 
 | 573 | 	 * Read per-user configuration file.  Ignore the system wide config | 
 | 574 | 	 * file if the user specifies a config file on the command line. | 
 | 575 | 	 */ | 
 | 576 | 	if (config != NULL) { | 
| Ben Lindstrom | edc0cf2 | 2001-09-12 18:32:20 +0000 | [diff] [blame] | 577 | 		if (!read_config_file(config, host, &options)) | 
 | 578 | 			fatal("Can't open user config file %.100s: " | 
 | 579 | 			    "%.100s", config, strerror(errno)); | 
| Ben Lindstrom | 14f31ab | 2001-09-12 17:48:04 +0000 | [diff] [blame] | 580 | 	} else  { | 
 | 581 | 		snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, | 
 | 582 | 		    _PATH_SSH_USER_CONFFILE); | 
| Ben Lindstrom | edc0cf2 | 2001-09-12 18:32:20 +0000 | [diff] [blame] | 583 | 		(void)read_config_file(buf, host, &options); | 
| Ben Lindstrom | 83f07d1 | 2001-10-03 17:22:29 +0000 | [diff] [blame] | 584 |  | 
 | 585 | 		/* Read systemwide configuration file after use config. */ | 
 | 586 | 		(void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); | 
| Ben Lindstrom | 14f31ab | 2001-09-12 17:48:04 +0000 | [diff] [blame] | 587 | 	} | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 588 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 589 | 	/* Fill configuration defaults. */ | 
 | 590 | 	fill_default_options(&options); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 591 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 592 | 	/* reinit */ | 
| Ben Lindstrom | 8a432f5 | 2001-03-05 07:24:46 +0000 | [diff] [blame] | 593 | 	log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 594 |  | 
| Damien Miller | 60bc517 | 2001-03-19 09:38:15 +1100 | [diff] [blame] | 595 | 	seed_rng(); | 
 | 596 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 597 | 	if (options.user == NULL) | 
 | 598 | 		options.user = xstrdup(pw->pw_name); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 599 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 600 | 	if (options.hostname != NULL) | 
 | 601 | 		host = options.hostname; | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 602 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 603 | 	/* Disable rhosts authentication if not running as root. */ | 
| Damien Miller | bac2d8a | 2000-09-05 16:13:06 +1100 | [diff] [blame] | 604 | #ifdef HAVE_CYGWIN | 
 | 605 | 	/* Ignore uid if running under Windows */ | 
 | 606 | 	if (!options.use_privileged_port) { | 
 | 607 | #else | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 608 | 	if (original_effective_uid != 0 || !options.use_privileged_port) { | 
| Damien Miller | bac2d8a | 2000-09-05 16:13:06 +1100 | [diff] [blame] | 609 | #endif | 
| Kevin Steves | fcec7f8 | 2000-12-15 19:55:48 +0000 | [diff] [blame] | 610 | 		debug("Rhosts Authentication disabled, " | 
 | 611 | 		    "originating port will not be trusted."); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 612 | 		options.rhosts_authentication = 0; | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 613 | 	} | 
| Kevin Steves | fcec7f8 | 2000-12-15 19:55:48 +0000 | [diff] [blame] | 614 | 	/* Open a connection to the remote host. */ | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 615 |  | 
| Ben Lindstrom | 2415757 | 2002-06-12 16:09:39 +0000 | [diff] [blame^] | 616 | 	if (ssh_connect(host, &hostaddr, options.port, IPv4or6, | 
| Kevin Steves | fcec7f8 | 2000-12-15 19:55:48 +0000 | [diff] [blame] | 617 | 	    options.connection_attempts, | 
| Ben Lindstrom | 1aa6427 | 2002-06-11 20:28:05 +0000 | [diff] [blame] | 618 | #ifdef HAVE_CYGWIN | 
 | 619 | 	    options.use_privileged_port, | 
 | 620 | #else | 
| Ben Lindstrom | f9c4884 | 2002-06-11 16:37:51 +0000 | [diff] [blame] | 621 | 	    original_effective_uid == 0 && options.use_privileged_port, | 
| Ben Lindstrom | 1aa6427 | 2002-06-11 20:28:05 +0000 | [diff] [blame] | 622 | #endif | 
| Ben Lindstrom | 2415757 | 2002-06-12 16:09:39 +0000 | [diff] [blame^] | 623 | 	    options.proxy_command) < 0) | 
 | 624 | 		exit(1); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 625 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 626 | 	/* | 
 | 627 | 	 * If we successfully made the connection, load the host private key | 
 | 628 | 	 * in case we will need it later for combined rsa-rhosts | 
 | 629 | 	 * authentication. This must be done before releasing extra | 
 | 630 | 	 * privileges, because the file is only readable by root. | 
| Ben Lindstrom | 9e5bb57 | 2002-06-06 19:58:27 +0000 | [diff] [blame] | 631 | 	 * If we cannot access the private keys, load the public keys | 
 | 632 | 	 * instead and try to execute the ssh-keysign helper instead. | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 633 | 	 */ | 
| Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 634 | 	sensitive_data.nkeys = 0; | 
 | 635 | 	sensitive_data.keys = NULL; | 
| Ben Lindstrom | 1bad256 | 2002-06-06 19:57:33 +0000 | [diff] [blame] | 636 | 	sensitive_data.external_keysign = 0; | 
| Ben Lindstrom | 2415757 | 2002-06-12 16:09:39 +0000 | [diff] [blame^] | 637 | 	if (options.rhosts_rsa_authentication || | 
 | 638 | 	    options.hostbased_authentication) { | 
| Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 639 | 		sensitive_data.nkeys = 3; | 
 | 640 | 		sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key)); | 
| Ben Lindstrom | f9c4884 | 2002-06-11 16:37:51 +0000 | [diff] [blame] | 641 |  | 
 | 642 | 		PRIV_START; | 
| Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 643 | 		sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, | 
| Ben Lindstrom | d0fca42 | 2001-03-26 13:44:06 +0000 | [diff] [blame] | 644 | 		    _PATH_HOST_KEY_FILE, "", NULL); | 
| Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 645 | 		sensitive_data.keys[1] = key_load_private_type(KEY_DSA, | 
 | 646 | 		    _PATH_HOST_DSA_KEY_FILE, "", NULL); | 
 | 647 | 		sensitive_data.keys[2] = key_load_private_type(KEY_RSA, | 
 | 648 | 		    _PATH_HOST_RSA_KEY_FILE, "", NULL); | 
| Ben Lindstrom | f9c4884 | 2002-06-11 16:37:51 +0000 | [diff] [blame] | 649 | 		PRIV_END; | 
| Ben Lindstrom | 1bad256 | 2002-06-06 19:57:33 +0000 | [diff] [blame] | 650 |  | 
 | 651 | 		if (sensitive_data.keys[0] == NULL && | 
 | 652 | 		    sensitive_data.keys[1] == NULL && | 
 | 653 | 		    sensitive_data.keys[2] == NULL) { | 
 | 654 | 			sensitive_data.keys[1] = key_load_public( | 
 | 655 | 			    _PATH_HOST_DSA_KEY_FILE, NULL); | 
 | 656 | 			sensitive_data.keys[2] = key_load_public( | 
 | 657 | 			    _PATH_HOST_RSA_KEY_FILE, NULL); | 
 | 658 | 			sensitive_data.external_keysign = 1; | 
 | 659 | 		} | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 660 | 	} | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 661 | 	/* | 
 | 662 | 	 * Get rid of any extra privileges that we may have.  We will no | 
 | 663 | 	 * longer need them.  Also, extra privileges could make it very hard | 
 | 664 | 	 * to read identity files and other non-world-readable files from the | 
 | 665 | 	 * user's home directory if it happens to be on a NFS volume where | 
 | 666 | 	 * root is mapped to nobody. | 
 | 667 | 	 */ | 
| Ben Lindstrom | f9c4884 | 2002-06-11 16:37:51 +0000 | [diff] [blame] | 668 | 	seteuid(original_real_uid); | 
 | 669 | 	setuid(original_real_uid); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 670 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 671 | 	/* | 
 | 672 | 	 * Now that we are back to our own permissions, create ~/.ssh | 
 | 673 | 	 * directory if it doesn\'t already exist. | 
 | 674 | 	 */ | 
| Ben Lindstrom | 930b14a | 2001-08-15 23:19:21 +0000 | [diff] [blame] | 675 | 	snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 676 | 	if (stat(buf, &st) < 0) | 
| Damien Miller | be484b5 | 2000-07-15 14:14:16 +1000 | [diff] [blame] | 677 | 		if (mkdir(buf, 0700) < 0) | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 678 | 			error("Could not create directory '%.200s'.", buf); | 
 | 679 |  | 
| Ben Lindstrom | 266dfdf | 2001-03-09 00:12:22 +0000 | [diff] [blame] | 680 | 	/* load options.identity_files */ | 
 | 681 | 	load_public_identity_files(); | 
 | 682 |  | 
 | 683 | 	/* Expand ~ in known host file names. */ | 
 | 684 | 	/* XXX mem-leaks: */ | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 685 | 	options.system_hostfile = | 
 | 686 | 	    tilde_expand_filename(options.system_hostfile, original_real_uid); | 
 | 687 | 	options.user_hostfile = | 
 | 688 | 	    tilde_expand_filename(options.user_hostfile, original_real_uid); | 
 | 689 | 	options.system_hostfile2 = | 
 | 690 | 	    tilde_expand_filename(options.system_hostfile2, original_real_uid); | 
 | 691 | 	options.user_hostfile2 = | 
 | 692 | 	    tilde_expand_filename(options.user_hostfile2, original_real_uid); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 693 |  | 
| Damien Miller | 07cd589 | 2001-11-12 10:52:03 +1100 | [diff] [blame] | 694 | 	signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ | 
 | 695 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 696 | 	/* Log into the remote system.  This never returns if the login fails. */ | 
| Ben Lindstrom | 1bad256 | 2002-06-06 19:57:33 +0000 | [diff] [blame] | 697 | 	ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 698 |  | 
| Ben Lindstrom | 5eabda3 | 2001-04-12 23:34:34 +0000 | [diff] [blame] | 699 | 	/* We no longer need the private host keys.  Clear them now. */ | 
 | 700 | 	if (sensitive_data.nkeys != 0) { | 
 | 701 | 		for (i = 0; i < sensitive_data.nkeys; i++) { | 
 | 702 | 			if (sensitive_data.keys[i] != NULL) { | 
 | 703 | 				/* Destroys contents safely */ | 
 | 704 | 				debug3("clear hostkey %d", i); | 
 | 705 | 				key_free(sensitive_data.keys[i]); | 
 | 706 | 				sensitive_data.keys[i] = NULL; | 
 | 707 | 			} | 
 | 708 | 		} | 
 | 709 | 		xfree(sensitive_data.keys); | 
 | 710 | 	} | 
| Ben Lindstrom | a6c8a8d | 2001-08-06 21:42:00 +0000 | [diff] [blame] | 711 | 	for (i = 0; i < options.num_identity_files; i++) { | 
 | 712 | 		if (options.identity_files[i]) { | 
 | 713 | 			xfree(options.identity_files[i]); | 
 | 714 | 			options.identity_files[i] = NULL; | 
 | 715 | 		} | 
 | 716 | 		if (options.identity_keys[i]) { | 
 | 717 | 			key_free(options.identity_keys[i]); | 
 | 718 | 			options.identity_keys[i] = NULL; | 
 | 719 | 		} | 
 | 720 | 	} | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 721 |  | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 722 | 	exit_status = compat20 ? ssh_session2() : ssh_session(); | 
 | 723 | 	packet_close(); | 
 | 724 | 	return exit_status; | 
 | 725 | } | 
 | 726 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 727 | static void | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 728 | x11_get_proto(char **_proto, char **_data) | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 729 | { | 
 | 730 | 	char line[512]; | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 731 | 	static char proto[512], data[512]; | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 732 | 	FILE *f; | 
 | 733 | 	int got_data = 0, i; | 
| Damien Miller | 35b13d6 | 2002-02-05 12:12:09 +1100 | [diff] [blame] | 734 | 	char *display; | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 735 |  | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 736 | 	*_proto = proto; | 
 | 737 | 	*_data = data; | 
 | 738 | 	proto[0] = data[0] = '\0'; | 
| Damien Miller | 35b13d6 | 2002-02-05 12:12:09 +1100 | [diff] [blame] | 739 | 	if (options.xauth_location && (display = getenv("DISPLAY"))) { | 
| Damien Miller | d3a1857 | 2000-06-07 19:55:44 +1000 | [diff] [blame] | 740 | 		/* Try to get Xauthority information for the display. */ | 
| Damien Miller | 35b13d6 | 2002-02-05 12:12:09 +1100 | [diff] [blame] | 741 | 		if (strncmp(display, "localhost:", 10) == 0) | 
 | 742 | 			/* | 
 | 743 | 			 * Handle FamilyLocal case where $DISPLAY does | 
 | 744 | 			 * not match an authorization entry.  For this we | 
 | 745 | 			 * just try "xauth list unix:displaynum.screennum". | 
 | 746 | 			 * XXX: "localhost" match to determine FamilyLocal | 
 | 747 | 			 *      is not perfect. | 
 | 748 | 			 */ | 
| Ben Lindstrom | fac7769 | 2002-06-06 19:49:54 +0000 | [diff] [blame] | 749 | 			snprintf(line, sizeof line, "%s list unix:%s 2>" | 
| Damien Miller | 35b13d6 | 2002-02-05 12:12:09 +1100 | [diff] [blame] | 750 | 			    _PATH_DEVNULL, options.xauth_location, display+10); | 
 | 751 | 		else | 
| Ben Lindstrom | fac7769 | 2002-06-06 19:49:54 +0000 | [diff] [blame] | 752 | 			snprintf(line, sizeof line, "%s list %.200s 2>" | 
| Damien Miller | 35b13d6 | 2002-02-05 12:12:09 +1100 | [diff] [blame] | 753 | 			    _PATH_DEVNULL, options.xauth_location, display); | 
 | 754 | 		debug2("x11_get_proto %s", line); | 
| Damien Miller | d3a1857 | 2000-06-07 19:55:44 +1000 | [diff] [blame] | 755 | 		f = popen(line, "r"); | 
 | 756 | 		if (f && fgets(line, sizeof(line), f) && | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 757 | 		    sscanf(line, "%*s %511s %511s", proto, data) == 2) | 
| Damien Miller | d3a1857 | 2000-06-07 19:55:44 +1000 | [diff] [blame] | 758 | 			got_data = 1; | 
 | 759 | 		if (f) | 
 | 760 | 			pclose(f); | 
 | 761 | 	} | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 762 | 	/* | 
 | 763 | 	 * If we didn't get authentication data, just make up some | 
 | 764 | 	 * data.  The forwarding code will check the validity of the | 
 | 765 | 	 * response anyway, and substitute this data.  The X11 | 
 | 766 | 	 * server, however, will ignore this fake data and use | 
 | 767 | 	 * whatever authentication mechanisms it was using otherwise | 
 | 768 | 	 * for the local connection. | 
 | 769 | 	 */ | 
 | 770 | 	if (!got_data) { | 
 | 771 | 		u_int32_t rand = 0; | 
 | 772 |  | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 773 | 		strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto); | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 774 | 		for (i = 0; i < 16; i++) { | 
 | 775 | 			if (i % 4 == 0) | 
 | 776 | 				rand = arc4random(); | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 777 | 			snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff); | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 778 | 			rand >>= 8; | 
 | 779 | 		} | 
 | 780 | 	} | 
 | 781 | } | 
 | 782 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 783 | static void | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 784 | ssh_init_forwarding(void) | 
 | 785 | { | 
| Kevin Steves | 1205750 | 2001-02-05 14:54:34 +0000 | [diff] [blame] | 786 | 	int success = 0; | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 787 | 	int i; | 
| Kevin Steves | 1205750 | 2001-02-05 14:54:34 +0000 | [diff] [blame] | 788 |  | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 789 | 	/* Initiate local TCP/IP port forwardings. */ | 
 | 790 | 	for (i = 0; i < options.num_local_forwards; i++) { | 
 | 791 | 		debug("Connections to local port %d forwarded to remote address %.200s:%d", | 
 | 792 | 		    options.local_forwards[i].port, | 
 | 793 | 		    options.local_forwards[i].host, | 
 | 794 | 		    options.local_forwards[i].host_port); | 
| Damien Miller | b16461c | 2002-01-22 23:29:22 +1100 | [diff] [blame] | 795 | 		success += channel_setup_local_fwd_listener( | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 796 | 		    options.local_forwards[i].port, | 
 | 797 | 		    options.local_forwards[i].host, | 
 | 798 | 		    options.local_forwards[i].host_port, | 
 | 799 | 		    options.gateway_ports); | 
 | 800 | 	} | 
| Kevin Steves | 1205750 | 2001-02-05 14:54:34 +0000 | [diff] [blame] | 801 | 	if (i > 0 && success == 0) | 
 | 802 | 		error("Could not request local forwarding."); | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 803 |  | 
 | 804 | 	/* Initiate remote TCP/IP port forwardings. */ | 
 | 805 | 	for (i = 0; i < options.num_remote_forwards; i++) { | 
 | 806 | 		debug("Connections to remote port %d forwarded to local address %.200s:%d", | 
 | 807 | 		    options.remote_forwards[i].port, | 
 | 808 | 		    options.remote_forwards[i].host, | 
 | 809 | 		    options.remote_forwards[i].host_port); | 
 | 810 | 		channel_request_remote_forwarding( | 
 | 811 | 		    options.remote_forwards[i].port, | 
 | 812 | 		    options.remote_forwards[i].host, | 
 | 813 | 		    options.remote_forwards[i].host_port); | 
 | 814 | 	} | 
 | 815 | } | 
 | 816 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 817 | static void | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 818 | check_agent_present(void) | 
 | 819 | { | 
 | 820 | 	if (options.forward_agent) { | 
 | 821 | 		/* Clear agent forwarding if we don\'t have an agent. */ | 
 | 822 | 		int authfd = ssh_get_authentication_socket(); | 
 | 823 | 		if (authfd < 0) | 
 | 824 | 			options.forward_agent = 0; | 
 | 825 | 		else | 
 | 826 | 			ssh_close_authentication_socket(authfd); | 
 | 827 | 	} | 
 | 828 | } | 
 | 829 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 830 | static int | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 831 | ssh_session(void) | 
 | 832 | { | 
 | 833 | 	int type; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 834 | 	int interactive = 0; | 
 | 835 | 	int have_tty = 0; | 
 | 836 | 	struct winsize ws; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 837 | 	char *cp; | 
 | 838 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 839 | 	/* Enable compression if requested. */ | 
 | 840 | 	if (options.compression) { | 
 | 841 | 		debug("Requesting compression at level %d.", options.compression_level); | 
 | 842 |  | 
 | 843 | 		if (options.compression_level < 1 || options.compression_level > 9) | 
 | 844 | 			fatal("Compression level must be from 1 (fast) to 9 (slow, best)."); | 
 | 845 |  | 
 | 846 | 		/* Send the request. */ | 
 | 847 | 		packet_start(SSH_CMSG_REQUEST_COMPRESSION); | 
 | 848 | 		packet_put_int(options.compression_level); | 
 | 849 | 		packet_send(); | 
 | 850 | 		packet_write_wait(); | 
| Damien Miller | dff5099 | 2002-01-22 23:16:32 +1100 | [diff] [blame] | 851 | 		type = packet_read(); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 852 | 		if (type == SSH_SMSG_SUCCESS) | 
 | 853 | 			packet_start_compression(options.compression_level); | 
 | 854 | 		else if (type == SSH_SMSG_FAILURE) | 
 | 855 | 			log("Warning: Remote host refused compression."); | 
 | 856 | 		else | 
 | 857 | 			packet_disconnect("Protocol error waiting for compression response."); | 
 | 858 | 	} | 
 | 859 | 	/* Allocate a pseudo tty if appropriate. */ | 
 | 860 | 	if (tty_flag) { | 
 | 861 | 		debug("Requesting pty."); | 
 | 862 |  | 
 | 863 | 		/* Start the packet. */ | 
 | 864 | 		packet_start(SSH_CMSG_REQUEST_PTY); | 
 | 865 |  | 
 | 866 | 		/* Store TERM in the packet.  There is no limit on the | 
 | 867 | 		   length of the string. */ | 
 | 868 | 		cp = getenv("TERM"); | 
 | 869 | 		if (!cp) | 
 | 870 | 			cp = ""; | 
| Ben Lindstrom | 664408d | 2001-06-09 01:42:01 +0000 | [diff] [blame] | 871 | 		packet_put_cstring(cp); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 872 |  | 
 | 873 | 		/* Store window size in the packet. */ | 
 | 874 | 		if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) | 
 | 875 | 			memset(&ws, 0, sizeof(ws)); | 
 | 876 | 		packet_put_int(ws.ws_row); | 
 | 877 | 		packet_put_int(ws.ws_col); | 
 | 878 | 		packet_put_int(ws.ws_xpixel); | 
 | 879 | 		packet_put_int(ws.ws_ypixel); | 
 | 880 |  | 
 | 881 | 		/* Store tty modes in the packet. */ | 
| Ben Lindstrom | ae8e2d3 | 2001-04-14 23:13:02 +0000 | [diff] [blame] | 882 | 		tty_make_modes(fileno(stdin), NULL); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 883 |  | 
 | 884 | 		/* Send the packet, and wait for it to leave. */ | 
 | 885 | 		packet_send(); | 
 | 886 | 		packet_write_wait(); | 
 | 887 |  | 
 | 888 | 		/* Read response from the server. */ | 
| Damien Miller | dff5099 | 2002-01-22 23:16:32 +1100 | [diff] [blame] | 889 | 		type = packet_read(); | 
| Damien Miller | 450a7a1 | 2000-03-26 13:04:51 +1000 | [diff] [blame] | 890 | 		if (type == SSH_SMSG_SUCCESS) { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 891 | 			interactive = 1; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 892 | 			have_tty = 1; | 
| Damien Miller | 450a7a1 | 2000-03-26 13:04:51 +1000 | [diff] [blame] | 893 | 		} else if (type == SSH_SMSG_FAILURE) | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 894 | 			log("Warning: Remote host failed or refused to allocate a pseudo tty."); | 
 | 895 | 		else | 
 | 896 | 			packet_disconnect("Protocol error waiting for pty request response."); | 
 | 897 | 	} | 
 | 898 | 	/* Request X11 forwarding if enabled and DISPLAY is set. */ | 
 | 899 | 	if (options.forward_x11 && getenv("DISPLAY") != NULL) { | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 900 | 		char *proto, *data; | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 901 | 		/* Get reasonable local authentication information. */ | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 902 | 		x11_get_proto(&proto, &data); | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 903 | 		/* Request forwarding with authentication spoofing. */ | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 904 | 		debug("Requesting X11 forwarding with authentication spoofing."); | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 905 | 		x11_request_forwarding_with_spoofing(0, proto, data); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 906 |  | 
 | 907 | 		/* Read response from the server. */ | 
| Damien Miller | dff5099 | 2002-01-22 23:16:32 +1100 | [diff] [blame] | 908 | 		type = packet_read(); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 909 | 		if (type == SSH_SMSG_SUCCESS) { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 910 | 			interactive = 1; | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 911 | 		} else if (type == SSH_SMSG_FAILURE) { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 912 | 			log("Warning: Remote host denied X11 forwarding."); | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 913 | 		} else { | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 914 | 			packet_disconnect("Protocol error waiting for X11 forwarding"); | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 915 | 		} | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 916 | 	} | 
 | 917 | 	/* Tell the packet module whether this is an interactive session. */ | 
| Ben Lindstrom | bf555ba | 2001-01-18 02:04:35 +0000 | [diff] [blame] | 918 | 	packet_set_interactive(interactive); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 919 |  | 
 | 920 | 	/* Request authentication agent forwarding if appropriate. */ | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 921 | 	check_agent_present(); | 
 | 922 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 923 | 	if (options.forward_agent) { | 
 | 924 | 		debug("Requesting authentication agent forwarding."); | 
 | 925 | 		auth_request_forwarding(); | 
 | 926 |  | 
 | 927 | 		/* Read response from the server. */ | 
| Damien Miller | dff5099 | 2002-01-22 23:16:32 +1100 | [diff] [blame] | 928 | 		type = packet_read(); | 
| Damien Miller | 48b03fc | 2002-01-22 23:11:40 +1100 | [diff] [blame] | 929 | 		packet_check_eom(); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 930 | 		if (type != SSH_SMSG_SUCCESS) | 
 | 931 | 			log("Warning: Remote host denied authentication agent forwarding."); | 
 | 932 | 	} | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 933 |  | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 934 | 	/* Initiate port forwardings. */ | 
 | 935 | 	ssh_init_forwarding(); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 936 |  | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 937 | 	/* If requested, let ssh continue in the background. */ | 
| Damien Miller | 4af5130 | 2000-04-16 11:18:38 +1000 | [diff] [blame] | 938 | 	if (fork_after_authentication_flag) | 
| Damien Miller | 5428f64 | 1999-11-25 11:54:57 +1100 | [diff] [blame] | 939 | 		if (daemon(1, 1) < 0) | 
 | 940 | 			fatal("daemon() failed: %.200s", strerror(errno)); | 
 | 941 |  | 
 | 942 | 	/* | 
 | 943 | 	 * If a command was specified on the command line, execute the | 
 | 944 | 	 * command now. Otherwise request the server to start a shell. | 
 | 945 | 	 */ | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 946 | 	if (buffer_len(&command) > 0) { | 
 | 947 | 		int len = buffer_len(&command); | 
 | 948 | 		if (len > 900) | 
 | 949 | 			len = 900; | 
| Damien Miller | 5a6b4fe | 2001-12-21 14:56:54 +1100 | [diff] [blame] | 950 | 		debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 951 | 		packet_start(SSH_CMSG_EXEC_CMD); | 
 | 952 | 		packet_put_string(buffer_ptr(&command), buffer_len(&command)); | 
 | 953 | 		packet_send(); | 
 | 954 | 		packet_write_wait(); | 
 | 955 | 	} else { | 
 | 956 | 		debug("Requesting shell."); | 
 | 957 | 		packet_start(SSH_CMSG_EXEC_SHELL); | 
 | 958 | 		packet_send(); | 
 | 959 | 		packet_write_wait(); | 
 | 960 | 	} | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 961 |  | 
| Damien Miller | 95def09 | 1999-11-25 00:26:21 +1100 | [diff] [blame] | 962 | 	/* Enter the interactive session. */ | 
| Ben Lindstrom | 2b1f71b | 2001-06-05 20:32:21 +0000 | [diff] [blame] | 963 | 	return client_loop(have_tty, tty_flag ? | 
 | 964 | 	    options.escape_char : SSH_ESCAPECHAR_NONE, 0); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 965 | } | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 966 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 967 | static void | 
| Damien Miller | 630d6f4 | 2002-01-22 23:17:30 +1100 | [diff] [blame] | 968 | client_subsystem_reply(int type, u_int32_t seq, void *ctxt) | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 969 | { | 
 | 970 | 	int id, len; | 
 | 971 |  | 
 | 972 | 	id = packet_get_int(); | 
 | 973 | 	len = buffer_len(&command); | 
| Ben Lindstrom | 4040fe1 | 2001-03-05 06:52:57 +0000 | [diff] [blame] | 974 | 	if (len > 900) | 
 | 975 | 		len = 900; | 
| Damien Miller | 48b03fc | 2002-01-22 23:11:40 +1100 | [diff] [blame] | 976 | 	packet_check_eom(); | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 977 | 	if (type == SSH2_MSG_CHANNEL_FAILURE) | 
 | 978 | 		fatal("Request for subsystem '%.*s' failed on channel %d", | 
| Damien Miller | 5a6b4fe | 2001-12-21 14:56:54 +1100 | [diff] [blame] | 979 | 		    len, (u_char *)buffer_ptr(&command), id); | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 980 | } | 
 | 981 |  | 
| Damien Miller | 2797f7f | 2002-04-23 21:09:44 +1000 | [diff] [blame] | 982 | void | 
 | 983 | client_global_request_reply(int type, u_int32_t seq, void *ctxt) | 
 | 984 | { | 
 | 985 | 	int i; | 
 | 986 |  | 
 | 987 | 	i = client_global_request_id++; | 
 | 988 | 	if (i >= options.num_remote_forwards) { | 
 | 989 | 		debug("client_global_request_reply: too many replies %d > %d", | 
 | 990 | 		    i, options.num_remote_forwards); | 
 | 991 | 		return; | 
 | 992 | 	} | 
 | 993 | 	debug("remote forward %s for: listen %d, connect %s:%d", | 
 | 994 | 	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 
 | 995 | 	    options.remote_forwards[i].port, | 
 | 996 | 	    options.remote_forwards[i].host, | 
 | 997 | 	    options.remote_forwards[i].host_port); | 
 | 998 | 	if (type == SSH2_MSG_REQUEST_FAILURE) | 
 | 999 | 		log("Warning: remote port forwarding failed for listen port %d", | 
 | 1000 | 		    options.remote_forwards[i].port); | 
 | 1001 | } | 
 | 1002 |  | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1003 | /* request pty/x11/agent/tcpfwd/shell for channel */ | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 1004 | static void | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1005 | ssh_session2_setup(int id, void *arg) | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1006 | { | 
 | 1007 | 	int len; | 
| Ben Lindstrom | bf555ba | 2001-01-18 02:04:35 +0000 | [diff] [blame] | 1008 | 	int interactive = 0; | 
| Ben Lindstrom | ae8e2d3 | 2001-04-14 23:13:02 +0000 | [diff] [blame] | 1009 | 	struct termios tio; | 
| Ben Lindstrom | bf555ba | 2001-01-18 02:04:35 +0000 | [diff] [blame] | 1010 |  | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1011 | 	debug("ssh_session2_setup: id %d", id); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1012 |  | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1013 | 	if (tty_flag) { | 
 | 1014 | 		struct winsize ws; | 
 | 1015 | 		char *cp; | 
 | 1016 | 		cp = getenv("TERM"); | 
 | 1017 | 		if (!cp) | 
 | 1018 | 			cp = ""; | 
 | 1019 | 		/* Store window size in the packet. */ | 
 | 1020 | 		if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) | 
 | 1021 | 			memset(&ws, 0, sizeof(ws)); | 
 | 1022 |  | 
 | 1023 | 		channel_request_start(id, "pty-req", 0); | 
 | 1024 | 		packet_put_cstring(cp); | 
 | 1025 | 		packet_put_int(ws.ws_col); | 
 | 1026 | 		packet_put_int(ws.ws_row); | 
 | 1027 | 		packet_put_int(ws.ws_xpixel); | 
 | 1028 | 		packet_put_int(ws.ws_ypixel); | 
| Ben Lindstrom | ae8e2d3 | 2001-04-14 23:13:02 +0000 | [diff] [blame] | 1029 | 		tio = get_saved_tio(); | 
 | 1030 | 		tty_make_modes(/*ignored*/ 0, &tio); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1031 | 		packet_send(); | 
| Ben Lindstrom | bf555ba | 2001-01-18 02:04:35 +0000 | [diff] [blame] | 1032 | 		interactive = 1; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1033 | 		/* XXX wait for reply */ | 
 | 1034 | 	} | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 1035 | 	if (options.forward_x11 && | 
 | 1036 | 	    getenv("DISPLAY") != NULL) { | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 1037 | 		char *proto, *data; | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 1038 | 		/* Get reasonable local authentication information. */ | 
| Ben Lindstrom | 4a4bd71 | 2001-12-06 17:45:19 +0000 | [diff] [blame] | 1039 | 		x11_get_proto(&proto, &data); | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 1040 | 		/* Request forwarding with authentication spoofing. */ | 
 | 1041 | 		debug("Requesting X11 forwarding with authentication spoofing."); | 
 | 1042 | 		x11_request_forwarding_with_spoofing(id, proto, data); | 
| Ben Lindstrom | bf555ba | 2001-01-18 02:04:35 +0000 | [diff] [blame] | 1043 | 		interactive = 1; | 
| Damien Miller | bd483e7 | 2000-04-30 10:00:53 +1000 | [diff] [blame] | 1044 | 		/* XXX wait for reply */ | 
 | 1045 | 	} | 
 | 1046 |  | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 1047 | 	check_agent_present(); | 
 | 1048 | 	if (options.forward_agent) { | 
 | 1049 | 		debug("Requesting authentication agent forwarding."); | 
 | 1050 | 		channel_request_start(id, "auth-agent-req@openssh.com", 0); | 
 | 1051 | 		packet_send(); | 
 | 1052 | 	} | 
 | 1053 |  | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1054 | 	len = buffer_len(&command); | 
 | 1055 | 	if (len > 0) { | 
 | 1056 | 		if (len > 900) | 
 | 1057 | 			len = 900; | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 1058 | 		if (subsystem_flag) { | 
| Damien Miller | 5a6b4fe | 2001-12-21 14:56:54 +1100 | [diff] [blame] | 1059 | 			debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command)); | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 1060 | 			channel_request_start(id, "subsystem", /*want reply*/ 1); | 
 | 1061 | 			/* register callback for reply */ | 
| Ben Lindstrom | f666fec | 2002-06-06 19:51:58 +0000 | [diff] [blame] | 1062 | 			/* XXX we assume that client_loop has already been called */ | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 1063 | 			dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply); | 
 | 1064 | 			dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply); | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 1065 | 		} else { | 
| Damien Miller | 5a6b4fe | 2001-12-21 14:56:54 +1100 | [diff] [blame] | 1066 | 			debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); | 
| Damien Miller | 832562e | 2001-01-30 09:30:01 +1100 | [diff] [blame] | 1067 | 			channel_request_start(id, "exec", 0); | 
 | 1068 | 		} | 
| Ben Lindstrom | 4040fe1 | 2001-03-05 06:52:57 +0000 | [diff] [blame] | 1069 | 		packet_put_string(buffer_ptr(&command), buffer_len(&command)); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1070 | 		packet_send(); | 
 | 1071 | 	} else { | 
| Damien Miller | a500cd6 | 2002-02-08 22:04:26 +1100 | [diff] [blame] | 1072 | 		channel_request_start(id, "shell", 0); | 
 | 1073 | 		packet_send(); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1074 | 	} | 
| Ben Lindstrom | 1e7d306 | 2001-02-09 02:36:43 +0000 | [diff] [blame] | 1075 |  | 
| Ben Lindstrom | bf555ba | 2001-01-18 02:04:35 +0000 | [diff] [blame] | 1076 | 	packet_set_interactive(interactive); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1077 | } | 
 | 1078 |  | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1079 | /* open new channel for a session */ | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 1080 | static int | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1081 | ssh_session2_open(void) | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1082 | { | 
| Ben Lindstrom | 99c73b3 | 2001-05-05 04:09:47 +0000 | [diff] [blame] | 1083 | 	Channel *c; | 
 | 1084 | 	int window, packetmax, in, out, err; | 
| Damien Miller | ad833b3 | 2000-08-23 10:46:23 +1000 | [diff] [blame] | 1085 |  | 
| Damien Miller | caf6dd6 | 2000-08-29 11:33:50 +1100 | [diff] [blame] | 1086 | 	if (stdin_null_flag) { | 
| Ben Lindstrom | 31ca54a | 2001-02-09 02:11:24 +0000 | [diff] [blame] | 1087 | 		in = open(_PATH_DEVNULL, O_RDONLY); | 
| Damien Miller | caf6dd6 | 2000-08-29 11:33:50 +1100 | [diff] [blame] | 1088 | 	} else { | 
 | 1089 | 		in = dup(STDIN_FILENO); | 
 | 1090 | 	} | 
 | 1091 | 	out = dup(STDOUT_FILENO); | 
 | 1092 | 	err = dup(STDERR_FILENO); | 
 | 1093 |  | 
 | 1094 | 	if (in < 0 || out < 0 || err < 0) | 
 | 1095 | 		fatal("dup() in/out/err failed"); | 
 | 1096 |  | 
| Damien Miller | 69b69aa | 2000-10-28 14:19:58 +1100 | [diff] [blame] | 1097 | 	/* enable nonblocking unless tty */ | 
 | 1098 | 	if (!isatty(in)) | 
 | 1099 | 		set_nonblock(in); | 
 | 1100 | 	if (!isatty(out)) | 
 | 1101 | 		set_nonblock(out); | 
 | 1102 | 	if (!isatty(err)) | 
 | 1103 | 		set_nonblock(err); | 
 | 1104 |  | 
| Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 1105 | 	window = CHAN_SES_WINDOW_DEFAULT; | 
 | 1106 | 	packetmax = CHAN_SES_PACKET_DEFAULT; | 
| Damien Miller | 19a5945 | 2002-02-19 15:20:57 +1100 | [diff] [blame] | 1107 | 	if (tty_flag) { | 
 | 1108 | 		window >>= 1; | 
 | 1109 | 		packetmax >>= 1; | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1110 | 	} | 
| Ben Lindstrom | 99c73b3 | 2001-05-05 04:09:47 +0000 | [diff] [blame] | 1111 | 	c = channel_new( | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1112 | 	    "session", SSH_CHANNEL_OPENING, in, out, err, | 
| Damien Miller | e4340be | 2000-09-16 13:29:08 +1100 | [diff] [blame] | 1113 | 	    window, packetmax, CHAN_EXTENDED_WRITE, | 
| Damien Miller | 69b69aa | 2000-10-28 14:19:58 +1100 | [diff] [blame] | 1114 | 	    xstrdup("client-session"), /*nonblock*/0); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1115 |  | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1116 | 	debug3("ssh_session2_open: channel_new: %d", c->self); | 
| Ben Lindstrom | 4c3f77d | 2001-04-05 23:37:36 +0000 | [diff] [blame] | 1117 |  | 
| Ben Lindstrom | 5ec2645 | 2001-06-09 00:18:51 +0000 | [diff] [blame] | 1118 | 	channel_send_open(c->self); | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1119 | 	if (!no_shell_flag) | 
| Damien Miller | 67f0bc0 | 2002-02-05 12:23:08 +1100 | [diff] [blame] | 1120 | 		channel_register_confirm(c->self, ssh_session2_setup); | 
| Damien Miller | 1383bd8 | 2000-04-06 12:32:37 +1000 | [diff] [blame] | 1121 |  | 
| Ben Lindstrom | 99c73b3 | 2001-05-05 04:09:47 +0000 | [diff] [blame] | 1122 | 	return c->self; | 
| Ben Lindstrom | 4c3f77d | 2001-04-05 23:37:36 +0000 | [diff] [blame] | 1123 | } | 
 | 1124 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 1125 | static int | 
| Ben Lindstrom | 4c3f77d | 2001-04-05 23:37:36 +0000 | [diff] [blame] | 1126 | ssh_session2(void) | 
 | 1127 | { | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1128 | 	int id = -1; | 
| Ben Lindstrom | 4c3f77d | 2001-04-05 23:37:36 +0000 | [diff] [blame] | 1129 |  | 
 | 1130 | 	/* XXX should be pre-session */ | 
 | 1131 | 	ssh_init_forwarding(); | 
 | 1132 |  | 
| Ben Lindstrom | f558cf6 | 2001-09-20 23:13:49 +0000 | [diff] [blame] | 1133 | 	if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) | 
 | 1134 | 		id = ssh_session2_open(); | 
| Ben Lindstrom | 4c3f77d | 2001-04-05 23:37:36 +0000 | [diff] [blame] | 1135 |  | 
 | 1136 | 	/* If requested, let ssh continue in the background. */ | 
 | 1137 | 	if (fork_after_authentication_flag) | 
 | 1138 | 		if (daemon(1, 1) < 0) | 
 | 1139 | 			fatal("daemon() failed: %.200s", strerror(errno)); | 
 | 1140 |  | 
| Ben Lindstrom | 2b1f71b | 2001-06-05 20:32:21 +0000 | [diff] [blame] | 1141 | 	return client_loop(tty_flag, tty_flag ? | 
 | 1142 | 	    options.escape_char : SSH_ESCAPECHAR_NONE, id); | 
| Damien Miller | d4a8b7e | 1999-10-27 13:42:43 +1000 | [diff] [blame] | 1143 | } | 
| Damien Miller | 0bc1bd8 | 2000-11-13 22:57:25 +1100 | [diff] [blame] | 1144 |  | 
| Ben Lindstrom | bba8121 | 2001-06-25 05:01:22 +0000 | [diff] [blame] | 1145 | static void | 
| Ben Lindstrom | 266dfdf | 2001-03-09 00:12:22 +0000 | [diff] [blame] | 1146 | load_public_identity_files(void) | 
 | 1147 | { | 
 | 1148 | 	char *filename; | 
| Ben Lindstrom | 711b04a | 2001-08-06 21:12:42 +0000 | [diff] [blame] | 1149 | 	int i = 0; | 
| Ben Lindstrom | 0936a5b | 2002-03-26 03:17:42 +0000 | [diff] [blame] | 1150 | 	Key *public; | 
| Ben Lindstrom | 711b04a | 2001-08-06 21:12:42 +0000 | [diff] [blame] | 1151 | #ifdef SMARTCARD | 
| Ben Lindstrom | 0936a5b | 2002-03-26 03:17:42 +0000 | [diff] [blame] | 1152 | 	Key **keys; | 
 | 1153 |  | 
| Ben Lindstrom | f7db3bb | 2001-08-06 21:35:51 +0000 | [diff] [blame] | 1154 | 	if (options.smartcard_device != NULL && | 
| Ben Lindstrom | 0936a5b | 2002-03-26 03:17:42 +0000 | [diff] [blame] | 1155 | 	    options.num_identity_files < SSH_MAX_IDENTITY_FILES && | 
 | 1156 | 	    (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) { | 
 | 1157 | 		int count = 0; | 
 | 1158 | 		for (i = 0; keys[i] != NULL; i++) { | 
 | 1159 | 			count++; | 
| Ben Lindstrom | 0936a5b | 2002-03-26 03:17:42 +0000 | [diff] [blame] | 1160 | 			memmove(&options.identity_files[1], &options.identity_files[0], | 
 | 1161 | 			    sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); | 
 | 1162 | 			memmove(&options.identity_keys[1], &options.identity_keys[0], | 
 | 1163 | 			    sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); | 
 | 1164 | 			options.num_identity_files++; | 
 | 1165 | 			options.identity_keys[0] = keys[i]; | 
 | 1166 | 			options.identity_files[0] = xstrdup("smartcard key");; | 
 | 1167 | 		} | 
| Ben Lindstrom | 4f05460 | 2002-03-26 03:23:00 +0000 | [diff] [blame] | 1168 | 		if (options.num_identity_files > SSH_MAX_IDENTITY_FILES) | 
 | 1169 | 			options.num_identity_files = SSH_MAX_IDENTITY_FILES; | 
| Ben Lindstrom | 0936a5b | 2002-03-26 03:17:42 +0000 | [diff] [blame] | 1170 | 		i = count; | 
 | 1171 | 		xfree(keys); | 
| Ben Lindstrom | 711b04a | 2001-08-06 21:12:42 +0000 | [diff] [blame] | 1172 | 	} | 
| Ben Lindstrom | ffce147 | 2001-08-06 21:57:31 +0000 | [diff] [blame] | 1173 | #endif /* SMARTCARD */ | 
| Ben Lindstrom | 711b04a | 2001-08-06 21:12:42 +0000 | [diff] [blame] | 1174 | 	for (; i < options.num_identity_files; i++) { | 
| Ben Lindstrom | 266dfdf | 2001-03-09 00:12:22 +0000 | [diff] [blame] | 1175 | 		filename = tilde_expand_filename(options.identity_files[i], | 
 | 1176 | 		    original_real_uid); | 
| Ben Lindstrom | d0fca42 | 2001-03-26 13:44:06 +0000 | [diff] [blame] | 1177 | 		public = key_load_public(filename, NULL); | 
| Ben Lindstrom | 266dfdf | 2001-03-09 00:12:22 +0000 | [diff] [blame] | 1178 | 		debug("identity file %s type %d", filename, | 
 | 1179 | 		    public ? public->type : -1); | 
 | 1180 | 		xfree(options.identity_files[i]); | 
 | 1181 | 		options.identity_files[i] = filename; | 
 | 1182 | 		options.identity_keys[i] = public; | 
 | 1183 | 	} | 
 | 1184 | } |