Beispiel #1
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 #2
0
int Ftp::login(const char* user, const char* password) {
    int ret;

    // get all the welcome message
    ret = ftp_cmd();
    switch (ret) {
        case 220:
            break;
        default:
            return ret;
    }

    ret = ftp_cmd("USER", user == NULL ? "anonymous" : user);
    switch (ret) {
        case 230:
            return 0;
        case 331:
            break;
        default:
            return ret;
    }

    ret = ftp_cmd("PASS", password == NULL ? "myget@myget" : password);
    switch (ret) {
        case 230:
            return 0;
        default:
            return ret;
    }
};
Beispiel #3
0
int ftp_rename(const char *oldname, const char *newname)
{
    char *on;
    char *nn;

#ifdef HAVE_LIBSSH
    if (ftp->session)
        return ssh_rename(oldname, newname);
#endif

    on = xstrdup(oldname);
    stripslash(on);
    ftp_cmd("RNFR %s", on);
    if(ftp->code != ctContinue) {
        free(on);
        return -1;
    }

    nn = xstrdup(newname);
    stripslash(nn);
    ftp_cmd("RNTO %s", nn);
    if(ftp->code != ctComplete) {
        free(on);
        free(nn);
        return -1;
    }

    ftp_cache_flush_mark_for(on);
    ftp_cache_flush_mark_for(nn);
    return 0;
}
Beispiel #4
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;
}
Beispiel #5
0
int Ftp::pasv(int *port) {
    int ret;
    char *ptr;
    *port = 0;

    /**********************************
     * RFC2428
     * ipv4:
     * <=PASV 
     * =>227 xxxx(h1,h2,h3,h4,p1,p2)
     * ipv6:
     * normal:
     * <=EPSV
     * extension:
     * <=EPSV 1  //use ipv4 connection
     * <=EPSV 2  //use ipv6 connection
     * =>229 xxxx(|||6446|)
     */

    if (remoteAddr.ai_family == AF_INET) {  // ipv4
        ret = ftp_cmd("PASV");
        switch (ret) {
            case 227:
                break;
            default:
                return ret;
        }
        // xxxx(h1,h2,h3,h4,p1,p2)
        if ((ptr=strrchr(stateLine, ',')) == NULL) return -1;
        *port = atoi(ptr+1);
        do {
            ptr--;
        } while (ptr != stateLine && ISDIGIT(*ptr));
        if (ptr == stateLine) return -1;
        *port += atoi(ptr+1)<<8;
    } else if (remoteAddr.ai_family == AF_INET6) {
        ret = ftp_cmd("EPSV", "2");
        switch (ret) {
            case 229:
                break;
            default:
                return ret;
        }
        // xxxx(|||6446|)
        if ((ptr=strrchr(stateLine, '|')) == NULL) return -1;
        do {
            ptr--;
        } while (ptr != stateLine && ISDIGIT(*ptr));
        if (ptr == stateLine) return -1;
        *port = atoi(ptr+1);
    } else {
        return -1;
    }

    return 0;
};
Beispiel #6
0
/*
 * Set transfer mode and data type
 */
