- 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:
Daniel Stenberg
2007-01-05 23:11:14 +00:00
parent b7aaa4d907
commit 4750e6f3c5
16 changed files with 269 additions and 20 deletions

View File

@@ -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) {