Exemple #1
0
static int ftp_init_transfer(void)
{
  if (!ftp_connected())
    return -1;

  if (!sock_dup(ftp->ctrl, &ftp->data))
    return -1;

  if (ftp_is_passive())
  {
    ftp_trace("Initializing passive connection.\n");

    struct sockaddr_storage sa;
    memcpy(&sa, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));

    unsigned char pac[6] = { 0 };
    unsigned short ipv6_port = { 0 };
    if (!ftp_pasv(sa.ss_family != AF_INET, pac, &ipv6_port))
    {
      ftp_trace("PASV/EPSV failed.\n");
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }

    socklen_t len = sizeof(struct sockaddr_in);
    if (sa.ss_family == AF_INET)
    {
      memcpy(&((struct sockaddr_in*)&sa)->sin_addr, pac, (size_t)4);
      memcpy(&((struct sockaddr_in*)&sa)->sin_port, pac+4, (size_t)2);
    }
#ifdef HAVE_IPV6
    else if (sa.ss_family == AF_INET6)
    {
      ((struct sockaddr_in6*)&sa)->sin6_port = htons(ipv6_port);
      len = sizeof(struct sockaddr_in6);
    }
#endif
    else
    {
      ftp_trace("Do not know how to handle family %d.\n", sa.ss_family);
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }

    struct sockaddr_storage tmp;
    memcpy(&tmp, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));
    if (is_reserved((struct sockaddr*) &sa) ||
         is_multicast((struct sockaddr*) &sa)  ||
         (is_private((struct sockaddr*) &sa) != is_private((struct sockaddr*) &tmp)) ||
         (is_loopback((struct sockaddr*) &sa) != is_loopback((struct sockaddr*) &tmp)))
    {
      // Invalid address returned by PASV. Replace with address from control
      // socket.
      ftp_err(_("Address returned by PASV seems to be incorrect.\n"));
      ((struct sockaddr_in*)&sa)->sin_addr = ((struct sockaddr_in*)&tmp)->sin_addr;
    }

    if (!sock_connect_addr(ftp->data, (struct sockaddr*) &sa, len))
    {
      ftp_trace("Could not connect to address from PASV/EPSV.\n");
      perror("connect()");
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }
  } else {
    ftp_trace("Initializing active connection.\n");

    const struct sockaddr* local = sock_local_addr(ftp->data);
    sock_listen(ftp->data, local->sa_family);

    if (local->sa_family == AF_INET)
    {
      struct sockaddr_in* tmp = (struct sockaddr_in*)local;
      unsigned char* a = (unsigned char *)&tmp->sin_addr;
      unsigned char* p = (unsigned char *)&tmp->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]);
    }
#ifdef HAVE_IPV6
    else if (local->sa_family == AF_INET6)
    {
      char* addr = printable_address(local);

      ftp_set_tmp_verbosity(vbError);
      ftp_cmd("EPRT |2|%s|%u|", addr, ntohs(((struct sockaddr_in6*)local)->sin6_port));
      free(addr);
    }
