static Backend *back;
static void *backhandle;
static Conf *conf;
+int sent_eof = FALSE;
static void source(char *src);
static void rsource(char *src);
assert(!"Unexpected call to from_backend_untrusted()");
return 0; /* not reached */
}
+int from_backend_eof(void *frontend)
+{
+ /*
+ * We expect to be the party deciding when to close the
+ * connection, so if we see EOF before we sent it ourselves, we
+ * should panic.
+ */
+ if (!sent_eof) {
+ connection_fatal(frontend,
+ "Received unexpected end-of-file from server");
+ }
+ return FALSE;
+}
static int ssh_scp_recv(unsigned char *buf, int len)
{
outptr = buf;
if (back != NULL && back->connected(backhandle)) {
char ch;
back->special(backhandle, TS_EOF);
+ sent_eof = TRUE;
ssh_scp_recv((unsigned char *) &ch, 1);
}
cleanup_exit(1);
}
+/*
+ * Wait for the reply to a single SFTP request. Parallels the same
+ * function in psftp.c (but isn't centralised into sftp.c because the
+ * latter module handles SFTP only and shouldn't assume that SFTP is
+ * the only thing going on by calling connection_fatal).
+ */
+struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
+{
+ struct sftp_packet *pktin;
+ struct sftp_request *rreq;
+
+ sftp_register(req);
+ pktin = sftp_recv();
+ if (pktin == NULL)
+ connection_fatal(NULL, "did not receive SFTP response packet "
+ "from server");
+ rreq = sftp_find_request(pktin);
+ if (rreq != req)
+ connection_fatal(NULL, "unable to understand SFTP response packet "
+ "from server: %s", fxp_error());
+ return pktin;
+}
+
/*
* Open an SSH connection to user@host and execute cmd.
*/
console_provide_logctx(logctx);
ssh_scp_init();
if (verbose && realhost != NULL && errs == 0)
- tell_user(stderr, "Connected to %s\n", realhost);
+ tell_user(stderr, "Connected to %s", realhost);
sfree(realhost);
}
} while (p < sizeof(rbuf) && ch != '\n');
rbuf[p - 1] = '\0';
if (resp == 1)
- tell_user(stderr, "%s\n", rbuf);
+ tell_user(stderr, "%s", rbuf);
else
bump("%s", rbuf);
errs++;
struct fxp_names *names;
struct fxp_name *ournames;
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
int nnames, namesize;
int i;
printf("Listing directory %s\n", dirname);
- sftp_register(req = fxp_opendir_send(dirname));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- dirh = fxp_opendir_recv(pktin, rreq);
+ req = fxp_opendir_send(dirname);
+ pktin = sftp_wait_for_reply(req);
+ dirh = fxp_opendir_recv(pktin, req);
if (dirh == NULL) {
printf("Unable to open %s: %s\n", dirname, fxp_error());
while (1) {
- sftp_register(req = fxp_readdir_send(dirh));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- names = fxp_readdir_recv(pktin, rreq);
+ req = fxp_readdir_send(dirh);
+ pktin = sftp_wait_for_reply(req);
+ names = fxp_readdir_recv(pktin, req);
if (names == NULL) {
if (fxp_error_type() == SSH_FX_EOF)
names->nnames = 0; /* prevent free_names */
fxp_free_names(names);
}
- sftp_register(req = fxp_close_send(dirh));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- fxp_close_recv(pktin, rreq);
+ req = fxp_close_send(dirh);
+ pktin = sftp_wait_for_reply(req);
+ fxp_close_recv(pktin, req);
/*
* Now we have our filenames. Sort them by actual file
* name, and then output the longname parts.
*/
- qsort(ournames, nnames, sizeof(*ournames), sftp_ls_compare);
+ if (nnames > 0)
+ qsort(ournames, nnames, sizeof(*ournames), sftp_ls_compare);
/*
* And print them.
* directory.
*/
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
struct fxp_attrs attrs;
int ret;
return 1;
}
- sftp_register(req = fxp_stat_send(target));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- ret = fxp_stat_recv(pktin, rreq, &attrs);
+ req = fxp_stat_send(target);
+ pktin = sftp_wait_for_reply(req);
+ ret = fxp_stat_recv(pktin, req, &attrs);
if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS))
scp_sftp_targetisdir = 0;
if (using_sftp) {
char *fullname;
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
struct fxp_attrs attrs;
if (scp_sftp_targetisdir) {
attrs.flags = 0;
PUT_PERMISSIONS(attrs, permissions);
- sftp_register(req = fxp_open_send(fullname, SSH_FXF_WRITE |
- SSH_FXF_CREAT | SSH_FXF_TRUNC,
- &attrs));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
+ req = fxp_open_send(fullname,
+ SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC,
+ &attrs);
+ pktin = sftp_wait_for_reply(req);
+ scp_sftp_filehandle = fxp_open_recv(pktin, req);
if (!scp_sftp_filehandle) {
tell_user(stderr, "pscp: unable to open %s: %s",
while (!xfer_upload_ready(scp_sftp_xfer)) {
pktin = sftp_recv();
ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
- if (!ret) {
- tell_user(stderr, "error while writing: %s\n", fxp_error());
+ if (ret <= 0) {
+ tell_user(stderr, "error while writing: %s", fxp_error());
+ if (ret == INT_MIN) /* pktin not even freed */
+ sfree(pktin);
errs++;
return 1;
}
if (using_sftp) {
struct fxp_attrs attrs;
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
int ret;
while (!xfer_done(scp_sftp_xfer)) {
pktin = sftp_recv();
- xfer_upload_gotpkt(scp_sftp_xfer, pktin);
+ ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
+ if (ret <= 0) {
+ tell_user(stderr, "error while writing: %s", fxp_error());
+ if (ret == INT_MIN) /* pktin not even freed */
+ sfree(pktin);
+ errs++;
+ return 1;
+ }
}
xfer_cleanup(scp_sftp_xfer);
attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME;
attrs.atime = scp_sftp_atime;
attrs.mtime = scp_sftp_mtime;
- sftp_register(req = fxp_fsetstat_send(scp_sftp_filehandle, attrs));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- ret = fxp_fsetstat_recv(pktin, rreq);
+ req = fxp_fsetstat_send(scp_sftp_filehandle, attrs);
+ pktin = sftp_wait_for_reply(req);
+ ret = fxp_fsetstat_recv(pktin, req);
if (!ret) {
- tell_user(stderr, "unable to set file times: %s\n", fxp_error());
+ tell_user(stderr, "unable to set file times: %s", fxp_error());
errs++;
}
}
- sftp_register(req = fxp_close_send(scp_sftp_filehandle));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- fxp_close_recv(pktin, rreq);
+ req = fxp_close_send(scp_sftp_filehandle);
+ pktin = sftp_wait_for_reply(req);
+ fxp_close_recv(pktin, req);
scp_has_times = 0;
return 0;
} else {
char const *err;
struct fxp_attrs attrs;
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
int ret;
if (scp_sftp_targetisdir) {
* exists and is a directory we will assume we were either
* successful or it didn't matter.
*/
- sftp_register(req = fxp_mkdir_send(fullname));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- ret = fxp_mkdir_recv(pktin, rreq);
+ req = fxp_mkdir_send(fullname);
+ pktin = sftp_wait_for_reply(req);
+ ret = fxp_mkdir_recv(pktin, req);
if (!ret)
err = fxp_error();
else
err = "server reported no error";
- sftp_register(req = fxp_stat_send(fullname));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- ret = fxp_stat_recv(pktin, rreq, &attrs);
+ req = fxp_stat_send(fullname);
+ pktin = sftp_wait_for_reply(req);
+ ret = fxp_stat_recv(pktin, req, &attrs);
if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
!(attrs.permissions & 0040000)) {
int must_free_fname;
struct fxp_attrs attrs;
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
int ret;
if (!scp_sftp_dirstack_head) {
* Now we have a filename. Stat it, and see if it's a file
* or a directory.
*/
- sftp_register(req = fxp_stat_send(fname));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- ret = fxp_stat_recv(pktin, rreq, &attrs);
+ req = fxp_stat_send(fname);
+ pktin = sftp_wait_for_reply(req);
+ ret = fxp_stat_recv(pktin, req, &attrs);
if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
tell_user(stderr, "unable to identify %s: %s", fname,
* list), we must push the other (target,namelist) pair
* on a stack.
*/
- sftp_register(req = fxp_opendir_send(fname));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- dirhandle = fxp_opendir_recv(pktin, rreq);
+ req = fxp_opendir_send(fname);
+ pktin = sftp_wait_for_reply(req);
+ dirhandle = fxp_opendir_recv(pktin, req);
if (!dirhandle) {
- tell_user(stderr, "scp: unable to open directory %s: %s",
+ tell_user(stderr, "pscp: unable to open directory %s: %s",
fname, fxp_error());
if (must_free_fname) sfree(fname);
errs++;
while (1) {
int i;
- sftp_register(req = fxp_readdir_send(dirhandle));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- names = fxp_readdir_recv(pktin, rreq);
+ req = fxp_readdir_send(dirhandle);
+ pktin = sftp_wait_for_reply(req);
+ names = fxp_readdir_recv(pktin, req);
if (names == NULL) {
if (fxp_error_type() == SSH_FX_EOF)
break;
- tell_user(stderr, "scp: reading directory %s: %s\n",
+ tell_user(stderr, "pscp: reading directory %s: %s",
fname, fxp_error());
+
+ req = fxp_close_send(dirhandle);
+ pktin = sftp_wait_for_reply(req);
+ fxp_close_recv(pktin, req);
+
if (must_free_fname) sfree(fname);
sfree(ournames);
errs++;
*/
} else if (!vet_filename(names->names[i].filename)) {
tell_user(stderr, "ignoring potentially dangerous server-"
- "supplied filename '%s'\n",
+ "supplied filename '%s'",
names->names[i].filename);
} else
ournames[nnames++] = names->names[i];
names->nnames = 0; /* prevent free_names */
fxp_free_names(names);
}
- sftp_register(req = fxp_close_send(dirhandle));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- fxp_close_recv(pktin, rreq);
+ req = fxp_close_send(dirhandle);
+ pktin = sftp_wait_for_reply(req);
+ fxp_close_recv(pktin, req);
newitem = snew(struct scp_sftp_dirstack);
newitem->next = scp_sftp_dirstack_head;
act->buf[i - 1] = '\0';
switch (action) {
case '\01': /* error */
- tell_user(stderr, "%s\n", act->buf);
+ tell_user(stderr, "%s", act->buf);
errs++;
continue; /* go round again */
case '\02': /* fatal error */
{
if (using_sftp) {
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
- sftp_register(req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ,
- NULL));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
+ req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ, NULL);
+ pktin = sftp_wait_for_reply(req);
+ scp_sftp_filehandle = fxp_open_recv(pktin, req);
if (!scp_sftp_filehandle) {
tell_user(stderr, "pscp: unable to open %s: %s",
xfer_download_queue(scp_sftp_xfer);
pktin = sftp_recv();
ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
-
- if (ret < 0) {
+ if (ret <= 0) {
tell_user(stderr, "pscp: error while reading: %s", fxp_error());
+ if (ret == INT_MIN) /* pktin not even freed */
+ sfree(pktin);
errs++;
return -1;
}
{
if (using_sftp) {
struct sftp_packet *pktin;
- struct sftp_request *req, *rreq;
+ struct sftp_request *req;
/*
* Ensure that xfer_done() will work correctly, so we can
xfer_set_error(scp_sftp_xfer);
while (!xfer_done(scp_sftp_xfer)) {
void *vbuf;
- int len;
+ int ret, len;
pktin = sftp_recv();
- xfer_download_gotpkt(scp_sftp_xfer, pktin);
+ ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
+ if (ret <= 0) {
+ tell_user(stderr, "pscp: error while reading: %s", fxp_error());
+ if (ret == INT_MIN) /* pktin not even freed */
+ sfree(pktin);
+ errs++;
+ return -1;
+ }
if (xfer_download_data(scp_sftp_xfer, &vbuf, &len))
sfree(vbuf);
}
xfer_cleanup(scp_sftp_xfer);
- sftp_register(req = fxp_close_send(scp_sftp_filehandle));
- rreq = sftp_find_request(pktin = sftp_recv());
- assert(rreq == req);
- fxp_close_recv(pktin, rreq);
+ req = fxp_close_send(scp_sftp_filehandle);
+ pktin = sftp_wait_for_reply(req);
+ fxp_close_recv(pktin, req);
return 0;
} else {
back->send(backhandle, "", 1);
va_start(ap, fmt);
errs++;
str = dupvprintf(fmt, ap);
- str2 = dupcat("scp: ", str, "\n", NULL);
+ str2 = dupcat("pscp: ", str, "\n", NULL);
sfree(str);
scp_send_errmsg(str2);
tell_user(stderr, "%s", str2);
preserve = 1;
} else if (strcmp(argv[i], "-q") == 0) {
statistics = 0;
- } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) {
+ } else if (strcmp(argv[i], "-h") == 0 ||
+ strcmp(argv[i], "-?") == 0 ||
+ strcmp(argv[i], "--help") == 0) {
usage();
- } else if (strcmp(argv[i], "-V") == 0) {
+ } else if (strcmp(argv[i], "-V") == 0 ||
+ strcmp(argv[i], "--version") == 0) {
version();
} else if (strcmp(argv[i], "-ls") == 0) {
list = 1;
if (back != NULL && back->connected(backhandle)) {
char ch;
back->special(backhandle, TS_EOF);
+ sent_eof = TRUE;
ssh_scp_recv((unsigned char *) &ch, 1);
}
random_save_seed();