aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--include/memcache.h402
-rw-r--r--include/mod_gnutls.h12
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gnutls_cache.c206
-rw-r--r--src/gnutls_io.c30
-rw-r--r--src/mod_gnutls.c46
7 files changed, 258 insertions, 444 deletions
diff --git a/configure.ac b/configure.ac
index 1a72b8c..001f145 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,8 +24,8 @@ CHECK_LIBGNUTLS($MIN_TLS_VERSION)
24 24
25CHECK_APR_MEMCACHE() 25CHECK_APR_MEMCACHE()
26 26
27MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES}" 27MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${APR_MEMCACHE_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES}"
28MODULE_LIBS="${LIBGNUTLS_LIBS} ${APR_MEMCACHE_LIBS}" 28MODULE_LIBS="${APR_MEMCACHE_LIBS} ${LIBGNUTLS_LIBS}"
29 29
30AC_SUBST(MODULE_CFLAGS) 30AC_SUBST(MODULE_CFLAGS)
31AC_SUBST(MODULE_LIBS) 31AC_SUBST(MODULE_LIBS)
diff --git a/include/memcache.h b/include/memcache.h
deleted file mode 100644
index b11bf4c..0000000
--- a/include/memcache.h
+++ /dev/null
@@ -1,402 +0,0 @@
1/* Copyright (c) 2004 Sean Chittenden <sean@chittenden.org>
2 *
3 * All rights reserved until such time as this code is released with
4 * an official license. Use of this code for commerical,
5 * non-commercial, and personal purposes is encouraged. Public forks
6 * of this code is permitted so long as the fork and its decendents
7 * use this copyright/license. Use of this software in programs
8 * released under the GPL programs is expressly prohibited by the
9 * author (ie, BSD, closed source, or artistic license is okay, but
10 * GPL is not). */
11
12#ifndef MEMCACHE_H
13#define MEMCACHE_H
14
15#include <netdb.h>
16#include <sys/queue.h>
17#include <sys/types.h>
18#include <sys/time.h>
19#include <unistd.h>
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25/* Our initial read(2) buffer has to be long enough to read the
26 * first line of the response. ie:
27 *
28 * "VALUE #{'k' * 250} #{2 ** 15} #{2 ** 32}\r\n.length => 275
29 *
30 * However, since we want to avoid the number of system calls
31 * necessary, include trailing part of the protocol in our estimate:
32 *
33 * "\r\nEND\r\n".length => 7
34 *
35 * Which yields a manditory limit of 282 bytes for a successful
36 * response. If we wish to try and get lucky with our first read(2)
37 * call and be able to read(2) in small values without making a second
38 * read(2) call, pad this number with a sufficiently large byte value.
39 * If most of your keys are 512B, then a GET_INIT_BUF_SIZE of 794
Nokis Mavrogiannopoulos 2007-12-08
* added more error checks.Gravatar Nokis Mavrogiannopoulos 2007-12-03
* better handling of RSAFile and DHFileGravatar Nokis Mavrogiannopoulos 2007-12-03
* report the missing GnuTLSPriorities for the gnutls enabled hosts only.Gravatar Nokis Mavrogiannopoulos 2007-12-02
* No more defaults for dhparams, rsaparams. Check for GnuTLSPriorities.Gravatar Nokis Mavrogiannopoulos 2007-12-02
* The compatibility mode can now be enabled only using the GnuTLSPriorities str...Gravatar Nokis Mavrogiannopoulos 2007-12-02
* (no commit message)Gravatar Nokis Mavrogiannopoulos 2007-12-02
* added SSL_SERVER/CLIENT_S_TYPEGravatar Nokis Mavrogiannopoulos 2007-12-02
* export the alternative names of the certificateGravatar Nokis Mavrogiannopoulos 2007-12-02
id=76bd3bfed0fda6fb670cb14c16bcdfd47453dfe5#n55'>55#define PEDANTIC 56 57#define MAX_KEY_LEN 250 58 59#define HAVE_SELECT 1 60 61#define USE_CRC32_HASH 1 62/* #define USE_ELF_HASH 1 */ 63/* #define USE_PERL_HASH 1 */ 64 65/* Various values for _flags */ 66#define MC_RES_FREE_ON_DELETE 0x01 67#define MC_RES_NO_FREE_ON_DELETE 0x02 68#define MC_RES_FOUND 0x04 69struct memcache_res { 70 const char *key; /* key */ 71 size_t len; /* length of key */ 72 u_int32_t hash; /* hash of the key */ 73 void *val; /* the value */ 74 size_t bytes; /* length of val */ 75 76 /* If size is zero (default), the memory for val is automatically 77 * allocated using mcMalloc(3). If size is zero, _flags has its 78 * MC_RES_FREE_ON_DELETE bit set. 79 * 80 * If size is non-zero, libmemcache(3) assumes that the caller has 81 * set val to an available portion of memory that is size bytes 82 * long. libmemcache(3) will only populate val with as many bytes 83 * as are specified by size (ie, it will trim the value in order to 84 * fit into val). If size is non-zero, _flags has its 85 * MC_RES_NO_FREE_ON_DELETE bit set by default. */ 86 size_t size; 87 TAILQ_ENTRY(memcache_res) entries; 88 89 /* Note: this flags is very different than _flags. */ 90 u_int16_t flags; 91 92 /* If _flags has 0x01 set, val will be free(3)'ed on when this 93 * struct is cleaned up via mc_res_free() or the request is cleaned 94 * up via mc_req_free(). 95 * 96 * If _flags has is 0x02 set, val will not be free(3)'ed when this 97 * response or its parent request are cleaned up. 98 * 99 * Note: Use mc_res_free_on_delete() to set the "free on delete" 100 * bits. */ 101 char _flags; 102}; 103 104struct memcache_req { 105 TAILQ_HEAD(memcache_res_list, memcache_res) query; 106 u_int16_t num_keys; 107}; 108 109struct memcache_server { 110 /* The hostname of the server. */ 111 char *hostname; 112 113 /* Port number of the host we're connecting to. */ 114 char *port; 115 116 /* The file descriptor for this server */ 117 int fd; 118 119 /* The file descriptor flags */ 120 int flags; 121 122 /* The timeout for this server */ 123 struct timeval tv; 124 125 /* Is this particular server active or not? 126 * 127 * 'd' == Down Last request was unsuccessful 128 * 'n' == No host The hostname doesn't exist 129 * 't' == Try Haven't connected to it yet, will attempt 130 * 'u' == Up Has been connected to successfully 131 */ 132 char active; 133 134 /* A cached copy of the looked up host. */ 135 struct addrinfo *hostinfo; 136 137 /* The number of addresses in the cached copy. If there is more 138 * than one per DNS entry (discouraged), we establish a connection 139 * to them all. */ 140 u_int32_t num_addrs; 141 142#ifdef HAVE_SELECT 143 /* Reduces the amount of user time required when reading data. */ 144 fd_set fds; 145 struct timeval select_tv; 146#endif 147 148 /* Misc list bits */ 149 TAILQ_ENTRY(memcache_server) entries; 150}; 151 152 153struct memcache_server_stats { 154 pid_t pid; 155 time_t uptime; 156 time_t time; 157 char *version; 158 struct timeval rusage_user; 159 struct timeval rusage_system; 160 u_int32_t curr_items; 161 u_int64_t total_items; 162 u_int64_t bytes; 163 u_int32_t curr_connections; 164 u_int64_t total_connections; 165 u_int32_t connection_structures; 166 u_int64_t cmd_get; 167 u_int64_t cmd_refresh; 168 u_int64_t cmd_set; 169 u_int64_t get_hits; 170 u_int64_t get_misses; 171 u_int64_t refresh_hits; 172 u_int64_t refresh_misses; 173 u_int64_t bytes_read; 174 u_int64_t bytes_written; 175 u_int64_t limit_maxbytes; 176}; 177 178 179struct memcache { 180 /* The default timeout for all servers */ 181 struct timeval tv; 182 183 /* The default read(2) size when reading a response. */ 184 size_t read_size; 185 186 /* The complete list of servers */ 187 TAILQ_HEAD(memcache_server_list, memcache_server) server_list; 188 189 /* A buffer for data */ 190 char *buf; 191 192 /* A cursor for where we are in the buffer */ 193 char *cur; 194 195 /* A pointer to where data should be appended with future read(2) 196 * calls. */ 197 char *read_cur; 198 199 /* A pointer to the start of the current line in the buffer. */ 200 char *start; 201 202 /* The allocated size of the buffer */ 203 size_t size; 204 205 /* The number of servers in live_servers */ 206 u_int32_t num_live_servers; 207 208 /* An array of usable memcache_servers */ 209 struct memcache_server **live_servers; 210}; 211 212 213/* Adds a given key to the cache */ 214int mc_add(struct memcache *mc, 215 const char *key, const size_t key_len, 216 const void *val, const size_t bytes, 217 const time_t expire, const u_int16_t flags); 218 219/* Gets the value from memcache and allocates the data for the caller. 220 * It is the caller's responsibility to free the returned value. 221 * mc_get() is the preferred interface, however. */ 222void *mc_aget(struct memcache *mc, const char *key, const size_t len); 223 224/* Gets the value from memcache and allocates the data for the caller. 225 * It is the caller's responsibility to free the returned value. 226 * mc_refresh() is the preferred interface, however. */ 227void *mc_arefresh(struct memcache *mc, const char *key, const size_t len); 228 229/* Disconnects from a given server and marks it as down. */ 230void mc_deactivate_server(struct memcache *mc, struct memcache_server *ms); 231 232/* Decrements a given key */ 233u_int32_t mc_decr(struct memcache *mc, const char *key, const size_t key_len, const u_int32_t val); 234 235/* Deletes a given key */ 236int mc_delete(struct memcache *mc, const char *key, const size_t key_len, const time_t hold); 237 238/* When given a hash value, this function returns the appropriate 239 * server to connect to in order to find the key. */ 240struct memcache_server *mc_find_server(struct memcache *mc, const u_int32_t hash); 241 242/* Flushes all keys */ 243int mc_flush_all(struct memcache *mc, const char *key, const size_t key_len); 244 245/* cleans up a memcache object. */ 246void mc_free(struct memcache *mc); 247 248/* Tells the response object to free the allocated memory when it gets 249 * cleaned up or to let the caller manage the memory. */ 250void mc_res_free_on_delete(struct memcache_res *res, int free_on_delete); 251 252/* mc_get() is the preferred method of accessing memcache. It 253 * accepts multiple keys and lets a user (should they so choose) 254 * perform memory caching to reduce the number of mcMalloc(3) calls 255 * mades. */ 256void mc_get(struct memcache *mc, struct memcache_req *req); 257 258/* Generates a hash value from a given key */ 259u_int32_t mc_hash_key(const char *key, const size_t len); 260 261/* Increments a given key */ 262u_int32_t mc_incr(struct memcache *mc, const char *key, const size_t key_len, const u_int32_t val); 263 264/* Allocates a new memcache object */ 265struct memcache *mc_new(void); 266 267/* mc_refresh() is the preferred method of accessing memcache. It 268 * accepts multiple keys and lets a user (should they so choose) 269 * perform memory caching to reduce the number of mcMalloc(3) calls 270 * mades. mc_refresh() differs from mc_get() in that mc_refresh 271 * updates the expiration time to be now + whatever the expiration for 272 * the item was set to. Sessions should use this as a way of noting 273 * sessions expiring. */ 274void mc_refresh(struct memcache *mc, struct memcache_req *req); 275 276/* Replaces a given key to the cache */ 277int mc_replace(struct memcache *mc, 278 const char *key, const size_t key_len, 279 const void *val, const size_t bytes, 280 const time_t expire, const u_int16_t flags); 281 282/* Adds a key to a given request */ 283struct memcache_res *mc_req_add(struct memcache_req *req, const char *key, size_t len); 284 285/* Cleans up a given request and its subsequent responses. If _flags 286 * has the MC_RES_FREE_ON_DELETE bit set (default), it will clean up 287 * the value too. If _flags has MC_RES_NO_FREE_ON_DELETE set, 288 * however, it is the caller's responsibility to free the value. To 289 * prevent double free(3) errors, if a value is free(3)'ed before 290 * mc_req_free() is called, set val to NULL. */ 291void mc_req_free(struct memcache_req *req); 292 293/* Allocates a new memcache request object. */ 294struct memcache_req *mc_req_new(void); 295 296/* Cleans up an individual response object. Normally this is not 297 * necessary as a call to mc_req_free() will clean up its response 298 * objects. */ 299void mc_res_free(struct memcache_req *req, struct memcache_res *res); 300 301/* Adds a server to the list of available servers. By default, 302 * servers are assumed to be available. Return codes: 303 * 304 * 0: success 305 * -1: Unable to allocate a new server instance 306 * -2: Unable to strdup hostname 307 * -3: Unable to strdup port 308 * -4: Unable to Unable to resolve the host, server deactivated, but added to list 309 * -5: Unable to realloc(3) the server list, server list unchanged */ 310int mc_server_add(struct memcache *mc, const char *hostname, const char *port); 311int mc_server_add2(struct memcache *mc, 312 const char *hostname, const size_t hostname_len, 313 const char *port, const size_t port_len); 314 315/* Cleans up a given stat's object */ 316void mc_server_stats_free(struct memcache_server_stats *s); 317 318/* Gets a stats object from the given server. It is the caller's 319 * responsibility to cleanup the resulting object via 320 * mc_server_stats_free(). */ 321struct memcache_server_stats *mc_server_stats(struct memcache *mc, struct memcache_server *ms); 322 323/* Sets a given key */ 324int mc_set(struct memcache *mc, 325 const char *key, const size_t key_len, 326 const void *val, const size_t bytes, 327 const time_t expire, const u_int16_t flags); 328 329/* Creates a stats object for all available servers and returns the 330 * cumulative stats. Per host-specific data is generally the same as 331 * the last server querried. */ 332struct memcache_server_stats *mc_stats(struct memcache *mc); 333 334/* Sets the default timeout for new servers. */ 335void mc_timeout(struct memcache *mc, const int sec, const int usec); 336 337 338 339/* BEGIN memory management API functions */ 340 341/* The memcache API allows callers to provide their own memory 342 * allocation routines to aid in embedability with existing programs, 343 * libraries, programming languages, and environments that have their 344 * own memory handling routines. This interface was inspired by 345 * libxml. */ 346typedef void (*mcFreeFunc)(void *mem); 347typedef void *(*mcMallocFunc)(const size_t size); 348typedef void *(*mcReallocFunc)(void *mem, const size_t size); 349typedef char *(*mcStrdupFunc)(const char *str); 350 351extern mcFreeFunc mcFree; 352extern mcMallocFunc mcMalloc; 353extern mcMallocFunc mcMallocAtomic; 354extern mcReallocFunc mcRealloc; 355extern mcStrdupFunc mcStrdup; 356 357int mcMemSetup(mcFreeFunc freeFunc, mcMallocFunc mallocFunc, 358 mcReallocFunc reallocFunc, mcStrdupFunc strdupFunc); 359int mcMemGet(mcFreeFunc *freeFunc, mcMallocFunc *mallocFunc, 360 mcReallocFunc *reallocFunc, mcStrdupFunc *strdupFunc); 361/* END memory management API functions */ 362 363 364/* APIs that should be implemented: */ 365 366/* Resets all hosts that are down to try */ 367void mc_server_reset_all_active(struct memcache *mc); 368 369/* Resets a given host back to a try state */ 370void mc_server_reset_active(struct memcache *mc, const char *hostname, const int port); 371 372/* Resets all dns entries */ 373void mc_server_reset_all_dns(struct memcache *mc); 374 375/* Resets only one host's DNS cache */ 376void mc_server_reset_dns(struct memcache *mc, const char *hostname, const int port); 377 378/* Disconnects from all memcache servers */ 379void mc_server_disconnect_all(struct memcache *mc); 380 381/* Disconnects from one memcache server */ 382void mc_server_disconnect(struct memcache *mc, const char *hostname, const int port); 383 384#ifdef TCP_NODELAY 385/* Enable/disable TCP_NODELAY */ 386void mc_nodelay_enable(struct memcache *mc, const int enable); 387 388/* Enable/disable TCP_NODELAY for a given server */ 389void mc_server_nodelay_enable(struct memcache_server *ms, const int enable); 390#endif 391 392/* Set the timeout on a per server basis */ 393void mc_server_timeout(struct memcache_server *ms, const int sec, const int usec); 394 395/* Set the number of seconds you're willing to wait in total for a 396 * response. ??? */ 397 398#ifdef __cplusplus 399} 400#endif 401 402#endif
diff --git a/include/mod_gnutls.h b/include/mod_gnutls.h
index 0f3433c..743a43f 100644
--- a/include/mod_gnutls.h
+++ b/include/mod_gnutls.h
@@ -29,6 +29,8 @@ 29#include "apr_strings.h" 29#include "apr_strings.h" 30#include "apr_tables.h" 30#include "apr_tables.h" 31 31 32#include "apr_memcache.h" 33 32#include <gcrypt.h> 34#include <gcrypt.h> 33#include <gnutls/gnutls.h> 35#include <gnutls/gnutls.h> 34 36@@ -68,6 +70,7 @@ typedef struct 68 int macs[16]; 70 int macs[16]; 69 int protocol[16]; 71 int protocol[16]; 70 int compression[16]; 72 int compression[16]; 73 const char* cache_config; 71} mod_gnutls_srvconf_rec; 74} mod_gnutls_srvconf_rec; 72 75 73typedef struct { 76typedef struct {@@ -155,4 +158,13 @@ ssize_t mod_gnutls_transport_write(gnutls_transport_ptr_t ptr, 155 const void *buffer, size_t len); 158 const void *buffer, size_t len); 156 159 157 160 161/** 162 * Init the Cache inside each Process 163 */ 164int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, 165 mod_gnutls_srvconf_rec *sc); 166/** 167 * Setup the Session Caching 168 */ 169int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt); 158#endif /* __mod_gnutls_h_inc */ 170#endif /* __mod_gnutls_h_inc */
diff --git a/src/Makefile.am b/src/Makefile.am
index 05d2fab..1f1860b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,7 +2,7 @@ CLEANFILES = .libs/libmod_gnutls *~ 2 2 3libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c 3libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c 4libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 4libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 5libmod_gnutls_la_LDFLAGS = ${MODULE_LIBS} 5libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} 6 6 7lib_LTLIBRARIES = libmod_gnutls.la 7lib_LTLIBRARIES = libmod_gnutls.la 8 8
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c
index 683cdf4..bc13440 100644
--- a/src/gnutls_cache.c
+++ b/src/gnutls_cache.c
@@ -16,46 +16,212 @@ 16 */ 16 */ 17 17 18#include "mod_gnutls.h" 18#include "mod_gnutls.h" 19#include "ap_mpm.h" 19 20 20/** 21/** 21 * GnuTLS Session Cache using libmemcached 22 * GnuTLS Session Cache using libmemcached 22 * 23 * 23 */ 24 */ 24/* 25#include "memcache.h" 26 25 27int mod_gnutls_cache_init() 26/* The underlying apr_memcache system is thread safe... woohoo */ 27static apr_memcache_t* mc; 28 29int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, 30 mod_gnutls_srvconf_rec *sc) 28{ 31{ 29 return 0; 32 apr_status_t rv = APR_SUCCESS; 33 int thread_limit = 0; 34 int nservers = 0; 35 char* cache_config; 36 char* split; 37 char* tok; 38 39 ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); 40 41 /* Find all the servers in the first run to get a total count */ 42 cache_config = apr_pstrdup(p, sc->cache_config); 43 split = apr_strtok(cache_config, " ", &tok); 44 while (split) { 45 nservers++; 46 split = apr_strtok(NULL," ", &tok); 47 } 48 49 rv = apr_memcache_create(p, nservers, 0, &mc); 50 if (rv != APR_SUCCESS) { 51 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 52 "[gnutls_cache] Failed to create Memcache Object of '%d' size.", 53 nservers); 54 return rv; 55 } 56 57 /* Now add each server to the memcache */ 58 cache_config = apr_pstrdup(p, sc->cache_config); 59 split = apr_strtok(cache_config, " ", &tok); 60 while (split) { 61 apr_memcache_server_t* st; 62 char* split2; 63 char* host_str; 64 char* port_str; 65 int port; 66 67 host_str = apr_strtok(split,":", &split2); 68 port_str = apr_strtok(NULL,":", &split2); 69 if (!port_str) { 70 port = 11211; /* default port */ 71 } 72 else { 73 port = atoi(port_str); 74 } 75 76 /* Should Max Conns be (thread_limit / nservers) ? */ 77 rv = apr_memcache_server_create(p, 78 host_str, port, 79 0, 80 1, 81 thread_limit, 82 600, 83 &st); 84 if(rv != APR_SUCCESS) { 85 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 86 "[gnutls_cache] Failed to Create Server: %s:%d", 87 host_str, port); 88 return rv; 89 } 90 91 rv = apr_memcache_add_server(mc, st); 92 if(rv != APR_SUCCESS) { 93 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 94 "[gnutls_cache] Failed to Add Server: %s:%d", 95 host_str, port); 96 return rv; 97 } 98 99 split = apr_strtok(NULL," ", &tok); 100 } 101 return rv; 30} 102} 31static int cache_store((void* baton, gnutls_datum_t key, gnutls_datum_t data) 103 104/* thanks mod_ssl */ 105#define GNUTLS_SESSION_ID_STRING_LEN \ 106 ((GNUTLS_MAX_SESSION_ID + 1) * 2) 107#define MC_TAG "mod_gnutls:" 108#define MC_TAG_LEN \ 109 (sizeof(MC_TAG)) 110#define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) 111 112 113static char *gnutls_session_id2sz(unsigned char *id, int idlen, 114 char *str, int strsize) 32{ 115{ 33 mc_set(struct memcache *mc, 116 char *cp; 34 key->data, key->size, 117 int n; 35 data->data, data->size, 118 36 3600, 0); 119 cp = apr_cpystrn(str, MC_TAG, MC_TAG_LEN); 37 return 0; 120 for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { 121 apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); 122 cp += 2; 123 } 124 *cp = '\0'; 125 return str; 38} 126} 39 127 40static int cache_fetch(void* baton, gnutls_datum_t key) 128 129static int cache_store(void* baton, gnutls_datum_t key, gnutls_datum_t data) 41{ 130{ 131 apr_status_t rv = APR_SUCCESS; 42 mod_gnutls_handle_t *ctxt = baton; 132 mod_gnutls_handle_t *ctxt = baton; 43 return 0; 133 char buf[STR_SESSION_LEN]; 134 char* strkey = NULL; 135 apr_uint32_t timeout; 136 137 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); 138 if(!strkey) 139 return -1; 140 141 timeout = 3600; 142 143 rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); 144 145 if(rv != APR_SUCCESS) { 146 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, 147 ctxt->c->base_server, 148 "[gnutls_cache] error setting key '%s' " 149 "with %d bytes of data", strkey, data.size); 150 return -1; 151 } 152 153 return 0; 154} 155 156static gnutls_datum_t cache_fetch(void* baton, gnutls_datum_t key) 157{ 158 apr_status_t rv = APR_SUCCESS; 159 mod_gnutls_handle_t *ctxt = baton; 160 char buf[STR_SESSION_LEN]; 161 char* strkey = NULL; 162 char* value; 163 apr_size_t value_len; 164 gnutls_datum_t data = { NULL, 0 }; 165 166 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); 167 if(!strkey) { 168 return data; 169 } 170 171 rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, 172 &value, &value_len, NULL); 173 174 if(rv != APR_SUCCESS) { 175 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 176 ctxt->c->base_server, 177 "[gnutls_cache] error fetching key '%s' ", 178 strkey); 179 180 data.size = 0; 181 data.data = NULL; 182 return data; 183 } 184 185 /* TODO: Eliminate this memcpy. ffs. gnutls-- */ 186 data.data = gnutls_malloc(value_len); 187 if (data.data == NULL) 188 return data; 189 190 data.size = value_len; 191 memcpy(data.data, value, value_len); 192 193 return data; 44} 194} 45 195 46static int cache_delete(void* baton, gnutls_datum_t key) 196static int cache_delete(void* baton, gnutls_datum_t key) 47{ 197{ 198 apr_status_t rv = APR_SUCCESS; 48 mod_gnutls_handle_t *ctxt = baton; 199 mod_gnutls_handle_t *ctxt = baton; 49 return 0; 200 char buf[STR_SESSION_LEN]; 201 char* strkey = NULL; 202 203 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); 204 if(!strkey) 205 return -1; 206 207 rv = apr_memcache_delete(mc, strkey, 0); 208 209 if(rv != APR_SUCCESS) { 210 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 211 ctxt->c->base_server, 212 "[gnutls_cache] error deleting key '%s' ", 213 strkey); 214 return -1; 215 } 216 217 return 0; 50} 218} 51 219 52int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) 220int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) 53{ 221{ 54 gnutls_db_set_cache_expiration 222 gnutls_db_set_retrieve_function(ctxt->session, cache_fetch); 55 gnutls_db_set_retrieve_function(session, cache_fetch); 223 gnutls_db_set_remove_function(ctxt->session, cache_delete); 56 gnutls_db_set_remove_function(session, cache_delete); 224 gnutls_db_set_store_function(ctxt->session, cache_store); 57 gnutls_db_set_store_function(session, cache_store); 225 gnutls_db_set_ptr(ctxt->session, ctxt); 58 gnutls_db_set_ptr(session, NULL); 226 return 0; 59 return 0; 60} 227} 61*/
diff --git a/src/gnutls_io.c b/src/gnutls_io.c
index e1c84be..e92646b 100644
--- a/src/gnutls_io.c
+++ b/src/gnutls_io.c
@@ -273,10 +273,16 @@ static apr_status_t gnutls_io_input_read(mod_gnutls_handle_t * ctxt, 273 } 273 } 274 else { 274 else { 275 /* Some Other Error. Report it. Die. */ 275 /* Some Other Error. Report it. Die. */ 276 ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, 276 if(gnutls_error_is_fatal(rc)) { 277 ctxt->c->base_server, 277 ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, 278 "GnuTLS: Error reading data. (%d) '%s'", rc, 278 ctxt->c->base_server, 279 gnutls_strerror(rc)); 279 "GnuTLS: Error reading data. (%d) '%s'", rc, 280 gnutls_strerror(rc)); 281 } 282 else if(*len > 0) { 283 ctxt->input_rc = APR_SUCCESS; 284 break; 285 } 280 } 286 } 281 287 282 if (ctxt->input_rc == APR_SUCCESS) { 288 if (ctxt->input_rc == APR_SUCCESS) {@@ -449,9 +455,10 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f, 449 455 450 while (!APR_BRIGADE_EMPTY(bb)) { 456 while (!APR_BRIGADE_EMPTY(bb)) { 451 apr_bucket *bucket = APR_BRIGADE_FIRST(bb); 457 apr_bucket *bucket = APR_BRIGADE_FIRST(bb); 452 if (APR_BUCKET_IS_EOS(bucket)) { 458 if (APR_BUCKET_IS_EOS(bucket) || AP_BUCKET_IS_EOC(bucket)) { 453 459 454 /* gnutls_bye(ctxt->session, GNUTLS_SHUT_RDWR); */ 460 gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); 461 gnutls_deinit(ctxt->session); 455 462 456 if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { 463 if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { 457 return status; 464 return status;@@ -464,17 +471,6 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f, 464 return status; 471 return status; 465 } 472 } 466 break; 473 break; 467 468 } 469 else if (AP_BUCKET_IS_EOC(bucket)) { 470 471 gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); 472 gnutls_deinit(ctxt->session); 473 if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { 474 return status; 475 } 476 break; 477 478 } 474 } 479 else { 475 else { 480 /* filter output */ 476 /* filter output */
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index 3dfbd9a..833edc2 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -70,7 +70,7 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 70 } 70 } 71 71 72 72 73 if(first_run) { 73// if(first_run) { 74 /* TODO: Should we regenerate these after X requests / X time ? */ 74 /* TODO: Should we regenerate these after X requests / X time ? */ 75 gnutls_dh_params_init(&dh_params); 75 gnutls_dh_params_init(&dh_params); 76 gnutls_dh_params_generate2(dh_params, DH_BITS); 76 gnutls_dh_params_generate2(dh_params, DH_BITS);@@ -78,7 +78,7 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 78 gnutls_rsa_params_init(&rsa_params); 78 gnutls_rsa_params_init(&rsa_params); 79 gnutls_rsa_params_generate2(rsa_params, RSA_BITS); 79 gnutls_rsa_params_generate2(rsa_params, RSA_BITS); 80#endif 80#endif 81 } 81// } 82 82 83 for (s = base_server; s; s = s->next) { 83 for (s = base_server; s; s = s->next) { 84 sc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, 84 sc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config,@@ -105,6 +105,25 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 105 return OK; 105 return OK; 106} 106} 107 107 108static void mod_gnutls_hook_child_init(apr_pool_t *p, server_rec *s) 109{ 110 apr_status_t rv = APR_SUCCESS; 111 mod_gnutls_srvconf_rec *sc = ap_get_module_config(s->module_config, 112 &gnutls_module); 113 114 if(sc->cache_config != NULL) { 115 rv = mod_gnutls_cache_child_init(p, s, sc); 116 if(rv != APR_SUCCESS) { 117 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 118 "[GnuTLS] - Failed to run Cache Init"); 119 } 120 } 121 else { 122 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, 123 "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); 124 } 125} 126 108static const char *mod_gnutls_hook_http_method(const request_rec * r) 127static const char *mod_gnutls_hook_http_method(const request_rec * r) 109{ 128{ 110 mod_gnutls_srvconf_rec *sc = 129 mod_gnutls_srvconf_rec *sc =@@ -172,6 +191,7 @@ static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c) 172 191 173 gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); 192 gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); 174 193 194 mod_gnutls_cache_session_init(ctxt); 175 return ctxt; 195 return ctxt; 176} 196} 177 197@@ -250,6 +270,21 @@ static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy, 250 return NULL; 270 return NULL; 251} 271} 252 272 273static const char *gnutls_set_cache(cmd_parms * parms, void *dummy, 274 const char *arg) 275{ 276 const char* err; 277 mod_gnutls_srvconf_rec *sc = ap_get_module_config(parms->server-> 278 module_config, 279 &gnutls_module); 280 if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { 281 return err; 282 } 283 284 sc->cache_config = apr_pstrdup(parms->pool, arg); 285 return NULL; 286} 287 253static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy, 288static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy, 254 const char *arg) 289 const char *arg) 255{ 290{@@ -279,6 +314,10 @@ static const command_rec gnutls_cmds[] = { 279 NULL, 314 NULL, 280 RSRC_CONF, 315 RSRC_CONF, 281 "SSL Server Certificate file"), 316 "SSL Server Certificate file"), 317 AP_INIT_TAKE1("GnuTLSCache", gnutls_set_cache, 318 NULL, 319 RSRC_CONF, 320 "SSL Server Certificate file"), 282 AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled, 321 AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled, 283 NULL, RSRC_CONF, 322 NULL, RSRC_CONF, 284 "Whether this server has GnuTLS Enabled. Default: Off"), 323 "Whether this server has GnuTLS Enabled. Default: Off"),@@ -299,6 +338,8 @@ static void gnutls_hooks(apr_pool_t * p) 299 APR_HOOK_MIDDLE); 338 APR_HOOK_MIDDLE); 300 ap_hook_post_config(mod_gnutls_hook_post_config, NULL, NULL, 339 ap_hook_post_config(mod_gnutls_hook_post_config, NULL, NULL, 301 APR_HOOK_MIDDLE); 340 APR_HOOK_MIDDLE); 341 ap_hook_child_init(mod_gnutls_hook_child_init, NULL, NULL, 342 APR_HOOK_MIDDLE); 302 ap_hook_http_method(mod_gnutls_hook_http_method, NULL, NULL, 343 ap_hook_http_method(mod_gnutls_hook_http_method, NULL, NULL, 303 APR_HOOK_MIDDLE); 344 APR_HOOK_MIDDLE); 304 ap_hook_default_port(mod_gnutls_hook_default_port, NULL, NULL, 345 ap_hook_default_port(mod_gnutls_hook_default_port, NULL, NULL,@@ -331,6 +372,7 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) 331 gnutls_anon_allocate_server_credentials(&sc->anoncred); 372 gnutls_anon_allocate_server_credentials(&sc->anoncred); 332 sc->key_file = NULL; 373 sc->key_file = NULL; 333 sc->cert_file = NULL; 374 sc->cert_file = NULL; 375 sc->cache_config = NULL; 334 376 335 i = 0; 377 i = 0; 336 sc->ciphers[i++] = GNUTLS_CIPHER_AES_256_CBC; 378 sc->ciphers[i++] = GNUTLS_CIPHER_AES_256_CBC;