static CURLcode choose_mech(struct connectdata *conn) { int ret; struct Curl_easy *data = conn->data; void *tmp_allocation; const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; tmp_allocation = realloc(conn->app_data, mech->size); if(tmp_allocation == NULL) { failf(data, "Failed realloc of size %u", mech->size); mech = NULL; return CURLE_OUT_OF_MEMORY; } conn->app_data = tmp_allocation; if(mech->init) { ret = mech->init(conn->app_data); if(ret) { infof(data, "Failed initialization for %s. Skipping it.\n", mech->name); return CURLE_FAILED_INIT; } } infof(data, "Trying mechanism %s...\n", mech->name); ret = ftp_send_command(conn, "AUTH %s", mech->name); if(ret < 0) /* FIXME: This error is too generic but it is OK for now. */ return CURLE_COULDNT_CONNECT; if(ret/100 != 3) { switch(ret) { case 504: infof(data, "Mechanism %s is not supported by the server (server " "returned ftp code: 504).\n", mech->name); break; case 534: infof(data, "Mechanism %s was rejected by the server (server returned " "ftp code: 534).\n", mech->name); break; default: if(ret/100 == 5) { infof(data, "server does not support the security extensions\n"); return CURLE_USE_SSL_FAILED; } break; } return CURLE_LOGIN_DENIED; } /* Authenticate */ ret = mech->auth(conn->app_data, conn); if(ret != AUTH_CONTINUE) { if(ret != AUTH_OK) { /* Mechanism has dumped the error to stderr, don't error here. */ return -1; } DEBUGASSERT(ret == AUTH_OK); conn->mech = mech; conn->sec_complete = 1; conn->recv[FIRSTSOCKET] = sec_recv; conn->send[FIRSTSOCKET] = sec_send; conn->recv[SECONDARYSOCKET] = sec_recv; conn->send[SECONDARYSOCKET] = sec_send; conn->command_prot = PROT_SAFE; /* Set the requested protection level */ /* BLOCKING */ (void)sec_set_protection_level(conn); } return CURLE_OK; }
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; }