summaryrefslogtreecommitdiffstats
path: root/contrib/serf/buckets/ssl_buckets.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/serf/buckets/ssl_buckets.c')
-rw-r--r--contrib/serf/buckets/ssl_buckets.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/contrib/serf/buckets/ssl_buckets.c b/contrib/serf/buckets/ssl_buckets.c
index c5a0e60..d2ced94 100644
--- a/contrib/serf/buckets/ssl_buckets.c
+++ b/contrib/serf/buckets/ssl_buckets.c
@@ -211,14 +211,14 @@ apps_ssl_info_callback(const SSL *s, int where, int ret)
const char *str;
int w;
w = where & ~SSL_ST_MASK;
-
+
if (w & SSL_ST_CONNECT)
str = "SSL_connect";
else if (w & SSL_ST_ACCEPT)
str = "SSL_accept";
else
str = "undefined";
-
+
if (where & SSL_CB_LOOP) {
serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str,
SSL_state_string_long(s));
@@ -255,7 +255,8 @@ static int bio_bucket_read(BIO *bio, char *in, int inlen)
if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
&& BIO_should_read(ctx->bio)) {
- serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read waiting: (%d %d %d)\n",
+ serf__log(SSL_VERBOSE, __FILE__,
+ "bio_bucket_read waiting: (%d %d %d)\n",
BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
BIO_get_retry_flags(ctx->bio));
/* Falling back... */
@@ -296,7 +297,8 @@ static int bio_bucket_write(BIO *bio, const char *in, int inl)
if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
&& !BIO_should_read(ctx->bio)) {
- serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write waiting: (%d %d %d)\n",
+ serf__log(SSL_VERBOSE, __FILE__,
+ "bio_bucket_write waiting: (%d %d %d)\n",
BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
BIO_get_retry_flags(ctx->bio));
/* Falling back... */
@@ -570,6 +572,15 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
apr_pool_destroy(subpool);
}
+ /* Return a specific error if the server certificate is not accepted by
+ OpenSSL and the application has not set callbacks to override this. */
+ if (!cert_valid &&
+ !ctx->server_cert_chain_callback &&
+ !ctx->server_cert_callback)
+ {
+ ctx->pending_err = SERF_ERROR_SSL_CERT_FAILED;
+ }
+
return cert_valid;
}
@@ -621,9 +632,12 @@ static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
switch (ssl_err) {
case SSL_ERROR_SYSCALL:
*len = 0;
+ /* Return the underlying network error that caused OpenSSL
+ to fail. ### This can be a crypt error! */
status = ctx->decrypt.status;
break;
case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
*len = 0;
status = APR_EAGAIN;
break;
@@ -784,16 +798,19 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
serf__log(SSL_VERBOSE, __FILE__,
"ssl_encrypt: SSL write: %d\n", ssl_len);
- /* We're done. */
- serf_bucket_mem_free(ctx->allocator, vecs_data);
-
/* If we failed to write... */
if (ssl_len < 0) {
int ssl_err;
- /* Ah, bugger. We need to put that data back. */
- serf_bucket_aggregate_prepend_iovec(ctx->encrypt.stream,
- vecs, vecs_read);
+ /* Ah, bugger. We need to put that data back.
+ Note: use the copy here, we do not own the original iovec
+ data buffer so it will be freed on next read. */
+ serf_bucket_t *vecs_copy =
+ serf_bucket_simple_own_create(vecs_data,
+ vecs_data_len,
+ ctx->allocator);
+ serf_bucket_aggregate_prepend(ctx->encrypt.stream,
+ vecs_copy);
ssl_err = SSL_get_error(ctx->ssl, ssl_len);
@@ -801,6 +818,8 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
"ssl_encrypt: SSL write error: %d\n", ssl_err);
if (ssl_err == SSL_ERROR_SYSCALL) {
+ /* Return the underlying network error that caused OpenSSL
+ to fail. ### This can be a decrypt error! */
status = ctx->encrypt.status;
if (SERF_BUCKET_READ_ERROR(status)) {
return status;
@@ -812,13 +831,17 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
status = SERF_ERROR_WAIT_CONN;
}
else {
- ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
+ ctx->fatal_err = status =
+ SERF_ERROR_SSL_COMM_FAILED;
}
}
serf__log(SSL_VERBOSE, __FILE__,
"ssl_encrypt: SSL write error: %d %d\n",
status, *len);
+ } else {
+ /* We're done with this data. */
+ serf_bucket_mem_free(ctx->allocator, vecs_data);
}
}
}
@@ -1024,7 +1047,7 @@ static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
}
if (status || !cert_path) {
- break;
+ break;
}
/* Load the x.509 cert file stored in PKCS12 */
@@ -1313,7 +1336,7 @@ apr_status_t serf_ssl_load_cert_file(
apr_pool_t *pool)
{
FILE *fp = fopen(file_path, "r");
-
+
if (fp) {
X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
fclose(fp);
OpenPOWER on IntegriCloud