Changes with Apache 2.0b1
+ *) Add a very early prototype of SSL support (in mod_tls.c). It is
+ vital that you read modules/tls/README before attempting to build
+ it. [Ben Laurie]
+
*) Fix a potential seg fault on all platforms. David Reid fixed this
on BEOS, but the problem could happen anywhere, so we don't want
to #ifdef it. [Cliff Woolley <cliffwoolley@yahoo.com>]
* @param ftype The type of filter function, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION
*/
AP_DECLARE(void) ap_register_input_filter(const char *name,
- ap_in_filter_func filter_func,
- ap_filter_type ftype);
+ ap_in_filter_func filter_func,
+ ap_filter_type ftype);
/**
* This function is used to register an output filter with the system.
* After this registration is performed, then a filter may be added
* @see ::ap_add_output_filter
*/
AP_DECLARE(void) ap_register_output_filter(const char *name,
- ap_out_filter_func filter_func,
- ap_filter_type ftype);
+ ap_out_filter_func filter_func,
+ ap_filter_type ftype);
/*
* ap_add_filter():
* @param c The connection to add the fillter for
* @deffunc void ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c)
*/
-AP_DECLARE(void) ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c);
+AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
+ request_rec *r, conn_rec *c);
/**
* Add a filter to the current request. Filters are added in a FIFO manner.
* @param c The connection to add this filter for
* @deffunc void ap_add_output_filter(const char *name, void *ctx, request_rec *r, conn_rec *c)
*/
-AP_DECLARE(void) ap_add_output_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c);
+AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
+ request_rec *r, conn_rec *c);
AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f);
--- /dev/null
+.libs
+.deps
+Makefile
+*.lo
+*.la
--- /dev/null
+LTLIBRARY_NAME = libapachemod_tls.la
+LTLIBRARY_SOURCES = mod_tls.lo openssl_state_machine.lo
+
+# temp!
+openssl_state_machine.lo: openssl_state_machine.c
+ gcc -I. -I/usr/home/ben/work/httpd-2.0/modules/tls -I/usr/home/ben/work/httpd-2.0/server/mpm/prefork -I/usr/home/ben/work/httpd-2.0/include -I/usr/home/ben/work/httpd-2.0/srclib/apr/include -I/usr/home/ben/work/httpd-2.0/srclib/apr-util/include -I/usr/home/ben/work/httpd-2.0/os/unix -I/usr/home/ben/work/httpd-2.0/srclib/expat-lite -I/home/ben/work/openssl/include -I/home/ben/work/openssl/include -D_REENTRANT -D_THREAD_SAFE -g -O2 -g -Wall -Wmissing-prototypes -Wmissing-declarations -DAP_DEBUG -DNO_KRB5 -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -c openssl_state_machine.c -o openssl_state_machine.lo
+
+include $(top_srcdir)/build/ltlib.mk
+
--- /dev/null
+This is a place-holder which indicates to Configure that it shouldn't
+provide the default targets when building the Makefile in this directory.
+Instead it'll just prepend all the important variable definitions, and
+copy the Makefile.tmpl onto the end.
--- /dev/null
+This currently won't work with Apache unaided. The manual things I
+have to do to make it work are:
+
+edit .../httpd-2.0/config_vars.mk:
+
+Add "-L<where OpenSSL is> -lssl -lcrypto" to EXTRA_LIBS.
+
+Change "modules/tls/mod_tls.la" to "modules/tls/libapachemod_tls.la" in
+BUILTIN_LIBS.
+
+edit .../httpd-2.0/modules/tls/Makefile.in:
+
+Diddle with the openssl_state_machine.lo target to match your setup.
+
+Then all you need is "TLSFilter on" and "TLSCertificateFile <file>" in
+your config, and you are away (note that the cert file must also
+contain the private key at present).
+
+Ben Laurie, 11 Feb 2001.
--- /dev/null
+APACHE_MODPATH_INIT(tls)
+
+APACHE_MODULE(tls, TLS/SSL support, , , no)
+
+APACHE_MODPATH_FINISH
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * Portions of this software are based upon public domain software
+ * originally written at the National Center for Supercomputing Applications,
+ * University of Illinois, Urbana-Champaign.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "util_filter.h"
+#include "http_connection.h"
+#include "openssl_state_machine.h"
+#include "apr_strings.h"
+#include "http_protocol.h"
+
+// temp
+#include <assert.h>
+
+AP_DECLARE_DATA module tls_module;
+static const char s_szTLSFilterName[]="TLSFilter";
+typedef struct
+{
+ int bEnabled;
+ const char *szCertificateFile;
+ const char *szKeyFile;
+} TLSServerConfig;
+
+typedef struct
+{
+ SSLStateMachine *pStateMachine;
+ ap_filter_t *pInputFilter;
+ ap_filter_t *pOutputFilter;
+} TLSFilterCtx;
+
+static void *create_tls_server_config(apr_pool_t *p, server_rec *s)
+{
+ TLSServerConfig *pConfig = apr_pcalloc(p, sizeof *pConfig);
+
+ pConfig->bEnabled = 0;
+ pConfig->szCertificateFile = pConfig->szKeyFile = NULL;
+
+ return pConfig;
+}
+
+static const char *tls_on(cmd_parms *cmd, void *dummy, int arg)
+{
+ TLSServerConfig *pConfig = ap_get_module_config(cmd->server->module_config,
+ &tls_module);
+ pConfig->bEnabled = arg;
+
+ return NULL;
+}
+
+static const char *tls_cert_file(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ TLSServerConfig *pConfig = ap_get_module_config(cmd->server->module_config,
+ &tls_module);
+ pConfig->szCertificateFile = arg;
+
+ // temp
+ pConfig->szKeyFile=pConfig->szCertificateFile;
+
+ return NULL;
+}
+
+static int tls_filter_inserter(conn_rec *c)
+{
+ TLSServerConfig *pConfig =
+ ap_get_module_config(c->base_server->module_config,
+ &tls_module);
+ TLSFilterCtx *pCtx;
+
+ if (!pConfig->bEnabled)
+ return DECLINED;
+
+ pCtx=apr_pcalloc(c->pool,sizeof *pCtx);
+ pCtx->pStateMachine=SSLStateMachine_new(pConfig->szCertificateFile,
+ pConfig->szKeyFile);
+
+ pCtx->pInputFilter=ap_add_input_filter(s_szTLSFilterName,pCtx,NULL,c);
+ pCtx->pOutputFilter=ap_add_output_filter(s_szTLSFilterName,pCtx,NULL,
+ c);
+
+ return OK;
+}
+
+static apr_status_t churn(TLSFilterCtx *pCtx)
+{
+ apr_bucket_brigade *pbbOutput=NULL;
+ int done;
+
+ do {
+ char buf[1024];
+ int n;
+ apr_bucket *pbkt;
+
+ done=0;
+
+ n=SSLStateMachine_write_extract(pCtx->pStateMachine,buf,sizeof buf);
+ if(n > 0) {
+ if(!pbbOutput)
+ pbbOutput=apr_brigade_create(pCtx->pOutputFilter->c->pool);
+ pbkt=apr_bucket_pool_create(buf,n,pCtx->pOutputFilter->c->pool);
+ APR_BRIGADE_INSERT_TAIL(pbbOutput,pbkt);
+ done=1;
+ /* } else if(n == 0) {
+ apr_bucket *pbktEOS=apr_bucket_create_eos();
+ APR_BRIGADE_INSERT_TAIL(pbbOutput,pbktEOS);*/
+ }
+ } while(done);
+
+ // XXX: check for errors
+ if(pbbOutput) {
+ apr_bucket *pbkt;
+
+ // XXX: it may be possible to not always flush
+ pbkt=apr_bucket_flush_create();
+ APR_BRIGADE_INSERT_TAIL(pbbOutput,pbkt);
+ ap_pass_brigade(pCtx->pOutputFilter->next,pbbOutput);
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t tls_out_filter(ap_filter_t *f,apr_bucket_brigade *pbbIn)
+{
+ TLSFilterCtx *pCtx=f->ctx;
+ apr_bucket *pbktIn;
+ int bFlush=0;
+ apr_status_t ret;
+
+ APR_BRIGADE_FOREACH(pbktIn,pbbIn) {
+ const char *data;
+ apr_size_t len;
+
+ if(APR_BUCKET_IS_EOS(pbktIn)) {
+ // XXX: why can't I reuse pbktIn???
+ // XXX: isn't this wrong?
+ // Write eof!
+ break;
+ }
+
+ if(APR_BUCKET_IS_FLUSH(pbktIn)) {
+ bFlush=1;
+ continue;
+ }
+
+ // read filter
+ apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ);
+
+ // write SSL
+ SSLStateMachine_write_inject(pCtx->pStateMachine,data,len);
+
+ }
+
+ // churn the state machine
+ ret=churn(pCtx);
+
+ if(bFlush) {
+ apr_bucket_brigade *pbbOut;
+ apr_bucket *pbktOut;
+
+ pbbOut=apr_brigade_create(f->c->pool);
+ pbktOut=apr_bucket_flush_create();
+ APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut);
+ // XXX: and what if this returns an error???
+ ap_pass_brigade(f->next,pbbOut);
+ }
+ return ret;
+}
+
+static apr_status_t tls_in_filter(ap_filter_t *f,apr_bucket_brigade *pbbOut,
+ ap_input_mode_t eMode)
+{
+ TLSFilterCtx *pCtx=f->ctx;
+ apr_bucket *pbktIn;
+ apr_bucket_brigade *pbbIn;
+ apr_read_type_e eReadType=eMode == AP_MODE_BLOCKING ? APR_BLOCK_READ :
+ APR_NONBLOCK_READ;
+
+ // XXX: we don't currently support peek
+ assert(eMode != AP_MODE_PEEK);
+
+ pbbIn=apr_brigade_create(f->c->pool);
+ ap_get_brigade(f->next,pbbIn,eMode);
+
+ APR_BRIGADE_FOREACH(pbktIn,pbbIn) {
+ const char *data;
+ apr_size_t len;
+ int n;
+ char buf[1024];
+
+ if(APR_BUCKET_IS_EOS(pbktIn)) {
+ // XXX: why can't I reuse pbktIn???
+ // XX: isn't this wrong?
+ // Write eof!
+ break;
+ }
+
+ // read filter
+ apr_bucket_read(pbktIn,&data,&len,eReadType);
+
+ // presumably this can only happen when we are non-blocking
+ if(len == 0) {
+ assert(eReadType == APR_NONBLOCK_READ);
+ break;
+ }
+
+ assert(len > 0);
+
+ // write SSL
+ SSLStateMachine_read_inject(pCtx->pStateMachine,data,len);
+
+ n=SSLStateMachine_read_extract(pCtx->pStateMachine,buf,sizeof buf);
+ if(n > 0) {
+ apr_bucket *pbktOut;
+ char *pbuf;
+
+ pbuf=apr_memdup(pCtx->pInputFilter->c->pool,buf,n);
+ // XXX: should we use a heap bucket instead? Or a transient (in
+ // which case we need a separate brigade for each bucket)?
+ pbktOut=apr_bucket_pool_create(pbuf,n,pCtx->pInputFilter->c->pool);
+ APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut);
+
+ // Once we've read something, we can move to non-blocking mode (if
+ // we weren't already).
+ eReadType=APR_NONBLOCK_READ;
+
+ // XXX: deal with EOF!
+ /* } else if(n == 0) {
+ apr_bucket *pbktEOS=apr_bucket_create_eos();
+ APR_BRIGADE_INSERT_TAIL(pbbInput,pbktEOS);*/
+ }
+ assert(n >= 0);
+
+ // churn the state machine
+ // XXX: check for errors
+ churn(pCtx);
+ }
+
+ return APR_SUCCESS;
+}
+
+static const char *tls_method(const request_rec *r)
+{
+ TLSServerConfig *pConfig =
+ ap_get_module_config(r->connection->base_server->module_config,
+ &tls_module);
+
+ if (!pConfig->bEnabled)
+ return NULL;
+
+ return "https";
+}
+
+static unsigned short tls_port(const request_rec *r)
+{
+ TLSServerConfig *pConfig =
+ ap_get_module_config(r->connection->base_server->module_config,
+ &tls_module);
+
+ if (!pConfig->bEnabled)
+ return 0;
+
+ return 443;
+}
+
+static const command_rec tls_cmds[] =
+{
+ /* XXX: We should be able to add the filter using AddOutputFilter */
+ AP_INIT_FLAG("TLSFilter", tls_on, NULL, RSRC_CONF,
+ "Run TLS/SSL on this host"),
+ AP_INIT_TAKE1("TLSCertificateFile", tls_cert_file, NULL, RSRC_CONF,
+ "Set the certificate file for this host"),
+ { NULL }
+};
+
+static void register_hooks(apr_pool_t *p)
+{
+ SSLStateMachine_init();
+
+ ap_register_output_filter(s_szTLSFilterName,tls_out_filter,
+ AP_FTYPE_NETWORK);
+ ap_register_input_filter(s_szTLSFilterName,tls_in_filter,
+ AP_FTYPE_NETWORK);
+ ap_hook_pre_connection(tls_filter_inserter,NULL,NULL,APR_HOOK_MIDDLE);
+ ap_hook_default_port(tls_port,NULL,NULL,APR_HOOK_MIDDLE);
+ ap_hook_http_method(tls_method,NULL,NULL,APR_HOOK_MIDDLE);
+}
+
+AP_DECLARE_DATA module tls_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ create_tls_server_config, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ tls_cmds, /* command apr_table_t */
+ register_hooks /* register hooks */
+};
--- /dev/null
+/* This is adapted from the OpenSSL state_machine demo */
+
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * Nuron, a leader in hardware encryption technology, generously
+ * sponsored the development of this demo by Ben Laurie.
+ *
+ * See http://www.nuron.com/.
+ */
+
+/*
+ * the aim of this demo is to provide a fully working state-machine
+ * style SSL implementation, i.e. one where the main loop acquires
+ * some data, then converts it from or to SSL by feeding it into the
+ * SSL state machine. It then does any I/O required by the state machine
+ * and loops.
+ *
+ * In order to keep things as simple as possible, this implementation
+ * listens on a TCP socket, which it expects to get an SSL connection
+ * on (for example, from s_client) and from then on writes decrypted
+ * data to stdout and encrypts anything arriving on stdin. Verbose
+ * commentary is written to stderr.
+ *
+ * This implementation acts as a server, but it can also be done for a client. */
+
+#include <openssl/ssl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <openssl/err.h>
+#include "openssl_state_machine.h"
+
+/* die_unless is intended to work like assert, except that it happens
+ always, even if NDEBUG is defined. Use assert as a stopgap. */
+
+#define die_unless(x) assert(x)
+
+struct SSLStateMachine
+ {
+ SSL_CTX *pCtx;
+ BIO *pbioRead;
+ BIO *pbioWrite;
+ SSL *pSSL;
+ };
+
+void SSLStateMachine_init(void)
+{
+ static int s_bInitDone;
+
+ if(s_bInitDone)
+ return;
+
+ SSL_library_init();
+ OpenSSL_add_ssl_algorithms();
+ SSL_load_error_strings();
+ ERR_load_crypto_strings();
+
+ s_bInitDone=1;
+}
+
+static void SSLStateMachine_print_error(SSLStateMachine *pMachine,
+ const char *szErr)
+ {
+ unsigned long l;
+
+ fprintf(stderr,"%s\n",szErr);
+ while((l=ERR_get_error()))
+ {
+ char buf[1024];
+
+ ERR_error_string_n(l,buf,sizeof buf);
+ fprintf(stderr,"Error %lx: %s\n",l,buf);
+ }
+ }
+
+SSLStateMachine *SSLStateMachine_new(const char *szCertificateFile,
+ const char *szKeyFile)
+ {
+ SSLStateMachine *pMachine=malloc(sizeof *pMachine);
+ int n;
+
+ die_unless(pMachine);
+
+ pMachine->pCtx=SSL_CTX_new(SSLv23_server_method());
+ die_unless(pMachine->pCtx);
+
+ n=SSL_CTX_use_certificate_file(pMachine->pCtx,szCertificateFile,
+ SSL_FILETYPE_PEM);
+ die_unless(n > 0);
+
+ n=SSL_CTX_use_PrivateKey_file(pMachine->pCtx,szKeyFile,SSL_FILETYPE_PEM);
+ die_unless(n > 0);
+
+ pMachine->pSSL=SSL_new(pMachine->pCtx);
+ die_unless(pMachine->pSSL);
+
+ pMachine->pbioRead=BIO_new(BIO_s_mem());
+
+ pMachine->pbioWrite=BIO_new(BIO_s_mem());
+
+ SSL_set_bio(pMachine->pSSL,pMachine->pbioRead,pMachine->pbioWrite);
+
+ SSL_set_accept_state(pMachine->pSSL);
+
+ return pMachine;
+ }
+
+void SSLStateMachine_read_inject(SSLStateMachine *pMachine,
+ const unsigned char *aucBuf,int nBuf)
+ {
+ int n=BIO_write(pMachine->pbioRead,aucBuf,nBuf);
+ /* If it turns out this assert fails, then buffer the data here
+ * and just feed it in in churn instead. Seems to me that it
+ * should be guaranteed to succeed, though.
+ */
+ assert(n == nBuf);
+ fprintf(stderr,"%d bytes of encrypted data fed to state machine\n",n);
+ }
+
+int SSLStateMachine_read_extract(SSLStateMachine *pMachine,
+ unsigned char *aucBuf,int nBuf)
+ {
+ int n;
+
+ if(!SSL_is_init_finished(pMachine->pSSL))
+ {
+ fprintf(stderr,"Doing SSL_accept\n");
+ n=SSL_accept(pMachine->pSSL);
+ if(n == 0)
+ fprintf(stderr,"SSL_accept returned zero\n");
+ if(n < 0)
+ {
+ int err;
+
+ if((err=SSL_get_error(pMachine->pSSL,n)) == SSL_ERROR_WANT_READ)
+ {
+ fprintf(stderr,"SSL_accept wants more data\n");
+ return 0;
+ }
+
+ SSLStateMachine_print_error(pMachine,"SSL_accept error");
+ exit(7);
+ }
+ return 0;
+ }
+
+ n=SSL_read(pMachine->pSSL,aucBuf,nBuf);
+ if(n < 0)
+ {
+ int err=SSL_get_error(pMachine->pSSL,n);
+
+ if(err == SSL_ERROR_WANT_READ)
+ {
+ fprintf(stderr,"SSL_read wants more data\n");
+ return 0;
+ }
+ }
+
+ fprintf(stderr,"%d bytes of decrypted data read from state machine\n",n);
+ return n;
+ }
+
+int SSLStateMachine_write_can_extract(SSLStateMachine *pMachine)
+ {
+ int n=BIO_pending(pMachine->pbioWrite);
+ if(n)
+ fprintf(stderr,"There is encrypted data available to write\n");
+ else
+ fprintf(stderr,"There is no encrypted data available to write\n");
+
+ return n;
+ }
+
+int SSLStateMachine_write_extract(SSLStateMachine *pMachine,
+ unsigned char *aucBuf,int nBuf)
+ {
+ int n;
+
+ n=BIO_read(pMachine->pbioWrite,aucBuf,nBuf);
+ fprintf(stderr,"%d bytes of encrypted data read from state machine\n",n);
+ return n;
+ }
+
+void SSLStateMachine_write_inject(SSLStateMachine *pMachine,
+ const unsigned char *aucBuf,int nBuf)
+ {
+ int n=SSL_write(pMachine->pSSL,aucBuf,nBuf);
+ /* If it turns out this assert fails, then buffer the data here
+ * and just feed it in in churn instead. Seems to me that it
+ * should be guaranteed to succeed, though.
+ */
+ assert(n == nBuf);
+ fprintf(stderr,"%d bytes of unencrypted data fed to state machine\n",n);
+ }
--- /dev/null
+typedef struct SSLStateMachine SSLStateMachine;
+
+void SSLStateMachine_init(void);
+SSLStateMachine *SSLStateMachine_new(const char *szCertificateFile,
+ const char *szKeyFile);
+void SSLStateMachine_read_inject(SSLStateMachine *pMachine,
+ const unsigned char *aucBuf,int nBuf);
+int SSLStateMachine_read_extract(SSLStateMachine *pMachine,
+ unsigned char *aucBuf,int nBuf);
+int SSLStateMachine_write_can_extract(SSLStateMachine *pMachine);
+int SSLStateMachine_write_extract(SSLStateMachine *pMachine,
+ unsigned char *aucBuf,int nBuf);
+void SSLStateMachine_write_inject(SSLStateMachine *pMachine,
+ const unsigned char *aucBuf,int nBuf);
register_filter(name, f, ftype, ®istered_output_filters);
}
-static void add_any_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c,
- ap_filter_rec_t *frec,
- ap_filter_t **r_filters,
- ap_filter_t **c_filters)
+static ap_filter_t *add_any_filter(const char *name, void *ctx,
+ request_rec *r, conn_rec *c,
+ ap_filter_rec_t *frec,
+ ap_filter_t **r_filters,
+ ap_filter_t **c_filters)
{
for (; frec != NULL; frec = frec->next) {
if (!strcasecmp(name, frec->name)) {
fscan->next = f;
}
- return;
+ return f;
}
}
"an unknown filter was not added: %s", name);
}
-AP_DECLARE(void) ap_add_input_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c)
+AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
+ request_rec *r, conn_rec *c)
{
- add_any_filter(name, ctx, r, c, registered_input_filters,
- r ? &r->input_filters : NULL, &c->input_filters);
+ return add_any_filter(name, ctx, r, c, registered_input_filters,
+ r ? &r->input_filters : NULL, &c->input_filters);
}
-AP_DECLARE(void) ap_add_output_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c)
+AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
+ request_rec *r, conn_rec *c)
{
- add_any_filter(name, ctx, r, c, registered_output_filters,
- r ? &r->output_filters : NULL, &c->output_filters);
+ return add_any_filter(name, ctx, r, c, registered_output_filters,
+ r ? &r->output_filters : NULL, &c->output_filters);
}
AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)