[mod_openssl] new module (preliminary layout)

personal/stbuehler/mod-csrf
Glenn Strauss 2016-12-21 04:23:49 -05:00
parent cb7ed13621
commit cb9ebe9fa6
7 changed files with 270 additions and 2 deletions

View File

@ -229,7 +229,7 @@ if 1:
autoconf.env.Append( LIBSQLITE3 = '', LIBXML2 = '', LIBMYSQL = '', LIBZ = '',
LIBBZ2 = '', LIBCRYPT = '', LIBMEMCACHED = '', LIBFCGI = '', LIBPCRE = '',
LIBLDAP = '', LIBLBER = '', LIBLUA = '', LIBDL = '', LIBUUID = '',
LIBKRB5 = '', LIBGSSAPI_KRB5 = '', LIBGDBM = '')
LIBKRB5 = '', LIBGSSAPI_KRB5 = '', LIBGDBM = '', LIBSSL = '', LIBCRYPTO = '')
if env['with_fam']:
if autoconf.CheckLibWithHeader('fam', 'fam.h', 'C'):
@ -253,7 +253,7 @@ if 1:
if env['with_openssl']:
if autoconf.CheckLibWithHeader('ssl', 'openssl/ssl.h', 'C'):
autoconf.env.Append(CPPFLAGS = [ '-DHAVE_OPENSSL_SSL_H', '-DHAVE_LIBSSL'] , LIBS = [ 'ssl', 'crypto' ])
autoconf.env.Append(CPPFLAGS = [ '-DHAVE_OPENSSL_SSL_H', '-DHAVE_LIBSSL'] , LIBSSL = 'ssl', LIBCRYPTO = 'crypto', LIBS = [ 'ssl', 'crypto' ])
if env['with_gzip']:
if autoconf.CheckLibWithHeader('z', 'zlib.h', 'C'):

View File

