📄 sslnetwork.c
字号:
TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock)
{
tcn_socket_t *ss = J2P(sock, tcn_socket_t *);
tcn_ssl_conn_t *con;
int s, i;
apr_status_t rv;
X509 *peer;
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
if (ss->net->type != TCN_SOCKET_SSL)
return APR_EINVAL;
con = (tcn_ssl_conn_t *)ss->opaque;
while (!SSL_is_init_finished(con->ssl)) {
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);
switch (i) {
case SSL_ERROR_NONE:
con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
return APR_SUCCESS;
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
if ((rv = wait_for_io_or_timeout(con, i)) != 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;
}
break;
default:
/*
* Anything else is a fatal error
*/
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return SSL_TO_APR_ERROR(i);
break;
}
}
if (!con->ssl)
return APR_ENOTSOCK;
/*
* Check for failed client authentication
*/
if (SSL_get_verify_result(con->ssl) != X509_V_OK) {
/* TODO: Log SSL client authentication failed */
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
/* TODO: Figure out the correct return value */
return APR_EGENERAL;
}
/*
* Remember the peer certificate
*/
if ((peer = SSL_get_peer_certificate(con->ssl)) != NULL) {
if (con->peer)
X509_free(con->peer);
con->peer = peer;
}
}
return APR_SUCCESS;
}
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;
for (;;) {
if ((s = SSL_read(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);
/* Special case if the "close notify" alert send by peer */
if (s == 0 && (con->ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) {
*len = 0;
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) {
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;
}
break;
default:
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return os;
break;
}
}
else {
*len = s;
con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
break;
}
}
return rv;
}
static apr_status_t APR_THREAD_FUNC
ssl_socket_send(apr_socket_t *sock, const 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;
for (;;) {
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);
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) {
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;
}
break;
default:
con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN;
return os;
break;
}
}
else {
*len = s;
break;
}
}
return rv;
}
static apr_status_t APR_THREAD_FUNC
ssl_socket_sendv(apr_socket_t *sock,
const struct iovec *vec,
apr_int32_t nvec, apr_size_t *len)
{
tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock;
apr_status_t rv;
apr_size_t written = 0;
apr_int32_t i;
for (i = 0; i < nvec; i++) {
apr_size_t rd = vec[i].iov_len;
if ((rv = ssl_socket_send((apr_socket_t *)con,
vec[i].iov_base, &rd)) != APR_SUCCESS) {
*len = written;
return rv;
}
written += rd;
}
*len = written;
return APR_SUCCESS;
}
static tcn_nlayer_t ssl_socket_layer = {
TCN_SOCKET_SSL,
ssl_cleanup,
ssl_socket_close,
ssl_socket_shutdown,
ssl_socket_opt_get,
ssl_socket_opt_set,
ssl_socket_timeout_get,
ssl_socket_timeout_set,
ssl_socket_send,
ssl_socket_sendv,
ssl_socket_recv
};
TCN_IMPLEMENT_CALL(jint, SSLSocket, attach)(TCN_STDARGS, jlong ctx,
jlong sock)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
tcn_ssl_conn_t *con;
apr_os_sock_t oss;
apr_status_t rv;
UNREFERENCED(o);
TCN_ASSERT(ctx != 0);
TCN_ASSERT(sock != 0);
if (!s->sock)
return APR_ENOTSOCK;
if ((rv = apr_os_sock_get(&oss, s->sock)) != APR_SUCCESS)
return rv;
if (oss == APR_INVALID_SOCKET)
return APR_ENOTSOCK;
if ((con = ssl_create(e, c, s->pool)) == NULL)
return APR_EGENERAL;
con->sock = s->sock;
SSL_set_fd(con->ssl, (int)oss);
if (c->mode)
SSL_set_accept_state(con->ssl);
else
SSL_set_connect_state(con->ssl);
/* Change socket type */
s->net = &ssl_socket_layer;
s->opaque = con;
return APR_SUCCESS;
}
TCN_IMPLEMENT_CALL(jint, SSLSocket, renegotiate)(TCN_STDARGS,
jlong sock)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
tcn_ssl_conn_t *con;
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
con = (tcn_ssl_conn_t *)s->opaque;
return SSL_renegotiate(con->ssl);
}
#else
/* OpenSSL is not supported.
* Create empty stubs.
*/
TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock)
{
UNREFERENCED_STDARGS;
UNREFERENCED(sock);
return (jint)APR_ENOTIMPL;
}
TCN_IMPLEMENT_CALL(jint, SSLSocket, attach)(TCN_STDARGS, jlong ctx,
jlong sock)
{
UNREFERENCED_STDARGS;
UNREFERENCED(ctx);
UNREFERENCED(sock);
return (jint)APR_ENOTIMPL;
}
TCN_IMPLEMENT_CALL(jint, SSLSocket, renegotiate)(TCN_STDARGS,
jlong sock)
{
UNREFERENCED_STDARGS;
UNREFERENCED(sock);
return (jint)APR_ENOTIMPL;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -