blob: f24f750712418f5f5f31bf2399bd6cb51232dd4d [file] [log] [blame]
Damien Miller33804262001-02-04 23:20:18 +11001/*
2 * Copyright (c) 2001 Damien Miller. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26
Ben Lindstrom46d6e092001-03-05 07:10:47 +000027RCSID("$OpenBSD: sftp.c,v 1.9 2001/03/03 23:52:22 markus Exp $");
Damien Miller33804262001-02-04 23:20:18 +110028
29/* XXX: commandline mode */
30/* XXX: copy between two remote hosts (commandline) */
31/* XXX: short-form remote directory listings (like 'ls -C') */
32
33#include "buffer.h"
34#include "xmalloc.h"
35#include "log.h"
36#include "pathnames.h"
37
38#include "sftp.h"
39#include "sftp-common.h"
40#include "sftp-client.h"
41#include "sftp-int.h"
42
Kevin Steves12888d12001-03-05 19:50:57 +000043#ifdef HAVE___PROGNAME
44extern char *__progname;
45#else
46char *__progname;
47#endif
48
Damien Millerd7686fd2001-02-10 00:40:03 +110049int use_ssh1 = 0;
50char *ssh_program = _PATH_SSH_PROGRAM;
51char *sftp_server = NULL;
52
Damien Miller33804262001-02-04 23:20:18 +110053void
54connect_to_server(char **args, int *in, int *out, pid_t *sshpid)
55{
56 int c_in, c_out;
57#ifdef USE_PIPES
58 int pin[2], pout[2];
59 if ((pipe(pin) == -1) || (pipe(pout) == -1))
60 fatal("pipe: %s", strerror(errno));
61 *in = pin[0];
62 *out = pout[1];
63 c_in = pout[0];
64 c_out = pin[1];
65#else /* USE_PIPES */
66 int inout[2];
67 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)
68 fatal("socketpair: %s", strerror(errno));
69 *in = *out = inout[0];
70 c_in = c_out = inout[1];
71#endif /* USE_PIPES */
72
73 if ((*sshpid = fork()) == -1)
74 fatal("fork: %s", strerror(errno));
75 else if (*sshpid == 0) {
76 if ((dup2(c_in, STDIN_FILENO) == -1) ||
77 (dup2(c_out, STDOUT_FILENO) == -1)) {
78 fprintf(stderr, "dup2: %s\n", strerror(errno));
79 exit(1);
80 }
81 close(*in);
82 close(*out);
83 close(c_in);
84 close(c_out);
Damien Millerd7686fd2001-02-10 00:40:03 +110085 execv(ssh_program, args);
86 fprintf(stderr, "exec: %s: %s\n", ssh_program, strerror(errno));
Damien Miller33804262001-02-04 23:20:18 +110087 exit(1);
88 }
89
90 close(c_in);
91 close(c_out);
92}
93
94char **
95make_ssh_args(char *add_arg)
96{
97 static char **args = NULL;
98 static int nargs = 0;
99 char debug_buf[4096];
Ben Lindstrom46d6e092001-03-05 07:10:47 +0000100 int i;
Damien Miller33804262001-02-04 23:20:18 +1100101
102 /* Init args array */
103 if (args == NULL) {
Ben Lindstrom46d6e092001-03-05 07:10:47 +0000104 nargs = 2;
Damien Miller33804262001-02-04 23:20:18 +1100105 i = 0;
106 args = xmalloc(sizeof(*args) * nargs);
107 args[i++] = "ssh";
Damien Miller33804262001-02-04 23:20:18 +1100108 args[i++] = NULL;
109 }
110
111 /* If asked to add args, then do so and return */
112 if (add_arg) {
113 i = nargs++ - 1;
114 args = xrealloc(args, sizeof(*args) * nargs);
115 args[i++] = add_arg;
116 args[i++] = NULL;
117 return(NULL);
118 }
119
Ben Lindstrom46d6e092001-03-05 07:10:47 +0000120 /* no subsystem if the server-spec contains a '/' */
121 if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)
122 make_ssh_args("-s");
123 make_ssh_args("-oForwardX11=no");
124 make_ssh_args("-oForwardAgent=no");
125 make_ssh_args(use_ssh1 ? "-oProtocol=1" : "-oProtocol=2");
126
Damien Miller33804262001-02-04 23:20:18 +1100127 /* Otherwise finish up and return the arg array */
Damien Millerd7686fd2001-02-10 00:40:03 +1100128 if (sftp_server != NULL)
129 make_ssh_args(sftp_server);
130 else
131 make_ssh_args("sftp");
Damien Miller33804262001-02-04 23:20:18 +1100132
133 /* XXX: overflow - doesn't grow debug_buf */
134 debug_buf[0] = '\0';
135 for(i = 0; args[i]; i++) {
136 if (i)
137 strlcat(debug_buf, " ", sizeof(debug_buf));
138
139 strlcat(debug_buf, args[i], sizeof(debug_buf));
140 }
141 debug("SSH args \"%s\"", debug_buf);
142
143 return(args);
144}
145
Kevin Stevesef4eea92001-02-05 12:42:17 +0000146void
Damien Miller33804262001-02-04 23:20:18 +1100147usage(void)
148{
Damien Millerd7686fd2001-02-10 00:40:03 +1100149 fprintf(stderr, "usage: sftp [-1vC] [-osshopt=value] [user@]host\n");
Damien Miller33804262001-02-04 23:20:18 +1100150 exit(1);
151}
152
Kevin Stevesef4eea92001-02-05 12:42:17 +0000153int
Damien Miller33804262001-02-04 23:20:18 +1100154main(int argc, char **argv)
155{
Damien Millerd7686fd2001-02-10 00:40:03 +1100156 int in, out, ch, debug_level, compress_flag;
Damien Miller33804262001-02-04 23:20:18 +1100157 pid_t sshpid;
Damien Millerd7686fd2001-02-10 00:40:03 +1100158 char *host, *userhost;
Damien Miller33804262001-02-04 23:20:18 +1100159 LogLevel ll;
Damien Millerd7686fd2001-02-10 00:40:03 +1100160 extern int optind;
161 extern char *optarg;
Damien Miller33804262001-02-04 23:20:18 +1100162
Kevin Steves12888d12001-03-05 19:50:57 +0000163 __progname = get_progname(argv[0]);
Damien Miller33804262001-02-04 23:20:18 +1100164 debug_level = compress_flag = 0;
Damien Millerd7686fd2001-02-10 00:40:03 +1100165
166 while ((ch = getopt(argc, argv, "1hvCo:s:S:")) != -1) {
167 switch (ch) {
168 case 'C':
Damien Miller33804262001-02-04 23:20:18 +1100169 compress_flag = 1;
Damien Millerd7686fd2001-02-10 00:40:03 +1100170 break;
171 case 'v':
172 debug_level = MIN(3, debug_level + 1);
173 break;
174 case 'o':
175 make_ssh_args("-o");
176 make_ssh_args(optarg);
177 break;
178 case '1':
179 use_ssh1 = 1;
180 if (sftp_server == NULL)
181 sftp_server = _PATH_SFTP_SERVER;
182 break;
183 case 's':
184 sftp_server = optarg;
185 break;
186 case 'S':
187 ssh_program = optarg;
188 break;
189 case 'h':
190 default:
Damien Miller33804262001-02-04 23:20:18 +1100191 usage();
192 }
193 }
194
Damien Millerd7686fd2001-02-10 00:40:03 +1100195 if (optind == argc || argc > (optind + 1))
Damien Miller33804262001-02-04 23:20:18 +1100196 usage();
197
Damien Millerd7686fd2001-02-10 00:40:03 +1100198 userhost = argv[optind];
199
200 if ((host = strchr(userhost, '@')) == NULL)
201 host = userhost;
Damien Miller33804262001-02-04 23:20:18 +1100202 else {
Damien Millerd7686fd2001-02-10 00:40:03 +1100203 *host = '\0';
204 if (!userhost[0]) {
Damien Miller33804262001-02-04 23:20:18 +1100205 fprintf(stderr, "Missing username\n");
206 usage();
207 }
208 make_ssh_args("-l");
Damien Millerd7686fd2001-02-10 00:40:03 +1100209 make_ssh_args(userhost);
210 host++;
Damien Miller33804262001-02-04 23:20:18 +1100211 }
212
Damien Millerd7686fd2001-02-10 00:40:03 +1100213 if (!*host) {
Damien Miller33804262001-02-04 23:20:18 +1100214 fprintf(stderr, "Missing hostname\n");
215 usage();
216 }
217
218 /* Set up logging and debug '-d' arguments to ssh */
219 ll = SYSLOG_LEVEL_INFO;
220 switch (debug_level) {
221 case 1:
222 ll = SYSLOG_LEVEL_DEBUG1;
223 make_ssh_args("-v");
224 break;
225 case 2:
226 ll = SYSLOG_LEVEL_DEBUG2;
227 make_ssh_args("-v");
228 make_ssh_args("-v");
229 break;
230 case 3:
231 ll = SYSLOG_LEVEL_DEBUG3;
232 make_ssh_args("-v");
233 make_ssh_args("-v");
234 make_ssh_args("-v");
235 break;
236 }
237
238 if (compress_flag)
239 make_ssh_args("-C");
240
241 log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
242
Damien Millerd7686fd2001-02-10 00:40:03 +1100243 make_ssh_args(host);
Damien Miller33804262001-02-04 23:20:18 +1100244
Damien Millerd7686fd2001-02-10 00:40:03 +1100245 fprintf(stderr, "Connecting to %s...\n", host);
Damien Miller33804262001-02-04 23:20:18 +1100246
247 connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid);
248
249 do_init(in, out);
250
251 interactive_loop(in, out);
252
Ben Lindstrom10b9bf92001-02-26 20:04:45 +0000253#if !defined(USE_PIPES)
254 shutdown(in, SHUT_RDWR);
255 shutdown(out, SHUT_RDWR);
256#endif
257
Damien Miller33804262001-02-04 23:20:18 +1100258 close(in);
259 close(out);
260
Damien Millerd7686fd2001-02-10 00:40:03 +1100261 if (waitpid(sshpid, NULL, 0) == -1)
262 fatal("Couldn't wait for ssh process: %s", strerror(errno));
Damien Miller33804262001-02-04 23:20:18 +1100263
264 exit(0);
265}