@ -383,6 +383,7 @@ else
use_openssl=no
fi
AC_MSG_RESULT([$use_openssl])
AM_CONDITIONAL(BUILD_WITH_OPENSSL, test ! $WITH_OPENSSL = no)
AC_ARG_WITH(openssl-includes,
AC_HELP_STRING([--with-openssl-includes=DIR],[OpenSSL includes]),
@ -403,10 +404,12 @@ if test "x$use_openssl" = "xyes"; then
OLDLIBS="$LIBS"
AC_CHECK_LIB(crypto, BIO_f_base64, [
AC_CHECK_LIB(ssl, SSL_new, [ SSL_LIB="-lssl -lcrypto"
CRYPTO_LIB="-lcrypto"
AC_DEFINE(HAVE_LIBSSL, [], [Have libssl]) ], [], [ -lcrypto "$DL_LIB" ])
], [], [])
LIBS="$OLDLIBS"
AC_SUBST(SSL_LIB)
AC_SUBST(CRYPTO_LIB)
fi
AC_MSG_CHECKING(for perl regular expressions support)

View File

@ -774,6 +774,9 @@ endif()
if(HAVE_LIBSSL AND HAVE_LIBCRYPTO)
target_link_libraries(lighttpd ssl)
target_link_libraries(lighttpd crypto)
add_and_install_library(mod_openssl "mod_openssl.c")
set(L_MOD_OPENSSL ${L_MOD_OPENSSL} ssl crypto)
target_link_libraries(mod_openssl ${L_MOD_OPENSSL})
endif()
if(WITH_LIBEV)

View File

@ -300,6 +300,13 @@ mod_authn_mysql_la_LIBADD = $(CRYPT_LIB) $(MYSQL_LIBS) $(common_libadd)
mod_authn_mysql_la_CPPFLAGS = $(MYSQL_INCLUDE)
endif
if BUILD_WITH_OPENSSL
lib_LTLIBRARIES += mod_openssl.la
mod_openssl_la_SOURCES = mod_openssl.c
mod_openssl_la_LDFLAGS = $(common_module_ldflags)
mod_openssl_la_LIBADD = $(SSL_LIB) $(common_libadd)
endif
lib_LTLIBRARIES += mod_rewrite.la
mod_rewrite_la_SOURCES = mod_rewrite.c
mod_rewrite_la_LDFLAGS = $(common_module_ldflags)
@ -416,6 +423,10 @@ lighttpd_SOURCES += mod_authn_mysql.c mod_mysql_vhost.c
lighttpd_CPPFLAGS += $(MYSQL_INCLUDE)
lighttpd_LDADD += $(MYSQL_LIBS)
endif
if BUILD_WITH_OPENSSL
lighttpd_SOURCES += mod_openssl.c
lighttpd_LDADD += $(SSL_LIB)
endif
if BUILD_WITH_MEMCACHED
lighttpd_CPPFLAGS += $(MEMCACHED_CFLAGS)
lighttpd_LDADD += $(MEMCACHED_LIB)

View File

@ -147,6 +147,9 @@ if env['with_mysql']:
modules['mod_authn_mysql'] = { 'src' : [ 'mod_authn_mysql.c' ], 'lib' : [ env['LIBCRYPT'], env['LIBMYSQL'] ] }
modules['mod_mysql_vhost'] = { 'src' : [ 'mod_mysql_vhost.c' ], 'lib' : [ env['LIBMYSQL'] ] }
if env['with_openssl']:
modules['mod_openssl'] = { 'src' : [ 'mod_openssl.c' ], 'lib' : [ env['LIBSSL'], env['LIBCRYPTO'] ] }
staticenv = env.Clone(CPPFLAGS=[ env['CPPFLAGS'], '-DLIGHTTPD_STATIC' ])
## all the core-sources + the modules

View File

@ -46,6 +46,25 @@ static void config_warn_authn_module (server *srv, const char *module) {
}
#endif
#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
static void config_warn_openssl_module (server *srv) {
for (size_t i = 0; i < srv->config_context->used; ++i) {
const data_config *config = (data_config const*)srv->config_context->data[i];
for (size_t j = 0; j < config->value->used; ++j) {
data_unset *du = config->value->data[j];
if (0 == strncmp(du->key->ptr, "ssl.", sizeof("ssl.")-1)) {
/* mod_openssl should be loaded after mod_extforward */
data_string *ds = data_string_init();
buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_openssl"));
array_insert_unique(srv->srvconf.modules, (data_unset *)ds);
log_error_write(srv, __FILE__, __LINE__, "S", "Warning: please add \"mod_openssl\" to server.modules list in lighttpd.conf. A future release of lighttpd 1.4.x *will not* automatically load mod_openssl and lighttpd *will not* use SSL/TLS where your lighttpd.conf contains ssl.* directives");
return;
}
}
}
}
#endif
static int config_insert(server *srv) {
size_t i;
int ret = 0;
@ -372,6 +391,7 @@ static int config_insert(server *srv) {
int append_mod_authn_file = 1;
int append_mod_authn_ldap = 1;
int append_mod_authn_mysql = 1;
int append_mod_openssl = 1;
int contains_mod_auth = 0;
/* prepend default modules */
@ -390,6 +410,10 @@ static int config_insert(server *srv) {
append_mod_dirlisting = 0;
}
if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_openssl"))) {
append_mod_openssl = 0;
}
if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_authn_file"))) {
append_mod_authn_file = 0;
}
@ -409,6 +433,7 @@ static int config_insert(server *srv) {
if (0 == prepend_mod_indexfile &&
0 == append_mod_dirlisting &&
0 == append_mod_staticfile &&
0 == append_mod_openssl &&
0 == append_mod_authn_file &&
0 == append_mod_authn_ldap &&
0 == append_mod_authn_mysql &&
@ -447,6 +472,12 @@ static int config_insert(server *srv) {
array_insert_unique(srv->srvconf.modules, (data_unset *)ds);
}
if (append_mod_openssl) {
#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
config_warn_openssl_module(srv);
#endif
}
/* mod_auth.c,http_auth.c auth backends were split into separate modules
* Automatically load auth backend modules for compatibility with
* existing lighttpd 1.4.x configs */

217
src/mod_openssl.c Normal file
View File

@ -0,0 +1,217 @@
#include "first.h"
#include <errno.h>
#include <string.h>
#ifndef USE_OPENSSL_KERBEROS
#ifndef OPENSSL_NO_KRB5
#define OPENSSL_NO_KRB5
#endif
#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "base.h"
#include "log.h"
#include "plugin.h"
typedef struct {
int dummy;
} plugin_config;
typedef struct {
PLUGIN_DATA;
plugin_config **config_storage;
plugin_config conf;
} plugin_data;
typedef struct {
SSL *ssl;
buffer *tlsext_server_name;
unsigned int renegotiations; /* count of SSL_CB_HANDSHAKE_START */
int request_env_patched;
plugin_config conf;
} handler_ctx;
static handler_ctx *
handler_ctx_init (void)
{
handler_ctx *hctx = calloc(1, sizeof(*hctx));
force_assert(hctx);
return hctx;
}
static void
handler_ctx_free (handler_ctx *hctx)
{
buffer_free(hctx->tlsext_server_name);
free(hctx);
}
INIT_FUNC(mod_openssl_init)
{
return calloc(1, sizeof(plugin_data));
}
FREE_FUNC(mod_openssl_free)
{
plugin_data *p = p_d;
if (!p) return HANDLER_GO_ON;
if (p->config_storage) {
for (size_t i = 0; i < srv->config_context->used; ++i) {
plugin_config *s = p->config_storage[i];
if (NULL == s) continue;
free(s);
}
free(p->config_storage);
}
free(p);
UNUSED(srv);
return HANDLER_GO_ON;
}
SETDEFAULTS_FUNC(mod_openssl_set_defaults)
{
UNUSED(srv);
UNUSED(p_d);
return HANDLER_GO_ON;
}
#define PATCH(x) \
p->conf.x = s->x;
static int
mod_openssl_patch_connection (server *srv, connection *con, handler_ctx *p)
{
UNUSED(srv);
UNUSED(con);
UNUSED(p);
return 0;
}
#undef PATCH
CONNECTION_FUNC(mod_openssl_handle_con_accept)
{
server_socket *srv_sock = con->srv_socket;
if (!srv_sock->is_ssl) return HANDLER_GO_ON;
{
plugin_data *p = p_d;
handler_ctx *hctx = handler_ctx_init();
con->plugin_ctx[p->id] = hctx;
mod_openssl_patch_connection(srv, con, hctx);
}
return HANDLER_GO_ON;
}
CONNECTION_FUNC(mod_openssl_handle_con_shut_wr)
{
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
if (NULL == hctx) return HANDLER_GO_ON;
UNUSED(srv);
return HANDLER_GO_ON;
}
CONNECTION_FUNC(mod_openssl_handle_con_close)
{
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
if (NULL == hctx) return HANDLER_GO_ON;
handler_ctx_free(hctx);
UNUSED(srv);
return HANDLER_GO_ON;
}
CONNECTION_FUNC(mod_openssl_handle_request_env)
{
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
if (NULL == hctx) return HANDLER_GO_ON;
if (hctx->request_env_patched) return HANDLER_GO_ON;
hctx->request_env_patched = 1;
UNUSED(srv);
return HANDLER_GO_ON;
}
CONNECTION_FUNC(mod_openssl_handle_uri_raw)
{
/* mod_openssl must be loaded prior to mod_auth
* if mod_openssl is configured to set REMOTE_USER based on client cert */
/* mod_openssl must be loaded after mod_extforward
* if mod_openssl config is based on lighttpd.conf remote IP conditional
* using remote IP address set by mod_extforward */
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
if (NULL == hctx) return HANDLER_GO_ON;
if (con->conf.ssl_verifyclient) {
mod_openssl_handle_request_env(srv, con, p);
}
return HANDLER_GO_ON;
}
CONNECTION_FUNC(mod_openssl_handle_request_reset)
{
plugin_data *p = p_d;
handler_ctx *hctx = con->plugin_ctx[p->id];
if (NULL == hctx) return HANDLER_GO_ON;
/*
* XXX: preserve (for now) lighttpd historical behavior which resets
* tlsext_server_name after each request, meaning SNI is valid only for
* initial request, prior to reading request headers. Probably should
* instead validate that Host header (or authority in request line)
* matches SNI server name for all requests on the connection on which
* SNI extension has been provided.
*/
buffer_reset(hctx->tlsext_server_name);
hctx->request_env_patched = 0;
UNUSED(srv);
return HANDLER_GO_ON;
}
int mod_openssl_plugin_init (plugin *p);
int mod_openssl_plugin_init (plugin *p)
{
p->version = LIGHTTPD_VERSION_ID;
p->name = buffer_init_string("openssl");
p->init = mod_openssl_init;
p->cleanup = mod_openssl_free;
p->set_defaults = mod_openssl_set_defaults;
p->handle_connection_accept = mod_openssl_handle_con_accept;
p->handle_connection_shut_wr = mod_openssl_handle_con_shut_wr;
p->handle_connection_close = mod_openssl_handle_con_close;
p->handle_uri_raw = mod_openssl_handle_uri_raw;
p->handle_request_env = mod_openssl_handle_request_env;
p->connection_reset = mod_openssl_handle_request_reset;
p->data = NULL;
return 0;
}