diff options
Diffstat (limited to 'contrib/serf/buckets/ssl_buckets.c')
-rw-r--r-- | contrib/serf/buckets/ssl_buckets.c | 49 |
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); |