- Linus Nielsen Feltzing introduced the --ftp-ssl-ccc command line option to
curl that uses the new CURLOPT_FTP_SSL_CCC option in libcurl. If enabled, it will make libcurl shutdown SSL/TLS after the authentication is done on a FTP-SSL operation.
This commit is contained in:
100
lib/ssluse.c
100
lib/ssluse.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -728,6 +728,102 @@ void Curl_ossl_close(struct connectdata *conn)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called to shut down the SSL layer but keep the
|
||||
* socket open (CCC - Clear Command Channel)
|
||||
*/
|
||||
int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
int result;
|
||||
int retval = 0;
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
struct SessionHandle *data = conn->data;
|
||||
char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
|
||||
to be at least 120 bytes long. */
|
||||
unsigned long sslerror;
|
||||
ssize_t nread;
|
||||
int err;
|
||||
int done = 0;
|
||||
|
||||
/* This has only been tested on the proftpd server, and the mod_tls code
|
||||
sends a close notify alert without waiting for a close notify alert in
|
||||
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(connssl->handle) {
|
||||
while(!done) {
|
||||
int what = Curl_select(conn->sock[sockindex],
|
||||
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
||||
if(what > 0) {
|
||||
/* Something to read, let's do it and hope that it is the close
|
||||
notify alert from the server */
|
||||
nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf,
|
||||
sizeof(buf));
|
||||
err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread);
|
||||
|
||||
switch(err) {
|
||||
case SSL_ERROR_NONE: /* this is not an error */
|
||||
case SSL_ERROR_ZERO_RETURN: /* no more data */
|
||||
/* This is the expected response. There was no data but only
|
||||
the close notify alert */
|
||||
done = 1;
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
/* there's data pending, re-invoke SSL_read() */
|
||||
infof(data, "SSL_ERROR_WANT_READ\n");
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
/* SSL wants a write. Really odd. Let's bail out. */
|
||||
infof(data, "SSL_ERROR_WANT_WRITE\n");
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
/* openssl/ssl.h says "look at error stack/return value/errno" */
|
||||
sslerror = ERR_get_error();
|
||||
failf(conn->data, "SSL read: %s, errno %d",
|
||||
ERR_error_string(sslerror, buf),
|
||||
Curl_sockerrno() );
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(0 == what) {
|
||||
/* timeout */
|
||||
failf(data, "SSL shutdown timeout");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* anything that gets here is fatally bad */
|
||||
failf(data, "select on SSL socket, errno: %d", Curl_sockerrno());
|
||||
retval = -1;
|
||||
done = 1;
|
||||
}
|
||||
} /* while()-loop for the select() */
|
||||
|
||||
if(data->set.verbose) {
|
||||
switch(SSL_get_shutdown(connssl->handle)) {
|
||||
case SSL_SENT_SHUTDOWN:
|
||||
infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
|
||||
break;
|
||||
case SSL_RECEIVED_SHUTDOWN:
|
||||
infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n");
|
||||
break;
|
||||
case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN:
|
||||
infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|"
|
||||
"SSL_RECEIVED__SHUTDOWN\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
connssl->use = FALSE; /* get back to ordinary socket usage */
|
||||
|
||||
SSL_free (connssl->handle);
|
||||
connssl->handle = NULL;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Curl_ossl_session_free(void *ptr)
|
||||
{
|
||||
/* free the ID */
|
||||
@@ -1629,7 +1725,7 @@ Curl_ossl_connect_common(struct connectdata *conn,
|
||||
while(1) {
|
||||
int what = Curl_select(readfd, writefd, nonblocking?0:(int)timeout_ms);
|
||||
if(what > 0)
|
||||
/* reabable or writable, go loop in the outer loop */
|
||||
/* readable or writable, go loop in the outer loop */
|
||||
break;
|
||||
else if(0 == what) {
|
||||
if (nonblocking) {
|
||||
|
||||
Reference in New Issue
Block a user