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; }
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; }
/* ** 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); }
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; }
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?"); }
/* 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; }
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; }
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; }
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]); }
void ftp_pwd(void) { #ifdef HAVE_LIBSSH if (ftp->session) { ssh_pwd(); return; } #endif ftp_set_tmp_verbosity(vbCommand); ftp_cmd("PWD"); }
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(); }
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; }
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; }
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; }
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"); }
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]); }
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); }
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; }
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; }
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"); }
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; }
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; }
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); }
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; }
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; }
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); }
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"); }
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; }
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"); }
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; }