ssl_buckets.c revision 262339
1/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
2 *
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
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
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.
14 *
15 * ----
16 *
17 * For the OpenSSL thread-safety locking code:
18 *
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
25 *
26 *     http://www.apache.org/licenses/LICENSE-2.0
27 *
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.
33 *
34 * Originally developed by Aaron Bannert and Justin Erenkrantz, eBuilt.
35 */
36
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>
44
45#include "serf.h"
46#include "serf_private.h"
47#include "serf_bucket_util.h"
48
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>
54
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 */
62
63#ifndef APR_ARRAY_PUSH
64#define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary)))
65#endif
66
67
68/*
69 * Here's an overview of the SSL bucket's relationship to OpenSSL and serf.
70 *
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]
75 *
76 * HTTP request read call path:
77 *
78 * write_to_connection
79 *  |- serf_bucket_read on SSLENCRYPT
80 *    |- serf_ssl_read
81 *      |- serf_databuf_read
82 *        |- common_databuf_prep
83 *          |- ssl_encrypt
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
87 *              |- ...
88 *                |- bio_bucket_read can be called
89 *                |- bio_bucket_write with encrypted data
90 *                  |- store in sink
91 *            |- 4. If successful, read pending encrypted data and return.
92 *            |- 5. If fails, place read data back in ctx->stream
93 *
94 * HTTP response read call path:
95 *
96 * read_from_connection
97 *  |- acceptor
98 *  |- handler
99 *    |- ...
100 *      |- serf_bucket_read(SSLDECRYPT)
101 *        |- serf_ssl_read
102 *          |- serf_databuf_read
103 *            |- ssl_decrypt
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()
108 *                |- ...
109 *                  |- bio_bucket_write can be called
110 *                  |- bio_bucket_read
111 *                    |- read data from ssl_ctx->source
112 *              |- If data read, return it.
113 *              |- If an error, set the STATUS value and return.
114 *
115 */
116
117typedef struct bucket_list {
118    serf_bucket_t *bucket;
119    struct bucket_list *next;
120} bucket_list_t;
121
122typedef struct {
123    /* Helper to read data. Wraps stream. */
124    serf_databuf_t databuf;
125
126    /* Our source for more data. */
127    serf_bucket_t *stream;
128
129    /* The next set of buckets */
130    bucket_list_t *stream_next;
131
132    /* The status of the last thing we read. */
133    apr_status_t status;
134    apr_status_t exhausted;
135    int exhausted_reset;
136
137    /* Data we've read but not processed. */
138    serf_bucket_t *pending;
139} serf_ssl_stream_t;
140
141struct serf_ssl_context_t {
142    /* How many open buckets refer to this context. */
143    int refcount;
144
145    /* The pool that this context uses. */
146    apr_pool_t *pool;
147
148    /* The allocator associated with the above pool. */
149    serf_bucket_alloc_t *allocator;
150
151    /* Internal OpenSSL parameters */
152    SSL_CTX *ctx;
153    SSL *ssl;
154    BIO *bio;
155
156    serf_ssl_stream_t encrypt;
157    serf_ssl_stream_t decrypt;
158
159    /* Client cert callbacks */
160    serf_ssl_need_client_cert_t cert_callback;
161    void *cert_userdata;
162    apr_pool_t *cert_cache_pool;
163    const char *cert_file_success;
164
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;
170
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;
175
176    const char *cert_path;
177
178    X509 *cached_cert;
179    EVP_PKEY *cached_cert_pw;
180
181    apr_status_t pending_err;
182
183    /* Status of a fatal error, returned on subsequent encrypt or decrypt
184       requests. */
185    apr_status_t fatal_err;
186};
187
188typedef struct {
189    /* The bucket-independent ssl context that this bucket is associated with */
190    serf_ssl_context_t *ssl_ctx;
191
192    /* Pointer to the 'right' databuf. */
193    serf_databuf_t *databuf;
194
195    /* Pointer to our stream, so we can find it later. */
196    serf_bucket_t **our_stream;
197} ssl_context_t;
198
199struct serf_ssl_certificate_t {
200    X509 *ssl_cert;
201    int depth;
202};
203
204static void disable_compression(serf_ssl_context_t *ssl_ctx);
205
206#if SSL_VERBOSE
207/* Log all ssl alerts that we receive from the server. */
208static void
209apps_ssl_info_callback(const SSL *s, int where, int ret)
210{
211    const char *str;
212    int w;
213    w = where & ~SSL_ST_MASK;
214
215    if (w & SSL_ST_CONNECT)
216        str = "SSL_connect";
217    else if (w & SSL_ST_ACCEPT)
218        str = "SSL_accept";
219    else
220        str = "undefined";
221
222    if (where & SSL_CB_LOOP) {
223        serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str,
224                  SSL_state_string_long(s));
225    }
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",
229               str,
230               SSL_alert_type_string_long(ret),
231               SSL_alert_desc_string_long(ret));
232    }
233    else if (where & SSL_CB_EXIT) {
234        if (ret == 0)
235            serf__log(SSL_VERBOSE, __FILE__, "%s:failed in %s\n", str,
236                      SSL_state_string_long(s));
237        else if (ret < 0) {
238            serf__log(SSL_VERBOSE, __FILE__, "%s:error in %s\n", str,
239                      SSL_state_string_long(s));
240        }
241    }
242}
243#endif
244
245/* Returns the amount read. */
246static int bio_bucket_read(BIO *bio, char *in, int inlen)
247{
248    serf_ssl_context_t *ctx = bio->ptr;
249    const char *data;
250    apr_status_t status;
251    apr_size_t len;
252
253    serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read called for %d bytes\n",
254              inlen);
255
256    if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
257        && BIO_should_read(ctx->bio)) {
258        serf__log(SSL_VERBOSE, __FILE__,
259                  "bio_bucket_read waiting: (%d %d %d)\n",
260           BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
261           BIO_get_retry_flags(ctx->bio));
262        /* Falling back... */
263        ctx->encrypt.exhausted_reset = 1;
264        BIO_clear_retry_flags(bio);
265    }
266
267    status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len);
268
269    ctx->decrypt.status = status;
270
271    serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read received %d bytes (%d)\n",
272              len, status);
273
274    if (!SERF_BUCKET_READ_ERROR(status)) {
275        /* Oh suck. */
276        if (len) {
277            memcpy(in, data, len);
278            return len;
279        }
280        if (APR_STATUS_IS_EOF(status)) {
281            BIO_set_retry_read(bio);
282            return -1;
283        }
284    }
285
286    return -1;
287}
288
289/* Returns the amount written. */
290static int bio_bucket_write(BIO *bio, const char *in, int inl)
291{
292    serf_ssl_context_t *ctx = bio->ptr;
293    serf_bucket_t *tmp;
294
295    serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write called for %d bytes\n",
296              inl);
297
298    if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
299        && !BIO_should_read(ctx->bio)) {
300        serf__log(SSL_VERBOSE, __FILE__,
301                  "bio_bucket_write waiting: (%d %d %d)\n",
302           BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
303           BIO_get_retry_flags(ctx->bio));
304        /* Falling back... */
305        ctx->encrypt.exhausted_reset = 1;
306        BIO_clear_retry_flags(bio);
307    }
308
309    tmp = serf_bucket_simple_copy_create(in, inl,
310                                         ctx->encrypt.pending->allocator);
311
312    serf_bucket_aggregate_append(ctx->encrypt.pending, tmp);
313
314    return inl;
315}
316
317/* Returns the amount read. */
318static int bio_file_read(BIO *bio, char *in, int inlen)
319{
320    apr_file_t *file = bio->ptr;
321    apr_status_t status;
322    apr_size_t len;
323
324    BIO_clear_retry_flags(bio);
325
326    len = inlen;
327    status = apr_file_read(file, in, &len);
328
329    if (!SERF_BUCKET_READ_ERROR(status)) {
330        /* Oh suck. */
331        if (APR_STATUS_IS_EOF(status)) {
332            BIO_set_retry_read(bio);
333            return -1;
334        } else {
335            return len;
336        }
337    }
338
339    return -1;
340}
341
342/* Returns the amount written. */
343static int bio_file_write(BIO *bio, const char *in, int inl)
344{
345    apr_file_t *file = bio->ptr;
346    apr_size_t nbytes;
347
348    BIO_clear_retry_flags(bio);
349
350    nbytes = inl;
351    apr_file_write(file, in, &nbytes);
352
353    return nbytes;
354}
355
356static int bio_file_gets(BIO *bio, char *in, int inlen)
357{
358    return bio_file_read(bio, in, inlen);
359}
360
361static int bio_bucket_create(BIO *bio)
362{
363    bio->shutdown = 1;
364    bio->init = 1;
365    bio->num = -1;
366    bio->ptr = NULL;
367
368    return 1;
369}
370
371static int bio_bucket_destroy(BIO *bio)
372{
373    /* Did we already free this? */
374    if (bio == NULL) {
375        return 0;
376    }
377
378    return 1;
379}
380
381static long bio_bucket_ctrl(BIO *bio, int cmd, long num, void *ptr)
382{
383    long ret = 1;
384
385    switch (cmd) {
386    default:
387        /* abort(); */
388        break;
389    case BIO_CTRL_FLUSH:
390        /* At this point we can't force a flush. */
391        break;
392    case BIO_CTRL_PUSH:
393    case BIO_CTRL_POP:
394        ret = 0;
395        break;
396    }
397    return ret;
398}
399
400static BIO_METHOD bio_bucket_method = {
401    BIO_TYPE_MEM,
402    "Serf SSL encryption and decryption buckets",
403    bio_bucket_write,
404    bio_bucket_read,
405    NULL,                        /* Is this called? */
406    NULL,                        /* Is this called? */
407    bio_bucket_ctrl,
408    bio_bucket_create,
409    bio_bucket_destroy,
410#ifdef OPENSSL_VERSION_NUMBER
411    NULL /* sslc does not have the callback_ctrl field */
412#endif
413};
414
415static BIO_METHOD bio_file_method = {
416    BIO_TYPE_FILE,
417    "Wrapper around APR file structures",
418    bio_file_write,
419    bio_file_read,
420    NULL,                        /* Is this called? */
421    bio_file_gets,               /* Is this called? */
422    bio_bucket_ctrl,
423    bio_bucket_create,
424    bio_bucket_destroy,
425#ifdef OPENSSL_VERSION_NUMBER
426    NULL /* sslc does not have the callback_ctrl field */
427#endif
428};
429
430static int
431validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
432{
433    SSL *ssl;
434    serf_ssl_context_t *ctx;
435    X509 *server_cert;
436    int err, depth;
437    int failures = 0;
438
439    ssl = X509_STORE_CTX_get_ex_data(store_ctx,
440                                     SSL_get_ex_data_X509_STORE_CTX_idx());
441    ctx = SSL_get_app_data(ssl);
442
443    server_cert = X509_STORE_CTX_get_current_cert(store_ctx);
444    depth = X509_STORE_CTX_get_error_depth(store_ctx);
445
446    /* If the certification was found invalid, get the error and convert it to
447       something our caller will understand. */
448    if (! cert_valid) {
449        err = X509_STORE_CTX_get_error(store_ctx);
450
451        switch(err) {
452            case X509_V_ERR_CERT_NOT_YET_VALID:
453                    failures |= SERF_SSL_CERT_NOTYETVALID;
454                    break;
455            case X509_V_ERR_CERT_HAS_EXPIRED:
456                    failures |= SERF_SSL_CERT_EXPIRED;
457                    break;
458            case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
459            case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
460                    failures |= SERF_SSL_CERT_SELF_SIGNED;
461                    break;
462            case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
463            case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
464            case X509_V_ERR_CERT_UNTRUSTED:
465            case X509_V_ERR_INVALID_CA:
466            case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
467                    failures |= SERF_SSL_CERT_UNKNOWNCA;
468                    break;
469            case X509_V_ERR_CERT_REVOKED:
470                    failures |= SERF_SSL_CERT_REVOKED;
471                    break;
472            default:
473                    failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
474                    break;
475        }
476    }
477
478    /* Check certificate expiry dates. */
479    if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
480        failures |= SERF_SSL_CERT_NOTYETVALID;
481    }
482    else if (X509_cmp_current_time(X509_get_notAfter(server_cert)) <= 0) {
483        failures |= SERF_SSL_CERT_EXPIRED;
484    }
485
486    if (ctx->server_cert_callback &&
487        (depth == 0 || failures)) {
488        apr_status_t status;
489        serf_ssl_certificate_t *cert;
490        apr_pool_t *subpool;
491
492        apr_pool_create(&subpool, ctx->pool);
493
494        cert = apr_palloc(subpool, sizeof(serf_ssl_certificate_t));
495        cert->ssl_cert = server_cert;
496        cert->depth = depth;
497
498        /* Callback for further verification. */
499        status = ctx->server_cert_callback(ctx->server_cert_userdata,
500                                           failures, cert);
501        if (status == APR_SUCCESS)
502            cert_valid = 1;
503        else {
504            /* Even if openssl found the certificate valid, the application
505               told us to reject it. */
506            cert_valid = 0;
507            /* Pass the error back to the caller through the context-run. */
508            ctx->pending_err = status;
509        }
510        apr_pool_destroy(subpool);
511    }
512
513    if (ctx->server_cert_chain_callback
514        && (depth == 0 || failures)) {
515        apr_status_t status;
516        STACK_OF(X509) *chain;
517        const serf_ssl_certificate_t **certs;
518        int certs_len;
519        apr_pool_t *subpool;
520
521        apr_pool_create(&subpool, ctx->pool);
522
523        /* Borrow the chain to pass to the callback. */
524        chain = X509_STORE_CTX_get_chain(store_ctx);
525
526        /* If the chain can't be retrieved, just pass the current
527           certificate. */
528        /* ### can this actually happen with _get_chain() ?  */
529        if (!chain) {
530            serf_ssl_certificate_t *cert = apr_palloc(subpool, sizeof(*cert));
531
532            cert->ssl_cert = server_cert;
533            cert->depth = depth;
534
535            /* Room for the server_cert and a trailing NULL.  */
536            certs = apr_palloc(subpool, sizeof(*certs) * 2);
537            certs[0] = cert;
538
539            certs_len = 1;
540        } else {
541            int i;
542
543            certs_len = sk_X509_num(chain);
544
545            /* Room for all the certs and a trailing NULL.  */
546            certs = apr_palloc(subpool, sizeof(*certs) * (certs_len + 1));
547            for (i = 0; i < certs_len; ++i) {
548                serf_ssl_certificate_t *cert;
549
550                cert = apr_palloc(subpool, sizeof(*cert));
551                cert->ssl_cert = sk_X509_value(chain, i);
552                cert->depth = i;
553
554                certs[i] = cert;
555            }
556        }
557        certs[certs_len] = NULL;
558
559        /* Callback for further verification. */
560        status = ctx->server_cert_chain_callback(ctx->server_cert_userdata,
561                                                 failures, depth,
562                                                 certs, certs_len);
563        if (status == APR_SUCCESS) {
564            cert_valid = 1;
565        } else {
566            /* Even if openssl found the certificate valid, the application
567               told us to reject it. */
568            cert_valid = 0;
569            /* Pass the error back to the caller through the context-run. */
570            ctx->pending_err = status;
571        }
572
573        apr_pool_destroy(subpool);
574    }
575
576    /* Return a specific error if the server certificate is not accepted by
577       OpenSSL and the application has not set callbacks to override this. */
578    if (!cert_valid &&
579        !ctx->server_cert_chain_callback &&
580        !ctx->server_cert_callback)
581    {
582        ctx->pending_err = SERF_ERROR_SSL_CERT_FAILED;
583    }
584
585    return cert_valid;
586}
587
588/* This function reads an encrypted stream and returns the decrypted stream. */
589static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
590                                char *buf, apr_size_t *len)
591{
592    serf_ssl_context_t *ctx = baton;
593    apr_size_t priv_len;
594    apr_status_t status;
595    const char *data;
596    int ssl_len;
597
598    if (ctx->fatal_err)
599        return ctx->fatal_err;
600
601    serf__log(SSL_VERBOSE, __FILE__, "ssl_decrypt: begin %d\n", bufsize);
602
603    /* Is there some data waiting to be read? */
604    ssl_len = SSL_read(ctx->ssl, buf, bufsize);
605    if (ssl_len > 0) {
606        serf__log(SSL_VERBOSE, __FILE__,
607                  "ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n",
608                  ssl_len, bufsize, ctx->decrypt.status,
609                  BIO_get_retry_flags(ctx->bio));
610        *len = ssl_len;
611        return APR_SUCCESS;
612    }
613
614    status = serf_bucket_read(ctx->decrypt.stream, bufsize, &data, &priv_len);
615
616    if (!SERF_BUCKET_READ_ERROR(status) && priv_len) {
617        serf_bucket_t *tmp;
618
619        serf__log(SSL_VERBOSE, __FILE__,
620                  "ssl_decrypt: read %d bytes (%d); status: %d\n",
621                  priv_len, bufsize, status);
622
623        tmp = serf_bucket_simple_copy_create(data, priv_len,
624                                             ctx->decrypt.pending->allocator);
625
626        serf_bucket_aggregate_append(ctx->decrypt.pending, tmp);
627
628        ssl_len = SSL_read(ctx->ssl, buf, bufsize);
629        if (ssl_len < 0) {
630            int ssl_err;
631
632            ssl_err = SSL_get_error(ctx->ssl, ssl_len);
633            switch (ssl_err) {
634            case SSL_ERROR_SYSCALL:
635                *len = 0;
636                /* Return the underlying network error that caused OpenSSL
637                   to fail. ### This can be a crypt error! */
638                status = ctx->decrypt.status;
639                break;
640            case SSL_ERROR_WANT_READ:
641            case SSL_ERROR_WANT_WRITE:
642                *len = 0;
643                status = APR_EAGAIN;
644                break;
645            case SSL_ERROR_SSL:
646                *len = 0;
647                if (ctx->pending_err) {
648                    status = ctx->pending_err;
649                    ctx->pending_err = 0;
650                } else {
651                    ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
652                }
653                break;
654            default:
655                *len = 0;
656                ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
657                break;
658            }
659        } else if (ssl_len == 0) {
660            /* The server shut down the connection. */
661            int ssl_err, shutdown;
662            *len = 0;
663
664            /* Check for SSL_RECEIVED_SHUTDOWN */
665            shutdown = SSL_get_shutdown(ctx->ssl);
666            /* Check for SSL_ERROR_ZERO_RETURN */
667            ssl_err = SSL_get_error(ctx->ssl, ssl_len);
668
669            if (shutdown == SSL_RECEIVED_SHUTDOWN &&
670                ssl_err == SSL_ERROR_ZERO_RETURN) {
671                /* The server closed the SSL session. While this doesn't
672                necessary mean the connection is closed, let's close
673                it here anyway.
674                We can optimize this later. */
675                serf__log(SSL_VERBOSE, __FILE__,
676                          "ssl_decrypt: SSL read error: server"
677                          " shut down connection!\n");
678                status = APR_EOF;
679            } else {
680                /* A fatal error occurred. */
681                ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
682            }
683        } else {
684            *len = ssl_len;
685            serf__log(SSL_MSG_VERBOSE, __FILE__,
686                      "---\n%.*s\n-(%d)-\n", *len, buf, *len);
687        }
688    }
689    else {
690        *len = 0;
691    }
692    serf__log(SSL_VERBOSE, __FILE__,
693              "ssl_decrypt: %d %d %d\n", status, *len,
694              BIO_get_retry_flags(ctx->bio));
695
696    return status;
697}
698
699/* This function reads a decrypted stream and returns an encrypted stream. */
700static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
701                                char *buf, apr_size_t *len)
702{
703    const char *data;
704    apr_size_t interim_bufsize;
705    serf_ssl_context_t *ctx = baton;
706    apr_status_t status;
707
708    if (ctx->fatal_err)
709        return ctx->fatal_err;
710
711    serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: begin %d\n", bufsize);
712
713    /* Try to read already encrypted but unread data first. */
714    status = serf_bucket_read(ctx->encrypt.pending, bufsize, &data, len);
715    if (SERF_BUCKET_READ_ERROR(status)) {
716        return status;
717    }
718
719    /* Aha, we read something.  Return that now. */
720    if (*len) {
721        memcpy(buf, data, *len);
722        if (APR_STATUS_IS_EOF(status)) {
723            status = APR_SUCCESS;
724        }
725
726        serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: %d %d %d (quick read)\n",
727                  status, *len, BIO_get_retry_flags(ctx->bio));
728
729        return status;
730    }
731
732    if (BIO_should_retry(ctx->bio) && BIO_should_write(ctx->bio)) {
733        serf__log(SSL_VERBOSE, __FILE__,
734                  "ssl_encrypt: %d %d %d (should write exit)\n",
735                  status, *len, BIO_get_retry_flags(ctx->bio));
736
737        return APR_EAGAIN;
738    }
739
740    /* If we were previously blocked, unblock ourselves now. */
741    if (BIO_should_read(ctx->bio)) {
742        serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: reset %d %d (%d %d %d)\n",
743                  status, ctx->encrypt.status,
744                  BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
745                  BIO_get_retry_flags(ctx->bio));
746
747        ctx->encrypt.status = APR_SUCCESS;
748        ctx->encrypt.exhausted_reset = 0;
749    }
750
751    /* Oh well, read from our stream now. */
752    interim_bufsize = bufsize;
753    do {
754        apr_size_t interim_len;
755
756        if (!ctx->encrypt.status) {
757            struct iovec vecs[64];
758            int vecs_read;
759
760            status = serf_bucket_read_iovec(ctx->encrypt.stream,
761                                            interim_bufsize, 64, vecs,
762                                            &vecs_read);
763
764            if (!SERF_BUCKET_READ_ERROR(status) && vecs_read) {
765                char *vecs_data;
766                int i, cur, vecs_data_len;
767                int ssl_len;
768
769                /* Combine the buffers of the iovec into one buffer, as
770                   that is with SSL_write requires. */
771                vecs_data_len = 0;
772                for (i = 0; i < vecs_read; i++) {
773                    vecs_data_len += vecs[i].iov_len;
774                }
775
776                vecs_data = serf_bucket_mem_alloc(ctx->allocator,
777                                                  vecs_data_len);
778
779                cur = 0;
780                for (i = 0; i < vecs_read; i++) {
781                    memcpy(vecs_data + cur, vecs[i].iov_base, vecs[i].iov_len);
782                    cur += vecs[i].iov_len;
783                }
784
785                interim_bufsize -= vecs_data_len;
786                interim_len = vecs_data_len;
787
788                serf__log(SSL_VERBOSE, __FILE__,
789                          "ssl_encrypt: bucket read %d bytes; "\
790                          "status %d\n", interim_len, status);
791                serf__log(SSL_MSG_VERBOSE, __FILE__, "---\n%.*s\n-(%d)-\n",
792                          interim_len, vecs_data, interim_len);
793
794                /* Stash our status away. */
795                ctx->encrypt.status = status;
796
797                ssl_len = SSL_write(ctx->ssl, vecs_data, interim_len);
798
799                serf__log(SSL_VERBOSE, __FILE__,
800                          "ssl_encrypt: SSL write: %d\n", ssl_len);
801
802                /* If we failed to write... */
803                if (ssl_len < 0) {
804                    int ssl_err;
805
806                    /* Ah, bugger. We need to put that data back.
807                       Note: use the copy here, we do not own the original iovec
808                       data buffer so it will be freed on next read. */
809                    serf_bucket_t *vecs_copy =
810                        serf_bucket_simple_own_create(vecs_data,
811                                                      vecs_data_len,
812                                                      ctx->allocator);
813                    serf_bucket_aggregate_prepend(ctx->encrypt.stream,
814                                                  vecs_copy);
815
816                    ssl_err = SSL_get_error(ctx->ssl, ssl_len);
817
818                    serf__log(SSL_VERBOSE, __FILE__,
819                              "ssl_encrypt: SSL write error: %d\n", ssl_err);
820
821                    if (ssl_err == SSL_ERROR_SYSCALL) {
822                        /* Return the underlying network error that caused OpenSSL
823                           to fail. ### This can be a decrypt error! */
824                        status = ctx->encrypt.status;
825                        if (SERF_BUCKET_READ_ERROR(status)) {
826                            return status;
827                        }
828                    }
829                    else {
830                        /* Oh, no. */
831                        if (ssl_err == SSL_ERROR_WANT_READ) {
832                            status = SERF_ERROR_WAIT_CONN;
833                        }
834                        else {
835                            ctx->fatal_err = status =
836                                SERF_ERROR_SSL_COMM_FAILED;
837                        }
838                    }
839
840                    serf__log(SSL_VERBOSE, __FILE__,
841                              "ssl_encrypt: SSL write error: %d %d\n",
842                              status, *len);
843                } else {
844                    /* We're done with this data. */
845                    serf_bucket_mem_free(ctx->allocator, vecs_data);
846                }
847            }
848        }
849        else {
850            interim_len = 0;
851            *len = 0;
852            status = ctx->encrypt.status;
853        }
854
855    } while (!status && interim_bufsize);
856
857    /* Okay, we exhausted our underlying stream. */
858    if (!SERF_BUCKET_READ_ERROR(status)) {
859        apr_status_t agg_status;
860        struct iovec vecs[64];
861        int vecs_read, i;
862
863        /* We read something! */
864        agg_status = serf_bucket_read_iovec(ctx->encrypt.pending, bufsize,
865                                            64, vecs, &vecs_read);
866        *len = 0;
867        for (i = 0; i < vecs_read; i++) {
868            memcpy(buf + *len, vecs[i].iov_base, vecs[i].iov_len);
869            *len += vecs[i].iov_len;
870        }
871
872        serf__log(SSL_VERBOSE, __FILE__,
873                  "ssl_encrypt read agg: %d %d %d %d\n", status, agg_status,
874            ctx->encrypt.status, *len);
875
876        if (!agg_status) {
877            status = agg_status;
878        }
879    }
880
881    if (status == SERF_ERROR_WAIT_CONN
882        && BIO_should_retry(ctx->bio) && BIO_should_read(ctx->bio)) {
883        ctx->encrypt.exhausted = ctx->encrypt.status;
884        ctx->encrypt.status = SERF_ERROR_WAIT_CONN;
885    }
886
887    serf__log(SSL_VERBOSE, __FILE__,
888              "ssl_encrypt finished: %d %d (%d %d %d)\n", status, *len,
889              BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
890              BIO_get_retry_flags(ctx->bio));
891
892    return status;
893}
894
895#if APR_HAS_THREADS
896static apr_pool_t *ssl_pool;
897static apr_thread_mutex_t **ssl_locks;
898
899typedef struct CRYPTO_dynlock_value {
900    apr_thread_mutex_t *lock;
901} CRYPTO_dynlock_value;
902
903static CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line)
904{
905    CRYPTO_dynlock_value *l;
906    apr_status_t rv;
907
908    l = apr_palloc(ssl_pool, sizeof(CRYPTO_dynlock_value));
909    rv = apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, ssl_pool);
910    if (rv != APR_SUCCESS) {
911        /* FIXME: return error here */
912    }
913    return l;
914}
915
916static void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file,
917                         int line)
918{
919    if (mode & CRYPTO_LOCK) {
920        apr_thread_mutex_lock(l->lock);
921    }
922    else if (mode & CRYPTO_UNLOCK) {
923        apr_thread_mutex_unlock(l->lock);
924    }
925}
926
927static void ssl_dyn_destroy(CRYPTO_dynlock_value *l, const char *file,
928                            int line)
929{
930    apr_thread_mutex_destroy(l->lock);
931}
932
933static void ssl_lock(int mode, int n, const char *file, int line)
934{
935    if (mode & CRYPTO_LOCK) {
936        apr_thread_mutex_lock(ssl_locks[n]);
937    }
938    else if (mode & CRYPTO_UNLOCK) {
939        apr_thread_mutex_unlock(ssl_locks[n]);
940    }
941}
942
943static unsigned long ssl_id(void)
944{
945    /* FIXME: This is lame and not portable. -aaron */
946    return (unsigned long) apr_os_thread_current();
947}
948
949static apr_status_t cleanup_ssl(void *data)
950{
951    CRYPTO_set_locking_callback(NULL);
952    CRYPTO_set_id_callback(NULL);
953    CRYPTO_set_dynlock_create_callback(NULL);
954    CRYPTO_set_dynlock_lock_callback(NULL);
955    CRYPTO_set_dynlock_destroy_callback(NULL);
956
957    return APR_SUCCESS;
958}
959
960#endif
961
962#if !APR_VERSION_AT_LEAST(1,0,0)
963#define apr_atomic_cas32(mem, with, cmp) apr_atomic_cas(mem, with, cmp)
964#endif
965
966enum ssl_init_e
967{
968   INIT_UNINITIALIZED = 0,
969   INIT_BUSY = 1,
970   INIT_DONE = 2
971};
972
973static volatile apr_uint32_t have_init_ssl = INIT_UNINITIALIZED;
974
975static void init_ssl_libraries(void)
976{
977    apr_uint32_t val;
978
979    val = apr_atomic_cas32(&have_init_ssl, INIT_BUSY, INIT_UNINITIALIZED);
980
981    if (!val) {
982#if APR_HAS_THREADS
983        int i, numlocks;
984#endif
985
986#ifdef SSL_VERBOSE
987        /* Warn when compile-time and run-time version of OpenSSL differ in
988           major/minor version number. */
989        long libver = SSLeay();
990
991        if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) {
992            serf__log(SSL_VERBOSE, __FILE__,
993                      "Warning: OpenSSL library version mismatch, compile-time "
994                      "was %lx, runtime is %lx.\n",
995                      OPENSSL_VERSION_NUMBER, libver);
996        }
997#endif
998
999        CRYPTO_malloc_init();
1000        ERR_load_crypto_strings();
1001        SSL_load_error_strings();
1002        SSL_library_init();
1003        OpenSSL_add_all_algorithms();
1004
1005#if APR_HAS_THREADS
1006        numlocks = CRYPTO_num_locks();
1007        apr_pool_create(&ssl_pool, NULL);
1008        ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks);
1009        for (i = 0; i < numlocks; i++) {
1010            apr_status_t rv;
1011
1012            /* Intraprocess locks don't /need/ a filename... */
1013            rv = apr_thread_mutex_create(&ssl_locks[i],
1014                                         APR_THREAD_MUTEX_DEFAULT, ssl_pool);
1015            if (rv != APR_SUCCESS) {
1016                /* FIXME: error out here */
1017            }
1018        }
1019        CRYPTO_set_locking_callback(ssl_lock);
1020        CRYPTO_set_id_callback(ssl_id);
1021        CRYPTO_set_dynlock_create_callback(ssl_dyn_create);
1022        CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock);
1023        CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy);
1024
1025        apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl);
1026#endif
1027        apr_atomic_cas32(&have_init_ssl, INIT_DONE, INIT_BUSY);
1028    }
1029  else
1030    {
1031        /* Make sure we don't continue before the initialization in another
1032           thread has completed */
1033        while (val != INIT_DONE) {
1034            apr_sleep(APR_USEC_PER_SEC / 1000);
1035
1036            val = apr_atomic_cas32(&have_init_ssl,
1037                                   INIT_UNINITIALIZED,
1038                                   INIT_UNINITIALIZED);
1039        }
1040    }
1041}
1042
1043static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
1044{
1045    serf_ssl_context_t *ctx = SSL_get_app_data(ssl);
1046    apr_status_t status;
1047
1048    if (ctx->cached_cert) {
1049        *cert = ctx->cached_cert;
1050        *pkey = ctx->cached_cert_pw;
1051        return 1;
1052    }
1053
1054    while (ctx->cert_callback) {
1055        const char *cert_path;
1056        apr_file_t *cert_file;
1057        BIO *bio;
1058        PKCS12 *p12;
1059        int i;
1060        int retrying_success = 0;
1061
1062        if (ctx->cert_file_success) {
1063            status = APR_SUCCESS;
1064            cert_path = ctx->cert_file_success;
1065            ctx->cert_file_success = NULL;
1066            retrying_success = 1;
1067        } else {
1068            status = ctx->cert_callback(ctx->cert_userdata, &cert_path);
1069        }
1070
1071        if (status || !cert_path) {
1072            break;
1073        }
1074
1075        /* Load the x.509 cert file stored in PKCS12 */
1076        status = apr_file_open(&cert_file, cert_path, APR_READ, APR_OS_DEFAULT,
1077                               ctx->pool);
1078
1079        if (status) {
1080            continue;
1081        }
1082
1083        bio = BIO_new(&bio_file_method);
1084        bio->ptr = cert_file;
1085
1086        ctx->cert_path = cert_path;
1087        p12 = d2i_PKCS12_bio(bio, NULL);
1088        apr_file_close(cert_file);
1089
1090        i = PKCS12_parse(p12, NULL, pkey, cert, NULL);
1091
1092        if (i == 1) {
1093            PKCS12_free(p12);
1094            ctx->cached_cert = *cert;
1095            ctx->cached_cert_pw = *pkey;
1096            if (!retrying_success && ctx->cert_cache_pool) {
1097                const char *c;
1098
1099                c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path);
1100
1101                apr_pool_userdata_setn(c, "serf:ssl:cert",
1102                                       apr_pool_cleanup_null,
1103                                       ctx->cert_cache_pool);
1104            }
1105            return 1;
1106        }
1107        else {
1108            int err = ERR_get_error();
1109            ERR_clear_error();
1110            if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
1111                ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
1112                if (ctx->cert_pw_callback) {
1113                    const char *password;
1114
1115                    if (ctx->cert_pw_success) {
1116                        status = APR_SUCCESS;
1117                        password = ctx->cert_pw_success;
1118                        ctx->cert_pw_success = NULL;
1119                    } else {
1120                        status = ctx->cert_pw_callback(ctx->cert_pw_userdata,
1121                                                       ctx->cert_path,
1122                                                       &password);
1123                    }
1124
1125                    if (!status && password) {
1126                        i = PKCS12_parse(p12, password, pkey, cert, NULL);
1127                        if (i == 1) {
1128                            PKCS12_free(p12);
1129                            ctx->cached_cert = *cert;
1130                            ctx->cached_cert_pw = *pkey;
1131                            if (!retrying_success && ctx->cert_cache_pool) {
1132                                const char *c;
1133
1134                                c = apr_pstrdup(ctx->cert_cache_pool,
1135                                                ctx->cert_path);
1136
1137                                apr_pool_userdata_setn(c, "serf:ssl:cert",
1138                                                       apr_pool_cleanup_null,
1139                                                       ctx->cert_cache_pool);
1140                            }
1141                            if (!retrying_success && ctx->cert_pw_cache_pool) {
1142                                const char *c;
1143
1144                                c = apr_pstrdup(ctx->cert_pw_cache_pool,
1145                                                password);
1146
1147                                apr_pool_userdata_setn(c, "serf:ssl:certpw",
1148                                                       apr_pool_cleanup_null,
1149                                                       ctx->cert_pw_cache_pool);
1150                            }
1151                            return 1;
1152                        }
1153                    }
1154                }
1155                PKCS12_free(p12);
1156                return 0;
1157            }
1158            else {
1159                printf("OpenSSL cert error: %d %d %d\n", ERR_GET_LIB(err),
1160                       ERR_GET_FUNC(err),
1161                       ERR_GET_REASON(err));
1162                PKCS12_free(p12);
1163            }
1164        }
1165    }
1166
1167    return 0;
1168}
1169
1170
1171void serf_ssl_client_cert_provider_set(
1172    serf_ssl_context_t *context,
1173    serf_ssl_need_client_cert_t callback,
1174    void *data,
1175    void *cache_pool)
1176{
1177    context->cert_callback = callback;
1178    context->cert_userdata = data;
1179    context->cert_cache_pool = cache_pool;
1180    if (context->cert_cache_pool) {
1181        apr_pool_userdata_get((void**)&context->cert_file_success,
1182                              "serf:ssl:cert", cache_pool);
1183    }
1184}
1185
1186
1187void serf_ssl_client_cert_password_set(
1188    serf_ssl_context_t *context,
1189    serf_ssl_need_cert_password_t callback,
1190    void *data,
1191    void *cache_pool)
1192{
1193    context->cert_pw_callback = callback;
1194    context->cert_pw_userdata = data;
1195    context->cert_pw_cache_pool = cache_pool;
1196    if (context->cert_pw_cache_pool) {
1197        apr_pool_userdata_get((void**)&context->cert_pw_success,
1198                              "serf:ssl:certpw", cache_pool);
1199    }
1200}
1201
1202
1203void serf_ssl_server_cert_callback_set(
1204    serf_ssl_context_t *context,
1205    serf_ssl_need_server_cert_t callback,
1206    void *data)
1207{
1208    context->server_cert_callback = callback;
1209    context->server_cert_userdata = data;
1210}
1211
1212void serf_ssl_server_cert_chain_callback_set(
1213    serf_ssl_context_t *context,
1214    serf_ssl_need_server_cert_t cert_callback,
1215    serf_ssl_server_cert_chain_cb_t cert_chain_callback,
1216    void *data)
1217{
1218    context->server_cert_callback = cert_callback;
1219    context->server_cert_chain_callback = cert_chain_callback;
1220    context->server_cert_userdata = data;
1221}
1222
1223static serf_ssl_context_t *ssl_init_context(serf_bucket_alloc_t *allocator)
1224{
1225    serf_ssl_context_t *ssl_ctx;
1226
1227    init_ssl_libraries();
1228
1229    ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx));
1230
1231    ssl_ctx->refcount = 0;
1232    ssl_ctx->pool = serf_bucket_allocator_get_pool(allocator);
1233    ssl_ctx->allocator = allocator;
1234
1235    ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
1236
1237    SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert);
1238    ssl_ctx->cached_cert = 0;
1239    ssl_ctx->cached_cert_pw = 0;
1240    ssl_ctx->pending_err = APR_SUCCESS;
1241    ssl_ctx->fatal_err = APR_SUCCESS;
1242
1243    ssl_ctx->cert_callback = NULL;
1244    ssl_ctx->cert_pw_callback = NULL;
1245    ssl_ctx->server_cert_callback = NULL;
1246    ssl_ctx->server_cert_chain_callback = NULL;
1247
1248    SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER,
1249                       validate_server_certificate);
1250    SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL);
1251    /* Disable SSL compression by default. */
1252    disable_compression(ssl_ctx);
1253
1254    ssl_ctx->ssl = SSL_new(ssl_ctx->ctx);
1255    ssl_ctx->bio = BIO_new(&bio_bucket_method);
1256    ssl_ctx->bio->ptr = ssl_ctx;
1257
1258    SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio);
1259
1260    SSL_set_connect_state(ssl_ctx->ssl);
1261
1262    SSL_set_app_data(ssl_ctx->ssl, ssl_ctx);
1263
1264#if SSL_VERBOSE
1265    SSL_CTX_set_info_callback(ssl_ctx->ctx, apps_ssl_info_callback);
1266#endif
1267
1268    ssl_ctx->encrypt.stream = NULL;
1269    ssl_ctx->encrypt.stream_next = NULL;
1270    ssl_ctx->encrypt.pending = serf_bucket_aggregate_create(allocator);
1271    ssl_ctx->encrypt.status = APR_SUCCESS;
1272    serf_databuf_init(&ssl_ctx->encrypt.databuf);
1273    ssl_ctx->encrypt.databuf.read = ssl_encrypt;
1274    ssl_ctx->encrypt.databuf.read_baton = ssl_ctx;
1275
1276    ssl_ctx->decrypt.stream = NULL;
1277    ssl_ctx->decrypt.pending = serf_bucket_aggregate_create(allocator);
1278    ssl_ctx->decrypt.status = APR_SUCCESS;
1279    serf_databuf_init(&ssl_ctx->decrypt.databuf);
1280    ssl_ctx->decrypt.databuf.read = ssl_decrypt;
1281    ssl_ctx->decrypt.databuf.read_baton = ssl_ctx;
1282
1283    return ssl_ctx;
1284}
1285
1286static apr_status_t ssl_free_context(
1287    serf_ssl_context_t *ssl_ctx)
1288{
1289    /* If never had the pending buckets, don't try to free them. */
1290    if (ssl_ctx->decrypt.pending != NULL) {
1291        serf_bucket_destroy(ssl_ctx->decrypt.pending);
1292    }
1293    if (ssl_ctx->encrypt.pending != NULL) {
1294        serf_bucket_destroy(ssl_ctx->encrypt.pending);
1295    }
1296
1297    /* SSL_free implicitly frees the underlying BIO. */
1298    SSL_free(ssl_ctx->ssl);
1299    SSL_CTX_free(ssl_ctx->ctx);
1300
1301    serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx);
1302
1303    return APR_SUCCESS;
1304}
1305
1306static serf_bucket_t * serf_bucket_ssl_create(
1307    serf_ssl_context_t *ssl_ctx,
1308    serf_bucket_alloc_t *allocator,
1309    const serf_bucket_type_t *type)
1310{
1311    ssl_context_t *ctx;
1312
1313    ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
1314    if (!ssl_ctx) {
1315        ctx->ssl_ctx = ssl_init_context(allocator);
1316    }
1317    else {
1318        ctx->ssl_ctx = ssl_ctx;
1319    }
1320    ctx->ssl_ctx->refcount++;
1321
1322    return serf_bucket_create(type, allocator, ctx);
1323}
1324
1325apr_status_t serf_ssl_set_hostname(serf_ssl_context_t *context,
1326                                   const char * hostname)
1327{
1328#ifdef SSL_set_tlsext_host_name
1329    if (SSL_set_tlsext_host_name(context->ssl, hostname) != 1) {
1330        ERR_clear_error();
1331    }
1332#endif
1333    return APR_SUCCESS;
1334}
1335
1336apr_status_t serf_ssl_use_default_certificates(serf_ssl_context_t *ssl_ctx)
1337{
1338    X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
1339
1340    int result = X509_STORE_set_default_paths(store);
1341
1342    return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED;
1343}
1344
1345apr_status_t serf_ssl_load_cert_file(
1346    serf_ssl_certificate_t **cert,
1347    const char *file_path,
1348    apr_pool_t *pool)
1349{
1350    FILE *fp = fopen(file_path, "r");
1351
1352    if (fp) {
1353        X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
1354        fclose(fp);
1355
1356        if (ssl_cert) {
1357            *cert = apr_palloc(pool, sizeof(serf_ssl_certificate_t));
1358            (*cert)->ssl_cert = ssl_cert;
1359
1360            return APR_SUCCESS;
1361        }
1362    }
1363
1364    return SERF_ERROR_SSL_CERT_FAILED;
1365}
1366
1367
1368apr_status_t serf_ssl_trust_cert(
1369    serf_ssl_context_t *ssl_ctx,
1370    serf_ssl_certificate_t *cert)
1371{
1372    X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
1373
1374    int result = X509_STORE_add_cert(store, cert->ssl_cert);
1375
1376    return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED;
1377}
1378
1379
1380serf_bucket_t *serf_bucket_ssl_decrypt_create(
1381    serf_bucket_t *stream,
1382    serf_ssl_context_t *ssl_ctx,
1383    serf_bucket_alloc_t *allocator)
1384{
1385    serf_bucket_t *bkt;
1386    ssl_context_t *ctx;
1387
1388    bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1389                                 &serf_bucket_type_ssl_decrypt);
1390
1391    ctx = bkt->data;
1392
1393    ctx->databuf = &ctx->ssl_ctx->decrypt.databuf;
1394    if (ctx->ssl_ctx->decrypt.stream != NULL) {
1395        return NULL;
1396    }
1397    ctx->ssl_ctx->decrypt.stream = stream;
1398    ctx->our_stream = &ctx->ssl_ctx->decrypt.stream;
1399
1400    return bkt;
1401}
1402
1403
1404serf_ssl_context_t *serf_bucket_ssl_decrypt_context_get(
1405     serf_bucket_t *bucket)
1406{
1407    ssl_context_t *ctx = bucket->data;
1408    return ctx->ssl_ctx;
1409}
1410
1411
1412serf_bucket_t *serf_bucket_ssl_encrypt_create(
1413    serf_bucket_t *stream,
1414    serf_ssl_context_t *ssl_ctx,
1415    serf_bucket_alloc_t *allocator)
1416{
1417    serf_bucket_t *bkt;
1418    ssl_context_t *ctx;
1419
1420    bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1421                                 &serf_bucket_type_ssl_encrypt);
1422
1423    ctx = bkt->data;
1424
1425    ctx->databuf = &ctx->ssl_ctx->encrypt.databuf;
1426    ctx->our_stream = &ctx->ssl_ctx->encrypt.stream;
1427    if (ctx->ssl_ctx->encrypt.stream == NULL) {
1428        serf_bucket_t *tmp = serf_bucket_aggregate_create(stream->allocator);
1429        serf_bucket_aggregate_append(tmp, stream);
1430        ctx->ssl_ctx->encrypt.stream = tmp;
1431    }
1432    else {
1433        bucket_list_t *new_list;
1434
1435        new_list = serf_bucket_mem_alloc(ctx->ssl_ctx->allocator,
1436                                         sizeof(*new_list));
1437        new_list->bucket = stream;
1438        new_list->next = NULL;
1439        if (ctx->ssl_ctx->encrypt.stream_next == NULL) {
1440            ctx->ssl_ctx->encrypt.stream_next = new_list;
1441        }
1442        else {
1443            bucket_list_t *scan = ctx->ssl_ctx->encrypt.stream_next;
1444
1445            while (scan->next != NULL)
1446                scan = scan->next;
1447            scan->next = new_list;
1448        }
1449    }
1450
1451    return bkt;
1452}
1453
1454
1455serf_ssl_context_t *serf_bucket_ssl_encrypt_context_get(
1456     serf_bucket_t *bucket)
1457{
1458    ssl_context_t *ctx = bucket->data;
1459    return ctx->ssl_ctx;
1460}
1461
1462/* Functions to read a serf_ssl_certificate structure. */
1463
1464/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
1465static apr_hash_t *
1466convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
1467{
1468    char buf[1024];
1469    int ret;
1470
1471    apr_hash_t *tgt = apr_hash_make(pool);
1472
1473    ret = X509_NAME_get_text_by_NID(org,
1474                                    NID_commonName,
1475                                    buf, 1024);
1476    if (ret != -1)
1477        apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1478    ret = X509_NAME_get_text_by_NID(org,
1479                                    NID_pkcs9_emailAddress,
1480                                    buf, 1024);
1481    if (ret != -1)
1482        apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1483    ret = X509_NAME_get_text_by_NID(org,
1484                                    NID_organizationalUnitName,
1485                                    buf, 1024);
1486    if (ret != -1)
1487        apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1488    ret = X509_NAME_get_text_by_NID(org,
1489                                    NID_organizationName,
1490                                    buf, 1024);
1491    if (ret != -1)
1492        apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1493    ret = X509_NAME_get_text_by_NID(org,
1494                                    NID_localityName,
1495                                    buf, 1024);
1496    if (ret != -1)
1497        apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1498    ret = X509_NAME_get_text_by_NID(org,
1499                                    NID_stateOrProvinceName,
1500                                    buf, 1024);
1501    if (ret != -1)
1502        apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1503    ret = X509_NAME_get_text_by_NID(org,
1504                                    NID_countryName,
1505                                    buf, 1024);
1506    if (ret != -1)
1507        apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1508
1509    return tgt;
1510}
1511
1512
1513int serf_ssl_cert_depth(const serf_ssl_certificate_t *cert)
1514{
1515    return cert->depth;
1516}
1517
1518
1519apr_hash_t *serf_ssl_cert_issuer(
1520    const serf_ssl_certificate_t *cert,
1521    apr_pool_t *pool)
1522{
1523    X509_NAME *issuer = X509_get_issuer_name(cert->ssl_cert);
1524
1525    if (!issuer)
1526        return NULL;
1527
1528    return convert_X509_NAME_to_table(issuer, pool);
1529}
1530
1531
1532apr_hash_t *serf_ssl_cert_subject(
1533    const serf_ssl_certificate_t *cert,
1534    apr_pool_t *pool)
1535{
1536    X509_NAME *subject = X509_get_subject_name(cert->ssl_cert);
1537
1538    if (!subject)
1539        return NULL;
1540
1541    return convert_X509_NAME_to_table(subject, pool);
1542}
1543
1544
1545apr_hash_t *serf_ssl_cert_certificate(
1546    const serf_ssl_certificate_t *cert,
1547    apr_pool_t *pool)
1548{
1549    apr_hash_t *tgt = apr_hash_make(pool);
1550    unsigned int md_size, i;
1551    unsigned char md[EVP_MAX_MD_SIZE];
1552    BIO *bio;
1553    STACK_OF(GENERAL_NAME) *names;
1554
1555    /* sha1 fingerprint */
1556    if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
1557        const char hex[] = "0123456789ABCDEF";
1558        char fingerprint[EVP_MAX_MD_SIZE * 3];
1559
1560        for (i=0; i<md_size; i++) {
1561            fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4];
1562            fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)];
1563            fingerprint[(3*i)+2] = ':';
1564        }
1565        if (md_size > 0)
1566            fingerprint[(3*(md_size-1))+2] = '\0';
1567        else
1568            fingerprint[0] = '\0';
1569
1570        apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING,
1571                     apr_pstrdup(pool, fingerprint));
1572    }
1573
1574    /* set expiry dates */
1575    bio = BIO_new(BIO_s_mem());
1576    if (bio) {
1577        ASN1_TIME *notBefore, *notAfter;
1578        char buf[256];
1579
1580        memset (buf, 0, sizeof (buf));
1581        notBefore = X509_get_notBefore(cert->ssl_cert);
1582        if (ASN1_TIME_print(bio, notBefore)) {
1583            BIO_read(bio, buf, 255);
1584            apr_hash_set(tgt, "notBefore", APR_HASH_KEY_STRING,
1585                         apr_pstrdup(pool, buf));
1586        }
1587        memset (buf, 0, sizeof (buf));
1588        notAfter = X509_get_notAfter(cert->ssl_cert);
1589        if (ASN1_TIME_print(bio, notAfter)) {
1590            BIO_read(bio, buf, 255);
1591            apr_hash_set(tgt, "notAfter", APR_HASH_KEY_STRING,
1592                         apr_pstrdup(pool, buf));
1593        }
1594    }
1595    BIO_free(bio);
1596
1597    /* Get subjectAltNames */
1598    names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL);
1599    if (names) {
1600        int names_count = sk_GENERAL_NAME_num(names);
1601
1602        apr_array_header_t *san_arr = apr_array_make(pool, names_count,
1603                                                     sizeof(char*));
1604        apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
1605        for (i = 0; i < names_count; i++) {
1606            char *p = NULL;
1607            GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i);
1608
1609            switch (nm->type) {
1610            case GEN_DNS:
1611                p = apr_pstrmemdup(pool, (const char *)nm->d.ia5->data,
1612                                   nm->d.ia5->length);
1613                break;
1614            default:
1615                /* Don't know what to do - skip. */
1616                break;
1617            }
1618            if (p) {
1619                APR_ARRAY_PUSH(san_arr, char*) = p;
1620            }
1621        }
1622        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
1623    }
1624
1625    return tgt;
1626}
1627
1628
1629const char *serf_ssl_cert_export(
1630    const serf_ssl_certificate_t *cert,
1631    apr_pool_t *pool)
1632{
1633    char *binary_cert;
1634    char *encoded_cert;
1635    int len;
1636    unsigned char *unused;
1637
1638    /* find the length of the DER encoding. */
1639    len = i2d_X509(cert->ssl_cert, NULL);
1640    if (len < 0) {
1641        return NULL;
1642    }
1643
1644    binary_cert = apr_palloc(pool, len);
1645    unused = (unsigned char *)binary_cert;
1646    len = i2d_X509(cert->ssl_cert, &unused);  /* unused is incremented  */
1647    if (len < 0) {
1648        return NULL;
1649    }
1650
1651    encoded_cert = apr_palloc(pool, apr_base64_encode_len(len));
1652    apr_base64_encode(encoded_cert, binary_cert, len);
1653
1654    return encoded_cert;
1655}
1656
1657/* Disables compression for all SSL sessions. */
1658static void disable_compression(serf_ssl_context_t *ssl_ctx)
1659{
1660#ifdef SSL_OP_NO_COMPRESSION
1661    SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_COMPRESSION);
1662#endif
1663}
1664
1665apr_status_t serf_ssl_use_compression(serf_ssl_context_t *ssl_ctx, int enabled)
1666{
1667    if (enabled) {
1668#ifdef SSL_OP_NO_COMPRESSION
1669        SSL_clear_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION);
1670        return APR_SUCCESS;
1671#endif
1672    } else {
1673#ifdef SSL_OP_NO_COMPRESSION
1674        SSL_set_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION);
1675        return APR_SUCCESS;
1676#endif
1677    }
1678
1679    return APR_EGENERAL;
1680}
1681
1682static void serf_ssl_destroy_and_data(serf_bucket_t *bucket)
1683{
1684    ssl_context_t *ctx = bucket->data;
1685
1686    if (!--ctx->ssl_ctx->refcount) {
1687        ssl_free_context(ctx->ssl_ctx);
1688    }
1689
1690    serf_default_destroy_and_data(bucket);
1691}
1692
1693static void serf_ssl_decrypt_destroy_and_data(serf_bucket_t *bucket)
1694{
1695    ssl_context_t *ctx = bucket->data;
1696
1697    serf_bucket_destroy(*ctx->our_stream);
1698
1699    serf_ssl_destroy_and_data(bucket);
1700}
1701
1702static void serf_ssl_encrypt_destroy_and_data(serf_bucket_t *bucket)
1703{
1704    ssl_context_t *ctx = bucket->data;
1705    serf_ssl_context_t *ssl_ctx = ctx->ssl_ctx;
1706
1707    if (ssl_ctx->encrypt.stream == *ctx->our_stream) {
1708        serf_bucket_destroy(*ctx->our_stream);
1709        serf_bucket_destroy(ssl_ctx->encrypt.pending);
1710
1711        /* Reset our encrypted status and databuf. */
1712        ssl_ctx->encrypt.status = APR_SUCCESS;
1713        ssl_ctx->encrypt.databuf.status = APR_SUCCESS;
1714
1715        /* Advance to the next stream - if we have one. */
1716        if (ssl_ctx->encrypt.stream_next == NULL) {
1717            ssl_ctx->encrypt.stream = NULL;
1718            ssl_ctx->encrypt.pending = NULL;
1719        }
1720        else {
1721            bucket_list_t *cur;
1722
1723            cur = ssl_ctx->encrypt.stream_next;
1724            ssl_ctx->encrypt.stream = cur->bucket;
1725            ssl_ctx->encrypt.pending =
1726                serf_bucket_aggregate_create(cur->bucket->allocator);
1727            ssl_ctx->encrypt.stream_next = cur->next;
1728            serf_bucket_mem_free(ssl_ctx->allocator, cur);
1729        }
1730    }
1731    else {
1732        /* Ah, darn.  We haven't sent this one along yet. */
1733        return;
1734    }
1735    serf_ssl_destroy_and_data(bucket);
1736}
1737
1738static apr_status_t serf_ssl_read(serf_bucket_t *bucket,
1739                                  apr_size_t requested,
1740                                  const char **data, apr_size_t *len)
1741{
1742    ssl_context_t *ctx = bucket->data;
1743
1744    return serf_databuf_read(ctx->databuf, requested, data, len);
1745}
1746
1747static apr_status_t serf_ssl_readline(serf_bucket_t *bucket,
1748                                      int acceptable, int *found,
1749                                      const char **data,
1750                                      apr_size_t *len)
1751{
1752    ssl_context_t *ctx = bucket->data;
1753
1754    return serf_databuf_readline(ctx->databuf, acceptable, found, data, len);
1755}
1756
1757static apr_status_t serf_ssl_peek(serf_bucket_t *bucket,
1758                                  const char **data,
1759                                  apr_size_t *len)
1760{
1761    ssl_context_t *ctx = bucket->data;
1762
1763    return serf_databuf_peek(ctx->databuf, data, len);
1764}
1765
1766
1767const serf_bucket_type_t serf_bucket_type_ssl_encrypt = {
1768    "SSLENCRYPT",
1769    serf_ssl_read,
1770    serf_ssl_readline,
1771    serf_default_read_iovec,
1772    serf_default_read_for_sendfile,
1773    serf_default_read_bucket,
1774    serf_ssl_peek,
1775    serf_ssl_encrypt_destroy_and_data,
1776};
1777
1778const serf_bucket_type_t serf_bucket_type_ssl_decrypt = {
1779    "SSLDECRYPT",
1780    serf_ssl_read,
1781    serf_ssl_readline,
1782    serf_default_read_iovec,
1783    serf_default_read_for_sendfile,
1784    serf_default_read_bucket,
1785    serf_ssl_peek,
1786    serf_ssl_decrypt_destroy_and_data,
1787};
1788