aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/curl.110
-rw-r--r--docs/libcurl/curl_easy_setopt.319
-rw-r--r--include/curl/curl.h8
-rw-r--r--lib/ftp.c2
-rw-r--r--lib/gtls.c3
-rw-r--r--lib/ssluse.c3
-rw-r--r--lib/url.c2
-rw-r--r--lib/urldata.h2
-rw-r--r--src/main.c23
9 files changed, 61 insertions, 11 deletions
diff --git a/docs/curl.1 b/docs/curl.1
index 881cd77a2..56659e8c8 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -448,10 +448,18 @@ If this option is used twice, the second will again disable this.
(FTP) Use CCC (Clear Command Channel)
Shuts down the SSL/TLS layer after authenticating. The rest of the
control channel communication will be unencrypted. This allows
-NAT routers to follow the FTP transaction.
+NAT routers to follow the FTP transaction. The default mode is
+passive. See --ftp-ssl-ccc-mode for other modes.
(Added in 7.16.1)
If this option is used twice, the second will again disable this.
+.IP "--ftp-ssl-ccc-mode [active/passive]"
+(FTP) Use CCC (Clear Command Channel)
+Sets the CCC mode. The passive mode will not initiate the shutdown, but
+instead wait for the server to do it, and will not reply to the
+shutdown from the server. The active mode initiates the shutdown and
+waits for a reply from the server.
+(Added in 7.16.2)
.IP "-F/--form <name=content>"
(HTTP) This lets curl emulate a filled in form in which a user has pressed the
submit button. This causes curl to POST data using the Content-Type
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index 66ca11f34..9e32f13aa 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -936,11 +936,20 @@ Try "AUTH SSL" first, and only if that fails try "AUTH TLS"
Try "AUTH TLS" first, and only if that fails try "AUTH SSL"
.RE
.IP CURLOPT_FTP_SSL_CCC
-Pass a long that is set to 0 to disable and 1 to enable. If enabled, this
-option makes libcurl use CCC (Clear Command Channel). It shuts down the
-SSL/TLS layer after authenticating. The rest of the control channel
-communication will be unencrypted. This allows NAT routers to follow the FTP
-transaction. (Added in 7.16.1)
+If enabled, this option makes libcurl use CCC (Clear Command Channel). It
+shuts down the SSL/TLS layer after authenticating. The rest of the
+control channel communication will be unencrypted. This allows NAT routers
+to follow the FTP transaction. Pass a long using one of the values below.
+(Added in 7.16.1)
+.RS
+.IP CURLFTPSSL_CCC_NONE
+Don't attempt to use CCC.
+.IP CURLFTPSSL_CCC_PASSIVE
+Do not initiate the shutdown, but wait for the server to do it. Do not send
+a reply.
+.IP CURLFTPSSL_CCC_ACTIVE
+Initiate the shutdown and wait for a reply.
+.RE
.IP CURLOPT_FTP_ACCOUNT
Pass a pointer to a zero-terminated string (or NULL to disable). When an FTP
server asks for "account data" after user name and password has been provided,
diff --git a/include/curl/curl.h b/include/curl/curl.h
index e911fca5a..d7f36645c 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -465,6 +465,14 @@ typedef enum {
CURLFTPSSL_LAST /* not an option, never use */
} curl_ftpssl;
+/* parameter for the CURLOPT_FTP_SSL_CCC option */
+typedef enum {
+ CURLFTPSSL_CCC_NONE, /* do not send CCC */
+ CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
+ CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */
+ CURLFTPSSL_CCC_LAST /* not an option, never use */
+} curl_ftpccc;
+
/* parameter for the CURLOPT_FTPSSLAUTH option */
typedef enum {
CURLFTPAUTH_DEFAULT, /* let libcurl decide */
diff --git a/lib/ftp.c b/lib/ftp.c
index a23acd43e..8328315dc 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2566,7 +2566,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* we failed and bails out */
return CURLE_FTP_SSL_FAILED;
- if(data->set.ftp_use_ccc) {
+ if(data->set.ftp_ccc) {
/* CCC - Clear Command Channel
*/
NBFTPSENDF(conn, "CCC", NULL);
diff --git a/lib/gtls.c b/lib/gtls.c
index daf69aafe..f8c103450 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -533,6 +533,9 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
response. Thus we wait for a close notify alert from the server, but
we do not send one. Let's hope other servers do the same... */
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
+
if(conn->ssl[sockindex].session) {
while(!done) {
int what = Curl_select(conn->sock[sockindex],
diff --git a/lib/ssluse.c b/lib/ssluse.c
index dc4fc927c..b362ab3f2 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -749,6 +749,9 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
response. Thus we wait for a close notify alert from the server, but
we do not send one. Let's hope other servers do the same... */
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ (void)SSL_shutdown(connssl->handle);
+
if(connssl->handle) {
while(!done) {
int what = Curl_select(conn->sock[sockindex],
diff --git a/lib/url.c b/lib/url.c
index 3bd8dcb6d..05920b72e 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1156,7 +1156,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_FTP_SSL_CCC:
- data->set.ftp_use_ccc = (bool)(0 != va_arg(param, long));
+ data->set.ftp_ccc = va_arg(param, long);
break;
case CURLOPT_FTP_SKIP_PASV_IP:
diff --git a/lib/urldata.h b/lib/urldata.h
index d50f9e44a..3325699d7 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1283,10 +1283,10 @@ struct UserDefined {
bool reuse_fresh; /* do not re-use an existing connection */
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
bool ftp_use_eprt; /* if EPRT is to be attempted or not */
- bool ftp_use_ccc; /* if CCC is to be attempted or not */
curl_ftpssl ftp_ssl; /* if AUTH TLS is to be attempted etc */
curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
+ curl_ftpccc ftp_ccc; /* FTP CCC options */
bool no_signal; /* do not use any signal/alarm handler */
bool global_dns_cache; /* subject for future removal */
bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */
diff --git a/src/main.c b/src/main.c
index b3f629590..ed6f338ef 100644
--- a/src/main.c
+++ b/src/main.c
@@ -440,6 +440,7 @@ struct Configurable {
bool ftp_ssl_reqd;
bool ftp_ssl_control;
bool ftp_ssl_ccc;
+ int ftp_ssl_ccc_mode;
char *socksproxy; /* set to server string */
int socksver; /* set to CURLPROXY_SOCKS* define */
@@ -627,7 +628,8 @@ static void help(void)
" --ftp-ssl Try SSL/TLS for ftp transfer (F)",
" --ftp-ssl-control Require SSL/TLS for ftp login, clear for transfer (F)",
" --ftp-ssl-reqd Require SSL/TLS for ftp transfer (F)",
- " --ftp-ssl-ccc Send CCC after authenticating (F)",
+ " --ftp-ssl-ccc Send CCC after authenticating. (F)",
+ " --ftp-ssl-ccc-mode [active/passive] Set CCC mode (F)",
" -F/--form <name=content> Specify HTTP multipart POST data (H)",
" --form-string <name=string> Specify HTTP multipart POST data (H)",
" -g/--globoff Disable URL sequences and ranges using {} and []",
@@ -1380,6 +1382,16 @@ static int ftpfilemethod(struct Configurable *config, char *str)
return CURLFTPMETHOD_MULTICWD;
}
+static int ftpcccmethod(struct Configurable *config, char *str)
+{
+ if(curlx_strequal("passive", str))
+ return CURLFTPSSL_CCC_PASSIVE;
+ if(curlx_strequal("active", str))
+ return CURLFTPSSL_CCC_ACTIVE;
+ warnf(config, "unrecognized ftp CCC method '%s', using default\n", str);
+ return CURLFTPSSL_CCC_PASSIVE;
+}
+
static ParameterError getparameter(char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */
bool *usedarg, /* set to TRUE if the arg
@@ -1460,6 +1472,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$w", "no-sessionid", FALSE},
{"$x", "ftp-ssl-control", FALSE},
{"$y", "ftp-ssl-ccc", FALSE},
+ {"$j", "ftp-ssl-ccc-mode", TRUE},
{"$z", "libcurl", TRUE},
{"$#", "raw", FALSE},
@@ -1888,6 +1901,12 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
break;
case 'y': /* --ftp-ssl-ccc */
config->ftp_ssl_ccc ^= TRUE;
+ if(!config->ftp_ssl_ccc_mode)
+ config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
+ break;
+ case 'j': /* --ftp-ssl-ccc-mode */
+ config->ftp_ssl_ccc = TRUE;
+ config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
break;
case 'z': /* --libcurl */
GetStr(&config->libcurl, nextarg);
@@ -4211,7 +4230,7 @@ operate(struct Configurable *config, int argc, char *argv[])
/* new in curl 7.16.1 */
if(config->ftp_ssl_ccc)
- my_setopt(curl, CURLOPT_FTP_SSL_CCC, TRUE);
+ my_setopt(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode);
/* new in curl 7.11.1, modified in 7.15.2 */
if(config->socksproxy) {