1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* _ _ 18 * _ __ ___ ___ __| | ___ ___| | mod_ssl 19 * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL 20 * | | | | | | (_) | (_| | \__ \__ \ | 21 * |_| |_| |_|\___/ \__,_|___|___/___/_| 22 * |_____| 23 * ssl_scache_dc.c 24 * Distributed Session Cache (client support) 25 */ 26 27#include "ssl_private.h" 28 29/* Only build this code if it's enabled at configure-time. */ 30#ifdef HAVE_DISTCACHE 31 32#include "distcache/dc_client.h" 33 34#if !defined(DISTCACHE_CLIENT_API) || (DISTCACHE_CLIENT_API < 0x0001) 35#error "You must compile with a more recent version of the distcache-base package" 36#endif 37 38/* 39 * This cache implementation allows modssl to access 'distcache' servers (or 40 * proxies) to facilitate distributed session caching. It is based on code 41 * released as open source by Cryptographic Appliances Inc, and was developed by 42 * Geoff Thorpe, Steve Robb, and Chris Zimmerman. 43 */ 44 45/* 46** 47** High-Level "handlers" as per ssl_scache.c 48** 49*/ 50 51void ssl_scache_dc_init(server_rec *s, apr_pool_t *p) 52{ 53 DC_CTX *ctx; 54 SSLModConfigRec *mc = myModConfig(s); 55 /* 56 * Create a session context 57 */ 58 if (mc->szSessionCacheDataFile == NULL) { 59 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "SSLSessionCache required"); 60 ssl_die(); 61 } 62#if 0 63 /* If a "persistent connection" mode of operation is preferred, you *must* 64 * also use the PIDCHECK flag to ensure fork()'d processes don't interlace 65 * comms on the same connection as each other. */ 66#define SESSION_CTX_FLAGS SESSION_CTX_FLAG_PERSISTENT | \ 67 SESSION_CTX_FLAG_PERSISTENT_PIDCHECK | \ 68 SESSION_CTX_FLAG_PERSISTENT_RETRY | \ 69 SESSION_CTX_FLAG_PERSISTENT_LATE 70#else 71 /* This mode of operation will open a temporary connection to the 'target' 72 * for each cache operation - this makes it safe against fork() 73 * automatically. This mode is preferred when running a local proxy (over 74 * unix domain sockets) because overhead is negligable and it reduces the 75 * performance/stability danger of file-descriptor bloatage. */ 76#define SESSION_CTX_FLAGS 0 77#endif 78 ctx = DC_CTX_new(mc->szSessionCacheDataFile, SESSION_CTX_FLAGS); 79 if (!ctx) { 80 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache failed to obtain context"); 81 ssl_die(); 82 } 83 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "distributed scache context initialised"); 84 /* 85 * Success ... 86 */ 87 mc->tSessionCacheDataTable = ctx; 88 return; 89} 90 91void ssl_scache_dc_kill(server_rec *s) 92{ 93 SSLModConfigRec *mc = myModConfig(s); 94 95 if (mc->tSessionCacheDataTable) 96 DC_CTX_free(mc->tSessionCacheDataTable); 97 mc->tSessionCacheDataTable = NULL; 98} 99 100BOOL ssl_scache_dc_store(server_rec *s, UCHAR *id, int idlen, 101 time_t timeout, SSL_SESSION * pSession) 102{ 103 unsigned char der[SSL_SESSION_MAX_DER]; 104 int der_len; 105 unsigned char *pder = der; 106 SSLModConfigRec *mc = myModConfig(s); 107 DC_CTX *ctx = mc->tSessionCacheDataTable; 108 109 /* Serialise the SSL_SESSION object */ 110 if ((der_len = i2d_SSL_SESSION(pSession, NULL)) > SSL_SESSION_MAX_DER) 111 return FALSE; 112 i2d_SSL_SESSION(pSession, &pder); 113 /* !@#$%^ - why do we deal with *absolute* time anyway??? */ 114 timeout -= time(NULL); 115 /* Send the serialised session to the distributed cache context */ 116 if (!DC_CTX_add_session(ctx, id, idlen, der, der_len, 117 (unsigned long)timeout * 1000)) { 118 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'add_session' failed"); 119 return FALSE; 120 } 121 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'add_session' successful"); 122 return TRUE; 123} 124 125SSL_SESSION *ssl_scache_dc_retrieve(server_rec *s, UCHAR *id, int idlen) 126{ 127 unsigned char der[SSL_SESSION_MAX_DER]; 128 unsigned int der_len; 129 SSL_SESSION *pSession; 130 MODSSL_D2I_SSL_SESSION_CONST unsigned char *pder = der; 131 SSLModConfigRec *mc = myModConfig(s); 132 DC_CTX *ctx = mc->tSessionCacheDataTable; 133 134 /* Retrieve any corresponding session from the distributed cache context */ 135 if (!DC_CTX_get_session(ctx, id, idlen, der, SSL_SESSION_MAX_DER, 136 &der_len)) { 137 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' MISS"); 138 return NULL; 139 } 140 if (der_len > SSL_SESSION_MAX_DER) { 141 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' OVERFLOW"); 142 return NULL; 143 } 144 pSession = d2i_SSL_SESSION(NULL, &pder, der_len); 145 if (!pSession) { 146 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' CORRUPT"); 147 return NULL; 148 } 149 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' HIT"); 150 return pSession; 151} 152 153void ssl_scache_dc_remove(server_rec *s, UCHAR *id, int idlen) 154{ 155 SSLModConfigRec *mc = myModConfig(s); 156 DC_CTX *ctx = mc->tSessionCacheDataTable; 157 158 /* Remove any corresponding session from the distributed cache context */ 159 if (!DC_CTX_remove_session(ctx, id, idlen)) { 160 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' MISS"); 161 } else { 162 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' HIT"); 163 } 164} 165 166void ssl_scache_dc_status(request_rec *r, int flags, apr_pool_t *pool) 167{ 168 SSLModConfigRec *mc = myModConfig(r->server); 169 170 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 171 "distributed scache 'ssl_scache_dc_status'"); 172 ap_rprintf(r, "cache type: <b>DC (Distributed Cache)</b>, " 173 " target: <b>%s</b><br>", mc->szSessionCacheDataFile); 174} 175 176#endif 177 178