static int
ftp_mode_type(conn_t *conn, int mode, int type)
{
	int e;

	switch (mode) {
	case 0:
	case 's':
		mode = 'S';
	case 'S':
		break;
	default:
		return (FTP_PROTOCOL_ERROR);
	}
	if ((e = ftp_cmd(conn, "MODE %c\r\n", mode)) != FTP_OK) {
		if (mode == 'S') {
			/*
			 * Stream mode is supposed to be the default - so
			 * much so that some servers not only do not
			 * support any other mode, but do not support the
			 * MODE command at all.
			 *
			 * If "MODE S" fails, it is unlikely that we
			 * previously succeeded in setting a different
			 * mode.  Therefore, we simply hope that the
			 * server is already in the correct mode, and
			 * silently ignore the failure.
			 */
		} else {
			return (e);
		}
	}

	switch (type) {
	case 0:
	case 'i':
		type = 'I';
	case 'I':
		break;
	case 'a':
		type = 'A';
	case 'A':
		break;
	case 'd':
		type = 'D';
	case 'D':
		/* can't handle yet */
	default:
		return (FTP_PROTOCOL_ERROR);
	}
	if ((e = ftp_cmd(conn, "TYPE %c\r\n", type)) != FTP_OK)
		return (e);

	return (FTP_OK);
}
Beispiel #7
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 #8
0
int Ftp::size(const char *file, off_t *size) {
    int ret;
    char *ptr;

    if (!file) return -1;

    ret = ftp_cmd("SIZE", file);
    switch (ret) {
        case 213:
            break;
        default:
            return ret;
    }

    *size = 0;
    ptr = stateLine;
    while (*ptr == ' ') ptr++;
    while (ISDIGIT(*ptr)) {
        *size *= 10;
        *size += *ptr -= '0';
        ptr++;
    }

    return 0;
};
Beispiel #9
0
int Ftp::port(int port) {
    int ret;
    char buffer[128];
    char addr[INET6_ADDRSTRLEN];
    char *ptr;

    /************************************
     * RFC2428
     * ipv4:
     * <=PORT 10,20,12,66,port>>8,port&0xff
     * <=EPRT |1|132.235.1.2|6275|
     * ipv6: 
     * <=EPRT |2|IPv6.ascii|PORT.ascii|
     * =>200 xxx
     */
    if (localAddr.ai_family == AF_INET) {
        if (localAddr.get_addr(addr, INET_ADDRSTRLEN) < 0)
            return -1;
        ptr = addr;
        while (*ptr) {
            if (*ptr == '.') *ptr = ',';
            ptr++;
        }
        snprintf(buffer, sizeof(buffer), "%s,%d,%d", addr, port>>8, port&0xff);
        ret = ftp_cmd("PORT", buffer);
    } else if (localAddr.ai_family == AF_INET6) {
Beispiel #10
0
/*
 * Close the FTP coprocess' current connection, but
 * keep the process itself alive.
 */
void
ftp_stop(void)
{
#if defined(__svr4__) && defined(__sun__)
    char	env[BUFSIZ];
#endif
    const char *tmp1, *tmp2;

    if (!ftp_started)
        return;

    tmp1=getenv(PKG_FTPIO_COMMAND);
    tmp2=getenv(PKG_FTPIO_ANSWER);

    /* (Only) the last one closes the link */
    if (tmp1 != NULL && tmp2 != NULL) {
        if (needclose)
            ftp_cmd("close\n", "\n(221 .*|Not connected.)\n");

        (void) close(ftpio.command);
        (void) close(ftpio.answer);
    }

#if defined(__svr4__) && defined(__sun__)
    (void) snprintf(env, sizeof(env), "%s=", PKG_FTPIO_COMMAND);
    putenv(env);
    (void) snprintf(env, sizeof(env), "%s=", PKG_FTPIO_ANSWER);
    putenv(env);
#else
    unsetenv(PKG_FTPIO_COMMAND);
    unsetenv(PKG_FTPIO_ANSWER);
#endif
}
Beispiel #11
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 #12
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 #13
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 #14
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 #15
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 #16
0
int Ftp::cwd(const char* dir) {
    int ret;

    ret = ftp_cmd("CWD", dir ? dir : "/");
    switch (ret) {
        case 250:
            return 0;
        default:
            return ret;
    }
};
Beispiel #17
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 #18
0
int Ftp::type(const char* type) {
    int ret;

    if (!type) return -1;
    ret = ftp_cmd("TYPE", type);
    switch (ret) {
        case 200:
            return 0;
        default:
            return ret;
    }
};
Beispiel #19
0
void ftp_pwd(void)
{
#ifdef HAVE_LIBSSH
    if (ftp->session)
		{
        ssh_pwd();
        return;
    }
#endif

    ftp_set_tmp_verbosity(vbCommand);
    ftp_cmd("PWD");
}
Beispiel #20
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 #21
0
int ftp_unlink(const char *path)
{
#ifdef HAVE_LIBSSH
    if(ftp->session)
        return ssh_unlink(path);
#endif

    ftp_cmd("DELE %s", path);
    if(ftp->code == ctComplete) {
        ftp_cache_flush_mark_for(path);
        return 0;
    }
    return -1;
}
Beispiel #22
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 #23
0
int Ftp::rest(off_t offset) {
    int ret;
    if (offset < 0) return -1;
    char buffer[64];

    snprintf(buffer, sizeof(buffer), "%lu", offset);
    ret = ftp_cmd("REST", buffer);
    switch (ret) {
        case 350:
            return 0;
        default:
            return ret;
    }
};
Beispiel #24
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 #25
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 #26
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;
}
Beispiel #27
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 #28
0
int ftp_type(transfer_mode_t type)
{
    if(ftp->ssh_pid)
        /* FIXME: is this relevant for ssh ? */
        return 0;

    if(type == tmCurrent)
        return 0;

    if(ftp->prev_type != type) {
        ftp_cmd("TYPE %c", type == tmAscii ? 'A' : 'I');
        if(ftp->code != ctComplete)
            return -1;
        ftp->prev_type = type;
    }
    return 0;
}
Beispiel #29
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 #30
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);
}