#endif
    else
    {
      ftp_trace("Do not know how to handle family %d.\n", local->sa_family);
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }

    if(ftp->code != ctComplete)
    {
      ftp_trace("PORT/EPRT not successful\n");
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }
  }

  sock_throughput(ftp->data);
  return 0;
}
Exemple #2
0
int ftp_open_url(url_t *urlp, bool reset_vars)
{
    bool use_proxy;
    int i;

    if(reset_vars)
        ftp_reset_vars();
    /* don't assume server is in ascii mode initially even if RFC says so */
    ftp->prev_type = '?';

#ifdef HAVE_POSIX_SIGSETJMP
    if(sigsetjmp(open_timeout_jmp, 1))
#else
    if(setjmp(open_timeout_jmp))
#endif
    {
        ftp_close();
        ftp_err(_("Connection timeout after %u seconds\n"),
                ftp->open_timeout);
        return 1;
    }
    ftp_set_signal(SIGALRM, ftp_open_handler);
    alarm(ftp->open_timeout);

    use_proxy = (proxy_type(urlp) != 0);

    ftp_err(_("Looking up %s... "),
            use_proxy ? gvProxyUrl->hostname : urlp->hostname);

    /* Set the default port (22) for SSH if no port is specified. We
     * need to do this here, 'cause host_lookup() sets it to 21
     * (default port for vanilla FTP)
     */
    if(urlp->protocol) {
        if(strcmp(urlp->protocol, "sftp") == 0)
            url_setprotocol(urlp, "ssh");
        if(strcmp(urlp->protocol, "ssh") == 0 && urlp->port == -1)
            urlp->port = 22; /* default SSH port */
    }

    ftp->host = host_create(use_proxy ? gvProxyUrl : urlp);

    if(!host_lookup(ftp->host)) {
        herror(host_getname(ftp->host));
        alarm(0);
        ftp_set_signal(SIGALRM, SIG_IGN);
        return -1;
    }
    /* keep the value in urlp->port
    urlp->port = ntohs(ftp->host->port);
    and set it to 21 if it is -1 */
    if(urlp->port == -1) {
	    urlp->port = 21;
    }


    fprintf(stderr, "\r               ");
    i = strlen(use_proxy ? gvProxyUrl->hostname : urlp->hostname);
    while(i--)
        fprintf(stderr, " ");
    fprintf(stderr, "\r");
    ftp_trace("\n");

#ifdef HAVE_LIBSSH
    if(urlp->protocol && strcmp(urlp->protocol, "ssh") == 0) {
        int ret = ssh_open_url(urlp);
        alarm(0);
        return ret;
    }
#endif

    if(urlp->protocol && strcmp(urlp->protocol, "ftp") != 0) {
        ftp_err(_("Sorry, don't know how to handle your '%s' protocol\n"
                  "trying 'ftp' instead...\n"),
                urlp->protocol);
        url_setprotocol(urlp, 0);
    }

    if(use_proxy) {
        ftp_err(_("Connecting to proxy %s at port %d...\n"),
                host_getoname(ftp->host), urlp->port);
    } else {
        ftp_err(_("Connecting to %s at port %d...\n"),
                host_getoname(ftp->host), urlp->port);
    }

    ftp->ctrl = sock_create();
    if (ftp->ctrl == 0) {
        ftp_err(_("Unable to create socket.\n"));
        alarm(0);
        ftp_set_signal(SIGALRM, SIG_IGN);
        return -1;
    }

    if(!sock_connect_host(ftp->ctrl, ftp->host)) {
        alarm(0);
        ftp_set_signal(SIGALRM, SIG_IGN);
        return -1;
    }
    sock_lowdelay(ftp->ctrl);
    char* ip = host_getip(ftp->host);
    ftp_err(_("Connected to %s ([%s]:%d).\n"),
        host_getoname(ftp->host), ip, urlp->port);
    free(ip);

    /* read startup message from server */
    ftp_set_tmp_verbosity(vbCommand);
    ftp_read_reply();
    if(ftp->fullcode == 120) {
        ftp_set_tmp_verbosity(vbCommand);
        ftp_read_reply();
    }
    alarm(0);
    ftp_set_signal(SIGALRM, SIG_IGN);
    if(!sock_connected(ftp->ctrl)) {
        ftp_close();
        return 1;
    }
    ftp->connected = (ftp->fullcode == 220);

    if(ftp->connected) {
        void (*tracefunq)(const char *fmt, ...);

        url_destroy(ftp->url);
        ftp->url = url_clone(urlp);

        tracefunq = (ftp->verbosity == vbDebug ? ftp_err : ftp_trace);

        char* remote_addr = printable_address(sock_remote_addr(ftp->ctrl)),
            *local_addr = printable_address(sock_local_addr(ftp->ctrl));
        tracefunq("remote address: %s\n", remote_addr);
        tracefunq("local address: %s\n", local_addr);
        free(remote_addr);
        free(local_addr);

        return 0;
    } else {
        ftp_close();
        return 1;
    }
}
Exemple #3
0
static int ftp_init_transfer(void)
{
	struct sockaddr_storage sa;
	unsigned char *a, *p;

	if(!ftp_connected())
		return -1;

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

	if (ftp_is_passive())
  {
    memcpy(&sa, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));

    unsigned char pac[6];
    unsigned short ipv6_port;
		if (!ftp_pasv(sa.ss_family != AF_INET, pac, &ipv6_port))
			goto err1;

    socklen_t len = sizeof(struct sockaddr_in);
    if (sa.ss_family == AF_INET)
    {
      memcpy(&((struct sockaddr_in*)&sa)->sin_addr, pac, (size_t)4);
		  memcpy(&((struct sockaddr_in*)&sa)->sin_port, pac+4, (size_t)2);
    }
#ifdef HAVE_IPV6
    else if (sa.ss_family == AF_INET6)
    {
      ((struct sockaddr_in6*)&sa)->sin6_port = htons(ipv6_port);
      len = sizeof(struct sockaddr_in6);
    }
#endif
    else
      return -1;

    struct sockaddr_storage tmp;
    memcpy(&tmp, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));
		if (is_reserved((struct sockaddr*) &sa) ||
			   is_multicast((struct sockaddr*) &sa)  ||
			   (is_private((struct sockaddr*) &sa) != is_private((struct sockaddr*) &tmp)) ||
			   (is_loopback((struct sockaddr*) &sa) != is_loopback((struct sockaddr*) &tmp)))
		{
			// Invalid address returned by PASV. Replace with address from control
			// socket.
			ftp_err(_("Address returned by PASV seems to be incorrect.\n"));
			((struct sockaddr_in*)&sa)->sin_addr = ((struct sockaddr_in*)&tmp)->sin_addr;
		}

		if (!sock_connect_addr(ftp->data, (struct sockaddr*) &sa, len))
    {
      perror("connect()");
			goto err1;
    }
	} else {
    const struct sockaddr* local = sock_local_addr(ftp->data);
		sock_listen(ftp->data, local->sa_family);

    if (local->sa_family == AF_INET)
    {
      struct sockaddr_in* tmp = (struct sockaddr_in*)local;
  		a = (unsigned char *)&tmp->sin_addr;
	  	p = (unsigned char *)&tmp->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]);
    }
#ifdef HAVE_IPV6
    else if (local->sa_family == AF_INET6)
    {
      char* addr = printable_address(local);

      ftp_set_tmp_verbosity(vbError);
		  ftp_cmd("EPRT |2|%s|%u", addr, ntohs(((struct sockaddr_in6*)local)->sin6_port));
      free(addr);
    }
#endif
    else
      goto err1;

		if(ftp->code != ctComplete)
			goto err1;
	}

	sock_throughput(ftp->data);

	return 0;

 err1:
	sock_destroy(ftp->data);
	ftp->data = 0;
	return -1;
}