source: mod_gnutls/src/gnutls_cache.c @ 95ca7c0

debian/masterdebian/stretch-backportsjessie-backportsmsvaupstream
Last change on this file since 95ca7c0 was 95ca7c0, checked in by Paul Querna <chip@…>, 15 years ago

use apr to parse hostnames..

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/* ====================================================================
2 *  Copyright 2004 Paul Querna
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  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#include "mod_gnutls.h"
19#include "ap_mpm.h"
20
21/**
22 * GnuTLS Session Cache using libmemcached
23 *
24 */
25
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)
31{
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* host_str;
63        char* scope_id;
64        apr_port_t port;
65
66        rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p);
67        if(rv != APR_SUCCESS) {
68            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
69                         "[gnutls_cache] Failed to Parse Server: '%s'", split);
70            return rv;
71        }
72
73        if(host_str == NULL) {
74            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
75                         "[gnutls_cache] Failed to Parse Server, "
76                         "no hostname specified: '%s'", split);
77            return rv;
78        }
79
80        if (port == 0) {
81            port = 11211; /* default port */
82        }
83
84        /* Should Max Conns be (thread_limit / nservers) ? */
85        rv = apr_memcache_server_create(p,
86                                        host_str, port,
87                                        0,
88                                        1,
89                                        thread_limit, 
90                                        600,
91                                        &st);
92        if(rv != APR_SUCCESS) {
93            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
94                         "[gnutls_cache] Failed to Create Server: %s:%d", 
95                         host_str, port);
96            return rv;
97        }
98
99        rv = apr_memcache_add_server(mc, st);
100        if(rv != APR_SUCCESS) {
101            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
102                         "[gnutls_cache] Failed to Add Server: %s:%d", 
103                         host_str, port);
104            return rv;
105        }
106
107        split = apr_strtok(NULL," ", &tok);
108    }
109    return rv;
110}
111
112/* thanks mod_ssl */
113#define GNUTLS_SESSION_ID_STRING_LEN \
114    ((GNUTLS_MAX_SESSION_ID + 1) * 2)
115#define MC_TAG "mod_gnutls:"
116#define MC_TAG_LEN \
117    (sizeof(MC_TAG))
118#define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN)
119
120
121static char *gnutls_session_id2sz(unsigned char *id, int idlen,
122                        char *str, int strsize)
123{
124    char *cp;
125    int n;
126 
127    cp = apr_cpystrn(str, MC_TAG, MC_TAG_LEN);
128    for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) {
129        apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]);
130        cp += 2;
131    }
132    *cp = '\0';
133    return str;
134}
135
136
137static int cache_store(void* baton, gnutls_datum_t key, gnutls_datum_t data)
138{
139    apr_status_t rv = APR_SUCCESS;
140    mod_gnutls_handle_t *ctxt = baton;
141    char buf[STR_SESSION_LEN];
142    char* strkey = NULL;
143    apr_uint32_t timeout;
144
145    strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf));
146    if(!strkey)
147        return -1;
148
149    timeout = 3600;
150
151    rv = apr_memcache_set(mc,  strkey, data.data, data.size, timeout, 0);
152
153    if(rv != APR_SUCCESS) {
154        ap_log_error(APLOG_MARK, APLOG_CRIT, rv,
155                     ctxt->c->base_server,
156                     "[gnutls_cache] error setting key '%s' "
157                     "with %d bytes of data", strkey, data.size);
158        return -1;
159    }
160
161    return 0;
162}
163
164static gnutls_datum_t cache_fetch(void* baton, gnutls_datum_t key)
165{
166    apr_status_t rv = APR_SUCCESS;
167    mod_gnutls_handle_t *ctxt = baton;
168    char buf[STR_SESSION_LEN];
169    char* strkey = NULL;
170    char* value;
171    apr_size_t value_len;
172    gnutls_datum_t data = { NULL, 0 };
173
174    strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf));
175    if(!strkey) {
176        return data;
177    }
178
179    rv = apr_memcache_getp(mc, ctxt->c->pool, strkey,
180                           &value, &value_len, NULL);
181
182    if(rv != APR_SUCCESS) {
183        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
184                     ctxt->c->base_server,
185                     "[gnutls_cache] error fetching key '%s' ",
186                     strkey);
187
188        data.size = 0;
189        data.data = NULL;
190        return data;
191    }
192
193    /* TODO: Eliminate this memcpy. ffs. gnutls-- */
194    data.data = gnutls_malloc(value_len);
195    if (data.data == NULL)
196        return data;
197
198    data.size = value_len;
199    memcpy(data.data, value, value_len);
200
201    return data;
202}
203
204static int cache_delete(void* baton, gnutls_datum_t key)
205{
206    apr_status_t rv = APR_SUCCESS;
207    mod_gnutls_handle_t *ctxt = baton;
208    char buf[STR_SESSION_LEN];
209    char* strkey = NULL;
210
211    strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf));
212    if(!strkey)
213        return -1;
214
215    rv = apr_memcache_delete(mc, strkey, 0);
216
217    if(rv != APR_SUCCESS) {
218        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
219                     ctxt->c->base_server,
220                     "[gnutls_cache] error deleting key '%s' ",
221                      strkey);
222        return -1;
223    }
224
225    return 0;
226}
227
228int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt)
229{
230    gnutls_db_set_retrieve_function(ctxt->session, cache_fetch);
231    gnutls_db_set_remove_function(ctxt->session, cache_delete);
232    gnutls_db_set_store_function(ctxt->session, cache_store);
233    gnutls_db_set_ptr(ctxt->session, ctxt);
234    return 0;
235}
Note: See TracBrowser for help on using the repository browser.