1 /* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * For the OpenSSL thread-safety locking code:
19 * Licensed to the Apache Software Foundation (ASF) under one or more
20 * contributor license agreements. See the NOTICE file distributed with
21 * this work for additional information regarding copyright ownership.
22 * The ASF licenses this file to You under the Apache License, Version 2.0
23 * (the "License"); you may not use this file except in compliance with
24 * the License. You may obtain a copy of the License at
26 * http://www.apache.org/licenses/LICENSE-2.0
28 * Unless required by applicable law or agreed to in writing, software
29 * distributed under the License is distributed on an "AS IS" BASIS,
30 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 * See the License for the specific language governing permissions and
32 * limitations under the License.
34 * Originally developed by Aaron Bannert and Justin Erenkrantz, eBuilt.
37 #include <apr_pools.h>
38 #include <apr_network_io.h>
39 #include <apr_portable.h>
40 #include <apr_strings.h>
41 #include <apr_base64.h>
42 #include <apr_version.h>
43 #include <apr_atomic.h>
46 #include "serf_private.h"
47 #include "serf_bucket_util.h"
49 #include <openssl/bio.h>
50 #include <openssl/ssl.h>
51 #include <openssl/err.h>
52 #include <openssl/pkcs12.h>
53 #include <openssl/x509v3.h>
55 #ifndef APR_VERSION_AT_LEAST /* Introduced in APR 1.3.0 */
56 #define APR_VERSION_AT_LEAST(major,minor,patch) \
57 (((major) < APR_MAJOR_VERSION) \
58 || ((major) == APR_MAJOR_VERSION && (minor) < APR_MINOR_VERSION) \
59 || ((major) == APR_MAJOR_VERSION && (minor) == APR_MINOR_VERSION && \
60 (patch) <= APR_PATCH_VERSION))
61 #endif /* APR_VERSION_AT_LEAST */
63 #ifndef APR_ARRAY_PUSH
64 #define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary)))
69 * Here's an overview of the SSL bucket's relationship to OpenSSL and serf.
71 * HTTP request: SSLENCRYPT(REQUEST)
72 * [context.c reads from SSLENCRYPT and writes out to the socket]
73 * HTTP response: RESPONSE(SSLDECRYPT(SOCKET))
74 * [handler function reads from RESPONSE which in turn reads from SSLDECRYPT]
76 * HTTP request read call path:
79 * |- serf_bucket_read on SSLENCRYPT
81 * |- serf_databuf_read
82 * |- common_databuf_prep
84 * |- 1. Try to read pending encrypted data; If available, return.
85 * |- 2. Try to read from ctx->stream [REQUEST bucket]
86 * |- 3. Call SSL_write with read data
88 * |- bio_bucket_read can be called
89 * |- bio_bucket_write with encrypted data
91 * |- 4. If successful, read pending encrypted data and return.
92 * |- 5. If fails, place read data back in ctx->stream
94 * HTTP response read call path:
96 * read_from_connection
100 * |- serf_bucket_read(SSLDECRYPT)
102 * |- serf_databuf_read
104 * |- 1. SSL_read() for pending decrypted data; if any, return.
105 * |- 2. Try to read from ctx->stream [SOCKET bucket]
106 * |- 3. Append data to ssl_ctx->source
107 * |- 4. Call SSL_read()
109 * |- bio_bucket_write can be called
111 * |- read data from ssl_ctx->source
112 * |- If data read, return it.
113 * |- If an error, set the STATUS value and return.
117 typedef struct bucket_list {
118 serf_bucket_t *bucket;
119 struct bucket_list *next;
123 /* Helper to read data. Wraps stream. */
124 serf_databuf_t databuf;
126 /* Our source for more data. */
127 serf_bucket_t *stream;
129 /* The next set of buckets */
130 bucket_list_t *stream_next;
132 /* The status of the last thing we read. */
134 apr_status_t exhausted;
137 /* Data we've read but not processed. */
138 serf_bucket_t *pending;
141 struct serf_ssl_context_t {
142 /* How many open buckets refer to this context. */
145 /* The pool that this context uses. */
148 /* The allocator associated with the above pool. */
149 serf_bucket_alloc_t *allocator;
151 /* Internal OpenSSL parameters */
156 serf_ssl_stream_t encrypt;
157 serf_ssl_stream_t decrypt;
159 /* Client cert callbacks */
160 serf_ssl_need_client_cert_t cert_callback;
162 apr_pool_t *cert_cache_pool;
163 const char *cert_file_success;
165 /* Client cert PW callbacks */
166 serf_ssl_need_cert_password_t cert_pw_callback;
167 void *cert_pw_userdata;
168 apr_pool_t *cert_pw_cache_pool;
169 const char *cert_pw_success;
171 /* Server cert callbacks */
172 serf_ssl_need_server_cert_t server_cert_callback;
173 serf_ssl_server_cert_chain_cb_t server_cert_chain_callback;
174 void *server_cert_userdata;
176 const char *cert_path;
179 EVP_PKEY *cached_cert_pw;
181 apr_status_t pending_err;
183 /* Status of a fatal error, returned on subsequent encrypt or decrypt
185 apr_status_t fatal_err;
189 /* The bucket-independent ssl context that this bucket is associated with */
190 serf_ssl_context_t *ssl_ctx;
192 /* Pointer to the 'right' databuf. */
193 serf_databuf_t *databuf;
195 /* Pointer to our stream, so we can find it later. */
196 serf_bucket_t **our_stream;
199 struct serf_ssl_certificate_t {
204 static void disable_compression(serf_ssl_context_t *ssl_ctx);
207 /* Log all ssl alerts that we receive from the server. */
209 apps_ssl_info_callback(const SSL *s, int where, int ret)
213 w = where & ~SSL_ST_MASK;
215 if (w & SSL_ST_CONNECT)
217 else if (w & SSL_ST_ACCEPT)
222 if (where & SSL_CB_LOOP) {
223 serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str,
224 SSL_state_string_long(s));
226 else if (where & SSL_CB_ALERT) {
227 str = (where & SSL_CB_READ) ? "read" : "write";
228 serf__log(SSL_VERBOSE, __FILE__, "SSL3 alert %s:%s:%s\n",
230 SSL_alert_type_string_long(ret),
231 SSL_alert_desc_string_long(ret));
233 else if (where & SSL_CB_EXIT) {
235 serf__log(SSL_VERBOSE, __FILE__, "%s:failed in %s\n", str,
236 SSL_state_string_long(s));
238 serf__log(SSL_VERBOSE, __FILE__, "%s:error in %s\n", str,
239 SSL_state_string_long(s));
245 /* Returns the amount read. */
246 static int bio_bucket_read(BIO *bio, char *in, int inlen)
248 serf_ssl_context_t *ctx = bio->ptr;
253 serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read called for %d bytes\n",
256 if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
257 && BIO_should_read(ctx->bio)) {
258 serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read waiting: (%d %d %d)\n",
259 BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
260 BIO_get_retry_flags(ctx->bio));
261 /* Falling back... */
262 ctx->encrypt.exhausted_reset = 1;
263 BIO_clear_retry_flags(bio);
266 status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len);
268 ctx->decrypt.status = status;
270 serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read received %d bytes (%d)\n",
273 if (!SERF_BUCKET_READ_ERROR(status)) {
276 memcpy(in, data, len);
279 if (APR_STATUS_IS_EOF(status)) {
280 BIO_set_retry_read(bio);
288 /* Returns the amount written. */
289 static int bio_bucket_write(BIO *bio, const char *in, int inl)
291 serf_ssl_context_t *ctx = bio->ptr;
294 serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write called for %d bytes\n",
297 if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
298 && !BIO_should_read(ctx->bio)) {
299 serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write waiting: (%d %d %d)\n",
300 BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
301 BIO_get_retry_flags(ctx->bio));
302 /* Falling back... */
303 ctx->encrypt.exhausted_reset = 1;
304 BIO_clear_retry_flags(bio);
307 tmp = serf_bucket_simple_copy_create(in, inl,
308 ctx->encrypt.pending->allocator);
310 serf_bucket_aggregate_append(ctx->encrypt.pending, tmp);
315 /* Returns the amount read. */
316 static int bio_file_read(BIO *bio, char *in, int inlen)
318 apr_file_t *file = bio->ptr;
322 BIO_clear_retry_flags(bio);
325 status = apr_file_read(file, in, &len);
327 if (!SERF_BUCKET_READ_ERROR(status)) {
329 if (APR_STATUS_IS_EOF(status)) {
330 BIO_set_retry_read(bio);
340 /* Returns the amount written. */
341 static int bio_file_write(BIO *bio, const char *in, int inl)
343 apr_file_t *file = bio->ptr;
346 BIO_clear_retry_flags(bio);
349 apr_file_write(file, in, &nbytes);
354 static int bio_file_gets(BIO *bio, char *in, int inlen)
356 return bio_file_read(bio, in, inlen);
359 static int bio_bucket_create(BIO *bio)
369 static int bio_bucket_destroy(BIO *bio)
371 /* Did we already free this? */
379 static long bio_bucket_ctrl(BIO *bio, int cmd, long num, void *ptr)
388 /* At this point we can't force a flush. */
398 static BIO_METHOD bio_bucket_method = {
400 "Serf SSL encryption and decryption buckets",
403 NULL, /* Is this called? */
404 NULL, /* Is this called? */
408 #ifdef OPENSSL_VERSION_NUMBER
409 NULL /* sslc does not have the callback_ctrl field */
413 static BIO_METHOD bio_file_method = {
415 "Wrapper around APR file structures",
418 NULL, /* Is this called? */
419 bio_file_gets, /* Is this called? */
423 #ifdef OPENSSL_VERSION_NUMBER
424 NULL /* sslc does not have the callback_ctrl field */
429 validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
432 serf_ssl_context_t *ctx;
437 ssl = X509_STORE_CTX_get_ex_data(store_ctx,
438 SSL_get_ex_data_X509_STORE_CTX_idx());
439 ctx = SSL_get_app_data(ssl);
441 server_cert = X509_STORE_CTX_get_current_cert(store_ctx);
442 depth = X509_STORE_CTX_get_error_depth(store_ctx);
444 /* If the certification was found invalid, get the error and convert it to
445 something our caller will understand. */
447 err = X509_STORE_CTX_get_error(store_ctx);
450 case X509_V_ERR_CERT_NOT_YET_VALID:
451 failures |= SERF_SSL_CERT_NOTYETVALID;
453 case X509_V_ERR_CERT_HAS_EXPIRED:
454 failures |= SERF_SSL_CERT_EXPIRED;
456 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
457 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
458 failures |= SERF_SSL_CERT_SELF_SIGNED;
460 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
461 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
462 case X509_V_ERR_CERT_UNTRUSTED:
463 case X509_V_ERR_INVALID_CA:
464 failures |= SERF_SSL_CERT_UNKNOWNCA;
466 case X509_V_ERR_CERT_REVOKED:
467 failures |= SERF_SSL_CERT_REVOKED;
470 failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
475 /* Check certificate expiry dates. */
476 if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
477 failures |= SERF_SSL_CERT_NOTYETVALID;
479 else if (X509_cmp_current_time(X509_get_notAfter(server_cert)) <= 0) {
480 failures |= SERF_SSL_CERT_EXPIRED;
483 if (ctx->server_cert_callback &&
484 (depth == 0 || failures)) {
486 serf_ssl_certificate_t *cert;
489 apr_pool_create(&subpool, ctx->pool);
491 cert = apr_palloc(subpool, sizeof(serf_ssl_certificate_t));
492 cert->ssl_cert = server_cert;
495 /* Callback for further verification. */
496 status = ctx->server_cert_callback(ctx->server_cert_userdata,
498 if (status == APR_SUCCESS)
501 /* Even if openssl found the certificate valid, the application
502 told us to reject it. */
504 /* Pass the error back to the caller through the context-run. */
505 ctx->pending_err = status;
507 apr_pool_destroy(subpool);
510 if (ctx->server_cert_chain_callback
511 && (depth == 0 || failures)) {
513 STACK_OF(X509) *chain;
514 const serf_ssl_certificate_t **certs;
518 apr_pool_create(&subpool, ctx->pool);
520 /* Borrow the chain to pass to the callback. */
521 chain = X509_STORE_CTX_get_chain(store_ctx);
523 /* If the chain can't be retrieved, just pass the current
525 /* ### can this actually happen with _get_chain() ? */
527 serf_ssl_certificate_t *cert = apr_palloc(subpool, sizeof(*cert));
529 cert->ssl_cert = server_cert;
532 /* Room for the server_cert and a trailing NULL. */
533 certs = apr_palloc(subpool, sizeof(*certs) * 2);
540 certs_len = sk_X509_num(chain);
542 /* Room for all the certs and a trailing NULL. */
543 certs = apr_palloc(subpool, sizeof(*certs) * (certs_len + 1));
544 for (i = 0; i < certs_len; ++i) {
545 serf_ssl_certificate_t *cert;
547 cert = apr_palloc(subpool, sizeof(*cert));
548 cert->ssl_cert = sk_X509_value(chain, i);
554 certs[certs_len] = NULL;
556 /* Callback for further verification. */
557 status = ctx->server_cert_chain_callback(ctx->server_cert_userdata,
560 if (status == APR_SUCCESS) {
563 /* Even if openssl found the certificate valid, the application
564 told us to reject it. */
566 /* Pass the error back to the caller through the context-run. */
567 ctx->pending_err = status;
570 apr_pool_destroy(subpool);
576 /* This function reads an encrypted stream and returns the decrypted stream. */
577 static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
578 char *buf, apr_size_t *len)
580 serf_ssl_context_t *ctx = baton;
587 return ctx->fatal_err;
589 serf__log(SSL_VERBOSE, __FILE__, "ssl_decrypt: begin %d\n", bufsize);
591 /* Is there some data waiting to be read? */
592 ssl_len = SSL_read(ctx->ssl, buf, bufsize);
594 serf__log(SSL_VERBOSE, __FILE__,
595 "ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n",
596 ssl_len, bufsize, ctx->decrypt.status,
597 BIO_get_retry_flags(ctx->bio));
602 status = serf_bucket_read(ctx->decrypt.stream, bufsize, &data, &priv_len);
604 if (!SERF_BUCKET_READ_ERROR(status) && priv_len) {
607 serf__log(SSL_VERBOSE, __FILE__,
608 "ssl_decrypt: read %d bytes (%d); status: %d\n",
609 priv_len, bufsize, status);
611 tmp = serf_bucket_simple_copy_create(data, priv_len,
612 ctx->decrypt.pending->allocator);
614 serf_bucket_aggregate_append(ctx->decrypt.pending, tmp);
616 ssl_len = SSL_read(ctx->ssl, buf, bufsize);
620 ssl_err = SSL_get_error(ctx->ssl, ssl_len);
622 case SSL_ERROR_SYSCALL:
624 status = ctx->decrypt.status;
626 case SSL_ERROR_WANT_READ:
632 if (ctx->pending_err) {
633 status = ctx->pending_err;
634 ctx->pending_err = 0;
636 ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
641 ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
644 } else if (ssl_len == 0) {
645 /* The server shut down the connection. */
646 int ssl_err, shutdown;
649 /* Check for SSL_RECEIVED_SHUTDOWN */
650 shutdown = SSL_get_shutdown(ctx->ssl);
651 /* Check for SSL_ERROR_ZERO_RETURN */
652 ssl_err = SSL_get_error(ctx->ssl, ssl_len);
654 if (shutdown == SSL_RECEIVED_SHUTDOWN &&
655 ssl_err == SSL_ERROR_ZERO_RETURN) {
656 /* The server closed the SSL session. While this doesn't
657 necessary mean the connection is closed, let's close
659 We can optimize this later. */
660 serf__log(SSL_VERBOSE, __FILE__,
661 "ssl_decrypt: SSL read error: server"
662 " shut down connection!\n");
665 /* A fatal error occurred. */
666 ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
670 serf__log(SSL_MSG_VERBOSE, __FILE__,
671 "---\n%.*s\n-(%d)-\n", *len, buf, *len);
677 serf__log(SSL_VERBOSE, __FILE__,
678 "ssl_decrypt: %d %d %d\n", status, *len,
679 BIO_get_retry_flags(ctx->bio));
684 /* This function reads a decrypted stream and returns an encrypted stream. */
685 static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
686 char *buf, apr_size_t *len)
689 apr_size_t interim_bufsize;
690 serf_ssl_context_t *ctx = baton;
694 return ctx->fatal_err;
696 serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: begin %d\n", bufsize);
698 /* Try to read already encrypted but unread data first. */
699 status = serf_bucket_read(ctx->encrypt.pending, bufsize, &data, len);
700 if (SERF_BUCKET_READ_ERROR(status)) {
704 /* Aha, we read something. Return that now. */
706 memcpy(buf, data, *len);
707 if (APR_STATUS_IS_EOF(status)) {
708 status = APR_SUCCESS;
711 serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: %d %d %d (quick read)\n",
712 status, *len, BIO_get_retry_flags(ctx->bio));
717 if (BIO_should_retry(ctx->bio) && BIO_should_write(ctx->bio)) {
718 serf__log(SSL_VERBOSE, __FILE__,
719 "ssl_encrypt: %d %d %d (should write exit)\n",
720 status, *len, BIO_get_retry_flags(ctx->bio));
725 /* If we were previously blocked, unblock ourselves now. */
726 if (BIO_should_read(ctx->bio)) {
727 serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: reset %d %d (%d %d %d)\n",
728 status, ctx->encrypt.status,
729 BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
730 BIO_get_retry_flags(ctx->bio));
732 ctx->encrypt.status = APR_SUCCESS;
733 ctx->encrypt.exhausted_reset = 0;
736 /* Oh well, read from our stream now. */
737 interim_bufsize = bufsize;
739 apr_size_t interim_len;
741 if (!ctx->encrypt.status) {
742 struct iovec vecs[64];
745 status = serf_bucket_read_iovec(ctx->encrypt.stream,
746 interim_bufsize, 64, vecs,
749 if (!SERF_BUCKET_READ_ERROR(status) && vecs_read) {
751 int i, cur, vecs_data_len;
754 /* Combine the buffers of the iovec into one buffer, as
755 that is with SSL_write requires. */
757 for (i = 0; i < vecs_read; i++) {
758 vecs_data_len += vecs[i].iov_len;
761 vecs_data = serf_bucket_mem_alloc(ctx->allocator,
765 for (i = 0; i < vecs_read; i++) {
766 memcpy(vecs_data + cur, vecs[i].iov_base, vecs[i].iov_len);
767 cur += vecs[i].iov_len;
770 interim_bufsize -= vecs_data_len;
771 interim_len = vecs_data_len;
773 serf__log(SSL_VERBOSE, __FILE__,
774 "ssl_encrypt: bucket read %d bytes; "\
775 "status %d\n", interim_len, status);
776 serf__log(SSL_MSG_VERBOSE, __FILE__, "---\n%.*s\n-(%d)-\n",
777 interim_len, vecs_data, interim_len);
779 /* Stash our status away. */
780 ctx->encrypt.status = status;
782 ssl_len = SSL_write(ctx->ssl, vecs_data, interim_len);
784 serf__log(SSL_VERBOSE, __FILE__,
785 "ssl_encrypt: SSL write: %d\n", ssl_len);
788 serf_bucket_mem_free(ctx->allocator, vecs_data);
790 /* If we failed to write... */
794 /* Ah, bugger. We need to put that data back. */
795 serf_bucket_aggregate_prepend_iovec(ctx->encrypt.stream,
798 ssl_err = SSL_get_error(ctx->ssl, ssl_len);
800 serf__log(SSL_VERBOSE, __FILE__,
801 "ssl_encrypt: SSL write error: %d\n", ssl_err);
803 if (ssl_err == SSL_ERROR_SYSCALL) {
804 status = ctx->encrypt.status;
805 if (SERF_BUCKET_READ_ERROR(status)) {
811 if (ssl_err == SSL_ERROR_WANT_READ) {
812 status = SERF_ERROR_WAIT_CONN;
815 ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
819 serf__log(SSL_VERBOSE, __FILE__,
820 "ssl_encrypt: SSL write error: %d %d\n",
828 status = ctx->encrypt.status;
831 } while (!status && interim_bufsize);
833 /* Okay, we exhausted our underlying stream. */
834 if (!SERF_BUCKET_READ_ERROR(status)) {
835 apr_status_t agg_status;
836 struct iovec vecs[64];
839 /* We read something! */
840 agg_status = serf_bucket_read_iovec(ctx->encrypt.pending, bufsize,
841 64, vecs, &vecs_read);
843 for (i = 0; i < vecs_read; i++) {
844 memcpy(buf + *len, vecs[i].iov_base, vecs[i].iov_len);
845 *len += vecs[i].iov_len;
848 serf__log(SSL_VERBOSE, __FILE__,
849 "ssl_encrypt read agg: %d %d %d %d\n", status, agg_status,
850 ctx->encrypt.status, *len);
857 if (status == SERF_ERROR_WAIT_CONN
858 && BIO_should_retry(ctx->bio) && BIO_should_read(ctx->bio)) {
859 ctx->encrypt.exhausted = ctx->encrypt.status;
860 ctx->encrypt.status = SERF_ERROR_WAIT_CONN;
863 serf__log(SSL_VERBOSE, __FILE__,
864 "ssl_encrypt finished: %d %d (%d %d %d)\n", status, *len,
865 BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
866 BIO_get_retry_flags(ctx->bio));
872 static apr_pool_t *ssl_pool;
873 static apr_thread_mutex_t **ssl_locks;
875 typedef struct CRYPTO_dynlock_value {
876 apr_thread_mutex_t *lock;
877 } CRYPTO_dynlock_value;
879 static CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line)
881 CRYPTO_dynlock_value *l;
884 l = apr_palloc(ssl_pool, sizeof(CRYPTO_dynlock_value));
885 rv = apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, ssl_pool);
886 if (rv != APR_SUCCESS) {
887 /* FIXME: return error here */
892 static void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file,
895 if (mode & CRYPTO_LOCK) {
896 apr_thread_mutex_lock(l->lock);
898 else if (mode & CRYPTO_UNLOCK) {
899 apr_thread_mutex_unlock(l->lock);
903 static void ssl_dyn_destroy(CRYPTO_dynlock_value *l, const char *file,
906 apr_thread_mutex_destroy(l->lock);
909 static void ssl_lock(int mode, int n, const char *file, int line)
911 if (mode & CRYPTO_LOCK) {
912 apr_thread_mutex_lock(ssl_locks[n]);
914 else if (mode & CRYPTO_UNLOCK) {
915 apr_thread_mutex_unlock(ssl_locks[n]);
919 static unsigned long ssl_id(void)
921 /* FIXME: This is lame and not portable. -aaron */
922 return (unsigned long) apr_os_thread_current();
925 static apr_status_t cleanup_ssl(void *data)
927 CRYPTO_set_locking_callback(NULL);
928 CRYPTO_set_id_callback(NULL);
929 CRYPTO_set_dynlock_create_callback(NULL);
930 CRYPTO_set_dynlock_lock_callback(NULL);
931 CRYPTO_set_dynlock_destroy_callback(NULL);
938 static apr_uint32_t have_init_ssl = 0;
940 static void init_ssl_libraries(void)
943 #if APR_VERSION_AT_LEAST(1,0,0)
944 val = apr_atomic_xchg32(&have_init_ssl, 1);
946 val = apr_atomic_cas(&have_init_ssl, 1, 0);
955 /* Warn when compile-time and run-time version of OpenSSL differ in
956 major/minor version number. */
957 long libver = SSLeay();
959 if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) {
960 serf__log(SSL_VERBOSE, __FILE__,
961 "Warning: OpenSSL library version mismatch, compile-time "
962 "was %lx, runtime is %lx.\n",
963 OPENSSL_VERSION_NUMBER, libver);
967 CRYPTO_malloc_init();
968 ERR_load_crypto_strings();
969 SSL_load_error_strings();
971 OpenSSL_add_all_algorithms();
974 numlocks = CRYPTO_num_locks();
975 apr_pool_create(&ssl_pool, NULL);
976 ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks);
977 for (i = 0; i < numlocks; i++) {
980 /* Intraprocess locks don't /need/ a filename... */
981 rv = apr_thread_mutex_create(&ssl_locks[i],
982 APR_THREAD_MUTEX_DEFAULT, ssl_pool);
983 if (rv != APR_SUCCESS) {
984 /* FIXME: error out here */
987 CRYPTO_set_locking_callback(ssl_lock);
988 CRYPTO_set_id_callback(ssl_id);
989 CRYPTO_set_dynlock_create_callback(ssl_dyn_create);
990 CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock);
991 CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy);
993 apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl);
998 static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
1000 serf_ssl_context_t *ctx = SSL_get_app_data(ssl);
1001 apr_status_t status;
1003 if (ctx->cached_cert) {
1004 *cert = ctx->cached_cert;
1005 *pkey = ctx->cached_cert_pw;
1009 while (ctx->cert_callback) {
1010 const char *cert_path;
1011 apr_file_t *cert_file;
1015 int retrying_success = 0;
1017 if (ctx->cert_file_success) {
1018 status = APR_SUCCESS;
1019 cert_path = ctx->cert_file_success;
1020 ctx->cert_file_success = NULL;
1021 retrying_success = 1;
1023 status = ctx->cert_callback(ctx->cert_userdata, &cert_path);
1026 if (status || !cert_path) {
1030 /* Load the x.509 cert file stored in PKCS12 */
1031 status = apr_file_open(&cert_file, cert_path, APR_READ, APR_OS_DEFAULT,
1038 bio = BIO_new(&bio_file_method);
1039 bio->ptr = cert_file;
1041 ctx->cert_path = cert_path;
1042 p12 = d2i_PKCS12_bio(bio, NULL);
1043 apr_file_close(cert_file);
1045 i = PKCS12_parse(p12, NULL, pkey, cert, NULL);
1049 ctx->cached_cert = *cert;
1050 ctx->cached_cert_pw = *pkey;
1051 if (!retrying_success && ctx->cert_cache_pool) {
1054 c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path);
1056 apr_pool_userdata_setn(c, "serf:ssl:cert",
1057 apr_pool_cleanup_null,
1058 ctx->cert_cache_pool);
1063 int err = ERR_get_error();
1065 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
1066 ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
1067 if (ctx->cert_pw_callback) {
1068 const char *password;
1070 if (ctx->cert_pw_success) {
1071 status = APR_SUCCESS;
1072 password = ctx->cert_pw_success;
1073 ctx->cert_pw_success = NULL;
1075 status = ctx->cert_pw_callback(ctx->cert_pw_userdata,
1080 if (!status && password) {
1081 i = PKCS12_parse(p12, password, pkey, cert, NULL);
1084 ctx->cached_cert = *cert;
1085 ctx->cached_cert_pw = *pkey;
1086 if (!retrying_success && ctx->cert_cache_pool) {
1089 c = apr_pstrdup(ctx->cert_cache_pool,
1092 apr_pool_userdata_setn(c, "serf:ssl:cert",
1093 apr_pool_cleanup_null,
1094 ctx->cert_cache_pool);
1096 if (!retrying_success && ctx->cert_pw_cache_pool) {
1099 c = apr_pstrdup(ctx->cert_pw_cache_pool,
1102 apr_pool_userdata_setn(c, "serf:ssl:certpw",
1103 apr_pool_cleanup_null,
1104 ctx->cert_pw_cache_pool);
1114 printf("OpenSSL cert error: %d %d %d\n", ERR_GET_LIB(err),
1116 ERR_GET_REASON(err));
1126 void serf_ssl_client_cert_provider_set(
1127 serf_ssl_context_t *context,
1128 serf_ssl_need_client_cert_t callback,
1132 context->cert_callback = callback;
1133 context->cert_userdata = data;
1134 context->cert_cache_pool = cache_pool;
1135 if (context->cert_cache_pool) {
1136 apr_pool_userdata_get((void**)&context->cert_file_success,
1137 "serf:ssl:cert", cache_pool);
1142 void serf_ssl_client_cert_password_set(
1143 serf_ssl_context_t *context,
1144 serf_ssl_need_cert_password_t callback,
1148 context->cert_pw_callback = callback;
1149 context->cert_pw_userdata = data;
1150 context->cert_pw_cache_pool = cache_pool;
1151 if (context->cert_pw_cache_pool) {
1152 apr_pool_userdata_get((void**)&context->cert_pw_success,
1153 "serf:ssl:certpw", cache_pool);
1158 void serf_ssl_server_cert_callback_set(
1159 serf_ssl_context_t *context,
1160 serf_ssl_need_server_cert_t callback,
1163 context->server_cert_callback = callback;
1164 context->server_cert_userdata = data;
1167 void serf_ssl_server_cert_chain_callback_set(
1168 serf_ssl_context_t *context,
1169 serf_ssl_need_server_cert_t cert_callback,
1170 serf_ssl_server_cert_chain_cb_t cert_chain_callback,
1173 context->server_cert_callback = cert_callback;
1174 context->server_cert_chain_callback = cert_chain_callback;
1175 context->server_cert_userdata = data;
1178 static serf_ssl_context_t *ssl_init_context(void)
1180 serf_ssl_context_t *ssl_ctx;
1182 serf_bucket_alloc_t *allocator;
1184 init_ssl_libraries();
1186 apr_pool_create(&pool, NULL);
1187 allocator = serf_bucket_allocator_create(pool, NULL, NULL);
1189 ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx));
1191 ssl_ctx->refcount = 0;
1192 ssl_ctx->pool = pool;
1193 ssl_ctx->allocator = allocator;
1195 ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
1197 SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert);
1198 ssl_ctx->cached_cert = 0;
1199 ssl_ctx->cached_cert_pw = 0;
1200 ssl_ctx->pending_err = APR_SUCCESS;
1201 ssl_ctx->fatal_err = APR_SUCCESS;
1203 ssl_ctx->cert_callback = NULL;
1204 ssl_ctx->cert_pw_callback = NULL;
1205 ssl_ctx->server_cert_callback = NULL;
1206 ssl_ctx->server_cert_chain_callback = NULL;
1208 SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER,
1209 validate_server_certificate);
1210 SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL);
1211 /* Disable SSL compression by default. */
1212 disable_compression(ssl_ctx);
1214 ssl_ctx->ssl = SSL_new(ssl_ctx->ctx);
1215 ssl_ctx->bio = BIO_new(&bio_bucket_method);
1216 ssl_ctx->bio->ptr = ssl_ctx;
1218 SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio);
1220 SSL_set_connect_state(ssl_ctx->ssl);
1222 SSL_set_app_data(ssl_ctx->ssl, ssl_ctx);
1225 SSL_CTX_set_info_callback(ssl_ctx->ctx, apps_ssl_info_callback);
1228 ssl_ctx->encrypt.stream = NULL;
1229 ssl_ctx->encrypt.stream_next = NULL;
1230 ssl_ctx->encrypt.pending = serf_bucket_aggregate_create(allocator);
1231 ssl_ctx->encrypt.status = APR_SUCCESS;
1232 serf_databuf_init(&ssl_ctx->encrypt.databuf);
1233 ssl_ctx->encrypt.databuf.read = ssl_encrypt;
1234 ssl_ctx->encrypt.databuf.read_baton = ssl_ctx;
1236 ssl_ctx->decrypt.stream = NULL;
1237 ssl_ctx->decrypt.pending = serf_bucket_aggregate_create(allocator);
1238 ssl_ctx->decrypt.status = APR_SUCCESS;
1239 serf_databuf_init(&ssl_ctx->decrypt.databuf);
1240 ssl_ctx->decrypt.databuf.read = ssl_decrypt;
1241 ssl_ctx->decrypt.databuf.read_baton = ssl_ctx;
1246 static apr_status_t ssl_free_context(
1247 serf_ssl_context_t *ssl_ctx)
1251 /* If never had the pending buckets, don't try to free them. */
1252 if (ssl_ctx->decrypt.pending != NULL) {
1253 serf_bucket_destroy(ssl_ctx->decrypt.pending);
1255 if (ssl_ctx->encrypt.pending != NULL) {
1256 serf_bucket_destroy(ssl_ctx->encrypt.pending);
1259 /* SSL_free implicitly frees the underlying BIO. */
1260 SSL_free(ssl_ctx->ssl);
1261 SSL_CTX_free(ssl_ctx->ctx);
1265 serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx);
1266 apr_pool_destroy(p);
1271 static serf_bucket_t * serf_bucket_ssl_create(
1272 serf_ssl_context_t *ssl_ctx,
1273 serf_bucket_alloc_t *allocator,
1274 const serf_bucket_type_t *type)
1278 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
1280 ctx->ssl_ctx = ssl_init_context();
1283 ctx->ssl_ctx = ssl_ctx;
1285 ctx->ssl_ctx->refcount++;
1287 return serf_bucket_create(type, allocator, ctx);
1290 apr_status_t serf_ssl_set_hostname(serf_ssl_context_t *context,
1291 const char * hostname)
1293 #ifdef SSL_set_tlsext_host_name
1294 if (SSL_set_tlsext_host_name(context->ssl, hostname) != 1) {
1301 apr_status_t serf_ssl_use_default_certificates(serf_ssl_context_t *ssl_ctx)
1303 X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
1305 int result = X509_STORE_set_default_paths(store);
1307 return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED;
1310 apr_status_t serf_ssl_load_cert_file(
1311 serf_ssl_certificate_t **cert,
1312 const char *file_path,
1315 FILE *fp = fopen(file_path, "r");
1318 X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
1322 *cert = apr_palloc(pool, sizeof(serf_ssl_certificate_t));
1323 (*cert)->ssl_cert = ssl_cert;
1329 return SERF_ERROR_SSL_CERT_FAILED;
1333 apr_status_t serf_ssl_trust_cert(
1334 serf_ssl_context_t *ssl_ctx,
1335 serf_ssl_certificate_t *cert)
1337 X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
1339 int result = X509_STORE_add_cert(store, cert->ssl_cert);
1341 return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED;
1345 serf_bucket_t *serf_bucket_ssl_decrypt_create(
1346 serf_bucket_t *stream,
1347 serf_ssl_context_t *ssl_ctx,
1348 serf_bucket_alloc_t *allocator)
1353 bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1354 &serf_bucket_type_ssl_decrypt);
1358 ctx->databuf = &ctx->ssl_ctx->decrypt.databuf;
1359 if (ctx->ssl_ctx->decrypt.stream != NULL) {
1362 ctx->ssl_ctx->decrypt.stream = stream;
1363 ctx->our_stream = &ctx->ssl_ctx->decrypt.stream;
1369 serf_ssl_context_t *serf_bucket_ssl_decrypt_context_get(
1370 serf_bucket_t *bucket)
1372 ssl_context_t *ctx = bucket->data;
1373 return ctx->ssl_ctx;
1377 serf_bucket_t *serf_bucket_ssl_encrypt_create(
1378 serf_bucket_t *stream,
1379 serf_ssl_context_t *ssl_ctx,
1380 serf_bucket_alloc_t *allocator)
1385 bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1386 &serf_bucket_type_ssl_encrypt);
1390 ctx->databuf = &ctx->ssl_ctx->encrypt.databuf;
1391 ctx->our_stream = &ctx->ssl_ctx->encrypt.stream;
1392 if (ctx->ssl_ctx->encrypt.stream == NULL) {
1393 serf_bucket_t *tmp = serf_bucket_aggregate_create(stream->allocator);
1394 serf_bucket_aggregate_append(tmp, stream);
1395 ctx->ssl_ctx->encrypt.stream = tmp;
1398 bucket_list_t *new_list;
1400 new_list = serf_bucket_mem_alloc(ctx->ssl_ctx->allocator,
1402 new_list->bucket = stream;
1403 new_list->next = NULL;
1404 if (ctx->ssl_ctx->encrypt.stream_next == NULL) {
1405 ctx->ssl_ctx->encrypt.stream_next = new_list;
1408 bucket_list_t *scan = ctx->ssl_ctx->encrypt.stream_next;
1410 while (scan->next != NULL)
1412 scan->next = new_list;
1420 serf_ssl_context_t *serf_bucket_ssl_encrypt_context_get(
1421 serf_bucket_t *bucket)
1423 ssl_context_t *ctx = bucket->data;
1424 return ctx->ssl_ctx;
1427 /* Functions to read a serf_ssl_certificate structure. */
1429 /* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
1431 convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
1436 apr_hash_t *tgt = apr_hash_make(pool);
1438 ret = X509_NAME_get_text_by_NID(org,
1442 apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1443 ret = X509_NAME_get_text_by_NID(org,
1444 NID_pkcs9_emailAddress,
1447 apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1448 ret = X509_NAME_get_text_by_NID(org,
1449 NID_organizationalUnitName,
1452 apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1453 ret = X509_NAME_get_text_by_NID(org,
1454 NID_organizationName,
1457 apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1458 ret = X509_NAME_get_text_by_NID(org,
1462 apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1463 ret = X509_NAME_get_text_by_NID(org,
1464 NID_stateOrProvinceName,
1467 apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1468 ret = X509_NAME_get_text_by_NID(org,
1472 apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1478 int serf_ssl_cert_depth(const serf_ssl_certificate_t *cert)
1484 apr_hash_t *serf_ssl_cert_issuer(
1485 const serf_ssl_certificate_t *cert,
1488 X509_NAME *issuer = X509_get_issuer_name(cert->ssl_cert);
1493 return convert_X509_NAME_to_table(issuer, pool);
1497 apr_hash_t *serf_ssl_cert_subject(
1498 const serf_ssl_certificate_t *cert,
1501 X509_NAME *subject = X509_get_subject_name(cert->ssl_cert);
1506 return convert_X509_NAME_to_table(subject, pool);
1510 apr_hash_t *serf_ssl_cert_certificate(
1511 const serf_ssl_certificate_t *cert,
1514 apr_hash_t *tgt = apr_hash_make(pool);
1515 unsigned int md_size, i;
1516 unsigned char md[EVP_MAX_MD_SIZE];
1518 STACK_OF(GENERAL_NAME) *names;
1520 /* sha1 fingerprint */
1521 if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
1522 const char hex[] = "0123456789ABCDEF";
1523 char fingerprint[EVP_MAX_MD_SIZE * 3];
1525 for (i=0; i<md_size; i++) {
1526 fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4];
1527 fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)];
1528 fingerprint[(3*i)+2] = ':';
1531 fingerprint[(3*(md_size-1))+2] = '\0';
1533 fingerprint[0] = '\0';
1535 apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING,
1536 apr_pstrdup(pool, fingerprint));
1539 /* set expiry dates */
1540 bio = BIO_new(BIO_s_mem());
1542 ASN1_TIME *notBefore, *notAfter;
1545 memset (buf, 0, sizeof (buf));
1546 notBefore = X509_get_notBefore(cert->ssl_cert);
1547 if (ASN1_TIME_print(bio, notBefore)) {
1548 BIO_read(bio, buf, 255);
1549 apr_hash_set(tgt, "notBefore", APR_HASH_KEY_STRING,
1550 apr_pstrdup(pool, buf));
1552 memset (buf, 0, sizeof (buf));
1553 notAfter = X509_get_notAfter(cert->ssl_cert);
1554 if (ASN1_TIME_print(bio, notAfter)) {
1555 BIO_read(bio, buf, 255);
1556 apr_hash_set(tgt, "notAfter", APR_HASH_KEY_STRING,
1557 apr_pstrdup(pool, buf));
1562 /* Get subjectAltNames */
1563 names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL);
1565 int names_count = sk_GENERAL_NAME_num(names);
1567 apr_array_header_t *san_arr = apr_array_make(pool, names_count,
1569 apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
1570 for (i = 0; i < names_count; i++) {
1572 GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i);
1576 p = apr_pstrmemdup(pool, (const char *)nm->d.ia5->data,
1580 /* Don't know what to do - skip. */
1584 APR_ARRAY_PUSH(san_arr, char*) = p;
1587 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
1594 const char *serf_ssl_cert_export(
1595 const serf_ssl_certificate_t *cert,
1601 unsigned char *unused;
1603 /* find the length of the DER encoding. */
1604 len = i2d_X509(cert->ssl_cert, NULL);
1609 binary_cert = apr_palloc(pool, len);
1610 unused = (unsigned char *)binary_cert;
1611 len = i2d_X509(cert->ssl_cert, &unused); /* unused is incremented */
1616 encoded_cert = apr_palloc(pool, apr_base64_encode_len(len));
1617 apr_base64_encode(encoded_cert, binary_cert, len);
1619 return encoded_cert;
1622 /* Disables compression for all SSL sessions. */
1623 static void disable_compression(serf_ssl_context_t *ssl_ctx)
1625 #ifdef SSL_OP_NO_COMPRESSION
1626 SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_COMPRESSION);
1630 apr_status_t serf_ssl_use_compression(serf_ssl_context_t *ssl_ctx, int enabled)
1633 #ifdef SSL_OP_NO_COMPRESSION
1634 SSL_clear_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION);
1638 #ifdef SSL_OP_NO_COMPRESSION
1639 SSL_set_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION);
1644 return APR_EGENERAL;
1647 static void serf_ssl_destroy_and_data(serf_bucket_t *bucket)
1649 ssl_context_t *ctx = bucket->data;
1651 if (!--ctx->ssl_ctx->refcount) {
1652 ssl_free_context(ctx->ssl_ctx);
1655 serf_default_destroy_and_data(bucket);
1658 static void serf_ssl_decrypt_destroy_and_data(serf_bucket_t *bucket)
1660 ssl_context_t *ctx = bucket->data;
1662 serf_bucket_destroy(*ctx->our_stream);
1664 serf_ssl_destroy_and_data(bucket);
1667 static void serf_ssl_encrypt_destroy_and_data(serf_bucket_t *bucket)
1669 ssl_context_t *ctx = bucket->data;
1670 serf_ssl_context_t *ssl_ctx = ctx->ssl_ctx;
1672 if (ssl_ctx->encrypt.stream == *ctx->our_stream) {
1673 serf_bucket_destroy(*ctx->our_stream);
1674 serf_bucket_destroy(ssl_ctx->encrypt.pending);
1676 /* Reset our encrypted status and databuf. */
1677 ssl_ctx->encrypt.status = APR_SUCCESS;
1678 ssl_ctx->encrypt.databuf.status = APR_SUCCESS;
1680 /* Advance to the next stream - if we have one. */
1681 if (ssl_ctx->encrypt.stream_next == NULL) {
1682 ssl_ctx->encrypt.stream = NULL;
1683 ssl_ctx->encrypt.pending = NULL;
1688 cur = ssl_ctx->encrypt.stream_next;
1689 ssl_ctx->encrypt.stream = cur->bucket;
1690 ssl_ctx->encrypt.pending =
1691 serf_bucket_aggregate_create(cur->bucket->allocator);
1692 ssl_ctx->encrypt.stream_next = cur->next;
1693 serf_bucket_mem_free(ssl_ctx->allocator, cur);
1697 /* Ah, darn. We haven't sent this one along yet. */
1700 serf_ssl_destroy_and_data(bucket);
1703 static apr_status_t serf_ssl_read(serf_bucket_t *bucket,
1704 apr_size_t requested,
1705 const char **data, apr_size_t *len)
1707 ssl_context_t *ctx = bucket->data;
1709 return serf_databuf_read(ctx->databuf, requested, data, len);
1712 static apr_status_t serf_ssl_readline(serf_bucket_t *bucket,
1713 int acceptable, int *found,
1717 ssl_context_t *ctx = bucket->data;
1719 return serf_databuf_readline(ctx->databuf, acceptable, found, data, len);
1722 static apr_status_t serf_ssl_peek(serf_bucket_t *bucket,
1726 ssl_context_t *ctx = bucket->data;
1728 return serf_databuf_peek(ctx->databuf, data, len);
1732 const serf_bucket_type_t serf_bucket_type_ssl_encrypt = {
1736 serf_default_read_iovec,
1737 serf_default_read_for_sendfile,
1738 serf_default_read_bucket,
1740 serf_ssl_encrypt_destroy_and_data,
1743 const serf_bucket_type_t serf_bucket_type_ssl_decrypt = {
1747 serf_default_read_iovec,
1748 serf_default_read_for_sendfile,
1749 serf_default_read_bucket,
1751 serf_ssl_decrypt_destroy_and_data,