]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/serf/buckets/ssl_buckets.c
Merge hostapd / wpa_supplicant 2.0.
[FreeBSD/FreeBSD.git] / contrib / serf / buckets / ssl_buckets.c
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
117 typedef struct bucket_list {
118     serf_bucket_t *bucket;
119     struct bucket_list *next;
120 } bucket_list_t;
121
122 typedef 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
141 struct 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
188 typedef 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
199 struct serf_ssl_certificate_t {
200     X509 *ssl_cert;
201     int depth;
202 };
203
204 static 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. */
208 static void
209 apps_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. */
246 static 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__, "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);
264     }
265
266     status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len);
267
268     ctx->decrypt.status = status;
269
270     serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read received %d bytes (%d)\n",
271               len, status);
272
273     if (!SERF_BUCKET_READ_ERROR(status)) {
274         /* Oh suck. */
275         if (len) {
276             memcpy(in, data, len);
277             return len;
278         }
279         if (APR_STATUS_IS_EOF(status)) {
280             BIO_set_retry_read(bio);
281             return -1;
282         }
283     }
284
285     return -1;
286 }
287
288 /* Returns the amount written. */
289 static int bio_bucket_write(BIO *bio, const char *in, int inl)
290 {
291     serf_ssl_context_t *ctx = bio->ptr;
292     serf_bucket_t *tmp;
293
294     serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write called for %d bytes\n",
295               inl);
296
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);
305     }
306
307     tmp = serf_bucket_simple_copy_create(in, inl,
308                                          ctx->encrypt.pending->allocator);
309
310     serf_bucket_aggregate_append(ctx->encrypt.pending, tmp);
311
312     return inl;
313 }
314
315 /* Returns the amount read. */
316 static int bio_file_read(BIO *bio, char *in, int inlen)
317 {
318     apr_file_t *file = bio->ptr;
319     apr_status_t status;
320     apr_size_t len;
321
322     BIO_clear_retry_flags(bio);
323
324     len = inlen;
325     status = apr_file_read(file, in, &len);
326
327     if (!SERF_BUCKET_READ_ERROR(status)) {
328         /* Oh suck. */
329         if (APR_STATUS_IS_EOF(status)) {
330             BIO_set_retry_read(bio);
331             return -1;
332         } else {
333             return len;
334         }
335     }
336
337     return -1;
338 }
339
340 /* Returns the amount written. */
341 static int bio_file_write(BIO *bio, const char *in, int inl)
342 {
343     apr_file_t *file = bio->ptr;
344     apr_size_t nbytes;
345
346     BIO_clear_retry_flags(bio);
347
348     nbytes = inl;
349     apr_file_write(file, in, &nbytes);
350
351     return nbytes;
352 }
353
354 static int bio_file_gets(BIO *bio, char *in, int inlen)
355 {
356     return bio_file_read(bio, in, inlen);
357 }
358
359 static int bio_bucket_create(BIO *bio)
360 {
361     bio->shutdown = 1;
362     bio->init = 1;
363     bio->num = -1;
364     bio->ptr = NULL;
365
366     return 1;
367 }
368
369 static int bio_bucket_destroy(BIO *bio)
370 {
371     /* Did we already free this? */
372     if (bio == NULL) {
373         return 0;
374     }
375
376     return 1;
377 }
378
379 static long bio_bucket_ctrl(BIO *bio, int cmd, long num, void *ptr)
380 {
381     long ret = 1;
382
383     switch (cmd) {
384     default:
385         /* abort(); */
386         break;
387     case BIO_CTRL_FLUSH:
388         /* At this point we can't force a flush. */
389         break;
390     case BIO_CTRL_PUSH:
391     case BIO_CTRL_POP:
392         ret = 0;
393         break;
394     }
395     return ret;
396 }
397
398 static BIO_METHOD bio_bucket_method = {
399     BIO_TYPE_MEM,
400     "Serf SSL encryption and decryption buckets",
401     bio_bucket_write,
402     bio_bucket_read,
403     NULL,                        /* Is this called? */
404     NULL,                        /* Is this called? */
405     bio_bucket_ctrl,
406     bio_bucket_create,
407     bio_bucket_destroy,
408 #ifdef OPENSSL_VERSION_NUMBER
409     NULL /* sslc does not have the callback_ctrl field */
410 #endif
411 };
412
413 static BIO_METHOD bio_file_method = {
414     BIO_TYPE_FILE,
415     "Wrapper around APR file structures",
416     bio_file_write,
417     bio_file_read,
418     NULL,                        /* Is this called? */
419     bio_file_gets,               /* Is this called? */
420     bio_bucket_ctrl,
421     bio_bucket_create,
422     bio_bucket_destroy,
423 #ifdef OPENSSL_VERSION_NUMBER
424     NULL /* sslc does not have the callback_ctrl field */
425 #endif
426 };
427
428 static int
429 validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
430 {
431     SSL *ssl;
432     serf_ssl_context_t *ctx;
433     X509 *server_cert;
434     int err, depth;
435     int failures = 0;
436
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);
440
441     server_cert = X509_STORE_CTX_get_current_cert(store_ctx);
442     depth = X509_STORE_CTX_get_error_depth(store_ctx);
443
444     /* If the certification was found invalid, get the error and convert it to
445        something our caller will understand. */
446     if (! cert_valid) {
447         err = X509_STORE_CTX_get_error(store_ctx);
448
449         switch(err) {
450             case X509_V_ERR_CERT_NOT_YET_VALID: 
451                     failures |= SERF_SSL_CERT_NOTYETVALID;
452                     break;
453             case X509_V_ERR_CERT_HAS_EXPIRED:
454                     failures |= SERF_SSL_CERT_EXPIRED;
455                     break;
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;
459                     break;
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;
465                     break;
466             case X509_V_ERR_CERT_REVOKED:
467                     failures |= SERF_SSL_CERT_REVOKED;
468                     break;
469             default:
470                     failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
471                     break;
472         }
473     }
474
475     /* Check certificate expiry dates. */
476     if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
477         failures |= SERF_SSL_CERT_NOTYETVALID;
478     }
479     else if (X509_cmp_current_time(X509_get_notAfter(server_cert)) <= 0) {
480         failures |= SERF_SSL_CERT_EXPIRED;
481     }
482
483     if (ctx->server_cert_callback &&
484         (depth == 0 || failures)) {
485         apr_status_t status;
486         serf_ssl_certificate_t *cert;
487         apr_pool_t *subpool;
488
489         apr_pool_create(&subpool, ctx->pool);
490
491         cert = apr_palloc(subpool, sizeof(serf_ssl_certificate_t));
492         cert->ssl_cert = server_cert;
493         cert->depth = depth;
494
495         /* Callback for further verification. */
496         status = ctx->server_cert_callback(ctx->server_cert_userdata,
497                                            failures, cert);
498         if (status == APR_SUCCESS)
499             cert_valid = 1;
500         else {
501             /* Even if openssl found the certificate valid, the application
502                told us to reject it. */
503             cert_valid = 0;
504             /* Pass the error back to the caller through the context-run. */
505             ctx->pending_err = status;
506         }
507         apr_pool_destroy(subpool);
508     }
509
510     if (ctx->server_cert_chain_callback
511         && (depth == 0 || failures)) {
512         apr_status_t status;
513         STACK_OF(X509) *chain;
514         const serf_ssl_certificate_t **certs;
515         int certs_len;
516         apr_pool_t *subpool;
517
518         apr_pool_create(&subpool, ctx->pool);
519
520         /* Borrow the chain to pass to the callback. */
521         chain = X509_STORE_CTX_get_chain(store_ctx);
522
523         /* If the chain can't be retrieved, just pass the current
524            certificate. */
525         /* ### can this actually happen with _get_chain() ?  */
526         if (!chain) {
527             serf_ssl_certificate_t *cert = apr_palloc(subpool, sizeof(*cert));
528
529             cert->ssl_cert = server_cert;
530             cert->depth = depth;
531
532             /* Room for the server_cert and a trailing NULL.  */
533             certs = apr_palloc(subpool, sizeof(*certs) * 2);
534             certs[0] = cert;
535
536             certs_len = 1;
537         } else {
538             int i;
539
540             certs_len = sk_X509_num(chain);
541
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;
546
547                 cert = apr_palloc(subpool, sizeof(*cert));
548                 cert->ssl_cert = sk_X509_value(chain, i);
549                 cert->depth = i;
550
551                 certs[i] = cert;
552             }
553         }
554         certs[certs_len] = NULL;
555
556         /* Callback for further verification. */
557         status = ctx->server_cert_chain_callback(ctx->server_cert_userdata,
558                                                  failures, depth,
559                                                  certs, certs_len);
560         if (status == APR_SUCCESS) {
561             cert_valid = 1;
562         } else {
563             /* Even if openssl found the certificate valid, the application
564                told us to reject it. */
565             cert_valid = 0;
566             /* Pass the error back to the caller through the context-run. */
567             ctx->pending_err = status;
568         }
569
570         apr_pool_destroy(subpool);
571     }
572
573     return cert_valid;
574 }
575
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)
579 {
580     serf_ssl_context_t *ctx = baton;
581     apr_size_t priv_len;
582     apr_status_t status;
583     const char *data;
584     int ssl_len;
585
586     if (ctx->fatal_err)
587         return ctx->fatal_err;
588
589     serf__log(SSL_VERBOSE, __FILE__, "ssl_decrypt: begin %d\n", bufsize);
590
591     /* Is there some data waiting to be read? */
592     ssl_len = SSL_read(ctx->ssl, buf, bufsize);
593     if (ssl_len > 0) {
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));
598         *len = ssl_len;
599         return APR_SUCCESS;
600     }
601
602     status = serf_bucket_read(ctx->decrypt.stream, bufsize, &data, &priv_len);
603
604     if (!SERF_BUCKET_READ_ERROR(status) && priv_len) {
605         serf_bucket_t *tmp;
606
607         serf__log(SSL_VERBOSE, __FILE__,
608                   "ssl_decrypt: read %d bytes (%d); status: %d\n",
609                   priv_len, bufsize, status);
610
611         tmp = serf_bucket_simple_copy_create(data, priv_len,
612                                              ctx->decrypt.pending->allocator);
613
614         serf_bucket_aggregate_append(ctx->decrypt.pending, tmp);
615
616         ssl_len = SSL_read(ctx->ssl, buf, bufsize);
617         if (ssl_len < 0) {
618             int ssl_err;
619
620             ssl_err = SSL_get_error(ctx->ssl, ssl_len);
621             switch (ssl_err) {
622             case SSL_ERROR_SYSCALL:
623                 *len = 0;
624                 status = ctx->decrypt.status;
625                 break;
626             case SSL_ERROR_WANT_READ:
627                 *len = 0;
628                 status = APR_EAGAIN;
629                 break;
630             case SSL_ERROR_SSL:
631                 *len = 0;
632                 if (ctx->pending_err) {
633                     status = ctx->pending_err;
634                     ctx->pending_err = 0;
635                 } else {
636                     ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
637                 }
638                 break;
639             default:
640                 *len = 0;
641                 ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
642                 break;
643             }
644         } else if (ssl_len == 0) {
645             /* The server shut down the connection. */
646             int ssl_err, shutdown;
647             *len = 0;
648
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);
653
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
658                 it here anyway.
659                 We can optimize this later. */
660                 serf__log(SSL_VERBOSE, __FILE__, 
661                           "ssl_decrypt: SSL read error: server"
662                           " shut down connection!\n");
663                 status = APR_EOF;
664             } else {
665                 /* A fatal error occurred. */
666                 ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
667             }
668         } else {
669             *len = ssl_len;
670             serf__log(SSL_MSG_VERBOSE, __FILE__, 
671                       "---\n%.*s\n-(%d)-\n", *len, buf, *len);
672         }
673     }
674     else {
675         *len = 0;
676     }
677     serf__log(SSL_VERBOSE, __FILE__, 
678               "ssl_decrypt: %d %d %d\n", status, *len,
679               BIO_get_retry_flags(ctx->bio));
680
681     return status;
682 }
683
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)
687 {
688     const char *data;
689     apr_size_t interim_bufsize;
690     serf_ssl_context_t *ctx = baton;
691     apr_status_t status;
692
693     if (ctx->fatal_err)
694         return ctx->fatal_err;
695
696     serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: begin %d\n", bufsize);
697
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)) {
701         return status;
702     }
703
704     /* Aha, we read something.  Return that now. */
705     if (*len) {
706         memcpy(buf, data, *len);
707         if (APR_STATUS_IS_EOF(status)) {
708             status = APR_SUCCESS;
709         }
710
711         serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: %d %d %d (quick read)\n",
712                   status, *len, BIO_get_retry_flags(ctx->bio));
713
714         return status;
715     }
716
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));
721
722         return APR_EAGAIN;
723     }
724
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));
731
732         ctx->encrypt.status = APR_SUCCESS;
733         ctx->encrypt.exhausted_reset = 0;
734     }
735
736     /* Oh well, read from our stream now. */
737     interim_bufsize = bufsize;
738     do {
739         apr_size_t interim_len;
740
741         if (!ctx->encrypt.status) {
742             struct iovec vecs[64];
743             int vecs_read;
744
745             status = serf_bucket_read_iovec(ctx->encrypt.stream,
746                                             interim_bufsize, 64, vecs,
747                                             &vecs_read);
748
749             if (!SERF_BUCKET_READ_ERROR(status) && vecs_read) {
750                 char *vecs_data;
751                 int i, cur, vecs_data_len;
752                 int ssl_len;
753
754                 /* Combine the buffers of the iovec into one buffer, as
755                    that is with SSL_write requires. */
756                 vecs_data_len = 0;
757                 for (i = 0; i < vecs_read; i++) {
758                     vecs_data_len += vecs[i].iov_len;
759                 }
760
761                 vecs_data = serf_bucket_mem_alloc(ctx->allocator,
762                                                   vecs_data_len);
763
764                 cur = 0;
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;
768                 }
769
770                 interim_bufsize -= vecs_data_len;
771                 interim_len = vecs_data_len;
772
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);
778
779                 /* Stash our status away. */
780                 ctx->encrypt.status = status;
781
782                 ssl_len = SSL_write(ctx->ssl, vecs_data, interim_len);
783
784                 serf__log(SSL_VERBOSE, __FILE__, 
785                           "ssl_encrypt: SSL write: %d\n", ssl_len);
786
787                 /* We're done. */
788                 serf_bucket_mem_free(ctx->allocator, vecs_data);
789
790                 /* If we failed to write... */
791                 if (ssl_len < 0) {
792                     int ssl_err;
793
794                     /* Ah, bugger. We need to put that data back. */
795                     serf_bucket_aggregate_prepend_iovec(ctx->encrypt.stream,
796                                                         vecs, vecs_read);
797
798                     ssl_err = SSL_get_error(ctx->ssl, ssl_len);
799
800                     serf__log(SSL_VERBOSE, __FILE__, 
801                               "ssl_encrypt: SSL write error: %d\n", ssl_err);
802
803                     if (ssl_err == SSL_ERROR_SYSCALL) {
804                         status = ctx->encrypt.status;
805                         if (SERF_BUCKET_READ_ERROR(status)) {
806                             return status;
807                         }
808                     }
809                     else {
810                         /* Oh, no. */
811                         if (ssl_err == SSL_ERROR_WANT_READ) {
812                             status = SERF_ERROR_WAIT_CONN;
813                         }
814                         else {
815                             ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
816                         }
817                     }
818
819                     serf__log(SSL_VERBOSE, __FILE__, 
820                               "ssl_encrypt: SSL write error: %d %d\n",
821                               status, *len);
822                 }
823             }
824         }
825         else {
826             interim_len = 0;
827             *len = 0;
828             status = ctx->encrypt.status;
829         }
830
831     } while (!status && interim_bufsize);
832
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];
837         int vecs_read, i;
838
839         /* We read something! */
840         agg_status = serf_bucket_read_iovec(ctx->encrypt.pending, bufsize,
841                                             64, vecs, &vecs_read);
842         *len = 0;
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;
846         }
847
848         serf__log(SSL_VERBOSE, __FILE__,
849                   "ssl_encrypt read agg: %d %d %d %d\n", status, agg_status,
850             ctx->encrypt.status, *len);
851
852         if (!agg_status) {
853             status = agg_status;
854         }
855     }
856
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;
861     }
862
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));
867
868     return status;
869 }
870
871 #if APR_HAS_THREADS
872 static apr_pool_t *ssl_pool;
873 static apr_thread_mutex_t **ssl_locks;
874
875 typedef struct CRYPTO_dynlock_value {
876     apr_thread_mutex_t *lock;
877 } CRYPTO_dynlock_value;
878
879 static CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line)
880 {
881     CRYPTO_dynlock_value *l;
882     apr_status_t rv;
883
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 */
888     }
889     return l;
890 }
891
892 static void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file,
893                          int line)
894 {
895     if (mode & CRYPTO_LOCK) {
896         apr_thread_mutex_lock(l->lock);
897     }
898     else if (mode & CRYPTO_UNLOCK) {
899         apr_thread_mutex_unlock(l->lock);
900     }
901 }
902
903 static void ssl_dyn_destroy(CRYPTO_dynlock_value *l, const char *file,
904                             int line)
905 {
906     apr_thread_mutex_destroy(l->lock);
907 }
908
909 static void ssl_lock(int mode, int n, const char *file, int line)
910 {
911     if (mode & CRYPTO_LOCK) {
912         apr_thread_mutex_lock(ssl_locks[n]);
913     }
914     else if (mode & CRYPTO_UNLOCK) {
915         apr_thread_mutex_unlock(ssl_locks[n]);
916     }
917 }
918
919 static unsigned long ssl_id(void)
920 {
921     /* FIXME: This is lame and not portable. -aaron */
922     return (unsigned long) apr_os_thread_current();
923 }
924
925 static apr_status_t cleanup_ssl(void *data)
926 {
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);
932
933     return APR_SUCCESS;
934 }
935
936 #endif
937
938 static apr_uint32_t have_init_ssl = 0;
939
940 static void init_ssl_libraries(void)
941 {
942     apr_uint32_t val;
943 #if APR_VERSION_AT_LEAST(1,0,0)
944     val = apr_atomic_xchg32(&have_init_ssl, 1);
945 #else
946     val = apr_atomic_cas(&have_init_ssl, 1, 0);
947 #endif
948
949     if (!val) {
950 #if APR_HAS_THREADS
951         int i, numlocks;
952 #endif
953
954 #ifdef SSL_VERBOSE
955         /* Warn when compile-time and run-time version of OpenSSL differ in
956            major/minor version number. */
957         long libver = SSLeay();
958
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);
964         }
965 #endif
966
967         CRYPTO_malloc_init();
968         ERR_load_crypto_strings();
969         SSL_load_error_strings();
970         SSL_library_init();
971         OpenSSL_add_all_algorithms();
972
973 #if APR_HAS_THREADS
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++) {
978             apr_status_t rv;
979
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 */
985             }
986         }
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);
992
993         apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl);
994 #endif
995     }
996 }
997
998 static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
999 {
1000     serf_ssl_context_t *ctx = SSL_get_app_data(ssl);
1001     apr_status_t status;
1002
1003     if (ctx->cached_cert) {
1004         *cert = ctx->cached_cert;
1005         *pkey = ctx->cached_cert_pw;
1006         return 1;
1007     }
1008
1009     while (ctx->cert_callback) {
1010         const char *cert_path;
1011         apr_file_t *cert_file;
1012         BIO *bio;
1013         PKCS12 *p12;
1014         int i;
1015         int retrying_success = 0;
1016
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;
1022         } else {
1023             status = ctx->cert_callback(ctx->cert_userdata, &cert_path);
1024         }
1025
1026         if (status || !cert_path) {
1027           break;
1028         }
1029
1030         /* Load the x.509 cert file stored in PKCS12 */
1031         status = apr_file_open(&cert_file, cert_path, APR_READ, APR_OS_DEFAULT,
1032                                ctx->pool);
1033
1034         if (status) {
1035             continue;
1036         }
1037
1038         bio = BIO_new(&bio_file_method);
1039         bio->ptr = cert_file;
1040
1041         ctx->cert_path = cert_path;
1042         p12 = d2i_PKCS12_bio(bio, NULL);
1043         apr_file_close(cert_file);
1044
1045         i = PKCS12_parse(p12, NULL, pkey, cert, NULL);
1046
1047         if (i == 1) {
1048             PKCS12_free(p12);
1049             ctx->cached_cert = *cert;
1050             ctx->cached_cert_pw = *pkey;
1051             if (!retrying_success && ctx->cert_cache_pool) {
1052                 const char *c;
1053
1054                 c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path);
1055
1056                 apr_pool_userdata_setn(c, "serf:ssl:cert",
1057                                        apr_pool_cleanup_null,
1058                                        ctx->cert_cache_pool);
1059             }
1060             return 1;
1061         }
1062         else {
1063             int err = ERR_get_error();
1064             ERR_clear_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;
1069
1070                     if (ctx->cert_pw_success) {
1071                         status = APR_SUCCESS;
1072                         password = ctx->cert_pw_success;
1073                         ctx->cert_pw_success = NULL;
1074                     } else {
1075                         status = ctx->cert_pw_callback(ctx->cert_pw_userdata,
1076                                                        ctx->cert_path,
1077                                                        &password);
1078                     }
1079
1080                     if (!status && password) {
1081                         i = PKCS12_parse(p12, password, pkey, cert, NULL);
1082                         if (i == 1) {
1083                             PKCS12_free(p12);
1084                             ctx->cached_cert = *cert;
1085                             ctx->cached_cert_pw = *pkey;
1086                             if (!retrying_success && ctx->cert_cache_pool) {
1087                                 const char *c;
1088
1089                                 c = apr_pstrdup(ctx->cert_cache_pool,
1090                                                 ctx->cert_path);
1091
1092                                 apr_pool_userdata_setn(c, "serf:ssl:cert",
1093                                                        apr_pool_cleanup_null,
1094                                                        ctx->cert_cache_pool);
1095                             }
1096                             if (!retrying_success && ctx->cert_pw_cache_pool) {
1097                                 const char *c;
1098
1099                                 c = apr_pstrdup(ctx->cert_pw_cache_pool,
1100                                                 password);
1101
1102                                 apr_pool_userdata_setn(c, "serf:ssl:certpw",
1103                                                        apr_pool_cleanup_null,
1104                                                        ctx->cert_pw_cache_pool);
1105                             }
1106                             return 1;
1107                         }
1108                     }
1109                 }
1110                 PKCS12_free(p12);
1111                 return 0;
1112             }
1113             else {
1114                 printf("OpenSSL cert error: %d %d %d\n", ERR_GET_LIB(err),
1115                        ERR_GET_FUNC(err),
1116                        ERR_GET_REASON(err));
1117                 PKCS12_free(p12);
1118             }
1119         }
1120     }
1121
1122     return 0;
1123 }
1124
1125
1126 void serf_ssl_client_cert_provider_set(
1127     serf_ssl_context_t *context,
1128     serf_ssl_need_client_cert_t callback,
1129     void *data,
1130     void *cache_pool)
1131 {
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);
1138     }
1139 }
1140
1141
1142 void serf_ssl_client_cert_password_set(
1143     serf_ssl_context_t *context,
1144     serf_ssl_need_cert_password_t callback,
1145     void *data,
1146     void *cache_pool)
1147 {
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);
1154     }
1155 }
1156
1157
1158 void serf_ssl_server_cert_callback_set(
1159     serf_ssl_context_t *context,
1160     serf_ssl_need_server_cert_t callback,
1161     void *data)
1162 {
1163     context->server_cert_callback = callback;
1164     context->server_cert_userdata = data;
1165 }
1166
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,
1171     void *data)
1172 {
1173     context->server_cert_callback = cert_callback;
1174     context->server_cert_chain_callback = cert_chain_callback;
1175     context->server_cert_userdata = data;
1176 }
1177
1178 static serf_ssl_context_t *ssl_init_context(void)
1179 {
1180     serf_ssl_context_t *ssl_ctx;
1181     apr_pool_t *pool;
1182     serf_bucket_alloc_t *allocator;
1183
1184     init_ssl_libraries();
1185
1186     apr_pool_create(&pool, NULL);
1187     allocator = serf_bucket_allocator_create(pool, NULL, NULL);
1188
1189     ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx));
1190
1191     ssl_ctx->refcount = 0;
1192     ssl_ctx->pool = pool;
1193     ssl_ctx->allocator = allocator;
1194
1195     ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
1196
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;
1202
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;
1207
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);
1213
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;
1217
1218     SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio);
1219
1220     SSL_set_connect_state(ssl_ctx->ssl);
1221
1222     SSL_set_app_data(ssl_ctx->ssl, ssl_ctx);
1223
1224 #if SSL_VERBOSE
1225     SSL_CTX_set_info_callback(ssl_ctx->ctx, apps_ssl_info_callback);
1226 #endif
1227
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;
1235
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;
1242
1243     return ssl_ctx;
1244 }
1245
1246 static apr_status_t ssl_free_context(
1247     serf_ssl_context_t *ssl_ctx)
1248 {
1249     apr_pool_t *p;
1250
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);
1254     }
1255     if (ssl_ctx->encrypt.pending != NULL) {
1256         serf_bucket_destroy(ssl_ctx->encrypt.pending);
1257     }
1258
1259     /* SSL_free implicitly frees the underlying BIO. */
1260     SSL_free(ssl_ctx->ssl);
1261     SSL_CTX_free(ssl_ctx->ctx);
1262
1263     p = ssl_ctx->pool;
1264
1265     serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx);
1266     apr_pool_destroy(p);
1267
1268     return APR_SUCCESS;
1269 }
1270
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)
1275 {
1276     ssl_context_t *ctx;
1277
1278     ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
1279     if (!ssl_ctx) {
1280         ctx->ssl_ctx = ssl_init_context();
1281     }
1282     else {
1283         ctx->ssl_ctx = ssl_ctx;
1284     }
1285     ctx->ssl_ctx->refcount++;
1286
1287     return serf_bucket_create(type, allocator, ctx);
1288 }
1289
1290 apr_status_t serf_ssl_set_hostname(serf_ssl_context_t *context,
1291                                    const char * hostname)
1292 {
1293 #ifdef SSL_set_tlsext_host_name
1294     if (SSL_set_tlsext_host_name(context->ssl, hostname) != 1) {
1295         ERR_clear_error();
1296     }
1297 #endif
1298     return APR_SUCCESS;
1299 }
1300
1301 apr_status_t serf_ssl_use_default_certificates(serf_ssl_context_t *ssl_ctx)
1302 {
1303     X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
1304
1305     int result = X509_STORE_set_default_paths(store);
1306
1307     return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED;
1308 }
1309
1310 apr_status_t serf_ssl_load_cert_file(
1311     serf_ssl_certificate_t **cert,
1312     const char *file_path,
1313     apr_pool_t *pool)
1314 {
1315     FILE *fp = fopen(file_path, "r");
1316         
1317     if (fp) {
1318         X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
1319         fclose(fp);
1320
1321         if (ssl_cert) {
1322             *cert = apr_palloc(pool, sizeof(serf_ssl_certificate_t));
1323             (*cert)->ssl_cert = ssl_cert;
1324
1325             return APR_SUCCESS;
1326         }
1327     }
1328
1329     return SERF_ERROR_SSL_CERT_FAILED;
1330 }
1331
1332
1333 apr_status_t serf_ssl_trust_cert(
1334     serf_ssl_context_t *ssl_ctx,
1335     serf_ssl_certificate_t *cert)
1336 {
1337     X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
1338
1339     int result = X509_STORE_add_cert(store, cert->ssl_cert);
1340
1341     return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED;
1342 }
1343
1344
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)
1349 {
1350     serf_bucket_t *bkt;
1351     ssl_context_t *ctx;
1352
1353     bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1354                                  &serf_bucket_type_ssl_decrypt);
1355
1356     ctx = bkt->data;
1357
1358     ctx->databuf = &ctx->ssl_ctx->decrypt.databuf;
1359     if (ctx->ssl_ctx->decrypt.stream != NULL) {
1360         return NULL;
1361     }
1362     ctx->ssl_ctx->decrypt.stream = stream;
1363     ctx->our_stream = &ctx->ssl_ctx->decrypt.stream;
1364
1365     return bkt;
1366 }
1367
1368
1369 serf_ssl_context_t *serf_bucket_ssl_decrypt_context_get(
1370      serf_bucket_t *bucket)
1371 {
1372     ssl_context_t *ctx = bucket->data;
1373     return ctx->ssl_ctx;
1374 }
1375
1376
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)
1381 {
1382     serf_bucket_t *bkt;
1383     ssl_context_t *ctx;
1384
1385     bkt = serf_bucket_ssl_create(ssl_ctx, allocator,
1386                                  &serf_bucket_type_ssl_encrypt);
1387
1388     ctx = bkt->data;
1389
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;
1396     }
1397     else {
1398         bucket_list_t *new_list;
1399
1400         new_list = serf_bucket_mem_alloc(ctx->ssl_ctx->allocator,
1401                                          sizeof(*new_list));
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;
1406         }
1407         else {
1408             bucket_list_t *scan = ctx->ssl_ctx->encrypt.stream_next;
1409
1410             while (scan->next != NULL)
1411                 scan = scan->next;
1412             scan->next = new_list;
1413         }
1414     }
1415
1416     return bkt;
1417 }
1418
1419
1420 serf_ssl_context_t *serf_bucket_ssl_encrypt_context_get(
1421      serf_bucket_t *bucket)
1422 {
1423     ssl_context_t *ctx = bucket->data;
1424     return ctx->ssl_ctx;
1425 }
1426
1427 /* Functions to read a serf_ssl_certificate structure. */
1428
1429 /* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
1430 static apr_hash_t *
1431 convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
1432 {
1433     char buf[1024];
1434     int ret;
1435
1436     apr_hash_t *tgt = apr_hash_make(pool);
1437
1438     ret = X509_NAME_get_text_by_NID(org,
1439                                     NID_commonName,
1440                                     buf, 1024);
1441     if (ret != -1)
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,
1445                                     buf, 1024);
1446     if (ret != -1)
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,
1450                                     buf, 1024);
1451     if (ret != -1)
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,
1455                                     buf, 1024);
1456     if (ret != -1)
1457         apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1458     ret = X509_NAME_get_text_by_NID(org,
1459                                     NID_localityName,
1460                                     buf, 1024);
1461     if (ret != -1)
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,
1465                                     buf, 1024);
1466     if (ret != -1)
1467         apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1468     ret = X509_NAME_get_text_by_NID(org,
1469                                     NID_countryName,
1470                                     buf, 1024);
1471     if (ret != -1)
1472         apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1473
1474     return tgt;
1475 }
1476
1477
1478 int serf_ssl_cert_depth(const serf_ssl_certificate_t *cert)
1479 {
1480     return cert->depth;
1481 }
1482
1483
1484 apr_hash_t *serf_ssl_cert_issuer(
1485     const serf_ssl_certificate_t *cert,
1486     apr_pool_t *pool)
1487 {
1488     X509_NAME *issuer = X509_get_issuer_name(cert->ssl_cert);
1489
1490     if (!issuer)
1491         return NULL;
1492
1493     return convert_X509_NAME_to_table(issuer, pool);
1494 }
1495
1496
1497 apr_hash_t *serf_ssl_cert_subject(
1498     const serf_ssl_certificate_t *cert,
1499     apr_pool_t *pool)
1500 {
1501     X509_NAME *subject = X509_get_subject_name(cert->ssl_cert);
1502
1503     if (!subject)
1504         return NULL;
1505
1506     return convert_X509_NAME_to_table(subject, pool);
1507 }
1508
1509
1510 apr_hash_t *serf_ssl_cert_certificate(
1511     const serf_ssl_certificate_t *cert,
1512     apr_pool_t *pool)
1513 {
1514     apr_hash_t *tgt = apr_hash_make(pool);
1515     unsigned int md_size, i;
1516     unsigned char md[EVP_MAX_MD_SIZE];
1517     BIO *bio;
1518     STACK_OF(GENERAL_NAME) *names;
1519
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];
1524
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] = ':';
1529         }
1530         if (md_size > 0)
1531             fingerprint[(3*(md_size-1))+2] = '\0';
1532         else
1533             fingerprint[0] = '\0';
1534
1535         apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING,
1536                      apr_pstrdup(pool, fingerprint));
1537     }
1538
1539     /* set expiry dates */
1540     bio = BIO_new(BIO_s_mem());
1541     if (bio) {
1542         ASN1_TIME *notBefore, *notAfter;
1543         char buf[256];
1544
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));
1551         }
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));
1558         }
1559     }
1560     BIO_free(bio);
1561
1562     /* Get subjectAltNames */
1563     names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL);
1564     if (names) {
1565         int names_count = sk_GENERAL_NAME_num(names);
1566
1567         apr_array_header_t *san_arr = apr_array_make(pool, names_count,
1568                                                      sizeof(char*));
1569         apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
1570         for (i = 0; i < names_count; i++) {
1571             char *p = NULL;
1572             GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i);
1573
1574             switch (nm->type) {
1575             case GEN_DNS:
1576                 p = apr_pstrmemdup(pool, (const char *)nm->d.ia5->data,
1577                                    nm->d.ia5->length);
1578                 break;
1579             default:
1580                 /* Don't know what to do - skip. */
1581                 break;
1582             }
1583             if (p) {
1584                 APR_ARRAY_PUSH(san_arr, char*) = p;
1585             }
1586         }
1587         sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
1588     }
1589
1590     return tgt;
1591 }
1592
1593
1594 const char *serf_ssl_cert_export(
1595     const serf_ssl_certificate_t *cert,
1596     apr_pool_t *pool)
1597 {
1598     char *binary_cert;
1599     char *encoded_cert;
1600     int len;
1601     unsigned char *unused;
1602
1603     /* find the length of the DER encoding. */
1604     len = i2d_X509(cert->ssl_cert, NULL);
1605     if (len < 0) {
1606         return NULL;
1607     }
1608
1609     binary_cert = apr_palloc(pool, len);
1610     unused = (unsigned char *)binary_cert;
1611     len = i2d_X509(cert->ssl_cert, &unused);  /* unused is incremented  */
1612     if (len < 0) {
1613         return NULL;
1614     }
1615
1616     encoded_cert = apr_palloc(pool, apr_base64_encode_len(len));
1617     apr_base64_encode(encoded_cert, binary_cert, len);
1618     
1619     return encoded_cert;
1620 }
1621
1622 /* Disables compression for all SSL sessions. */
1623 static void disable_compression(serf_ssl_context_t *ssl_ctx)
1624 {
1625 #ifdef SSL_OP_NO_COMPRESSION
1626     SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_COMPRESSION);
1627 #endif
1628 }
1629
1630 apr_status_t serf_ssl_use_compression(serf_ssl_context_t *ssl_ctx, int enabled)
1631 {
1632     if (enabled) {
1633 #ifdef SSL_OP_NO_COMPRESSION
1634         SSL_clear_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION);
1635         return APR_SUCCESS;
1636 #endif
1637     } else {
1638 #ifdef SSL_OP_NO_COMPRESSION
1639         SSL_set_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION);
1640         return APR_SUCCESS;
1641 #endif
1642     }
1643
1644     return APR_EGENERAL;
1645 }
1646
1647 static void serf_ssl_destroy_and_data(serf_bucket_t *bucket)
1648 {
1649     ssl_context_t *ctx = bucket->data;
1650
1651     if (!--ctx->ssl_ctx->refcount) {
1652         ssl_free_context(ctx->ssl_ctx);
1653     }
1654
1655     serf_default_destroy_and_data(bucket);
1656 }
1657
1658 static void serf_ssl_decrypt_destroy_and_data(serf_bucket_t *bucket)
1659 {
1660     ssl_context_t *ctx = bucket->data;
1661
1662     serf_bucket_destroy(*ctx->our_stream);
1663
1664     serf_ssl_destroy_and_data(bucket);
1665 }
1666
1667 static void serf_ssl_encrypt_destroy_and_data(serf_bucket_t *bucket)
1668 {
1669     ssl_context_t *ctx = bucket->data;
1670     serf_ssl_context_t *ssl_ctx = ctx->ssl_ctx;
1671
1672     if (ssl_ctx->encrypt.stream == *ctx->our_stream) {
1673         serf_bucket_destroy(*ctx->our_stream);
1674         serf_bucket_destroy(ssl_ctx->encrypt.pending);
1675
1676         /* Reset our encrypted status and databuf. */
1677         ssl_ctx->encrypt.status = APR_SUCCESS;
1678         ssl_ctx->encrypt.databuf.status = APR_SUCCESS;
1679
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;
1684         }
1685         else {
1686             bucket_list_t *cur;
1687
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);
1694         }
1695     }
1696     else {
1697         /* Ah, darn.  We haven't sent this one along yet. */
1698         return;
1699     }
1700     serf_ssl_destroy_and_data(bucket);
1701 }
1702
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)
1706 {
1707     ssl_context_t *ctx = bucket->data;
1708
1709     return serf_databuf_read(ctx->databuf, requested, data, len);
1710 }
1711
1712 static apr_status_t serf_ssl_readline(serf_bucket_t *bucket,
1713                                       int acceptable, int *found,
1714                                       const char **data,
1715                                       apr_size_t *len)
1716 {
1717     ssl_context_t *ctx = bucket->data;
1718
1719     return serf_databuf_readline(ctx->databuf, acceptable, found, data, len);
1720 }
1721
1722 static apr_status_t serf_ssl_peek(serf_bucket_t *bucket,
1723                                   const char **data,
1724                                   apr_size_t *len)
1725 {
1726     ssl_context_t *ctx = bucket->data;
1727
1728     return serf_databuf_peek(ctx->databuf, data, len);
1729 }
1730
1731
1732 const serf_bucket_type_t serf_bucket_type_ssl_encrypt = {
1733     "SSLENCRYPT",
1734     serf_ssl_read,
1735     serf_ssl_readline,
1736     serf_default_read_iovec,
1737     serf_default_read_for_sendfile,
1738     serf_default_read_bucket,
1739     serf_ssl_peek,
1740     serf_ssl_encrypt_destroy_and_data,
1741 };
1742
1743 const serf_bucket_type_t serf_bucket_type_ssl_decrypt = {
1744     "SSLDECRYPT",
1745     serf_ssl_read,
1746     serf_ssl_readline,
1747     serf_default_read_iovec,
1748     serf_default_read_for_sendfile,
1749     serf_default_read_bucket,
1750     serf_ssl_peek,
1751     serf_ssl_decrypt_destroy_and_data,
1752 };