]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - scp.c
Add pscp to .cvsignore
[PuTTY.git] / scp.c
1 /*
2  * scp.c  -  Scp (Secure Copy) client for PuTTY.
3  * Joris van Rantwijk, Simon Tatham
4  *
5  * This is mainly based on ssh-1.2.26/scp.c by Timo Rinne & Tatu Ylonen.
6  * They, in turn, used stuff from BSD rcp.
7  * 
8  * (SGT, 2001-09-10: Joris van Rantwijk assures me that although
9  * this file as originally submitted was inspired by, and
10  * _structurally_ based on, ssh-1.2.26's scp.c, there wasn't any
11  * actual code duplicated, so the above comment shouldn't give rise
12  * to licensing issues.)
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <time.h>
20 #include <assert.h>
21
22 #define PUTTY_DO_GLOBALS
23 #include "putty.h"
24 #include "psftp.h"
25 #include "ssh.h"
26 #include "sftp.h"
27 #include "storage.h"
28
29 static int list = 0;
30 static int verbose = 0;
31 static int recursive = 0;
32 static int preserve = 0;
33 static int targetshouldbedirectory = 0;
34 static int statistics = 1;
35 static int prev_stats_len = 0;
36 static int scp_unsafe_mode = 0;
37 static int errs = 0;
38 static int gui_mode = 0;
39 static int using_sftp = 0;
40
41 static Backend *back;
42 static void *backhandle;
43 static Config cfg;
44
45 static void source(char *src);
46 static void rsource(char *src);
47 static void sink(char *targ, char *src);
48
49 /*
50  * The maximum amount of queued data we accept before we stop and
51  * wait for the server to process some.
52  */
53 #define MAX_SCP_BUFSIZE 16384
54
55 void ldisc_send(void *handle, char *buf, int len, int interactive)
56 {
57     /*
58      * This is only here because of the calls to ldisc_send(NULL,
59      * 0) in ssh.c. Nothing in PSCP actually needs to use the ldisc
60      * as an ldisc. So if we get called with any real data, I want
61      * to know about it.
62      */
63     assert(len == 0);
64 }
65
66 static void tell_char(FILE * stream, char c)
67 {
68     if (!gui_mode)
69         fputc(c, stream);
70     else
71         gui_send_char(stream == stderr, c);
72 }
73
74 static void tell_str(FILE * stream, char *str)
75 {
76     unsigned int i;
77
78     for (i = 0; i < strlen(str); ++i)
79         tell_char(stream, str[i]);
80 }
81
82 static void tell_user(FILE * stream, char *fmt, ...)
83 {
84     char *str, *str2;
85     va_list ap;
86     va_start(ap, fmt);
87     str = dupvprintf(fmt, ap);
88     va_end(ap);
89     str2 = dupcat(str, "\n", NULL);
90     sfree(str);
91     tell_str(stream, str2);
92     sfree(str2);
93 }
94
95 /*
96  *  Print an error message and perform a fatal exit.
97  */
98 void fatalbox(char *fmt, ...)
99 {
100     char *str, *str2;
101     va_list ap;
102     va_start(ap, fmt);
103     str = dupvprintf(fmt, ap);
104     str2 = dupcat("Fatal: ", str, "\n", NULL);
105     sfree(str);
106     va_end(ap);
107     tell_str(stderr, str2);
108     sfree(str2);
109     errs++;
110
111     if (gui_mode)
112         gui_send_errcount(list, errs);
113
114     cleanup_exit(1);
115 }
116 void modalfatalbox(char *fmt, ...)
117 {
118     char *str, *str2;
119     va_list ap;
120     va_start(ap, fmt);
121     str = dupvprintf(fmt, ap);
122     str2 = dupcat("Fatal: ", str, "\n", NULL);
123     sfree(str);
124     va_end(ap);
125     tell_str(stderr, str2);
126     sfree(str2);
127     errs++;
128
129     if (gui_mode)
130         gui_send_errcount(list, errs);
131
132     cleanup_exit(1);
133 }
134 void connection_fatal(void *frontend, char *fmt, ...)
135 {
136     char *str, *str2;
137     va_list ap;
138     va_start(ap, fmt);
139     str = dupvprintf(fmt, ap);
140     str2 = dupcat("Fatal: ", str, "\n", NULL);
141     sfree(str);
142     va_end(ap);
143     tell_str(stderr, str2);
144     sfree(str2);
145     errs++;
146
147     if (gui_mode)
148         gui_send_errcount(list, errs);
149
150     cleanup_exit(1);
151 }
152
153 /*
154  * In pscp, all agent requests should be synchronous, so this is a
155  * never-called stub.
156  */
157 void agent_schedule_callback(void (*callback)(void *, void *, int),
158                              void *callback_ctx, void *data, int len)
159 {
160     assert(!"We shouldn't be here");
161 }
162
163 /*
164  * Receive a block of data from the SSH link. Block until all data
165  * is available.
166  *
167  * To do this, we repeatedly call the SSH protocol module, with our
168  * own trap in from_backend() to catch the data that comes back. We
169  * do this until we have enough data.
170  */
171
172 static unsigned char *outptr;          /* where to put the data */
173 static unsigned outlen;                /* how much data required */
174 static unsigned char *pending = NULL;  /* any spare data */
175 static unsigned pendlen = 0, pendsize = 0;      /* length and phys. size of buffer */
176 int from_backend(void *frontend, int is_stderr, const char *data, int datalen)
177 {
178     unsigned char *p = (unsigned char *) data;
179     unsigned len = (unsigned) datalen;
180
181     assert(len > 0);
182
183     /*
184      * stderr data is just spouted to local stderr and otherwise
185      * ignored.
186      */
187     if (is_stderr) {
188         fwrite(data, 1, len, stderr);
189         return 0;
190     }
191
192     /*
193      * If this is before the real session begins, just return.
194      */
195     if (!outptr)
196         return 0;
197
198     if (outlen > 0) {
199         unsigned used = outlen;
200         if (used > len)
201             used = len;
202         memcpy(outptr, p, used);
203         outptr += used;
204         outlen -= used;
205         p += used;
206         len -= used;
207     }
208
209     if (len > 0) {
210         if (pendsize < pendlen + len) {
211             pendsize = pendlen + len + 4096;
212             pending = sresize(pending, pendsize, unsigned char);
213             if (!pending)
214                 fatalbox("Out of memory");
215         }
216         memcpy(pending + pendlen, p, len);
217         pendlen += len;
218     }
219
220     return 0;
221 }
222 static int ssh_scp_recv(unsigned char *buf, int len)
223 {
224     outptr = buf;
225     outlen = len;
226
227     /*
228      * See if the pending-input block contains some of what we
229      * need.
230      */
231     if (pendlen > 0) {
232         unsigned pendused = pendlen;
233         if (pendused > outlen)
234             pendused = outlen;
235         memcpy(outptr, pending, pendused);
236         memmove(pending, pending + pendused, pendlen - pendused);
237         outptr += pendused;
238         outlen -= pendused;
239         pendlen -= pendused;
240         if (pendlen == 0) {
241             pendsize = 0;
242             sfree(pending);
243             pending = NULL;
244         }
245         if (outlen == 0)
246             return len;
247     }
248
249     while (outlen > 0) {
250         if (ssh_sftp_loop_iteration() < 0)
251             return 0;                  /* doom */
252     }
253
254     return len;
255 }
256
257 /*
258  * Loop through the ssh connection and authentication process.
259  */
260 static void ssh_scp_init(void)
261 {
262     while (!back->sendok(backhandle)) {
263         if (ssh_sftp_loop_iteration() < 0)
264             return;                    /* doom */
265     }
266     using_sftp = !ssh_fallback_cmd(backhandle);
267     if (verbose) {
268         if (using_sftp)
269             tell_user(stderr, "Using SFTP");
270         else
271             tell_user(stderr, "Using SCP1");
272     }
273 }
274
275 /*
276  *  Print an error message and exit after closing the SSH link.
277  */
278 static void bump(char *fmt, ...)
279 {
280     char *str, *str2;
281     va_list ap;
282     va_start(ap, fmt);
283     str = dupvprintf(fmt, ap);
284     va_end(ap);
285     str2 = dupcat(str, "\n", NULL);
286     sfree(str);
287     tell_str(stderr, str2);
288     sfree(str2);
289     errs++;
290
291     if (back != NULL && back->socket(backhandle) != NULL) {
292         char ch;
293         back->special(backhandle, TS_EOF);
294         ssh_scp_recv(&ch, 1);
295     }
296
297     if (gui_mode)
298         gui_send_errcount(list, errs);
299
300     cleanup_exit(1);
301 }
302
303 /*
304  *  Open an SSH connection to user@host and execute cmd.
305  */
306 static void do_cmd(char *host, char *user, char *cmd)
307 {
308     const char *err;
309     char *realhost;
310     void *logctx;
311
312     if (host == NULL || host[0] == '\0')
313         bump("Empty host name");
314
315     /* Try to load settings for this host */
316     do_defaults(host, &cfg);
317     if (cfg.host[0] == '\0') {
318         /* No settings for this host; use defaults */
319         do_defaults(NULL, &cfg);
320         strncpy(cfg.host, host, sizeof(cfg.host) - 1);
321         cfg.host[sizeof(cfg.host) - 1] = '\0';
322     }
323
324     /*
325      * Force use of SSH. (If they got the protocol wrong we assume the
326      * port is useless too.)
327      */
328     if (cfg.protocol != PROT_SSH) {
329         cfg.protocol = PROT_SSH;
330         cfg.port = 22;
331     }
332
333     /*
334      * Enact command-line overrides.
335      */
336     cmdline_run_saved(&cfg);
337
338     /*
339      * Trim leading whitespace off the hostname if it's there.
340      */
341     {
342         int space = strspn(cfg.host, " \t");
343         memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
344     }
345
346     /* See if host is of the form user@host */
347     if (cfg.host[0] != '\0') {
348         char *atsign = strchr(cfg.host, '@');
349         /* Make sure we're not overflowing the user field */
350         if (atsign) {
351             if (atsign - cfg.host < sizeof cfg.username) {
352                 strncpy(cfg.username, cfg.host, atsign - cfg.host);
353                 cfg.username[atsign - cfg.host] = '\0';
354             }
355             memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
356         }
357     }
358
359     /*
360      * Trim a colon suffix off the hostname if it's there.
361      */
362     cfg.host[strcspn(cfg.host, ":")] = '\0';
363
364     /*
365      * Remove any remaining whitespace from the hostname.
366      */
367     {
368         int p1 = 0, p2 = 0;
369         while (cfg.host[p2] != '\0') {
370             if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
371                 cfg.host[p1] = cfg.host[p2];
372                 p1++;
373             }
374             p2++;
375         }
376         cfg.host[p1] = '\0';
377     }
378
379     /* Set username */
380     if (user != NULL && user[0] != '\0') {
381         strncpy(cfg.username, user, sizeof(cfg.username) - 1);
382         cfg.username[sizeof(cfg.username) - 1] = '\0';
383     } else if (cfg.username[0] == '\0') {
384         user = get_username();
385         if (!user)
386             bump("Empty user name");
387         else {
388             if (verbose)
389                 tell_user(stderr, "Guessing user name: %s", user);
390             strncpy(cfg.username, user, sizeof(cfg.username) - 1);
391             cfg.username[sizeof(cfg.username) - 1] = '\0';
392             sfree(user);
393         }
394     }
395
396     /*
397      * Disable scary things which shouldn't be enabled for simple
398      * things like SCP and SFTP: agent forwarding, port forwarding,
399      * X forwarding.
400      */
401     cfg.x11_forward = 0;
402     cfg.agentfwd = 0;
403     cfg.portfwd[0] = cfg.portfwd[1] = '\0';
404
405     /*
406      * Attempt to start the SFTP subsystem as a first choice,
407      * falling back to the provided scp command if that fails.
408      */
409     strcpy(cfg.remote_cmd, "sftp");
410     cfg.ssh_subsys = TRUE;
411     cfg.remote_cmd_ptr2 = cmd;
412     cfg.ssh_subsys2 = FALSE;
413     cfg.nopty = TRUE;
414
415     back = &ssh_backend;
416
417     err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0);
418     if (err != NULL)
419         bump("ssh_init: %s", err);
420     logctx = log_init(NULL, &cfg);
421     back->provide_logctx(backhandle, logctx);
422     console_provide_logctx(logctx);
423     ssh_scp_init();
424     if (verbose && realhost != NULL)
425         tell_user(stderr, "Connected to %s\n", realhost);
426     sfree(realhost);
427 }
428
429 /*
430  *  Update statistic information about current file.
431  */
432 static void print_stats(char *name, unsigned long size, unsigned long done,
433                         time_t start, time_t now)
434 {
435     float ratebs;
436     unsigned long eta;
437     char etastr[10];
438     int pct;
439     int len;
440     int elap;
441
442     elap = (unsigned long) difftime(now, start);
443
444     if (now > start)
445         ratebs = (float) done / elap;
446     else
447         ratebs = (float) done;
448
449     if (ratebs < 1.0)
450         eta = size - done;
451     else
452         eta = (unsigned long) ((size - done) / ratebs);
453     sprintf(etastr, "%02ld:%02ld:%02ld",
454             eta / 3600, (eta % 3600) / 60, eta % 60);
455
456     pct = (int) (100 * (done * 1.0 / size));
457
458     if (gui_mode) {
459         gui_update_stats(name, size, pct, elap, done, eta, 
460                          (unsigned long) ratebs);
461     } else {
462         len = printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%",
463                      name, done / 1024, ratebs / 1024.0, etastr, pct);
464         if (len < prev_stats_len)
465             printf("%*s", prev_stats_len - len, "");
466         prev_stats_len = len;
467
468         if (done == size)
469             printf("\n");
470     }
471 }
472
473 /*
474  *  Find a colon in str and return a pointer to the colon.
475  *  This is used to separate hostname from filename.
476  */
477 static char *colon(char *str)
478 {
479     /* We ignore a leading colon, since the hostname cannot be
480        empty. We also ignore a colon as second character because
481        of filenames like f:myfile.txt. */
482     if (str[0] == '\0' || str[0] == ':' || str[1] == ':')
483         return (NULL);
484     while (*str != '\0' && *str != ':' && *str != '/' && *str != '\\')
485         str++;
486     if (*str == ':')
487         return (str);
488     else
489         return (NULL);
490 }
491
492 /*
493  * Return a pointer to the portion of str that comes after the last
494  * slash (or backslash or colon, if `local' is TRUE).
495  */
496 static char *stripslashes(char *str, int local)
497 {
498     char *p;
499
500     if (local) {
501         p = strchr(str, ':');
502         if (p) str = p+1;
503     }
504
505     p = strrchr(str, '/');
506     if (p) str = p+1;
507
508     if (local) {
509         p = strrchr(str, '\\');
510         if (p) str = p+1;
511     }
512
513     return str;
514 }
515
516 /*
517  * Determine whether a string is entirely composed of dots.
518  */
519 static int is_dots(char *str)
520 {
521     return str[strspn(str, ".")] == '\0';
522 }
523
524 /*
525  *  Wait for a response from the other side.
526  *  Return 0 if ok, -1 if error.
527  */
528 static int response(void)
529 {
530     char ch, resp, rbuf[2048];
531     int p;
532
533     if (ssh_scp_recv(&resp, 1) <= 0)
534         bump("Lost connection");
535
536     p = 0;
537     switch (resp) {
538       case 0:                          /* ok */
539         return (0);
540       default:
541         rbuf[p++] = resp;
542         /* fallthrough */
543       case 1:                          /* error */
544       case 2:                          /* fatal error */
545         do {
546             if (ssh_scp_recv(&ch, 1) <= 0)
547                 bump("Protocol error: Lost connection");
548             rbuf[p++] = ch;
549         } while (p < sizeof(rbuf) && ch != '\n');
550         rbuf[p - 1] = '\0';
551         if (resp == 1)
552             tell_user(stderr, "%s\n", rbuf);
553         else
554             bump("%s", rbuf);
555         errs++;
556         return (-1);
557     }
558 }
559
560 int sftp_recvdata(char *buf, int len)
561 {
562     return ssh_scp_recv(buf, len);
563 }
564 int sftp_senddata(char *buf, int len)
565 {
566     back->send(backhandle, (unsigned char *) buf, len);
567     return 1;
568 }
569
570 /* ----------------------------------------------------------------------
571  * sftp-based replacement for the hacky `pscp -ls'.
572  */
573 static int sftp_ls_compare(const void *av, const void *bv)
574 {
575     const struct fxp_name *a = (const struct fxp_name *) av;
576     const struct fxp_name *b = (const struct fxp_name *) bv;
577     return strcmp(a->filename, b->filename);
578 }
579 void scp_sftp_listdir(char *dirname)
580 {
581     struct fxp_handle *dirh;
582     struct fxp_names *names;
583     struct fxp_name *ournames;
584     struct sftp_packet *pktin;
585     struct sftp_request *req, *rreq;
586     int nnames, namesize;
587     int i;
588
589     if (!fxp_init()) {
590         tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
591         errs++;
592         return;
593     }
594
595     printf("Listing directory %s\n", dirname);
596
597     sftp_register(req = fxp_opendir_send(dirname));
598     rreq = sftp_find_request(pktin = sftp_recv());
599     assert(rreq == req);
600     dirh = fxp_opendir_recv(pktin, rreq);
601
602     if (dirh == NULL) {
603         printf("Unable to open %s: %s\n", dirname, fxp_error());
604     } else {
605         nnames = namesize = 0;
606         ournames = NULL;
607
608         while (1) {
609
610             sftp_register(req = fxp_readdir_send(dirh));
611             rreq = sftp_find_request(pktin = sftp_recv());
612             assert(rreq == req);
613             names = fxp_readdir_recv(pktin, rreq);
614
615             if (names == NULL) {
616                 if (fxp_error_type() == SSH_FX_EOF)
617                     break;
618                 printf("Reading directory %s: %s\n", dirname, fxp_error());
619                 break;
620             }
621             if (names->nnames == 0) {
622                 fxp_free_names(names);
623                 break;
624             }
625
626             if (nnames + names->nnames >= namesize) {
627                 namesize += names->nnames + 128;
628                 ournames = sresize(ournames, namesize, struct fxp_name);
629             }
630
631             for (i = 0; i < names->nnames; i++)
632                 ournames[nnames++] = names->names[i];
633
634             names->nnames = 0;         /* prevent free_names */
635             fxp_free_names(names);
636         }
637         sftp_register(req = fxp_close_send(dirh));
638         rreq = sftp_find_request(pktin = sftp_recv());
639         assert(rreq == req);
640         fxp_close_recv(pktin, rreq);
641
642         /*
643          * Now we have our filenames. Sort them by actual file
644          * name, and then output the longname parts.
645          */
646         qsort(ournames, nnames, sizeof(*ournames), sftp_ls_compare);
647
648         /*
649          * And print them.
650          */
651         for (i = 0; i < nnames; i++)
652             printf("%s\n", ournames[i].longname);
653     }
654 }
655
656 /* ----------------------------------------------------------------------
657  * Helper routines that contain the actual SCP protocol elements,
658  * implemented both as SCP1 and SFTP.
659  */
660
661 static struct scp_sftp_dirstack {
662     struct scp_sftp_dirstack *next;
663     struct fxp_name *names;
664     int namepos, namelen;
665     char *dirpath;
666     char *wildcard;
667     int matched_something;             /* wildcard match set was non-empty */
668 } *scp_sftp_dirstack_head;
669 static char *scp_sftp_remotepath, *scp_sftp_currentname;
670 static char *scp_sftp_wildcard;
671 static int scp_sftp_targetisdir, scp_sftp_donethistarget;
672 static int scp_sftp_preserve, scp_sftp_recursive;
673 static unsigned long scp_sftp_mtime, scp_sftp_atime;
674 static int scp_has_times;
675 static struct fxp_handle *scp_sftp_filehandle;
676 static uint64 scp_sftp_fileoffset;
677
678 void scp_source_setup(char *target, int shouldbedir)
679 {
680     if (using_sftp) {
681         /*
682          * Find out whether the target filespec is in fact a
683          * directory.
684          */
685         struct sftp_packet *pktin;
686         struct sftp_request *req, *rreq;
687         struct fxp_attrs attrs;
688         int ret;
689
690         if (!fxp_init()) {
691             tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
692             errs++;
693             return;
694         }
695
696         sftp_register(req = fxp_stat_send(target));
697         rreq = sftp_find_request(pktin = sftp_recv());
698         assert(rreq == req);
699         ret = fxp_stat_recv(pktin, rreq, &attrs);
700
701         if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS))
702             scp_sftp_targetisdir = 0;
703         else
704             scp_sftp_targetisdir = (attrs.permissions & 0040000) != 0;
705
706         if (shouldbedir && !scp_sftp_targetisdir) {
707             bump("pscp: remote filespec %s: not a directory\n", target);
708         }
709
710         scp_sftp_remotepath = dupstr(target);
711
712         scp_has_times = 0;
713     } else {
714         (void) response();
715     }
716 }
717
718 int scp_send_errmsg(char *str)
719 {
720     if (using_sftp) {
721         /* do nothing; we never need to send our errors to the server */
722     } else {
723         back->send(backhandle, "\001", 1);/* scp protocol error prefix */
724         back->send(backhandle, str, strlen(str));
725     }
726     return 0;                          /* can't fail */
727 }
728
729 int scp_send_filetimes(unsigned long mtime, unsigned long atime)
730 {
731     if (using_sftp) {
732         scp_sftp_mtime = mtime;
733         scp_sftp_atime = atime;
734         scp_has_times = 1;
735         return 0;
736     } else {
737         char buf[80];
738         sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime);
739         back->send(backhandle, buf, strlen(buf));
740         return response();
741     }
742 }
743
744 int scp_send_filename(char *name, unsigned long size, int modes)
745 {
746     if (using_sftp) {
747         char *fullname;
748         struct sftp_packet *pktin;
749         struct sftp_request *req, *rreq;
750
751         if (scp_sftp_targetisdir) {
752             fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);
753         } else {
754             fullname = dupstr(scp_sftp_remotepath);
755         }
756
757         sftp_register(req = fxp_open_send(fullname, SSH_FXF_WRITE |
758                                           SSH_FXF_CREAT | SSH_FXF_TRUNC));
759         rreq = sftp_find_request(pktin = sftp_recv());
760         assert(rreq == req);
761         scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
762
763         if (!scp_sftp_filehandle) {
764             tell_user(stderr, "pscp: unable to open %s: %s",
765                       fullname, fxp_error());
766             errs++;
767             return 1;
768         }
769         scp_sftp_fileoffset = uint64_make(0, 0);
770         sfree(fullname);
771         return 0;
772     } else {
773         char buf[40];
774         sprintf(buf, "C%04o %lu ", modes, size);
775         back->send(backhandle, buf, strlen(buf));
776         back->send(backhandle, name, strlen(name));
777         back->send(backhandle, "\n", 1);
778         return response();
779     }
780 }
781
782 int scp_send_filedata(char *data, int len)
783 {
784     if (using_sftp) {
785         int ret;
786         struct sftp_packet *pktin;
787         struct sftp_request *req, *rreq;
788
789         if (!scp_sftp_filehandle) {
790             return 1;
791         }
792
793         sftp_register(req = fxp_write_send(scp_sftp_filehandle,
794                                            data, scp_sftp_fileoffset, len));
795         rreq = sftp_find_request(pktin = sftp_recv());
796         assert(rreq == req);
797         ret = fxp_write_recv(pktin, rreq);
798
799         if (!ret) {
800             tell_user(stderr, "error while writing: %s\n", fxp_error());
801             errs++;
802             return 1;
803         }
804         scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);
805         return 0;
806     } else {
807         int bufsize = back->send(backhandle, data, len);
808
809         /*
810          * If the network transfer is backing up - that is, the
811          * remote site is not accepting data as fast as we can
812          * produce it - then we must loop on network events until
813          * we have space in the buffer again.
814          */
815         while (bufsize > MAX_SCP_BUFSIZE) {
816             if (ssh_sftp_loop_iteration() < 0)
817                 return 1;
818             bufsize = back->sendbuffer(backhandle);
819         }
820
821         return 0;
822     }
823 }
824
825 int scp_send_finish(void)
826 {
827     if (using_sftp) {
828         struct fxp_attrs attrs;
829         struct sftp_packet *pktin;
830         struct sftp_request *req, *rreq;
831         int ret;
832
833         if (!scp_sftp_filehandle) {
834             return 1;
835         }
836         if (scp_has_times) {
837             attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME;
838             attrs.atime = scp_sftp_atime;
839             attrs.mtime = scp_sftp_mtime;
840             sftp_register(req = fxp_fsetstat_send(scp_sftp_filehandle, attrs));
841             rreq = sftp_find_request(pktin = sftp_recv());
842             assert(rreq == req);
843             ret = fxp_fsetstat_recv(pktin, rreq);
844             if (!ret) {
845                 tell_user(stderr, "unable to set file times: %s\n", fxp_error());
846                 errs++;
847             }
848         }
849         sftp_register(req = fxp_close_send(scp_sftp_filehandle));
850         rreq = sftp_find_request(pktin = sftp_recv());
851         assert(rreq == req);
852         fxp_close_recv(pktin, rreq);
853         scp_has_times = 0;
854         return 0;
855     } else {
856         back->send(backhandle, "", 1);
857         return response();
858     }
859 }
860
861 char *scp_save_remotepath(void)
862 {
863     if (using_sftp)
864         return scp_sftp_remotepath;
865     else
866         return NULL;
867 }
868
869 void scp_restore_remotepath(char *data)
870 {
871     if (using_sftp)
872         scp_sftp_remotepath = data;
873 }
874
875 int scp_send_dirname(char *name, int modes)
876 {
877     if (using_sftp) {
878         char *fullname;
879         char const *err;
880         struct fxp_attrs attrs;
881         struct sftp_packet *pktin;
882         struct sftp_request *req, *rreq;
883         int ret;
884
885         if (scp_sftp_targetisdir) {
886             fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);
887         } else {
888             fullname = dupstr(scp_sftp_remotepath);
889         }
890
891         /*
892          * We don't worry about whether we managed to create the
893          * directory, because if it exists already it's OK just to
894          * use it. Instead, we will stat it afterwards, and if it
895          * exists and is a directory we will assume we were either
896          * successful or it didn't matter.
897          */
898         sftp_register(req = fxp_mkdir_send(fullname));
899         rreq = sftp_find_request(pktin = sftp_recv());
900         assert(rreq == req);
901         ret = fxp_mkdir_recv(pktin, rreq);
902
903         if (!ret)
904             err = fxp_error();
905         else
906             err = "server reported no error";
907
908         sftp_register(req = fxp_stat_send(fullname));
909         rreq = sftp_find_request(pktin = sftp_recv());
910         assert(rreq == req);
911         ret = fxp_stat_recv(pktin, rreq, &attrs);
912
913         if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
914             !(attrs.permissions & 0040000)) {
915             tell_user(stderr, "unable to create directory %s: %s",
916                       fullname, err);
917             errs++;
918             return 1;
919         }
920
921         scp_sftp_remotepath = fullname;
922
923         return 0;
924     } else {
925         char buf[40];
926         sprintf(buf, "D%04o 0 ", modes);
927         back->send(backhandle, buf, strlen(buf));
928         back->send(backhandle, name, strlen(name));
929         back->send(backhandle, "\n", 1);
930         return response();
931     }
932 }
933
934 int scp_send_enddir(void)
935 {
936     if (using_sftp) {
937         sfree(scp_sftp_remotepath);
938         return 0;
939     } else {
940         back->send(backhandle, "E\n", 2);
941         return response();
942     }
943 }
944
945 /*
946  * Yes, I know; I have an scp_sink_setup _and_ an scp_sink_init.
947  * That's bad. The difference is that scp_sink_setup is called once
948  * right at the start, whereas scp_sink_init is called to
949  * initialise every level of recursion in the protocol.
950  */
951 int scp_sink_setup(char *source, int preserve, int recursive)
952 {
953     if (using_sftp) {
954         char *newsource;
955
956         if (!fxp_init()) {
957             tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
958             errs++;
959             return 1;
960         }
961         /*
962          * It's possible that the source string we've been given
963          * contains a wildcard. If so, we must split the directory
964          * away from the wildcard itself (throwing an error if any
965          * wildcardness comes before the final slash) and arrange
966          * things so that a dirstack entry will be set up.
967          */
968         newsource = snewn(1+strlen(source), char);
969         if (!wc_unescape(newsource, source)) {
970             /* Yes, here we go; it's a wildcard. Bah. */
971             char *dupsource, *lastpart, *dirpart, *wildcard;
972             dupsource = dupstr(source);
973             lastpart = stripslashes(dupsource, 0);
974             wildcard = dupstr(lastpart);
975             *lastpart = '\0';
976             if (*dupsource && dupsource[1]) {
977                 /*
978                  * The remains of dupsource are at least two
979                  * characters long, meaning the pathname wasn't
980                  * empty or just `/'. Hence, we remove the trailing
981                  * slash.
982                  */
983                 lastpart[-1] = '\0';
984             } else if (!*dupsource) {
985                 /*
986                  * The remains of dupsource are _empty_ - the whole
987                  * pathname was a wildcard. Hence we need to
988                  * replace it with ".".
989                  */
990                 sfree(dupsource);
991                 dupsource = dupstr(".");
992             }
993
994             /*
995              * Now we have separated our string into dupsource (the
996              * directory part) and wildcard. Both of these will
997              * need freeing at some point. Next step is to remove
998              * wildcard escapes from the directory part, throwing
999              * an error if it contains a real wildcard.
1000              */
1001             dirpart = snewn(1+strlen(dupsource), char);
1002             if (!wc_unescape(dirpart, dupsource)) {
1003                 tell_user(stderr, "%s: multiple-level wildcards unsupported",
1004                           source);
1005                 errs++;
1006                 sfree(dirpart);
1007                 sfree(wildcard);
1008                 sfree(dupsource);
1009                 return 1;
1010             }
1011
1012             /*
1013              * Now we have dirpart (unescaped, ie a valid remote
1014              * path), and wildcard (a wildcard). This will be
1015              * sufficient to arrange a dirstack entry.
1016              */
1017             scp_sftp_remotepath = dirpart;
1018             scp_sftp_wildcard = wildcard;
1019             sfree(dupsource);
1020         } else {
1021             scp_sftp_remotepath = newsource;
1022             scp_sftp_wildcard = NULL;
1023         }
1024         scp_sftp_preserve = preserve;
1025         scp_sftp_recursive = recursive;
1026         scp_sftp_donethistarget = 0;
1027         scp_sftp_dirstack_head = NULL;
1028     }
1029     return 0;
1030 }
1031
1032 int scp_sink_init(void)
1033 {
1034     if (!using_sftp) {
1035         back->send(backhandle, "", 1);
1036     }
1037     return 0;
1038 }
1039
1040 #define SCP_SINK_FILE   1
1041 #define SCP_SINK_DIR    2
1042 #define SCP_SINK_ENDDIR 3
1043 #define SCP_SINK_RETRY  4              /* not an action; just try again */
1044 struct scp_sink_action {
1045     int action;                        /* FILE, DIR, ENDDIR */
1046     char *buf;                         /* will need freeing after use */
1047     char *name;                        /* filename or dirname (not ENDDIR) */
1048     int mode;                          /* access mode (not ENDDIR) */
1049     unsigned long size;                /* file size (not ENDDIR) */
1050     int settime;                       /* 1 if atime and mtime are filled */
1051     unsigned long atime, mtime;        /* access times for the file */
1052 };
1053
1054 int scp_get_sink_action(struct scp_sink_action *act)
1055 {
1056     if (using_sftp) {
1057         char *fname;
1058         int must_free_fname;
1059         struct fxp_attrs attrs;
1060         struct sftp_packet *pktin;
1061         struct sftp_request *req, *rreq;
1062         int ret;
1063
1064         if (!scp_sftp_dirstack_head) {
1065             if (!scp_sftp_donethistarget) {
1066                 /*
1067                  * Simple case: we are only dealing with one file.
1068                  */
1069                 fname = scp_sftp_remotepath;
1070                 must_free_fname = 0;
1071                 scp_sftp_donethistarget = 1;
1072             } else {
1073                 /*
1074                  * Even simpler case: one file _which we've done_.
1075                  * Return 1 (finished).
1076                  */
1077                 return 1;
1078             }
1079         } else {
1080             /*
1081              * We're now in the middle of stepping through a list
1082              * of names returned from fxp_readdir(); so let's carry
1083              * on.
1084              */
1085             struct scp_sftp_dirstack *head = scp_sftp_dirstack_head;
1086             while (head->namepos < head->namelen &&
1087                    (is_dots(head->names[head->namepos].filename) ||
1088                     (head->wildcard &&
1089                      !wc_match(head->wildcard,
1090                                head->names[head->namepos].filename))))
1091                 head->namepos++;       /* skip . and .. */
1092             if (head->namepos < head->namelen) {
1093                 head->matched_something = 1;
1094                 fname = dupcat(head->dirpath, "/",
1095                                head->names[head->namepos++].filename,
1096                                NULL);
1097                 must_free_fname = 1;
1098             } else {
1099                 /*
1100                  * We've come to the end of the list; pop it off
1101                  * the stack and return an ENDDIR action (or RETRY
1102                  * if this was a wildcard match).
1103                  */
1104                 if (head->wildcard) {
1105                     act->action = SCP_SINK_RETRY;
1106                     if (!head->matched_something) {
1107                         tell_user(stderr, "pscp: wildcard '%s' matched "
1108                                   "no files", head->wildcard);
1109                         errs++;
1110                     }
1111                     sfree(head->wildcard);
1112
1113                 } else {
1114                     act->action = SCP_SINK_ENDDIR;
1115                 }
1116
1117                 sfree(head->dirpath);
1118                 sfree(head->names);
1119                 scp_sftp_dirstack_head = head->next;
1120                 sfree(head);
1121
1122                 return 0;
1123             }
1124         }
1125
1126         /*
1127          * Now we have a filename. Stat it, and see if it's a file
1128          * or a directory.
1129          */
1130         sftp_register(req = fxp_stat_send(fname));
1131         rreq = sftp_find_request(pktin = sftp_recv());
1132         assert(rreq == req);
1133         ret = fxp_stat_recv(pktin, rreq, &attrs);
1134
1135         if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
1136             tell_user(stderr, "unable to identify %s: %s", fname,
1137                       ret ? "file type not supplied" : fxp_error());
1138             errs++;
1139             return 1;
1140         }
1141
1142         if (attrs.permissions & 0040000) {
1143             struct scp_sftp_dirstack *newitem;
1144             struct fxp_handle *dirhandle;
1145             int nnames, namesize;
1146             struct fxp_name *ournames;
1147             struct fxp_names *names;
1148
1149             /*
1150              * It's a directory. If we're not in recursive mode,
1151              * this merits a complaint (which is fatal if the name
1152              * was specified directly, but not if it was matched by
1153              * a wildcard).
1154              * 
1155              * We skip this complaint completely if
1156              * scp_sftp_wildcard is set, because that's an
1157              * indication that we're not actually supposed to
1158              * _recursively_ transfer the dir, just scan it for
1159              * things matching the wildcard.
1160              */
1161             if (!scp_sftp_recursive && !scp_sftp_wildcard) {
1162                 tell_user(stderr, "pscp: %s: is a directory", fname);
1163                 errs++;
1164                 if (must_free_fname) sfree(fname);
1165                 if (scp_sftp_dirstack_head) {
1166                     act->action = SCP_SINK_RETRY;
1167                     return 0;
1168                 } else {
1169                     return 1;
1170                 }
1171             }
1172
1173             /*
1174              * Otherwise, the fun begins. We must fxp_opendir() the
1175              * directory, slurp the filenames into memory, return
1176              * SCP_SINK_DIR (unless this is a wildcard match), and
1177              * set targetisdir. The next time we're called, we will
1178              * run through the list of filenames one by one,
1179              * matching them against a wildcard if present.
1180              * 
1181              * If targetisdir is _already_ set (meaning we're
1182              * already in the middle of going through another such
1183              * list), we must push the other (target,namelist) pair
1184              * on a stack.
1185              */
1186             sftp_register(req = fxp_opendir_send(fname));
1187             rreq = sftp_find_request(pktin = sftp_recv());
1188             assert(rreq == req);
1189             dirhandle = fxp_opendir_recv(pktin, rreq);
1190
1191             if (!dirhandle) {
1192                 tell_user(stderr, "scp: unable to open directory %s: %s",
1193                           fname, fxp_error());
1194                 if (must_free_fname) sfree(fname);
1195                 errs++;
1196                 return 1;
1197             }
1198             nnames = namesize = 0;
1199             ournames = NULL;
1200             while (1) {
1201                 int i;
1202
1203                 sftp_register(req = fxp_readdir_send(dirhandle));
1204                 rreq = sftp_find_request(pktin = sftp_recv());
1205                 assert(rreq == req);
1206                 names = fxp_readdir_recv(pktin, rreq);
1207
1208                 if (names == NULL) {
1209                     if (fxp_error_type() == SSH_FX_EOF)
1210                         break;
1211                     tell_user(stderr, "scp: reading directory %s: %s\n",
1212                               fname, fxp_error());
1213                     if (must_free_fname) sfree(fname);
1214                     sfree(ournames);
1215                     errs++;
1216                     return 1;
1217                 }
1218                 if (names->nnames == 0) {
1219                     fxp_free_names(names);
1220                     break;
1221                 }
1222                 if (nnames + names->nnames >= namesize) {
1223                     namesize += names->nnames + 128;
1224                     ournames = sresize(ournames, namesize, struct fxp_name);
1225                 }
1226                 for (i = 0; i < names->nnames; i++)
1227                     ournames[nnames++] = names->names[i];
1228                 names->nnames = 0;             /* prevent free_names */
1229                 fxp_free_names(names);
1230             }
1231             sftp_register(req = fxp_close_send(dirhandle));
1232             rreq = sftp_find_request(pktin = sftp_recv());
1233             assert(rreq == req);
1234             fxp_close_recv(pktin, rreq);
1235
1236             newitem = snew(struct scp_sftp_dirstack);
1237             newitem->next = scp_sftp_dirstack_head;
1238             newitem->names = ournames;
1239             newitem->namepos = 0;
1240             newitem->namelen = nnames;
1241             if (must_free_fname)
1242                 newitem->dirpath = fname;
1243             else
1244                 newitem->dirpath = dupstr(fname);
1245             if (scp_sftp_wildcard) {
1246                 newitem->wildcard = scp_sftp_wildcard;
1247                 newitem->matched_something = 0;
1248                 scp_sftp_wildcard = NULL;
1249             } else {
1250                 newitem->wildcard = NULL;
1251             }
1252             scp_sftp_dirstack_head = newitem;
1253
1254             if (newitem->wildcard) {
1255                 act->action = SCP_SINK_RETRY;
1256             } else {
1257                 act->action = SCP_SINK_DIR;
1258                 act->buf = dupstr(stripslashes(fname, 0));
1259                 act->name = act->buf;
1260                 act->size = 0;         /* duhh, it's a directory */
1261                 act->mode = 07777 & attrs.permissions;
1262                 if (scp_sftp_preserve &&
1263                     (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
1264                     act->atime = attrs.atime;
1265                     act->mtime = attrs.mtime;
1266                     act->settime = 1;
1267                 } else
1268                     act->settime = 0;
1269             }
1270             return 0;
1271
1272         } else {
1273             /*
1274              * It's a file. Return SCP_SINK_FILE.
1275              */
1276             act->action = SCP_SINK_FILE;
1277             act->buf = dupstr(stripslashes(fname, 0));
1278             act->name = act->buf;
1279             if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {
1280                 if (uint64_compare(attrs.size,
1281                                    uint64_make(0, ULONG_MAX)) > 0) {
1282                     act->size = ULONG_MAX;   /* *boggle* */
1283                 } else
1284                     act->size = attrs.size.lo;
1285             } else
1286                 act->size = ULONG_MAX;   /* no idea */
1287             act->mode = 07777 & attrs.permissions;
1288             if (scp_sftp_preserve &&
1289                 (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
1290                 act->atime = attrs.atime;
1291                 act->mtime = attrs.mtime;
1292                 act->settime = 1;
1293             } else
1294                 act->settime = 0;
1295             if (must_free_fname)
1296                 scp_sftp_currentname = fname;
1297             else
1298                 scp_sftp_currentname = dupstr(fname);
1299             return 0;
1300         }
1301
1302     } else {
1303         int done = 0;
1304         int i, bufsize;
1305         int action;
1306         char ch;
1307
1308         act->settime = 0;
1309         act->buf = NULL;
1310         bufsize = 0;
1311
1312         while (!done) {
1313             if (ssh_scp_recv(&ch, 1) <= 0)
1314                 return 1;
1315             if (ch == '\n')
1316                 bump("Protocol error: Unexpected newline");
1317             i = 0;
1318             action = ch;
1319             do {
1320                 if (ssh_scp_recv(&ch, 1) <= 0)
1321                     bump("Lost connection");
1322                 if (i >= bufsize) {
1323                     bufsize = i + 128;
1324                     act->buf = sresize(act->buf, bufsize, char);
1325                 }
1326                 act->buf[i++] = ch;
1327             } while (ch != '\n');
1328             act->buf[i - 1] = '\0';
1329             switch (action) {
1330               case '\01':                      /* error */
1331                 tell_user(stderr, "%s\n", act->buf);
1332                 errs++;
1333                 continue;                      /* go round again */
1334               case '\02':                      /* fatal error */
1335                 bump("%s", act->buf);
1336               case 'E':
1337                 back->send(backhandle, "", 1);
1338                 act->action = SCP_SINK_ENDDIR;
1339                 return 0;
1340               case 'T':
1341                 if (sscanf(act->buf, "%ld %*d %ld %*d",
1342                            &act->mtime, &act->atime) == 2) {
1343                     act->settime = 1;
1344                     back->send(backhandle, "", 1);
1345                     continue;          /* go round again */
1346                 }
1347                 bump("Protocol error: Illegal time format");
1348               case 'C':
1349               case 'D':
1350                 act->action = (action == 'C' ? SCP_SINK_FILE : SCP_SINK_DIR);
1351                 break;
1352               default:
1353                 bump("Protocol error: Expected control record");
1354             }
1355             /*
1356              * We will go round this loop only once, unless we hit
1357              * `continue' above.
1358              */
1359             done = 1;
1360         }
1361
1362         /*
1363          * If we get here, we must have seen SCP_SINK_FILE or
1364          * SCP_SINK_DIR.
1365          */
1366         if (sscanf(act->buf, "%o %lu %n", &act->mode, &act->size, &i) != 2)
1367             bump("Protocol error: Illegal file descriptor format");
1368         act->name = act->buf + i;
1369         return 0;
1370     }
1371 }
1372
1373 int scp_accept_filexfer(void)
1374 {
1375     if (using_sftp) {
1376         struct sftp_packet *pktin;
1377         struct sftp_request *req, *rreq;
1378
1379         sftp_register(req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ));
1380         rreq = sftp_find_request(pktin = sftp_recv());
1381         assert(rreq == req);
1382         scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
1383
1384         if (!scp_sftp_filehandle) {
1385             tell_user(stderr, "pscp: unable to open %s: %s",
1386                       scp_sftp_currentname, fxp_error());
1387             errs++;
1388             return 1;
1389         }
1390         scp_sftp_fileoffset = uint64_make(0, 0);
1391         sfree(scp_sftp_currentname);
1392         return 0;
1393     } else {
1394         back->send(backhandle, "", 1);
1395         return 0;                      /* can't fail */
1396     }
1397 }
1398
1399 int scp_recv_filedata(char *data, int len)
1400 {
1401     if (using_sftp) {
1402         struct sftp_packet *pktin;
1403         struct sftp_request *req, *rreq;
1404         int actuallen;
1405
1406         sftp_register(req = fxp_read_send(scp_sftp_filehandle,
1407                                           scp_sftp_fileoffset, len));
1408         rreq = sftp_find_request(pktin = sftp_recv());
1409         assert(rreq == req);
1410         actuallen = fxp_read_recv(pktin, rreq, data, len);
1411
1412         if (actuallen == -1 && fxp_error_type() != SSH_FX_EOF) {
1413             tell_user(stderr, "pscp: error while reading: %s", fxp_error());
1414             errs++;
1415             return -1;
1416         }
1417         if (actuallen < 0)
1418             actuallen = 0;
1419
1420         scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, actuallen);
1421
1422         return actuallen;
1423     } else {
1424         return ssh_scp_recv(data, len);
1425     }
1426 }
1427
1428 int scp_finish_filerecv(void)
1429 {
1430     if (using_sftp) {
1431         struct sftp_packet *pktin;
1432         struct sftp_request *req, *rreq;
1433
1434         sftp_register(req = fxp_close_send(scp_sftp_filehandle));
1435         rreq = sftp_find_request(pktin = sftp_recv());
1436         assert(rreq == req);
1437         fxp_close_recv(pktin, rreq);
1438         return 0;
1439     } else {
1440         back->send(backhandle, "", 1);
1441         return response();
1442     }
1443 }
1444
1445 /* ----------------------------------------------------------------------
1446  *  Send an error message to the other side and to the screen.
1447  *  Increment error counter.
1448  */
1449 static void run_err(const char *fmt, ...)
1450 {
1451     char *str, *str2;
1452     va_list ap;
1453     va_start(ap, fmt);
1454     errs++;
1455     str = dupvprintf(fmt, ap);
1456     str2 = dupcat("scp: ", str, "\n", NULL);
1457     sfree(str);
1458     scp_send_errmsg(str2);
1459     tell_user(stderr, "%s", str2);
1460     va_end(ap);
1461     sfree(str2);
1462 }
1463
1464 /*
1465  *  Execute the source part of the SCP protocol.
1466  */
1467 static void source(char *src)
1468 {
1469     unsigned long size;
1470     unsigned long mtime, atime;
1471     char *last;
1472     RFile *f;
1473     int attr;
1474     unsigned long i;
1475     unsigned long stat_bytes;
1476     time_t stat_starttime, stat_lasttime;
1477
1478     attr = file_type(src);
1479     if (attr == FILE_TYPE_NONEXISTENT ||
1480         attr == FILE_TYPE_WEIRD) {
1481         run_err("%s: %s file or directory", src,
1482                 (attr == FILE_TYPE_WEIRD ? "Not a" : "No such"));
1483         return;
1484     }
1485
1486     if (attr == FILE_TYPE_DIRECTORY) {
1487         if (recursive) {
1488             /*
1489              * Avoid . and .. directories.
1490              */
1491             char *p;
1492             p = strrchr(src, '/');
1493             if (!p)
1494                 p = strrchr(src, '\\');
1495             if (!p)
1496                 p = src;
1497             else
1498                 p++;
1499             if (!strcmp(p, ".") || !strcmp(p, ".."))
1500                 /* skip . and .. */ ;
1501             else
1502                 rsource(src);
1503         } else {
1504             run_err("%s: not a regular file", src);
1505         }
1506         return;
1507     }
1508
1509     if ((last = strrchr(src, '/')) == NULL)
1510         last = src;
1511     else
1512         last++;
1513     if (strrchr(last, '\\') != NULL)
1514         last = strrchr(last, '\\') + 1;
1515     if (last == src && strchr(src, ':') != NULL)
1516         last = strchr(src, ':') + 1;
1517
1518     f = open_existing_file(src, &size, &mtime, &atime);
1519     if (f == NULL) {
1520         run_err("%s: Cannot open file", src);
1521         return;
1522     }
1523     if (preserve) {
1524         if (scp_send_filetimes(mtime, atime))
1525             return;
1526     }
1527
1528     if (verbose)
1529         tell_user(stderr, "Sending file %s, size=%lu", last, size);
1530     if (scp_send_filename(last, size, 0644))
1531         return;
1532
1533     stat_bytes = 0;
1534     stat_starttime = time(NULL);
1535     stat_lasttime = 0;
1536
1537     for (i = 0; i < size; i += 4096) {
1538         char transbuf[4096];
1539         int j, k = 4096;
1540
1541         if (i + k > size)
1542             k = size - i;
1543         if ((j = read_from_file(f, transbuf, k)) != k) {
1544             if (statistics)
1545                 printf("\n");
1546             bump("%s: Read error", src);
1547         }
1548         if (scp_send_filedata(transbuf, k))
1549             bump("%s: Network error occurred", src);
1550
1551         if (statistics) {
1552             stat_bytes += k;
1553             if (time(NULL) != stat_lasttime || i + k == size) {
1554                 stat_lasttime = time(NULL);
1555                 print_stats(last, size, stat_bytes,
1556                             stat_starttime, stat_lasttime);
1557             }
1558         }
1559
1560     }
1561     close_rfile(f);
1562
1563     (void) scp_send_finish();
1564 }
1565
1566 /*
1567  *  Recursively send the contents of a directory.
1568  */
1569 static void rsource(char *src)
1570 {
1571     char *last;
1572     char *save_target;
1573     DirHandle *dir;
1574
1575     if ((last = strrchr(src, '/')) == NULL)
1576         last = src;
1577     else
1578         last++;
1579     if (strrchr(last, '\\') != NULL)
1580         last = strrchr(last, '\\') + 1;
1581     if (last == src && strchr(src, ':') != NULL)
1582         last = strchr(src, ':') + 1;
1583
1584     /* maybe send filetime */
1585
1586     save_target = scp_save_remotepath();
1587
1588     if (verbose)
1589         tell_user(stderr, "Entering directory: %s", last);
1590     if (scp_send_dirname(last, 0755))
1591         return;
1592
1593     dir = open_directory(src);
1594     if (dir != NULL) {
1595         char *filename;
1596         while ((filename = read_filename(dir)) != NULL) {
1597             char *foundfile = dupcat(src, "/", filename, NULL);
1598             source(foundfile);
1599             sfree(foundfile);
1600             sfree(filename);
1601         }
1602     }
1603     close_directory(dir);
1604
1605     (void) scp_send_enddir();
1606
1607     scp_restore_remotepath(save_target);
1608 }
1609
1610 /*
1611  * Execute the sink part of the SCP protocol.
1612  */
1613 static void sink(char *targ, char *src)
1614 {
1615     char *destfname;
1616     int targisdir = 0;
1617     int exists;
1618     int attr;
1619     WFile *f;
1620     unsigned long received;
1621     int wrerror = 0;
1622     unsigned long stat_bytes;
1623     time_t stat_starttime, stat_lasttime;
1624     char *stat_name;
1625
1626     attr = file_type(targ);
1627     if (attr == FILE_TYPE_DIRECTORY)
1628         targisdir = 1;
1629
1630     if (targetshouldbedirectory && !targisdir)
1631         bump("%s: Not a directory", targ);
1632
1633     scp_sink_init();
1634     while (1) {
1635         struct scp_sink_action act;
1636         if (scp_get_sink_action(&act))
1637             return;
1638
1639         if (act.action == SCP_SINK_ENDDIR)
1640             return;
1641
1642         if (act.action == SCP_SINK_RETRY)
1643             continue;
1644
1645         if (targisdir) {
1646             /*
1647              * Prevent the remote side from maliciously writing to
1648              * files outside the target area by sending a filename
1649              * containing `../'. In fact, it shouldn't be sending
1650              * filenames with any slashes or colons in at all; so
1651              * we'll find the last slash, backslash or colon in the
1652              * filename and use only the part after that. (And
1653              * warn!)
1654              * 
1655              * In addition, we also ensure here that if we're
1656              * copying a single file and the target is a directory
1657              * (common usage: `pscp host:filename .') the remote
1658              * can't send us a _different_ file name. We can
1659              * distinguish this case because `src' will be non-NULL
1660              * and the last component of that will fail to match
1661              * (the last component of) the name sent.
1662              * 
1663              * Well, not always; if `src' is a wildcard, we do
1664              * expect to get back filenames that don't correspond
1665              * exactly to it. Ideally in this case, we would like
1666              * to ensure that the returned filename actually
1667              * matches the wildcard pattern - but one of SCP's
1668              * protocol infelicities is that wildcard matching is
1669              * done at the server end _by the server's rules_ and
1670              * so in general this is infeasible. Hence, we only
1671              * accept filenames that don't correspond to `src' if
1672              * unsafe mode is enabled or we are using SFTP (which
1673              * resolves remote wildcards on the client side and can
1674              * be trusted).
1675              */
1676             char *striptarget, *stripsrc;
1677
1678             striptarget = stripslashes(act.name, 1);
1679             if (striptarget != act.name) {
1680                 tell_user(stderr, "warning: remote host sent a compound"
1681                           " pathname '%s'", act.name);
1682                 tell_user(stderr, "         renaming local file to '%s'",
1683                           striptarget);
1684             }
1685
1686             /*
1687              * Also check to see if the target filename is '.' or
1688              * '..', or indeed '...' and so on because Windows
1689              * appears to interpret those like '..'.
1690              */
1691             if (is_dots(striptarget)) {
1692                 bump("security violation: remote host attempted to write to"
1693                      " a '.' or '..' path!");
1694             }
1695
1696             if (src) {
1697                 stripsrc = stripslashes(src, 1);
1698                 if (strcmp(striptarget, stripsrc) &&
1699                     !using_sftp && !scp_unsafe_mode) {
1700                     tell_user(stderr, "warning: remote host tried to write "
1701                               "to a file called '%s'", striptarget);
1702                     tell_user(stderr, "         when we requested a file "
1703                               "called '%s'.", stripsrc);
1704                     tell_user(stderr, "         If this is a wildcard, "
1705                               "consider upgrading to SSH 2 or using");
1706                     tell_user(stderr, "         the '-unsafe' option. Renaming"
1707                               " of this file has been disallowed.");
1708                     /* Override the name the server provided with our own. */
1709                     striptarget = stripsrc;
1710                 }
1711             }
1712
1713             if (targ[0] != '\0')
1714                 destfname = dir_file_cat(targ, striptarget);
1715             else
1716                 destfname = dupstr(striptarget);
1717         } else {
1718             /*
1719              * In this branch of the if, the target area is a
1720              * single file with an explicitly specified name in any
1721              * case, so there's no danger.
1722              */
1723             destfname = dupstr(targ);
1724         }
1725         attr = file_type(destfname);
1726         exists = (attr != FILE_TYPE_NONEXISTENT);
1727
1728         if (act.action == SCP_SINK_DIR) {
1729             if (exists && attr != FILE_TYPE_DIRECTORY) {
1730                 run_err("%s: Not a directory", destfname);
1731                 continue;
1732             }
1733             if (!exists) {
1734                 if (!create_directory(destfname)) {
1735                     run_err("%s: Cannot create directory", destfname);
1736                     continue;
1737                 }
1738             }
1739             sink(destfname, NULL);
1740             /* can we set the timestamp for directories ? */
1741             continue;
1742         }
1743
1744         f = open_new_file(destfname);
1745         if (f == NULL) {
1746             run_err("%s: Cannot create file", destfname);
1747             continue;
1748         }
1749
1750         if (scp_accept_filexfer())
1751             return;
1752
1753         stat_bytes = 0;
1754         stat_starttime = time(NULL);
1755         stat_lasttime = 0;
1756         stat_name = stripslashes(destfname, 1);
1757
1758         received = 0;
1759         while (received < act.size) {
1760             char transbuf[4096];
1761             int blksize, read;
1762             blksize = 4096;
1763             if (blksize > (int)(act.size - received))
1764                 blksize = act.size - received;
1765             read = scp_recv_filedata(transbuf, blksize);
1766             if (read <= 0)
1767                 bump("Lost connection");
1768             if (wrerror)
1769                 continue;
1770             if (write_to_file(f, transbuf, read) != (int)read) {
1771                 wrerror = 1;
1772                 /* FIXME: in sftp we can actually abort the transfer */
1773                 if (statistics)
1774                     printf("\r%-25.25s | %50s\n",
1775                            stat_name,
1776                            "Write error.. waiting for end of file");
1777                 continue;
1778             }
1779             if (statistics) {
1780                 stat_bytes += read;
1781                 if (time(NULL) > stat_lasttime ||
1782                     received + read == act.size) {
1783                     stat_lasttime = time(NULL);
1784                     print_stats(stat_name, act.size, stat_bytes,
1785                                 stat_starttime, stat_lasttime);
1786                 }
1787             }
1788             received += read;
1789         }
1790         if (act.settime) {
1791             set_file_times(f, act.mtime, act.atime);
1792         }
1793
1794         close_wfile(f);
1795         if (wrerror) {
1796             run_err("%s: Write error", destfname);
1797             continue;
1798         }
1799         (void) scp_finish_filerecv();
1800         sfree(destfname);
1801         sfree(act.buf);
1802     }
1803 }
1804
1805 /*
1806  * We will copy local files to a remote server.
1807  */
1808 static void toremote(int argc, char *argv[])
1809 {
1810     char *src, *targ, *host, *user;
1811     char *cmd;
1812     int i, wc_type;
1813
1814     targ = argv[argc - 1];
1815
1816     /* Separate host from filename */
1817     host = targ;
1818     targ = colon(targ);
1819     if (targ == NULL)
1820         bump("targ == NULL in toremote()");
1821     *targ++ = '\0';
1822     if (*targ == '\0')
1823         targ = ".";
1824     /* Substitute "." for emtpy target */
1825
1826     /* Separate host and username */
1827     user = host;
1828     host = strrchr(host, '@');
1829     if (host == NULL) {
1830         host = user;
1831         user = NULL;
1832     } else {
1833         *host++ = '\0';
1834         if (*user == '\0')
1835             user = NULL;
1836     }
1837
1838     if (argc == 2) {
1839         if (colon(argv[0]) != NULL)
1840             bump("%s: Remote to remote not supported", argv[0]);
1841
1842         wc_type = test_wildcard(argv[0], 1);
1843         if (wc_type == WCTYPE_NONEXISTENT)
1844             bump("%s: No such file or directory\n", argv[0]);
1845         else if (wc_type == WCTYPE_WILDCARD)
1846             targetshouldbedirectory = 1;
1847     }
1848
1849     cmd = dupprintf("scp%s%s%s%s -t %s",
1850                     verbose ? " -v" : "",
1851                     recursive ? " -r" : "",
1852                     preserve ? " -p" : "",
1853                     targetshouldbedirectory ? " -d" : "", targ);
1854     do_cmd(host, user, cmd);
1855     sfree(cmd);
1856
1857     scp_source_setup(targ, targetshouldbedirectory);
1858
1859     for (i = 0; i < argc - 1; i++) {
1860         src = argv[i];
1861         if (colon(src) != NULL) {
1862             tell_user(stderr, "%s: Remote to remote not supported\n", src);
1863             errs++;
1864             continue;
1865         }
1866
1867         wc_type = test_wildcard(src, 1);
1868         if (wc_type == WCTYPE_NONEXISTENT) {
1869             run_err("%s: No such file or directory", src);
1870             continue;
1871         } else if (wc_type == WCTYPE_FILENAME) {
1872             source(src);
1873             continue;
1874         } else {
1875             WildcardMatcher *wc;
1876             char *filename;
1877
1878             wc = begin_wildcard_matching(src);
1879             if (wc == NULL) {
1880                 run_err("%s: No such file or directory", src);
1881                 continue;
1882             }
1883
1884             while ((filename = wildcard_get_filename(wc)) != NULL) {
1885                 source(filename);
1886                 sfree(filename);
1887             }
1888
1889             finish_wildcard_matching(wc);
1890         }
1891     }
1892 }
1893
1894 /*
1895  *  We will copy files from a remote server to the local machine.
1896  */
1897 static void tolocal(int argc, char *argv[])
1898 {
1899     char *src, *targ, *host, *user;
1900     char *cmd;
1901
1902     if (argc != 2)
1903         bump("More than one remote source not supported");
1904
1905     src = argv[0];
1906     targ = argv[1];
1907
1908     /* Separate host from filename */
1909     host = src;
1910     src = colon(src);
1911     if (src == NULL)
1912         bump("Local to local copy not supported");
1913     *src++ = '\0';
1914     if (*src == '\0')
1915         src = ".";
1916     /* Substitute "." for empty filename */
1917
1918     /* Separate username and hostname */
1919     user = host;
1920     host = strrchr(host, '@');
1921     if (host == NULL) {
1922         host = user;
1923         user = NULL;
1924     } else {
1925         *host++ = '\0';
1926         if (*user == '\0')
1927             user = NULL;
1928     }
1929
1930     cmd = dupprintf("scp%s%s%s%s -f %s",
1931                     verbose ? " -v" : "",
1932                     recursive ? " -r" : "",
1933                     preserve ? " -p" : "",
1934                     targetshouldbedirectory ? " -d" : "", src);
1935     do_cmd(host, user, cmd);
1936     sfree(cmd);
1937
1938     if (scp_sink_setup(src, preserve, recursive))
1939         return;
1940
1941     sink(targ, src);
1942 }
1943
1944 /*
1945  *  We will issue a list command to get a remote directory.
1946  */
1947 static void get_dir_list(int argc, char *argv[])
1948 {
1949     char *src, *host, *user;
1950     char *cmd, *p, *q;
1951     char c;
1952
1953     src = argv[0];
1954
1955     /* Separate host from filename */
1956     host = src;
1957     src = colon(src);
1958     if (src == NULL)
1959         bump("Local to local copy not supported");
1960     *src++ = '\0';
1961     if (*src == '\0')
1962         src = ".";
1963     /* Substitute "." for empty filename */
1964
1965     /* Separate username and hostname */
1966     user = host;
1967     host = strrchr(host, '@');
1968     if (host == NULL) {
1969         host = user;
1970         user = NULL;
1971     } else {
1972         *host++ = '\0';
1973         if (*user == '\0')
1974             user = NULL;
1975     }
1976
1977     cmd = snewn(4 * strlen(src) + 100, char);
1978     strcpy(cmd, "ls -la '");
1979     p = cmd + strlen(cmd);
1980     for (q = src; *q; q++) {
1981         if (*q == '\'') {
1982             *p++ = '\'';
1983             *p++ = '\\';
1984             *p++ = '\'';
1985             *p++ = '\'';
1986         } else {
1987             *p++ = *q;
1988         }
1989     }
1990     *p++ = '\'';
1991     *p = '\0';
1992
1993     do_cmd(host, user, cmd);
1994     sfree(cmd);
1995
1996     if (using_sftp) {
1997         scp_sftp_listdir(src);
1998     } else {
1999         while (ssh_scp_recv(&c, 1) > 0)
2000             tell_char(stdout, c);
2001     }
2002 }
2003
2004 /*
2005  *  Short description of parameters.
2006  */
2007 static void usage(void)
2008 {
2009     printf("PuTTY Secure Copy client\n");
2010     printf("%s\n", ver);
2011     printf("Usage: pscp [options] [user@]host:source target\n");
2012     printf
2013         ("       pscp [options] source [source...] [user@]host:target\n");
2014     printf("       pscp [options] -ls user@host:filespec\n");
2015     printf("Options:\n");
2016     printf("  -p        preserve file attributes\n");
2017     printf("  -q        quiet, don't show statistics\n");
2018     printf("  -r        copy directories recursively\n");
2019     printf("  -v        show verbose messages\n");
2020     printf("  -load sessname  Load settings from saved session\n");
2021     printf("  -P port   connect to specified port\n");
2022     printf("  -l user   connect with specified username\n");
2023     printf("  -pw passw login with specified password\n");
2024     printf("  -1 -2     force use of particular SSH protocol version\n");
2025     printf("  -C        enable compression\n");
2026     printf("  -i key    private key file for authentication\n");
2027     printf("  -batch    disable all interactive prompts\n");
2028     printf("  -unsafe   allow server-side wildcards (DANGEROUS)\n");
2029 #if 0
2030     /*
2031      * -gui is an internal option, used by GUI front ends to get
2032      * pscp to pass progress reports back to them. It's not an
2033      * ordinary user-accessible option, so it shouldn't be part of
2034      * the command-line help. The only people who need to know
2035      * about it are programmers, and they can read the source.
2036      */
2037     printf
2038         ("  -gui hWnd GUI mode with the windows handle for receiving messages\n");
2039 #endif
2040     cleanup_exit(1);
2041 }
2042
2043 void cmdline_error(char *p, ...)
2044 {
2045     va_list ap;
2046     fprintf(stderr, "pscp: ");
2047     va_start(ap, p);
2048     vfprintf(stderr, p, ap);
2049     va_end(ap);
2050     fprintf(stderr, "\n      try typing just \"pscp\" for help\n");
2051     exit(1);
2052 }
2053
2054 /*
2055  * Main program. (Called `psftp_main' because it gets called from
2056  * *sftp.c; bit silly, I know, but it had to be called _something_.)
2057  */
2058 int psftp_main(int argc, char *argv[])
2059 {
2060     int i;
2061
2062     default_protocol = PROT_TELNET;
2063
2064     flags = FLAG_STDERR
2065 #ifdef FLAG_SYNCAGENT
2066         | FLAG_SYNCAGENT
2067 #endif
2068         ;
2069     cmdline_tooltype = TOOLTYPE_FILETRANSFER;
2070     ssh_get_line = &console_get_line;
2071     sk_init();
2072
2073     for (i = 1; i < argc; i++) {
2074         int ret;
2075         if (argv[i][0] != '-')
2076             break;
2077         ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, &cfg);
2078         if (ret == -2) {
2079             cmdline_error("option \"%s\" requires an argument", argv[i]);
2080         } else if (ret == 2) {
2081             i++;               /* skip next argument */
2082         } else if (ret == 1) {
2083             /* We have our own verbosity in addition to `flags'. */
2084             if (flags & FLAG_VERBOSE)
2085                 verbose = 1;
2086         } else if (strcmp(argv[i], "-r") == 0) {
2087             recursive = 1;
2088         } else if (strcmp(argv[i], "-p") == 0) {
2089             preserve = 1;
2090         } else if (strcmp(argv[i], "-q") == 0) {
2091             statistics = 0;
2092         } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) {
2093             usage();
2094         } else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {
2095             gui_enable(argv[++i]);
2096             gui_mode = 1;
2097             console_batch_mode = TRUE;
2098         } else if (strcmp(argv[i], "-ls") == 0) {
2099             list = 1;
2100         } else if (strcmp(argv[i], "-batch") == 0) {
2101             console_batch_mode = 1;
2102         } else if (strcmp(argv[i], "-unsafe") == 0) {
2103             scp_unsafe_mode = 1;
2104         } else if (strcmp(argv[i], "--") == 0) {
2105             i++;
2106             break;
2107         } else {
2108             cmdline_error("unknown option \"%s\"", argv[i]);
2109         }
2110     }
2111     argc -= i;
2112     argv += i;
2113     back = NULL;
2114
2115     if (list) {
2116         if (argc != 1)
2117             usage();
2118         get_dir_list(argc, argv);
2119
2120     } else {
2121
2122         if (argc < 2)
2123             usage();
2124         if (argc > 2)
2125             targetshouldbedirectory = 1;
2126
2127         if (colon(argv[argc - 1]) != NULL)
2128             toremote(argc, argv);
2129         else
2130             tolocal(argc, argv);
2131     }
2132
2133     if (back != NULL && back->socket(backhandle) != NULL) {
2134         char ch;
2135         back->special(backhandle, TS_EOF);
2136         ssh_scp_recv(&ch, 1);
2137     }
2138     random_save_seed();
2139
2140     if (gui_mode)
2141         gui_send_errcount(list, errs);
2142
2143     return (errs == 0 ? 0 : 1);
2144 }
2145
2146 /* end */