static void create_bookmark(const char *guessed_alias) { char *default_alias = 0; char *prompt; url_t *url; listitem *li; int a; char *alias; alias = xstrdup(guessed_alias); while(true) { if(!alias) { default_alias = guess_alias(ftp->url); if(default_alias) asprintf(&prompt, "alias (%s): ", default_alias); else prompt = xstrdup("alias: "); force_completion_type = cpBookmark; alias = input_read_string(prompt); free(prompt); if(!alias || !*alias) alias = default_alias; else free(default_alias); } url = url_clone(ftp->url); url_setalias(url, alias); free(alias); alias = 0; li = list_search(gvBookmarks, (listsearchfunc)urlcmp, url); if(li) { a = ask(ASKYES|ASKNO|ASKCANCEL, ASKYES, _("a bookmark named '%s' already exists, overwrite?"), url->alias ? url->alias : url->hostname); if(a == ASKCANCEL) { url_destroy(url); return; } if(a == ASKYES) break; } else break; } /* password is automatically saved if anonymous login */ if(!url_isanon(url) && url->password) { a = ask(ASKYES|ASKNO, ASKNO, _("Save password?")); if(a == ASKNO) url_setpassword(url, 0); } create_the_bookmark(url); printf(_("created bookmark %s\n"), url->alias); }
int ftp_reopen(void) { if(ftp && ftp->url) { url_t *u = url_clone(ftp->url); int r; url_setdirectory(u, ftp->curdir); r = ftp_open_url(u, false); if(r == 0) { r = ftp_login(u->username, gvAnonPasswd); } else ftp_close(); url_destroy(u); return r; } return -1; }
int ftp_login(const char *guessed_username, const char *anonpass) { int ptype, r; static url_t *purl = 0; if(!ftp_connected()) return 1; if(!ftp->url) return -1; #ifdef HAVE_LIBSSH if (ftp->session) /* login authentication is performed by the ssh program */ return 0; #endif ptype = proxy_type(ftp->url); if(purl) { url_destroy(purl); purl = 0; } if(ptype > 0) purl = url_clone(gvProxyUrl); r = get_username(ftp->url, guessed_username, false); if(r != 0) return r; if(ptype > 1 && ptype < 7) { r = get_username(purl, 0, true); if(r != 0) return r; } #ifdef SECFTP ftp->sec_complete = false; ftp->data_prot = prot_clear; /* don't use secure stuff if anonymous */ if(!url_isanon(ftp->url)) { list *mechlist; /* request a protection level */ if(ftp->url->protlevel) { if(sec_request_prot(ftp->url->protlevel) != 0) ftp_err(_("Invalid protection level '%s'\n"), ftp->url->protlevel); } /* get list of mechanisms to try */ mechlist = ftp->url->mech ? ftp->url->mech : gvDefaultMechanism; if(mechlist) { listitem *li = mechlist->first; int ret = 0; for(; li; li=li->next) { const char *mech_name; mech_name = secext_name((char *)li->data); if(mech_name == 0) { ftp_err(_("unknown mechanism '%s'\n"), (char *)li->data); continue; } if(mech_unsupported(mech_name)) { ftp_err(_("Yafc was not compiled with support for %s\n"), mech_name); continue; } ret = sec_login(host_getname(ftp->host), mech_name); if(ret == -1) { if(ftp->code == ctError && ftp->fullcode != 504 && ftp->fullcode != 534) url_setmech(ftp->url, "none"); } if(ret != 1) break; } } if(ftp->sec_complete) ftp_err(_("Authentication successful.\n")); else ftp_err(_("*** Using plaintext username" " and password ***\n")); } #endif if(url_isanon(ftp->url)) fprintf(stderr, _("logging in anonymously...\n")); ftp_set_tmp_verbosity(ftp->url->password ? vbError : vbCommand); switch(ptype) { case 0: default: ftp_cmd("USER %s", ftp->url->username); break; case 1: ftp_cmd("USER %s@%s", ftp->url->username, ftp->url->hostname); break; case 2: case 3: case 4: ftp_cmd("USER %s", purl->username); if(ftp->code == ctContinue) { r = get_password(purl, 0, true); if(r != 0) return 0; ftp_cmd("PASS %s", purl->password); /* FIXME: what reply code do we expect now? */ if(ftp->code < ctTransient) { if(ptype == 2) { ftp_cmd("USER %s@%s", ftp->url->username, ftp->url->hostname); } else { if(ptype == 3) ftp_cmd("SITE %s", purl->hostname); else ftp_cmd("OPEN %s", purl->hostname); if(ftp->code < ctTransient) ftp_cmd("USER %s", ftp->url->username); } } } break; case 5: ftp_cmd("USER %s@%s@%s", ftp->url->username, purl->username, ftp->url->hostname); break; case 6: ftp_cmd("USER %s@%s", purl->username, ftp->url->hostname); if(ftp->code == ctContinue) { r = get_password(purl, 0, true); if(r != 0) return 0; ftp_cmd("PASS %s", purl->password); if(ftp->code < ctTransient) ftp_cmd("USER %s", ftp->url->username); } break; case 7: ftp_cmd("USER %s@%s:%i", ftp->url->username, ftp->url->hostname, ftp->url->port); break; } if(ftp->code == ctContinue) { ftp->loggedin = false; r = get_password(ftp->url, anonpass, false); if(r != 0) return r; if(ptype == 5) { r = get_password(purl, 0, true); if(r != 0) { url_destroy(purl); purl = 0; return 0; } } ftp_set_tmp_verbosity(vbCommand); switch(ptype) { default: case 0: case 1: case 2: case 3: case 4: case 6: ftp_cmd("PASS %s", ftp->url->password); break; case 5: ftp_cmd("PASS %s@%s", ftp->url->password, purl->password); break; } } url_destroy(purl); purl = 0; if(ftp->code > ctContinue) { if(ftp->fullcode == 530 && ftp_loggedin()) { /* this probable means '530 Already logged in' */ return 2; } ftp->loggedin = false; return 1; } if(ftp->code == ctComplete) { ftp->loggedin = true; #ifdef SECFTP /* we are logged in, now set the requested data protection level * requested from the autologin information in the config file, * if any, else uses default protection level 'clear', ie * no protection on the data channel */ if(ftp->sec_complete) { sec_set_protection_level(); fprintf(stderr, _("Data protection is %s\n"), level_to_name(ftp->data_prot)); } #endif ftp->homedir = ftp_getcurdir(); ftp->curdir = xstrdup(ftp->homedir); ftp->prevdir = xstrdup(ftp->homedir); if(ftp->url->directory) ftp_chdir(ftp->url->directory); ftp_get_feat(); return 0; } if(ftp->code == ctTransient) return 1; return -1; }
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; } }
void auto_create_bookmark(void) { listitem *li; int a; bool auto_create, had_passwd = false; bool update = false; if(gvAutoBookmark == 0 && gvAutoBookmarkUpdate == 0) return; if(!ftp_loggedin() || gvSighupReceived) return; auto_create = (gvAutoBookmark == 1); /* check if bookmark already exists */ li = list_search(gvBookmarks, (listsearchfunc)urlcmp, ftp->url); if(li) { if(!should_update_bookmark((url_t *)li->data)) return; /* bookmark already exist, update it */ if(gvAutoBookmarkUpdate == 2) { a = ask(ASKYES|ASKNO, ASKYES, _("Do you want to update the bookmark for this site?")); if(a == ASKNO) return; } update = true; auto_create = true; had_passwd = (((url_t *)li->data)->password != 0); } if(gvAutoBookmark == 2 && !auto_create) { a = ask(ASKYES|ASKNO, ASKYES, _("Do you want to create a bookmark for this site?")); if(a == ASKNO) return; create_bookmark(0); } else { /* auto autobookmark... */ url_t* url = url_clone(ftp->url); char* a = guess_alias(ftp->url); url_setalias(url, a); free(a); li = list_search(gvBookmarks, (listsearchfunc)urlcmp, url); if(li) { /* bookmark already exist, overwrite it */ while(true) { url_t *xurl = (url_t *)li->data; if(xurl->alias && (strcmp(xurl->alias, url->alias) == 0) && (strcmp(xurl->hostname, url->hostname) != 0)) { /* create a new version of the alias, since guessed alias * already exists but for another host */ update = false; char* par = strrchr(url->alias, '('); int ver = 1; if (par) { *par = 0; ver = atoi(par + 1); } if (asprintf(&a, "%s(%d)", url->alias, ver + 1) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); url_destroy(url); return; } url_setalias(url, a); free(a); } else { update = true; had_passwd = (xurl->password != 0); break; } li = list_search(gvBookmarks, (listsearchfunc)urlcmp, url); if(li == 0) break; } if(li) /* overwrite bookmark (ie, delete old and create a new) */ list_delitem(gvBookmarks, li); if(!url_isanon(url) && gvAutoBookmarkSavePasswd == false && !had_passwd) url_setpassword(url, 0); } else { if(!url_isanon(url) && gvAutoBookmarkSavePasswd == false) url_setpassword(url, 0); } create_the_bookmark(url); if(!gvAutoBookmarkSilent) { if(update) printf(_("updated bookmark %s\n"), url->alias); else printf(_("created bookmark %s\n"), url->alias); } } }
int ssh_open_url(url_t* urlp) { ftp->session = ssh_new(); if (!ftp->session) return -1; /* set log level */ if (ftp_get_verbosity() == vbDebug) { int verbosity = SSH_LOG_PROTOCOL; ssh_options_set(ftp->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); } /* If we have ssh options from yafcrc, load them */ if (gvSSHOptions) { args_t *args = args_create(); args_init(args, 0, NULL); args_push_back(args, gvSSHOptions); int argc = 0; if (ssh_options_getopt(ftp->session, &argc, args->argv) != SSH_OK) { ftp_err(_("Failed to load SSH options from yafcrc config (ssh_options = '%s')\n"), gvSSHOptions); ssh_free(ftp->session); ftp->session = NULL; return -1; } args->argc = argc; args_destroy(args); } /* set host name */ ssh_options_set(ftp->session, SSH_OPTIONS_HOST, urlp->hostname); /* if we have port use that one */ if (urlp->port > 0) ssh_options_set(ftp->session, SSH_OPTIONS_PORT, &urlp->port); /* parse .ssh/config */ int r = ssh_options_parse_config(ftp->session, NULL); if (r != SSH_OK) { ftp_err(_("Failed to parse ssh config: %s\n"), ssh_get_error(ftp->session)); ssh_free(ftp->session); ftp->session = NULL; return r; } /* if we have username use that one */ if (urlp->username) ssh_options_set(ftp->session, SSH_OPTIONS_USER, urlp->username); /* connect to server */ r = ssh_connect(ftp->session); if (r != SSH_OK) { ftp_err(_("Couldn't initialise connection to server: %s\n"), ssh_get_error(ftp->session)); ssh_free(ftp->session); ftp->session = NULL; return r; } /* verify server */ if (verify_knownhost(ftp->session)) { ssh_disconnect(ftp->session); ssh_free(ftp->session); ftp->session = NULL; return -1; } /* authenticate user */ r = test_several_auth_methods(ftp->session, urlp); if (r != SSH_OK) { ftp_err(_("Authentication failed: %s\n"), ssh_get_error(ftp->session)); ssh_disconnect(ftp->session); ssh_free(ftp->session); ftp->session = NULL; return -1; } ftp->ssh_version = ssh_get_version(ftp->session); if (!ftp->ssh_version) { ftp_err(_("Couldn't initialise connection to server\n")); return -1; } ftp->sftp_session = sftp_new(ftp->session); if (!ftp->sftp_session) { ftp_err(_("Couldn't initialise ftp subsystem: %s\n"), ssh_get_error(ftp->session)); ssh_disconnect(ftp->session); ssh_free(ftp->session); ftp->session = NULL; return -1; } r = sftp_init(ftp->sftp_session); if (r != SSH_OK) { ftp_err(_("Couldn't initialise ftp subsystem: %s\n"), ssh_get_error(ftp->sftp_session)); sftp_free(ftp->sftp_session); ftp->sftp_session = NULL; ssh_disconnect(ftp->session); ssh_free(ftp->session); ftp->session = NULL; return r; } ftp->connected = true; ftp->loggedin = true; free(ftp->homedir); ftp->homedir = ftp_getcurdir(); url_destroy(ftp->url); ftp->url = url_clone(urlp); free(ftp->curdir); ftp->curdir = xstrdup(ftp->homedir); free(ftp->prevdir); ftp->prevdir = xstrdup(ftp->homedir); if (ftp->url->directory) ftp_chdir(ftp->url->directory); ftp_get_feat(); return 0; }
int ssh_open_url(url_t *urlp) { char *sftp = gvSFTPServerProgram; char *s; int r; args_clear(ftp->ssh_args); if(urlp->sftp_server) sftp = urlp->sftp_server; args_push_back(ftp->ssh_args, gvSSHProgram); if(gvSSHOptions && strlen(gvSSHOptions)) args_push_back(ftp->ssh_args, gvSSHOptions); args_push_back(ftp->ssh_args, urlp->hostname); r = get_username(urlp, gvUsername, false); if(r != 0) return r; if(urlp->username) { args_push_back(ftp->ssh_args, "-l"); args_push_back(ftp->ssh_args, urlp->username); } else { /* we need a username, otherwise other functions will fail */ urlp->username = xstrdup(gvUsername); } if(urlp->port) { char *p; asprintf(&p, "%d", urlp->port); args_push_back(ftp->ssh_args, "-p"); args_push_back(ftp->ssh_args, p); free(p); } if(ftp_get_verbosity() == vbDebug) args_push_back(ftp->ssh_args, "-v"); /* no subsystem if the server-spec contains a '/' */ if(sftp == 0 || strchr(sftp, '/') == 0) args_push_back(ftp->ssh_args, "-s"); /* Otherwise finish up and return the arg array */ if(sftp != 0) args_push_back(ftp->ssh_args, sftp); else args_push_back(ftp->ssh_args, "sftp"); s = args_cat2(ftp->ssh_args, 0); ftp_trace("SSH args: %s\n", s); if(ftp_get_verbosity() == vbDebug) fprintf(stderr, "SSH args: %s\n", s); free(s); args_add_null(ftp->ssh_args); if(ssh_connect(ftp->ssh_args->argv, &ftp->ssh_in, &ftp->ssh_out, &ftp->ssh_pid) == -1) { return -1; } ftp->ssh_version = ssh_init(); if(ftp->ssh_version == -1) { ftp_err("Couldn't initialise connection to server\n"); return -1; } ftp->connected = true; ftp->loggedin = true; ftp->homedir = ftp_getcurdir(); url_destroy(ftp->url); ftp->url = url_clone(urlp); ftp->curdir = xstrdup(ftp->homedir); ftp->prevdir = xstrdup(ftp->homedir); if(ftp->url->directory) ftp_chdir(ftp->url->directory); ftp_get_feat(); return 0; }