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); 205269847Speterstatic char * 206269847Speter pstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool); 207251877Speter 208251877Speter#if SSL_VERBOSE 209251877Speter/* Log all ssl alerts that we receive from the server. */ 210251877Speterstatic void 211251877Speterapps_ssl_info_callback(const SSL *s, int where, int ret) 212251877Speter{ 213251877Speter const char *str; 214251877Speter int w; 215251877Speter w = where & ~SSL_ST_MASK; 216253895Speter 217251877Speter if (w & SSL_ST_CONNECT) 218251877Speter str = "SSL_connect"; 219251877Speter else if (w & SSL_ST_ACCEPT) 220251877Speter str = "SSL_accept"; 221251877Speter else 222251877Speter str = "undefined"; 223253895Speter 224251877Speter if (where & SSL_CB_LOOP) { 225251877Speter serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str, 226251877Speter SSL_state_string_long(s)); 227251877Speter } 228251877Speter else if (where & SSL_CB_ALERT) { 229251877Speter str = (where & SSL_CB_READ) ? "read" : "write"; 230251877Speter serf__log(SSL_VERBOSE, __FILE__, "SSL3 alert %s:%s:%s\n", 231251877Speter str, 232251877Speter SSL_alert_type_string_long(ret), 233251877Speter SSL_alert_desc_string_long(ret)); 234251877Speter } 235251877Speter else if (where & SSL_CB_EXIT) { 236251877Speter if (ret == 0) 237251877Speter serf__log(SSL_VERBOSE, __FILE__, "%s:failed in %s\n", str, 238251877Speter SSL_state_string_long(s)); 239251877Speter else if (ret < 0) { 240251877Speter serf__log(SSL_VERBOSE, __FILE__, "%s:error in %s\n", str, 241251877Speter SSL_state_string_long(s)); 242251877Speter } 243251877Speter } 244251877Speter} 245251877Speter#endif 246251877Speter 247251877Speter/* Returns the amount read. */ 248251877Speterstatic int bio_bucket_read(BIO *bio, char *in, int inlen) 249251877Speter{ 250251877Speter serf_ssl_context_t *ctx = bio->ptr; 251251877Speter const char *data; 252251877Speter apr_status_t status; 253251877Speter apr_size_t len; 254251877Speter 255251877Speter serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read called for %d bytes\n", 256251877Speter inlen); 257251877Speter 258251877Speter if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN 259251877Speter && BIO_should_read(ctx->bio)) { 260253895Speter serf__log(SSL_VERBOSE, __FILE__, 261253895Speter "bio_bucket_read waiting: (%d %d %d)\n", 262251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 263251877Speter BIO_get_retry_flags(ctx->bio)); 264251877Speter /* Falling back... */ 265251877Speter ctx->encrypt.exhausted_reset = 1; 266251877Speter BIO_clear_retry_flags(bio); 267251877Speter } 268251877Speter 269251877Speter status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len); 270251877Speter 271251877Speter ctx->decrypt.status = status; 272251877Speter 273251877Speter serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read received %d bytes (%d)\n", 274251877Speter len, status); 275251877Speter 276251877Speter if (!SERF_BUCKET_READ_ERROR(status)) { 277251877Speter /* Oh suck. */ 278251877Speter if (len) { 279251877Speter memcpy(in, data, len); 280251877Speter return len; 281251877Speter } 282251877Speter if (APR_STATUS_IS_EOF(status)) { 283251877Speter BIO_set_retry_read(bio); 284251877Speter return -1; 285251877Speter } 286251877Speter } 287251877Speter 288251877Speter return -1; 289251877Speter} 290251877Speter 291251877Speter/* Returns the amount written. */ 292251877Speterstatic int bio_bucket_write(BIO *bio, const char *in, int inl) 293251877Speter{ 294251877Speter serf_ssl_context_t *ctx = bio->ptr; 295251877Speter serf_bucket_t *tmp; 296251877Speter 297251877Speter serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write called for %d bytes\n", 298251877Speter inl); 299251877Speter 300251877Speter if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN 301251877Speter && !BIO_should_read(ctx->bio)) { 302253895Speter serf__log(SSL_VERBOSE, __FILE__, 303253895Speter "bio_bucket_write waiting: (%d %d %d)\n", 304251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 305251877Speter BIO_get_retry_flags(ctx->bio)); 306251877Speter /* Falling back... */ 307251877Speter ctx->encrypt.exhausted_reset = 1; 308251877Speter BIO_clear_retry_flags(bio); 309251877Speter } 310251877Speter 311251877Speter tmp = serf_bucket_simple_copy_create(in, inl, 312251877Speter ctx->encrypt.pending->allocator); 313251877Speter 314251877Speter serf_bucket_aggregate_append(ctx->encrypt.pending, tmp); 315251877Speter 316251877Speter return inl; 317251877Speter} 318251877Speter 319251877Speter/* Returns the amount read. */ 320251877Speterstatic int bio_file_read(BIO *bio, char *in, int inlen) 321251877Speter{ 322251877Speter apr_file_t *file = bio->ptr; 323251877Speter apr_status_t status; 324251877Speter apr_size_t len; 325251877Speter 326251877Speter BIO_clear_retry_flags(bio); 327251877Speter 328251877Speter len = inlen; 329251877Speter status = apr_file_read(file, in, &len); 330251877Speter 331251877Speter if (!SERF_BUCKET_READ_ERROR(status)) { 332251877Speter /* Oh suck. */ 333251877Speter if (APR_STATUS_IS_EOF(status)) { 334251877Speter BIO_set_retry_read(bio); 335251877Speter return -1; 336251877Speter } else { 337251877Speter return len; 338251877Speter } 339251877Speter } 340251877Speter 341251877Speter return -1; 342251877Speter} 343251877Speter 344251877Speter/* Returns the amount written. */ 345251877Speterstatic int bio_file_write(BIO *bio, const char *in, int inl) 346251877Speter{ 347251877Speter apr_file_t *file = bio->ptr; 348251877Speter apr_size_t nbytes; 349251877Speter 350251877Speter BIO_clear_retry_flags(bio); 351251877Speter 352251877Speter nbytes = inl; 353251877Speter apr_file_write(file, in, &nbytes); 354251877Speter 355251877Speter return nbytes; 356251877Speter} 357251877Speter 358251877Speterstatic int bio_file_gets(BIO *bio, char *in, int inlen) 359251877Speter{ 360251877Speter return bio_file_read(bio, in, inlen); 361251877Speter} 362251877Speter 363251877Speterstatic int bio_bucket_create(BIO *bio) 364251877Speter{ 365251877Speter bio->shutdown = 1; 366251877Speter bio->init = 1; 367251877Speter bio->num = -1; 368251877Speter bio->ptr = NULL; 369251877Speter 370251877Speter return 1; 371251877Speter} 372251877Speter 373251877Speterstatic int bio_bucket_destroy(BIO *bio) 374251877Speter{ 375251877Speter /* Did we already free this? */ 376251877Speter if (bio == NULL) { 377251877Speter return 0; 378251877Speter } 379251877Speter 380251877Speter return 1; 381251877Speter} 382251877Speter 383251877Speterstatic long bio_bucket_ctrl(BIO *bio, int cmd, long num, void *ptr) 384251877Speter{ 385251877Speter long ret = 1; 386251877Speter 387251877Speter switch (cmd) { 388251877Speter default: 389251877Speter /* abort(); */ 390251877Speter break; 391251877Speter case BIO_CTRL_FLUSH: 392251877Speter /* At this point we can't force a flush. */ 393251877Speter break; 394251877Speter case BIO_CTRL_PUSH: 395251877Speter case BIO_CTRL_POP: 396251877Speter ret = 0; 397251877Speter break; 398251877Speter } 399251877Speter return ret; 400251877Speter} 401251877Speter 402251877Speterstatic BIO_METHOD bio_bucket_method = { 403251877Speter BIO_TYPE_MEM, 404251877Speter "Serf SSL encryption and decryption buckets", 405251877Speter bio_bucket_write, 406251877Speter bio_bucket_read, 407251877Speter NULL, /* Is this called? */ 408251877Speter NULL, /* Is this called? */ 409251877Speter bio_bucket_ctrl, 410251877Speter bio_bucket_create, 411251877Speter bio_bucket_destroy, 412251877Speter#ifdef OPENSSL_VERSION_NUMBER 413251877Speter NULL /* sslc does not have the callback_ctrl field */ 414251877Speter#endif 415251877Speter}; 416251877Speter 417251877Speterstatic BIO_METHOD bio_file_method = { 418251877Speter BIO_TYPE_FILE, 419251877Speter "Wrapper around APR file structures", 420251877Speter bio_file_write, 421251877Speter bio_file_read, 422251877Speter NULL, /* Is this called? */ 423251877Speter bio_file_gets, /* Is this called? */ 424251877Speter bio_bucket_ctrl, 425251877Speter bio_bucket_create, 426251877Speter bio_bucket_destroy, 427251877Speter#ifdef OPENSSL_VERSION_NUMBER 428251877Speter NULL /* sslc does not have the callback_ctrl field */ 429251877Speter#endif 430251877Speter}; 431251877Speter 432269847Spetertypedef enum san_copy_t { 433269847Speter EscapeNulAndCopy = 0, 434269847Speter ErrorOnNul = 1, 435269847Speter} san_copy_t; 436269847Speter 437269847Speter 438269847Speterstatic apr_status_t 439269847Speterget_subject_alt_names(apr_array_header_t **san_arr, X509 *ssl_cert, 440269847Speter san_copy_t copy_action, apr_pool_t *pool) 441269847Speter{ 442269847Speter STACK_OF(GENERAL_NAME) *names; 443269847Speter 444269847Speter /* assert: copy_action == ErrorOnNul || (san_arr && pool) */ 445269847Speter 446269847Speter if (san_arr) { 447269847Speter *san_arr = NULL; 448269847Speter } 449269847Speter 450269847Speter /* Get subjectAltNames */ 451269847Speter names = X509_get_ext_d2i(ssl_cert, NID_subject_alt_name, NULL, NULL); 452269847Speter if (names) { 453269847Speter int names_count = sk_GENERAL_NAME_num(names); 454269847Speter int name_idx; 455269847Speter 456269847Speter if (san_arr) 457269847Speter *san_arr = apr_array_make(pool, names_count, sizeof(char*)); 458269847Speter for (name_idx = 0; name_idx < names_count; name_idx++) { 459269847Speter char *p = NULL; 460269847Speter GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, name_idx); 461269847Speter 462269847Speter switch (nm->type) { 463269847Speter case GEN_DNS: 464269847Speter if (copy_action == ErrorOnNul && 465269847Speter strlen(nm->d.ia5->data) != nm->d.ia5->length) 466269847Speter return SERF_ERROR_SSL_CERT_FAILED; 467269847Speter if (san_arr && *san_arr) 468269847Speter p = pstrdup_escape_nul_bytes((const char *)nm->d.ia5->data, 469269847Speter nm->d.ia5->length, 470269847Speter pool); 471269847Speter break; 472269847Speter default: 473269847Speter /* Don't know what to do - skip. */ 474269847Speter break; 475269847Speter } 476269847Speter 477269847Speter if (p) { 478269847Speter APR_ARRAY_PUSH(*san_arr, char*) = p; 479269847Speter } 480269847Speter } 481269847Speter sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); 482269847Speter } 483269847Speter 484269847Speter return APR_SUCCESS; 485269847Speter} 486269847Speter 487269847Speterstatic apr_status_t validate_cert_hostname(X509 *server_cert, apr_pool_t *pool) 488269847Speter{ 489269847Speter char buf[1024]; 490269847Speter int length; 491269847Speter apr_status_t ret; 492269847Speter 493269847Speter ret = get_subject_alt_names(NULL, server_cert, ErrorOnNul, NULL); 494269847Speter if (ret) { 495269847Speter return ret; 496269847Speter } else { 497269847Speter /* Fail if the subject's CN field contains \0 characters. */ 498269847Speter X509_NAME *subject = X509_get_subject_name(server_cert); 499269847Speter if (!subject) 500269847Speter return SERF_ERROR_SSL_CERT_FAILED; 501269847Speter 502269847Speter length = X509_NAME_get_text_by_NID(subject, NID_commonName, buf, 1024); 503269847Speter if (length != -1) 504269847Speter if (strlen(buf) != length) 505269847Speter return SERF_ERROR_SSL_CERT_FAILED; 506269847Speter } 507269847Speter 508269847Speter return APR_SUCCESS; 509269847Speter} 510269847Speter 511251877Speterstatic int 512251877Spetervalidate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx) 513251877Speter{ 514251877Speter SSL *ssl; 515251877Speter serf_ssl_context_t *ctx; 516251877Speter X509 *server_cert; 517251877Speter int err, depth; 518251877Speter int failures = 0; 519269847Speter apr_status_t status; 520251877Speter 521251877Speter ssl = X509_STORE_CTX_get_ex_data(store_ctx, 522251877Speter SSL_get_ex_data_X509_STORE_CTX_idx()); 523251877Speter ctx = SSL_get_app_data(ssl); 524251877Speter 525251877Speter server_cert = X509_STORE_CTX_get_current_cert(store_ctx); 526251877Speter depth = X509_STORE_CTX_get_error_depth(store_ctx); 527251877Speter 528251877Speter /* If the certification was found invalid, get the error and convert it to 529251877Speter something our caller will understand. */ 530251877Speter if (! cert_valid) { 531251877Speter err = X509_STORE_CTX_get_error(store_ctx); 532251877Speter 533251877Speter switch(err) { 534251877Speter case X509_V_ERR_CERT_NOT_YET_VALID: 535251877Speter failures |= SERF_SSL_CERT_NOTYETVALID; 536251877Speter break; 537251877Speter case X509_V_ERR_CERT_HAS_EXPIRED: 538251877Speter failures |= SERF_SSL_CERT_EXPIRED; 539251877Speter break; 540251877Speter case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 541251877Speter case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 542251877Speter failures |= SERF_SSL_CERT_SELF_SIGNED; 543251877Speter break; 544251877Speter case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 545251877Speter case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 546251877Speter case X509_V_ERR_CERT_UNTRUSTED: 547251877Speter case X509_V_ERR_INVALID_CA: 548262339Speter case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 549251877Speter failures |= SERF_SSL_CERT_UNKNOWNCA; 550251877Speter break; 551251877Speter case X509_V_ERR_CERT_REVOKED: 552251877Speter failures |= SERF_SSL_CERT_REVOKED; 553251877Speter break; 554251877Speter default: 555251877Speter failures |= SERF_SSL_CERT_UNKNOWN_FAILURE; 556251877Speter break; 557251877Speter } 558251877Speter } 559251877Speter 560269847Speter /* Validate hostname */ 561269847Speter status = validate_cert_hostname(server_cert, ctx->pool); 562269847Speter if (status) 563269847Speter failures |= SERF_SSL_CERT_UNKNOWN_FAILURE; 564269847Speter 565251877Speter /* Check certificate expiry dates. */ 566251877Speter if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) { 567251877Speter failures |= SERF_SSL_CERT_NOTYETVALID; 568251877Speter } 569251877Speter else if (X509_cmp_current_time(X509_get_notAfter(server_cert)) <= 0) { 570251877Speter failures |= SERF_SSL_CERT_EXPIRED; 571251877Speter } 572251877Speter 573251877Speter if (ctx->server_cert_callback && 574251877Speter (depth == 0 || failures)) { 575251877Speter serf_ssl_certificate_t *cert; 576251877Speter apr_pool_t *subpool; 577251877Speter 578251877Speter apr_pool_create(&subpool, ctx->pool); 579251877Speter 580251877Speter cert = apr_palloc(subpool, sizeof(serf_ssl_certificate_t)); 581251877Speter cert->ssl_cert = server_cert; 582251877Speter cert->depth = depth; 583251877Speter 584251877Speter /* Callback for further verification. */ 585251877Speter status = ctx->server_cert_callback(ctx->server_cert_userdata, 586251877Speter failures, cert); 587251877Speter if (status == APR_SUCCESS) 588251877Speter cert_valid = 1; 589251877Speter else { 590251877Speter /* Even if openssl found the certificate valid, the application 591251877Speter told us to reject it. */ 592251877Speter cert_valid = 0; 593251877Speter /* Pass the error back to the caller through the context-run. */ 594251877Speter ctx->pending_err = status; 595251877Speter } 596251877Speter apr_pool_destroy(subpool); 597251877Speter } 598251877Speter 599251877Speter if (ctx->server_cert_chain_callback 600251877Speter && (depth == 0 || failures)) { 601251877Speter STACK_OF(X509) *chain; 602251877Speter const serf_ssl_certificate_t **certs; 603251877Speter int certs_len; 604251877Speter apr_pool_t *subpool; 605251877Speter 606251877Speter apr_pool_create(&subpool, ctx->pool); 607251877Speter 608251877Speter /* Borrow the chain to pass to the callback. */ 609251877Speter chain = X509_STORE_CTX_get_chain(store_ctx); 610251877Speter 611251877Speter /* If the chain can't be retrieved, just pass the current 612251877Speter certificate. */ 613251877Speter /* ### can this actually happen with _get_chain() ? */ 614251877Speter if (!chain) { 615251877Speter serf_ssl_certificate_t *cert = apr_palloc(subpool, sizeof(*cert)); 616251877Speter 617251877Speter cert->ssl_cert = server_cert; 618251877Speter cert->depth = depth; 619251877Speter 620251877Speter /* Room for the server_cert and a trailing NULL. */ 621251877Speter certs = apr_palloc(subpool, sizeof(*certs) * 2); 622251877Speter certs[0] = cert; 623251877Speter 624251877Speter certs_len = 1; 625251877Speter } else { 626251877Speter int i; 627251877Speter 628251877Speter certs_len = sk_X509_num(chain); 629251877Speter 630251877Speter /* Room for all the certs and a trailing NULL. */ 631251877Speter certs = apr_palloc(subpool, sizeof(*certs) * (certs_len + 1)); 632251877Speter for (i = 0; i < certs_len; ++i) { 633251877Speter serf_ssl_certificate_t *cert; 634251877Speter 635251877Speter cert = apr_palloc(subpool, sizeof(*cert)); 636251877Speter cert->ssl_cert = sk_X509_value(chain, i); 637251877Speter cert->depth = i; 638251877Speter 639251877Speter certs[i] = cert; 640251877Speter } 641251877Speter } 642251877Speter certs[certs_len] = NULL; 643251877Speter 644251877Speter /* Callback for further verification. */ 645251877Speter status = ctx->server_cert_chain_callback(ctx->server_cert_userdata, 646251877Speter failures, depth, 647251877Speter certs, certs_len); 648251877Speter if (status == APR_SUCCESS) { 649251877Speter cert_valid = 1; 650251877Speter } else { 651251877Speter /* Even if openssl found the certificate valid, the application 652251877Speter told us to reject it. */ 653251877Speter cert_valid = 0; 654251877Speter /* Pass the error back to the caller through the context-run. */ 655251877Speter ctx->pending_err = status; 656251877Speter } 657251877Speter 658251877Speter apr_pool_destroy(subpool); 659251877Speter } 660251877Speter 661253895Speter /* Return a specific error if the server certificate is not accepted by 662253895Speter OpenSSL and the application has not set callbacks to override this. */ 663253895Speter if (!cert_valid && 664253895Speter !ctx->server_cert_chain_callback && 665253895Speter !ctx->server_cert_callback) 666253895Speter { 667253895Speter ctx->pending_err = SERF_ERROR_SSL_CERT_FAILED; 668253895Speter } 669253895Speter 670251877Speter return cert_valid; 671251877Speter} 672251877Speter 673251877Speter/* This function reads an encrypted stream and returns the decrypted stream. */ 674251877Speterstatic apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize, 675251877Speter char *buf, apr_size_t *len) 676251877Speter{ 677251877Speter serf_ssl_context_t *ctx = baton; 678251877Speter apr_size_t priv_len; 679251877Speter apr_status_t status; 680251877Speter const char *data; 681251877Speter int ssl_len; 682251877Speter 683251877Speter if (ctx->fatal_err) 684251877Speter return ctx->fatal_err; 685251877Speter 686251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_decrypt: begin %d\n", bufsize); 687251877Speter 688251877Speter /* Is there some data waiting to be read? */ 689251877Speter ssl_len = SSL_read(ctx->ssl, buf, bufsize); 690251877Speter if (ssl_len > 0) { 691251877Speter serf__log(SSL_VERBOSE, __FILE__, 692251877Speter "ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n", 693251877Speter ssl_len, bufsize, ctx->decrypt.status, 694251877Speter BIO_get_retry_flags(ctx->bio)); 695251877Speter *len = ssl_len; 696251877Speter return APR_SUCCESS; 697251877Speter } 698251877Speter 699251877Speter status = serf_bucket_read(ctx->decrypt.stream, bufsize, &data, &priv_len); 700251877Speter 701251877Speter if (!SERF_BUCKET_READ_ERROR(status) && priv_len) { 702251877Speter serf_bucket_t *tmp; 703251877Speter 704251877Speter serf__log(SSL_VERBOSE, __FILE__, 705251877Speter "ssl_decrypt: read %d bytes (%d); status: %d\n", 706251877Speter priv_len, bufsize, status); 707251877Speter 708251877Speter tmp = serf_bucket_simple_copy_create(data, priv_len, 709251877Speter ctx->decrypt.pending->allocator); 710251877Speter 711251877Speter serf_bucket_aggregate_append(ctx->decrypt.pending, tmp); 712251877Speter 713251877Speter ssl_len = SSL_read(ctx->ssl, buf, bufsize); 714251877Speter if (ssl_len < 0) { 715251877Speter int ssl_err; 716251877Speter 717251877Speter ssl_err = SSL_get_error(ctx->ssl, ssl_len); 718251877Speter switch (ssl_err) { 719251877Speter case SSL_ERROR_SYSCALL: 720251877Speter *len = 0; 721253895Speter /* Return the underlying network error that caused OpenSSL 722253895Speter to fail. ### This can be a crypt error! */ 723251877Speter status = ctx->decrypt.status; 724251877Speter break; 725251877Speter case SSL_ERROR_WANT_READ: 726253895Speter case SSL_ERROR_WANT_WRITE: 727251877Speter *len = 0; 728251877Speter status = APR_EAGAIN; 729251877Speter break; 730251877Speter case SSL_ERROR_SSL: 731251877Speter *len = 0; 732251877Speter if (ctx->pending_err) { 733251877Speter status = ctx->pending_err; 734251877Speter ctx->pending_err = 0; 735251877Speter } else { 736251877Speter ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; 737251877Speter } 738251877Speter break; 739251877Speter default: 740251877Speter *len = 0; 741251877Speter ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; 742251877Speter break; 743251877Speter } 744251877Speter } else if (ssl_len == 0) { 745251877Speter /* The server shut down the connection. */ 746251877Speter int ssl_err, shutdown; 747251877Speter *len = 0; 748251877Speter 749251877Speter /* Check for SSL_RECEIVED_SHUTDOWN */ 750251877Speter shutdown = SSL_get_shutdown(ctx->ssl); 751251877Speter /* Check for SSL_ERROR_ZERO_RETURN */ 752251877Speter ssl_err = SSL_get_error(ctx->ssl, ssl_len); 753251877Speter 754251877Speter if (shutdown == SSL_RECEIVED_SHUTDOWN && 755251877Speter ssl_err == SSL_ERROR_ZERO_RETURN) { 756251877Speter /* The server closed the SSL session. While this doesn't 757251877Speter necessary mean the connection is closed, let's close 758251877Speter it here anyway. 759251877Speter We can optimize this later. */ 760251877Speter serf__log(SSL_VERBOSE, __FILE__, 761251877Speter "ssl_decrypt: SSL read error: server" 762251877Speter " shut down connection!\n"); 763251877Speter status = APR_EOF; 764251877Speter } else { 765251877Speter /* A fatal error occurred. */ 766251877Speter ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; 767251877Speter } 768251877Speter } else { 769251877Speter *len = ssl_len; 770251877Speter serf__log(SSL_MSG_VERBOSE, __FILE__, 771251877Speter "---\n%.*s\n-(%d)-\n", *len, buf, *len); 772251877Speter } 773251877Speter } 774251877Speter else { 775251877Speter *len = 0; 776251877Speter } 777251877Speter serf__log(SSL_VERBOSE, __FILE__, 778251877Speter "ssl_decrypt: %d %d %d\n", status, *len, 779251877Speter BIO_get_retry_flags(ctx->bio)); 780251877Speter 781251877Speter return status; 782251877Speter} 783251877Speter 784251877Speter/* This function reads a decrypted stream and returns an encrypted stream. */ 785251877Speterstatic apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize, 786251877Speter char *buf, apr_size_t *len) 787251877Speter{ 788251877Speter const char *data; 789251877Speter apr_size_t interim_bufsize; 790251877Speter serf_ssl_context_t *ctx = baton; 791251877Speter apr_status_t status; 792251877Speter 793251877Speter if (ctx->fatal_err) 794251877Speter return ctx->fatal_err; 795251877Speter 796251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: begin %d\n", bufsize); 797251877Speter 798251877Speter /* Try to read already encrypted but unread data first. */ 799251877Speter status = serf_bucket_read(ctx->encrypt.pending, bufsize, &data, len); 800251877Speter if (SERF_BUCKET_READ_ERROR(status)) { 801251877Speter return status; 802251877Speter } 803251877Speter 804251877Speter /* Aha, we read something. Return that now. */ 805251877Speter if (*len) { 806251877Speter memcpy(buf, data, *len); 807251877Speter if (APR_STATUS_IS_EOF(status)) { 808251877Speter status = APR_SUCCESS; 809251877Speter } 810251877Speter 811251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: %d %d %d (quick read)\n", 812251877Speter status, *len, BIO_get_retry_flags(ctx->bio)); 813251877Speter 814251877Speter return status; 815251877Speter } 816251877Speter 817251877Speter if (BIO_should_retry(ctx->bio) && BIO_should_write(ctx->bio)) { 818251877Speter serf__log(SSL_VERBOSE, __FILE__, 819251877Speter "ssl_encrypt: %d %d %d (should write exit)\n", 820251877Speter status, *len, BIO_get_retry_flags(ctx->bio)); 821251877Speter 822251877Speter return APR_EAGAIN; 823251877Speter } 824251877Speter 825251877Speter /* If we were previously blocked, unblock ourselves now. */ 826251877Speter if (BIO_should_read(ctx->bio)) { 827251877Speter serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: reset %d %d (%d %d %d)\n", 828251877Speter status, ctx->encrypt.status, 829251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 830251877Speter BIO_get_retry_flags(ctx->bio)); 831251877Speter 832251877Speter ctx->encrypt.status = APR_SUCCESS; 833251877Speter ctx->encrypt.exhausted_reset = 0; 834251877Speter } 835251877Speter 836251877Speter /* Oh well, read from our stream now. */ 837251877Speter interim_bufsize = bufsize; 838251877Speter do { 839251877Speter apr_size_t interim_len; 840251877Speter 841251877Speter if (!ctx->encrypt.status) { 842251877Speter struct iovec vecs[64]; 843251877Speter int vecs_read; 844251877Speter 845251877Speter status = serf_bucket_read_iovec(ctx->encrypt.stream, 846251877Speter interim_bufsize, 64, vecs, 847251877Speter &vecs_read); 848251877Speter 849251877Speter if (!SERF_BUCKET_READ_ERROR(status) && vecs_read) { 850251877Speter char *vecs_data; 851251877Speter int i, cur, vecs_data_len; 852251877Speter int ssl_len; 853251877Speter 854251877Speter /* Combine the buffers of the iovec into one buffer, as 855251877Speter that is with SSL_write requires. */ 856251877Speter vecs_data_len = 0; 857251877Speter for (i = 0; i < vecs_read; i++) { 858251877Speter vecs_data_len += vecs[i].iov_len; 859251877Speter } 860251877Speter 861251877Speter vecs_data = serf_bucket_mem_alloc(ctx->allocator, 862251877Speter vecs_data_len); 863251877Speter 864251877Speter cur = 0; 865251877Speter for (i = 0; i < vecs_read; i++) { 866251877Speter memcpy(vecs_data + cur, vecs[i].iov_base, vecs[i].iov_len); 867251877Speter cur += vecs[i].iov_len; 868251877Speter } 869251877Speter 870251877Speter interim_bufsize -= vecs_data_len; 871251877Speter interim_len = vecs_data_len; 872251877Speter 873251877Speter serf__log(SSL_VERBOSE, __FILE__, 874251877Speter "ssl_encrypt: bucket read %d bytes; "\ 875251877Speter "status %d\n", interim_len, status); 876251877Speter serf__log(SSL_MSG_VERBOSE, __FILE__, "---\n%.*s\n-(%d)-\n", 877251877Speter interim_len, vecs_data, interim_len); 878251877Speter 879251877Speter /* Stash our status away. */ 880251877Speter ctx->encrypt.status = status; 881251877Speter 882251877Speter ssl_len = SSL_write(ctx->ssl, vecs_data, interim_len); 883251877Speter 884251877Speter serf__log(SSL_VERBOSE, __FILE__, 885251877Speter "ssl_encrypt: SSL write: %d\n", ssl_len); 886251877Speter 887251877Speter /* If we failed to write... */ 888251877Speter if (ssl_len < 0) { 889251877Speter int ssl_err; 890251877Speter 891253895Speter /* Ah, bugger. We need to put that data back. 892253895Speter Note: use the copy here, we do not own the original iovec 893253895Speter data buffer so it will be freed on next read. */ 894253895Speter serf_bucket_t *vecs_copy = 895253895Speter serf_bucket_simple_own_create(vecs_data, 896253895Speter vecs_data_len, 897253895Speter ctx->allocator); 898253895Speter serf_bucket_aggregate_prepend(ctx->encrypt.stream, 899253895Speter vecs_copy); 900251877Speter 901251877Speter ssl_err = SSL_get_error(ctx->ssl, ssl_len); 902251877Speter 903251877Speter serf__log(SSL_VERBOSE, __FILE__, 904251877Speter "ssl_encrypt: SSL write error: %d\n", ssl_err); 905251877Speter 906251877Speter if (ssl_err == SSL_ERROR_SYSCALL) { 907253895Speter /* Return the underlying network error that caused OpenSSL 908253895Speter to fail. ### This can be a decrypt error! */ 909251877Speter status = ctx->encrypt.status; 910251877Speter if (SERF_BUCKET_READ_ERROR(status)) { 911251877Speter return status; 912251877Speter } 913251877Speter } 914251877Speter else { 915251877Speter /* Oh, no. */ 916251877Speter if (ssl_err == SSL_ERROR_WANT_READ) { 917251877Speter status = SERF_ERROR_WAIT_CONN; 918251877Speter } 919251877Speter else { 920253895Speter ctx->fatal_err = status = 921253895Speter SERF_ERROR_SSL_COMM_FAILED; 922251877Speter } 923251877Speter } 924251877Speter 925251877Speter serf__log(SSL_VERBOSE, __FILE__, 926251877Speter "ssl_encrypt: SSL write error: %d %d\n", 927251877Speter status, *len); 928253895Speter } else { 929253895Speter /* We're done with this data. */ 930253895Speter serf_bucket_mem_free(ctx->allocator, vecs_data); 931251877Speter } 932251877Speter } 933251877Speter } 934251877Speter else { 935251877Speter interim_len = 0; 936251877Speter *len = 0; 937251877Speter status = ctx->encrypt.status; 938251877Speter } 939251877Speter 940251877Speter } while (!status && interim_bufsize); 941251877Speter 942251877Speter /* Okay, we exhausted our underlying stream. */ 943251877Speter if (!SERF_BUCKET_READ_ERROR(status)) { 944251877Speter apr_status_t agg_status; 945251877Speter struct iovec vecs[64]; 946251877Speter int vecs_read, i; 947251877Speter 948251877Speter /* We read something! */ 949251877Speter agg_status = serf_bucket_read_iovec(ctx->encrypt.pending, bufsize, 950251877Speter 64, vecs, &vecs_read); 951251877Speter *len = 0; 952251877Speter for (i = 0; i < vecs_read; i++) { 953251877Speter memcpy(buf + *len, vecs[i].iov_base, vecs[i].iov_len); 954251877Speter *len += vecs[i].iov_len; 955251877Speter } 956251877Speter 957251877Speter serf__log(SSL_VERBOSE, __FILE__, 958251877Speter "ssl_encrypt read agg: %d %d %d %d\n", status, agg_status, 959251877Speter ctx->encrypt.status, *len); 960251877Speter 961251877Speter if (!agg_status) { 962251877Speter status = agg_status; 963251877Speter } 964251877Speter } 965251877Speter 966251877Speter if (status == SERF_ERROR_WAIT_CONN 967251877Speter && BIO_should_retry(ctx->bio) && BIO_should_read(ctx->bio)) { 968251877Speter ctx->encrypt.exhausted = ctx->encrypt.status; 969251877Speter ctx->encrypt.status = SERF_ERROR_WAIT_CONN; 970251877Speter } 971251877Speter 972251877Speter serf__log(SSL_VERBOSE, __FILE__, 973251877Speter "ssl_encrypt finished: %d %d (%d %d %d)\n", status, *len, 974251877Speter BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), 975251877Speter BIO_get_retry_flags(ctx->bio)); 976251877Speter 977251877Speter return status; 978251877Speter} 979251877Speter 980251877Speter#if APR_HAS_THREADS 981251877Speterstatic apr_pool_t *ssl_pool; 982251877Speterstatic apr_thread_mutex_t **ssl_locks; 983251877Speter 984251877Spetertypedef struct CRYPTO_dynlock_value { 985251877Speter apr_thread_mutex_t *lock; 986251877Speter} CRYPTO_dynlock_value; 987251877Speter 988251877Speterstatic CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line) 989251877Speter{ 990251877Speter CRYPTO_dynlock_value *l; 991251877Speter apr_status_t rv; 992251877Speter 993251877Speter l = apr_palloc(ssl_pool, sizeof(CRYPTO_dynlock_value)); 994251877Speter rv = apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, ssl_pool); 995251877Speter if (rv != APR_SUCCESS) { 996251877Speter /* FIXME: return error here */ 997251877Speter } 998251877Speter return l; 999251877Speter} 1000251877Speter 1001251877Speterstatic void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file, 1002251877Speter int line) 1003251877Speter{ 1004251877Speter if (mode & CRYPTO_LOCK) { 1005251877Speter apr_thread_mutex_lock(l->lock); 1006251877Speter } 1007251877Speter else if (mode & CRYPTO_UNLOCK) { 1008251877Speter apr_thread_mutex_unlock(l->lock); 1009251877Speter } 1010251877Speter} 1011251877Speter 1012251877Speterstatic void ssl_dyn_destroy(CRYPTO_dynlock_value *l, const char *file, 1013251877Speter int line) 1014251877Speter{ 1015251877Speter apr_thread_mutex_destroy(l->lock); 1016251877Speter} 1017251877Speter 1018251877Speterstatic void ssl_lock(int mode, int n, const char *file, int line) 1019251877Speter{ 1020251877Speter if (mode & CRYPTO_LOCK) { 1021251877Speter apr_thread_mutex_lock(ssl_locks[n]); 1022251877Speter } 1023251877Speter else if (mode & CRYPTO_UNLOCK) { 1024251877Speter apr_thread_mutex_unlock(ssl_locks[n]); 1025251877Speter } 1026251877Speter} 1027251877Speter 1028251877Speterstatic unsigned long ssl_id(void) 1029251877Speter{ 1030251877Speter /* FIXME: This is lame and not portable. -aaron */ 1031251877Speter return (unsigned long) apr_os_thread_current(); 1032251877Speter} 1033251877Speter 1034251877Speterstatic apr_status_t cleanup_ssl(void *data) 1035251877Speter{ 1036251877Speter CRYPTO_set_locking_callback(NULL); 1037251877Speter CRYPTO_set_id_callback(NULL); 1038251877Speter CRYPTO_set_dynlock_create_callback(NULL); 1039251877Speter CRYPTO_set_dynlock_lock_callback(NULL); 1040251877Speter CRYPTO_set_dynlock_destroy_callback(NULL); 1041251877Speter 1042251877Speter return APR_SUCCESS; 1043251877Speter} 1044251877Speter 1045251877Speter#endif 1046251877Speter 1047262339Speter#if !APR_VERSION_AT_LEAST(1,0,0) 1048262339Speter#define apr_atomic_cas32(mem, with, cmp) apr_atomic_cas(mem, with, cmp) 1049262339Speter#endif 1050251877Speter 1051262339Speterenum ssl_init_e 1052262339Speter{ 1053262339Speter INIT_UNINITIALIZED = 0, 1054262339Speter INIT_BUSY = 1, 1055262339Speter INIT_DONE = 2 1056262339Speter}; 1057262339Speter 1058262339Speterstatic volatile apr_uint32_t have_init_ssl = INIT_UNINITIALIZED; 1059262339Speter 1060251877Speterstatic void init_ssl_libraries(void) 1061251877Speter{ 1062251877Speter apr_uint32_t val; 1063251877Speter 1064262339Speter val = apr_atomic_cas32(&have_init_ssl, INIT_BUSY, INIT_UNINITIALIZED); 1065262339Speter 1066251877Speter if (!val) { 1067251877Speter#if APR_HAS_THREADS 1068251877Speter int i, numlocks; 1069251877Speter#endif 1070251877Speter 1071251877Speter#ifdef SSL_VERBOSE 1072251877Speter /* Warn when compile-time and run-time version of OpenSSL differ in 1073251877Speter major/minor version number. */ 1074251877Speter long libver = SSLeay(); 1075251877Speter 1076251877Speter if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) { 1077251877Speter serf__log(SSL_VERBOSE, __FILE__, 1078251877Speter "Warning: OpenSSL library version mismatch, compile-time " 1079251877Speter "was %lx, runtime is %lx.\n", 1080251877Speter OPENSSL_VERSION_NUMBER, libver); 1081251877Speter } 1082251877Speter#endif 1083251877Speter 1084251877Speter CRYPTO_malloc_init(); 1085251877Speter ERR_load_crypto_strings(); 1086251877Speter SSL_load_error_strings(); 1087251877Speter SSL_library_init(); 1088251877Speter OpenSSL_add_all_algorithms(); 1089251877Speter 1090251877Speter#if APR_HAS_THREADS 1091251877Speter numlocks = CRYPTO_num_locks(); 1092251877Speter apr_pool_create(&ssl_pool, NULL); 1093251877Speter ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks); 1094251877Speter for (i = 0; i < numlocks; i++) { 1095251877Speter apr_status_t rv; 1096251877Speter 1097251877Speter /* Intraprocess locks don't /need/ a filename... */ 1098251877Speter rv = apr_thread_mutex_create(&ssl_locks[i], 1099251877Speter APR_THREAD_MUTEX_DEFAULT, ssl_pool); 1100251877Speter if (rv != APR_SUCCESS) { 1101251877Speter /* FIXME: error out here */ 1102251877Speter } 1103251877Speter } 1104251877Speter CRYPTO_set_locking_callback(ssl_lock); 1105251877Speter CRYPTO_set_id_callback(ssl_id); 1106251877Speter CRYPTO_set_dynlock_create_callback(ssl_dyn_create); 1107251877Speter CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock); 1108251877Speter CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy); 1109251877Speter 1110251877Speter apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl); 1111251877Speter#endif 1112262339Speter apr_atomic_cas32(&have_init_ssl, INIT_DONE, INIT_BUSY); 1113251877Speter } 1114262339Speter else 1115262339Speter { 1116262339Speter /* Make sure we don't continue before the initialization in another 1117262339Speter thread has completed */ 1118262339Speter while (val != INIT_DONE) { 1119262339Speter apr_sleep(APR_USEC_PER_SEC / 1000); 1120262339Speter 1121262339Speter val = apr_atomic_cas32(&have_init_ssl, 1122262339Speter INIT_UNINITIALIZED, 1123262339Speter INIT_UNINITIALIZED); 1124262339Speter } 1125262339Speter } 1126251877Speter} 1127251877Speter 1128251877Speterstatic int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey) 1129251877Speter{ 1130251877Speter serf_ssl_context_t *ctx = SSL_get_app_data(ssl); 1131251877Speter apr_status_t status; 1132251877Speter 1133251877Speter if (ctx->cached_cert) { 1134251877Speter *cert = ctx->cached_cert; 1135251877Speter *pkey = ctx->cached_cert_pw; 1136251877Speter return 1; 1137251877Speter } 1138251877Speter 1139251877Speter while (ctx->cert_callback) { 1140251877Speter const char *cert_path; 1141251877Speter apr_file_t *cert_file; 1142251877Speter BIO *bio; 1143251877Speter PKCS12 *p12; 1144251877Speter int i; 1145251877Speter int retrying_success = 0; 1146251877Speter 1147251877Speter if (ctx->cert_file_success) { 1148251877Speter status = APR_SUCCESS; 1149251877Speter cert_path = ctx->cert_file_success; 1150251877Speter ctx->cert_file_success = NULL; 1151251877Speter retrying_success = 1; 1152251877Speter } else { 1153251877Speter status = ctx->cert_callback(ctx->cert_userdata, &cert_path); 1154251877Speter } 1155251877Speter 1156251877Speter if (status || !cert_path) { 1157253895Speter break; 1158251877Speter } 1159251877Speter 1160251877Speter /* Load the x.509 cert file stored in PKCS12 */ 1161251877Speter status = apr_file_open(&cert_file, cert_path, APR_READ, APR_OS_DEFAULT, 1162251877Speter ctx->pool); 1163251877Speter 1164251877Speter if (status) { 1165251877Speter continue; 1166251877Speter } 1167251877Speter 1168251877Speter bio = BIO_new(&bio_file_method); 1169251877Speter bio->ptr = cert_file; 1170251877Speter 1171251877Speter ctx->cert_path = cert_path; 1172251877Speter p12 = d2i_PKCS12_bio(bio, NULL); 1173251877Speter apr_file_close(cert_file); 1174251877Speter 1175251877Speter i = PKCS12_parse(p12, NULL, pkey, cert, NULL); 1176251877Speter 1177251877Speter if (i == 1) { 1178251877Speter PKCS12_free(p12); 1179251877Speter ctx->cached_cert = *cert; 1180251877Speter ctx->cached_cert_pw = *pkey; 1181251877Speter if (!retrying_success && ctx->cert_cache_pool) { 1182251877Speter const char *c; 1183251877Speter 1184251877Speter c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path); 1185251877Speter 1186251877Speter apr_pool_userdata_setn(c, "serf:ssl:cert", 1187251877Speter apr_pool_cleanup_null, 1188251877Speter ctx->cert_cache_pool); 1189251877Speter } 1190251877Speter return 1; 1191251877Speter } 1192251877Speter else { 1193251877Speter int err = ERR_get_error(); 1194251877Speter ERR_clear_error(); 1195251877Speter if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 && 1196251877Speter ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) { 1197251877Speter if (ctx->cert_pw_callback) { 1198251877Speter const char *password; 1199251877Speter 1200251877Speter if (ctx->cert_pw_success) { 1201251877Speter status = APR_SUCCESS; 1202251877Speter password = ctx->cert_pw_success; 1203251877Speter ctx->cert_pw_success = NULL; 1204251877Speter } else { 1205251877Speter status = ctx->cert_pw_callback(ctx->cert_pw_userdata, 1206251877Speter ctx->cert_path, 1207251877Speter &password); 1208251877Speter } 1209251877Speter 1210251877Speter if (!status && password) { 1211251877Speter i = PKCS12_parse(p12, password, pkey, cert, NULL); 1212251877Speter if (i == 1) { 1213251877Speter PKCS12_free(p12); 1214251877Speter ctx->cached_cert = *cert; 1215251877Speter ctx->cached_cert_pw = *pkey; 1216251877Speter if (!retrying_success && ctx->cert_cache_pool) { 1217251877Speter const char *c; 1218251877Speter 1219251877Speter c = apr_pstrdup(ctx->cert_cache_pool, 1220251877Speter ctx->cert_path); 1221251877Speter 1222251877Speter apr_pool_userdata_setn(c, "serf:ssl:cert", 1223251877Speter apr_pool_cleanup_null, 1224251877Speter ctx->cert_cache_pool); 1225251877Speter } 1226251877Speter if (!retrying_success && ctx->cert_pw_cache_pool) { 1227251877Speter const char *c; 1228251877Speter 1229251877Speter c = apr_pstrdup(ctx->cert_pw_cache_pool, 1230251877Speter password); 1231251877Speter 1232251877Speter apr_pool_userdata_setn(c, "serf:ssl:certpw", 1233251877Speter apr_pool_cleanup_null, 1234251877Speter ctx->cert_pw_cache_pool); 1235251877Speter } 1236251877Speter return 1; 1237251877Speter } 1238251877Speter } 1239251877Speter } 1240251877Speter PKCS12_free(p12); 1241251877Speter return 0; 1242251877Speter } 1243251877Speter else { 1244251877Speter printf("OpenSSL cert error: %d %d %d\n", ERR_GET_LIB(err), 1245251877Speter ERR_GET_FUNC(err), 1246251877Speter ERR_GET_REASON(err)); 1247251877Speter PKCS12_free(p12); 1248251877Speter } 1249251877Speter } 1250251877Speter } 1251251877Speter 1252251877Speter return 0; 1253251877Speter} 1254251877Speter 1255251877Speter 1256251877Spetervoid serf_ssl_client_cert_provider_set( 1257251877Speter serf_ssl_context_t *context, 1258251877Speter serf_ssl_need_client_cert_t callback, 1259251877Speter void *data, 1260251877Speter void *cache_pool) 1261251877Speter{ 1262251877Speter context->cert_callback = callback; 1263251877Speter context->cert_userdata = data; 1264251877Speter context->cert_cache_pool = cache_pool; 1265251877Speter if (context->cert_cache_pool) { 1266251877Speter apr_pool_userdata_get((void**)&context->cert_file_success, 1267251877Speter "serf:ssl:cert", cache_pool); 1268251877Speter } 1269251877Speter} 1270251877Speter 1271251877Speter 1272251877Spetervoid serf_ssl_client_cert_password_set( 1273251877Speter serf_ssl_context_t *context, 1274251877Speter serf_ssl_need_cert_password_t callback, 1275251877Speter void *data, 1276251877Speter void *cache_pool) 1277251877Speter{ 1278251877Speter context->cert_pw_callback = callback; 1279251877Speter context->cert_pw_userdata = data; 1280251877Speter context->cert_pw_cache_pool = cache_pool; 1281251877Speter if (context->cert_pw_cache_pool) { 1282251877Speter apr_pool_userdata_get((void**)&context->cert_pw_success, 1283251877Speter "serf:ssl:certpw", cache_pool); 1284251877Speter } 1285251877Speter} 1286251877Speter 1287251877Speter 1288251877Spetervoid serf_ssl_server_cert_callback_set( 1289251877Speter serf_ssl_context_t *context, 1290251877Speter serf_ssl_need_server_cert_t callback, 1291251877Speter void *data) 1292251877Speter{ 1293251877Speter context->server_cert_callback = callback; 1294251877Speter context->server_cert_userdata = data; 1295251877Speter} 1296251877Speter 1297251877Spetervoid serf_ssl_server_cert_chain_callback_set( 1298251877Speter serf_ssl_context_t *context, 1299251877Speter serf_ssl_need_server_cert_t cert_callback, 1300251877Speter serf_ssl_server_cert_chain_cb_t cert_chain_callback, 1301251877Speter void *data) 1302251877Speter{ 1303251877Speter context->server_cert_callback = cert_callback; 1304251877Speter context->server_cert_chain_callback = cert_chain_callback; 1305251877Speter context->server_cert_userdata = data; 1306251877Speter} 1307251877Speter 1308262339Speterstatic serf_ssl_context_t *ssl_init_context(serf_bucket_alloc_t *allocator) 1309251877Speter{ 1310251877Speter serf_ssl_context_t *ssl_ctx; 1311251877Speter 1312251877Speter init_ssl_libraries(); 1313251877Speter 1314251877Speter ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx)); 1315251877Speter 1316251877Speter ssl_ctx->refcount = 0; 1317262339Speter ssl_ctx->pool = serf_bucket_allocator_get_pool(allocator); 1318251877Speter ssl_ctx->allocator = allocator; 1319251877Speter 1320251877Speter ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method()); 1321251877Speter 1322251877Speter SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert); 1323251877Speter ssl_ctx->cached_cert = 0; 1324251877Speter ssl_ctx->cached_cert_pw = 0; 1325251877Speter ssl_ctx->pending_err = APR_SUCCESS; 1326251877Speter ssl_ctx->fatal_err = APR_SUCCESS; 1327251877Speter 1328251877Speter ssl_ctx->cert_callback = NULL; 1329251877Speter ssl_ctx->cert_pw_callback = NULL; 1330251877Speter ssl_ctx->server_cert_callback = NULL; 1331251877Speter ssl_ctx->server_cert_chain_callback = NULL; 1332251877Speter 1333251877Speter SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER, 1334251877Speter validate_server_certificate); 1335251877Speter SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL); 1336251877Speter /* Disable SSL compression by default. */ 1337251877Speter disable_compression(ssl_ctx); 1338251877Speter 1339251877Speter ssl_ctx->ssl = SSL_new(ssl_ctx->ctx); 1340251877Speter ssl_ctx->bio = BIO_new(&bio_bucket_method); 1341251877Speter ssl_ctx->bio->ptr = ssl_ctx; 1342251877Speter 1343251877Speter SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio); 1344251877Speter 1345251877Speter SSL_set_connect_state(ssl_ctx->ssl); 1346251877Speter 1347251877Speter SSL_set_app_data(ssl_ctx->ssl, ssl_ctx); 1348251877Speter 1349251877Speter#if SSL_VERBOSE 1350251877Speter SSL_CTX_set_info_callback(ssl_ctx->ctx, apps_ssl_info_callback); 1351251877Speter#endif 1352251877Speter 1353251877Speter ssl_ctx->encrypt.stream = NULL; 1354251877Speter ssl_ctx->encrypt.stream_next = NULL; 1355251877Speter ssl_ctx->encrypt.pending = serf_bucket_aggregate_create(allocator); 1356251877Speter ssl_ctx->encrypt.status = APR_SUCCESS; 1357251877Speter serf_databuf_init(&ssl_ctx->encrypt.databuf); 1358251877Speter ssl_ctx->encrypt.databuf.read = ssl_encrypt; 1359251877Speter ssl_ctx->encrypt.databuf.read_baton = ssl_ctx; 1360251877Speter 1361251877Speter ssl_ctx->decrypt.stream = NULL; 1362251877Speter ssl_ctx->decrypt.pending = serf_bucket_aggregate_create(allocator); 1363251877Speter ssl_ctx->decrypt.status = APR_SUCCESS; 1364251877Speter serf_databuf_init(&ssl_ctx->decrypt.databuf); 1365251877Speter ssl_ctx->decrypt.databuf.read = ssl_decrypt; 1366251877Speter ssl_ctx->decrypt.databuf.read_baton = ssl_ctx; 1367251877Speter 1368251877Speter return ssl_ctx; 1369251877Speter} 1370251877Speter 1371251877Speterstatic apr_status_t ssl_free_context( 1372251877Speter serf_ssl_context_t *ssl_ctx) 1373251877Speter{ 1374251877Speter /* If never had the pending buckets, don't try to free them. */ 1375251877Speter if (ssl_ctx->decrypt.pending != NULL) { 1376251877Speter serf_bucket_destroy(ssl_ctx->decrypt.pending); 1377251877Speter } 1378251877Speter if (ssl_ctx->encrypt.pending != NULL) { 1379251877Speter serf_bucket_destroy(ssl_ctx->encrypt.pending); 1380251877Speter } 1381251877Speter 1382251877Speter /* SSL_free implicitly frees the underlying BIO. */ 1383251877Speter SSL_free(ssl_ctx->ssl); 1384251877Speter SSL_CTX_free(ssl_ctx->ctx); 1385251877Speter 1386251877Speter serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx); 1387251877Speter 1388251877Speter return APR_SUCCESS; 1389251877Speter} 1390251877Speter 1391251877Speterstatic serf_bucket_t * serf_bucket_ssl_create( 1392251877Speter serf_ssl_context_t *ssl_ctx, 1393251877Speter serf_bucket_alloc_t *allocator, 1394251877Speter const serf_bucket_type_t *type) 1395251877Speter{ 1396251877Speter ssl_context_t *ctx; 1397251877Speter 1398251877Speter ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 1399251877Speter if (!ssl_ctx) { 1400262339Speter ctx->ssl_ctx = ssl_init_context(allocator); 1401251877Speter } 1402251877Speter else { 1403251877Speter ctx->ssl_ctx = ssl_ctx; 1404251877Speter } 1405251877Speter ctx->ssl_ctx->refcount++; 1406251877Speter 1407251877Speter return serf_bucket_create(type, allocator, ctx); 1408251877Speter} 1409251877Speter 1410251877Speterapr_status_t serf_ssl_set_hostname(serf_ssl_context_t *context, 1411251877Speter const char * hostname) 1412251877Speter{ 1413251877Speter#ifdef SSL_set_tlsext_host_name 1414251877Speter if (SSL_set_tlsext_host_name(context->ssl, hostname) != 1) { 1415251877Speter ERR_clear_error(); 1416251877Speter } 1417251877Speter#endif 1418251877Speter return APR_SUCCESS; 1419251877Speter} 1420251877Speter 1421251877Speterapr_status_t serf_ssl_use_default_certificates(serf_ssl_context_t *ssl_ctx) 1422251877Speter{ 1423251877Speter X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx); 1424251877Speter 1425251877Speter int result = X509_STORE_set_default_paths(store); 1426251877Speter 1427251877Speter return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED; 1428251877Speter} 1429251877Speter 1430251877Speterapr_status_t serf_ssl_load_cert_file( 1431251877Speter serf_ssl_certificate_t **cert, 1432251877Speter const char *file_path, 1433251877Speter apr_pool_t *pool) 1434251877Speter{ 1435251877Speter FILE *fp = fopen(file_path, "r"); 1436253895Speter 1437251877Speter if (fp) { 1438251877Speter X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL); 1439251877Speter fclose(fp); 1440251877Speter 1441251877Speter if (ssl_cert) { 1442251877Speter *cert = apr_palloc(pool, sizeof(serf_ssl_certificate_t)); 1443251877Speter (*cert)->ssl_cert = ssl_cert; 1444251877Speter 1445251877Speter return APR_SUCCESS; 1446251877Speter } 1447251877Speter } 1448251877Speter 1449251877Speter return SERF_ERROR_SSL_CERT_FAILED; 1450251877Speter} 1451251877Speter 1452251877Speter 1453251877Speterapr_status_t serf_ssl_trust_cert( 1454251877Speter serf_ssl_context_t *ssl_ctx, 1455251877Speter serf_ssl_certificate_t *cert) 1456251877Speter{ 1457251877Speter X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx); 1458251877Speter 1459251877Speter int result = X509_STORE_add_cert(store, cert->ssl_cert); 1460251877Speter 1461251877Speter return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED; 1462251877Speter} 1463251877Speter 1464251877Speter 1465251877Speterserf_bucket_t *serf_bucket_ssl_decrypt_create( 1466251877Speter serf_bucket_t *stream, 1467251877Speter serf_ssl_context_t *ssl_ctx, 1468251877Speter serf_bucket_alloc_t *allocator) 1469251877Speter{ 1470251877Speter serf_bucket_t *bkt; 1471251877Speter ssl_context_t *ctx; 1472251877Speter 1473251877Speter bkt = serf_bucket_ssl_create(ssl_ctx, allocator, 1474251877Speter &serf_bucket_type_ssl_decrypt); 1475251877Speter 1476251877Speter ctx = bkt->data; 1477251877Speter 1478251877Speter ctx->databuf = &ctx->ssl_ctx->decrypt.databuf; 1479251877Speter if (ctx->ssl_ctx->decrypt.stream != NULL) { 1480251877Speter return NULL; 1481251877Speter } 1482251877Speter ctx->ssl_ctx->decrypt.stream = stream; 1483251877Speter ctx->our_stream = &ctx->ssl_ctx->decrypt.stream; 1484251877Speter 1485251877Speter return bkt; 1486251877Speter} 1487251877Speter 1488251877Speter 1489251877Speterserf_ssl_context_t *serf_bucket_ssl_decrypt_context_get( 1490251877Speter serf_bucket_t *bucket) 1491251877Speter{ 1492251877Speter ssl_context_t *ctx = bucket->data; 1493251877Speter return ctx->ssl_ctx; 1494251877Speter} 1495251877Speter 1496251877Speter 1497251877Speterserf_bucket_t *serf_bucket_ssl_encrypt_create( 1498251877Speter serf_bucket_t *stream, 1499251877Speter serf_ssl_context_t *ssl_ctx, 1500251877Speter serf_bucket_alloc_t *allocator) 1501251877Speter{ 1502251877Speter serf_bucket_t *bkt; 1503251877Speter ssl_context_t *ctx; 1504251877Speter 1505251877Speter bkt = serf_bucket_ssl_create(ssl_ctx, allocator, 1506251877Speter &serf_bucket_type_ssl_encrypt); 1507251877Speter 1508251877Speter ctx = bkt->data; 1509251877Speter 1510251877Speter ctx->databuf = &ctx->ssl_ctx->encrypt.databuf; 1511251877Speter ctx->our_stream = &ctx->ssl_ctx->encrypt.stream; 1512251877Speter if (ctx->ssl_ctx->encrypt.stream == NULL) { 1513251877Speter serf_bucket_t *tmp = serf_bucket_aggregate_create(stream->allocator); 1514251877Speter serf_bucket_aggregate_append(tmp, stream); 1515251877Speter ctx->ssl_ctx->encrypt.stream = tmp; 1516251877Speter } 1517251877Speter else { 1518251877Speter bucket_list_t *new_list; 1519251877Speter 1520251877Speter new_list = serf_bucket_mem_alloc(ctx->ssl_ctx->allocator, 1521251877Speter sizeof(*new_list)); 1522251877Speter new_list->bucket = stream; 1523251877Speter new_list->next = NULL; 1524251877Speter if (ctx->ssl_ctx->encrypt.stream_next == NULL) { 1525251877Speter ctx->ssl_ctx->encrypt.stream_next = new_list; 1526251877Speter } 1527251877Speter else { 1528251877Speter bucket_list_t *scan = ctx->ssl_ctx->encrypt.stream_next; 1529251877Speter 1530251877Speter while (scan->next != NULL) 1531251877Speter scan = scan->next; 1532251877Speter scan->next = new_list; 1533251877Speter } 1534251877Speter } 1535251877Speter 1536251877Speter return bkt; 1537251877Speter} 1538251877Speter 1539251877Speter 1540251877Speterserf_ssl_context_t *serf_bucket_ssl_encrypt_context_get( 1541251877Speter serf_bucket_t *bucket) 1542251877Speter{ 1543251877Speter ssl_context_t *ctx = bucket->data; 1544251877Speter return ctx->ssl_ctx; 1545251877Speter} 1546251877Speter 1547251877Speter/* Functions to read a serf_ssl_certificate structure. */ 1548251877Speter 1549269847Speter/* Takes a counted length string and escapes any NUL bytes so that 1550269847Speter * it can be used as a C string. NUL bytes are escaped as 3 characters 1551269847Speter * "\00" (that's a literal backslash). 1552269847Speter * The returned string is allocated in POOL. 1553269847Speter */ 1554269847Speterstatic char * 1555269847Speterpstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool) 1556269847Speter{ 1557269847Speter int i, nul_count = 0; 1558269847Speter char *ret; 1559269847Speter 1560269847Speter /* First determine if there are any nul bytes in the string. */ 1561269847Speter for (i = 0; i < len; i++) { 1562269847Speter if (buf[i] == '\0') 1563269847Speter nul_count++; 1564269847Speter } 1565269847Speter 1566269847Speter if (nul_count == 0) { 1567269847Speter /* There aren't so easy case to just copy the string */ 1568269847Speter ret = apr_pstrdup(pool, buf); 1569269847Speter } else { 1570269847Speter /* There are so we have to replace nul bytes with escape codes 1571269847Speter * Proper length is the length of the original string, plus 1572269847Speter * 2 times the number of nulls (for two digit hex code for 1573269847Speter * the value) + the trailing null. */ 1574269847Speter char *pos; 1575269847Speter ret = pos = apr_palloc(pool, len + 2 * nul_count + 1); 1576269847Speter for (i = 0; i < len; i++) { 1577269847Speter if (buf[i] != '\0') { 1578269847Speter *(pos++) = buf[i]; 1579269847Speter } else { 1580269847Speter *(pos++) = '\\'; 1581269847Speter *(pos++) = '0'; 1582269847Speter *(pos++) = '0'; 1583269847Speter } 1584269847Speter } 1585269847Speter *pos = '\0'; 1586269847Speter } 1587269847Speter 1588269847Speter return ret; 1589269847Speter} 1590269847Speter 1591269847Speter/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). Any NUL bytes in 1592269847Speter these fields in the certificate will be escaped as \00. */ 1593251877Speterstatic apr_hash_t * 1594251877Speterconvert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool) 1595251877Speter{ 1596251877Speter char buf[1024]; 1597251877Speter int ret; 1598251877Speter 1599251877Speter apr_hash_t *tgt = apr_hash_make(pool); 1600251877Speter 1601251877Speter ret = X509_NAME_get_text_by_NID(org, 1602251877Speter NID_commonName, 1603251877Speter buf, 1024); 1604251877Speter if (ret != -1) 1605269847Speter apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, 1606269847Speter pstrdup_escape_nul_bytes(buf, ret, pool)); 1607251877Speter ret = X509_NAME_get_text_by_NID(org, 1608251877Speter NID_pkcs9_emailAddress, 1609251877Speter buf, 1024); 1610251877Speter if (ret != -1) 1611269847Speter apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, 1612269847Speter pstrdup_escape_nul_bytes(buf, ret, pool)); 1613251877Speter ret = X509_NAME_get_text_by_NID(org, 1614251877Speter NID_organizationalUnitName, 1615251877Speter buf, 1024); 1616251877Speter if (ret != -1) 1617269847Speter apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, 1618269847Speter pstrdup_escape_nul_bytes(buf, ret, pool)); 1619251877Speter ret = X509_NAME_get_text_by_NID(org, 1620251877Speter NID_organizationName, 1621251877Speter buf, 1024); 1622251877Speter if (ret != -1) 1623269847Speter apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, 1624269847Speter pstrdup_escape_nul_bytes(buf, ret, pool)); 1625251877Speter ret = X509_NAME_get_text_by_NID(org, 1626251877Speter NID_localityName, 1627251877Speter buf, 1024); 1628251877Speter if (ret != -1) 1629269847Speter apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, 1630269847Speter pstrdup_escape_nul_bytes(buf, ret, pool)); 1631251877Speter ret = X509_NAME_get_text_by_NID(org, 1632251877Speter NID_stateOrProvinceName, 1633251877Speter buf, 1024); 1634251877Speter if (ret != -1) 1635269847Speter apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, 1636269847Speter pstrdup_escape_nul_bytes(buf, ret, pool)); 1637251877Speter ret = X509_NAME_get_text_by_NID(org, 1638251877Speter NID_countryName, 1639251877Speter buf, 1024); 1640251877Speter if (ret != -1) 1641269847Speter apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, 1642269847Speter pstrdup_escape_nul_bytes(buf, ret, pool)); 1643251877Speter 1644251877Speter return tgt; 1645251877Speter} 1646251877Speter 1647251877Speter 1648251877Speterint serf_ssl_cert_depth(const serf_ssl_certificate_t *cert) 1649251877Speter{ 1650251877Speter return cert->depth; 1651251877Speter} 1652251877Speter 1653251877Speter 1654251877Speterapr_hash_t *serf_ssl_cert_issuer( 1655251877Speter const serf_ssl_certificate_t *cert, 1656251877Speter apr_pool_t *pool) 1657251877Speter{ 1658251877Speter X509_NAME *issuer = X509_get_issuer_name(cert->ssl_cert); 1659251877Speter 1660251877Speter if (!issuer) 1661251877Speter return NULL; 1662251877Speter 1663251877Speter return convert_X509_NAME_to_table(issuer, pool); 1664251877Speter} 1665251877Speter 1666251877Speter 1667251877Speterapr_hash_t *serf_ssl_cert_subject( 1668251877Speter const serf_ssl_certificate_t *cert, 1669251877Speter apr_pool_t *pool) 1670251877Speter{ 1671251877Speter X509_NAME *subject = X509_get_subject_name(cert->ssl_cert); 1672251877Speter 1673251877Speter if (!subject) 1674251877Speter return NULL; 1675251877Speter 1676251877Speter return convert_X509_NAME_to_table(subject, pool); 1677251877Speter} 1678251877Speter 1679251877Speter 1680251877Speterapr_hash_t *serf_ssl_cert_certificate( 1681251877Speter const serf_ssl_certificate_t *cert, 1682251877Speter apr_pool_t *pool) 1683251877Speter{ 1684251877Speter apr_hash_t *tgt = apr_hash_make(pool); 1685251877Speter unsigned int md_size, i; 1686251877Speter unsigned char md[EVP_MAX_MD_SIZE]; 1687251877Speter BIO *bio; 1688269847Speter apr_array_header_t *san_arr; 1689251877Speter 1690251877Speter /* sha1 fingerprint */ 1691251877Speter if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) { 1692251877Speter const char hex[] = "0123456789ABCDEF"; 1693251877Speter char fingerprint[EVP_MAX_MD_SIZE * 3]; 1694251877Speter 1695251877Speter for (i=0; i<md_size; i++) { 1696251877Speter fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4]; 1697251877Speter fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)]; 1698251877Speter fingerprint[(3*i)+2] = ':'; 1699251877Speter } 1700251877Speter if (md_size > 0) 1701251877Speter fingerprint[(3*(md_size-1))+2] = '\0'; 1702251877Speter else 1703251877Speter fingerprint[0] = '\0'; 1704251877Speter 1705251877Speter apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING, 1706251877Speter apr_pstrdup(pool, fingerprint)); 1707251877Speter } 1708251877Speter 1709251877Speter /* set expiry dates */ 1710251877Speter bio = BIO_new(BIO_s_mem()); 1711251877Speter if (bio) { 1712251877Speter ASN1_TIME *notBefore, *notAfter; 1713251877Speter char buf[256]; 1714251877Speter 1715251877Speter memset (buf, 0, sizeof (buf)); 1716251877Speter notBefore = X509_get_notBefore(cert->ssl_cert); 1717251877Speter if (ASN1_TIME_print(bio, notBefore)) { 1718251877Speter BIO_read(bio, buf, 255); 1719251877Speter apr_hash_set(tgt, "notBefore", APR_HASH_KEY_STRING, 1720251877Speter apr_pstrdup(pool, buf)); 1721251877Speter } 1722251877Speter memset (buf, 0, sizeof (buf)); 1723251877Speter notAfter = X509_get_notAfter(cert->ssl_cert); 1724251877Speter if (ASN1_TIME_print(bio, notAfter)) { 1725251877Speter BIO_read(bio, buf, 255); 1726251877Speter apr_hash_set(tgt, "notAfter", APR_HASH_KEY_STRING, 1727251877Speter apr_pstrdup(pool, buf)); 1728251877Speter } 1729251877Speter } 1730251877Speter BIO_free(bio); 1731251877Speter 1732251877Speter /* Get subjectAltNames */ 1733269847Speter if (!get_subject_alt_names(&san_arr, cert->ssl_cert, EscapeNulAndCopy, pool)) 1734251877Speter apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr); 1735251877Speter 1736251877Speter return tgt; 1737251877Speter} 1738251877Speter 1739251877Speter 1740251877Speterconst char *serf_ssl_cert_export( 1741251877Speter const serf_ssl_certificate_t *cert, 1742251877Speter apr_pool_t *pool) 1743251877Speter{ 1744251877Speter char *binary_cert; 1745251877Speter char *encoded_cert; 1746251877Speter int len; 1747251877Speter unsigned char *unused; 1748251877Speter 1749251877Speter /* find the length of the DER encoding. */ 1750251877Speter len = i2d_X509(cert->ssl_cert, NULL); 1751251877Speter if (len < 0) { 1752251877Speter return NULL; 1753251877Speter } 1754251877Speter 1755251877Speter binary_cert = apr_palloc(pool, len); 1756251877Speter unused = (unsigned char *)binary_cert; 1757251877Speter len = i2d_X509(cert->ssl_cert, &unused); /* unused is incremented */ 1758251877Speter if (len < 0) { 1759251877Speter return NULL; 1760251877Speter } 1761251877Speter 1762251877Speter encoded_cert = apr_palloc(pool, apr_base64_encode_len(len)); 1763251877Speter apr_base64_encode(encoded_cert, binary_cert, len); 1764251877Speter 1765251877Speter return encoded_cert; 1766251877Speter} 1767251877Speter 1768251877Speter/* Disables compression for all SSL sessions. */ 1769251877Speterstatic void disable_compression(serf_ssl_context_t *ssl_ctx) 1770251877Speter{ 1771251877Speter#ifdef SSL_OP_NO_COMPRESSION 1772251877Speter SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_COMPRESSION); 1773251877Speter#endif 1774251877Speter} 1775251877Speter 1776251877Speterapr_status_t serf_ssl_use_compression(serf_ssl_context_t *ssl_ctx, int enabled) 1777251877Speter{ 1778251877Speter if (enabled) { 1779251877Speter#ifdef SSL_OP_NO_COMPRESSION 1780251877Speter SSL_clear_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION); 1781251877Speter return APR_SUCCESS; 1782251877Speter#endif 1783251877Speter } else { 1784251877Speter#ifdef SSL_OP_NO_COMPRESSION 1785251877Speter SSL_set_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION); 1786251877Speter return APR_SUCCESS; 1787251877Speter#endif 1788251877Speter } 1789251877Speter 1790251877Speter return APR_EGENERAL; 1791251877Speter} 1792251877Speter 1793251877Speterstatic void serf_ssl_destroy_and_data(serf_bucket_t *bucket) 1794251877Speter{ 1795251877Speter ssl_context_t *ctx = bucket->data; 1796251877Speter 1797251877Speter if (!--ctx->ssl_ctx->refcount) { 1798251877Speter ssl_free_context(ctx->ssl_ctx); 1799251877Speter } 1800251877Speter 1801251877Speter serf_default_destroy_and_data(bucket); 1802251877Speter} 1803251877Speter 1804251877Speterstatic void serf_ssl_decrypt_destroy_and_data(serf_bucket_t *bucket) 1805251877Speter{ 1806251877Speter ssl_context_t *ctx = bucket->data; 1807251877Speter 1808251877Speter serf_bucket_destroy(*ctx->our_stream); 1809251877Speter 1810251877Speter serf_ssl_destroy_and_data(bucket); 1811251877Speter} 1812251877Speter 1813251877Speterstatic void serf_ssl_encrypt_destroy_and_data(serf_bucket_t *bucket) 1814251877Speter{ 1815251877Speter ssl_context_t *ctx = bucket->data; 1816251877Speter serf_ssl_context_t *ssl_ctx = ctx->ssl_ctx; 1817251877Speter 1818251877Speter if (ssl_ctx->encrypt.stream == *ctx->our_stream) { 1819251877Speter serf_bucket_destroy(*ctx->our_stream); 1820251877Speter serf_bucket_destroy(ssl_ctx->encrypt.pending); 1821251877Speter 1822251877Speter /* Reset our encrypted status and databuf. */ 1823251877Speter ssl_ctx->encrypt.status = APR_SUCCESS; 1824251877Speter ssl_ctx->encrypt.databuf.status = APR_SUCCESS; 1825251877Speter 1826251877Speter /* Advance to the next stream - if we have one. */ 1827251877Speter if (ssl_ctx->encrypt.stream_next == NULL) { 1828251877Speter ssl_ctx->encrypt.stream = NULL; 1829251877Speter ssl_ctx->encrypt.pending = NULL; 1830251877Speter } 1831251877Speter else { 1832251877Speter bucket_list_t *cur; 1833251877Speter 1834251877Speter cur = ssl_ctx->encrypt.stream_next; 1835251877Speter ssl_ctx->encrypt.stream = cur->bucket; 1836251877Speter ssl_ctx->encrypt.pending = 1837251877Speter serf_bucket_aggregate_create(cur->bucket->allocator); 1838251877Speter ssl_ctx->encrypt.stream_next = cur->next; 1839251877Speter serf_bucket_mem_free(ssl_ctx->allocator, cur); 1840251877Speter } 1841251877Speter } 1842251877Speter else { 1843251877Speter /* Ah, darn. We haven't sent this one along yet. */ 1844251877Speter return; 1845251877Speter } 1846251877Speter serf_ssl_destroy_and_data(bucket); 1847251877Speter} 1848251877Speter 1849251877Speterstatic apr_status_t serf_ssl_read(serf_bucket_t *bucket, 1850251877Speter apr_size_t requested, 1851251877Speter const char **data, apr_size_t *len) 1852251877Speter{ 1853251877Speter ssl_context_t *ctx = bucket->data; 1854251877Speter 1855251877Speter return serf_databuf_read(ctx->databuf, requested, data, len); 1856251877Speter} 1857251877Speter 1858251877Speterstatic apr_status_t serf_ssl_readline(serf_bucket_t *bucket, 1859251877Speter int acceptable, int *found, 1860251877Speter const char **data, 1861251877Speter apr_size_t *len) 1862251877Speter{ 1863251877Speter ssl_context_t *ctx = bucket->data; 1864251877Speter 1865251877Speter return serf_databuf_readline(ctx->databuf, acceptable, found, data, len); 1866251877Speter} 1867251877Speter 1868251877Speterstatic apr_status_t serf_ssl_peek(serf_bucket_t *bucket, 1869251877Speter const char **data, 1870251877Speter apr_size_t *len) 1871251877Speter{ 1872251877Speter ssl_context_t *ctx = bucket->data; 1873251877Speter 1874251877Speter return serf_databuf_peek(ctx->databuf, data, len); 1875251877Speter} 1876251877Speter 1877251877Speter 1878251877Speterconst serf_bucket_type_t serf_bucket_type_ssl_encrypt = { 1879251877Speter "SSLENCRYPT", 1880251877Speter serf_ssl_read, 1881251877Speter serf_ssl_readline, 1882251877Speter serf_default_read_iovec, 1883251877Speter serf_default_read_for_sendfile, 1884251877Speter serf_default_read_bucket, 1885251877Speter serf_ssl_peek, 1886251877Speter serf_ssl_encrypt_destroy_and_data, 1887251877Speter}; 1888251877Speter 1889251877Speterconst serf_bucket_type_t serf_bucket_type_ssl_decrypt = { 1890251877Speter "SSLDECRYPT", 1891251877Speter serf_ssl_read, 1892251877Speter serf_ssl_readline, 1893251877Speter serf_default_read_iovec, 1894251877Speter serf_default_read_for_sendfile, 1895251877Speter serf_default_read_bucket, 1896251877Speter serf_ssl_peek, 1897251877Speter serf_ssl_decrypt_destroy_and_data, 1898251877Speter}; 1899