Exemple #1
0
static int ftp_init_receive(const char *path, transfer_mode_t mode,
							ftp_transfer_func hookf)
{
	long rp = ftp->restart_offset;
	char *e;

	ftp->restart_offset = 0L;

	foo_hookf = hookf;
	reset_transfer_info();

	if(ftp_init_transfer() != 0)
		return -1;

	ftp_type(mode);

	if(rp > 0) {
		/* fp is assumed to be fseek'd already */
		ftp_cmd("REST %ld", rp);
		if(ftp->code != ctContinue)
			return -1;
		ftp->ti.size = rp;
		ftp->ti.restart_size = rp;
	}

	ftp_cmd("RETR %s", path);
	if(ftp->code != ctPrelim)
		return -1;

	if(!sock_accept(ftp->data, "r", ftp_is_passive())) {
		ftp_err(_("data connection not accepted\n"));
		return -1;
	}

	/* try to get the total file size */
	{
		/* see if we have cached this directory/file */
		rfile *f = ftp_cache_get_file(path);
		if(f)
			ftp->ti.total_size = f->size;
		else {
			/* try to figure out file size from RETR reply
			 * Opening BINARY mode data connection for foo.mp3 (14429793 bytes)
			 *                                                  ^^^^^^^^ aha!
			 *
			 * note: this might not be the _total_ filesize if we are RESTarting
			 */
			e = strstr(ftp->reply, " bytes");
			if(e != 0) {
				while((e > ftp->reply) && isdigit((int)e[-1]))
					e--;
				ftp->ti.total_size = strtoul(e,NULL,10);
			} /* else we don't bother */
		}
	}
	return 0;
}
Exemple #2
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;
}
Exemple #3
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;
}
Exemple #4
0
static int ftp_send(const char *path, FILE *fp, putmode_t how,
					transfer_mode_t mode, ftp_transfer_func hookf)
{
	int r;
	long rp = ftp->restart_offset;
	ftp->restart_offset = 0L;

	if(how == putUnique && !ftp->has_stou_command)
		return -1;

  if (how == putTryUnique && !ftp->has_stou_command)
    how = putNormal;

	reset_transfer_info();
	ftp->ti.transfer_is_put = true;

	if(ftp_init_transfer() != 0)
		return -1;

	ftp_type(mode);

	if(rp > 0) {
		/* fp is assumed to be fseek'd already */
		ftp_cmd("REST %ld", rp);
		if(ftp->code != ctContinue)
			return -1;
		ftp->ti.size = rp;
		ftp->ti.restart_size = rp;
	}

  ftp_set_tmp_verbosity(vbError);
  switch (how) {
  case putAppend:
    ftp_cmd("APPE %s", path);
    break;

  case putTryUnique:
  case putUnique:
    ftp_cmd("STOU %s", path);
    if (ftp->fullcode == 502 || ftp->fullcode == 504) {
      ftp->has_stou_command = false;
      if (how == putTryUnique)
        how = putNormal;
      else
        break;
    }
    else
      break;

  default:
    ftp_cmd("STOR %s", path);
    break;
  }

	if(ftp->code != ctPrelim)
		return -1;

	if(how == putUnique) {
		/* 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);
			}
		}
	}

	if(!sock_accept(ftp->data, "w", ftp_is_passive())) {
		ftp_err(_("data connection not accepted\n"));
		return -1;
	}

	ftp_cache_flush_mark_for(path);

	if(mode == tmBinary)
		r = FILE_send_binary(fp, ftp->data);
	else
		r = FILE_send_ascii(fp, ftp->data);
	sock_flush(ftp->data);
	sock_destroy(ftp->data);
	ftp->data = 0;

	if(r == 0) {
		transfer_finished();
		ftp_read_reply();
		ftp->ti.ioerror = (ftp->code != ctComplete);
		if(ftp->code != ctComplete) {
			ftp_trace("transfer failed\n");
			return -1;
		}
	} else
		transfer_finished();

	return 0;
}
Exemple #5
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 #6
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;
}