1251877Speter/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein 2251877Speter * 3251877Speter * Licensed under the Apache License, Version 2.0 (the "License"); 4251877Speter * you may not use this file except in compliance with the License. 5251877Speter * You may obtain a copy of the License at 6251877Speter * 7251877Speter * http://www.apache.org/licenses/LICENSE-2.0 8251877Speter * 9251877Speter * Unless required by applicable law or agreed to in writing, software 10251877Speter * distributed under the License is distributed on an "AS IS" BASIS, 11251877Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12251877Speter * See the License for the specific language governing permissions and 13251877Speter * limitations under the License. 14251877Speter * 15251877Speter * ---- 16251877Speter * 17251877Speter * For the OpenSSL thread-safety locking code: 18251877Speter * 19251877Speter * Licensed to the Apache Software Foundation (ASF) under one or more 20251877Speter * contributor license agreements. See the NOTICE file distributed with 21251877Speter * this work for additional information regarding copyright ownership. 22251877Speter * The ASF licenses this file to You under the Apache License, Version 2.0 23251877Speter * (the "License"); you may not use this file except in compliance with 24251877Speter * the License. You may obtain a copy of the License at 25251877Speter * 26251877Speter * http://www.apache.org/licenses/LICENSE-2.0 27251877Speter * 28251877Speter * Unless required by applicable law or agreed to in writing, software 29251877Speter * distributed under the License is distributed on an "AS IS" BASIS, 30251877Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 31251877Speter * See the License for the specific language governing permissions and 32251877Speter * limitations under the License. 33251877Speter * 34251877Speter * Originally developed by Aaron Bannert and Justin Erenkrantz, eBuilt. 35251877Speter */ 36251877Speter 37251877Speter#include <apr_pools.h> 38251877Speter#include <apr_network_io.h> 39251877Speter#include <apr_portable.h> 40251877Speter#include <apr_strings.h> 41251877Speter#include <apr_base64.h> 42251877Speter#include <apr_version.h> 43251877Speter#include <apr_atomic.h> 44251877Speter 45251877Speter#include "serf.h" 46251877Speter#include "serf_private.h" 47251877Speter#include "serf_bucket_util.h" 48251877Speter 49251877Speter#include <openssl/bio.h> 50251877Speter#include <openssl/ssl.h> 51251877Speter#include <openssl/err.h> 52251877Speter#include <openssl/pkcs12.h> 53251877Speter#include <openssl/x509v3.h> 54251877Speter 55251877Speter#ifndef APR_VERSION_AT_LEAST /* Introduced in APR 1.3.0 */ 56251877Speter#define APR_VERSION_AT_LEAST(major,minor,patch) \ 57251877Speter (((major) < APR_MAJOR_VERSION) \ 58251877Speter || ((major) == APR_MAJOR_VERSION && (minor) < APR_MINOR_VERSION) \ 59251877Speter || ((major) == APR_MAJOR_VERSION && (minor) == APR_MINOR_VERSION && \ 60251877Speter (patch) <= APR_PATCH_VERSION)) 61251877Speter#endif /* APR_VERSION_AT_LEAST */ 62251877Speter 63251877Speter#ifndef APR_ARRAY_PUSH 64251877Speter#define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary))) 65251877Speter#endif 66251877Speter 67251877Speter 68251877Speter/* 69251877Speter * Here's an overview of the SSL bucket's relationship to OpenSSL and serf. 70251877Speter * 71251877Speter * HTTP request: SSLENCRYPT(REQUEST) 72251877Speter * [context.c reads from SSLENCRYPT and writes out to the socket] 73251877Speter * HTTP response: RESPONSE(SSLDECRYPT(SOCKET)) 74251877Speter * [handler function reads from RESPONSE which in turn reads from SSLDECRYPT] 75251877Speter * 76251877Speter * HTTP request read call path: 77251877Speter * 78251877Speter * write_to_connection 79251877Speter * |- serf_bucket_read on SSLENCRYPT 80251877Speter * |- serf_ssl_read 81251877Speter * |- serf_databuf_read 82251877Speter * |- common_databuf_prep 83251877Speter * |- ssl_encrypt 84251877Speter * |- 1. Try to read pending encrypted data; If available, return. 85251877Speter * |- 2. Try to read from ctx->stream [REQUEST bucket] 86251877Speter * |- 3. Call SSL_write with read data 87251877Speter * |- ... 88251877Speter * |- bio_bucket_read can be called 89251877Speter * |- bio_bucket_write with encrypted data 90251877Speter * |- store in sink 91251877Speter * |- 4. If successful, read pending encrypted data and return. 92251877Speter * |- 5. If fails, place read data back in ctx->stream 93251877Speter * 94251877Speter * HTTP response read call path: 95251877Speter * 96251877Speter * read_from_connection 97251877Speter * |- acceptor 98251877Speter * |- handler 99251877Speter * |- ... 100251877Speter * |- serf_bucket_read(SSLDECRYPT) 101251877Speter * |- serf_ssl_read 102251877Speter * |- serf_databuf_read 103251877Speter * |- ssl_decrypt 104251877Speter * |- 1. SSL_read() for pending decrypted data; if any, return. 105251877Speter * |- 2. Try to read from ctx->stream [SOCKET bucket] 106251877Speter * |- 3. Append data to ssl_ctx->source 107251877Speter * |- 4. Call SSL_read() 108251877Speter * |- ... 109251877Speter * |- bio_bucket_write can be called 110251877Speter * |- bio_bucket_read 111251877Speter * |- read data from ssl_ctx->source 112251877Speter * |- If data read, return it. 113251877Speter * |- If an error, set the STATUS value and return. 114251877Speter * 115251877Speter */ 116251877Speter 117251877Spetertypedef struct bucket_list { 118251877Speter serf_bucket_t *bucket; 119251877Speter struct bucket_list *next; 120251877Speter} bucket_list_t; 121251877Speter 122251877Spetertypedef struct { 123251877Speter /* Helper to read data. Wraps stream. */ 124251877Speter serf_databuf_t databuf; 125251877Speter 126251877Speter /* Our source for more data. */ 127251877Speter serf_bucket_t *stream; 128251877Speter 129251877Speter /* The next set of buckets */ 130251877Speter bucket_list_t *stream_next; 131251877Speter 132251877Speter /* The status of the last thing we read. */ 133251877Speter apr_status_t status; 134251877Speter apr_status_t exhausted; 135251877Speter int exhausted_reset; 136251877Speter 137251877Speter /* Data we've read but not processed. */ 138251877Speter serf_bucket_t *pending; 139251877Speter} serf_ssl_stream_t; 140251877Speter 141251877Speterstruct serf_ssl_context_t { 142251877Speter /* How many open buckets refer to this context. */ 143251877Speter int refcount; 144251877Speter 145251877Speter /* The pool that this context uses. */ 146251877Speter apr_pool_t *pool; 147251877Speter 148251877Speter /* The allocator associated with the above pool. */ 149251877Speter serf_bucket_alloc_t *allocator; 150251877Speter 151251877Speter /* Internal OpenSSL parameters */ 152251877Speter SSL_CTX *ctx; 153251877Speter SSL *ssl; 154251877Speter BIO *bio; 155251877Speter 156251877Speter serf_ssl_stream_t encrypt; 157251877Speter serf_ssl_stream_t decrypt; 158251877Speter 159251877Speter /* Client cert callbacks */ 160251877Speter serf_ssl_need_client_cert_t cert_callback; 161251877Speter void *cert_userdata; 162251877Speter apr_pool_t *cert_cache_pool; 163251877Speter const char *cert_file_success; 164251877Speter 165251877Speter /* Client cert PW callbacks */ 166251877Speter serf_ssl_need_cert_password_t cert_pw_callback; 167251877Speter void *cert_pw_userdata; 168251877Speter apr_pool_t *cert_pw_cache_pool; 169251877Speter const char *cert_pw_success; 170251877Speter 171251877Speter /* Server cert callbacks */ 172251877Speter serf_ssl_need_server_cert_t server_cert_callback; 173251877Speter serf_ssl_server_cert_chain_cb_t server_cert_chain_callback; 174251877Speter void *server_cert_userdata; 175251877Speter 176251877Speter const char *cert_path; 177251877Speter 178251877Speter X509 *cached_cert; 179251877Speter EVP_PKEY *cached_cert_pw; 180251877Speter 181251877Speter apr_status_t pending_err; 182251877Speter 183251877Speter /* Status of a fatal error, returned on subsequent encrypt or decrypt 184251877Speter requests. */ 185251877Speter apr_status_t fatal_err; 186251877Speter}; 187251877Speter 188251877Spetertypedef struct { 189251877Speter /* The bucket-independent ssl context that this bucket is associated with */ 190251877Speter serf_ssl_context_t *ssl_ctx; 191251877Speter 192251877Speter /* Pointer to the 'right' databuf. */ 193251877Speter serf_databuf_t *databuf; 194251877Speter 195251877Speter /* Pointer to our stream, so we can find it later. */ 196251877Speter serf_bucket_t **our_stream; 197251877Speter} ssl_context_t; 198251877Speter 199251877Speterstruct serf_ssl_certificate_t { 200251877Speter X509 *ssl_cert; 201251877Speter int depth; 202251877Speter}; 203251877Speter 204251877Speterstatic void disable_compression(serf_ssl_context_t *ssl_ctx); 205251877Speter 206251877Speter#if SSL_VERBOSE 207251877Speter/* Log all ssl alerts that we receive from the server. */ 208251877Speterstatic void 209251877Speterapps_ssl_info_callback(const SSL *s, int where, int ret) 210251877Speter{ 211251877Speter const char *str; 212251877Speter int w; 213251877Speter w = where & ~SSL_ST_MASK; 214253895Speter 215251877Speter if (w & SSL_ST_CONNECT) 216251877Speter str = "SSL_connect"; 217251877Speter else if (w & SSL_ST_ACCEPT) 218251877Speter str = "SSL_accept"; 219251877Speter else 220251877Speter str = "undefined"; 221253895Speter 222251877Speter if (where & SSL_CB_LOOP) { 223251877Speter serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str, 224251877Speter SSL_state_string_long(s)); 225251877Speter } 226251877Speter else if (where & SSL_CB_ALERT) { 227251877Speter str = (where & SSL_CB_READ) ? "read" : "write"; 228251877Speter serf__log(SSL_VERBOSE, __FILE__, "SSL3 alert %s:%s:%s\n", 229251877Speter str, 230251877Speter SSL_alert_type_string_long(ret), 231251877Speter SSL_alert_desc_string_long(ret)); 232251877Speter } 233251877Speter else if (where & SSL_CB_EXIT) { 234251877Speter if (ret == 0) 235251877Speter serf__log(SSL_VERBOSE, __FILE__, "%s:failed in %s\n", str, 236251877Speter SSL_state_string_long(s)); 237251877Speter else if (ret < 0) { 238251877Speter serf__log(SSL_VERBOSE, __FILE__, "%s:error in %s\n", str, 239251877Speter SSL_state_string_long(s)); 240251877Speter } 241251877Speter } 242251877Speter} 243251877Speter#endif 244251877Speter 245251877Speter/* Returns the amount read. */ 246251877Speterstatic int bio_bucket_read(BIO *bio, char *in, int inlen) 247251877Speter{ 248251877Speter serf_ssl_context_t *ctx = bio->ptr; 249251877Speter const char *data; 250251877Speter apr_status_t status; 251251877Speter apr_size_t len; 252251877Speter 253251877Speter serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read called for %d bytes\n", 254251877Speter inlen); 255251877Speter 256251877Speter if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN 257251877Speter && BIO_should_read(ctx->bio)) { 258253895Speter serf__log(SSL_VERBOSE, __FILE__, 259253895Speter "bio_bucket_read waiting: (%d %d %d)\n", 260251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 261251877Speter BIO_get_retry_flags(ctx->bio)); 262251877Speter /* Falling back... */ 263251877Speter ctx->encrypt.exhausted_reset = 1; 264251877Speter BIO_clear_retry_flags(bio); 265251877Speter } 266251877Speter 267251877Speter status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len); 268251877Speter 269251877Speter ctx->decrypt.status = status; 270251877Speter 271251877Speter serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read received %d bytes (%d)\n", 272251877Speter len, status); 273251877Speter 274251877Speter if (!SERF_BUCKET_READ_ERROR(status)) { 275251877Speter /* Oh suck. */ 276251877Speter if (len) { 277251877Speter memcpy(in, data, len); 278251877Speter return len; 279251877Speter } 280251877Speter if (APR_STATUS_IS_EOF(status)) { 281251877Speter BIO_set_retry_read(bio); 282251877Speter return -1; 283251877Speter } 284251877Speter } 285251877Speter 286251877Speter return -1; 287251877Speter} 288251877Speter 289251877Speter/* Returns the amount written. */ 290251877Speterstatic int bio_bucket_write(BIO *bio, const char *in, int inl) 291251877Speter{ 292251877Speter serf_ssl_context_t *ctx = bio->ptr; 293251877Speter serf_bucket_t *tmp; 294251877Speter 295251877Speter serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write called for %d bytes\n", 296251877Speter inl); 297251877Speter 298251877Speter if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN 299251877Speter && !BIO_should_read(ctx->bio)) { 300253895Speter serf__log(SSL_VERBOSE, __FILE__, 301253895Speter "bio_bucket_write waiting: (%d %d %d)\n", 302251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 303251877Speter BIO_get_retry_flags(ctx->bio)); 304251877Speter /* Falling back... */ 305251877Speter ctx->encrypt.exhausted_reset = 1; 306251877Speter BIO_clear_retry_flags(bio); 307251877Speter } 308251877Speter 309251877Speter tmp = serf_bucket_simple_copy_create(in, inl, 310251877Speter ctx->encrypt.pending->allocator); 311251877Speter 312251877Speter serf_bucket_aggregate_append(ctx->encrypt.pending, tmp); 313251877Speter 314251877Speter return inl; 315251877Speter} 316251877Speter 317251877Speter/* Returns the amount read. */ 318251877Speterstatic int bio_file_read(BIO *bio, char *in, int inlen) 319251877Speter{ 320251877Speter apr_file_t *file = bio->ptr; 321251877Speter apr_status_t status; 322251877Speter apr_size_t len; 323251877Speter 324251877Speter BIO_clear_retry_flags(bio); 325251877Speter 326251877Speter len = inlen; 327251877Speter status = apr_file_read(file, in, &len); 328251877Speter 329251877Speter if (!SERF_BUCKET_READ_ERROR(status)) { 330251877Speter /* Oh suck. */ 331251877Speter if (APR_STATUS_IS_EOF(status)) { 332251877Speter BIO_set_retry_read(bio); 333251877Speter return -1; 334251877Speter } else { 335251877Speter return len; 336251877Speter } 337251877Speter } 338251877Speter 339251877Speter return -1; 340251877Speter} 341251877Speter 342251877Speter/* Returns the amount written. */ 343251877Speterstatic int bio_file_write(BIO *bio, const char *in, int inl) 344251877Speter{ 345251877Speter apr_file_t *file = bio->ptr; 346251877Speter apr_size_t nbytes; 347251877Speter 348251877Speter BIO_clear_retry_flags(bio); 349251877Speter 350251877Speter nbytes = inl; 351251877Speter apr_file_write(file, in, &nbytes); 352251877Speter 353251877Speter return nbytes; 354251877Speter} 355251877Speter 356251877Speterstatic int bio_file_gets(BIO *bio, char *in, int inlen) 357251877Speter{ 358251877Speter return bio_file_read(bio, in, inlen); 359251877Speter} 360251877Speter 361251877Speterstatic int bio_bucket_create(BIO *bio) 362251877Speter{ 363251877Speter bio->shutdown = 1; 364251877Speter bio->init = 1; 365251877Speter bio->num = -1; 366251877Speter bio->ptr = NULL; 367251877Speter 368251877Speter return 1; 369251877Speter} 370251877Speter 371251877Speterstatic int bio_bucket_destroy(BIO *bio) 372251877Speter{ 373251877Speter /* Did we already free this? */ 374251877Speter if (bio == NULL) { 375251877Speter return 0; 376251877Speter } 377251877Speter 378251877Speter return 1; 379251877Speter} 380251877Speter 381251877Speterstatic long bio_bucket_ctrl(BIO *bio, int cmd, long num, void *ptr) 382251877Speter{ 383251877Speter long ret = 1; 384251877Speter 385251877Speter switch (cmd) { 386251877Speter default: 387251877Speter /* abort(); */ 388251877Speter break; 389251877Speter case BIO_CTRL_FLUSH: 390251877Speter /* At this point we can't force a flush. */ 391251877Speter break; 392251877Speter case BIO_CTRL_PUSH: 393251877Speter case BIO_CTRL_POP: 394251877Speter ret = 0; 395251877Speter break; 396251877Speter } 397251877Speter return ret; 398251877Speter} 399251877Speter 400251877Speterstatic BIO_METHOD bio_bucket_method = { 401251877Speter BIO_TYPE_MEM, 402251877Speter "Serf SSL encryption and decryption buckets", 403251877Speter bio_bucket_write, 404251877Speter bio_bucket_read, 405251877Speter NULL, /* Is this called? */ 406251877Speter NULL, /* Is this called? */ 407251877Speter bio_bucket_ctrl, 408251877Speter bio_bucket_create, 409251877Speter bio_bucket_destroy, 410251877Speter#ifdef OPENSSL_VERSION_NUMBER 411251877Speter NULL /* sslc does not have the callback_ctrl field */ 412251877Speter#endif 413251877Speter}; 414251877Speter 415251877Speterstatic BIO_METHOD bio_file_method = { 416251877Speter BIO_TYPE_FILE, 417251877Speter "Wrapper around APR file structures", 418251877Speter bio_file_write, 419251877Speter bio_file_read, 420251877Speter NULL, /* Is this called? */ 421251877Speter bio_file_gets, /* Is this called? */ 422251877Speter bio_bucket_ctrl, 423251877Speter bio_bucket_create, 424251877Speter bio_bucket_destroy, 425251877Speter#ifdef OPENSSL_VERSION_NUMBER 426251877Speter NULL /* sslc does not have the callback_ctrl field */ 427251877Speter#endif 428251877Speter}; 429251877Speter 430251877Speterstatic int 431251877Spetervalidate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx) 432251877Speter{ 433251877Speter SSL *ssl; 434251877Speter serf_ssl_context_t *ctx; 435251877Speter X509 *server_cert; 436251877Speter int err, depth; 437251877Speter int failures = 0; 438251877Speter 439251877Speter ssl = X509_STORE_CTX_get_ex_data(store_ctx, 440251877Speter SSL_get_ex_data_X509_STORE_CTX_idx()); 441251877Speter ctx = SSL_get_app_data(ssl); 442251877Speter 443251877Speter server_cert = X509_STORE_CTX_get_current_cert(store_ctx); 444251877Speter depth = X509_STORE_CTX_get_error_depth(store_ctx); 445251877Speter 446251877Speter /* If the certification was found invalid, get the error and convert it to 447251877Speter something our caller will understand. */ 448251877Speter if (! cert_valid) { 449251877Speter err = X509_STORE_CTX_get_error(store_ctx); 450251877Speter 451251877Speter switch(err) { 452251877Speter case X509_V_ERR_CERT_NOT_YET_VALID: 453251877Speter failures |= SERF_SSL_CERT_NOTYETVALID; 454251877Speter break; 455251877Speter case X509_V_ERR_CERT_HAS_EXPIRED: 456251877Speter failures |= SERF_SSL_CERT_EXPIRED; 457251877Speter break; 458251877Speter case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 459251877Speter case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 460251877Speter failures |= SERF_SSL_CERT_SELF_SIGNED; 461251877Speter break; 462251877Speter case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 463251877Speter case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 464251877Speter case X509_V_ERR_CERT_UNTRUSTED: 465251877Speter case X509_V_ERR_INVALID_CA: 466251877Speter failures |= SERF_SSL_CERT_UNKNOWNCA; 467251877Speter break; 468251877Speter case X509_V_ERR_CERT_REVOKED: 469251877Speter failures |= SERF_SSL_CERT_REVOKED; 470251877Speter break; 471251877Speter default: 472251877Speter failures |= SERF_SSL_CERT_UNKNOWN_FAILURE; 473251877Speter break; 474251877Speter } 475251877Speter } 476251877Speter 477251877Speter /* Check certificate expiry dates. */ 478251877Speter if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) { 479251877Speter failures |= SERF_SSL_CERT_NOTYETVALID; 480251877Speter } 481251877Speter else if (X509_cmp_current_time(X509_get_notAfter(server_cert)) <= 0) { 482251877Speter failures |= SERF_SSL_CERT_EXPIRED; 483251877Speter } 484251877Speter 485251877Speter if (ctx->server_cert_callback && 486251877Speter (depth == 0 || failures)) { 487251877Speter apr_status_t status; 488251877Speter serf_ssl_certificate_t *cert; 489251877Speter apr_pool_t *subpool; 490251877Speter 491251877Speter apr_pool_create(&subpool, ctx->pool); 492251877Speter 493251877Speter cert = apr_palloc(subpool, sizeof(serf_ssl_certificate_t)); 494251877Speter cert->ssl_cert = server_cert; 495251877Speter cert->depth = depth; 496251877Speter 497251877Speter /* Callback for further verification. */ 498251877Speter status = ctx->server_cert_callback(ctx->server_cert_userdata, 499251877Speter failures, cert); 500251877Speter if (status == APR_SUCCESS) 501251877Speter cert_valid = 1; 502251877Speter else { 503251877Speter /* Even if openssl found the certificate valid, the application 504251877Speter told us to reject it. */ 505251877Speter cert_valid = 0; 506251877Speter /* Pass the error back to the caller through the context-run. */ 507251877Speter ctx->pending_err = status; 508251877Speter } 509251877Speter apr_pool_destroy(subpool); 510251877Speter } 511251877Speter 512251877Speter if (ctx->server_cert_chain_callback 513251877Speter && (depth == 0 || failures)) { 514251877Speter apr_status_t status; 515251877Speter STACK_OF(X509) *chain; 516251877Speter const serf_ssl_certificate_t **certs; 517251877Speter int certs_len; 518251877Speter apr_pool_t *subpool; 519251877Speter 520251877Speter apr_pool_create(&subpool, ctx->pool); 521251877Speter 522251877Speter /* Borrow the chain to pass to the callback. */ 523251877Speter chain = X509_STORE_CTX_get_chain(store_ctx); 524251877Speter 525251877Speter /* If the chain can't be retrieved, just pass the current 526251877Speter certificate. */ 527251877Speter /* ### can this actually happen with _get_chain() ? */ 528251877Speter if (!chain) { 529251877Speter serf_ssl_certificate_t *cert = apr_palloc(subpool, sizeof(*cert)); 530251877Speter 531251877Speter cert->ssl_cert = server_cert; 532251877Speter cert->depth = depth; 533251877Speter 534251877Speter /* Room for the server_cert and a trailing NULL. */ 535251877Speter certs = apr_palloc(subpool, sizeof(*certs) * 2); 536251877Speter certs[0] = cert; 537251877Speter 538251877Speter certs_len = 1; 539251877Speter } else { 540251877Speter int i; 541251877Speter 542251877Speter certs_len = sk_X509_num(chain); 543251877Speter 544251877Speter /* Room for all the certs and a trailing NULL. */ 545251877Speter certs = apr_palloc(subpool, sizeof(*certs) * (certs_len + 1)); 546251877Speter for (i = 0; i < certs_len; ++i) { 547251877Speter serf_ssl_certificate_t *cert; 548251877Speter 549251877Speter cert = apr_palloc(subpool, sizeof(*cert)); 550251877Speter cert->ssl_cert = sk_X509_value(chain, i); 551251877Speter cert->depth = i; 552251877Speter 553251877Speter certs[i] = cert; 554251877Speter } 555251877Speter } 556251877Speter certs[certs_len] = NULL; 557251877Speter 558251877Speter /* Callback for further verification. */ 559251877Speter status = ctx->server_cert_chain_callback(ctx->server_cert_userdata, 560251877Speter failures, depth, 561251877Speter certs, certs_len); 562251877Speter if (status == APR_SUCCESS) { 563251877Speter cert_valid = 1; 564251877Speter } else { 565251877Speter /* Even if openssl found the certificate valid, the application 566251877Speter told us to reject it. */ 567251877Speter cert_valid = 0; 568251877Speter /* Pass the error back to the caller through the context-run. */ 569251877Speter ctx->pending_err = status; 570251877Speter } 571251877Speter 572251877Speter apr_pool_destroy(subpool); 573251877Speter } 574251877Speter 575253895Speter /* Return a specific error if the server certificate is not accepted by 576253895Speter OpenSSL and the application has not set callbacks to override this. */ 577253895Speter if (!cert_valid && 578253895Speter !ctx->server_cert_chain_callback && 579253895Speter !ctx->server_cert_callback) 580253895Speter { 581253895Speter ctx->pending_err = SERF_ERROR_SSL_CERT_FAILED; 582253895Speter } 583253895Speter 584251877Speter return cert_valid; 585251877Speter} 586251877Speter 587251877Speter/* This function reads an encrypted stream and returns the decrypted stream. */ 588251877Speterstatic apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize, 589251877Speter char *buf, apr_size_t *len) 590251877Speter{ 591251877Speter serf_ssl_context_t *ctx = baton; 592251877Speter apr_size_t priv_len; 593251877Speter apr_status_t status; 594251877Speter const char *data; 595251877Speter int ssl_len; 596251877Speter 597251877Speter if (ctx->fatal_err) 598251877Speter return ctx->fatal_err; 599251877Speter 600251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_decrypt: begin %d\n", bufsize); 601251877Speter 602251877Speter /* Is there some data waiting to be read? */ 603251877Speter ssl_len = SSL_read(ctx->ssl, buf, bufsize); 604251877Speter if (ssl_len > 0) { 605251877Speter serf__log(SSL_VERBOSE, __FILE__, 606251877Speter "ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n", 607251877Speter ssl_len, bufsize, ctx->decrypt.status, 608251877Speter BIO_get_retry_flags(ctx->bio)); 609251877Speter *len = ssl_len; 610251877Speter return APR_SUCCESS; 611251877Speter } 612251877Speter 613251877Speter status = serf_bucket_read(ctx->decrypt.stream, bufsize, &data, &priv_len); 614251877Speter 615251877Speter if (!SERF_BUCKET_READ_ERROR(status) && priv_len) { 616251877Speter serf_bucket_t *tmp; 617251877Speter 618251877Speter serf__log(SSL_VERBOSE, __FILE__, 619251877Speter "ssl_decrypt: read %d bytes (%d); status: %d\n", 620251877Speter priv_len, bufsize, status); 621251877Speter 622251877Speter tmp = serf_bucket_simple_copy_create(data, priv_len, 623251877Speter ctx->decrypt.pending->allocator); 624251877Speter 625251877Speter serf_bucket_aggregate_append(ctx->decrypt.pending, tmp); 626251877Speter 627251877Speter ssl_len = SSL_read(ctx->ssl, buf, bufsize); 628251877Speter if (ssl_len < 0) { 629251877Speter int ssl_err; 630251877Speter 631251877Speter ssl_err = SSL_get_error(ctx->ssl, ssl_len); 632251877Speter switch (ssl_err) { 633251877Speter case SSL_ERROR_SYSCALL: 634251877Speter *len = 0; 635253895Speter /* Return the underlying network error that caused OpenSSL 636253895Speter to fail. ### This can be a crypt error! */ 637251877Speter status = ctx->decrypt.status; 638251877Speter break; 639251877Speter case SSL_ERROR_WANT_READ: 640253895Speter case SSL_ERROR_WANT_WRITE: 641251877Speter *len = 0; 642251877Speter status = APR_EAGAIN; 643251877Speter break; 644251877Speter case SSL_ERROR_SSL: 645251877Speter *len = 0; 646251877Speter if (ctx->pending_err) { 647251877Speter status = ctx->pending_err; 648251877Speter ctx->pending_err = 0; 649251877Speter } else { 650251877Speter ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; 651251877Speter } 652251877Speter break; 653251877Speter default: 654251877Speter *len = 0; 655251877Speter ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; 656251877Speter break; 657251877Speter } 658251877Speter } else if (ssl_len == 0) { 659251877Speter /* The server shut down the connection. */ 660251877Speter int ssl_err, shutdown; 661251877Speter *len = 0; 662251877Speter 663251877Speter /* Check for SSL_RECEIVED_SHUTDOWN */ 664251877Speter shutdown = SSL_get_shutdown(ctx->ssl); 665251877Speter /* Check for SSL_ERROR_ZERO_RETURN */ 666251877Speter ssl_err = SSL_get_error(ctx->ssl, ssl_len); 667251877Speter 668251877Speter if (shutdown == SSL_RECEIVED_SHUTDOWN && 669251877Speter ssl_err == SSL_ERROR_ZERO_RETURN) { 670251877Speter /* The server closed the SSL session. While this doesn't 671251877Speter necessary mean the connection is closed, let's close 672251877Speter it here anyway. 673251877Speter We can optimize this later. */ 674251877Speter serf__log(SSL_VERBOSE, __FILE__, 675251877Speter "ssl_decrypt: SSL read error: server" 676251877Speter " shut down connection!\n"); 677251877Speter status = APR_EOF; 678251877Speter } else { 679251877Speter /* A fatal error occurred. */ 680251877Speter ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; 681251877Speter } 682251877Speter } else { 683251877Speter *len = ssl_len; 684251877Speter serf__log(SSL_MSG_VERBOSE, __FILE__, 685251877Speter "---\n%.*s\n-(%d)-\n", *len, buf, *len); 686251877Speter } 687251877Speter } 688251877Speter else { 689251877Speter *len = 0; 690251877Speter } 691251877Speter serf__log(SSL_VERBOSE, __FILE__, 692251877Speter "ssl_decrypt: %d %d %d\n", status, *len, 693251877Speter BIO_get_retry_flags(ctx->bio)); 694251877Speter 695251877Speter return status; 696251877Speter} 697251877Speter 698251877Speter/* This function reads a decrypted stream and returns an encrypted stream. */ 699251877Speterstatic apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize, 700251877Speter char *buf, apr_size_t *len) 701251877Speter{ 702251877Speter const char *data; 703251877Speter apr_size_t interim_bufsize; 704251877Speter serf_ssl_context_t *ctx = baton; 705251877Speter apr_status_t status; 706251877Speter 707251877Speter if (ctx->fatal_err) 708251877Speter return ctx->fatal_err; 709251877Speter 710251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: begin %d\n", bufsize); 711251877Speter 712251877Speter /* Try to read already encrypted but unread data first. */ 713251877Speter status = serf_bucket_read(ctx->encrypt.pending, bufsize, &data, len); 714251877Speter if (SERF_BUCKET_READ_ERROR(status)) { 715251877Speter return status; 716251877Speter } 717251877Speter 718251877Speter /* Aha, we read something. Return that now. */ 719251877Speter if (*len) { 720251877Speter memcpy(buf, data, *len); 721251877Speter if (APR_STATUS_IS_EOF(status)) { 722251877Speter status = APR_SUCCESS; 723251877Speter } 724251877Speter 725251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: %d %d %d (quick read)\n", 726251877Speter status, *len, BIO_get_retry_flags(ctx->bio)); 727251877Speter 728251877Speter return status; 729251877Speter } 730251877Speter 731251877Speter if (BIO_should_retry(ctx->bio) && BIO_should_write(ctx->bio)) { 732251877Speter serf__log(SSL_VERBOSE, __FILE__, 733251877Speter "ssl_encrypt: %d %d %d (should write exit)\n", 734251877Speter status, *len, BIO_get_retry_flags(ctx->bio)); 735251877Speter 736251877Speter return APR_EAGAIN; 737251877Speter } 738251877Speter 739251877Speter /* If we were previously blocked, unblock ourselves now. */ 740251877Speter if (BIO_should_read(ctx->bio)) { 741251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: reset %d %d (%d %d %d)\n", 742251877Speter status, ctx->encrypt.status, 743251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 744251877Speter BIO_get_retry_flags(ctx->bio)); 745251877Speter 746251877Speter ctx->encrypt.status = APR_SUCCESS; 747251877Speter ctx->encrypt.exhausted_reset = 0; 748251877Speter } 749251877Speter 750251877Speter /* Oh well, read from our stream now. */ 751251877Speter interim_bufsize = bufsize; 752251877Speter do { 753251877Speter apr_size_t interim_len; 754251877Speter 755251877Speter if (!ctx->encrypt.status) { 756251877Speter struct iovec vecs[64]; 757251877Speter int vecs_read; 758251877Speter 759251877Speter status = serf_bucket_read_iovec(ctx->encrypt.stream, 760251877Speter interim_bufsize, 64, vecs, 761251877Speter &vecs_read); 762251877Speter 763251877Speter if (!SERF_BUCKET_READ_ERROR(status) && vecs_read) { 764251877Speter char *vecs_data; 765251877Speter int i, cur, vecs_data_len; 766251877Speter int ssl_len; 767251877Speter 768251877Speter /* Combine the buffers of the iovec into one buffer, as 769251877Speter that is with SSL_write requires. */ 770251877Speter vecs_data_len = 0; 771251877Speter for (i = 0; i < vecs_read; i++) { 772251877Speter vecs_data_len += vecs[i].iov_len; 773251877Speter } 774251877Speter 775251877Speter vecs_data = serf_bucket_mem_alloc(ctx->allocator, 776251877Speter vecs_data_len); 777251877Speter 778251877Speter cur = 0; 779251877Speter for (i = 0; i < vecs_read; i++) { 780251877Speter memcpy(vecs_data + cur, vecs[i].iov_base, vecs[i].iov_len); 781251877Speter cur += vecs[i].iov_len; 782251877Speter } 783251877Speter 784251877Speter interim_bufsize -= vecs_data_len; 785251877Speter interim_len = vecs_data_len; 786251877Speter 787251877Speter serf__log(SSL_VERBOSE, __FILE__, 788251877Speter "ssl_encrypt: bucket read %d bytes; "\ 789251877Speter "status %d\n", interim_len, status); 790251877Speter serf__log(SSL_MSG_VERBOSE, __FILE__, "---\n%.*s\n-(%d)-\n", 791251877Speter interim_len, vecs_data, interim_len); 792251877Speter 793251877Speter /* Stash our status away. */ 794251877Speter ctx->encrypt.status = status; 795251877Speter 796251877Speter ssl_len = SSL_write(ctx->ssl, vecs_data, interim_len); 797251877Speter 798251877Speter serf__log(SSL_VERBOSE, __FILE__, 799251877Speter "ssl_encrypt: SSL write: %d\n", ssl_len); 800251877Speter 801251877Speter /* If we failed to write... */ 802251877Speter if (ssl_len < 0) { 803251877Speter int ssl_err; 804251877Speter 805253895Speter /* Ah, bugger. We need to put that data back. 806253895Speter Note: use the copy here, we do not own the original iovec 807253895Speter data buffer so it will be freed on next read. */ 808253895Speter serf_bucket_t *vecs_copy = 809253895Speter serf_bucket_simple_own_create(vecs_data, 810253895Speter vecs_data_len, 811253895Speter ctx->allocator); 812253895Speter serf_bucket_aggregate_prepend(ctx->encrypt.stream, 813253895Speter vecs_copy); 814251877Speter 815251877Speter ssl_err = SSL_get_error(ctx->ssl, ssl_len); 816251877Speter 817251877Speter serf__log(SSL_VERBOSE, __FILE__, 818251877Speter "ssl_encrypt: SSL write error: %d\n", ssl_err); 819251877Speter 820251877Speter if (ssl_err == SSL_ERROR_SYSCALL) { 821253895Speter /* Return the underlying network error that caused OpenSSL 822253895Speter to fail. ### This can be a decrypt error! */ 823251877Speter status = ctx->encrypt.status; 824251877Speter if (SERF_BUCKET_READ_ERROR(status)) { 825251877Speter return status; 826251877Speter } 827251877Speter } 828251877Speter else { 829251877Speter /* Oh, no. */ 830251877Speter if (ssl_err == SSL_ERROR_WANT_READ) { 831251877Speter status = SERF_ERROR_WAIT_CONN; 832251877Speter } 833251877Speter else { 834253895Speter ctx->fatal_err = status = 835253895Speter SERF_ERROR_SSL_COMM_FAILED; 836251877Speter } 837251877Speter } 838251877Speter 839251877Speter serf__log(SSL_VERBOSE, __FILE__, 840251877Speter "ssl_encrypt: SSL write error: %d %d\n", 841251877Speter status, *len); 842253895Speter } else { 843253895Speter /* We're done with this data. */ 844253895Speter serf_bucket_mem_free(ctx->allocator, vecs_data); 845251877Speter } 846251877Speter } 847251877Speter } 848251877Speter else { 849251877Speter interim_len = 0; 850251877Speter *len = 0; 851251877Speter status = ctx->encrypt.status; 852251877Speter } 853251877Speter 854251877Speter } while (!status && interim_bufsize); 855251877Speter 856251877Speter /* Okay, we exhausted our underlying stream. */ 857251877Speter if (!SERF_BUCKET_READ_ERROR(status)) { 858251877Speter apr_status_t agg_status; 859251877Speter struct iovec vecs[64]; 860251877Speter int vecs_read, i; 861251877Speter 862251877Speter /* We read something! */ 863251877Speter agg_status = serf_bucket_read_iovec(ctx->encrypt.pending, bufsize, 864251877Speter 64, vecs, &vecs_read); 865251877Speter *len = 0; 866251877Speter for (i = 0; i < vecs_read; i++) { 867251877Speter memcpy(buf + *len, vecs[i].iov_base, vecs[i].iov_len); 868251877Speter *len += vecs[i].iov_len; 869251877Speter } 870251877Speter 871251877Speter serf__log(SSL_VERBOSE, __FILE__, 872251877Speter "ssl_encrypt read agg: %d %d %d %d\n", status, agg_status, 873251877Speter ctx->encrypt.status, *len); 874251877Speter 875251877Speter if (!agg_status) { 876251877Speter status = agg_status; 877251877Speter } 878251877Speter } 879251877Speter 880251877Speter if (status == SERF_ERROR_WAIT_CONN 881251877Speter && BIO_should_retry(ctx->bio) && BIO_should_read(ctx->bio)) { 882251877Speter ctx->encrypt.exhausted = ctx->encrypt.status; 883251877Speter ctx->encrypt.status = SERF_ERROR_WAIT_CONN; 884251877Speter } 885251877Speter 886251877Speter serf__log(SSL_VERBOSE, __FILE__, 887251877Speter "ssl_encrypt finished: %d %d (%d %d %d)\n", status, *len, 888251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 889251877Speter BIO_get_retry_flags(ctx->bio)); 890251877Speter 891251877Speter return status; 892251877Speter} 893251877Speter 894251877Speter#if APR_HAS_THREADS 895251877Speterstatic apr_pool_t *ssl_pool; 896251877Speterstatic apr_thread_mutex_t **ssl_locks; 897251877Speter 898251877Spetertypedef struct CRYPTO_dynlock_value { 899251877Speter apr_thread_mutex_t *lock; 900251877Speter} CRYPTO_dynlock_value; 901251877Speter 902251877Speterstatic CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line) 903251877Speter{ 904251877Speter CRYPTO_dynlock_value *l; 905251877Speter apr_status_t rv; 906251877Speter 907251877Speter l = apr_palloc(ssl_pool, sizeof(CRYPTO_dynlock_value)); 908251877Speter rv = apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, ssl_pool); 909251877Speter if (rv != APR_SUCCESS) { 910251877Speter /* FIXME: return error here */ 911251877Speter } 912251877Speter return l; 913251877Speter} 914251877Speter 915251877Speterstatic void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file, 916251877Speter int line) 917251877Speter{ 918251877Speter if (mode & CRYPTO_LOCK) { 919251877Speter apr_thread_mutex_lock(l->lock); 920251877Speter } 921251877Speter else if (mode & CRYPTO_UNLOCK) { 922251877Speter apr_thread_mutex_unlock(l->lock); 923251877Speter } 924251877Speter} 925251877Speter 926251877Speterstatic void ssl_dyn_destroy(CRYPTO_dynlock_value *l, const char *file, 927251877Speter int line) 928251877Speter{ 929251877Speter apr_thread_mutex_destroy(l->lock); 930251877Speter} 931251877Speter 932251877Speterstatic void ssl_lock(int mode, int n, const char *file, int line) 933251877Speter{ 934251877Speter if (mode & CRYPTO_LOCK) { 935251877Speter apr_thread_mutex_lock(ssl_locks[n]); 936251877Speter } 937251877Speter else if (mode & CRYPTO_UNLOCK) { 938251877Speter apr_thread_mutex_unlock(ssl_locks[n]); 939251877Speter } 940251877Speter} 941251877Speter 942251877Speterstatic unsigned long ssl_id(void) 943251877Speter{ 944251877Speter /* FIXME: This is lame and not portable. -aaron */ 945251877Speter return (unsigned long) apr_os_thread_current(); 946251877Speter} 947251877Speter 948251877Speterstatic apr_status_t cleanup_ssl(void *data) 949251877Speter{ 950251877Speter CRYPTO_set_locking_callback(NULL); 951251877Speter CRYPTO_set_id_callback(NULL); 952251877Speter CRYPTO_set_dynlock_create_callback(NULL); 953251877Speter CRYPTO_set_dynlock_lock_callback(NULL); 954251877Speter CRYPTO_set_dynlock_destroy_callback(NULL); 955251877Speter 956251877Speter return APR_SUCCESS; 957251877Speter} 958251877Speter 959251877Speter#endif 960251877Speter 961251877Speterstatic apr_uint32_t have_init_ssl = 0; 962251877Speter 963251877Speterstatic void init_ssl_libraries(void) 964251877Speter{ 965251877Speter apr_uint32_t val; 966251877Speter#if APR_VERSION_AT_LEAST(1,0,0) 967251877Speter val = apr_atomic_xchg32(&have_init_ssl, 1); 968251877Speter#else 969251877Speter val = apr_atomic_cas(&have_init_ssl, 1, 0); 970251877Speter#endif 971251877Speter 972251877Speter if (!val) { 973251877Speter#if APR_HAS_THREADS 974251877Speter int i, numlocks; 975251877Speter#endif 976251877Speter 977251877Speter#ifdef SSL_VERBOSE 978251877Speter /* Warn when compile-time and run-time version of OpenSSL differ in 979251877Speter major/minor version number. */ 980251877Speter long libver = SSLeay(); 981251877Speter 982251877Speter if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) { 983251877Speter serf__log(SSL_VERBOSE, __FILE__, 984251877Speter "Warning: OpenSSL library version mismatch, compile-time " 985251877Speter "was %lx, runtime is %lx.\n", 986251877Speter OPENSSL_VERSION_NUMBER, libver); 987251877Speter } 988251877Speter#endif 989251877Speter 990251877Speter CRYPTO_malloc_init(); 991251877Speter ERR_load_crypto_strings(); 992251877Speter SSL_load_error_strings(); 993251877Speter SSL_library_init(); 994251877Speter OpenSSL_add_all_algorithms(); 995251877Speter 996251877Speter#if APR_HAS_THREADS 997251877Speter numlocks = CRYPTO_num_locks(); 998251877Speter apr_pool_create(&ssl_pool, NULL); 999251877Speter ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks); 1000251877Speter for (i = 0; i < numlocks; i++) { 1001251877Speter apr_status_t rv; 1002251877Speter 1003251877Speter /* Intraprocess locks don't /need/ a filename... */ 1004251877Speter rv = apr_thread_mutex_create(&ssl_locks[i], 1005251877Speter APR_THREAD_MUTEX_DEFAULT, ssl_pool); 1006251877Speter if (rv != APR_SUCCESS) { 1007251877Speter /* FIXME: error out here */ 1008251877Speter } 1009251877Speter } 1010251877Speter CRYPTO_set_locking_callback(ssl_lock); 1011251877Speter CRYPTO_set_id_callback(ssl_id); 1012251877Speter CRYPTO_set_dynlock_create_callback(ssl_dyn_create); 1013251877Speter CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock); 1014251877Speter CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy); 1015251877Speter 1016251877Speter apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl); 1017251877Speter#endif 1018251877Speter } 1019251877Speter} 1020251877Speter 1021251877Speterstatic int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey) 1022251877Speter{ 1023251877Speter serf_ssl_context_t *ctx = SSL_get_app_data(ssl); 1024251877Speter apr_status_t status; 1025251877Speter 1026251877Speter if (ctx->cached_cert) { 1027251877Speter *cert = ctx->cached_cert; 1028251877Speter *pkey = ctx->cached_cert_pw; 1029251877Speter return 1; 1030251877Speter } 1031251877Speter 1032251877Speter while (ctx->cert_callback) { 1033251877Speter const char *cert_path; 1034251877Speter apr_file_t *cert_file; 1035251877Speter BIO *bio; 1036251877Speter PKCS12 *p12; 1037251877Speter int i; 1038251877Speter int retrying_success = 0; 1039251877Speter 1040251877Speter if (ctx->cert_file_success) { 1041251877Speter status = APR_SUCCESS; 1042251877Speter cert_path = ctx->cert_file_success; 1043251877Speter ctx->cert_file_success = NULL; 1044251877Speter retrying_success = 1; 1045251877Speter } else { 1046251877Speter status = ctx->cert_callback(ctx->cert_userdata, &cert_path); 1047251877Speter } 1048251877Speter 1049251877Speter if (status || !cert_path) { 1050253895Speter break; 1051251877Speter } 1052251877Speter 1053251877Speter /* Load the x.509 cert file stored in PKCS12 */ 1054251877Speter status = apr_file_open(&cert_file, cert_path, APR_READ, APR_OS_DEFAULT, 1055251877Speter ctx->pool); 1056251877Speter 1057251877Speter if (status) { 1058251877Speter continue; 1059251877Speter } 1060251877Speter 1061251877Speter bio = BIO_new(&bio_file_method); 1062251877Speter bio->ptr = cert_file; 1063251877Speter 1064251877Speter ctx->cert_path = cert_path; 1065251877Speter p12 = d2i_PKCS12_bio(bio, NULL); 1066251877Speter apr_file_close(cert_file); 1067251877Speter 1068251877Speter i = PKCS12_parse(p12, NULL, pkey, cert, NULL); 1069251877Speter 1070251877Speter if (i == 1) { 1071251877Speter PKCS12_free(p12); 1072251877Speter ctx->cached_cert = *cert; 1073251877Speter ctx->cached_cert_pw = *pkey; 1074251877Speter if (!retrying_success && ctx->cert_cache_pool) { 1075251877Speter const char *c; 1076251877Speter 1077251877Speter c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path); 1078251877Speter 1079251877Speter apr_pool_userdata_setn(c, "serf:ssl:cert", 1080251877Speter apr_pool_cleanup_null, 1081251877Speter ctx->cert_cache_pool); 1082251877Speter } 1083251877Speter return 1; 1084251877Speter } 1085251877Speter else { 1086251877Speter int err = ERR_get_error(); 1087251877Speter ERR_clear_error(); 1088251877Speter if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 && 1089251877Speter ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) { 1090251877Speter if (ctx->cert_pw_callback) { 1091251877Speter const char *password; 1092251877Speter 1093251877Speter if (ctx->cert_pw_success) { 1094251877Speter status = APR_SUCCESS; 1095251877Speter password = ctx->cert_pw_success; 1096251877Speter ctx->cert_pw_success = NULL; 1097251877Speter } else { 1098251877Speter status = ctx->cert_pw_callback(ctx->cert_pw_userdata, 1099251877Speter ctx->cert_path, 1100251877Speter &password); 1101251877Speter } 1102251877Speter 1103251877Speter if (!status && password) { 1104251877Speter i = PKCS12_parse(p12, password, pkey, cert, NULL); 1105251877Speter if (i == 1) { 1106251877Speter PKCS12_free(p12); 1107251877Speter ctx->cached_cert = *cert; 1108251877Speter ctx->cached_cert_pw = *pkey; 1109251877Speter if (!retrying_success && ctx->cert_cache_pool) { 1110251877Speter const char *c; 1111251877Speter 1112251877Speter c = apr_pstrdup(ctx->cert_cache_pool, 1113251877Speter ctx->cert_path); 1114251877Speter 1115251877Speter apr_pool_userdata_setn(c, "serf:ssl:cert", 1116251877Speter apr_pool_cleanup_null, 1117251877Speter ctx->cert_cache_pool); 1118251877Speter } 1119251877Speter if (!retrying_success && ctx->cert_pw_cache_pool) { 1120251877Speter const char *c; 1121251877Speter 1122251877Speter c = apr_pstrdup(ctx->cert_pw_cache_pool, 1123251877Speter password); 1124251877Speter 1125251877Speter apr_pool_userdata_setn(c, "serf:ssl:certpw", 1126251877Speter apr_pool_cleanup_null, 1127251877Speter ctx->cert_pw_cache_pool); 1128251877Speter } 1129251877Speter return 1; 1130251877Speter } 1131251877Speter } 1132251877Speter } 1133251877Speter PKCS12_free(p12); 1134251877Speter return 0; 1135251877Speter } 1136251877Speter else { 1137251877Speter printf("OpenSSL cert error: %d %d %d\n", ERR_GET_LIB(err), 1138251877Speter ERR_GET_FUNC(err), 1139251877Speter ERR_GET_REASON(err)); 1140251877Speter PKCS12_free(p12); 1141251877Speter } 1142251877Speter } 1143251877Speter } 1144251877Speter 1145251877Speter return 0; 1146251877Speter} 1147251877Speter 1148251877Speter 1149251877Spetervoid serf_ssl_client_cert_provider_set( 1150251877Speter serf_ssl_context_t *context, 1151251877Speter serf_ssl_need_client_cert_t callback, 1152251877Speter void *data, 1153251877Speter void *cache_pool) 1154251877Speter{ 1155251877Speter context->cert_callback = callback; 1156251877Speter context->cert_userdata = data; 1157251877Speter context->cert_cache_pool = cache_pool; 1158251877Speter if (context->cert_cache_pool) { 1159251877Speter apr_pool_userdata_get((void**)&context->cert_file_success, 1160251877Speter "serf:ssl:cert", cache_pool); 1161251877Speter } 1162251877Speter} 1163251877Speter 1164251877Speter 1165251877Spetervoid serf_ssl_client_cert_password_set( 1166251877Speter serf_ssl_context_t *context, 1167251877Speter serf_ssl_need_cert_password_t callback, 1168251877Speter void *data, 1169251877Speter void *cache_pool) 1170251877Speter{ 1171251877Speter context->cert_pw_callback = callback; 1172251877Speter context->cert_pw_userdata = data; 1173251877Speter context->cert_pw_cache_pool = cache_pool; 1174251877Speter if (context->cert_pw_cache_pool) { 1175251877Speter apr_pool_userdata_get((void**)&context->cert_pw_success, 1176251877Speter "serf:ssl:certpw", cache_pool); 1177251877Speter } 1178251877Speter} 1179251877Speter 1180251877Speter 1181251877Spetervoid serf_ssl_server_cert_callback_set( 1182251877Speter serf_ssl_context_t *context, 1183251877Speter serf_ssl_need_server_cert_t callback, 1184251877Speter void *data) 1185251877Speter{ 1186251877Speter context->server_cert_callback = callback; 1187251877Speter context->server_cert_userdata = data; 1188251877Speter} 1189251877Speter 1190251877Spetervoid serf_ssl_server_cert_chain_callback_set( 1191251877Speter serf_ssl_context_t *context, 1192251877Speter serf_ssl_need_server_cert_t cert_callback, 1193251877Speter serf_ssl_server_cert_chain_cb_t cert_chain_callback, 1194251877Speter void *data) 1195251877Speter{ 1196251877Speter context->server_cert_callback = cert_callback; 1197251877Speter context->server_cert_chain_callback = cert_chain_callback; 1198251877Speter context->server_cert_userdata = data; 1199251877Speter} 1200251877Speter 1201251877Speterstatic serf_ssl_context_t *ssl_init_context(void) 1202251877Speter{ 1203251877Speter serf_ssl_context_t *ssl_ctx; 1204251877Speter apr_pool_t *pool; 1205251877Speter serf_bucket_alloc_t *allocator; 1206251877Speter 1207251877Speter init_ssl_libraries(); 1208251877Speter 1209251877Speter apr_pool_create(&pool, NULL); 1210251877Speter allocator = serf_bucket_allocator_create(pool, NULL, NULL); 1211251877Speter 1212251877Speter ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx)); 1213251877Speter 1214251877Speter ssl_ctx->refcount = 0; 1215251877Speter ssl_ctx->pool = pool; 1216251877Speter ssl_ctx->allocator = allocator; 1217251877Speter 1218251877Speter ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method()); 1219251877Speter 1220251877Speter SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert); 1221251877Speter ssl_ctx->cached_cert = 0; 1222251877Speter ssl_ctx->cached_cert_pw = 0; 1223251877Speter ssl_ctx->pending_err = APR_SUCCESS; 1224251877Speter ssl_ctx->fatal_err = APR_SUCCESS; 1225251877Speter 1226251877Speter ssl_ctx->cert_callback = NULL; 1227251877Speter ssl_ctx->cert_pw_callback = NULL; 1228251877Speter ssl_ctx->server_cert_callback = NULL; 1229251877Speter ssl_ctx->server_cert_chain_callback = NULL; 1230251877Speter 1231251877Speter SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER, 1232251877Speter validate_server_certificate); 1233251877Speter SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL); 1234251877Speter /* Disable SSL compression by default. */ 1235251877Speter disable_compression(ssl_ctx); 1236251877Speter 1237251877Speter ssl_ctx->ssl = SSL_new(ssl_ctx->ctx); 1238251877Speter ssl_ctx->bio = BIO_new(&bio_bucket_method); 1239251877Speter ssl_ctx->bio->ptr = ssl_ctx; 1240251877Speter 1241251877Speter SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio); 1242251877Speter 1243251877Speter SSL_set_connect_state(ssl_ctx->ssl); 1244251877Speter 1245251877Speter SSL_set_app_data(ssl_ctx->ssl, ssl_ctx); 1246251877Speter 1247251877Speter#if SSL_VERBOSE 1248251877Speter SSL_CTX_set_info_callback(ssl_ctx->ctx, apps_ssl_info_callback); 1249251877Speter#endif 1250251877Speter 1251251877Speter ssl_ctx->encrypt.stream = NULL; 1252251877Speter ssl_ctx->encrypt.stream_next = NULL; 1253251877Speter ssl_ctx->encrypt.pending = serf_bucket_aggregate_create(allocator); 1254251877Speter ssl_ctx->encrypt.status = APR_SUCCESS; 1255251877Speter serf_databuf_init(&ssl_ctx->encrypt.databuf); 1256251877Speter ssl_ctx->encrypt.databuf.read = ssl_encrypt; 1257251877Speter ssl_ctx->encrypt.databuf.read_baton = ssl_ctx; 1258251877Speter 1259251877Speter ssl_ctx->decrypt.stream = NULL; 1260251877Speter ssl_ctx->decrypt.pending = serf_bucket_aggregate_create(allocator); 1261251877Speter ssl_ctx->decrypt.status = APR_SUCCESS; 1262251877Speter serf_databuf_init(&ssl_ctx->decrypt.databuf); 1263251877Speter ssl_ctx->decrypt.databuf.read = ssl_decrypt; 1264251877Speter ssl_ctx->decrypt.databuf.read_baton = ssl_ctx; 1265251877Speter 1266251877Speter return ssl_ctx; 1267251877Speter} 1268251877Speter 1269251877Speterstatic apr_status_t ssl_free_context( 1270251877Speter serf_ssl_context_t *ssl_ctx) 1271251877Speter{ 1272251877Speter apr_pool_t *p; 1273251877Speter 1274251877Speter /* If never had the pending buckets, don't try to free them. */ 1275251877Speter if (ssl_ctx->decrypt.pending != NULL) { 1276251877Speter serf_bucket_destroy(ssl_ctx->decrypt.pending); 1277251877Speter } 1278251877Speter if (ssl_ctx->encrypt.pending != NULL) { 1279251877Speter serf_bucket_destroy(ssl_ctx->encrypt.pending); 1280251877Speter } 1281251877Speter 1282251877Speter /* SSL_free implicitly frees the underlying BIO. */ 1283251877Speter SSL_free(ssl_ctx->ssl); 1284251877Speter SSL_CTX_free(ssl_ctx->ctx); 1285251877Speter 1286251877Speter p = ssl_ctx->pool; 1287251877Speter 1288251877Speter serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx); 1289251877Speter apr_pool_destroy(p); 1290251877Speter 1291251877Speter return APR_SUCCESS; 1292251877Speter} 1293251877Speter 1294251877Speterstatic serf_bucket_t * serf_bucket_ssl_create( 1295251877Speter serf_ssl_context_t *ssl_ctx, 1296251877Speter serf_bucket_alloc_t *allocator, 1297251877Speter const serf_bucket_type_t *type) 1298251877Speter{ 1299251877Speter ssl_context_t *ctx; 1300251877Speter 1301251877Speter ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 1302251877Speter if (!ssl_ctx) { 1303251877Speter ctx->ssl_ctx = ssl_init_context(); 1304251877Speter } 1305251877Speter else { 1306251877Speter ctx->ssl_ctx = ssl_ctx; 1307251877Speter } 1308251877Speter ctx->ssl_ctx->refcount++; 1309251877Speter 1310251877Speter return serf_bucket_create(type, allocator, ctx); 1311251877Speter} 1312251877Speter 1313251877Speterapr_status_t serf_ssl_set_hostname(serf_ssl_context_t *context, 1314251877Speter const char * hostname) 1315251877Speter{ 1316251877Speter#ifdef SSL_set_tlsext_host_name 1317251877Speter if (SSL_set_tlsext_host_name(context->ssl, hostname) != 1) { 1318251877Speter ERR_clear_error(); 1319251877Speter } 1320251877Speter#endif 1321251877Speter return APR_SUCCESS; 1322251877Speter} 1323251877Speter 1324251877Speterapr_status_t serf_ssl_use_default_certificates(serf_ssl_context_t *ssl_ctx) 1325251877Speter{ 1326251877Speter X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx); 1327251877Speter 1328251877Speter int result = X509_STORE_set_default_paths(store); 1329251877Speter 1330251877Speter return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED; 1331251877Speter} 1332251877Speter 1333251877Speterapr_status_t serf_ssl_load_cert_file( 1334251877Speter serf_ssl_certificate_t **cert, 1335251877Speter const char *file_path, 1336251877Speter apr_pool_t *pool) 1337251877Speter{ 1338251877Speter FILE *fp = fopen(file_path, "r"); 1339253895Speter 1340251877Speter if (fp) { 1341251877Speter X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL); 1342251877Speter fclose(fp); 1343251877Speter 1344251877Speter if (ssl_cert) { 1345251877Speter *cert = apr_palloc(pool, sizeof(serf_ssl_certificate_t)); 1346251877Speter (*cert)->ssl_cert = ssl_cert; 1347251877Speter 1348251877Speter return APR_SUCCESS; 1349251877Speter } 1350251877Speter } 1351251877Speter 1352251877Speter return SERF_ERROR_SSL_CERT_FAILED; 1353251877Speter} 1354251877Speter 1355251877Speter 1356251877Speterapr_status_t serf_ssl_trust_cert( 1357251877Speter serf_ssl_context_t *ssl_ctx, 1358251877Speter serf_ssl_certificate_t *cert) 1359251877Speter{ 1360251877Speter X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx); 1361251877Speter 1362251877Speter int result = X509_STORE_add_cert(store, cert->ssl_cert); 1363251877Speter 1364251877Speter return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED; 1365251877Speter} 1366251877Speter 1367251877Speter 1368251877Speterserf_bucket_t *serf_bucket_ssl_decrypt_create( 1369251877Speter serf_bucket_t *stream, 1370251877Speter serf_ssl_context_t *ssl_ctx, 1371251877Speter serf_bucket_alloc_t *allocator) 1372251877Speter{ 1373251877Speter serf_bucket_t *bkt; 1374251877Speter ssl_context_t *ctx; 1375251877Speter 1376251877Speter bkt = serf_bucket_ssl_create(ssl_ctx, allocator, 1377251877Speter &serf_bucket_type_ssl_decrypt); 1378251877Speter 1379251877Speter ctx = bkt->data; 1380251877Speter 1381251877Speter ctx->databuf = &ctx->ssl_ctx->decrypt.databuf; 1382251877Speter if (ctx->ssl_ctx->decrypt.stream != NULL) { 1383251877Speter return NULL; 1384251877Speter } 1385251877Speter ctx->ssl_ctx->decrypt.stream = stream; 1386251877Speter ctx->our_stream = &ctx->ssl_ctx->decrypt.stream; 1387251877Speter 1388251877Speter return bkt; 1389251877Speter} 1390251877Speter 1391251877Speter 1392251877Speterserf_ssl_context_t *serf_bucket_ssl_decrypt_context_get( 1393251877Speter serf_bucket_t *bucket) 1394251877Speter{ 1395251877Speter ssl_context_t *ctx = bucket->data; 1396251877Speter return ctx->ssl_ctx; 1397251877Speter} 1398251877Speter 1399251877Speter 1400251877Speterserf_bucket_t *serf_bucket_ssl_encrypt_create( 1401251877Speter serf_bucket_t *stream, 1402251877Speter serf_ssl_context_t *ssl_ctx, 1403251877Speter serf_bucket_alloc_t *allocator) 1404251877Speter{ 1405251877Speter serf_bucket_t *bkt; 1406251877Speter ssl_context_t *ctx; 1407251877Speter 1408251877Speter bkt = serf_bucket_ssl_create(ssl_ctx, allocator, 1409251877Speter &serf_bucket_type_ssl_encrypt); 1410251877Speter 1411251877Speter ctx = bkt->data; 1412251877Speter 1413251877Speter ctx->databuf = &ctx->ssl_ctx->encrypt.databuf; 1414251877Speter ctx->our_stream = &ctx->ssl_ctx->encrypt.stream; 1415251877Speter if (ctx->ssl_ctx->encrypt.stream == NULL) { 1416251877Speter serf_bucket_t *tmp = serf_bucket_aggregate_create(stream->allocator); 1417251877Speter serf_bucket_aggregate_append(tmp, stream); 1418251877Speter ctx->ssl_ctx->encrypt.stream = tmp; 1419251877Speter } 1420251877Speter else { 1421251877Speter bucket_list_t *new_list; 1422251877Speter 1423251877Speter new_list = serf_bucket_mem_alloc(ctx->ssl_ctx->allocator, 1424251877Speter sizeof(*new_list)); 1425251877Speter new_list->bucket = stream; 1426251877Speter new_list->next = NULL; 1427251877Speter if (ctx->ssl_ctx->encrypt.stream_next == NULL) { 1428251877Speter ctx->ssl_ctx->encrypt.stream_next = new_list; 1429251877Speter } 1430251877Speter else { 1431251877Speter bucket_list_t *scan = ctx->ssl_ctx->encrypt.stream_next; 1432251877Speter 1433251877Speter while (scan->next != NULL) 1434251877Speter scan = scan->next; 1435251877Speter scan->next = new_list; 1436251877Speter } 1437251877Speter } 1438251877Speter 1439251877Speter return bkt; 1440251877Speter} 1441251877Speter 1442251877Speter 1443251877Speterserf_ssl_context_t *serf_bucket_ssl_encrypt_context_get( 1444251877Speter serf_bucket_t *bucket) 1445251877Speter{ 1446251877Speter ssl_context_t *ctx = bucket->data; 1447251877Speter return ctx->ssl_ctx; 1448251877Speter} 1449251877Speter 1450251877Speter/* Functions to read a serf_ssl_certificate structure. */ 1451251877Speter 1452251877Speter/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */ 1453251877Speterstatic apr_hash_t * 1454251877Speterconvert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool) 1455251877Speter{ 1456251877Speter char buf[1024]; 1457251877Speter int ret; 1458251877Speter 1459251877Speter apr_hash_t *tgt = apr_hash_make(pool); 1460251877Speter 1461251877Speter ret = X509_NAME_get_text_by_NID(org, 1462251877Speter NID_commonName, 1463251877Speter buf, 1024); 1464251877Speter if (ret != -1) 1465251877Speter apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); 1466251877Speter ret = X509_NAME_get_text_by_NID(org, 1467251877Speter NID_pkcs9_emailAddress, 1468251877Speter buf, 1024); 1469251877Speter if (ret != -1) 1470251877Speter apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); 1471251877Speter ret = X509_NAME_get_text_by_NID(org, 1472251877Speter NID_organizationalUnitName, 1473251877Speter buf, 1024); 1474251877Speter if (ret != -1) 1475251877Speter apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); 1476251877Speter ret = X509_NAME_get_text_by_NID(org, 1477251877Speter NID_organizationName, 1478251877Speter buf, 1024); 1479251877Speter if (ret != -1) 1480251877Speter apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); 1481251877Speter ret = X509_NAME_get_text_by_NID(org, 1482251877Speter NID_localityName, 1483251877Speter buf, 1024); 1484251877Speter if (ret != -1) 1485251877Speter apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); 1486251877Speter ret = X509_NAME_get_text_by_NID(org, 1487251877Speter NID_stateOrProvinceName, 1488251877Speter buf, 1024); 1489251877Speter if (ret != -1) 1490251877Speter apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); 1491251877Speter ret = X509_NAME_get_text_by_NID(org, 1492251877Speter NID_countryName, 1493251877Speter buf, 1024); 1494251877Speter if (ret != -1) 1495251877Speter apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); 1496251877Speter 1497251877Speter return tgt; 1498251877Speter} 1499251877Speter 1500251877Speter 1501251877Speterint serf_ssl_cert_depth(const serf_ssl_certificate_t *cert) 1502251877Speter{ 1503251877Speter return cert->depth; 1504251877Speter} 1505251877Speter 1506251877Speter 1507251877Speterapr_hash_t *serf_ssl_cert_issuer( 1508251877Speter const serf_ssl_certificate_t *cert, 1509251877Speter apr_pool_t *pool) 1510251877Speter{ 1511251877Speter X509_NAME *issuer = X509_get_issuer_name(cert->ssl_cert); 1512251877Speter 1513251877Speter if (!issuer) 1514251877Speter return NULL; 1515251877Speter 1516251877Speter return convert_X509_NAME_to_table(issuer, pool); 1517251877Speter} 1518251877Speter 1519251877Speter 1520251877Speterapr_hash_t *serf_ssl_cert_subject( 1521251877Speter const serf_ssl_certificate_t *cert, 1522251877Speter apr_pool_t *pool) 1523251877Speter{ 1524251877Speter X509_NAME *subject = X509_get_subject_name(cert->ssl_cert); 1525251877Speter 1526251877Speter if (!subject) 1527251877Speter return NULL; 1528251877Speter 1529251877Speter return convert_X509_NAME_to_table(subject, pool); 1530251877Speter} 1531251877Speter 1532251877Speter 1533251877Speterapr_hash_t *serf_ssl_cert_certificate( 1534251877Speter const serf_ssl_certificate_t *cert, 1535251877Speter apr_pool_t *pool) 1536251877Speter{ 1537251877Speter apr_hash_t *tgt = apr_hash_make(pool); 1538251877Speter unsigned int md_size, i; 1539251877Speter unsigned char md[EVP_MAX_MD_SIZE]; 1540251877Speter BIO *bio; 1541251877Speter STACK_OF(GENERAL_NAME) *names; 1542251877Speter 1543251877Speter /* sha1 fingerprint */ 1544251877Speter if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) { 1545251877Speter const char hex[] = "0123456789ABCDEF"; 1546251877Speter char fingerprint[EVP_MAX_MD_SIZE * 3]; 1547251877Speter 1548251877Speter for (i=0; i<md_size; i++) { 1549251877Speter fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4]; 1550251877Speter fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)]; 1551251877Speter fingerprint[(3*i)+2] = ':'; 1552251877Speter } 1553251877Speter if (md_size > 0) 1554251877Speter fingerprint[(3*(md_size-1))+2] = '\0'; 1555251877Speter else 1556251877Speter fingerprint[0] = '\0'; 1557251877Speter 1558251877Speter apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING, 1559251877Speter apr_pstrdup(pool, fingerprint)); 1560251877Speter } 1561251877Speter 1562251877Speter /* set expiry dates */ 1563251877Speter bio = BIO_new(BIO_s_mem()); 1564251877Speter if (bio) { 1565251877Speter ASN1_TIME *notBefore, *notAfter; 1566251877Speter char buf[256]; 1567251877Speter 1568251877Speter memset (buf, 0, sizeof (buf)); 1569251877Speter notBefore = X509_get_notBefore(cert->ssl_cert); 1570251877Speter if (ASN1_TIME_print(bio, notBefore)) { 1571251877Speter BIO_read(bio, buf, 255); 1572251877Speter apr_hash_set(tgt, "notBefore", APR_HASH_KEY_STRING, 1573251877Speter apr_pstrdup(pool, buf)); 1574251877Speter } 1575251877Speter memset (buf, 0, sizeof (buf)); 1576251877Speter notAfter = X509_get_notAfter(cert->ssl_cert); 1577251877Speter if (ASN1_TIME_print(bio, notAfter)) { 1578251877Speter BIO_read(bio, buf, 255); 1579251877Speter apr_hash_set(tgt, "notAfter", APR_HASH_KEY_STRING, 1580251877Speter apr_pstrdup(pool, buf)); 1581251877Speter } 1582251877Speter } 1583251877Speter BIO_free(bio); 1584251877Speter 1585251877Speter /* Get subjectAltNames */ 1586251877Speter names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL); 1587251877Speter if (names) { 1588251877Speter int names_count = sk_GENERAL_NAME_num(names); 1589251877Speter 1590251877Speter apr_array_header_t *san_arr = apr_array_make(pool, names_count, 1591251877Speter sizeof(char*)); 1592251877Speter apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr); 1593251877Speter for (i = 0; i < names_count; i++) { 1594251877Speter char *p = NULL; 1595251877Speter GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i); 1596251877Speter 1597251877Speter switch (nm->type) { 1598251877Speter case GEN_DNS: 1599251877Speter p = apr_pstrmemdup(pool, (const char *)nm->d.ia5->data, 1600251877Speter nm->d.ia5->length); 1601251877Speter break; 1602251877Speter default: 1603251877Speter /* Don't know what to do - skip. */ 1604251877Speter break; 1605251877Speter } 1606251877Speter if (p) { 1607251877Speter APR_ARRAY_PUSH(san_arr, char*) = p; 1608251877Speter } 1609251877Speter } 1610251877Speter sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); 1611251877Speter } 1612251877Speter 1613251877Speter return tgt; 1614251877Speter} 1615251877Speter 1616251877Speter 1617251877Speterconst char *serf_ssl_cert_export( 1618251877Speter const serf_ssl_certificate_t *cert, 1619251877Speter apr_pool_t *pool) 1620251877Speter{ 1621251877Speter char *binary_cert; 1622251877Speter char *encoded_cert; 1623251877Speter int len; 1624251877Speter unsigned char *unused; 1625251877Speter 1626251877Speter /* find the length of the DER encoding. */ 1627251877Speter len = i2d_X509(cert->ssl_cert, NULL); 1628251877Speter if (len < 0) { 1629251877Speter return NULL; 1630251877Speter } 1631251877Speter 1632251877Speter binary_cert = apr_palloc(pool, len); 1633251877Speter unused = (unsigned char *)binary_cert; 1634251877Speter len = i2d_X509(cert->ssl_cert, &unused); /* unused is incremented */ 1635251877Speter if (len < 0) { 1636251877Speter return NULL; 1637251877Speter } 1638251877Speter 1639251877Speter encoded_cert = apr_palloc(pool, apr_base64_encode_len(len)); 1640251877Speter apr_base64_encode(encoded_cert, binary_cert, len); 1641251877Speter 1642251877Speter return encoded_cert; 1643251877Speter} 1644251877Speter 1645251877Speter/* Disables compression for all SSL sessions. */ 1646251877Speterstatic void disable_compression(serf_ssl_context_t *ssl_ctx) 1647251877Speter{ 1648251877Speter#ifdef SSL_OP_NO_COMPRESSION 1649251877Speter SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_COMPRESSION); 1650251877Speter#endif 1651251877Speter} 1652251877Speter 1653251877Speterapr_status_t serf_ssl_use_compression(serf_ssl_context_t *ssl_ctx, int enabled) 1654251877Speter{ 1655251877Speter if (enabled) { 1656251877Speter#ifdef SSL_OP_NO_COMPRESSION 1657251877Speter SSL_clear_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION); 1658251877Speter return APR_SUCCESS; 1659251877Speter#endif 1660251877Speter } else { 1661251877Speter#ifdef SSL_OP_NO_COMPRESSION 1662251877Speter SSL_set_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION); 1663251877Speter return APR_SUCCESS; 1664251877Speter#endif 1665251877Speter } 1666251877Speter 1667251877Speter return APR_EGENERAL; 1668251877Speter} 1669251877Speter 1670251877Speterstatic void serf_ssl_destroy_and_data(serf_bucket_t *bucket) 1671251877Speter{ 1672251877Speter ssl_context_t *ctx = bucket->data; 1673251877Speter 1674251877Speter if (!--ctx->ssl_ctx->refcount) { 1675251877Speter ssl_free_context(ctx->ssl_ctx); 1676251877Speter } 1677251877Speter 1678251877Speter serf_default_destroy_and_data(bucket); 1679251877Speter} 1680251877Speter 1681251877Speterstatic void serf_ssl_decrypt_destroy_and_data(serf_bucket_t *bucket) 1682251877Speter{ 1683251877Speter ssl_context_t *ctx = bucket->data; 1684251877Speter 1685251877Speter serf_bucket_destroy(*ctx->our_stream); 1686251877Speter 1687251877Speter serf_ssl_destroy_and_data(bucket); 1688251877Speter} 1689251877Speter 1690251877Speterstatic void serf_ssl_encrypt_destroy_and_data(serf_bucket_t *bucket) 1691251877Speter{ 1692251877Speter ssl_context_t *ctx = bucket->data; 1693251877Speter serf_ssl_context_t *ssl_ctx = ctx->ssl_ctx; 1694251877Speter 1695251877Speter if (ssl_ctx->encrypt.stream == *ctx->our_stream) { 1696251877Speter serf_bucket_destroy(*ctx->our_stream); 1697251877Speter serf_bucket_destroy(ssl_ctx->encrypt.pending); 1698251877Speter 1699251877Speter /* Reset our encrypted status and databuf. */ 1700251877Speter ssl_ctx->encrypt.status = APR_SUCCESS; 1701251877Speter ssl_ctx->encrypt.databuf.status = APR_SUCCESS; 1702251877Speter 1703251877Speter /* Advance to the next stream - if we have one. */ 1704251877Speter if (ssl_ctx->encrypt.stream_next == NULL) { 1705251877Speter ssl_ctx->encrypt.stream = NULL; 1706251877Speter ssl_ctx->encrypt.pending = NULL; 1707251877Speter } 1708251877Speter else { 1709251877Speter bucket_list_t *cur; 1710251877Speter 1711251877Speter cur = ssl_ctx->encrypt.stream_next; 1712251877Speter ssl_ctx->encrypt.stream = cur->bucket; 1713251877Speter ssl_ctx->encrypt.pending = 1714251877Speter serf_bucket_aggregate_create(cur->bucket->allocator); 1715251877Speter ssl_ctx->encrypt.stream_next = cur->next; 1716251877Speter serf_bucket_mem_free(ssl_ctx->allocator, cur); 1717251877Speter } 1718251877Speter } 1719251877Speter else { 1720251877Speter /* Ah, darn. We haven't sent this one along yet. */ 1721251877Speter return; 1722251877Speter } 1723251877Speter serf_ssl_destroy_and_data(bucket); 1724251877Speter} 1725251877Speter 1726251877Speterstatic apr_status_t serf_ssl_read(serf_bucket_t *bucket, 1727251877Speter apr_size_t requested, 1728251877Speter const char **data, apr_size_t *len) 1729251877Speter{ 1730251877Speter ssl_context_t *ctx = bucket->data; 1731251877Speter 1732251877Speter return serf_databuf_read(ctx->databuf, requested, data, len); 1733251877Speter} 1734251877Speter 1735251877Speterstatic apr_status_t serf_ssl_readline(serf_bucket_t *bucket, 1736251877Speter int acceptable, int *found, 1737251877Speter const char **data, 1738251877Speter apr_size_t *len) 1739251877Speter{ 1740251877Speter ssl_context_t *ctx = bucket->data; 1741251877Speter 1742251877Speter return serf_databuf_readline(ctx->databuf, acceptable, found, data, len); 1743251877Speter} 1744251877Speter 1745251877Speterstatic apr_status_t serf_ssl_peek(serf_bucket_t *bucket, 1746251877Speter const char **data, 1747251877Speter apr_size_t *len) 1748251877Speter{ 1749251877Speter ssl_context_t *ctx = bucket->data; 1750251877Speter 1751251877Speter return serf_databuf_peek(ctx->databuf, data, len); 1752251877Speter} 1753251877Speter 1754251877Speter 1755251877Speterconst serf_bucket_type_t serf_bucket_type_ssl_encrypt = { 1756251877Speter "SSLENCRYPT", 1757251877Speter serf_ssl_read, 1758251877Speter serf_ssl_readline, 1759251877Speter serf_default_read_iovec, 1760251877Speter serf_default_read_for_sendfile, 1761251877Speter serf_default_read_bucket, 1762251877Speter serf_ssl_peek, 1763251877Speter serf_ssl_encrypt_destroy_and_data, 1764251877Speter}; 1765251877Speter 1766251877Speterconst serf_bucket_type_t serf_bucket_type_ssl_decrypt = { 1767251877Speter "SSLDECRYPT", 1768251877Speter serf_ssl_read, 1769251877Speter serf_ssl_readline, 1770251877Speter serf_default_read_iovec, 1771251877Speter serf_default_read_for_sendfile, 1772251877Speter serf_default_read_bucket, 1773251877Speter serf_ssl_peek, 1774251877Speter serf_ssl_decrypt_destroy_and_data, 1775251877Speter}; 1776