Author: mturk
Date: Tue Oct 25 08:29:47 2011
New Revision: 1188562
URL: http://svn.apache.org/viewvc?rev=1188562&view=rev
Log:
Implement SSL shutdown and add required API
Modified:
commons/sandbox/runtime/trunk/src/main/native/include/acr/ssl.h
commons/sandbox/runtime/trunk/src/main/native/modules/openssl/api.c
commons/sandbox/runtime/trunk/src/main/native/modules/openssl/netio.c
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/ssl.h
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/ssl.h?rev=1188562&r1=1188561&r2=1188562&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/ssl.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/ssl.h Tue Oct 25
08:29:47 2011
@@ -470,6 +470,7 @@ struct ssl_sd_t {
int shutdown_type;
int is_proxy;
int disabled;
+ int aborted;
int non_ssl_request;
};
Modified: commons/sandbox/runtime/trunk/src/main/native/modules/openssl/api.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/modules/openssl/api.c?rev=1188562&r1=1188561&r2=1188562&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/modules/openssl/api.c
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/modules/openssl/api.c Tue Oct
25 08:29:47 2011
@@ -98,6 +98,9 @@ struct SSLAPIst {
int (*fpBIO_printf)(BIO *, const char *, ...);
int (*fpBIO_vprintf)(BIO *, const char *, va_list);
int (*fpBIO_write)(BIO *, const void *, int);
+ void (*fpBIO_set_flags)(BIO *, int);
+ int (*fpBIO_test_flags)(const BIO *, int);
+ void (*fpBIO_clear_flags)(BIO *, int);
/*** BIGNUM ***/
BIGNUM* (*fpBN_new)(void);
@@ -208,6 +211,12 @@ struct SSLAPIst {
int (*fpSSL_connect)(SSL *);
void (*fpSSL_set_verify_result)(SSL *, long);
int (*fpSSL_set_fd)(SSL *, int);
+ void (*fpSSL_set_shutdown)(SSL *, int);
+ int (*fpSSL_shutdown)(SSL *);
+ void (*fpSSL_set_connect_state)(SSL *);
+ void (*fpSSL_set_accept_state)(SSL *);
+ int (*fpSSL_do_handshake)(SSL *);
+
CONST_SSL_METHOD* (*fpSSLv3_method)(void); /* SSLv3 */
@@ -356,6 +365,11 @@ ACR_JNI_EXPORT(jboolean, Native, ldopens
LIBSSL_FPLOAD(SSL_connect);
LIBSSL_FPLOAD(SSL_set_verify_result);
LIBSSL_FPLOAD(SSL_set_fd);
+ LIBSSL_FPLOAD(SSL_set_shutdown);
+ LIBSSL_FPLOAD(SSL_shutdown);
+ LIBSSL_FPLOAD(SSL_set_connect_state);
+ LIBSSL_FPLOAD(SSL_set_accept_state);
+ LIBSSL_FPLOAD(SSL_do_handshake);
LIBSSL_FPLOAD(SSLv3_method);
LIBSSL_FPLOAD(SSLv3_server_method);
@@ -406,6 +420,9 @@ ACR_JNI_EXPORT(jboolean, Native, ldopens
CRYPTO_FPLOAD(BIO_printf);
CRYPTO_FPLOAD(BIO_vprintf);
CRYPTO_FPLOAD(BIO_write);
+ CRYPTO_FPLOAD(BIO_set_flags);
+ CRYPTO_FPLOAD(BIO_test_flags);
+ CRYPTO_FPLOAD(BIO_clear_flags);
/*** BIGNUM ***/
CRYPTO_FPLOAD(BN_new);
@@ -645,6 +662,21 @@ int BIO_write(BIO *b, const void *data,
return SSLAPI_CALL(BIO_write)(b, data, len);
}
+void BIO_set_flags(BIO *b, int flags)
+{
+ SSLAPI_CALL(BIO_set_flags)(b, flags);
+}
+
+int BIO_test_flags(const BIO *b, int flags)
+{
+ return SSLAPI_CALL(BIO_test_flags)(b, flags);
+}
+
+void BIO_clear_flags(BIO *b, int flags)
+{
+ SSLAPI_CALL(BIO_clear_flags)(b, flags);
+}
+
BIGNUM *BN_new(void)
{
return SSLAPI_CALL(BN_new)();
@@ -1144,6 +1176,31 @@ int SSL_set_fd(SSL *s, int fd)
return SSLAPI_CALL(SSL_set_fd)(s, fd);
}
+void SSL_set_shutdown(SSL *ssl, int mode)
+{
+ SSLAPI_CALL(SSL_set_shutdown)(ssl, mode);
+}
+
+int SSL_shutdown(SSL *ssl)
+{
+ return SSLAPI_CALL(SSL_shutdown)(ssl);
+}
+
+void SSL_set_connect_state(SSL *s)
+{
+ SSLAPI_CALL(SSL_set_connect_state)(s);
+}
+
+void SSL_set_accept_state(SSL *s)
+{
+ SSLAPI_CALL(SSL_set_accept_state)(s);
+}
+
+int SSL_do_handshake(SSL *s)
+{
+ return SSLAPI_CALL(SSL_do_handshake)(s);
+}
+
#define IMPLEMENT_SSLAPI_METHOD(name) \
CONST_SSL_METHOD *name##_method(void) { \
return (*SSLapi.fp##name##_method)(); \
Modified: commons/sandbox/runtime/trunk/src/main/native/modules/openssl/netio.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/modules/openssl/netio.c?rev=1188562&r1=1188561&r2=1188562&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/modules/openssl/netio.c
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/modules/openssl/netio.c Tue
Oct 25 08:29:47 2011
@@ -28,6 +28,120 @@
#error "Cannot compile this file without HAVE_OPENSSL defined"
#endif
+static int SSL_smart_shutdown(SSL *ssl)
+{
+ int i;
+ int rc = 0;
+
+ /*
+ * Repeat the calls, because SSL_shutdown internally dispatches through a
+ * little state machine. Usually only one or two interation should be
+ * needed, so we restrict the total number of restrictions in order to
+ * avoid process hangs in case the client played bad with the socket
+ * connection and OpenSSL cannot recognize it.
+ */
+ for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) {
+ if ((rc = SSL_shutdown(ssl)))
+ break;
+ }
+ return rc;
+}
+
+/*
+ * Close the SSL part of the socket connection
+ * (called immediately _before_ the socket is closed)
+ * or called with
+ */
+static void SSL_io_shutdown(ssl_sd_t *ss, int abortive)
+{
+ SSL *ssl = ss->ssl;
+ int shutdown_type;
+
+ if (ssl == 0) {
+ /* Already shutdown */
+ return;
+ }
+
+ /*
+ * Now close the SSL layer of the connection. We've to take
+ * the TLSv1 standard into account here:
+ *
+ * | 7.2.1. Closure alerts
+ * |
+ * | The client and the server must share knowledge that the connection is
+ * | ending in order to avoid a truncation attack. Either party may
+ * | initiate the exchange of closing messages.
+ * |
+ * | close_notify
+ * | This message notifies the recipient that the sender will not send
+ * | any more messages on this connection. The session becomes
+ * | unresumable if any connection is terminated without proper
+ * | close_notify messages with level equal to warning.
+ * |
+ * | Either party may initiate a close by sending a close_notify alert.
+ * | Any data received after a closure alert is ignored.
+ * |
+ * | Each party is required to send a close_notify alert before closing
+ * | the write side of the connection. It is required that the other party
+ * | respond with a close_notify alert of its own and close down the
+ * | connection immediately, discarding any pending writes. It is not
+ * | required for the initiator of the close to wait for the responding
+ * | close_notify alert before closing the read side of the connection.
+ *
+ * This means we've to send a close notify message, but haven't to wait
+ * for the close notify of the client. Actually we cannot wait for the
+ * close notify of the client because some clients (including Netscape
+ * 4.x) don't send one, so we would hang.
+ */
+
+ /*
+ * exchange close notify messages, but allow the user
+ * to force the type of handshake via SetEnvIf directive
+ */
+ if (abortive) {
+ shutdown_type = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN;
+ }
+ else {
+ switch (ss->shutdown_type) {
+ case SSL_SHUTDOWN_TYPE_UNCLEAN:
+ /* perform no close notify handshake at all
+ * (violates the SSL/TLS standard!)
+ */
+ shutdown_type = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN;
+ break;
+ case SSL_SHUTDOWN_TYPE_ACCURATE:
+ /* send close notify and wait for clients close notify
+ * (standard compliant, but usually causes connection hangs)
+ */
+ shutdown_type = 0;
+ break;
+ default:
+ /*
+ * case SSL_SHUTDOWN_TYPE_UNSET:
+ * case SSL_SHUTDOWN_TYPE_STANDARD:
+ */
+ /* send close notify, but don't wait for clients close notify
+ * (standard compliant and safe, so it's the DEFAULT!)
+ */
+ shutdown_type = SSL_RECEIVED_SHUTDOWN;
+ break;
+ }
+ }
+ SSL_set_shutdown(ssl, shutdown_type);
+ SSL_smart_shutdown(ssl);
+ /* deallocate the SSL connection */
+ if (ss->peer != 0) {
+ X509_free(ss->peer);
+ ss->peer = 0;
+ }
+ SSL_free(ssl);
+ ss->ssl = 0;
+ if (abortive) {
+ /* prevent any further I/O */
+ ss->aborted = 1;
+ }
+}
+
ACR_NET_EXPORT(jlong, SSLSocketDescriptor, socket0)(JNI_STDARGS, jlong ssd,
jlong ctx)
{
@@ -72,12 +186,7 @@ ACR_NET_EXPORT(jint, SSLSocketDescriptor
if (ss == 0)
return ACR_EBADF;
if (AcrAtomic32Dec(&ss->refs) == 0) {
- if (ss->ssl != 0) {
- SSL_free(ss->ssl);
- }
- if (ss->peer != 0) {
- X509_free(ss->peer);
- }
+ SSL_io_shutdown(ss, 1);
AcrAtomic32Dec(&ss->sd->refs);
AcrFree(ss);
}