diff --git a/CHANGES b/CHANGES index d2c219bf42..29c2aa2639 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,10 @@ Changelog Daniel (26 July 2006) +- Dan Nelson added the CURLOPT_FTP_ALTERNATIVE_TO_USER libcurl option and curl + tool option named --ftp-alternative-to-user. It provides a mean to send a + particular command if the normal USER/PASS approach fails. + - Michael Jerris added magic that builds lib/curllib.vcproj automatically for newer MSVC. diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 1eef7be4f0..a29daea1ae 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -2,8 +2,8 @@ Curl and libcurl 7.15.5 Public curl release number: 95 Releases counted from the very beginning: 122 - Available command line options: 112 - Available curl_easy_setopt() options: 132 + Available command line options: 113 + Available curl_easy_setopt() options: 133 Number of public functions in libcurl: 49 Amount of public web site mirrors: 33 Number of known libcurl bindings: 32 @@ -11,6 +11,8 @@ Curl and libcurl 7.15.5 This release includes the following changes: + o added CURLOPT_FTP_ALTERNATIVE_TO_USER and --ftp-alternative-to-user + o now includes a vcproj file for building libcurl o added curl_formget() o added CURLOPT_MAX_SEND_SPEED_LARGE and CURLOPT_MAX_RECV_SPEED_LARGE o configure --enable-hidden-symbols @@ -41,6 +43,6 @@ advice from friends like these: Dan Fandrich, Peter Silva, Arve Knudsen, Michael Wallner, Toshiyuki Maezawa, Ingmar Runge, Ates Goral, David McCreedy, Jari Sundell, Georg Horn, - Gisle Vanem, Yang Tse + Gisle Vanem, Yang Tse, Michael Jerris, Dan Nelson Thanks! (and sorry if I forgot to mention someone) diff --git a/docs/curl.1 b/docs/curl.1 index d99fbceaa8..de72eb5b61 100644 --- a/docs/curl.1 +++ b/docs/curl.1 @@ -396,6 +396,11 @@ in 7.11.0) If this option is used several times, the following occurrences make no difference. +.IP "--ftp-alternative-to-user " +(FTP) If authenticating with the USER and PASS commands fails, send this +command. When connecting to Tumbleweed's Secure Transport server over FTPS +using a client certificate, using "SITE AUTH" will tell the server to retrieve +the username from the certificate. (Added in 7.15.5) .IP "--ftp-skip-pasv-ip" (FTP) Tell curl to not use the IP address the server suggests in its response to curl's PASV command when curl connects the data connection. Instead curl diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index c4b9695777..6ac538a7a7 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -859,6 +859,12 @@ waiting for a response, this value overrides \fICURLOPT_TIMEOUT\fP. It is recommended that if used in conjunction with \fICURLOPT_TIMEOUT\fP, you set \fICURLOPT_FTP_RESPONSE_TIMEOUT\fP to a value smaller than \fICURLOPT_TIMEOUT\fP. (Added in 7.10.8) +.IP CURLOPT_FTP_ALTERNATIVE_TO_USER +Pass a char * as parameter, pointing to a string which will be used to +authenticate if the usual FTP "USER user" and "PASS password" negotiation +fails. This is currently only known to be required when connecting to +Tumbleweed's Secure Transport FTPS server using client certificates for +authentication. (Added in 7.15.5) .IP CURLOPT_FTP_SKIP_PASV_IP Pass a long. If set to a non-zero value, it instructs libcurl to not use the IP address the server suggests in its 227-response to libcurl's PASV command diff --git a/include/curl/curl.h b/include/curl/curl.h index b9b341deef..db14fe1f59 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -61,14 +61,14 @@ extern "C" { #ifdef CURL_HIDDEN_SYMBOLS /* - * This definition is used to make external definitions visibile in the + * This definition is used to make external definitions visibile in the * shared library when symbols are hidden by default. It makes no * difference when compiling applications whether this is set or not, * only when compiling the library. */ #define CURL_EXTERN CURL_EXTERN_SYMBOL #else -#define CURL_EXTERN +#define CURL_EXTERN #endif #endif @@ -979,6 +979,9 @@ typedef enum { CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/ftp.c b/lib/ftp.c index c270305043..c17d9fbaa2 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -699,6 +699,7 @@ static CURLcode ftp_state_user(struct connectdata *conn) NBFTPSENDF(conn, "USER %s", ftp->user?ftp->user:""); state(conn, FTP_USER); + conn->data->state.ftp_trying_alternative = FALSE; return CURLE_OK; } @@ -2302,8 +2303,19 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn, 530 User ... access denied (the server denies to log the specified user) */ - failf(data, "Access denied: %03d", ftpcode); - result = CURLE_LOGIN_DENIED; + + if (conn->data->set.ftp_alternative_to_user && + !conn->data->state.ftp_trying_alternative) { + /* Ok, USER failed. Let's try the supplied command. */ + NBFTPSENDF(conn, "%s", conn->data->set.ftp_alternative_to_user); + conn->data->state.ftp_trying_alternative = TRUE; + state(conn, FTP_USER); + result = CURLE_OK; + } + else { + failf(data, "Access denied: %03d", ftpcode); + result = CURLE_LOGIN_DENIED; + } } return result; } diff --git a/lib/url.c b/lib/url.c index 17e3a7f57c..b25d02be85 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1546,6 +1546,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, data->set.connect_only = va_arg(param, long)?TRUE:FALSE; break; + case CURLOPT_FTP_ALTERNATIVE_TO_USER: + data->set.ftp_alternative_to_user = va_arg(param, char *); + break; + default: /* unknown tag and its companion, just ignore: */ result = CURLE_FAILED_INIT; /* correct this */ diff --git a/lib/urldata.h b/lib/urldata.h index 63ccfe70ae..c804105b6b 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -937,6 +937,9 @@ struct UrlState { /* a place to store the most recenlty set FTP entrypath */ char *most_recent_ftp_entrypath; + /* set after initial USER failure, to prevent an authentication loop */ + bool ftp_trying_alternative; + #ifndef WIN32 /* do FTP line-end conversions on most platforms */ #define CURL_DO_LINEEND_CONV @@ -1054,6 +1057,7 @@ struct UserDefined { bool cookiesession; /* new cookie session? */ bool crlf; /* convert crlf on ftp upload(?) */ char *ftp_account; /* ftp account data */ + char *ftp_alternative_to_user; /* command to send if USER/PASS fails */ struct curl_slist *quote; /* after connection is established */ struct curl_slist *postquote; /* after the transfer */ struct curl_slist *prequote; /* before the transfer, after type */ diff --git a/src/main.c b/src/main.c index 3e717a3d25..af20a396c7 100644 --- a/src/main.c +++ b/src/main.c @@ -353,6 +353,7 @@ struct Configurable { struct curl_slist *tp_postquote; struct curl_slist *tp_prequote; char *ftp_account; /* for ACCT */ + char *ftp_alternative_to_user; /* send command if USER/PASS fails */ int ftp_filemethod; bool ignorecl; /* --ignore-content-length */ @@ -1340,6 +1341,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ {"$r", "ftp-method", TRUE}, {"$s", "local-port", TRUE}, {"$t", "socks4", TRUE}, + {"$u", "ftp-alternative-to-user", TRUE}, {"0", "http1.0", FALSE}, {"1", "tlsv1", FALSE}, @@ -1776,6 +1778,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ } } break; + case 'u': /* --ftp-alternative-to-user */ + GetStr(&config->ftp_alternative_to_user, nextarg); + break; } break; case '#': /* --progress-bar */ @@ -3998,6 +4003,9 @@ operate(struct Configurable *config, int argc, char *argv[]) curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, config->localportrange); } + /* curl x.xx.x */ + curl_easy_setopt(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, config->ftp_alternative_to_user); + retry_numretries = config->req_retry; retrystart = curlx_tvnow();