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>
43 #include "serf_bucket_util.h"
45 #include <openssl/bio.h>
46 #include <openssl/ssl.h>
47 #include <openssl/err.h>
48 #include <openssl/pkcs12.h>
50 /*#define SSL_VERBOSE*/
53 * Here's an overview of the SSL bucket's relationship to OpenSSL and serf.
55 * HTTP request: SSLENCRYPT(REQUEST)
56 * [context.c reads from SSLENCRYPT and writes out to the socket]
57 * HTTP response: RESPONSE(SSLDECRYPT(SOCKET))
58 * [handler function reads from RESPONSE which in turn reads from SSLDECRYPT]
60 * HTTP request read call path:
63 * |- serf_bucket_read on SSLENCRYPT
65 * |- serf_databuf_read
66 * |- common_databuf_prep
68 * |- 1. Try to read pending encrypted data; If available, return.
69 * |- 2. Try to read from ctx->stream [REQUEST bucket]
70 * |- 3. Call SSL_write with read data
72 * |- bio_bucket_write with encrypted data
74 * |- 4. If successful, read pending encrypted data and return.
75 * |- 5. If fails, place read data back in ctx->stream
77 * HTTP response read call path:
79 * read_from_connection
83 * |- serf_bucket_read(SSLDECRYPT)
85 * |- serf_databuf_read
87 * |- 1. SSL_read() for pending decrypted data; if any, return.
88 * |- 2. Try to read from ctx->stream [SOCKET bucket]
89 * |- 3. Append data to ssl_ctx->source
90 * |- 4. Call SSL_read()
93 * |- read data from ssl_ctx->source
94 * |- If data read, return it.
95 * |- If an error, set the STATUS value and return.
99 typedef struct bucket_list {
100 serf_bucket_t *bucket;
101 struct bucket_list *next;
105 /* Helper to read data. Wraps stream. */
106 serf_databuf_t databuf;
108 /* Our source for more data. */
109 serf_bucket_t *stream;
111 /* The next set of buckets */
112 bucket_list_t *stream_next;
114 /* The status of the last thing we read. */
117 /* Data we've read but not processed. */
118 serf_bucket_t *pending;
121 struct serf_ssl_context_t {
122 /* How many open buckets refer to this context. */
125 /* The pool that this context uses. */
128 /* The allocator associated with the above pool. */
129 serf_bucket_alloc_t *allocator;
131 /* Internal OpenSSL parameters */
136 serf_ssl_stream_t encrypt;
137 serf_ssl_stream_t decrypt;
139 /* Client cert callbacks */
140 serf_ssl_need_client_cert_t cert_callback;
142 apr_pool_t *cert_cache_pool;
143 const char *cert_file_success;
145 /* Client cert PW callbacks */
146 serf_ssl_need_cert_password_t cert_pw_callback;
147 void *cert_pw_userdata;
148 apr_pool_t *cert_pw_cache_pool;
149 const char *cert_pw_success;
151 /* Server cert callbacks */
152 serf_ssl_need_server_cert_t server_cert_callback;
153 void *server_cert_userdata;
155 const char *cert_path;
158 EVP_PKEY *cached_cert_pw;
160 apr_status_t pending_err;
164 /* The bucket-independent ssl context that this bucket is associated with */
165 serf_ssl_context_t *ssl_ctx;
167 /* Pointer to the 'right' databuf. */
168 serf_databuf_t *databuf;
170 /* Pointer to our stream, so we can find it later. */
171 serf_bucket_t **our_stream;
174 struct serf_ssl_certificate_t {
178 /* Returns the amount read. */
179 static int bio_bucket_read(BIO *bio, char *in, int inlen)
181 serf_ssl_context_t *ctx = bio->ptr;
187 printf("bio_bucket_read called for %d bytes\n", inlen);
190 BIO_clear_retry_flags(bio);
192 status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len);
194 ctx->decrypt.status = status;
196 printf("bio_bucket_read received %d bytes (%d)\n", len, status);
199 if (!SERF_BUCKET_READ_ERROR(status)) {
202 memcpy(in, data, len);
205 if (APR_STATUS_IS_EOF(status)) {
206 BIO_set_retry_read(bio);
214 /* Returns the amount written. */
215 static int bio_bucket_write(BIO *bio, const char *in, int inl)
217 serf_ssl_context_t *ctx = bio->ptr;
218 serf_bucket_t *tmp = NULL;
221 printf("bio_bucket_write called for %d bytes\n", inl);
223 BIO_clear_retry_flags(bio);
225 if (ctx && ctx->encrypt.pending && ctx->encrypt.pending->allocator) {
226 tmp = serf_bucket_simple_copy_create(in, inl,
227 ctx->encrypt.pending->allocator);
228 serf_bucket_aggregate_append(ctx->encrypt.pending, tmp);
234 /* Returns the amount read. */
235 static int bio_file_read(BIO *bio, char *in, int inlen)
237 apr_file_t *file = bio->ptr;
241 BIO_clear_retry_flags(bio);
244 status = apr_file_read(file, in, &len);
246 if (!SERF_BUCKET_READ_ERROR(status)) {
248 if (APR_STATUS_IS_EOF(status)) {
249 BIO_set_retry_read(bio);
259 /* Returns the amount written. */
260 static int bio_file_write(BIO *bio, const char *in, int inl)
262 apr_file_t *file = bio->ptr;
265 BIO_clear_retry_flags(bio);
268 apr_file_write(file, in, &nbytes);
273 static int bio_file_gets(BIO *bio, char *in, int inlen)
275 return bio_file_read(bio, in, inlen);
278 static int bio_bucket_create(BIO *bio)
288 static int bio_bucket_destroy(BIO *bio)
290 /* Did we already free this? */
298 static long bio_bucket_ctrl(BIO *bio, int cmd, long num, void *ptr)
307 /* At this point we can't force a flush. */
317 static BIO_METHOD bio_bucket_method = {
319 "Serf SSL encryption and decryption buckets",
322 NULL, /* Is this called? */
323 NULL, /* Is this called? */
327 #ifdef OPENSSL_VERSION_NUMBER
328 NULL /* sslc does not have the callback_ctrl field */
332 static BIO_METHOD bio_file_method = {
334 "Wrapper around APR file structures",
337 NULL, /* Is this called? */
338 bio_file_gets, /* Is this called? */
342 #ifdef OPENSSL_VERSION_NUMBER
343 NULL /* sslc does not have the callback_ctrl field */
348 validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
351 serf_ssl_context_t *ctx;
356 ssl = X509_STORE_CTX_get_ex_data(store_ctx,
357 SSL_get_ex_data_X509_STORE_CTX_idx());
358 ctx = SSL_get_app_data(ssl);
360 server_cert = X509_STORE_CTX_get_current_cert(store_ctx);
361 depth = X509_STORE_CTX_get_error_depth(store_ctx);
363 /* If the certification was found invalid, get the error and convert it to
364 something our caller will understand. */
366 err = X509_STORE_CTX_get_error(store_ctx);
369 case X509_V_ERR_CERT_NOT_YET_VALID:
370 failures |= SERF_SSL_CERT_NOTYETVALID;
372 case X509_V_ERR_CERT_HAS_EXPIRED:
373 failures |= SERF_SSL_CERT_EXPIRED;
375 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
376 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
377 failures |= SERF_SSL_CERT_SELF_SIGNED;
379 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
380 failures |= SERF_SSL_CERT_UNKNOWNCA;
383 failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
388 /* Check certificate expiry dates. */
389 if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
390 failures |= SERF_SSL_CERT_NOTYETVALID;
392 else if (X509_cmp_current_time(X509_get_notAfter(server_cert)) <= 0) {
393 failures |= SERF_SSL_CERT_EXPIRED;
396 if (ctx->server_cert_callback &&
397 (depth == 0 || failures)) {
399 serf_ssl_certificate_t *cert;
402 apr_pool_create(&subpool, ctx->pool);
404 cert = apr_palloc(subpool, sizeof(serf_ssl_certificate_t));
405 cert->ssl_cert = server_cert;
407 /* Callback for further verification. */
408 status = ctx->server_cert_callback(ctx->server_cert_userdata,
410 if (status == APR_SUCCESS)
413 /* Pass the error back to the caller through the context-run. */
414 ctx->pending_err = status;
415 apr_pool_destroy(subpool);
421 /* This function reads an encrypted stream and returns the decrypted stream. */
422 static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
423 char *buf, apr_size_t *len)
425 serf_ssl_context_t *ctx = baton;
431 /* Is there some data waiting to be read? */
432 ssl_len = SSL_read(ctx->ssl, buf, bufsize);
435 printf("ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n",
436 ssl_len, bufsize, ctx->decrypt.status,
437 BIO_get_retry_flags(ctx->bio));
443 status = serf_bucket_read(ctx->decrypt.stream, bufsize, &data, &priv_len);
445 if (!SERF_BUCKET_READ_ERROR(status) && priv_len) {
449 printf("ssl_decrypt: read %d bytes (%d); status: %d\n", priv_len,
453 tmp = serf_bucket_simple_copy_create(data, priv_len,
454 ctx->decrypt.pending->allocator);
456 serf_bucket_aggregate_append(ctx->decrypt.pending, tmp);
458 ssl_len = SSL_read(ctx->ssl, buf, bufsize);
462 ssl_err = SSL_get_error(ctx->ssl, ssl_len);
464 case SSL_ERROR_SYSCALL:
466 status = ctx->decrypt.status;
468 case SSL_ERROR_WANT_READ:
474 status = ctx->pending_err;
475 ctx->pending_err = 0;
479 status = APR_EGENERAL;
491 printf("ssl_decrypt: %d %d %d\n", status, *len,
492 BIO_get_retry_flags(ctx->bio));
497 /* This function reads a decrypted stream and returns an encrypted stream. */
498 static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
499 char *buf, apr_size_t *len)
502 serf_ssl_context_t *ctx = baton;
505 /* Try to read unread data first. */
506 status = serf_bucket_read(ctx->encrypt.pending, bufsize, &data, len);
507 if (SERF_BUCKET_READ_ERROR(status)) {
511 /* Aha, we read something. Return that now. */
513 memcpy(buf, data, *len);
514 if (APR_STATUS_IS_EOF(status)) {
515 status = APR_SUCCESS;
518 printf("ssl_encrypt: %d %d %d (quick read)\n", status, *len,
519 BIO_get_retry_flags(ctx->bio));
524 if (BIO_should_retry(ctx->bio) && BIO_should_write(ctx->bio)) {
526 printf("ssl_encrypt: %d %d %d (should write exit)\n", status, *len,
527 BIO_get_retry_flags(ctx->bio));
532 /* Oh well, read from our stream now. */
533 if (!APR_STATUS_IS_EOF(ctx->encrypt.status)) {
534 status = serf_bucket_read(ctx->encrypt.stream, bufsize, &data, len);
541 if (!SERF_BUCKET_READ_ERROR(status) && *len) {
545 printf("ssl_encrypt: bucket read %d bytes; status %d\n", *len, status);
547 ctx->encrypt.status = status;
549 ssl_len = SSL_write(ctx->ssl, data, *len);
551 printf("ssl_encrypt: SSL write: %d\n", ssl_len);
557 /* Ah, bugger. We need to put that data back. */
558 if (!SERF_BUCKET_IS_AGGREGATE(ctx->encrypt.stream)) {
559 tmp = serf_bucket_aggregate_create(ctx->encrypt.stream->allocator);
560 serf_bucket_aggregate_append(tmp, ctx->encrypt.stream);
561 ctx->encrypt.stream = tmp;
564 tmp = serf_bucket_simple_copy_create(data, *len,
565 ctx->encrypt.stream->allocator);
567 serf_bucket_aggregate_prepend(ctx->encrypt.stream, tmp);
569 ssl_err = SSL_get_error(ctx->ssl, ssl_len);
570 if (ssl_err == SSL_ERROR_SYSCALL) {
571 status = ctx->encrypt.status;
572 if (SERF_BUCKET_READ_ERROR(status)) {
578 if (ssl_err == SSL_ERROR_WANT_READ) {
582 status = APR_EGENERAL;
588 apr_status_t agg_status;
590 /* We read something! */
591 agg_status = serf_bucket_read(ctx->encrypt.pending, bufsize,
594 memcpy(buf, data, *len);
596 if (APR_STATUS_IS_EOF(status) && !APR_STATUS_IS_EOF(agg_status)) {
603 printf("ssl_encrypt finished: %d %d %d\n", status, *len,
604 BIO_get_retry_flags(ctx->bio));
610 apr_pool_t *ssl_pool;
611 apr_thread_mutex_t **ssl_locks;
613 typedef struct CRYPTO_dynlock_value {
614 apr_thread_mutex_t *lock;
615 } CRYPTO_dynlock_value;
617 static CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line)
619 CRYPTO_dynlock_value *l;
622 l = apr_palloc(ssl_pool, sizeof(CRYPTO_dynlock_value));
623 rv = apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, ssl_pool);
624 if (rv != APR_SUCCESS) {
625 /* FIXME: return error here */
630 static void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file,
633 if (mode & CRYPTO_LOCK) {
634 apr_thread_mutex_lock(l->lock);
636 else if (mode & CRYPTO_UNLOCK) {
637 apr_thread_mutex_unlock(l->lock);
641 static void ssl_dyn_destroy(CRYPTO_dynlock_value *l, const char *file,
644 apr_thread_mutex_destroy(l->lock);
647 static void ssl_lock(int mode, int n, const char *file, int line)
649 if (mode & CRYPTO_LOCK) {
650 apr_thread_mutex_lock(ssl_locks[n]);
652 else if (mode & CRYPTO_UNLOCK) {
653 apr_thread_mutex_unlock(ssl_locks[n]);
657 static unsigned long ssl_id(void)
659 /* FIXME: This is lame and not portable. -aaron */
660 return (unsigned long) apr_os_thread_current();
663 static apr_status_t cleanup_ssl(void *data)
665 CRYPTO_set_locking_callback(NULL);
666 CRYPTO_set_id_callback(NULL);
667 CRYPTO_set_dynlock_create_callback(NULL);
668 CRYPTO_set_dynlock_lock_callback(NULL);
669 CRYPTO_set_dynlock_destroy_callback(NULL);
676 static int have_init_ssl = 0;
678 static void init_ssl_libraries(void)
680 if (!have_init_ssl) {
684 CRYPTO_malloc_init();
685 ERR_load_crypto_strings();
686 SSL_load_error_strings();
688 OpenSSL_add_all_algorithms();
691 numlocks = CRYPTO_num_locks();
692 apr_pool_create(&ssl_pool, NULL);
693 ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks);
694 for (i = 0; i < numlocks; i++) {
697 /* Intraprocess locks don't /need/ a filename... */
698 rv = apr_thread_mutex_create(&ssl_locks[i],
699 APR_THREAD_MUTEX_DEFAULT, ssl_pool);
700 if (rv != APR_SUCCESS) {
701 /* FIXME: error out here */
704 CRYPTO_set_locking_callback(ssl_lock);
705 CRYPTO_set_id_callback(ssl_id);
706 CRYPTO_set_dynlock_create_callback(ssl_dyn_create);
707 CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock);
708 CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy);
710 apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl);
717 static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
719 serf_ssl_context_t *ctx = SSL_get_app_data(ssl);
722 if (ctx->cached_cert) {
723 *cert = ctx->cached_cert;
724 *pkey = ctx->cached_cert_pw;
728 while (ctx->cert_callback) {
729 const char *cert_path;
730 apr_file_t *cert_file;
734 int retrying_success = 0;
736 if (ctx->cert_file_success) {
737 status = APR_SUCCESS;
738 cert_path = ctx->cert_file_success;
739 ctx->cert_file_success = NULL;
740 retrying_success = 1;
742 status = ctx->cert_callback(ctx->cert_userdata, &cert_path);
745 if (status || !cert_path) {
749 /* Load the x.509 cert file stored in PKCS12 */
750 status = apr_file_open(&cert_file, cert_path, APR_READ, APR_OS_DEFAULT,
757 bio = BIO_new(&bio_file_method);
758 bio->ptr = cert_file;
760 ctx->cert_path = cert_path;
761 p12 = d2i_PKCS12_bio(bio, NULL);
762 apr_file_close(cert_file);
764 i = PKCS12_parse(p12, NULL, pkey, cert, NULL);
768 ctx->cached_cert = *cert;
769 ctx->cached_cert_pw = *pkey;
770 if (!retrying_success && ctx->cert_cache_pool) {
773 c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path);
775 apr_pool_userdata_setn(c, "serf:ssl:cert",
776 apr_pool_cleanup_null,
777 ctx->cert_cache_pool);
782 int err = ERR_get_error();
784 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
785 ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
786 if (ctx->cert_pw_callback) {
787 const char *password;
789 if (ctx->cert_pw_success) {
790 status = APR_SUCCESS;
791 password = ctx->cert_pw_success;
792 ctx->cert_pw_success = NULL;
794 status = ctx->cert_pw_callback(ctx->cert_pw_userdata,
799 if (!status && password) {
800 i = PKCS12_parse(p12, password, pkey, cert, NULL);
803 ctx->cached_cert = *cert;
804 ctx->cached_cert_pw = *pkey;
805 if (!retrying_success && ctx->cert_cache_pool) {
808 c = apr_pstrdup(ctx->cert_cache_pool,
811 apr_pool_userdata_setn(c, "serf:ssl:cert",
812 apr_pool_cleanup_null,
813 ctx->cert_cache_pool);
815 if (!retrying_success && ctx->cert_pw_cache_pool) {
818 c = apr_pstrdup(ctx->cert_pw_cache_pool,
821 apr_pool_userdata_setn(c, "serf:ssl:certpw",
822 apr_pool_cleanup_null,
823 ctx->cert_pw_cache_pool);
833 printf("OpenSSL cert error: %d %d %d\n", ERR_GET_LIB(err),
835 ERR_GET_REASON(err));
845 serf_ssl_client_cert_provider_set(serf_ssl_context_t *context,
846 serf_ssl_need_client_cert_t callback,
850 context->cert_callback = callback;
851 context->cert_userdata = data;
852 context->cert_cache_pool = cache_pool;
853 if (context->cert_cache_pool) {
854 apr_pool_userdata_get((void**)&context->cert_file_success,
855 "serf:ssl:cert", cache_pool);
860 serf_ssl_client_cert_password_set(serf_ssl_context_t *context,
861 serf_ssl_need_cert_password_t callback,
865 context->cert_pw_callback = callback;
866 context->cert_pw_userdata = data;
867 context->cert_pw_cache_pool = cache_pool;
868 if (context->cert_pw_cache_pool) {
869 apr_pool_userdata_get((void**)&context->cert_pw_success,
870 "serf:ssl:certpw", cache_pool);
875 serf_ssl_server_cert_callback_set(serf_ssl_context_t *context,
876 serf_ssl_need_server_cert_t callback,
879 context->server_cert_callback = callback;
880 context->server_cert_userdata = data;
883 static serf_ssl_context_t *ssl_init_context(void)
885 serf_ssl_context_t *ssl_ctx;
887 serf_bucket_alloc_t *allocator;
889 init_ssl_libraries();
891 apr_pool_create(&pool, NULL);
892 allocator = serf_bucket_allocator_create(pool, NULL, NULL);
894 ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx));
896 ssl_ctx->refcount = 0;
897 ssl_ctx->pool = pool;
898 ssl_ctx->allocator = allocator;
900 ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
902 SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert);
903 ssl_ctx->cached_cert = 0;
904 ssl_ctx->cached_cert_pw = 0;
906 #if 0 /* for mod_chxj only */
907 SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER,
908 validate_server_certificate);
910 SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_NONE,
911 validate_server_certificate);
913 SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL);
915 ssl_ctx->ssl = SSL_new(ssl_ctx->ctx);
916 ssl_ctx->bio = BIO_new(&bio_bucket_method);
917 ssl_ctx->bio->ptr = ssl_ctx;
919 SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio);
921 SSL_set_connect_state(ssl_ctx->ssl);
923 SSL_set_app_data(ssl_ctx->ssl, ssl_ctx);
925 ssl_ctx->encrypt.stream = NULL;
926 ssl_ctx->encrypt.stream_next = NULL;
927 ssl_ctx->encrypt.pending = NULL;
928 ssl_ctx->encrypt.status = APR_SUCCESS;
929 serf_databuf_init(&ssl_ctx->encrypt.databuf);
930 ssl_ctx->encrypt.databuf.read = ssl_encrypt;
931 ssl_ctx->encrypt.databuf.read_baton = ssl_ctx;
933 ssl_ctx->decrypt.stream = NULL;
934 ssl_ctx->decrypt.pending = NULL;
935 ssl_ctx->decrypt.status = APR_SUCCESS;
936 serf_databuf_init(&ssl_ctx->decrypt.databuf);
937 ssl_ctx->decrypt.databuf.read = ssl_decrypt;
938 ssl_ctx->decrypt.databuf.read_baton = ssl_ctx;
943 static apr_status_t ssl_free_context(
944 serf_ssl_context_t *ssl_ctx)
948 /* If never had the pending buckets, don't try to free them. */
949 if (ssl_ctx->decrypt.pending != NULL) {
950 serf_bucket_destroy(ssl_ctx->decrypt.pending);
952 if (ssl_ctx->encrypt.pending != NULL) {
953 serf_bucket_destroy(ssl_ctx->encrypt.pending);
956 /* SSL_free implicitly frees the underlying BIO. */
957 SSL_free(ssl_ctx->ssl);
958 SSL_CTX_free(ssl_ctx->ctx);
962 serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx);
968 static serf_bucket_t * serf_bucket_ssl_create(
969 serf_ssl_context_t *ssl_ctx,
970 serf_bucket_alloc_t *allocator,
971 const serf_bucket_type_t *type)
975 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
977 ctx->ssl_ctx = ssl_init_context();
980 ctx->ssl_ctx = ssl_ctx;
982 ctx->ssl_ctx->refcount++;
984 return serf_bucket_create(type, allocator, ctx);
987 SERF_DECLARE(apr_status_t)
988 serf_ssl_use_default_certificates(serf_ssl_context_t *ssl_ctx)
990 X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
992 int result = X509_STORE_set_default_paths(store);
994 return result ? APR_SUCCESS : APR_EGENERAL;
997 SERF_DECLARE(apr_status_t)
998 serf_ssl_load_cert_file(serf_ssl_certificate_t **cert, const char *file_path,
1001 FILE *fp = fopen(file_path, "r");
1004 X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
1008 *cert = apr_palloc(pool, sizeof(serf_ssl_certificate_t));
1009 (*cert)->ssl_cert = ssl_cert;
1015 return APR_EGENERAL;
1018 SERF_DECLARE(apr_status_t)
1019 serf_ssl_trust_cert(serf_ssl_context_t *ssl_ctx, serf_ssl_certificate_t *cert)
1021 X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
1023 int result = X509_STORE_add_cert(store, cert->ssl_cert);
1025 return result ? APR_SUCCESS : APR_EGENERAL;
1028 SERF_DECLARE(serf_bucket_t *) serf_bucket_ssl_decrypt_create(
1029 serf_bucket_t *stream,
1030 serf_ssl_context_t *ssl_ctx,
1031 serf_bucket_alloc_t *allocator)
1036 bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1037 &serf_bucket_type_ssl_decrypt);
1041 ctx->databuf = &ctx->ssl_ctx->decrypt.databuf;
1042 if (ctx->ssl_ctx->decrypt.stream != NULL) {
1045 ctx->ssl_ctx->decrypt.stream = stream;
1046 ctx->our_stream = &ctx->ssl_ctx->decrypt.stream;
1047 ctx->ssl_ctx->decrypt.pending =
1048 serf_bucket_aggregate_create(allocator);
1053 SERF_DECLARE(serf_ssl_context_t *) serf_bucket_ssl_decrypt_context_get(
1054 serf_bucket_t *bucket)
1056 ssl_context_t *ctx = bucket->data;
1057 return ctx->ssl_ctx;
1060 SERF_DECLARE(serf_bucket_t *) serf_bucket_ssl_encrypt_create(
1061 serf_bucket_t *stream,
1062 serf_ssl_context_t *ssl_ctx,
1063 serf_bucket_alloc_t *allocator)
1068 bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1069 &serf_bucket_type_ssl_encrypt);
1073 ctx->databuf = &ctx->ssl_ctx->encrypt.databuf;
1074 ctx->our_stream = &ctx->ssl_ctx->encrypt.stream;
1075 if (ctx->ssl_ctx->encrypt.stream == NULL) {
1076 ctx->ssl_ctx->encrypt.stream = stream;
1077 ctx->ssl_ctx->encrypt.pending =
1078 serf_bucket_aggregate_create(allocator);
1081 bucket_list_t *new_list;
1083 new_list = serf_bucket_mem_alloc(ctx->ssl_ctx->allocator,
1085 new_list->bucket = stream;
1086 new_list->next = NULL;
1087 if (ctx->ssl_ctx->encrypt.stream_next == NULL) {
1088 ctx->ssl_ctx->encrypt.stream_next = new_list;
1091 bucket_list_t *scan = ctx->ssl_ctx->encrypt.stream_next;
1093 while (scan->next != NULL)
1095 scan->next = new_list;
1102 SERF_DECLARE(serf_ssl_context_t *) serf_bucket_ssl_encrypt_context_get(
1103 serf_bucket_t *bucket)
1105 ssl_context_t *ctx = bucket->data;
1106 return ctx->ssl_ctx;
1109 /* Functions to read a serf_ssl_certificate structure. */
1111 /* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
1113 convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
1118 apr_hash_t *tgt = apr_hash_make(pool);
1120 ret = X509_NAME_get_text_by_NID(org,
1124 apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1125 ret = X509_NAME_get_text_by_NID(org,
1126 NID_pkcs9_emailAddress,
1129 apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1130 ret = X509_NAME_get_text_by_NID(org,
1131 NID_organizationalUnitName,
1134 apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1135 ret = X509_NAME_get_text_by_NID(org,
1136 NID_organizationName,
1139 apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1140 ret = X509_NAME_get_text_by_NID(org,
1144 apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1145 ret = X509_NAME_get_text_by_NID(org,
1146 NID_stateOrProvinceName,
1149 apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1150 ret = X509_NAME_get_text_by_NID(org,
1154 apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1159 SERF_DECLARE(apr_hash_t *)
1160 serf_ssl_cert_issuer(const serf_ssl_certificate_t *cert, apr_pool_t *pool)
1163 X509_NAME *issuer = X509_get_issuer_name(cert->ssl_cert);
1167 return convert_X509_NAME_to_table(issuer, pool);
1170 SERF_DECLARE(apr_hash_t *)
1171 serf_ssl_cert_subject(const serf_ssl_certificate_t *cert, apr_pool_t *pool)
1174 X509_NAME *subject = X509_get_subject_name(cert->ssl_cert);
1178 return convert_X509_NAME_to_table(subject, pool);
1181 SERF_DECLARE(apr_hash_t *)
1182 serf_ssl_cert_certificate(const serf_ssl_certificate_t *cert, apr_pool_t *pool)
1184 apr_hash_t *tgt = apr_hash_make(pool);
1185 unsigned int md_size, i;
1186 unsigned char md[EVP_MAX_MD_SIZE];
1189 /* sha1 fingerprint */
1190 if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
1191 const char hex[] = "0123456789ABCDEF";
1192 char fingerprint[EVP_MAX_MD_SIZE * 3];
1194 for (i=0; i<md_size; i++) {
1195 fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4];
1196 fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)];
1197 fingerprint[(3*i)+2] = ':';
1200 fingerprint[(3*(md_size-1))+2] = '\0';
1202 fingerprint[0] = '\0';
1204 apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING,
1205 apr_pstrdup(pool, fingerprint));
1208 /* set expiry dates */
1209 bio = BIO_new(BIO_s_mem());
1211 ASN1_TIME *notBefore, *notAfter;
1214 memset (buf, 0, sizeof (buf));
1215 notBefore = X509_get_notBefore(cert->ssl_cert);
1216 if (ASN1_TIME_print(bio, notBefore)) {
1217 BIO_read(bio, buf, 255);
1218 apr_hash_set(tgt, "notBefore", APR_HASH_KEY_STRING,
1219 apr_pstrdup(pool, buf));
1221 memset (buf, 0, sizeof (buf));
1222 notAfter = X509_get_notAfter(cert->ssl_cert);
1223 if (ASN1_TIME_print(bio, notAfter)) {
1224 BIO_read(bio, buf, 255);
1225 apr_hash_set(tgt, "notAfter", APR_HASH_KEY_STRING,
1226 apr_pstrdup(pool, buf));
1234 static void serf_ssl_destroy_and_data(serf_bucket_t *bucket)
1236 ssl_context_t *ctx = bucket->data;
1238 if (!--ctx->ssl_ctx->refcount) {
1239 ssl_free_context(ctx->ssl_ctx);
1242 serf_default_destroy_and_data(bucket);
1245 static void serf_ssl_decrypt_destroy_and_data(serf_bucket_t *bucket)
1247 ssl_context_t *ctx = bucket->data;
1249 serf_bucket_destroy(*ctx->our_stream);
1251 serf_ssl_destroy_and_data(bucket);
1254 static void serf_ssl_encrypt_destroy_and_data(serf_bucket_t *bucket)
1256 ssl_context_t *ctx = bucket->data;
1257 serf_ssl_context_t *ssl_ctx = ctx->ssl_ctx;
1259 if (ssl_ctx->encrypt.stream == *ctx->our_stream) {
1260 serf_bucket_destroy(*ctx->our_stream);
1261 serf_bucket_destroy(ssl_ctx->encrypt.pending);
1263 /* Reset our encrypted status and databuf. */
1264 ssl_ctx->encrypt.status = APR_SUCCESS;
1265 ssl_ctx->encrypt.databuf.status = APR_SUCCESS;
1267 /* Advance to the next stream - if we have one. */
1268 if (ssl_ctx->encrypt.stream_next == NULL) {
1269 ssl_ctx->encrypt.stream = NULL;
1270 ssl_ctx->encrypt.pending = NULL;
1275 cur = ssl_ctx->encrypt.stream_next;
1276 ssl_ctx->encrypt.stream = cur->bucket;
1277 ssl_ctx->encrypt.pending =
1278 serf_bucket_aggregate_create(cur->bucket->allocator);
1279 ssl_ctx->encrypt.stream_next = cur->next;
1280 serf_bucket_mem_free(ssl_ctx->allocator, cur);
1284 /* Ah, darn. We haven't sent this one along yet. */
1287 serf_ssl_destroy_and_data(bucket);
1290 static apr_status_t serf_ssl_read(serf_bucket_t *bucket,
1291 apr_size_t requested,
1292 const char **data, apr_size_t *len)
1294 ssl_context_t *ctx = bucket->data;
1296 return serf_databuf_read(ctx->databuf, requested, data, len);
1299 static apr_status_t serf_ssl_readline(serf_bucket_t *bucket,
1300 int acceptable, int *found,
1304 ssl_context_t *ctx = bucket->data;
1306 return serf_databuf_readline(ctx->databuf, acceptable, found, data, len);
1309 static apr_status_t serf_ssl_peek(serf_bucket_t *bucket,
1313 ssl_context_t *ctx = bucket->data;
1315 return serf_databuf_peek(ctx->databuf, data, len);
1319 SERF_DECLARE_DATA const serf_bucket_type_t serf_bucket_type_ssl_encrypt = {
1323 serf_default_read_iovec,
1324 serf_default_read_for_sendfile,
1325 serf_default_read_bucket,
1327 serf_ssl_encrypt_destroy_and_data,
1330 SERF_DECLARE_DATA const serf_bucket_type_t serf_bucket_type_ssl_decrypt = {
1334 serf_default_read_iovec,
1335 serf_default_read_for_sendfile,
1336 serf_default_read_bucket,
1338 serf_ssl_decrypt_destroy_and_data,