Author: mturk
Date: Thu Nov 15 07:59:36 2012
New Revision: 1409681
URL: http://svn.apache.org/viewvc?rev=1409681&view=rev
Log:
Clean up SSL network layer. Ensure the behavior is similar to standard APR layer
Modified:
tomcat/native/branches/1.1.x/native/src/sslnetwork.c
Modified: tomcat/native/branches/1.1.x/native/src/sslnetwork.c
URL:
http://svn.apache.org/viewvc/tomcat/native/branches/1.1.x/native/src/sslnetwork.c?rev=1409681&r1=1409680&r2=1409681&view=diff
==============================================================================
--- tomcat/native/branches/1.1.x/native/src/sslnetwork.c (original)
+++ tomcat/native/branches/1.1.x/native/src/sslnetwork.c Thu Nov 15 07:59:36
2012
@@ -169,9 +169,9 @@ static tcn_ssl_conn_t *ssl_create(JNIEnv
#endif
static apr_status_t wait_for_io_or_timeout(tcn_ssl_conn_t *con,
- int for_what)
+ int for_what,
+ apr_interval_time_t timeout)
{
- apr_interval_time_t timeout;
apr_pollfd_t pfd;
int type;
apr_status_t status;
@@ -206,8 +206,11 @@ static apr_status_t wait_for_io_or_timeo
return APR_EINVAL;
break;
}
-
- apr_socket_timeout_get(con->sock, &timeout);
+ if (timeout <= 0) {
+ /* Waiting on zero or infinite timeouts is not allowed
+ */
+ return APR_EAGAIN;
+ }
pfd.desc_type = APR_POLL_SOCKET;
pfd.desc.s = con->sock;
pfd.reqevents = type;
@@ -305,6 +308,7 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, hand
{
tcn_socket_t *ss = J2P(sock, tcn_socket_t *);
tcn_ssl_conn_t *con;
+ apr_interval_time_t timeout;
int s, i;
long vr;
apr_status_t rv;
@@ -315,12 +319,15 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, hand
if (ss->net->type != TCN_SOCKET_SSL)
return APR_EINVAL;
con = (tcn_ssl_conn_t *)ss->opaque;
+
+ apr_socket_timeout_get(con->sock, &timeout);
while (!SSL_is_init_finished(con->ssl)) {
+ ERR_clear_error();
if ((s = SSL_do_handshake(con->ssl)) <= 0) {
- apr_status_t os = apr_get_netos_error();
if (!con->ssl)
- return os == APR_SUCCESS ? APR_ENOTSOCK : os;
- i = SSL_get_error(con->ssl, s);
+ return APR_ENOTSOCK;
+ rv = apr_get_netos_error();
+ i = SSL_get_error(con->ssl, s);
switch (i) {
case SSL_ERROR_NONE:
con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
@@ -328,23 +335,23 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, hand
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
- if ((rv = wait_for_io_or_timeout(con, i)) != APR_SUCCESS) {
+ if ((rv = wait_for_io_or_timeout(con, i, timeout)) !=
APR_SUCCESS) {
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return rv;
}
break;
case SSL_ERROR_SYSCALL:
- case SSL_ERROR_SSL:
- if (!APR_STATUS_IS_EAGAIN(os) &&
- !APR_STATUS_IS_EINTR(os)) {
- con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
- return os == APR_SUCCESS ? APR_EGENERAL : os;
- }
- break;
+#if !defined(_WIN32)
+ if (APR_STATUS_IS_EINTR(rv)) {
+ /* Interrupted by signal */
+ continue;
+ }
+#endif
+ /* Fall trough */
default:
/*
- * Anything else is a fatal error
- */
+ * Anything else is a fatal error
+ */
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return SSL_TO_APR_ERROR(i);
break;
@@ -385,50 +392,58 @@ static apr_status_t APR_THREAD_FUNC
ssl_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len)
{
tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock;
- int s, i, wr = (int)(*len);
- apr_status_t rv = APR_SUCCESS;
+ int s, i, rd = (int)(*len);
+ apr_status_t rv;
+ apr_interval_time_t timeout;
+ *len = 0;
if (con->reneg_state == RENEG_ABORT) {
- *len = 0;
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return APR_ECONNABORTED;
}
+ apr_socket_timeout_get(con->sock, &timeout);
for (;;) {
- if ((s = SSL_read(con->ssl, buf, wr)) <= 0) {
- apr_status_t os = apr_get_netos_error();
+ ERR_clear_error();
+ if ((s = SSL_read(con->ssl, buf, rd)) <= 0) {
if (!con->ssl)
- return os == APR_SUCCESS ? APR_ENOTSOCK : os;
-
- i = SSL_get_error(con->ssl, s);
+ return APR_ENOTSOCK;
+ rv = apr_get_netos_error();
+ i = SSL_get_error(con->ssl, s);
/* Special case if the "close notify" alert send by peer */
if (s == 0 && (con->ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) {
- *len = 0;
+ con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
return APR_EOF;
}
switch (i) {
- case SSL_ERROR_ZERO_RETURN:
- *len = 0;
- con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
- return APR_EOF;
- break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
- if ((rv = wait_for_io_or_timeout(con, i)) != APR_SUCCESS) {
+ if ((rv = wait_for_io_or_timeout(con, i, timeout)) !=
APR_SUCCESS) {
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return rv;
}
break;
case SSL_ERROR_SYSCALL:
- case SSL_ERROR_SSL:
- if (!APR_STATUS_IS_EAGAIN(os) &&
- !APR_STATUS_IS_EINTR(os)) {
- con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
- return os == APR_SUCCESS ? APR_EGENERAL : os;
+ if (APR_STATUS_IS_EPIPE(rv) ||
APR_STATUS_IS_ECONNRESET(rv)) {
+ con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
+ return APR_EOF;
}
- break;
+#if !defined(_WIN32)
+ else if (APR_STATUS_IS_EINTR(rv)) {
+ /* Interrupted by signal
+ */
+ continue;
+ }
+#endif
+ /* Fall trough */
+ case SSL_ERROR_ZERO_RETURN:
+ if (s == 0) {
+ con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
+ return APR_EOF;
+ }
+ /* Fall trough */
default:
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
- return os;
+ return APR_EGENERAL;
break;
}
}
@@ -438,7 +453,7 @@ ssl_socket_recv(apr_socket_t *sock, char
break;
}
}
- return rv;
+ return APR_SUCCESS;
}
static apr_status_t APR_THREAD_FUNC
@@ -447,50 +462,66 @@ ssl_socket_send(apr_socket_t *sock, cons
{
tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock;
int s, i, wr = (int)(*len);
- apr_status_t rv = APR_SUCCESS;
- apr_int32_t nb;
+ apr_status_t rv;
+ apr_interval_time_t timeout;
+ *len = 0;
if (con->reneg_state == RENEG_ABORT) {
- *len = 0;
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return APR_ECONNABORTED;
}
- apr_socket_opt_get(con->sock, APR_SO_NONBLOCK, &nb);
+ if (!SSL_is_init_finished(con->ssl)) {
+ /* XXX: Is this a correct retval ? */
+ return APR_EINPROGRESS;
+ }
+ if (wr == 0) {
+ /* According to docs calling SSL_write() with num=0 bytes
+ * to be sent the behaviour is undefined.
+ */
+ return APR_EINVAL;
+ }
+ apr_socket_timeout_get(con->sock, &timeout);
for (;;) {
+ ERR_clear_error();
if ((s = SSL_write(con->ssl, buf, wr)) <= 0) {
- apr_status_t os = apr_get_netos_error();
if (!con->ssl)
- return os == APR_SUCCESS ? APR_ENOTSOCK : os;
-
- i = SSL_get_error(con->ssl, s);
+ return APR_ENOTSOCK;
+ rv = apr_get_netos_error();
+ i = SSL_get_error(con->ssl, s);
switch (i) {
- case SSL_ERROR_ZERO_RETURN:
- *len = 0;
- con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
- return APR_EOF;
- break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
- if (nb && i == SSL_ERROR_WANT_WRITE) {
- *len = 0;
- return APR_SUCCESS;
- }
- if ((rv = wait_for_io_or_timeout(con, i)) != APR_SUCCESS) {
+ if ((rv = wait_for_io_or_timeout(con, i, timeout)) !=
APR_SUCCESS) {
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return rv;
}
break;
case SSL_ERROR_SYSCALL:
- case SSL_ERROR_SSL:
- if (!APR_STATUS_IS_EAGAIN(os) &&
- !APR_STATUS_IS_EINTR(os)) {
- con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
- return os == APR_SUCCESS ? APR_EGENERAL : os;
+ if (s == -1) {
+ if (APR_STATUS_IS_EPIPE(rv) ||
APR_STATUS_IS_ECONNRESET(rv)) {
+ con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
+ return APR_EOF;
+ }
+#if !defined(_WIN32)
+ else if (APR_STATUS_IS_EINTR(rv)) {
+ /* Interrupted by signal
+ */
+ continue;
+ }
+#endif
}
+ con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
+ return rv;
break;
+ case SSL_ERROR_ZERO_RETURN:
+ if (s == 0) {
+ con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
+ return APR_EOF;
+ }
+ /* Fall trough */
default:
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
- return os;
+ return rv;
break;
}
}
@@ -499,7 +530,7 @@ ssl_socket_send(apr_socket_t *sock, cons
break;
}
}
- return rv;
+ return APR_SUCCESS;
}
static apr_status_t APR_THREAD_FUNC
@@ -584,6 +615,8 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, rene
tcn_ssl_conn_t *con;
int retVal;
int ecode = SSL_ERROR_WANT_READ;
+ apr_status_t rv;
+ apr_interval_time_t timeout;
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
@@ -613,14 +646,15 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, rene
}
con->ssl->state = SSL_ST_ACCEPT;
+ apr_socket_timeout_get(con->sock, &timeout);
ecode = SSL_ERROR_WANT_READ;
while (ecode == SSL_ERROR_WANT_READ) {
retVal = SSL_do_handshake(con->ssl);
if (retVal <= 0) {
ecode = SSL_get_error(con->ssl, retVal);
if (ecode == SSL_ERROR_WANT_READ) {
- if (wait_for_io_or_timeout(con, ecode) != APR_SUCCESS)
- return APR_EGENERAL; /* Can't wait */
+ if ((rv = wait_for_io_or_timeout(con, ecode, timeout)) !=
APR_SUCCESS)
+ return rv; /* Can't wait */
continue; /* It should be ok now */
}
else
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]