Beispiel #1
0
int ssh_send(const char *path, FILE *fp, putmode_t how,
       transfer_mode_t mode, ftp_transfer_func hookf)
{
  uint64_t offset = ftp->restart_offset;

  reset_transfer_info();
  ftp->ti.size = ftp->ti.restart_size = offset;
  ftp->restart_offset = 0L;

  ftp->ti.transfer_is_put = true;

  if(how == putUnique) {
    ftp_err(_("Unique put with SSH not implemented yet\n"));
    return -1;
  }

  char* p = ftp_path_absolute(path);
  stripslash(p);
  ftp_cache_flush_mark_for(p);

  if(how == putAppend) {
    ftp_set_tmp_verbosity(vbNone);
    offset = ftp_filesize(p);
  }

  int r = do_write(p, fp, hookf, offset);
  free(p);

  transfer_finished();
  return r;
}
Beispiel #2
0
unsigned long long ftp_filesize(const char *path)
{
    unsigned long long ret;

#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_filesize(path);
#endif

    if(!ftp->has_size_command)
        return -1;
    if(ftp_type(tmBinary) != 0)
        return -1;
    ftp_set_tmp_verbosity(vbError);
    ftp_cmd("SIZE %s", path);
    if(ftp->fullcode == 502) {
        ftp->has_size_command = false;
        return -1;
    }
    if(ftp->code == ctComplete) {
        sscanf(ftp->reply, "%*s %llu", &ret);
        return ret;
    }
    return -1;
}
Beispiel #3
0
/*
** Function:    time_t ftp_filetime(const char *filename)
**
** Description: User routine for attempting to obtain a remote file's
**      modification time in Universal Coordinated Time (GMT).
**
** Returns; Either -1 upon failure or the time_t file modification
**      time upon success.
*/
time_t ftp_filetime(const char *filename)
{
    struct tm ts;

    if(!ftp_connected())
        return -1;

#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_filetime(filename);
#endif

    if(!ftp->has_mdtm_command)
        return -1;

    memset(&ts, 0, sizeof(ts));
    ftp_set_tmp_verbosity(vbNone);
    ftp_cmd("MDTM %s", filename);
    if (ftp->fullcode == 202) {
        ftp->has_mdtm_command = false;
        return -1;
    }
    if (ftp->fullcode != 213)
        return -1;
    /* time is Universal Coordinated Time */
    sscanf(ftp->reply, "%*s %04d%02d%02d%02d%02d%02d", &ts.tm_year,
           &ts.tm_mon, &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
    ts.tm_year -= 1900;
    ts.tm_mon--;
    return gmt_mktime(&ts);
}
Beispiel #4
0
static bool ftp_pasv(bool ipv6, unsigned char* result, unsigned short* ipv6_port)
{
  if (!ftp->has_pasv_command) {
    ftp_err(_("Host doesn't support passive mode\n"));
    return false;
  }
  ftp_set_tmp_verbosity(vbNone);

  /* request passive mode */
  if (!ipv6)
    ftp_cmd("PASV");
#ifdef HAVE_IPV6
  else if (ipv6)
    ftp_cmd("EPSV");
#endif
  else
    return false;

  if (!ftp_connected())
    return false;

  if (ftp->code != ctComplete) {
    ftp_err(_("Unable to enter passive mode\n"));
    if(ftp->code == ctError) /* no use try it again */
      ftp->has_pasv_command = false;
    return false;
  }

  const char* e = ftp_getreply(false);
  while (e && !isdigit((int)*e))
    e++;

  if (!e)
  {
    ftp_err(_("Error parsing EPSV/PASV reply: '%s'\n"), ftp_getreply(false));
    return false;
  }

  if (!ipv6)
  {
    if (sscanf(e, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", &result[0], &result[1],
          &result[2], &result[3], &result[4], &result[5]) != 6)
    {
      ftp_err(_("Error parsing PASV reply: '%s'\n"), ftp_getreply(false));
      return false;
    }
  }
#ifdef HAVE_IPV6
  else
  {
    if (sscanf(e, "%hu", ipv6_port) != 1)
    {
      ftp_err(_("Error parsing EPSV reply: '%s'\n"), ftp_getreply(false));
      return false;
    }
  }
#endif

  return true;
}
Beispiel #5
0
char *ftp_getcurdir(void)
{
#ifdef HAVE_LIBSSH
    if (ftp->session)
        return ssh_getcurdir();
#endif

    ftp_set_tmp_verbosity(vbNone);
    ftp_cmd("PWD");
    if(ftp->code == ctComplete) {
        char *beg, *end, *ret;
        beg = strchr(ftp->reply, '\"');
        if(!beg)
            return xstrdup("CWD?");
        beg++;
        end = strchr(beg, '\"');
        if(!end)
            return xstrdup("CWD?");
        ret = (char *)xmalloc(end-beg+1);
        strncpy(ret, beg, end-beg);
        stripslash(ret);
        /* path shouldn't include any quoted chars */
        path_dos2unix(ret);
        return ret;
    }
    return xstrdup("CWD?");
}
Beispiel #6
0
/* return values:
 * 0 - success
 * 1 - failed, try another mechanism
 * -1 - failed, security extensions not supported
 */
int sec_login(const char *host, const char *mech_to_try)
{
	int ret;
	struct sec_client_mech **m;
	void *tmp;

	/* shut up all messages this will produce (they
	 are usually not very user friendly) */
	ftp_set_tmp_verbosity(vbError);

	if(!mech_to_try || strcasecmp(mech_to_try, "none") == 0)
		return 0;

	m = find_mech(mech_to_try);
	if(!m)
		return 1;

	tmp = realloc(ftp->app_data, (*m)->size);
	if (tmp == NULL) {
		ftp_err(_("realloc %zu failed"), (*m)->size);
		return -1;
	}
	ftp->app_data = tmp;

	if ((*m)->init && (*(*m)->init) (ftp->app_data) != 0) {
		printf(_("Skipping %s...\n"), (*m)->name);
		return 1;
	}
	printf(_("Trying %s...\n"), (*m)->name);
	ret = ftp_cmd("AUTH %s", (*m)->name);
	if (ftp->code != ctContinue) {
		if (ret == 504) {
			printf(_("%s is not supported by the server.\n"), (*m)->name);
		} else if (ret == 534) {
			printf(_("%s rejected as security mechanism.\n"), (*m)->name);
		} else if (ftp->code == ctError) {
			printf(_("The server doesn't support the FTP "
					 "security extensions.\n"));
			return -1;
		}
		return 1;
	}

	ret = (*(*m)->auth) (ftp->app_data, host);

	if (ret == AUTH_CONTINUE)
		return 1;
	else if (ret != AUTH_OK) {
		/* mechanism is supposed to output error string */
		return -1;
	}
	ftp->mech = *m;
	ftp->sec_complete = 1;
	ftp->command_prot = prot_safe;

	return *m == NULL;
}
Beispiel #7
0
int ftp_noop(void)
{
#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_noop();
#endif

    ftp_set_tmp_verbosity(vbCommand);
    ftp_cmd("NOOP");
    return ftp->code == ctComplete ? 0 : -1;
}
Beispiel #8
0
int ssh_send(const char *path, FILE *fp, putmode_t how,
			 transfer_mode_t mode, ftp_transfer_func hookf)
{
	int r;
	long offset = ftp->restart_offset;
	char *p;

	reset_transfer_info();
	ftp->ti.size = ftp->ti.restart_size = offset;
	ftp->restart_offset = 0L;

	ftp->ti.transfer_is_put = true;

	if(how == putUnique) {
		ftp_err("Unique put with SSH not implemented yet\n");
		return -1;
#if 0
		/* try to figure out remote filename */
		char *e = strstr(ftp->reply, " for ");
		if(e) {
			int l;
			e += 5;
			l = strlen(e);
			if(l) {
				free(ftp->ti.local_name);
				if(*e == '\'')
					ftp->ti.local_name = xstrndup(e+1, l-3);
				else
					ftp->ti.local_name = xstrndup(e, l-1);
				ftp_trace("parsed unique filename as '%s'\n",
						  ftp->ti.local_name);
			}
		}
#endif
	}

	p = ftp_path_absolute(path);
	stripslash(p);

	ftp_cache_flush_mark_for(p);

	if(how == putAppend) {
		ftp_set_tmp_verbosity(vbNone);
		offset = ftp_filesize(p);
	}

	r = ssh_send_binary(p, fp, hookf, offset);
	free(p);

	transfer_finished();

	return 0;
}
Beispiel #9
0
void cmd_mv(int argc, char **argv)
{
	OPT_HELP_NEW(_("Rename or move a file."), "mv [options] <src> <dest>", NULL);

	minargs(optind + 1);
	maxargs(optind + 1);
	need_connected();
	need_loggedin();

	ftp_set_tmp_verbosity(vbError);
	if(ftp_rename(argv[optind], argv[optind + 1]) == 0)
		printf("%s -> %s\n", argv[optind], argv[optind + 1]);
}
Beispiel #10
0
void ftp_pwd(void)
{
#ifdef HAVE_LIBSSH
    if (ftp->session)
		{
        ssh_pwd();
        return;
    }
#endif

    ftp_set_tmp_verbosity(vbCommand);
    ftp_cmd("PWD");
}
Beispiel #11
0
void ftp_quit(void)
{
#ifdef HAVE_LIBSSH
	if (ftp_connected() && !ftp->session)
#else
	if (ftp_connected())
#endif
	{
		ftp_reply_timeout(10);
    ftp_set_tmp_verbosity(vbCommand);
    ftp_cmd("QUIT");
  }
  ftp_close();
}
Beispiel #12
0
int ftp_help(const char *arg)
{
#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_help(arg);
#endif

    ftp_set_tmp_verbosity(vbCommand);
    if(arg)
        ftp_cmd("HELP %s", arg);
    else
        ftp_cmd("HELP");
    return ftp->code == ctComplete ? 0 : -1;
}
Beispiel #13
0
int ftp_chdir(const char *path)
{
#ifdef HAVE_LIBSSH
    if (ftp->session)
        return ssh_chdir(path);
#endif

    ftp_set_tmp_verbosity(vbCommand);
    ftp_cmd("CWD %s", path);
    if(ftp->code == ctComplete) {
        /* Now, try to be smart ;-)
         * Many ftp servers include the current directory in the CWD reply
         * try to parse it, so we don't need to issue a PWD command
         */

        if(strncasecmp(ftp->reply, "250 Changed to ", 15) == 0) {
            /* this is what Troll-ftpd replies: 250 Changed to /foo/bar */
            ftp_update_curdir_x(ftp->reply+15);
            ftp_trace("Parsed cwd '%s' from reply\n", ftp->curdir);
        } else if(strncasecmp(ftp->reply,
                              "250 OK. Current directory is ", 29) == 0) {
            /* PureFTPd responds: "250 OK. Current directory is /foo/bar */
            ftp_update_curdir_x(ftp->reply+29);
            ftp_trace("Parsed cwd '%s' from reply\n", ftp->curdir);
        } else if(strstr(ftp->reply, " is current directory") != 0) {
            /* WarFTPD answers: 250 "/foo/bar/" is current directory */
            char *edq;
            char *sdq = strchr(ftp->reply, '\"');
            if(sdq) {
                edq = strchr(sdq+1, '\"');
                if(edq) {
                    char *e = xstrndup(sdq+1, edq-sdq-1);
                    stripslash(e);
                    ftp_update_curdir_x(e);
                    free(e);
                    ftp_trace("Parsed cwd '%s' from reply\n", ftp->curdir);
                }
            }
        } else if(strncasecmp(ftp->reply,
                              "250 Directory changed to ", 25) == 0) {
            /* Serv-U FTP Server for WinSock */
            ftp_update_curdir_x(ftp->reply + 25);
            ftp_trace("Parsed cwd '%s' from reply\n", ftp->curdir);
        } else
            ftp_update_curdir();
        return 0;
    }
    return -1;
}
Beispiel #14
0
int ftp_cdup(void)
{
#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_cdup();
#endif

    ftp_set_tmp_verbosity(vbCommand);
    ftp_cmd("CDUP");
    if(ftp->code == ctComplete) {
        ftp_update_curdir();
        return 0;
    }
    return -1;
}
Beispiel #15
0
void cmd_rstatus(int argc, char **argv)
{
	OPT_HELP_NEW(_("Show status of remote host."), "rstatus [options]", NULL);
	maxargs(optind - 1);
	need_connected();

#ifdef HAVE_LIBSSH
	if(ftp->session) {
		printf("No status for SSH connection\n");
		return;
	}
#endif

	ftp_set_tmp_verbosity(vbCommand);
	ftp_cmd("STAT");
}
Beispiel #16
0
void cmd_mv(int argc, char **argv)
{
	OPT_HELP("Rename or move a file.  Usage:\n"
			 "  mv [options] <src> <dest>\n"
			 "Options:\n"
			 "  -h, --help    show this help\n");

	minargs(optind + 1);
	maxargs(optind + 1);
	need_connected();
	need_loggedin();

	ftp_set_tmp_verbosity(vbError);
	if(ftp_rename(argv[optind], argv[optind + 1]) == 0)
		printf("%s -> %s\n", argv[optind], argv[optind + 1]);
}
Beispiel #17
0
void cmd_site(int argc, char **argv)
{
	char *e;

	minargs_nohelp(1);
	need_connected();

	if(ftp->ssh_pid) {
		printf("SITE commands not available in SSH connections\n");
		return;
	}

	e = args_cat(argc, argv, 1);
	ftp_set_tmp_verbosity(vbCommand);
	ftp_cmd("SITE %s", e);
	free(e);
}
Beispiel #18
0
static int ftp_init_transfer(void)
{
    struct sockaddr_in sa;
    unsigned char *a, *p;
    unsigned char pac[6];

    if(!ftp_connected())
        goto err0;

    if (!(ftp->data = sock_create())) {
        goto err0;
    }
    sock_copy(ftp->data, ftp->ctrl);

    if(ftp_is_passive()) {
        if(ftp_pasv(pac) != 0) {
            goto err1;
        }

        sock_getsockname(ftp->ctrl, &sa);
        memcpy(&sa.sin_addr, pac, (size_t)4);
        memcpy(&sa.sin_port, pac+4, (size_t)2);
        if(sock_connect_addr(ftp->data, &sa) == -1)
            goto err1;
    } else {
        sock_listen(ftp->data);

        a = (unsigned char *)&ftp->data->local_addr.sin_addr;
        p = (unsigned char *)&ftp->data->local_addr.sin_port;

        ftp_set_tmp_verbosity(vbError);
        ftp_cmd("PORT %d,%d,%d,%d,%d,%d",
                a[0], a[1], a[2], a[3], p[0], p[1]);
        if(ftp->code != ctComplete)
            goto err1;
    }

    sock_throughput(ftp->data);

    return 0;

err1:
    sock_destroy(ftp->data);
err0:
    return -1;
}
Beispiel #19
0
int ftp_list(const char *cmd, const char *param, FILE *fp)
{
  if (!cmd || !fp || !ftp_connected())
    return -1;

#ifdef HAVE_LIBSSH
  if (ftp->session)
    return ssh_list(cmd, param, fp);
#endif

  reset_transfer_info();
  foo_hookf = NULL;

#if 0 /* don't care about transfer type, binary should work well... */
  ftp_type(tmAscii);
#endif

  if (ftp_init_transfer() != 0) {
    ftp_err(_("transfer initialization failed"));
    return -1;
  }

  ftp_set_tmp_verbosity(vbNone);
  if (param)
    ftp_cmd("%s %s", cmd, param);
  else
    ftp_cmd("%s", cmd);
  if (ftp->code != ctPrelim)
    return -1;

  if (!sock_accept(ftp->data, "r", ftp_is_passive())) {
    perror("accept()");
    return -1;
  }

  if (FILE_recv_ascii(ftp->data, fp) != 0)
    return -1;

  sock_destroy(ftp->data);
  ftp->data = NULL;

  ftp_read_reply();

  return ftp->code == ctComplete ? 0 : -1;
}
Beispiel #20
0
void cmd_rstatus(int argc, char **argv)
{
	OPT_HELP("Show status of remote host.  Usage:\n"
			 "  rstatus [options]\n"
			 "Options:\n"
			 "  -h, --help    show this help\n");

	maxargs(optind - 1);
	need_connected();

	if(ftp->ssh_pid) {
		printf("No status for SSH connection\n");
		return;
	}

	ftp_set_tmp_verbosity(vbCommand);
	ftp_cmd("STAT");
}
Beispiel #21
0
static int ftp_mkdir_verb(const char *path, verbose_t verb)
{
    char *p;

#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_mkdir_verb(path, verb);
#endif

    p = xstrdup(path);
    stripslash(p);

    ftp_set_tmp_verbosity(verb);
    ftp_cmd("MKD %s", p);
    if(ftp->code == ctComplete)
        ftp_cache_flush_mark_for(p);
    free(p);
    return ftp->code == ctComplete ? 0 : -1;
}
Beispiel #22
0
int ftp_rmdir(const char *path)
{
    char *p;

#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_rmdir(path);
#endif

    p = xstrdup(path);
    stripslash(p);
    ftp_set_tmp_verbosity(vbError);
    ftp_cmd("RMD %s", p);
    if(ftp->code == ctComplete) {
        ftp_cache_flush_mark(p);
        ftp_cache_flush_mark_for(p);
    }
    free(p);
    return ftp->code == ctComplete ? 0 : -1;
}
Beispiel #23
0
void cmd_quote(int argc, char **argv)
{
	char *e;

	OPT_HELP_NEW(_("Send arbitrary FTP command."), "quote [options] <commands>", NULL);

	minargs(optind);
	need_connected();

#ifdef HAVE_LIBSSH
	if(ftp->session) {
		printf("Command not available in SSH connection\n");
		return;
	}
#endif

	e = args_cat(argc, argv, optind);
	ftp_set_tmp_verbosity(vbDebug);
	ftp_cmd("%s", e);
	free(e);
}
Beispiel #24
0
int ftp_chmod(const char *path, const char *mode)
{
#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_chmod(path, mode);
#endif

    if(ftp->has_site_chmod_command) {
        ftp_set_tmp_verbosity(vbNone);
        ftp_cmd("SITE CHMOD %s %s", mode, path);
        if(ftp->fullcode == 502)
            ftp->has_site_chmod_command = false;
        if(ftp->code == ctComplete) {
            ftp_cache_flush_mark_for(path);
            return 0;
        }
    } else
        ftp_err(_("Server doesn't support SITE CHMOD\n"));

    return -1;
}
Beispiel #25
0
static int ftp_pasv(unsigned char result[6])
{
    int pa[6];
    char *e;
    int i;

    if(!ftp->has_pasv_command) {
        ftp_err(_("Host doesn't support passive mode\n"));
        return -1;
    }
    ftp_set_tmp_verbosity(vbNone);

    /* request passive mode */
    ftp_cmd("PASV");

    if(!ftp_connected())
        return -1;

    if(ftp->code != ctComplete) {
        ftp_err(_("Unable to enter passive mode\n"));
        if(ftp->code == ctError) /* no use try it again */
            ftp->has_pasv_command = false;
        return -1;
    }

    e = ftp->reply + 4;
    while(!isdigit((int)*e))
        e++;

    if(sscanf(e, "%d,%d,%d,%d,%d,%d",
              &pa[0], &pa[1], &pa[2], &pa[3], &pa[4], &pa[5]) != 6) {
        ftp_err(_("Error parsing PASV reply: '%s'\n"),
                ftp_getreply(false));
        return -1;
    }
    for(i=0; i<6; i++)
        result[i] = (unsigned char)(pa[i] & 0xFF);

    return 0;
}
Beispiel #26
0
void cmd_quote(int argc, char **argv)
{
	char *e;

	OPT_HELP("Send arbitrary FTP command.  Usage:\n"
			 "  quote [options] <commands>\n"
			 "Options:\n"
			 "  -h, --help    show this help\n");

	minargs(optind);
	need_connected();

	if(ftp->ssh_pid) {
		printf("Command not available in SSH connection\n");
		return;
	}

	e = args_cat(argc, argv, optind);
	ftp_set_tmp_verbosity(vbDebug);
	ftp_cmd("%s", e);
	free(e);
}
Beispiel #27
0
void cmd_system(int argc, char **argv)
{
	if(argv) {
		OPT_HELP_NEW(_("Show type of remote system."), "system [options]\n", NULL);

		maxargs(optind - 1);
	}
	need_connected();
	need_loggedin();

#ifdef HAVE_LIBSSH
	if(ftp->session) {
		fprintf(stderr, "remote system: SSH (version %d)\n", ftp->ssh_version);
		return;
	}
#endif

	if(ftp_get_verbosity() != vbDebug)
		fprintf(stderr, _("remote system: "));
	ftp_set_tmp_verbosity(vbCommand);
	ftp_cmd("SYST");
}
Beispiel #28
0
int ftp_idle(const char *idletime)
{
#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_idle(idletime);
#endif

    if(!ftp->has_site_idle_command) {
        ftp_err(_("Server doesn't support SITE IDLE\n"));
        return -1;
    }

    ftp_set_tmp_verbosity(vbCommand);
    if(idletime)
        ftp_cmd("SITE IDLE %s", idletime);
    else
        ftp_cmd("SITE IDLE");

    if(ftp->fullcode == 502)
        ftp->has_site_idle_command = false;
    return ftp->code == ctComplete ? 0 : -1;
}
Beispiel #29
0
void cmd_system(int argc, char **argv)
{
	if(argv) {
		OPT_HELP("Show type of remote system.  Usage:\n"
				 "  system [options]\n"
				 "Options:\n"
				 "  -h, --help    show this help\n");

		maxargs(optind - 1);
	}
	need_connected();
	need_loggedin();

	if(ftp->ssh_pid) {
		fprintf(stderr, "remote system: SSH (version %d)\n", ftp->ssh_version);
		return;
	}

	if(ftp_get_verbosity() != vbDebug)
		fprintf(stderr, _("remote system: "));
	ftp_set_tmp_verbosity(vbCommand);
	ftp_cmd("SYST");
}
Beispiel #30
0
static int sec_prot_internal(int level)
{
	char *p;
	unsigned int s = 1048576;

	ftp_set_tmp_verbosity(vbError);

	if (!ftp->sec_complete) {
		ftp_err(_("No security data exchange has taken place.\n"));
		return -1;
	}

	if (level) {
		ftp_cmd("PBSZ %u", s);
		if (ftp->code != ctComplete) {
			ftp_err(_("Failed to set protection buffer size.\n"));
			return -1;
		}
		ftp->buffer_size = s;
		p = strstr(ftp->reply, "PBSZ=");
		if (p)
			sscanf(p, "PBSZ=%u", &s);
		if (s < ftp->buffer_size)
			ftp->buffer_size = s;
	}

	ftp_cmd("PROT %c", level["CSEP"]);	/* XXX :-) */
	if (ftp->code != ctComplete) {
		ftp_err(_("Failed to set protection level.\n"));
		return -1;
	}

	ftp->data_prot = (enum protection_level)level;
	url_setprotlevel(ftp->url, level_to_name(ftp->data_prot));
	return 0;
}