diff options
| author | 2010-10-25 21:21:04 +0200 | |
|---|---|---|
| committer | 2010-10-25 21:21:04 +0200 | |
| commit | e02dd8c03ce5b66c81a47830eebe73a21ce71002 (patch) | |
| tree | 6b35cc9815eb90b4cf9d97d7f981aff764eeb0ea /src | |
| parent | 62def2f82df4b35b03843063364533bd36646ee0 (diff) | |
indented code
Diffstat (limited to 'src')
| -rw-r--r-- | src/gnutls_cache.c | 925 | ||||
| -rw-r--r-- | src/gnutls_config.c | 1039 | ||||
| -rw-r--r-- | src/gnutls_hooks.c | 1944 | ||||
| -rw-r--r-- | src/gnutls_io.c | 1367 | ||||
| -rw-r--r-- | src/gnutls_lua.c | 465 | ||||
| -rw-r--r-- | src/mod_gnutls.c | 253 |
6 files changed, 3101 insertions, 2892 deletions
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c index 90ea440..cbf879c 100644 --- a/src/gnutls_cache.c +++ b/src/gnutls_cache.c | |||
| @@ -44,18 +44,18 @@ | |||
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | char *mgs_session_id2sz(unsigned char *id, int idlen, | 46 | char *mgs_session_id2sz(unsigned char *id, int idlen, |
| 47 | char *str, int strsize) | 47 | char *str, int strsize) |
| 48 | { | 48 | { |
| 49 | char *cp; | 49 | char *cp; |
| 50 | int n; | 50 | int n; |
| 51 | 51 | ||
| 52 | cp = str; | 52 | cp = str; |
| 53 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { | 53 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { |
| 54 | apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); | 54 | apr_snprintf(cp, strsize - (cp - str), "%02X", id[n]); |
| 55 | cp += 2; | 55 | cp += 2; |
| 56 | } | 56 | } |
| 57 | *cp = '\0'; | 57 | *cp = '\0'; |
| 58 | return str; | 58 | return str; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | 61 | ||
| @@ -63,35 +63,38 @@ char *mgs_session_id2sz(unsigned char *id, int idlen, | |||
| 63 | * server:port.SessionID | 63 | * server:port.SessionID |
| 64 | * to disallow resuming sessions on different servers | 64 | * to disallow resuming sessions on different servers |
| 65 | */ | 65 | */ |
| 66 | static int mgs_session_id2dbm(conn_rec* c, unsigned char *id, int idlen, | 66 | static int mgs_session_id2dbm(conn_rec * c, unsigned char *id, int idlen, |
| 67 | apr_datum_t* dbmkey) | 67 | apr_datum_t * dbmkey) |
| 68 | { | 68 | { |
| 69 | char buf[STR_SESSION_LEN]; | 69 | char buf[STR_SESSION_LEN]; |
| 70 | char *sz; | 70 | char *sz; |
| 71 | 71 | ||
| 72 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); | 72 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); |
| 73 | if (sz == NULL) | 73 | if (sz == NULL) |
| 74 | return -1; | 74 | return -1; |
| 75 | 75 | ||
| 76 | dbmkey->dptr = apr_psprintf(c->pool, "%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); | 76 | dbmkey->dptr = |
| 77 | dbmkey->dsize = strlen( dbmkey->dptr); | 77 | apr_psprintf(c->pool, "%s:%d.%s", |
| 78 | 78 | c->base_server->server_hostname, | |
| 79 | return 0; | 79 | c->base_server->port, sz); |
| 80 | dbmkey->dsize = strlen(dbmkey->dptr); | ||
| 81 | |||
| 82 | return 0; | ||
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | #define CTIME "%b %d %k:%M:%S %Y %Z" | 85 | #define CTIME "%b %d %k:%M:%S %Y %Z" |
| 83 | char *mgs_time2sz(time_t in_time, char *str, int strsize) | 86 | char *mgs_time2sz(time_t in_time, char *str, int strsize) |
| 84 | { | 87 | { |
| 85 | apr_time_exp_t vtm; | 88 | apr_time_exp_t vtm; |
| 86 | apr_size_t ret_size; | 89 | apr_size_t ret_size; |
| 87 | apr_time_t t; | 90 | apr_time_t t; |
| 88 | 91 | ||
| 89 | 92 | ||
| 90 | apr_time_ansi_put (&t, in_time); | 93 | apr_time_ansi_put(&t, in_time); |
| 91 | apr_time_exp_gmt (&vtm, t); | 94 | apr_time_exp_gmt(&vtm, t); |
| 92 | apr_strftime(str, &ret_size, strsize-1, CTIME, &vtm); | 95 | apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm); |
| 93 | 96 | ||
| 94 | return str; | 97 | return str; |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 97 | #if HAVE_APR_MEMCACHE | 100 | #if HAVE_APR_MEMCACHE |
| @@ -99,16 +102,18 @@ char *mgs_time2sz(time_t in_time, char *str, int strsize) | |||
| 99 | * server:port.SessionID | 102 | * server:port.SessionID |
| 100 | * to disallow resuming sessions on different servers | 103 | * to disallow resuming sessions on different servers |
| 101 | */ | 104 | */ |
| 102 | static char* mgs_session_id2mc(conn_rec* c, unsigned char *id, int idlen) | 105 | static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen) |
| 103 | { | 106 | { |
| 104 | char buf[STR_SESSION_LEN]; | 107 | char buf[STR_SESSION_LEN]; |
| 105 | char *sz; | 108 | char *sz; |
| 106 | 109 | ||
| 107 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); | 110 | sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); |
| 108 | if (sz == NULL) | 111 | if (sz == NULL) |
| 109 | return NULL; | 112 | return NULL; |
| 110 | 113 | ||
| 111 | return apr_psprintf(c->pool, MC_TAG"%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); | 114 | return apr_psprintf(c->pool, MC_TAG "%s:%d.%s", |
| 115 | c->base_server->server_hostname, | ||
| 116 | c->base_server->port, sz); | ||
| 112 | } | 117 | } |
| 113 | 118 | ||
| 114 | /** | 119 | /** |
| @@ -117,482 +122,498 @@ char *sz; | |||
| 117 | */ | 122 | */ |
| 118 | 123 | ||
| 119 | /* The underlying apr_memcache system is thread safe... woohoo */ | 124 | /* The underlying apr_memcache system is thread safe... woohoo */ |
| 120 | static apr_memcache_t* mc; | 125 | static apr_memcache_t *mc; |
| 121 | 126 | ||
| 122 | static int mc_cache_child_init(apr_pool_t *p, server_rec *s, | 127 | static int mc_cache_child_init(apr_pool_t * p, server_rec * s, |
| 123 | mgs_srvconf_rec *sc) | 128 | mgs_srvconf_rec * sc) |
| 124 | { | 129 | { |
| 125 | apr_status_t rv = APR_SUCCESS; | 130 | apr_status_t rv = APR_SUCCESS; |
| 126 | int thread_limit = 0; | 131 | int thread_limit = 0; |
| 127 | int nservers = 0; | 132 | int nservers = 0; |
| 128 | char* cache_config; | 133 | char *cache_config; |
| 129 | char* split; | 134 | char *split; |
| 130 | char* tok; | 135 | char *tok; |
| 131 | 136 | ||
| 132 | ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); | 137 | ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); |
| 133 | 138 | ||
| 134 | /* Find all the servers in the first run to get a total count */ | 139 | /* Find all the servers in the first run to get a total count */ |
| 135 | cache_config = apr_pstrdup(p, sc->cache_config); | 140 | cache_config = apr_pstrdup(p, sc->cache_config); |
| 136 | split = apr_strtok(cache_config, " ", &tok); | 141 | split = apr_strtok(cache_config, " ", &tok); |
| 137 | while (split) { | 142 | while (split) { |
| 138 | nservers++; | 143 | nservers++; |
| 139 | split = apr_strtok(NULL," ", &tok); | 144 | split = apr_strtok(NULL, " ", &tok); |
| 140 | } | 145 | } |
| 141 | 146 | ||
| 142 | rv = apr_memcache_create(p, nservers, 0, &mc); | 147 | rv = apr_memcache_create(p, nservers, 0, &mc); |
| 143 | if (rv != APR_SUCCESS) { | 148 | if (rv != APR_SUCCESS) { |
| 144 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 149 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
| 145 | "[gnutls_cache] Failed to create Memcache Object of '%d' size.", | 150 | "[gnutls_cache] Failed to create Memcache Object of '%d' size.", |
| 146 | nservers); | 151 | nservers); |
| 147 | return rv; | 152 | return rv; |
| 148 | } | 153 | } |
| 149 | 154 | ||
| 150 | /* Now add each server to the memcache */ | 155 | /* Now add each server to the memcache */ |
| 151 | cache_config = apr_pstrdup(p, sc->cache_config); | 156 | cache_config = apr_pstrdup(p, sc->cache_config); |
| 152 | split = apr_strtok(cache_config, " ", &tok); | 157 | split = apr_strtok(cache_config, " ", &tok); |
| 153 | while (split) { | 158 | while (split) { |
| 154 | apr_memcache_server_t* st; | 159 | apr_memcache_server_t *st; |
| 155 | char* host_str; | 160 | char *host_str; |
| 156 | char* scope_id; | 161 | char *scope_id; |
| 157 | apr_port_t port; | 162 | apr_port_t port; |
| 158 | 163 | ||
| 159 | rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); | 164 | rv = apr_parse_addr_port(&host_str, &scope_id, &port, |
| 160 | if (rv != APR_SUCCESS) { | 165 | split, p); |
| 161 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 166 | if (rv != APR_SUCCESS) { |
| 162 | "[gnutls_cache] Failed to Parse Server: '%s'", split); | 167 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
| 163 | return rv; | 168 | "[gnutls_cache] Failed to Parse Server: '%s'", |
| 164 | } | 169 | split); |
| 165 | 170 | return rv; | |
| 166 | if (host_str == NULL) { | 171 | } |
| 167 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 172 | |
| 168 | "[gnutls_cache] Failed to Parse Server, " | 173 | if (host_str == NULL) { |
| 169 | "no hostname specified: '%s'", split); | 174 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
| 170 | return rv; | 175 | "[gnutls_cache] Failed to Parse Server, " |
| 171 | } | 176 | "no hostname specified: '%s'", split); |
| 172 | 177 | return rv; | |
| 173 | if (port == 0) { | 178 | } |
| 174 | port = 11211; /* default port */ | 179 | |
| 175 | } | 180 | if (port == 0) { |
| 176 | 181 | port = 11211; /* default port */ | |
| 177 | /* Should Max Conns be (thread_limit / nservers) ? */ | 182 | } |
| 178 | rv = apr_memcache_server_create(p, | 183 | |
| 179 | host_str, port, | 184 | /* Should Max Conns be (thread_limit / nservers) ? */ |
| 180 | 0, | 185 | rv = apr_memcache_server_create(p, |
| 181 | 1, | 186 | host_str, port, |
| 182 | thread_limit, | 187 | 0, |
| 183 | 600, | 188 | 1, thread_limit, 600, &st); |
| 184 | &st); | 189 | if (rv != APR_SUCCESS) { |
| 185 | if (rv != APR_SUCCESS) { | 190 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
| 186 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 191 | "[gnutls_cache] Failed to Create Server: %s:%d", |
| 187 | "[gnutls_cache] Failed to Create Server: %s:%d", | 192 | host_str, port); |
| 188 | host_str, port); | 193 | return rv; |
| 189 | return rv; | 194 | } |
| 190 | } | 195 | |
| 191 | 196 | rv = apr_memcache_add_server(mc, st); | |
| 192 | rv = apr_memcache_add_server(mc, st); | 197 | if (rv != APR_SUCCESS) { |
| 193 | if (rv != APR_SUCCESS) { | 198 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
| 194 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 199 | "[gnutls_cache] Failed to Add Server: %s:%d", |
| 195 | "[gnutls_cache] Failed to Add Server: %s:%d", | 200 | host_str, port); |
| 196 | host_str, port); | 201 | return rv; |
| 197 | return rv; | 202 | } |
| 198 | } | 203 | |
| 199 | 204 | split = apr_strtok(NULL, " ", &tok); | |
| 200 | split = apr_strtok(NULL," ", &tok); | 205 | } |
| 201 | } | 206 | return rv; |
| 202 | return rv; | ||
| 203 | } | 207 | } |
| 204 | 208 | ||
| 205 | static int mc_cache_store(void* baton, gnutls_datum_t key, | 209 | static int mc_cache_store(void *baton, gnutls_datum_t key, |
| 206 | gnutls_datum_t data) | 210 | gnutls_datum_t data) |
| 207 | { | 211 | { |
| 208 | apr_status_t rv = APR_SUCCESS; | 212 | apr_status_t rv = APR_SUCCESS; |
| 209 | mgs_handle_t *ctxt = baton; | 213 | mgs_handle_t *ctxt = baton; |
| 210 | char* strkey = NULL; | 214 | char *strkey = NULL; |
| 211 | apr_uint32_t timeout; | 215 | apr_uint32_t timeout; |
| 212 | 216 | ||
| 213 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); | 217 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
| 214 | if(!strkey) | 218 | if (!strkey) |
| 215 | return -1; | 219 | return -1; |
| 216 | 220 | ||
| 217 | timeout = apr_time_sec(ctxt->sc->cache_timeout); | 221 | timeout = apr_time_sec(ctxt->sc->cache_timeout); |
| 218 | 222 | ||
| 219 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); | 223 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, |
| 224 | 0); | ||
| 220 | 225 | ||
| 221 | if (rv != APR_SUCCESS) { | 226 | if (rv != APR_SUCCESS) { |
| 222 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, | 227 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, |
| 223 | ctxt->c->base_server, | 228 | ctxt->c->base_server, |
| 224 | "[gnutls_cache] error setting key '%s' " | 229 | "[gnutls_cache] error setting key '%s' " |
| 225 | "with %d bytes of data", strkey, data.size); | 230 | "with %d bytes of data", strkey, data.size); |
| 226 | return -1; | 231 | return -1; |
| 227 | } | 232 | } |
| 228 | 233 | ||
| 229 | return 0; | 234 | return 0; |
| 230 | } | 235 | } |
| 231 | 236 | ||
| 232 | static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) | 237 | static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key) |
| 233 | { | 238 | { |
| 234 | apr_status_t rv = APR_SUCCESS; | 239 | apr_status_t rv = APR_SUCCESS; |
| 235 | mgs_handle_t *ctxt = baton; | 240 | mgs_handle_t *ctxt = baton; |
| 236 | char* strkey = NULL; | 241 | char *strkey = NULL; |
| 237 | char* value; | 242 | char *value; |
| 238 | apr_size_t value_len; | 243 | apr_size_t value_len; |
| 239 | gnutls_datum_t data = { NULL, 0 }; | 244 | gnutls_datum_t data = { NULL, 0 }; |
| 240 | 245 | ||
| 241 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); | 246 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
| 242 | if (!strkey) { | 247 | if (!strkey) { |
| 243 | return data; | 248 | return data; |
| 244 | } | 249 | } |
| 245 | 250 | ||
| 246 | rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, | 251 | rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, |
| 247 | &value, &value_len, NULL); | 252 | &value, &value_len, NULL); |
| 248 | 253 | ||
| 249 | if (rv != APR_SUCCESS) { | 254 | if (rv != APR_SUCCESS) { |
| 250 | #if MOD_GNUTLS_DEBUG | 255 | #if MOD_GNUTLS_DEBUG |
| 251 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 256 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
| 252 | ctxt->c->base_server, | 257 | ctxt->c->base_server, |
| 253 | "[gnutls_cache] error fetching key '%s' ", | 258 | "[gnutls_cache] error fetching key '%s' ", |
| 254 | strkey); | 259 | strkey); |
| 255 | #endif | 260 | #endif |
| 256 | data.size = 0; | 261 | data.size = 0; |
| 257 | data.data = NULL; | 262 | data.data = NULL; |
| 258 | return data; | 263 | return data; |
| 259 | } | 264 | } |
| 260 | 265 | ||
| 261 | /* TODO: Eliminate this memcpy. gnutls-- */ | 266 | /* TODO: Eliminate this memcpy. gnutls-- */ |
| 262 | data.data = gnutls_malloc(value_len); | 267 | data.data = gnutls_malloc(value_len); |
| 263 | if (data.data == NULL) | 268 | if (data.data == NULL) |
| 264 | return data; | 269 | return data; |
| 265 | 270 | ||
| 266 | data.size = value_len; | 271 | data.size = value_len; |
| 267 | memcpy(data.data, value, value_len); | 272 | memcpy(data.data, value, value_len); |
| 268 | 273 | ||
| 269 | return data; | 274 | return data; |
| 270 | } | 275 | } |
| 271 | 276 | ||
| 272 | static int mc_cache_delete(void* baton, gnutls_datum_t key) | 277 | static int mc_cache_delete(void *baton, gnutls_datum_t key) |
| 273 | { | 278 | { |
| 274 | apr_status_t rv = APR_SUCCESS; | 279 | apr_status_t rv = APR_SUCCESS; |
| 275 | mgs_handle_t *ctxt = baton; | 280 | mgs_handle_t *ctxt = baton; |
| 276 | char* strkey = NULL; | 281 | char *strkey = NULL; |
| 277 | 282 | ||
| 278 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); | 283 | strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); |
| 279 | if(!strkey) | 284 | if (!strkey) |
| 280 | return -1; | 285 | return -1; |
| 281 | 286 | ||
| 282 | rv = apr_memcache_delete(mc, strkey, 0); | 287 | rv = apr_memcache_delete(mc, strkey, 0); |
| 283 | 288 | ||
| 284 | if (rv != APR_SUCCESS) { | 289 | if (rv != APR_SUCCESS) { |
| 285 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 290 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
| 286 | ctxt->c->base_server, | 291 | ctxt->c->base_server, |
| 287 | "[gnutls_cache] error deleting key '%s' ", | 292 | "[gnutls_cache] error deleting key '%s' ", |
| 288 | strkey); | 293 | strkey); |
| 289 | return -1; | 294 | return -1; |
| 290 | } | 295 | } |
| 291 | 296 | ||
| 292 | return 0; | 297 | return 0; |
| 293 | } | 298 | } |
| 294 | 299 | ||
| 295 | #endif /* have_apr_memcache */ | 300 | #endif /* have_apr_memcache */ |
| 296 | 301 | ||
| 297 | const char* db_type(mgs_srvconf_rec * sc) | 302 | const char *db_type(mgs_srvconf_rec * sc) |
| 298 | { | 303 | { |
| 299 | if (sc->cache_type == mgs_cache_gdbm) | 304 | if (sc->cache_type == mgs_cache_gdbm) |
| 300 | return "gdbm"; | 305 | return "gdbm"; |
| 301 | else | 306 | else |
| 302 | return "db"; | 307 | return "db"; |
| 303 | } | 308 | } |
| 304 | 309 | ||
| 305 | #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) | 310 | #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) |
| 306 | 311 | ||
| 307 | static void dbm_cache_expire(mgs_handle_t *ctxt) | 312 | static void dbm_cache_expire(mgs_handle_t * ctxt) |
| 308 | { | 313 | { |
| 309 | apr_status_t rv; | 314 | apr_status_t rv; |
| 310 | apr_dbm_t *dbm; | 315 | apr_dbm_t *dbm; |
| 311 | apr_datum_t dbmkey; | 316 | apr_datum_t dbmkey; |
| 312 | apr_datum_t dbmval; | 317 | apr_datum_t dbmval; |
| 313 | apr_time_t now; | 318 | apr_time_t now; |
| 314 | apr_time_t dtime; | 319 | apr_time_t dtime; |
| 315 | apr_pool_t* spool; | 320 | apr_pool_t *spool; |
| 316 | int total, deleted; | 321 | int total, deleted; |
| 317 | 322 | ||
| 318 | now = apr_time_now(); | 323 | now = apr_time_now(); |
| 319 | 324 | ||
| 320 | if (now - ctxt->sc->last_cache_check < (ctxt->sc->cache_timeout)/2) | 325 | if (now - ctxt->sc->last_cache_check < |
| 321 | return; | 326 | (ctxt->sc->cache_timeout) / 2) |
| 322 | 327 | return; | |
| 323 | ctxt->sc->last_cache_check = now; | 328 | |
| 324 | 329 | ctxt->sc->last_cache_check = now; | |
| 325 | apr_pool_create(&spool, ctxt->c->pool); | 330 | |
| 326 | 331 | apr_pool_create(&spool, ctxt->c->pool); | |
| 327 | total = 0; | 332 | |
| 328 | deleted = 0; | 333 | total = 0; |
| 329 | 334 | deleted = 0; | |
| 330 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, APR_DBM_RWCREATE, | 335 | |
| 331 | SSL_DBM_FILE_MODE, spool); | 336 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
| 332 | if (rv != APR_SUCCESS) { | 337 | ctxt->sc->cache_config, APR_DBM_RWCREATE, |
| 333 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 338 | SSL_DBM_FILE_MODE, spool); |
| 334 | ctxt->c->base_server, | 339 | if (rv != APR_SUCCESS) { |
| 335 | "[gnutls_cache] error opening cache searcher '%s'", | 340 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
| 336 | ctxt->sc->cache_config); | 341 | ctxt->c->base_server, |
| 337 | apr_pool_destroy(spool); | 342 | "[gnutls_cache] error opening cache searcher '%s'", |
| 338 | return; | 343 | ctxt->sc->cache_config); |
| 339 | } | 344 | apr_pool_destroy(spool); |
| 340 | 345 | return; | |
| 341 | apr_dbm_firstkey(dbm, &dbmkey); | 346 | } |
| 342 | while (dbmkey.dptr != NULL) { | 347 | |
| 343 | apr_dbm_fetch(dbm, dbmkey, &dbmval); | 348 | apr_dbm_firstkey(dbm, &dbmkey); |
| 344 | if (dbmval.dptr != NULL && dbmval.dsize >= sizeof(apr_time_t)) { | 349 | while (dbmkey.dptr != NULL) { |
| 345 | memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t)); | 350 | apr_dbm_fetch(dbm, dbmkey, &dbmval); |
| 346 | 351 | if (dbmval.dptr != NULL | |
| 347 | if (now >= dtime) { | 352 | && dbmval.dsize >= sizeof(apr_time_t)) { |
| 348 | apr_dbm_delete(dbm, dbmkey); | 353 | memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t)); |
| 349 | deleted++; | 354 | |
| 350 | } | 355 | if (now >= dtime) { |
| 351 | apr_dbm_freedatum( dbm, dbmval); | 356 | apr_dbm_delete(dbm, dbmkey); |
| 352 | } else { | 357 | deleted++; |
| 353 | apr_dbm_delete(dbm, dbmkey); | 358 | } |
| 354 | deleted++; | 359 | apr_dbm_freedatum(dbm, dbmval); |
| 355 | } | 360 | } else { |
| 356 | total++; | 361 | apr_dbm_delete(dbm, dbmkey); |
| 357 | apr_dbm_nextkey(dbm, &dbmkey); | 362 | deleted++; |
| 358 | } | 363 | } |
| 359 | apr_dbm_close(dbm); | 364 | total++; |
| 360 | 365 | apr_dbm_nextkey(dbm, &dbmkey); | |
| 361 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 366 | } |
| 362 | ctxt->c->base_server, | 367 | apr_dbm_close(dbm); |
| 363 | "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d", | 368 | |
| 364 | ctxt->sc->cache_config, deleted, total-deleted); | 369 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
| 365 | 370 | ctxt->c->base_server, | |
| 366 | apr_pool_destroy(spool); | 371 | "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d", |
| 367 | 372 | ctxt->sc->cache_config, deleted, total - deleted); | |
| 368 | return; | 373 | |
| 374 | apr_pool_destroy(spool); | ||
| 375 | |||
| 376 | return; | ||
| 369 | } | 377 | } |
| 370 | 378 | ||
| 371 | static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | 379 | static gnutls_datum_t dbm_cache_fetch(void *baton, gnutls_datum_t key) |
| 372 | { | 380 | { |
| 373 | gnutls_datum_t data = { NULL, 0 }; | 381 | gnutls_datum_t data = { NULL, 0 }; |
| 374 | apr_dbm_t *dbm; | 382 | apr_dbm_t *dbm; |
| 375 | apr_datum_t dbmkey; | 383 | apr_datum_t dbmkey; |
| 376 | apr_datum_t dbmval; | 384 | apr_datum_t dbmval; |
| 377 | mgs_handle_t *ctxt = baton; | 385 | mgs_handle_t *ctxt = baton; |
| 378 | apr_status_t rv; | 386 | apr_status_t rv; |
| 379 | 387 | ||
| 380 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) | 388 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
| 381 | return data; | 389 | return data; |
| 382 | 390 | ||
| 383 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, | 391 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
| 384 | APR_DBM_READONLY, SSL_DBM_FILE_MODE, ctxt->c->pool); | 392 | ctxt->sc->cache_config, APR_DBM_READONLY, |
| 385 | if (rv != APR_SUCCESS) { | 393 | SSL_DBM_FILE_MODE, ctxt->c->pool); |
| 386 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 394 | if (rv != APR_SUCCESS) { |
| 387 | ctxt->c->base_server, | 395 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
| 388 | "[gnutls_cache] error opening cache '%s'", | 396 | ctxt->c->base_server, |
| 389 | ctxt->sc->cache_config); | 397 | "[gnutls_cache] error opening cache '%s'", |
| 390 | return data; | 398 | ctxt->sc->cache_config); |
| 391 | } | 399 | return data; |
| 392 | 400 | } | |
| 393 | rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); | 401 | |
| 394 | 402 | rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); | |
| 395 | if (rv != APR_SUCCESS) { | 403 | |
| 396 | apr_dbm_close(dbm); | 404 | if (rv != APR_SUCCESS) { |
| 397 | return data; | 405 | apr_dbm_close(dbm); |
| 398 | } | 406 | return data; |
| 399 | 407 | } | |
| 400 | if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { | 408 | |
| 401 | apr_dbm_freedatum( dbm, dbmval); | 409 | if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { |
| 402 | apr_dbm_close(dbm); | 410 | apr_dbm_freedatum(dbm, dbmval); |
| 403 | return data; | 411 | apr_dbm_close(dbm); |
| 404 | } | 412 | return data; |
| 405 | 413 | } | |
| 406 | data.size = dbmval.dsize - sizeof(apr_time_t); | 414 | |
| 407 | 415 | data.size = dbmval.dsize - sizeof(apr_time_t); | |
| 408 | data.data = gnutls_malloc(data.size); | 416 | |
| 409 | if (data.data == NULL) { | 417 | data.data = gnutls_malloc(data.size); |
| 410 | apr_dbm_freedatum( dbm, dbmval); | 418 | if (data.data == NULL) { |
| 411 | apr_dbm_close(dbm); | 419 | apr_dbm_freedatum(dbm, dbmval); |
| 412 | return data; | 420 | apr_dbm_close(dbm); |
| 413 | } | 421 | return data; |
| 414 | 422 | } | |
| 415 | memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); | 423 | |
| 416 | 424 | memcpy(data.data, dbmval.dptr + sizeof(apr_time_t), data.size); | |
| 417 | apr_dbm_freedatum( dbm, dbmval); | 425 | |
| 418 | apr_dbm_close(dbm); | 426 | apr_dbm_freedatum(dbm, dbmval); |
| 419 | 427 | apr_dbm_close(dbm); | |
| 420 | return data; | 428 | |
| 429 | return data; | ||
| 421 | } | 430 | } |
| 422 | 431 | ||
| 423 | static int dbm_cache_store(void* baton, gnutls_datum_t key, | 432 | static int dbm_cache_store(void *baton, gnutls_datum_t key, |
| 424 | gnutls_datum_t data) | 433 | gnutls_datum_t data) |
| 425 | { | 434 | { |
| 426 | apr_dbm_t *dbm; | 435 | apr_dbm_t *dbm; |
| 427 | apr_datum_t dbmkey; | 436 | apr_datum_t dbmkey; |
| 428 | apr_datum_t dbmval; | 437 | apr_datum_t dbmval; |
| 429 | mgs_handle_t *ctxt = baton; | 438 | mgs_handle_t *ctxt = baton; |
| 430 | apr_status_t rv; | 439 | apr_status_t rv; |
| 431 | apr_time_t expiry; | 440 | apr_time_t expiry; |
| 432 | apr_pool_t* spool; | 441 | apr_pool_t *spool; |
| 433 | 442 | ||
| 434 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) | 443 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
| 435 | return -1; | 444 | return -1; |
| 436 | 445 | ||
| 437 | /* we expire dbm only on every store | 446 | /* we expire dbm only on every store |
| 438 | */ | 447 | */ |
| 439 | dbm_cache_expire(ctxt); | 448 | dbm_cache_expire(ctxt); |
| 440 | 449 | ||
| 441 | apr_pool_create(&spool, ctxt->c->pool); | 450 | apr_pool_create(&spool, ctxt->c->pool); |
| 442 | 451 | ||
| 443 | /* create DBM value */ | 452 | /* create DBM value */ |
| 444 | dbmval.dsize = data.size + sizeof(apr_time_t); | 453 | dbmval.dsize = data.size + sizeof(apr_time_t); |
| 445 | dbmval.dptr = (char *)apr_palloc(spool, dbmval.dsize); | 454 | dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize); |
| 446 | 455 | ||
| 447 | expiry = apr_time_now() + ctxt->sc->cache_timeout; | 456 | expiry = apr_time_now() + ctxt->sc->cache_timeout; |
| 448 | 457 | ||
| 449 | memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t)); | 458 | memcpy((char *) dbmval.dptr, &expiry, sizeof(apr_time_t)); |
| 450 | memcpy((char *)dbmval.dptr+sizeof(apr_time_t), | 459 | memcpy((char *) dbmval.dptr + sizeof(apr_time_t), |
| 451 | data.data, data.size); | 460 | data.data, data.size); |
| 452 | 461 | ||
| 453 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, | 462 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
| 454 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 463 | ctxt->sc->cache_config, APR_DBM_RWCREATE, |
| 455 | if (rv != APR_SUCCESS) { | 464 | SSL_DBM_FILE_MODE, ctxt->c->pool); |
| 456 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 465 | if (rv != APR_SUCCESS) { |
| 457 | ctxt->c->base_server, | 466 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
| 458 | "[gnutls_cache] error opening cache '%s'", | 467 | ctxt->c->base_server, |
| 459 | ctxt->sc->cache_config); | 468 | "[gnutls_cache] error opening cache '%s'", |
| 460 | apr_pool_destroy(spool); | 469 | ctxt->sc->cache_config); |
| 461 | return -1; | 470 | apr_pool_destroy(spool); |
| 462 | } | 471 | return -1; |
| 463 | 472 | } | |
| 464 | rv = apr_dbm_store(dbm, dbmkey, dbmval); | 473 | |
| 465 | 474 | rv = apr_dbm_store(dbm, dbmkey, dbmval); | |
| 466 | if (rv != APR_SUCCESS) { | 475 | |
| 467 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 476 | if (rv != APR_SUCCESS) { |
| 468 | ctxt->c->base_server, | 477 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
| 469 | "[gnutls_cache] error storing in cache '%s'", | 478 | ctxt->c->base_server, |
| 470 | ctxt->sc->cache_config); | 479 | "[gnutls_cache] error storing in cache '%s'", |
| 471 | apr_dbm_close(dbm); | 480 | ctxt->sc->cache_config); |
| 472 | apr_pool_destroy(spool); | 481 | apr_dbm_close(dbm); |
| 473 | return -1; | 482 | apr_pool_destroy(spool); |
| 474 | } | 483 | return -1; |
| 475 | 484 | } | |
| 476 | apr_dbm_close(dbm); | 485 | |
| 477 | 486 | apr_dbm_close(dbm); | |
| 478 | apr_pool_destroy(spool); | 487 | |
| 479 | 488 | apr_pool_destroy(spool); | |
| 480 | return 0; | 489 | |
| 490 | return 0; | ||
| 481 | } | 491 | } |
| 482 | 492 | ||
| 483 | static int dbm_cache_delete(void* baton, gnutls_datum_t key) | 493 | static int dbm_cache_delete(void *baton, gnutls_datum_t key) |
| 484 | { | 494 | { |
| 485 | apr_dbm_t *dbm; | 495 | apr_dbm_t *dbm; |
| 486 | apr_datum_t dbmkey; | 496 | apr_datum_t dbmkey; |
| 487 | mgs_handle_t *ctxt = baton; | 497 | mgs_handle_t *ctxt = baton; |
| 488 | apr_status_t rv; | 498 | apr_status_t rv; |
| 489 | 499 | ||
| 490 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) | 500 | if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) |
| 491 | return -1; | 501 | return -1; |
| 492 | 502 | ||
| 493 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, | 503 | rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), |
| 494 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 504 | ctxt->sc->cache_config, APR_DBM_RWCREATE, |
| 495 | if (rv != APR_SUCCESS) { | 505 | SSL_DBM_FILE_MODE, ctxt->c->pool); |
| 496 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 506 | if (rv != APR_SUCCESS) { |
| 497 | ctxt->c->base_server, | 507 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
| 498 | "[gnutls_cache] error opening cache '%s'", | 508 | ctxt->c->base_server, |
| 499 | ctxt->sc->cache_config); | 509 | "[gnutls_cache] error opening cache '%s'", |
| 500 | return -1; | 510 | ctxt->sc->cache_config); |
| 501 | } | 511 | return -1; |
| 502 | 512 | } | |
| 503 | rv = apr_dbm_delete(dbm, dbmkey); | 513 | |
| 504 | 514 | rv = apr_dbm_delete(dbm, dbmkey); | |
| 505 | if (rv != APR_SUCCESS) { | 515 | |
| 506 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 516 | if (rv != APR_SUCCESS) { |
| 507 | ctxt->c->base_server, | 517 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
| 508 | "[gnutls_cache] error deleting from cache '%s'", | 518 | ctxt->c->base_server, |
| 509 | ctxt->sc->cache_config); | 519 | "[gnutls_cache] error deleting from cache '%s'", |
| 510 | apr_dbm_close(dbm); | 520 | ctxt->sc->cache_config); |
| 511 | return -1; | 521 | apr_dbm_close(dbm); |
| 512 | } | 522 | return -1; |
| 513 | 523 | } | |
| 514 | apr_dbm_close(dbm); | 524 | |
| 515 | 525 | apr_dbm_close(dbm); | |
| 516 | return 0; | 526 | |
| 527 | return 0; | ||
| 517 | } | 528 | } |
| 518 | 529 | ||
| 519 | static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, | 530 | static int dbm_cache_post_config(apr_pool_t * p, server_rec * s, |
| 520 | mgs_srvconf_rec *sc) | 531 | mgs_srvconf_rec * sc) |
| 521 | { | 532 | { |
| 522 | apr_status_t rv; | 533 | apr_status_t rv; |
| 523 | apr_dbm_t *dbm; | 534 | apr_dbm_t *dbm; |
| 524 | const char* path1; | 535 | const char *path1; |
| 525 | const char* path2; | 536 | const char *path2; |
| 526 | 537 | ||
| 527 | rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, APR_DBM_RWCREATE, | 538 | rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, |
| 528 | SSL_DBM_FILE_MODE, p); | 539 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p); |
| 529 | 540 | ||
| 530 | if (rv != APR_SUCCESS) { | 541 | if (rv != APR_SUCCESS) { |
| 531 | ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, | 542 | ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, |
| 532 | "GnuTLS: Cannot create DBM Cache at `%s'", | 543 | "GnuTLS: Cannot create DBM Cache at `%s'", |
| 533 | sc->cache_config); | 544 | sc->cache_config); |
| 534 | return rv; | 545 | return rv; |
| 535 | } | 546 | } |
| 536 | 547 | ||
| 537 | apr_dbm_close(dbm); | 548 | apr_dbm_close(dbm); |
| 538 | 549 | ||
| 539 | apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, &path2); | 550 | apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, |
| 551 | &path2); | ||
| 540 | 552 | ||
| 541 | /* The Following Code takes logic directly from mod_ssl's DBM Cache */ | 553 | /* The Following Code takes logic directly from mod_ssl's DBM Cache */ |
| 542 | #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) | 554 | #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) |
| 543 | /* Running as Root */ | 555 | /* Running as Root */ |
| 544 | if (path1 && geteuid() == 0) { | 556 | if (path1 && geteuid() == 0) { |
| 545 | chown(path1, ap_unixd_config.user_id, -1); | 557 | chown(path1, ap_unixd_config.user_id, -1); |
| 546 | if (path2 != NULL) { | 558 | if (path2 != NULL) { |
| 547 | chown(path2, ap_unixd_config.user_id, -1); | 559 | chown(path2, ap_unixd_config.user_id, -1); |
| 548 | } | 560 | } |
| 549 | } | 561 | } |
| 550 | #endif | 562 | #endif |
| 551 | 563 | ||
| 552 | return rv; | 564 | return rv; |
| 553 | } | 565 | } |
| 554 | 566 | ||
| 555 | int mgs_cache_post_config(apr_pool_t *p, server_rec *s, | 567 | int mgs_cache_post_config(apr_pool_t * p, server_rec * s, |
| 556 | mgs_srvconf_rec *sc) | 568 | mgs_srvconf_rec * sc) |
| 557 | { | 569 | { |
| 558 | if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { | 570 | if (sc->cache_type == mgs_cache_dbm |
| 559 | return dbm_cache_post_config(p, s, sc); | 571 | || sc->cache_type == mgs_cache_gdbm) { |
| 560 | } | 572 | return dbm_cache_post_config(p, s, sc); |
| 561 | return 0; | 573 | } |
| 574 | return 0; | ||
| 562 | } | 575 | } |
| 563 | 576 | ||
| 564 | int mgs_cache_child_init(apr_pool_t *p, server_rec *s, | 577 | int mgs_cache_child_init(apr_pool_t * p, server_rec * s, |
| 565 | mgs_srvconf_rec *sc) | 578 | mgs_srvconf_rec * sc) |
| 566 | { | 579 | { |
| 567 | if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { | 580 | if (sc->cache_type == mgs_cache_dbm |
| 568 | return 0; | 581 | || sc->cache_type == mgs_cache_gdbm) { |
| 569 | } | 582 | return 0; |
| 583 | } | ||
| 570 | #if HAVE_APR_MEMCACHE | 584 | #if HAVE_APR_MEMCACHE |
| 571 | else if (sc->cache_type == mgs_cache_memcache) { | 585 | else if (sc->cache_type == mgs_cache_memcache) { |
| 572 | return mc_cache_child_init(p, s, sc); | 586 | return mc_cache_child_init(p, s, sc); |
| 573 | } | 587 | } |
| 574 | #endif | 588 | #endif |
| 575 | return 0; | 589 | return 0; |
| 576 | } | 590 | } |
| 577 | 591 | ||
| 578 | #include <assert.h> | 592 | #include <assert.h> |
| 579 | 593 | ||
| 580 | int mgs_cache_session_init(mgs_handle_t *ctxt) | 594 | int mgs_cache_session_init(mgs_handle_t * ctxt) |
| 581 | { | 595 | { |
| 582 | if (ctxt->sc->cache_type == mgs_cache_dbm || ctxt->sc->cache_type == mgs_cache_gdbm) { | 596 | if (ctxt->sc->cache_type == mgs_cache_dbm |
| 583 | gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); | 597 | || ctxt->sc->cache_type == mgs_cache_gdbm) { |
| 584 | gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); | 598 | gnutls_db_set_retrieve_function(ctxt->session, |
| 585 | gnutls_db_set_store_function(ctxt->session, dbm_cache_store); | 599 | dbm_cache_fetch); |
| 586 | gnutls_db_set_ptr(ctxt->session, ctxt); | 600 | gnutls_db_set_remove_function(ctxt->session, |
| 587 | } | 601 | dbm_cache_delete); |
| 602 | gnutls_db_set_store_function(ctxt->session, | ||
| 603 | dbm_cache_store); | ||
| 604 | gnutls_db_set_ptr(ctxt->session, ctxt); | ||
| 605 | } | ||
| 588 | #if HAVE_APR_MEMCACHE | 606 | #if HAVE_APR_MEMCACHE |
| 589 | else if (ctxt->sc->cache_type == mgs_cache_memcache) { | 607 | else if (ctxt->sc->cache_type == mgs_cache_memcache) { |
| 590 | gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch); | 608 | gnutls_db_set_retrieve_function(ctxt->session, |
| 591 | gnutls_db_set_remove_function(ctxt->session, mc_cache_delete); | 609 | mc_cache_fetch); |
| 592 | gnutls_db_set_store_function(ctxt->session, mc_cache_store); | 610 | gnutls_db_set_remove_function(ctxt->session, |
| 593 | gnutls_db_set_ptr(ctxt->session, ctxt); | 611 | mc_cache_delete); |
| 594 | } | 612 | gnutls_db_set_store_function(ctxt->session, |
| 613 | mc_cache_store); | ||
| 614 | gnutls_db_set_ptr(ctxt->session, ctxt); | ||
| 615 | } | ||
| 595 | #endif | 616 | #endif |
| 596 | 617 | ||
| 597 | return 0; | 618 | return 0; |
| 598 | } | 619 | } |
diff --git a/src/gnutls_config.c b/src/gnutls_config.c index ff8ec33..fc3e166 100644 --- a/src/gnutls_config.c +++ b/src/gnutls_config.c | |||
| @@ -21,284 +21,308 @@ | |||
| 21 | static int load_datum_from_file(apr_pool_t * pool, | 21 | static int load_datum_from_file(apr_pool_t * pool, |
| 22 | const char *file, gnutls_datum_t * data) | 22 | const char *file, gnutls_datum_t * data) |
| 23 | { | 23 | { |
| 24 | apr_file_t *fp; | 24 | apr_file_t *fp; |
| 25 | apr_finfo_t finfo; | 25 | apr_finfo_t finfo; |
| 26 | apr_status_t rv; | 26 | apr_status_t rv; |
| 27 | apr_size_t br = 0; | 27 | apr_size_t br = 0; |
| 28 | 28 | ||
| 29 | rv = apr_file_open(&fp, file, APR_READ | APR_BINARY, APR_OS_DEFAULT, | 29 | rv = apr_file_open(&fp, file, APR_READ | APR_BINARY, |
| 30 | pool); | 30 | APR_OS_DEFAULT, pool); |
| 31 | if (rv != APR_SUCCESS) { | 31 | if (rv != APR_SUCCESS) { |
| 32 | return rv; | 32 | return rv; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); | 35 | rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); |
| 36 | 36 | ||
| 37 | if (rv != APR_SUCCESS) { | 37 | if (rv != APR_SUCCESS) { |
| 38 | return rv; | 38 | return rv; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | data->data = apr_palloc(pool, finfo.size + 1); | 41 | data->data = apr_palloc(pool, finfo.size + 1); |
| 42 | rv = apr_file_read_full(fp, data->data, finfo.size, &br); | 42 | rv = apr_file_read_full(fp, data->data, finfo.size, &br); |
| 43 | 43 | ||
| 44 | if (rv != APR_SUCCESS) { | 44 | if (rv != APR_SUCCESS) { |
| 45 | return rv; | 45 | return rv; |
| 46 | } | 46 | } |
| 47 | apr_file_close(fp); | 47 | apr_file_close(fp); |
| 48 | 48 | ||
| 49 | data->data[br] = '\0'; | 49 | data->data[br] = '\0'; |
| 50 | data->size = br; | 50 | data->size = br; |
| 51 | 51 | ||
| 52 | return 0; | 52 | return 0; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | const char *mgs_set_dh_file(cmd_parms * parms, void *dummy, | 55 | const char *mgs_set_dh_file(cmd_parms * parms, void *dummy, |
| 56 | const char *arg) | 56 | const char *arg) |
| 57 | { | 57 | { |
| 58 | int ret; | 58 | int ret; |
| 59 | gnutls_datum_t data; | 59 | gnutls_datum_t data; |
| 60 | const char *file; | 60 | const char *file; |
| 61 | apr_pool_t *spool; | 61 | apr_pool_t *spool; |
| 62 | mgs_srvconf_rec *sc = | 62 | mgs_srvconf_rec *sc = |
| 63 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 63 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 64 | module_config, | 64 | module_config, |
| 65 | &gnutls_module); | 65 | &gnutls_module); |
| 66 | 66 | ||
| 67 | apr_pool_create(&spool, parms->pool); | 67 | apr_pool_create(&spool, parms->pool); |
| 68 | 68 | ||
| 69 | file = ap_server_root_relative(spool, arg); | 69 | file = ap_server_root_relative(spool, arg); |
| 70 | 70 | ||
| 71 | if (load_datum_from_file(spool, file, &data) != 0) { | 71 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 72 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 72 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 73 | "DH params '%s'", file); | 73 | "DH params '%s'", file); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | ret = gnutls_dh_params_init(&sc->dh_params); | 76 | ret = gnutls_dh_params_init(&sc->dh_params); |
| 77 | if (ret < 0) { | 77 | if (ret < 0) { |
| 78 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 78 | return apr_psprintf(parms->pool, |
| 79 | ": (%d) %s", ret, gnutls_strerror(ret)); | 79 | "GnuTLS: Failed to initialize" |
| 80 | } | 80 | ": (%d) %s", ret, |
| 81 | 81 | gnutls_strerror(ret)); | |
| 82 | ret = | 82 | } |
| 83 | gnutls_dh_params_import_pkcs3(sc->dh_params, &data, GNUTLS_X509_FMT_PEM); | 83 | |
| 84 | if (ret < 0) { | 84 | ret = |
| 85 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 85 | gnutls_dh_params_import_pkcs3(sc->dh_params, &data, |
| 86 | "DH params '%s': (%d) %s", file, ret, | 86 | GNUTLS_X509_FMT_PEM); |
| 87 | gnutls_strerror(ret)); | 87 | if (ret < 0) { |
| 88 | } | 88 | return apr_psprintf(parms->pool, |
| 89 | 89 | "GnuTLS: Failed to Import " | |
| 90 | apr_pool_destroy(spool); | 90 | "DH params '%s': (%d) %s", file, ret, |
| 91 | 91 | gnutls_strerror(ret)); | |
| 92 | return NULL; | 92 | } |
| 93 | |||
| 94 | apr_pool_destroy(spool); | ||
| 95 | |||
| 96 | return NULL; | ||
| 93 | } | 97 | } |
| 94 | 98 | ||
| 95 | const char *mgs_set_rsa_export_file(cmd_parms * parms, void *dummy, | 99 | const char *mgs_set_rsa_export_file(cmd_parms * parms, void *dummy, |
| 96 | const char *arg) | 100 | const char *arg) |
| 97 | { | 101 | { |
| 98 | int ret; | 102 | int ret; |
| 99 | gnutls_datum_t data; | 103 | gnutls_datum_t data; |
| 100 | const char *file; | 104 | const char *file; |
| 101 | apr_pool_t *spool; | 105 | apr_pool_t *spool; |
| 102 | mgs_srvconf_rec *sc = | 106 | mgs_srvconf_rec *sc = |
| 103 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 107 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 104 | module_config, | 108 | module_config, |
| 105 | &gnutls_module); | 109 | &gnutls_module); |
| 106 | 110 | ||
| 107 | apr_pool_create(&spool, parms->pool); | 111 | apr_pool_create(&spool, parms->pool); |
| 108 | 112 | ||
| 109 | file = ap_server_root_relative(spool, arg); | 113 | file = ap_server_root_relative(spool, arg); |
| 110 | 114 | ||
| 111 | if (load_datum_from_file(spool, file, &data) != 0) { | 115 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 112 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 116 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 113 | "RSA params '%s'", file); | 117 | "RSA params '%s'", file); |
| 114 | } | 118 | } |
| 115 | 119 | ||
| 116 | ret = gnutls_rsa_params_init(&sc->rsa_params); | 120 | ret = gnutls_rsa_params_init(&sc->rsa_params); |
| 117 | if (ret < 0) { | 121 | if (ret < 0) { |
| 118 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 122 | return apr_psprintf(parms->pool, |
| 119 | ": (%d) %s", ret, gnutls_strerror(ret)); | 123 | "GnuTLS: Failed to initialize" |
| 120 | } | 124 | ": (%d) %s", ret, |
| 121 | 125 | gnutls_strerror(ret)); | |
| 122 | ret = | 126 | } |
| 123 | gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data, GNUTLS_X509_FMT_PEM); | 127 | |
| 124 | if (ret != 0) { | 128 | ret = |
| 125 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 129 | gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data, |
| 126 | "RSA params '%s': (%d) %s", file, ret, | 130 | GNUTLS_X509_FMT_PEM); |
| 127 | gnutls_strerror(ret)); | 131 | if (ret != 0) { |
| 128 | } | 132 | return apr_psprintf(parms->pool, |
| 129 | 133 | "GnuTLS: Failed to Import " | |
| 130 | apr_pool_destroy(spool); | 134 | "RSA params '%s': (%d) %s", file, ret, |
| 131 | return NULL; | 135 | gnutls_strerror(ret)); |
| 136 | } | ||
| 137 | |||
| 138 | apr_pool_destroy(spool); | ||
| 139 | return NULL; | ||
| 132 | } | 140 | } |
| 133 | 141 | ||
| 134 | 142 | ||
| 135 | const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, | 143 | const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, |
| 136 | const char *arg) | 144 | const char *arg) |
| 137 | { | 145 | { |
| 138 | int ret; | 146 | int ret; |
| 139 | gnutls_datum_t data; | 147 | gnutls_datum_t data; |
| 140 | const char *file; | 148 | const char *file; |
| 141 | apr_pool_t *spool; | 149 | apr_pool_t *spool; |
| 142 | mgs_srvconf_rec *sc = | 150 | mgs_srvconf_rec *sc = |
| 143 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 151 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 144 | module_config, | 152 | module_config, |
| 145 | &gnutls_module); | 153 | &gnutls_module); |
| 146 | apr_pool_create(&spool, parms->pool); | 154 | apr_pool_create(&spool, parms->pool); |
| 147 | 155 | ||
| 148 | file = ap_server_root_relative(spool, arg); | 156 | file = ap_server_root_relative(spool, arg); |
| 149 | 157 | ||
| 150 | if (load_datum_from_file(spool, file, &data) != 0) { | 158 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 151 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 159 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 152 | "Certificate '%s'", file); | 160 | "Certificate '%s'", file); |
| 153 | } | 161 | } |
| 154 | 162 | ||
| 155 | sc->certs_x509_num = MAX_CHAIN_SIZE; | 163 | sc->certs_x509_num = MAX_CHAIN_SIZE; |
| 156 | ret = | 164 | ret = |
| 157 | gnutls_x509_crt_list_import(sc->certs_x509, &sc->certs_x509_num, &data, GNUTLS_X509_FMT_PEM, 0); | 165 | gnutls_x509_crt_list_import(sc->certs_x509, |
| 158 | if (ret < 0) { | 166 | &sc->certs_x509_num, &data, |
| 159 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 167 | GNUTLS_X509_FMT_PEM, 0); |
| 160 | "Certificate '%s': (%d) %s", file, ret, | 168 | if (ret < 0) { |
| 161 | gnutls_strerror(ret)); | 169 | return apr_psprintf(parms->pool, |
| 162 | } | 170 | "GnuTLS: Failed to Import " |
| 163 | 171 | "Certificate '%s': (%d) %s", file, ret, | |
| 164 | apr_pool_destroy(spool); | 172 | gnutls_strerror(ret)); |
| 165 | return NULL; | 173 | } |
| 174 | |||
| 175 | apr_pool_destroy(spool); | ||
| 176 | return NULL; | ||
| 166 | } | 177 | } |
| 167 | 178 | ||
| 168 | const char *mgs_set_key_file(cmd_parms * parms, void *dummy, | 179 | const char *mgs_set_key_file(cmd_parms * parms, void *dummy, |
| 169 | const char *arg) | 180 | const char *arg) |
| 170 | { | 181 | { |
| 171 | int ret; | 182 | int ret; |
| 172 | gnutls_datum_t data; | 183 | gnutls_datum_t data; |
| 173 | const char *file; | 184 | const char *file; |
| 174 | apr_pool_t *spool; | 185 | apr_pool_t *spool; |
| 175 | mgs_srvconf_rec *sc = | 186 | mgs_srvconf_rec *sc = |
| 176 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 187 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 177 | module_config, | 188 | module_config, |
| 178 | &gnutls_module); | 189 | &gnutls_module); |
| 179 | apr_pool_create(&spool, parms->pool); | 190 | apr_pool_create(&spool, parms->pool); |
| 180 | 191 | ||
| 181 | file = ap_server_root_relative(spool, arg); | 192 | file = ap_server_root_relative(spool, arg); |
| 182 | 193 | ||
| 183 | if (load_datum_from_file(spool, file, &data) != 0) { | 194 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 184 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 195 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 185 | "Private Key '%s'", file); | 196 | "Private Key '%s'", file); |
| 186 | } | 197 | } |
| 187 | 198 | ||
| 188 | ret = gnutls_x509_privkey_init(&sc->privkey_x509); | 199 | ret = gnutls_x509_privkey_init(&sc->privkey_x509); |
| 189 | if (ret < 0) { | 200 | if (ret < 0) { |
| 190 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 201 | return apr_psprintf(parms->pool, |
| 191 | ": (%d) %s", ret, gnutls_strerror(ret)); | 202 | "GnuTLS: Failed to initialize" |
| 192 | } | 203 | ": (%d) %s", ret, |
| 193 | 204 | gnutls_strerror(ret)); | |
| 194 | ret = | 205 | } |
| 195 | gnutls_x509_privkey_import(sc->privkey_x509, &data, | 206 | |
| 196 | GNUTLS_X509_FMT_PEM); | 207 | ret = |
| 197 | 208 | gnutls_x509_privkey_import(sc->privkey_x509, &data, | |
| 198 | if (ret < 0) | 209 | GNUTLS_X509_FMT_PEM); |
| 199 | ret = gnutls_x509_privkey_import_pkcs8 (sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM, | 210 | |
| 200 | NULL, GNUTLS_PKCS_PLAIN); | 211 | if (ret < 0) |
| 201 | 212 | ret = | |
| 202 | if (ret < 0) { | 213 | gnutls_x509_privkey_import_pkcs8(sc->privkey_x509, |
| 203 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 214 | &data, |
| 204 | "Private Key '%s': (%d) %s", file, ret, | 215 | GNUTLS_X509_FMT_PEM, |
| 205 | gnutls_strerror(ret)); | 216 | NULL, |
| 206 | } | 217 | GNUTLS_PKCS_PLAIN); |
| 207 | apr_pool_destroy(spool); | 218 | |
| 208 | return NULL; | 219 | if (ret < 0) { |
| 220 | return apr_psprintf(parms->pool, | ||
| 221 | "GnuTLS: Failed to Import " | ||
| 222 | "Private Key '%s': (%d) %s", file, ret, | ||
| 223 | gnutls_strerror(ret)); | ||
| 224 | } | ||
| 225 | apr_pool_destroy(spool); | ||
| 226 | return NULL; | ||
| 209 | } | 227 | } |
| 210 | 228 | ||
| 211 | const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, | 229 | const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, |
| 212 | const char *arg) | 230 | const char *arg) |
| 213 | { | 231 | { |
| 214 | int ret; | 232 | int ret; |
| 215 | gnutls_datum_t data; | 233 | gnutls_datum_t data; |
| 216 | const char *file; | 234 | const char *file; |
| 217 | apr_pool_t *spool; | 235 | apr_pool_t *spool; |
| 218 | mgs_srvconf_rec *sc = | 236 | mgs_srvconf_rec *sc = |
| 219 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 237 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 220 | module_config, | 238 | module_config, |
| 221 | &gnutls_module); | 239 | &gnutls_module); |
| 222 | apr_pool_create(&spool, parms->pool); | 240 | apr_pool_create(&spool, parms->pool); |
| 223 | 241 | ||
| 224 | file = ap_server_root_relative(spool, arg); | 242 | file = ap_server_root_relative(spool, arg); |
| 225 | 243 | ||
| 226 | if (load_datum_from_file(spool, file, &data) != 0) { | 244 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 227 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 245 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 228 | "Certificate '%s'", file); | 246 | "Certificate '%s'", file); |
| 229 | } | 247 | } |
| 230 | 248 | ||
| 231 | ret = gnutls_openpgp_crt_init( &sc->cert_pgp); | 249 | ret = gnutls_openpgp_crt_init(&sc->cert_pgp); |
| 232 | if (ret < 0) { | 250 | if (ret < 0) { |
| 233 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Init " | 251 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Init " |
| 234 | "PGP Certificate: (%d) %s", ret, | 252 | "PGP Certificate: (%d) %s", ret, |
| 235 | gnutls_strerror(ret)); | 253 | gnutls_strerror(ret)); |
| 236 | } | 254 | } |
| 237 | 255 | ||
| 238 | ret = | 256 | ret = |
| 239 | gnutls_openpgp_crt_import(sc->cert_pgp, &data, GNUTLS_OPENPGP_FMT_BASE64); | 257 | gnutls_openpgp_crt_import(sc->cert_pgp, &data, |
| 240 | if (ret < 0) { | 258 | GNUTLS_OPENPGP_FMT_BASE64); |
| 241 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 259 | if (ret < 0) { |
| 242 | "PGP Certificate '%s': (%d) %s", file, ret, | 260 | return apr_psprintf(parms->pool, |
| 243 | gnutls_strerror(ret)); | 261 | "GnuTLS: Failed to Import " |
| 244 | } | 262 | "PGP Certificate '%s': (%d) %s", file, |
| 245 | 263 | ret, gnutls_strerror(ret)); | |
| 246 | apr_pool_destroy(spool); | 264 | } |
| 247 | return NULL; | 265 | |
| 266 | apr_pool_destroy(spool); | ||
| 267 | return NULL; | ||
| 248 | } | 268 | } |
| 249 | 269 | ||
| 250 | const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, | 270 | const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, |
| 251 | const char *arg) | 271 | const char *arg) |
| 252 | { | 272 | { |
| 253 | int ret; | 273 | int ret; |
| 254 | gnutls_datum_t data; | 274 | gnutls_datum_t data; |
| 255 | const char *file; | 275 | const char *file; |
| 256 | apr_pool_t *spool; | 276 | apr_pool_t *spool; |
| 257 | mgs_srvconf_rec *sc = | 277 | mgs_srvconf_rec *sc = |
| 258 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 278 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 259 | module_config, | 279 | module_config, |
| 260 | &gnutls_module); | 280 | &gnutls_module); |
| 261 | apr_pool_create(&spool, parms->pool); | 281 | apr_pool_create(&spool, parms->pool); |
| 262 | 282 | ||
| 263 | file = ap_server_root_relative(spool, arg); | 283 | file = ap_server_root_relative(spool, arg); |
| 264 | 284 | ||
| 265 | if (load_datum_from_file(spool, file, &data) != 0) { | 285 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 266 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 286 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 267 | "Private Key '%s'", file); | 287 | "Private Key '%s'", file); |
| 268 | } | 288 | } |
| 269 | 289 | ||
| 270 | ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp); | 290 | ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp); |
| 271 | if (ret < 0) { | 291 | if (ret < 0) { |
| 272 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 292 | return apr_psprintf(parms->pool, |
| 273 | ": (%d) %s", ret, gnutls_strerror(ret)); | 293 | "GnuTLS: Failed to initialize" |
| 274 | } | 294 | ": (%d) %s", ret, |
| 275 | 295 | gnutls_strerror(ret)); | |
| 276 | ret = | 296 | } |
| 277 | gnutls_openpgp_privkey_import(sc->privkey_pgp, &data, | 297 | |
| 278 | GNUTLS_OPENPGP_FMT_BASE64, NULL, 0); | 298 | ret = |
| 279 | if (ret != 0) { | 299 | gnutls_openpgp_privkey_import(sc->privkey_pgp, &data, |
| 280 | return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " | 300 | GNUTLS_OPENPGP_FMT_BASE64, NULL, |
| 281 | "PGP Private Key '%s': (%d) %s", file, ret, | 301 | 0); |
| 282 | gnutls_strerror(ret)); | 302 | if (ret != 0) { |
| 283 | } | 303 | return apr_psprintf(parms->pool, |
| 284 | apr_pool_destroy(spool); | 304 | "GnuTLS: Failed to Import " |
| 285 | return NULL; | 305 | "PGP Private Key '%s': (%d) %s", file, |
| 306 | ret, gnutls_strerror(ret)); | ||
| 307 | } | ||
| 308 | apr_pool_destroy(spool); | ||
| 309 | return NULL; | ||
| 286 | } | 310 | } |
| 287 | 311 | ||
| 288 | const char *mgs_set_tickets(cmd_parms * parms, void *dummy, | 312 | const char *mgs_set_tickets(cmd_parms * parms, void *dummy, |
| 289 | const char *arg) | 313 | const char *arg) |
| 290 | { | 314 | { |
| 291 | mgs_srvconf_rec *sc = | 315 | mgs_srvconf_rec *sc = |
| 292 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 316 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 293 | module_config, | 317 | module_config, |
| 294 | &gnutls_module); | 318 | &gnutls_module); |
| 295 | 319 | ||
| 296 | sc->tickets = 0; | 320 | sc->tickets = 0; |
| 297 | if (strcasecmp("on", arg) == 0) { | 321 | if (strcasecmp("on", arg) == 0) { |
| 298 | sc->tickets = 1; | 322 | sc->tickets = 1; |
| 299 | } | 323 | } |
| 300 | 324 | ||
| 301 | return NULL; | 325 | return NULL; |
| 302 | } | 326 | } |
| 303 | 327 | ||
| 304 | 328 | ||
| @@ -307,27 +331,28 @@ const char *mgs_set_tickets(cmd_parms * parms, void *dummy, | |||
| 307 | const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, | 331 | const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, |
| 308 | const char *arg) | 332 | const char *arg) |
| 309 | { | 333 | { |
| 310 | mgs_srvconf_rec *sc = | 334 | mgs_srvconf_rec *sc = |
| 311 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 335 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 312 | module_config, | 336 | module_config, |
| 313 | &gnutls_module); | 337 | &gnutls_module); |
| 314 | 338 | ||
| 315 | sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg); | 339 | sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg); |
| 316 | 340 | ||
| 317 | return NULL; | 341 | return NULL; |
| 318 | } | 342 | } |
| 319 | 343 | ||
| 320 | const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, | 344 | const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, |
| 321 | const char *arg) | 345 | const char *arg) |
| 322 | { | 346 | { |
| 323 | mgs_srvconf_rec *sc = | 347 | mgs_srvconf_rec *sc = |
| 324 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 348 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 325 | module_config, | 349 | module_config, |
| 326 | &gnutls_module); | 350 | &gnutls_module); |
| 327 | 351 | ||
| 328 | sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg); | 352 | sc->srp_tpasswd_conf_file = |
| 353 | ap_server_root_relative(parms->pool, arg); | ||
| 329 | 354 | ||
| 330 | return NULL; | 355 | return NULL; |
| 331 | } | 356 | } |
| 332 | 357 | ||
| 333 | #endif | 358 | #endif |
| @@ -335,308 +360,326 @@ const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, | |||
| 335 | const char *mgs_set_cache(cmd_parms * parms, void *dummy, | 360 | const char *mgs_set_cache(cmd_parms * parms, void *dummy, |
| 336 | const char *type, const char *arg) | 361 | const char *type, const char *arg) |
| 337 | { | 362 | { |
| 338 | const char *err; | 363 | const char *err; |
| 339 | mgs_srvconf_rec *sc = ap_get_module_config(parms->server-> | 364 | mgs_srvconf_rec *sc = |
| 340 | module_config, | 365 | ap_get_module_config(parms->server->module_config, |
| 341 | &gnutls_module); | 366 | &gnutls_module); |
| 342 | if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { | 367 | if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { |
| 343 | return err; | 368 | return err; |
| 344 | } | 369 | } |
| 345 | 370 | ||
| 346 | if (strcasecmp("none", type) == 0) { | 371 | if (strcasecmp("none", type) == 0) { |
| 347 | sc->cache_type = mgs_cache_none; | 372 | sc->cache_type = mgs_cache_none; |
| 348 | } else if (strcasecmp("dbm", type) == 0) { | 373 | } else if (strcasecmp("dbm", type) == 0) { |
| 349 | sc->cache_type = mgs_cache_dbm; | 374 | sc->cache_type = mgs_cache_dbm; |
| 350 | } | 375 | } else if (strcasecmp("gdbm", type) == 0) { |
| 351 | else if (strcasecmp("gdbm", type) == 0) { | 376 | sc->cache_type = mgs_cache_gdbm; |
| 352 | sc->cache_type = mgs_cache_gdbm; | 377 | } |
| 353 | } | ||
| 354 | #if HAVE_APR_MEMCACHE | 378 | #if HAVE_APR_MEMCACHE |
| 355 | else if (strcasecmp("memcache", type) == 0) { | 379 | else if (strcasecmp("memcache", type) == 0) { |
| 356 | sc->cache_type = mgs_cache_memcache; | 380 | sc->cache_type = mgs_cache_memcache; |
| 357 | } | 381 | } |
| 358 | #endif | 382 | #endif |
| 359 | else { | 383 | else { |
| 360 | return "Invalid Type for GnuTLSCache!"; | 384 | return "Invalid Type for GnuTLSCache!"; |
| 361 | } | 385 | } |
| 362 | 386 | ||
| 363 | if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { | 387 | if (sc->cache_type == mgs_cache_dbm |
| 364 | sc->cache_config = ap_server_root_relative(parms->pool, arg); | 388 | || sc->cache_type == mgs_cache_gdbm) { |
| 365 | } else { | 389 | sc->cache_config = |
| 366 | sc->cache_config = apr_pstrdup(parms->pool, arg); | 390 | ap_server_root_relative(parms->pool, arg); |
| 367 | } | 391 | } else { |
| 368 | 392 | sc->cache_config = apr_pstrdup(parms->pool, arg); | |
| 369 | return NULL; | 393 | } |
| 394 | |||
| 395 | return NULL; | ||
| 370 | } | 396 | } |
| 371 | 397 | ||
| 372 | const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, | 398 | const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, |
| 373 | const char *arg) | 399 | const char *arg) |
| 374 | { | 400 | { |
| 375 | int argint; | 401 | int argint; |
| 376 | mgs_srvconf_rec *sc = | ||
| 377 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | ||
| 378 | module_config, | ||
| 379 | &gnutls_module); | ||
| 380 | |||
| 381 | argint = atoi(arg); | ||
| 382 | |||
| 383 | if (argint < 0) { | ||
| 384 | return "GnuTLSCacheTimeout: Invalid argument"; | ||
| 385 | } else if (argint == 0) { | ||
| 386 | sc->cache_timeout = 0; | ||
| 387 | } else { | ||
| 388 | sc->cache_timeout = apr_time_from_sec(argint); | ||
| 389 | } | ||
| 390 | |||
| 391 | return NULL; | ||
| 392 | } | ||
| 393 | |||
| 394 | const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, | ||
| 395 | const char *arg) | ||
| 396 | { | ||
| 397 | int mode; | ||
| 398 | |||
| 399 | if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { | ||
| 400 | mode = GNUTLS_CERT_IGNORE; | ||
| 401 | } else if (strcasecmp("optional", arg) == 0 | ||
| 402 | || strcasecmp("request", arg) == 0) { | ||
| 403 | mode = GNUTLS_CERT_REQUEST; | ||
| 404 | } else if (strcasecmp("require", arg) == 0) { | ||
| 405 | mode = GNUTLS_CERT_REQUIRE; | ||
| 406 | } else { | ||
| 407 | return "GnuTLSClientVerify: Invalid argument"; | ||
| 408 | } | ||
| 409 | |||
| 410 | /* This was set from a directory context */ | ||
| 411 | if (parms->path) { | ||
| 412 | mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy; | ||
| 413 | dc->client_verify_mode = mode; | ||
| 414 | } else { | ||
| 415 | mgs_srvconf_rec *sc = | 402 | mgs_srvconf_rec *sc = |
| 416 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 403 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 417 | module_config, | 404 | module_config, |
| 418 | &gnutls_module); | 405 | &gnutls_module); |
| 419 | sc->client_verify_mode = mode; | ||
| 420 | } | ||
| 421 | 406 | ||
| 422 | return NULL; | 407 | argint = atoi(arg); |
| 408 | |||
| 409 | if (argint < 0) { | ||
| 410 | return "GnuTLSCacheTimeout: Invalid argument"; | ||
| 411 | } else if (argint == 0) { | ||
| 412 | sc->cache_timeout = 0; | ||
| 413 | } else { | ||
| 414 | sc->cache_timeout = apr_time_from_sec(argint); | ||
| 415 | } | ||
| 416 | |||
| 417 | return NULL; | ||
| 418 | } | ||
| 419 | |||
| 420 | const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, | ||
| 421 | const char *arg) | ||
| 422 | { | ||
| 423 | int mode; | ||
| 424 | |||
| 425 | if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { | ||
| 426 | mode = GNUTLS_CERT_IGNORE; | ||
| 427 | } else if (strcasecmp("optional", arg) == 0 | ||
| 428 | || strcasecmp("request", arg) == 0) { | ||
| 429 | mode = GNUTLS_CERT_REQUEST; | ||
| 430 | } else if (strcasecmp("require", arg) == 0) { | ||
| 431 | mode = GNUTLS_CERT_REQUIRE; | ||
| 432 | } else { | ||
| 433 | return "GnuTLSClientVerify: Invalid argument"; | ||
| 434 | } | ||
| 435 | |||
| 436 | /* This was set from a directory context */ | ||
| 437 | if (parms->path) { | ||
| 438 | mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy; | ||
| 439 | dc->client_verify_mode = mode; | ||
| 440 | } else { | ||
| 441 | mgs_srvconf_rec *sc = | ||
| 442 | (mgs_srvconf_rec *) | ||
| 443 | ap_get_module_config(parms->server->module_config, | ||
| 444 | &gnutls_module); | ||
| 445 | sc->client_verify_mode = mode; | ||
| 446 | } | ||
| 447 | |||
| 448 | return NULL; | ||
| 423 | } | 449 | } |
| 424 | 450 | ||
| 425 | #define INIT_CA_SIZE 128 | 451 | #define INIT_CA_SIZE 128 |
| 426 | const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, | 452 | const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, |
| 427 | const char *arg) | 453 | const char *arg) |
| 428 | { | 454 | { |
| 429 | int rv; | 455 | int rv; |
| 430 | const char *file; | 456 | const char *file; |
| 431 | apr_pool_t *spool; | 457 | apr_pool_t *spool; |
| 432 | gnutls_datum_t data; | 458 | gnutls_datum_t data; |
| 433 | 459 | ||
| 434 | mgs_srvconf_rec *sc = | 460 | mgs_srvconf_rec *sc = |
| 435 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 461 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 436 | module_config, | 462 | module_config, |
| 437 | &gnutls_module); | 463 | &gnutls_module); |
| 438 | apr_pool_create(&spool, parms->pool); | 464 | apr_pool_create(&spool, parms->pool); |
| 439 | 465 | ||
| 440 | file = ap_server_root_relative(spool, arg); | 466 | file = ap_server_root_relative(spool, arg); |
| 441 | 467 | ||
| 442 | if (load_datum_from_file(spool, file, &data) != 0) { | 468 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 443 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 469 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 444 | "Client CA File '%s'", file); | 470 | "Client CA File '%s'", file); |
| 445 | } | 471 | } |
| 446 | 472 | ||
| 447 | sc->ca_list_size = INIT_CA_SIZE; | 473 | sc->ca_list_size = INIT_CA_SIZE; |
| 448 | sc->ca_list = malloc(sc->ca_list_size * sizeof(*sc->ca_list)); | 474 | sc->ca_list = malloc(sc->ca_list_size * sizeof(*sc->ca_list)); |
| 449 | if (sc->ca_list == NULL) { | 475 | if (sc->ca_list == NULL) { |
| 450 | return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error"); | 476 | return apr_psprintf(parms->pool, |
| 451 | } | 477 | "mod_gnutls: Memory allocation error"); |
| 452 | 478 | } | |
| 453 | rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, | 479 | |
| 454 | &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); | 480 | rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, |
| 455 | if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) { | 481 | &data, GNUTLS_X509_FMT_PEM, |
| 456 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | 482 | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); |
| 457 | "Client CA File '%s': (%d) %s", file, rv, | 483 | if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) { |
| 458 | gnutls_strerror(rv)); | 484 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " |
| 459 | } | 485 | "Client CA File '%s': (%d) %s", file, |
| 460 | 486 | rv, gnutls_strerror(rv)); | |
| 461 | if (INIT_CA_SIZE < sc->ca_list_size) { | 487 | } |
| 462 | sc->ca_list = realloc(sc->ca_list, sc->ca_list_size*sizeof(*sc->ca_list)); | 488 | |
| 463 | if (sc->ca_list == NULL) { | 489 | if (INIT_CA_SIZE < sc->ca_list_size) { |
| 464 | return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error"); | 490 | sc->ca_list = |
| 465 | } | 491 | realloc(sc->ca_list, |
| 466 | 492 | sc->ca_list_size * sizeof(*sc->ca_list)); | |
| 467 | /* re-read */ | 493 | if (sc->ca_list == NULL) { |
| 468 | rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, | 494 | return apr_psprintf(parms->pool, |
| 469 | &data, GNUTLS_X509_FMT_PEM, 0); | 495 | "mod_gnutls: Memory allocation error"); |
| 470 | 496 | } | |
| 471 | if (rv < 0) { | 497 | |
| 472 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | 498 | /* re-read */ |
| 473 | "Client CA File '%s': (%d) %s", file, rv, | 499 | rv = gnutls_x509_crt_list_import(sc->ca_list, |
| 474 | gnutls_strerror(rv)); | 500 | &sc->ca_list_size, &data, |
| 475 | } | 501 | GNUTLS_X509_FMT_PEM, 0); |
| 476 | } | 502 | |
| 477 | 503 | if (rv < 0) { | |
| 478 | apr_pool_destroy(spool); | 504 | return apr_psprintf(parms->pool, |
| 479 | return NULL; | 505 | "GnuTLS: Failed to load " |
| 506 | "Client CA File '%s': (%d) %s", | ||
| 507 | file, rv, gnutls_strerror(rv)); | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 511 | apr_pool_destroy(spool); | ||
| 512 | return NULL; | ||
| 480 | } | 513 | } |
| 481 | 514 | ||
| 482 | const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, | 515 | const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, |
| 483 | const char *arg) | 516 | const char *arg) |
| 484 | { | 517 | { |
| 485 | int rv; | 518 | int rv; |
| 486 | const char *file; | 519 | const char *file; |
| 487 | apr_pool_t *spool; | 520 | apr_pool_t *spool; |
| 488 | gnutls_datum_t data; | 521 | gnutls_datum_t data; |
| 489 | 522 | ||
| 490 | mgs_srvconf_rec *sc = | 523 | mgs_srvconf_rec *sc = |
| 491 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 524 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 492 | module_config, | 525 | module_config, |
| 493 | &gnutls_module); | 526 | &gnutls_module); |
| 494 | apr_pool_create(&spool, parms->pool); | 527 | apr_pool_create(&spool, parms->pool); |
| 495 | 528 | ||
| 496 | file = ap_server_root_relative(spool, arg); | 529 | file = ap_server_root_relative(spool, arg); |
| 497 | 530 | ||
| 498 | if (load_datum_from_file(spool, file, &data) != 0) { | 531 | if (load_datum_from_file(spool, file, &data) != 0) { |
| 499 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " | 532 | return apr_psprintf(parms->pool, "GnuTLS: Error Reading " |
| 500 | "Keyring File '%s'", file); | 533 | "Keyring File '%s'", file); |
| 501 | } | 534 | } |
| 502 | 535 | ||
| 503 | rv = gnutls_openpgp_keyring_init(&sc->pgp_list); | 536 | rv = gnutls_openpgp_keyring_init(&sc->pgp_list); |
| 504 | if (rv < 0) { | 537 | if (rv < 0) { |
| 505 | return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" | 538 | return apr_psprintf(parms->pool, |
| 506 | "keyring: (%d) %s", rv, gnutls_strerror(rv)); | 539 | "GnuTLS: Failed to initialize" |
| 507 | } | 540 | "keyring: (%d) %s", rv, |
| 508 | 541 | gnutls_strerror(rv)); | |
| 509 | rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, GNUTLS_OPENPGP_FMT_BASE64); | 542 | } |
| 510 | if (rv < 0) { | 543 | |
| 511 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | 544 | rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, |
| 512 | "Keyring File '%s': (%d) %s", file, rv, | 545 | GNUTLS_OPENPGP_FMT_BASE64); |
| 513 | gnutls_strerror(rv)); | 546 | if (rv < 0) { |
| 514 | } | 547 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " |
| 515 | 548 | "Keyring File '%s': (%d) %s", file, rv, | |
| 516 | apr_pool_destroy(spool); | 549 | gnutls_strerror(rv)); |
| 517 | return NULL; | 550 | } |
| 551 | |||
| 552 | apr_pool_destroy(spool); | ||
| 553 | return NULL; | ||
| 518 | } | 554 | } |
| 519 | 555 | ||
| 520 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, | 556 | const char *mgs_set_enabled(cmd_parms * parms, void *dummy, |
| 521 | const char *arg) | 557 | const char *arg) |
| 522 | { | 558 | { |
| 523 | mgs_srvconf_rec *sc = | 559 | mgs_srvconf_rec *sc = |
| 524 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 560 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 525 | module_config, | 561 | module_config, |
| 526 | &gnutls_module); | 562 | &gnutls_module); |
| 527 | if (!strcasecmp(arg, "On")) { | 563 | if (!strcasecmp(arg, "On")) { |
| 528 | sc->enabled = GNUTLS_ENABLED_TRUE; | 564 | sc->enabled = GNUTLS_ENABLED_TRUE; |
| 529 | } else if (!strcasecmp(arg, "Off")) { | 565 | } else if (!strcasecmp(arg, "Off")) { |
| 530 | sc->enabled = GNUTLS_ENABLED_FALSE; | 566 | sc->enabled = GNUTLS_ENABLED_FALSE; |
| 531 | } else { | 567 | } else { |
| 532 | return "GnuTLSEnable must be set to 'On' or 'Off'"; | 568 | return "GnuTLSEnable must be set to 'On' or 'Off'"; |
| 533 | } | 569 | } |
| 534 | 570 | ||
| 535 | return NULL; | 571 | return NULL; |
| 536 | } | 572 | } |
| 537 | 573 | ||
| 538 | const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, | 574 | const char *mgs_set_export_certificates_enabled(cmd_parms * parms, |
| 539 | const char *arg) | 575 | void *dummy, |
| 576 | const char *arg) | ||
| 540 | { | 577 | { |
| 541 | mgs_srvconf_rec *sc = | 578 | mgs_srvconf_rec *sc = |
| 542 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 579 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 543 | module_config, | 580 | module_config, |
| 544 | &gnutls_module); | 581 | &gnutls_module); |
| 545 | if (!strcasecmp(arg, "On")) { | 582 | if (!strcasecmp(arg, "On")) { |
| 546 | sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE; | 583 | sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE; |
| 547 | } else if (!strcasecmp(arg, "Off")) { | 584 | } else if (!strcasecmp(arg, "Off")) { |
| 548 | sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE; | 585 | sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE; |
| 549 | } else { | 586 | } else { |
| 550 | return "GnuTLSExportCertificates must be set to 'On' or 'Off'"; | 587 | return |
| 551 | } | 588 | "GnuTLSExportCertificates must be set to 'On' or 'Off'"; |
| 552 | 589 | } | |
| 553 | return NULL; | 590 | |
| 591 | return NULL; | ||
| 554 | } | 592 | } |
| 555 | 593 | ||
| 556 | 594 | ||
| 557 | const char *mgs_set_priorities(cmd_parms * parms, void *dummy, const char *arg) | 595 | const char *mgs_set_priorities(cmd_parms * parms, void *dummy, |
| 596 | const char *arg) | ||
| 558 | { | 597 | { |
| 559 | int ret; | 598 | int ret; |
| 560 | const char *err; | 599 | const char *err; |
| 561 | mgs_srvconf_rec *sc = | 600 | mgs_srvconf_rec *sc = |
| 562 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> | 601 | (mgs_srvconf_rec *) ap_get_module_config(parms->server-> |
| 563 | module_config, | 602 | module_config, |
| 564 | &gnutls_module); | 603 | &gnutls_module); |
| 565 | 604 | ||
| 566 | 605 | ||
| 567 | ret = gnutls_priority_init( &sc->priorities, arg, &err); | 606 | ret = gnutls_priority_init(&sc->priorities, arg, &err); |
| 568 | if (ret < 0) { | 607 | if (ret < 0) { |
| 569 | if (ret == GNUTLS_E_INVALID_REQUEST) | 608 | if (ret == GNUTLS_E_INVALID_REQUEST) |
| 570 | return apr_psprintf(parms->pool, "GnuTLS: Syntax error parsing priorities string at: %s", err); | 609 | return apr_psprintf(parms->pool, |
| 571 | return "Error setting priorities"; | 610 | "GnuTLS: Syntax error parsing priorities string at: %s", |
| 572 | } | 611 | err); |
| 573 | 612 | return "Error setting priorities"; | |
| 574 | return NULL; | 613 | } |
| 614 | |||
| 615 | return NULL; | ||
| 575 | } | 616 | } |
| 576 | 617 | ||
| 577 | void *mgs_config_server_create(apr_pool_t * p, server_rec * s) | 618 | void *mgs_config_server_create(apr_pool_t * p, server_rec * s) |
| 578 | { | 619 | { |
| 579 | mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); | 620 | mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); |
| 580 | int ret; | 621 | int ret; |
| 581 | |||
| 582 | sc->enabled = GNUTLS_ENABLED_FALSE; | ||
| 583 | |||
| 584 | ret = gnutls_certificate_allocate_credentials(&sc->certs); | ||
| 585 | if (ret < 0) { | ||
| 586 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
| 587 | ": (%d) %s", ret, gnutls_strerror(ret)); | ||
| 588 | } | ||
| 589 | |||
| 590 | ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); | ||
| 591 | if (ret < 0) { | ||
| 592 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
| 593 | ": (%d) %s", ret, gnutls_strerror(ret)); | ||
| 594 | } | ||
| 595 | 622 | ||
| 623 | sc->enabled = GNUTLS_ENABLED_FALSE; | ||
| 624 | |||
| 625 | ret = gnutls_certificate_allocate_credentials(&sc->certs); | ||
| 626 | if (ret < 0) { | ||
| 627 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
| 628 | ": (%d) %s", ret, | ||
| 629 | gnutls_strerror(ret)); | ||
| 630 | } | ||
| 631 | |||
| 632 | ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); | ||
| 633 | if (ret < 0) { | ||
| 634 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | ||
| 635 | ": (%d) %s", ret, | ||
| 636 | gnutls_strerror(ret)); | ||
| 637 | } | ||
| 596 | #ifdef ENABLE_SRP | 638 | #ifdef ENABLE_SRP |
| 597 | ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); | 639 | ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); |
| 598 | if (ret < 0) { | 640 | if (ret < 0) { |
| 599 | return apr_psprintf(p, "GnuTLS: Failed to initialize" | 641 | return apr_psprintf(p, "GnuTLS: Failed to initialize" |
| 600 | ": (%d) %s", ret, gnutls_strerror(ret)); | 642 | ": (%d) %s", ret, |
| 601 | } | 643 | gnutls_strerror(ret)); |
| 602 | 644 | } | |
| 603 | sc->srp_tpasswd_conf_file = NULL; | 645 | |
| 604 | sc->srp_tpasswd_file = NULL; | 646 | sc->srp_tpasswd_conf_file = NULL; |
| 647 | sc->srp_tpasswd_file = NULL; | ||
| 605 | #endif | 648 | #endif |
| 606 | 649 | ||
| 607 | sc->privkey_x509 = NULL; | 650 | sc->privkey_x509 = NULL; |
| 608 | memset( sc->certs_x509, 0, sizeof(sc->certs_x509)); | 651 | memset(sc->certs_x509, 0, sizeof(sc->certs_x509)); |
| 609 | sc->certs_x509_num = 0; | 652 | sc->certs_x509_num = 0; |
| 610 | sc->cache_timeout = apr_time_from_sec(300); | 653 | sc->cache_timeout = apr_time_from_sec(300); |
| 611 | sc->cache_type = mgs_cache_none; | 654 | sc->cache_type = mgs_cache_none; |
| 612 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); | 655 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); |
| 613 | sc->tickets = 1; /* by default enable session tickets */ | 656 | sc->tickets = 1; /* by default enable session tickets */ |
| 614 | 657 | ||
| 615 | sc->client_verify_mode = GNUTLS_CERT_IGNORE; | 658 | sc->client_verify_mode = GNUTLS_CERT_IGNORE; |
| 616 | 659 | ||
| 617 | return sc; | 660 | return sc; |
| 618 | } | 661 | } |
| 619 | 662 | ||
| 620 | void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) | 663 | void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) |
| 621 | { | 664 | { |
| 622 | mgs_dirconf_rec *new; | 665 | mgs_dirconf_rec *new; |
| 623 | /* mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */ | 666 | /* mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */ |
| 624 | mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv; | 667 | mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv; |
| 625 | 668 | ||
| 626 | new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec)); | 669 | new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec)); |
| 627 | new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode, | 670 | new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode, |
| 628 | add->lua_bytecode_len); | 671 | add->lua_bytecode_len); |
| 629 | new->lua_bytecode_len = add->lua_bytecode_len; | 672 | new->lua_bytecode_len = add->lua_bytecode_len; |
| 630 | new->client_verify_mode = add->client_verify_mode; | 673 | new->client_verify_mode = add->client_verify_mode; |
| 631 | return new; | 674 | return new; |
| 632 | } | 675 | } |
| 633 | 676 | ||
| 634 | void *mgs_config_dir_create(apr_pool_t * p, char *dir) | 677 | void *mgs_config_dir_create(apr_pool_t * p, char *dir) |
| 635 | { | 678 | { |
| 636 | mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); | 679 | mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); |
| 637 | 680 | ||
| 638 | dc->client_verify_mode = -1; | 681 | dc->client_verify_mode = -1; |
| 639 | dc->lua_bytecode = NULL; | 682 | dc->lua_bytecode = NULL; |
| 640 | dc->lua_bytecode_len = 0; | 683 | dc->lua_bytecode_len = 0; |
| 641 | return dc; | 684 | return dc; |
| 642 | } | 685 | } |
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c index 7c638fb..34c3585 100644 --- a/src/gnutls_hooks.c +++ b/src/gnutls_hooks.c | |||
| @@ -40,179 +40,191 @@ static gnutls_datum session_ticket_key = { NULL, 0 }; | |||
| 40 | 40 | ||
| 41 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); | 41 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); |
| 42 | /* use side==0 for server and side==1 for client */ | 42 | /* use side==0 for server and side==1 for client */ |
| 43 | static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, | 43 | static void mgs_add_common_cert_vars(request_rec * r, |
| 44 | int side, | 44 | gnutls_x509_crt_t cert, int side, |
| 45 | int export_certificates_enabled); | ||
| 46 | static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, | ||
| 47 | int side, | ||
| 48 | int export_certificates_enabled); | 45 | int export_certificates_enabled); |
| 46 | static void mgs_add_common_pgpcert_vars(request_rec * r, | ||
| 47 | gnutls_openpgp_crt_t cert, | ||
| 48 | int side, | ||
| 49 | int export_certificates_enabled); | ||
| 49 | 50 | ||
| 50 | static apr_status_t mgs_cleanup_pre_config(void *data) | 51 | static apr_status_t mgs_cleanup_pre_config(void *data) |
| 51 | { | 52 | { |
| 52 | gnutls_free(session_ticket_key.data); | 53 | gnutls_free(session_ticket_key.data); |
| 53 | session_ticket_key.data = NULL; | 54 | session_ticket_key.data = NULL; |
| 54 | session_ticket_key.size = 0; | 55 | session_ticket_key.size = 0; |
| 55 | gnutls_global_deinit(); | 56 | gnutls_global_deinit(); |
| 56 | return APR_SUCCESS; | 57 | return APR_SUCCESS; |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | #if MOD_GNUTLS_DEBUG | 60 | #if MOD_GNUTLS_DEBUG |
| 60 | static void gnutls_debug_log_all(int level, const char *str) | 61 | static void gnutls_debug_log_all(int level, const char *str) |
| 61 | { | 62 | { |
| 62 | apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); | 63 | apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); |
| 63 | } | 64 | } |
| 65 | |||
| 64 | #define _gnutls_log apr_file_printf | 66 | #define _gnutls_log apr_file_printf |
| 65 | #else | 67 | #else |
| 66 | # define _gnutls_log(...) | 68 | # define _gnutls_log(...) |
| 67 | #endif | 69 | #endif |
| 68 | 70 | ||
| 69 | int | 71 | int |
| 70 | mgs_hook_pre_config(apr_pool_t * pconf, | 72 | mgs_hook_pre_config(apr_pool_t * pconf, |
| 71 | apr_pool_t * plog, apr_pool_t * ptemp) | 73 | apr_pool_t * plog, apr_pool_t * ptemp) |
| 72 | { | 74 | { |
| 73 | int ret; | 75 | int ret; |
| 74 | 76 | ||
| 75 | #if MOD_GNUTLS_DEBUG | 77 | #if MOD_GNUTLS_DEBUG |
| 76 | apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", | 78 | apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", |
| 77 | APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, | 79 | APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, |
| 78 | pconf); | 80 | pconf); |
| 79 | 81 | ||
| 80 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 82 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 81 | 83 | ||
| 82 | gnutls_global_set_log_level(9); | 84 | gnutls_global_set_log_level(9); |
| 83 | gnutls_global_set_log_function(gnutls_debug_log_all); | 85 | gnutls_global_set_log_function(gnutls_debug_log_all); |
| 84 | _gnutls_log(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL)); | 86 | _gnutls_log(debug_log_fp, "gnutls: %s\n", |
| 87 | gnutls_check_version(NULL)); | ||
| 85 | #endif | 88 | #endif |
| 86 | 89 | ||
| 87 | #if APR_HAS_THREADS | 90 | #if APR_HAS_THREADS |
| 88 | ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); | 91 | ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); |
| 89 | #if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2 | 92 | #if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2 |
| 90 | if (mpm_is_threaded) { | 93 | if (mpm_is_threaded) { |
| 91 | gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); | 94 | gcry_control(GCRYCTL_SET_THREAD_CBS, |
| 92 | } | 95 | &gcry_threads_pthread); |
| 96 | } | ||
| 93 | #endif | 97 | #endif |
| 94 | #else | 98 | #else |
| 95 | mpm_is_threaded = 0; | 99 | mpm_is_threaded = 0; |
| 96 | #endif | 100 | #endif |
| 97 | 101 | ||
| 98 | 102 | ||
| 99 | if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) { | 103 | if (gnutls_check_version(LIBGNUTLS_VERSION) == NULL) { |
| 100 | _gnutls_log(debug_log_fp, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", | 104 | _gnutls_log(debug_log_fp, |
| 101 | LIBGNUTLS_VERSION, gnutls_check_version(NULL)); | 105 | "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", |
| 102 | return -3; | 106 | LIBGNUTLS_VERSION, gnutls_check_version(NULL)); |
| 103 | } | 107 | return -3; |
| 108 | } | ||
| 109 | |||
| 110 | ret = gnutls_global_init(); | ||
| 111 | if (ret < 0) { | ||
| 112 | _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", | ||
| 113 | gnutls_strerror(ret)); | ||
| 114 | return -3; | ||
| 115 | } | ||
| 104 | 116 | ||
| 105 | ret = gnutls_global_init(); | 117 | ret = gnutls_session_ticket_key_generate(&session_ticket_key); |
| 106 | if (ret < 0) { | 118 | if (ret < 0) { |
| 107 | _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", gnutls_strerror(ret)); | 119 | _gnutls_log(debug_log_fp, |
| 108 | return -3; | 120 | "gnutls_session_ticket_key_generate: %s\n", |
| 109 | } | 121 | gnutls_strerror(ret)); |
| 110 | 122 | } | |
| 111 | ret = gnutls_session_ticket_key_generate( &session_ticket_key); | ||
| 112 | if (ret < 0) { | ||
| 113 | _gnutls_log(debug_log_fp, "gnutls_session_ticket_key_generate: %s\n", gnutls_strerror(ret)); | ||
| 114 | } | ||
| 115 | 123 | ||
| 116 | apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, | 124 | apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, |
| 117 | apr_pool_cleanup_null); | 125 | apr_pool_cleanup_null); |
| 118 | 126 | ||
| 119 | 127 | ||
| 120 | return OK; | 128 | return OK; |
| 121 | } | 129 | } |
| 122 | 130 | ||
| 123 | static int mgs_select_virtual_server_cb(gnutls_session_t session) | 131 | static int mgs_select_virtual_server_cb(gnutls_session_t session) |
| 124 | { | 132 | { |
| 125 | mgs_handle_t *ctxt; | 133 | mgs_handle_t *ctxt; |
| 126 | mgs_srvconf_rec *tsc; | 134 | mgs_srvconf_rec *tsc; |
| 127 | int ret; | 135 | int ret; |
| 128 | int cprio[2]; | 136 | int cprio[2]; |
| 129 | 137 | ||
| 130 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 138 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 131 | 139 | ||
| 132 | ctxt = gnutls_transport_get_ptr(session); | 140 | ctxt = gnutls_transport_get_ptr(session); |
| 133 | 141 | ||
| 134 | /* find the virtual server */ | 142 | /* find the virtual server */ |
| 135 | tsc = mgs_find_sni_server(session); | 143 | tsc = mgs_find_sni_server(session); |
| 136 | 144 | ||
| 137 | if (tsc != NULL) | 145 | if (tsc != NULL) |
| 138 | ctxt->sc = tsc; | 146 | ctxt->sc = tsc; |
| 139 | 147 | ||
| 140 | gnutls_certificate_server_set_request(session, | 148 | gnutls_certificate_server_set_request(session, |
| 141 | ctxt->sc->client_verify_mode); | 149 | ctxt-> |
| 150 | sc->client_verify_mode); | ||
| 142 | 151 | ||
| 143 | /* set the new server credentials | 152 | /* set the new server credentials |
| 144 | */ | 153 | */ |
| 145 | 154 | ||
| 146 | gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, | 155 | gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, |
| 147 | ctxt->sc->certs); | 156 | ctxt->sc->certs); |
| 148 | 157 | ||
| 149 | gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds); | 158 | gnutls_credentials_set(session, GNUTLS_CRD_ANON, |
| 159 | ctxt->sc->anon_creds); | ||
| 150 | 160 | ||
| 151 | #ifdef ENABLE_SRP | 161 | #ifdef ENABLE_SRP |
| 152 | if (ctxt->sc->srp_tpasswd_conf_file != NULL | 162 | if (ctxt->sc->srp_tpasswd_conf_file != NULL |
| 153 | && ctxt->sc->srp_tpasswd_file != NULL) { | 163 | && ctxt->sc->srp_tpasswd_file != NULL) { |
| 154 | gnutls_credentials_set(session, GNUTLS_CRD_SRP, | 164 | gnutls_credentials_set(session, GNUTLS_CRD_SRP, |
| 155 | ctxt->sc->srp_creds); | 165 | ctxt->sc->srp_creds); |
| 156 | } | 166 | } |
| 157 | #endif | 167 | #endif |
| 158 | 168 | ||
| 159 | /* update the priorities - to avoid negotiating a ciphersuite that is not | 169 | /* update the priorities - to avoid negotiating a ciphersuite that is not |
| 160 | * enabled on this virtual server. Note that here we ignore the version | 170 | * enabled on this virtual server. Note that here we ignore the version |
| 161 | * negotiation. | 171 | * negotiation. |
| 162 | */ | 172 | */ |
| 163 | ret = gnutls_priority_set(session, ctxt->sc->priorities); | 173 | ret = gnutls_priority_set(session, ctxt->sc->priorities); |
| 164 | /* actually it shouldn't fail since we have checked at startup */ | 174 | /* actually it shouldn't fail since we have checked at startup */ |
| 165 | if (ret < 0) | 175 | if (ret < 0) |
| 166 | return ret; | 176 | return ret; |
| 167 | 177 | ||
| 168 | /* If both certificate types are not present disallow them from | 178 | /* If both certificate types are not present disallow them from |
| 169 | * being negotiated. | 179 | * being negotiated. |
| 170 | */ | 180 | */ |
| 171 | if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { | 181 | if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { |
| 172 | cprio[0] = GNUTLS_CRT_X509; | 182 | cprio[0] = GNUTLS_CRT_X509; |
| 173 | cprio[1] = 0; | 183 | cprio[1] = 0; |
| 174 | gnutls_certificate_type_set_priority( session, cprio); | 184 | gnutls_certificate_type_set_priority(session, cprio); |
| 175 | } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) { | 185 | } else if (ctxt->sc->cert_pgp != NULL |
| 176 | cprio[0] = GNUTLS_CRT_OPENPGP; | 186 | && ctxt->sc->certs_x509[0] == NULL) { |
| 177 | cprio[1] = 0; | 187 | cprio[0] = GNUTLS_CRT_OPENPGP; |
| 178 | gnutls_certificate_type_set_priority( session, cprio); | 188 | cprio[1] = 0; |
| 179 | } | 189 | gnutls_certificate_type_set_priority(session, cprio); |
| 180 | 190 | } | |
| 181 | return 0; | 191 | |
| 192 | return 0; | ||
| 182 | } | 193 | } |
| 183 | 194 | ||
| 184 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) | 195 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) |
| 185 | { | 196 | { |
| 186 | mgs_handle_t *ctxt; | 197 | mgs_handle_t *ctxt; |
| 198 | |||
| 199 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
| 200 | ctxt = gnutls_transport_get_ptr(session); | ||
| 187 | 201 | ||
| 188 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 202 | if (ctxt == NULL) |
| 189 | ctxt = gnutls_transport_get_ptr(session); | 203 | return GNUTLS_E_INTERNAL_ERROR; |
| 190 | 204 | ||
| 191 | if (ctxt == NULL) | 205 | if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) { |
| 192 | return GNUTLS_E_INTERNAL_ERROR; | 206 | ret->type = GNUTLS_CRT_X509; |
| 207 | ret->ncerts = ctxt->sc->certs_x509_num; | ||
| 208 | ret->deinit_all = 0; | ||
| 193 | 209 | ||
| 194 | if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) { | 210 | ret->cert.x509 = ctxt->sc->certs_x509; |
| 195 | ret->type = GNUTLS_CRT_X509; | 211 | ret->key.x509 = ctxt->sc->privkey_x509; |
| 196 | ret->ncerts = ctxt->sc->certs_x509_num; | ||
| 197 | ret->deinit_all = 0; | ||
| 198 | 212 | ||
| 199 | ret->cert.x509 = ctxt->sc->certs_x509; | 213 | return 0; |
| 200 | ret->key.x509 = ctxt->sc->privkey_x509; | 214 | } else if (gnutls_certificate_type_get(session) == |
| 201 | 215 | GNUTLS_CRT_OPENPGP) { | |
| 202 | return 0; | 216 | ret->type = GNUTLS_CRT_OPENPGP; |
| 203 | } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) { | 217 | ret->ncerts = 1; |
| 204 | ret->type = GNUTLS_CRT_OPENPGP; | 218 | ret->deinit_all = 0; |
| 205 | ret->ncerts = 1; | ||
| 206 | ret->deinit_all = 0; | ||
| 207 | 219 | ||
| 208 | ret->cert.pgp = ctxt->sc->cert_pgp; | 220 | ret->cert.pgp = ctxt->sc->cert_pgp; |
| 209 | ret->key.pgp = ctxt->sc->privkey_pgp; | 221 | ret->key.pgp = ctxt->sc->privkey_pgp; |
| 210 | 222 | ||
| 211 | return 0; | 223 | return 0; |
| 212 | |||
| 213 | } | ||
| 214 | 224 | ||
| 215 | return GNUTLS_E_INTERNAL_ERROR; | 225 | } |
| 226 | |||
| 227 | return GNUTLS_E_INTERNAL_ERROR; | ||
| 216 | } | 228 | } |
| 217 | 229 | ||
| 218 | /* 2048-bit group parameters from SRP specification */ | 230 | /* 2048-bit group parameters from SRP specification */ |
| @@ -233,78 +245,81 @@ const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" | |||
| 233 | static int read_crt_cn(server_rec * s, apr_pool_t * p, | 245 | static int read_crt_cn(server_rec * s, apr_pool_t * p, |
| 234 | gnutls_x509_crt_t cert, char **cert_cn) | 246 | gnutls_x509_crt_t cert, char **cert_cn) |
| 235 | { | 247 | { |
| 236 | int rv = 0, i; | 248 | int rv = 0, i; |
| 237 | size_t data_len; | 249 | size_t data_len; |
| 238 | |||
| 239 | 250 | ||
| 240 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
| 241 | *cert_cn = NULL; | ||
| 242 | 251 | ||
| 243 | data_len = 0; | 252 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 244 | rv = gnutls_x509_crt_get_dn_by_oid(cert, | 253 | *cert_cn = NULL; |
| 245 | GNUTLS_OID_X520_COMMON_NAME, | ||
| 246 | 0, 0, NULL, &data_len); | ||
| 247 | 254 | ||
| 248 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { | 255 | data_len = 0; |
| 249 | *cert_cn = apr_palloc(p, data_len); | ||
| 250 | rv = gnutls_x509_crt_get_dn_by_oid(cert, | 256 | rv = gnutls_x509_crt_get_dn_by_oid(cert, |
| 251 | GNUTLS_OID_X520_COMMON_NAME, 0, | 257 | GNUTLS_OID_X520_COMMON_NAME, |
| 252 | 0, *cert_cn, &data_len); | 258 | 0, 0, NULL, &data_len); |
| 253 | } else { /* No CN return subject alternative name */ | 259 | |
| 254 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, | 260 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { |
| 255 | "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", | 261 | *cert_cn = apr_palloc(p, data_len); |
| 256 | s->server_hostname, s->port); | 262 | rv = gnutls_x509_crt_get_dn_by_oid(cert, |
| 257 | rv = 0; | 263 | GNUTLS_OID_X520_COMMON_NAME, |
| 258 | /* read subject alternative name */ | 264 | 0, 0, *cert_cn, |
| 259 | for (i = 0; !(rv < 0); i++) { | 265 | &data_len); |
| 260 | data_len = 0; | 266 | } else { /* No CN return subject alternative name */ |
| 261 | rv = gnutls_x509_crt_get_subject_alt_name(cert, i, | 267 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, |
| 262 | NULL, &data_len, | 268 | "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", |
| 263 | NULL); | 269 | s->server_hostname, s->port); |
| 264 | 270 | rv = 0; | |
| 265 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { | 271 | /* read subject alternative name */ |
| 266 | /* FIXME: not very efficient. What if we have several alt names | 272 | for (i = 0; !(rv < 0); i++) { |
| 267 | * before DNSName? | 273 | data_len = 0; |
| 268 | */ | 274 | rv = gnutls_x509_crt_get_subject_alt_name(cert, i, |
| 269 | *cert_cn = apr_palloc(p, data_len + 1); | 275 | NULL, |
| 270 | 276 | &data_len, | |
| 271 | rv = gnutls_x509_crt_get_subject_alt_name(cert, i, | 277 | NULL); |
| 272 | *cert_cn, | 278 | |
| 273 | &data_len, NULL); | 279 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER |
| 274 | (*cert_cn)[data_len] = 0; | 280 | && data_len > 1) { |
| 275 | 281 | /* FIXME: not very efficient. What if we have several alt names | |
| 276 | if (rv == GNUTLS_SAN_DNSNAME) | 282 | * before DNSName? |
| 277 | break; | 283 | */ |
| 278 | } | 284 | *cert_cn = apr_palloc(p, data_len + 1); |
| 285 | |||
| 286 | rv = gnutls_x509_crt_get_subject_alt_name | ||
| 287 | (cert, i, *cert_cn, &data_len, NULL); | ||
| 288 | (*cert_cn)[data_len] = 0; | ||
| 289 | |||
| 290 | if (rv == GNUTLS_SAN_DNSNAME) | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | } | ||
| 279 | } | 294 | } |
| 280 | } | ||
| 281 | 295 | ||
| 282 | return rv; | 296 | return rv; |
| 283 | } | 297 | } |
| 284 | 298 | ||
| 285 | static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, | 299 | static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, |
| 286 | gnutls_openpgp_crt_t cert, char **cert_cn) | 300 | gnutls_openpgp_crt_t cert, char **cert_cn) |
| 287 | { | 301 | { |
| 288 | int rv = 0; | 302 | int rv = 0; |
| 289 | size_t data_len; | 303 | size_t data_len; |
| 290 | 304 | ||
| 291 | 305 | ||
| 292 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 306 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 293 | *cert_cn = NULL; | 307 | *cert_cn = NULL; |
| 294 | 308 | ||
| 295 | data_len = 0; | 309 | data_len = 0; |
| 296 | rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); | 310 | rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); |
| 297 | 311 | ||
| 298 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { | 312 | if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { |
| 299 | *cert_cn = apr_palloc(p, data_len); | 313 | *cert_cn = apr_palloc(p, data_len); |
| 300 | rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len); | 314 | rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, |
| 301 | } else { /* No CN return subject alternative name */ | 315 | &data_len); |
| 302 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, | 316 | } else { /* No CN return subject alternative name */ |
| 303 | "No name found in PGP certificate for '%s:%d'.", | 317 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, |
| 304 | s->server_hostname, s->port); | 318 | "No name found in PGP certificate for '%s:%d'.", |
| 305 | } | 319 | s->server_hostname, s->port); |
| 320 | } | ||
| 306 | 321 | ||
| 307 | return rv; | 322 | return rv; |
| 308 | } | 323 | } |
| 309 | 324 | ||
| 310 | 325 | ||
| @@ -312,27 +327,27 @@ int | |||
| 312 | mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | 327 | mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, |
| 313 | apr_pool_t * ptemp, server_rec * base_server) | 328 | apr_pool_t * ptemp, server_rec * base_server) |
| 314 | { | 329 | { |
| 315 | int rv; | 330 | int rv; |
| 316 | server_rec *s; | 331 | server_rec *s; |
| 317 | gnutls_dh_params_t dh_params = NULL; | 332 | gnutls_dh_params_t dh_params = NULL; |
| 318 | gnutls_rsa_params_t rsa_params = NULL; | 333 | gnutls_rsa_params_t rsa_params = NULL; |
| 319 | mgs_srvconf_rec *sc; | 334 | mgs_srvconf_rec *sc; |
| 320 | mgs_srvconf_rec *sc_base; | 335 | mgs_srvconf_rec *sc_base; |
| 321 | void *data = NULL; | 336 | void *data = NULL; |
| 322 | int first_run = 0; | 337 | int first_run = 0; |
| 323 | const char *userdata_key = "mgs_init"; | 338 | const char *userdata_key = "mgs_init"; |
| 324 | 339 | ||
| 325 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 340 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 326 | apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); | 341 | apr_pool_userdata_get(&data, userdata_key, |
| 327 | if (data == NULL) { | ||
| 328 | first_run = 1; | ||
| 329 | apr_pool_userdata_set((const void *) 1, userdata_key, | ||
| 330 | apr_pool_cleanup_null, | ||
| 331 | base_server->process->pool); | 342 | base_server->process->pool); |
| 332 | } | 343 | if (data == NULL) { |
| 344 | first_run = 1; | ||
| 345 | apr_pool_userdata_set((const void *) 1, userdata_key, | ||
| 346 | apr_pool_cleanup_null, | ||
| 347 | base_server->process->pool); | ||
| 348 | } | ||
| 333 | 349 | ||
| 334 | 350 | ||
| 335 | { | ||
| 336 | s = base_server; | 351 | s = base_server; |
| 337 | sc_base = | 352 | sc_base = |
| 338 | (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 353 | (mgs_srvconf_rec *) ap_get_module_config(s->module_config, |
| @@ -341,545 +356,568 @@ mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
| 341 | gnutls_dh_params_init(&dh_params); | 356 | gnutls_dh_params_init(&dh_params); |
| 342 | 357 | ||
| 343 | if (sc_base->dh_params == NULL) { | 358 | if (sc_base->dh_params == NULL) { |
| 344 | gnutls_datum pdata = { (void *) static_dh_params, sizeof(static_dh_params) }; | 359 | gnutls_datum pdata = { |
| 345 | /* loading defaults */ | 360 | (void *) static_dh_params, |
| 346 | rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, | 361 | sizeof(static_dh_params) |
| 347 | GNUTLS_X509_FMT_PEM); | 362 | }; |
| 348 | 363 | /* loading defaults */ | |
| 349 | if (rv < 0) { | 364 | rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, |
| 350 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 365 | GNUTLS_X509_FMT_PEM); |
| 351 | "GnuTLS: Unable to load DH Params: (%d) %s", | 366 | |
| 352 | rv, gnutls_strerror(rv)); | 367 | if (rv < 0) { |
| 353 | exit(rv); | 368 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, |
| 354 | } | 369 | "GnuTLS: Unable to load DH Params: (%d) %s", |
| 355 | } else dh_params = sc_base->dh_params; | 370 | rv, gnutls_strerror(rv)); |
| 356 | 371 | exit(rv); | |
| 357 | if (sc_base->rsa_params != NULL) | 372 | } |
| 358 | rsa_params = sc_base->rsa_params; | 373 | } else |
| 374 | dh_params = sc_base->dh_params; | ||
| 375 | |||
| 376 | if (sc_base->rsa_params != NULL) | ||
| 377 | rsa_params = sc_base->rsa_params; | ||
| 359 | 378 | ||
| 360 | /* else not an error but RSA-EXPORT ciphersuites are not available | 379 | /* else not an error but RSA-EXPORT ciphersuites are not available |
| 361 | */ | 380 | */ |
| 362 | 381 | ||
| 363 | rv = mgs_cache_post_config(p, s, sc_base); | 382 | rv = mgs_cache_post_config(p, s, sc_base); |
| 364 | if (rv != 0) { | 383 | if (rv != 0) { |
| 365 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | 384 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, |
| 366 | "GnuTLS: Post Config for GnuTLSCache Failed." | 385 | "GnuTLS: Post Config for GnuTLSCache Failed." |
| 367 | " Shutting Down."); | 386 | " Shutting Down."); |
| 368 | exit(-1); | 387 | exit(-1); |
| 369 | } | 388 | } |
| 370 | 389 | ||
| 371 | for (s = base_server; s; s = s->next) { | 390 | for (s = base_server; s; s = s->next) { |
| 372 | void *load = NULL; | 391 | void *load = NULL; |
| 373 | sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 392 | sc = (mgs_srvconf_rec *) |
| 374 | &gnutls_module); | 393 | ap_get_module_config(s->module_config, &gnutls_module); |
| 375 | sc->cache_type = sc_base->cache_type; | 394 | sc->cache_type = sc_base->cache_type; |
| 376 | sc->cache_config = sc_base->cache_config; | 395 | sc->cache_config = sc_base->cache_config; |
| 377 | 396 | ||
| 378 | /* Check if the priorities have been set */ | 397 | /* Check if the priorities have been set */ |
| 379 | if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { | 398 | if (sc->priorities == NULL |
| 380 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 399 | && sc->enabled == GNUTLS_ENABLED_TRUE) { |
| 381 | "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", | 400 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, |
| 382 | s->server_hostname, s->port); | 401 | "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", |
| 383 | exit(-1); | 402 | s->server_hostname, s->port); |
| 384 | } | 403 | exit(-1); |
| 385 | 404 | } | |
| 386 | /* Check if DH or RSA params have been set per host */ | 405 | |
| 387 | if (sc->rsa_params != NULL) | 406 | /* Check if DH or RSA params have been set per host */ |
| 388 | load = sc->rsa_params; | 407 | if (sc->rsa_params != NULL) |
| 389 | else if (rsa_params) load = rsa_params; | 408 | load = sc->rsa_params; |
| 390 | 409 | else if (rsa_params) | |
| 391 | if (load != NULL) | 410 | load = rsa_params; |
| 392 | gnutls_certificate_set_rsa_export_params(sc->certs, load); | 411 | |
| 393 | 412 | if (load != NULL) | |
| 394 | 413 | gnutls_certificate_set_rsa_export_params(sc->certs, | |
| 395 | load = NULL; | 414 | load); |
| 396 | if (sc->dh_params != NULL) | 415 | |
| 397 | load = sc->dh_params; | 416 | |
| 398 | else if (dh_params) load = dh_params; | 417 | load = NULL; |
| 399 | 418 | if (sc->dh_params != NULL) | |
| 400 | if (load != NULL) { /* not needed but anyway */ | 419 | load = sc->dh_params; |
| 401 | gnutls_certificate_set_dh_params(sc->certs, load); | 420 | else if (dh_params) |
| 402 | gnutls_anon_set_server_dh_params(sc->anon_creds, load); | 421 | load = dh_params; |
| 403 | } | 422 | |
| 404 | 423 | if (load != NULL) { /* not needed but anyway */ | |
| 405 | gnutls_certificate_server_set_retrieve_function(sc->certs, | 424 | gnutls_certificate_set_dh_params(sc->certs, load); |
| 406 | cert_retrieve_fn); | 425 | gnutls_anon_set_server_dh_params(sc->anon_creds, |
| 426 | load); | ||
| 427 | } | ||
| 428 | |||
| 429 | gnutls_certificate_server_set_retrieve_function(sc->certs, | ||
| 430 | cert_retrieve_fn); | ||
| 407 | 431 | ||
| 408 | #ifdef ENABLE_SRP | 432 | #ifdef ENABLE_SRP |
| 409 | if (sc->srp_tpasswd_conf_file != NULL | 433 | if (sc->srp_tpasswd_conf_file != NULL |
| 410 | && sc->srp_tpasswd_file != NULL) { | 434 | && sc->srp_tpasswd_file != NULL) { |
| 411 | rv = gnutls_srp_set_server_credentials_file(sc->srp_creds, | 435 | rv = gnutls_srp_set_server_credentials_file |
| 412 | sc-> | 436 | (sc->srp_creds, sc->srp_tpasswd_file, |
| 413 | srp_tpasswd_file, | 437 | sc->srp_tpasswd_conf_file); |
| 414 | sc-> | 438 | |
| 415 | srp_tpasswd_conf_file); | 439 | if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { |
| 416 | 440 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, | |
| 417 | if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { | 441 | s, |
| 418 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 442 | "[GnuTLS] - Host '%s:%d' is missing a " |
| 419 | "[GnuTLS] - Host '%s:%d' is missing a " | 443 | "SRP password or conf File!", |
| 420 | "SRP password or conf File!", | 444 | s->server_hostname, s->port); |
| 421 | s->server_hostname, s->port); | 445 | exit(-1); |
| 422 | exit(-1); | 446 | } |
| 423 | } | 447 | } |
| 424 | } | ||
| 425 | #endif | 448 | #endif |
| 426 | 449 | ||
| 427 | if (sc->certs_x509[0] == NULL && | 450 | if (sc->certs_x509[0] == NULL && |
| 428 | sc->cert_pgp == NULL && | 451 | sc->cert_pgp == NULL && |
| 429 | sc->enabled == GNUTLS_ENABLED_TRUE) { | 452 | sc->enabled == GNUTLS_ENABLED_TRUE) { |
| 430 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 453 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, |
| 431 | "[GnuTLS] - Host '%s:%d' is missing a " | 454 | "[GnuTLS] - Host '%s:%d' is missing a " |
| 432 | "Certificate File!", s->server_hostname, | 455 | "Certificate File!", |
| 433 | s->port); | 456 | s->server_hostname, s->port); |
| 434 | exit(-1); | 457 | exit(-1); |
| 435 | } | 458 | } |
| 436 | |||
| 437 | if (sc->enabled == GNUTLS_ENABLED_TRUE && | ||
| 438 | ((sc->certs_x509[0] != NULL && sc->privkey_x509 == NULL) || | ||
| 439 | (sc->cert_pgp != NULL && sc->privkey_pgp == NULL))) { | ||
| 440 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
| 441 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
| 442 | "Private Key File!", | ||
| 443 | s->server_hostname, s->port); | ||
| 444 | exit(-1); | ||
| 445 | } | ||
| 446 | 459 | ||
| 447 | if (sc->enabled == GNUTLS_ENABLED_TRUE) { | 460 | if (sc->enabled == GNUTLS_ENABLED_TRUE && |
| 448 | rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); | 461 | ((sc->certs_x509[0] != NULL |
| 449 | if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ | 462 | && sc->privkey_x509 == NULL) || (sc->cert_pgp != NULL |
| 450 | rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn); | 463 | && sc->privkey_pgp |
| 464 | == NULL))) { | ||
| 465 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
| 466 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
| 467 | "Private Key File!", | ||
| 468 | s->server_hostname, s->port); | ||
| 469 | exit(-1); | ||
| 470 | } | ||
| 451 | 471 | ||
| 452 | if (rv < 0) { | 472 | if (sc->enabled == GNUTLS_ENABLED_TRUE) { |
| 453 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | 473 | rv = read_crt_cn(s, p, sc->certs_x509[0], |
| 454 | "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", | 474 | &sc->cert_cn); |
| 455 | s->server_hostname, s->port); | 475 | if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ |
| 456 | sc->cert_cn = NULL; | 476 | rv = read_pgpcrt_cn(s, p, sc->cert_pgp, |
| 457 | continue; | 477 | &sc->cert_cn); |
| 478 | |||
| 479 | if (rv < 0) { | ||
| 480 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, | ||
| 481 | s, | ||
| 482 | "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", | ||
| 483 | s->server_hostname, s->port); | ||
| 484 | sc->cert_cn = NULL; | ||
| 485 | continue; | ||
| 486 | } | ||
| 458 | } | 487 | } |
| 459 | } | ||
| 460 | } | 488 | } |
| 461 | } | ||
| 462 | 489 | ||
| 463 | ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); | ||
| 464 | 490 | ||
| 465 | return OK; | 491 | ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); |
| 492 | |||
| 493 | return OK; | ||
| 466 | } | 494 | } |
| 467 | 495 | ||
| 468 | void mgs_hook_child_init(apr_pool_t * p, server_rec * s) | 496 | void mgs_hook_child_init(apr_pool_t * p, server_rec * s) |
| 469 | { | 497 | { |
| 470 | apr_status_t rv = APR_SUCCESS; | 498 | apr_status_t rv = APR_SUCCESS; |
| 471 | mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, | 499 | mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, |
| 472 | &gnutls_module); | 500 | &gnutls_module); |
| 473 | 501 | ||
| 474 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 502 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 475 | if (sc->cache_type != mgs_cache_none) { | 503 | if (sc->cache_type != mgs_cache_none) { |
| 476 | rv = mgs_cache_child_init(p, s, sc); | 504 | rv = mgs_cache_child_init(p, s, sc); |
| 477 | if (rv != APR_SUCCESS) { | 505 | if (rv != APR_SUCCESS) { |
| 478 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, | 506 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, |
| 479 | "[GnuTLS] - Failed to run Cache Init"); | 507 | "[GnuTLS] - Failed to run Cache Init"); |
| 508 | } | ||
| 509 | } else { | ||
| 510 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, | ||
| 511 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); | ||
| 480 | } | 512 | } |
| 481 | } else { | ||
| 482 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, | ||
| 483 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); | ||
| 484 | } | ||
| 485 | } | 513 | } |
| 486 | 514 | ||
| 487 | const char *mgs_hook_http_scheme(const request_rec * r) | 515 | const char *mgs_hook_http_scheme(const request_rec * r) |
| 488 | { | 516 | { |
| 489 | mgs_srvconf_rec *sc; | 517 | mgs_srvconf_rec *sc; |
| 490 | |||
| 491 | if (r == NULL) | ||
| 492 | return NULL; | ||
| 493 | |||
| 494 | sc = | ||
| 495 | (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config, | ||
| 496 | &gnutls_module); | ||
| 497 | |||
| 498 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
| 499 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
| 500 | return NULL; | ||
| 501 | } | ||
| 502 | 518 | ||
| 503 | return "https"; | 519 | if (r == NULL) |
| 520 | return NULL; | ||
| 521 | |||
| 522 | sc = (mgs_srvconf_rec *) ap_get_module_config(r-> | ||
| 523 | server->module_config, | ||
| 524 | &gnutls_module); | ||
| 525 | |||
| 526 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | ||
| 527 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | ||
| 528 | return NULL; | ||
| 529 | } | ||
| 530 | |||
| 531 | return "https"; | ||
| 504 | } | 532 | } |
| 505 | 533 | ||
| 506 | apr_port_t mgs_hook_default_port(const request_rec * r) | 534 | apr_port_t mgs_hook_default_port(const request_rec * r) |
| 507 | { | 535 | { |
| 508 | mgs_srvconf_rec *sc; | 536 | mgs_srvconf_rec *sc; |
| 509 | 537 | ||
| 510 | if (r == NULL) | 538 | if (r == NULL) |
| 511 | return 0; | 539 | return 0; |
| 512 | 540 | ||
| 513 | sc = | 541 | sc = (mgs_srvconf_rec *) ap_get_module_config(r-> |
| 514 | (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config, | 542 | server->module_config, |
| 515 | &gnutls_module); | 543 | &gnutls_module); |
| 516 | 544 | ||
| 517 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 545 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 518 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { | 546 | if (sc->enabled == GNUTLS_ENABLED_FALSE) { |
| 519 | return 0; | 547 | return 0; |
| 520 | } | 548 | } |
| 521 | 549 | ||
| 522 | return 443; | 550 | return 443; |
| 523 | } | 551 | } |
| 524 | 552 | ||
| 525 | #define MAX_HOST_LEN 255 | 553 | #define MAX_HOST_LEN 255 |
| 526 | 554 | ||
| 527 | #if USING_2_1_RECENT | 555 | #if USING_2_1_RECENT |
| 528 | typedef struct { | 556 | typedef struct { |
| 529 | mgs_handle_t *ctxt; | 557 | mgs_handle_t *ctxt; |
| 530 | mgs_srvconf_rec *sc; | 558 | mgs_srvconf_rec *sc; |
| 531 | const char *sni_name; | 559 | const char *sni_name; |
| 532 | } vhost_cb_rec; | 560 | } vhost_cb_rec; |
| 533 | 561 | ||
| 534 | static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) | 562 | static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) |
| 535 | { | 563 | { |
| 536 | mgs_srvconf_rec *tsc; | 564 | mgs_srvconf_rec *tsc; |
| 537 | vhost_cb_rec *x = baton; | 565 | vhost_cb_rec *x = baton; |
| 538 | 566 | ||
| 539 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 567 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 540 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 568 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, |
| 541 | &gnutls_module); | 569 | &gnutls_module); |
| 542 | 570 | ||
| 543 | if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { | 571 | if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { |
| 544 | return 0; | 572 | return 0; |
| 545 | } | 573 | } |
| 546 | 574 | ||
| 547 | /* The CN can contain a * -- this will match those too. */ | 575 | /* The CN can contain a * -- this will match those too. */ |
| 548 | if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { | 576 | if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { |
| 549 | /* found a match */ | 577 | /* found a match */ |
| 550 | #if MOD_GNUTLS_DEBUG | 578 | #if MOD_GNUTLS_DEBUG |
| 551 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 579 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
| 552 | x->ctxt->c->base_server, | 580 | x->ctxt->c->base_server, |
| 553 | "GnuTLS: Virtual Host CB: " | 581 | "GnuTLS: Virtual Host CB: " |
| 554 | "'%s' == '%s'", tsc->cert_cn, x->sni_name); | 582 | "'%s' == '%s'", tsc->cert_cn, x->sni_name); |
| 555 | #endif | 583 | #endif |
| 556 | /* Because we actually change the server used here, we need to reset | 584 | /* Because we actually change the server used here, we need to reset |
| 557 | * things like ClientVerify. | 585 | * things like ClientVerify. |
| 558 | */ | 586 | */ |
| 559 | x->sc = tsc; | 587 | x->sc = tsc; |
| 560 | /* Shit. Crap. Dammit. We *really* should rehandshake here, as our | 588 | /* Shit. Crap. Dammit. We *really* should rehandshake here, as our |
| 561 | * certificate structure *should* change when the server changes. | 589 | * certificate structure *should* change when the server changes. |
| 562 | * acccckkkkkk. | 590 | * acccckkkkkk. |
| 563 | */ | 591 | */ |
| 564 | return 1; | 592 | return 1; |
| 565 | } else { | 593 | } else { |
| 566 | #if MOD_GNUTLS_DEBUG | 594 | #if MOD_GNUTLS_DEBUG |
| 567 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 595 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
| 568 | x->ctxt->c->base_server, | 596 | x->ctxt->c->base_server, |
| 569 | "GnuTLS: Virtual Host CB: " | 597 | "GnuTLS: Virtual Host CB: " |
| 570 | "'%s' != '%s'", tsc->cert_cn, x->sni_name); | 598 | "'%s' != '%s'", tsc->cert_cn, x->sni_name); |
| 571 | #endif | 599 | #endif |
| 572 | 600 | ||
| 573 | } | 601 | } |
| 574 | return 0; | 602 | return 0; |
| 575 | } | 603 | } |
| 576 | #endif | 604 | #endif |
| 577 | 605 | ||
| 578 | mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) | 606 | mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) |
| 579 | { | 607 | { |
| 580 | int rv; | 608 | int rv; |
| 581 | unsigned int sni_type; | 609 | unsigned int sni_type; |
| 582 | size_t data_len = MAX_HOST_LEN; | 610 | size_t data_len = MAX_HOST_LEN; |
| 583 | char sni_name[MAX_HOST_LEN]; | 611 | char sni_name[MAX_HOST_LEN]; |
| 584 | mgs_handle_t *ctxt; | 612 | mgs_handle_t *ctxt; |
| 585 | #if USING_2_1_RECENT | 613 | #if USING_2_1_RECENT |
| 586 | vhost_cb_rec cbx; | 614 | vhost_cb_rec cbx; |
| 587 | #else | 615 | #else |
| 588 | server_rec *s; | 616 | server_rec *s; |
| 589 | mgs_srvconf_rec *tsc; | 617 | mgs_srvconf_rec *tsc; |
| 590 | #endif | 618 | #endif |
| 591 | 619 | ||
| 592 | if (session == NULL) | 620 | if (session == NULL) |
| 593 | return NULL; | 621 | return NULL; |
| 594 | 622 | ||
| 595 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 623 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 596 | ctxt = gnutls_transport_get_ptr(session); | 624 | ctxt = gnutls_transport_get_ptr(session); |
| 597 | 625 | ||
| 598 | rv = gnutls_server_name_get(ctxt->session, sni_name, | 626 | rv = gnutls_server_name_get(ctxt->session, sni_name, |
| 599 | &data_len, &sni_type, 0); | 627 | &data_len, &sni_type, 0); |
| 600 | 628 | ||
| 601 | if (rv != 0) { | 629 | if (rv != 0) { |
| 602 | return NULL; | 630 | return NULL; |
| 603 | } | 631 | } |
| 604 | 632 | ||
| 605 | if (sni_type != GNUTLS_NAME_DNS) { | 633 | if (sni_type != GNUTLS_NAME_DNS) { |
| 606 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, | 634 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, |
| 607 | ctxt->c->base_server, | 635 | ctxt->c->base_server, |
| 608 | "GnuTLS: Unknown type '%d' for SNI: " | 636 | "GnuTLS: Unknown type '%d' for SNI: " |
| 609 | "'%s'", sni_type, sni_name); | 637 | "'%s'", sni_type, sni_name); |
| 610 | return NULL; | 638 | return NULL; |
| 611 | } | 639 | } |
| 612 | 640 | ||
| 613 | /** | 641 | /** |
| 614 | * Code in the Core already sets up the c->base_server as the base | 642 | * Code in the Core already sets up the c->base_server as the base |
| 615 | * for this IP/Port combo. Trust that the core did the 'right' thing. | 643 | * for this IP/Port combo. Trust that the core did the 'right' thing. |
| 616 | */ | 644 | */ |
| 617 | #if USING_2_1_RECENT | 645 | #if USING_2_1_RECENT |
| 618 | cbx.ctxt = ctxt; | 646 | cbx.ctxt = ctxt; |
| 619 | cbx.sc = NULL; | 647 | cbx.sc = NULL; |
| 620 | cbx.sni_name = sni_name; | 648 | cbx.sni_name = sni_name; |
| 621 | |||
| 622 | rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); | ||
| 623 | if (rv == 1) { | ||
| 624 | return cbx.sc; | ||
| 625 | } | ||
| 626 | #else | ||
| 627 | for (s = ap_server_conf; s; s = s->next) { | ||
| 628 | 649 | ||
| 629 | tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, | 650 | rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); |
| 630 | &gnutls_module); | 651 | if (rv == 1) { |
| 631 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { | 652 | return cbx.sc; |
| 632 | continue; | ||
| 633 | } | 653 | } |
| 654 | #else | ||
| 655 | for (s = ap_server_conf; s; s = s->next) { | ||
| 656 | |||
| 657 | tsc = | ||
| 658 | (mgs_srvconf_rec *) | ||
| 659 | ap_get_module_config(s->module_config, &gnutls_module); | ||
| 660 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { | ||
| 661 | continue; | ||
| 662 | } | ||
| 634 | #if MOD_GNUTLS_DEBUG | 663 | #if MOD_GNUTLS_DEBUG |
| 635 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 664 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
| 636 | ctxt->c->base_server, | 665 | ctxt->c->base_server, |
| 637 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", | 666 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", |
| 638 | tsc->cert_cn, rv, | 667 | tsc->cert_cn, rv, |
| 639 | gnutls_pk_algorithm_get_name | 668 | gnutls_pk_algorithm_get_name |
| 640 | (gnutls_x509_privkey_get_pk_algorithm | 669 | (gnutls_x509_privkey_get_pk_algorithm |
| 641 | (ctxt->sc->privkey_x509)), (unsigned int) s, | 670 | (ctxt->sc->privkey_x509)), (unsigned int) s, |
| 642 | (unsigned int) s->next, (unsigned int) tsc); | 671 | (unsigned int) s->next, (unsigned int) tsc); |
| 643 | #endif | 672 | #endif |
| 644 | /* The CN can contain a * -- this will match those too. */ | 673 | /* The CN can contain a * -- this will match those too. */ |
| 645 | if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { | 674 | if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { |
| 646 | #if MOD_GNUTLS_DEBUG | 675 | #if MOD_GNUTLS_DEBUG |
| 647 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 676 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
| 648 | ctxt->c->base_server, | 677 | ctxt->c->base_server, |
| 649 | "GnuTLS: Virtual Host: " | 678 | "GnuTLS: Virtual Host: " |
| 650 | "'%s' == '%s'", tsc->cert_cn, sni_name); | 679 | "'%s' == '%s'", tsc->cert_cn, |
| 680 | sni_name); | ||
| 651 | #endif | 681 | #endif |
| 652 | return tsc; | 682 | return tsc; |
| 683 | } | ||
| 653 | } | 684 | } |
| 654 | } | ||
| 655 | #endif | 685 | #endif |
| 656 | return NULL; | 686 | return NULL; |
| 657 | } | 687 | } |
| 658 | 688 | ||
| 659 | 689 | ||
| 660 | static const int protocol_priority[] = { | 690 | static const int protocol_priority[] = { |
| 661 | GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 | 691 | GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 |
| 662 | }; | 692 | }; |
| 663 | 693 | ||
| 664 | 694 | ||
| 665 | static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) | 695 | static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) |
| 666 | { | 696 | { |
| 667 | mgs_handle_t *ctxt; | 697 | mgs_handle_t *ctxt; |
| 668 | mgs_srvconf_rec *sc = | 698 | mgs_srvconf_rec *sc = |
| 669 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> | 699 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> |
| 670 | module_config, | 700 | module_config, |
| 671 | &gnutls_module); | 701 | &gnutls_module); |
| 672 | 702 | ||
| 673 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 703 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 674 | ctxt = apr_pcalloc(pool, sizeof(*ctxt)); | 704 | ctxt = apr_pcalloc(pool, sizeof(*ctxt)); |
| 675 | ctxt->c = c; | 705 | ctxt->c = c; |
| 676 | ctxt->sc = sc; | 706 | ctxt->sc = sc; |
| 677 | ctxt->status = 0; | 707 | ctxt->status = 0; |
| 678 | 708 | ||
| 679 | ctxt->input_rc = APR_SUCCESS; | 709 | ctxt->input_rc = APR_SUCCESS; |
| 680 | ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); | 710 | ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); |
| 681 | ctxt->input_cbuf.length = 0; | 711 | ctxt->input_cbuf.length = 0; |
| 682 | 712 | ||
| 683 | ctxt->output_rc = APR_SUCCESS; | 713 | ctxt->output_rc = APR_SUCCESS; |
| 684 | ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); | 714 | ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); |
| 685 | ctxt->output_blen = 0; | 715 | ctxt->output_blen = 0; |
| 686 | ctxt->output_length = 0; | 716 | ctxt->output_length = 0; |
| 687 | 717 | ||
| 688 | gnutls_init(&ctxt->session, GNUTLS_SERVER); | 718 | gnutls_init(&ctxt->session, GNUTLS_SERVER); |
| 689 | if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) | 719 | if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) |
| 690 | gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key); | 720 | gnutls_session_ticket_enable_server(ctxt->session, |
| 691 | 721 | &session_ticket_key); | |
| 692 | /* because we don't set any default priorities here (we set later at | 722 | |
| 693 | * the user hello callback) we need to at least set this in order for | 723 | /* because we don't set any default priorities here (we set later at |
| 694 | * gnutls to be able to read packets. | 724 | * the user hello callback) we need to at least set this in order for |
| 695 | */ | 725 | * gnutls to be able to read packets. |
| 696 | gnutls_protocol_set_priority(ctxt->session, protocol_priority); | 726 | */ |
| 727 | gnutls_protocol_set_priority(ctxt->session, protocol_priority); | ||
| 697 | 728 | ||
| 698 | gnutls_handshake_set_post_client_hello_function(ctxt->session, | 729 | gnutls_handshake_set_post_client_hello_function(ctxt->session, |
| 699 | mgs_select_virtual_server_cb); | 730 | mgs_select_virtual_server_cb); |
| 700 | 731 | ||
| 701 | mgs_cache_session_init(ctxt); | 732 | mgs_cache_session_init(ctxt); |
| 702 | 733 | ||
| 703 | return ctxt; | 734 | return ctxt; |
| 704 | } | 735 | } |
| 705 | 736 | ||
| 706 | int mgs_hook_pre_connection(conn_rec * c, void *csd) | 737 | int mgs_hook_pre_connection(conn_rec * c, void *csd) |
| 707 | { | 738 | { |
| 708 | mgs_handle_t *ctxt; | 739 | mgs_handle_t *ctxt; |
| 709 | mgs_srvconf_rec *sc; | 740 | mgs_srvconf_rec *sc; |
| 710 | 741 | ||
| 711 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 742 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 712 | 743 | ||
| 713 | if (c == NULL) | 744 | if (c == NULL) |
| 714 | return DECLINED; | 745 | return DECLINED; |
| 715 | |||
| 716 | sc = | ||
| 717 | (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> | ||
| 718 | module_config, | ||
| 719 | &gnutls_module); | ||
| 720 | |||
| 721 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { | ||
| 722 | return DECLINED; | ||
| 723 | } | ||
| 724 | 746 | ||
| 725 | if(c->remote_addr->hostname) | 747 | sc = (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> |
| 726 | /* Connection initiated by Apache (mod_proxy) => ignore */ | 748 | module_config, |
| 727 | return OK; | 749 | &gnutls_module); |
| 728 | 750 | ||
| 729 | ctxt = create_gnutls_handle(c->pool, c); | 751 | if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { |
| 752 | return DECLINED; | ||
| 753 | } | ||
| 754 | |||
| 755 | if (c->remote_addr->hostname) | ||
| 756 | /* Connection initiated by Apache (mod_proxy) => ignore */ | ||
| 757 | return OK; | ||
| 758 | |||
| 759 | ctxt = create_gnutls_handle(c->pool, c); | ||
| 730 | 760 | ||
| 731 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); | 761 | ap_set_module_config(c->conn_config, &gnutls_module, ctxt); |
| 732 | 762 | ||
| 733 | gnutls_transport_set_pull_function(ctxt->session, mgs_transport_read); | 763 | gnutls_transport_set_pull_function(ctxt->session, |
| 734 | gnutls_transport_set_push_function(ctxt->session, mgs_transport_write); | 764 | mgs_transport_read); |
| 735 | gnutls_transport_set_ptr(ctxt->session, ctxt); | 765 | gnutls_transport_set_push_function(ctxt->session, |
| 766 | mgs_transport_write); | ||
| 767 | gnutls_transport_set_ptr(ctxt->session, ctxt); | ||
| 736 | 768 | ||
| 737 | ctxt->input_filter = | 769 | ctxt->input_filter = |
| 738 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); | 770 | ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); |
| 739 | ctxt->output_filter = | 771 | ctxt->output_filter = |
| 740 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); | 772 | ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); |
| 741 | 773 | ||
| 742 | return OK; | 774 | return OK; |
| 743 | } | 775 | } |
| 744 | 776 | ||
| 745 | int mgs_hook_fixups(request_rec * r) | 777 | int mgs_hook_fixups(request_rec * r) |
| 746 | { | 778 | { |
| 747 | unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; | 779 | unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; |
| 748 | char buf[AP_IOBUFSIZE]; | 780 | char buf[AP_IOBUFSIZE]; |
| 749 | const char *tmp; | 781 | const char *tmp; |
| 750 | size_t len; | 782 | size_t len; |
| 751 | mgs_handle_t *ctxt; | 783 | mgs_handle_t *ctxt; |
| 752 | int rv = OK; | 784 | int rv = OK; |
| 753 | 785 | ||
| 754 | if (r == NULL) | 786 | if (r == NULL) |
| 755 | return DECLINED; | 787 | return DECLINED; |
| 756 | 788 | ||
| 757 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 789 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 758 | apr_table_t *env = r->subprocess_env; | 790 | apr_table_t *env = r->subprocess_env; |
| 759 | 791 | ||
| 760 | ctxt = | 792 | ctxt = |
| 761 | ap_get_module_config(r->connection->conn_config, &gnutls_module); | 793 | ap_get_module_config(r->connection->conn_config, |
| 794 | &gnutls_module); | ||
| 762 | 795 | ||
| 763 | if (!ctxt || ctxt->session == NULL) { | 796 | if (!ctxt || ctxt->session == NULL) { |
| 764 | return DECLINED; | 797 | return DECLINED; |
| 765 | } | 798 | } |
| 766 | 799 | ||
| 767 | apr_table_setn(env, "HTTPS", "on"); | 800 | apr_table_setn(env, "HTTPS", "on"); |
| 768 | 801 | ||
| 769 | apr_table_setn(env, "SSL_VERSION_LIBRARY", | 802 | apr_table_setn(env, "SSL_VERSION_LIBRARY", |
| 770 | "GnuTLS/" LIBGNUTLS_VERSION); | 803 | "GnuTLS/" LIBGNUTLS_VERSION); |
| 771 | apr_table_setn(env, "SSL_VERSION_INTERFACE", | 804 | apr_table_setn(env, "SSL_VERSION_INTERFACE", |
| 772 | "mod_gnutls/" MOD_GNUTLS_VERSION); | 805 | "mod_gnutls/" MOD_GNUTLS_VERSION); |
| 773 | 806 | ||
| 774 | apr_table_setn(env, "SSL_PROTOCOL", | 807 | apr_table_setn(env, "SSL_PROTOCOL", |
| 775 | gnutls_protocol_get_name(gnutls_protocol_get_version | 808 | gnutls_protocol_get_name(gnutls_protocol_get_version |
| 776 | (ctxt->session))); | 809 | (ctxt->session))); |
| 777 | 810 | ||
| 778 | /* should have been called SSL_CIPHERSUITE instead */ | 811 | /* should have been called SSL_CIPHERSUITE instead */ |
| 779 | apr_table_setn(env, "SSL_CIPHER", | 812 | apr_table_setn(env, "SSL_CIPHER", |
| 780 | gnutls_cipher_suite_get_name(gnutls_kx_get | 813 | gnutls_cipher_suite_get_name(gnutls_kx_get |
| 781 | (ctxt->session), | 814 | (ctxt->session), |
| 782 | gnutls_cipher_get(ctxt-> | 815 | gnutls_cipher_get |
| 783 | session), | 816 | (ctxt->session), |
| 784 | gnutls_mac_get(ctxt-> | 817 | gnutls_mac_get |
| 785 | session))); | 818 | (ctxt->session))); |
| 786 | 819 | ||
| 787 | apr_table_setn(env, "SSL_COMPRESS_METHOD", | 820 | apr_table_setn(env, "SSL_COMPRESS_METHOD", |
| 788 | gnutls_compression_get_name(gnutls_compression_get | 821 | gnutls_compression_get_name(gnutls_compression_get |
| 789 | (ctxt->session))); | 822 | (ctxt->session))); |
| 790 | 823 | ||
| 791 | #ifdef ENABLE_SRP | 824 | #ifdef ENABLE_SRP |
| 792 | tmp = gnutls_srp_server_get_username(ctxt->session); | 825 | tmp = gnutls_srp_server_get_username(ctxt->session); |
| 793 | apr_table_setn(env, "SSL_SRP_USER", (tmp!=NULL)?tmp:""); | 826 | apr_table_setn(env, "SSL_SRP_USER", (tmp != NULL) ? tmp : ""); |
| 794 | #endif | 827 | #endif |
| 795 | 828 | ||
| 796 | if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) | 829 | if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) |
| 797 | apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); | 830 | apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); |
| 798 | 831 | ||
| 799 | unsigned int key_size = | 832 | unsigned int key_size = |
| 800 | 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); | 833 | 8 * |
| 801 | tmp = apr_psprintf(r->pool, "%u", key_size); | 834 | gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); |
| 835 | tmp = apr_psprintf(r->pool, "%u", key_size); | ||
| 802 | 836 | ||
| 803 | apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); | 837 | apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); |
| 804 | 838 | ||
| 805 | apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); | 839 | apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); |
| 806 | 840 | ||
| 807 | apr_table_setn(env, "SSL_CIPHER_EXPORT", | 841 | apr_table_setn(env, "SSL_CIPHER_EXPORT", |
| 808 | (key_size <= 40) ? "true" : "false"); | 842 | (key_size <= 40) ? "true" : "false"); |
| 809 | 843 | ||
| 810 | len = sizeof(sbuf); | 844 | len = sizeof(sbuf); |
| 811 | gnutls_session_get_id(ctxt->session, sbuf, &len); | 845 | gnutls_session_get_id(ctxt->session, sbuf, &len); |
| 812 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | 846 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); |
| 813 | apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); | 847 | apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); |
| 814 | 848 | ||
| 815 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) | 849 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) |
| 816 | mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, | 850 | mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, |
| 817 | ctxt->sc->export_certificates_enabled); | 851 | ctxt-> |
| 818 | else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | 852 | sc->export_certificates_enabled); |
| 819 | mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, | 853 | else if (gnutls_certificate_type_get(ctxt->session) == |
| 820 | ctxt->sc->export_certificates_enabled); | 854 | GNUTLS_CRT_OPENPGP) |
| 855 | mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, | ||
| 856 | ctxt-> | ||
| 857 | sc->export_certificates_enabled); | ||
| 821 | 858 | ||
| 822 | return rv; | 859 | return rv; |
| 823 | } | 860 | } |
| 824 | 861 | ||
| 825 | int mgs_hook_authz(request_rec * r) | 862 | int mgs_hook_authz(request_rec * r) |
| 826 | { | 863 | { |
| 827 | int rv; | 864 | int rv; |
| 828 | mgs_handle_t *ctxt; | 865 | mgs_handle_t *ctxt; |
| 829 | mgs_dirconf_rec *dc; | 866 | mgs_dirconf_rec *dc; |
| 830 | 867 | ||
| 831 | if (r == NULL) | 868 | if (r == NULL) |
| 832 | return DECLINED; | 869 | return DECLINED; |
| 833 | 870 | ||
| 834 | dc = ap_get_module_config(r->per_dir_config, | 871 | dc = ap_get_module_config(r->per_dir_config, &gnutls_module); |
| 835 | &gnutls_module); | 872 | |
| 836 | 873 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | |
| 837 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 874 | ctxt = |
| 838 | ctxt = | 875 | ap_get_module_config(r->connection->conn_config, |
| 839 | ap_get_module_config(r->connection->conn_config, &gnutls_module); | 876 | &gnutls_module); |
| 840 | 877 | ||
| 841 | if (!ctxt || ctxt->session == NULL) { | 878 | if (!ctxt || ctxt->session == NULL) { |
| 842 | return DECLINED; | 879 | return DECLINED; |
| 843 | } | 880 | } |
| 844 | 881 | ||
| 845 | if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { | 882 | if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { |
| 846 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 883 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
| 847 | "GnuTLS: Directory set to Ignore Client Certificate!"); | 884 | "GnuTLS: Directory set to Ignore Client Certificate!"); |
| 848 | } else { | 885 | } else { |
| 849 | if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { | 886 | if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { |
| 850 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 887 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
| 851 | "GnuTLS: Attempting to rehandshake with peer. %d %d", | 888 | "GnuTLS: Attempting to rehandshake with peer. %d %d", |
| 852 | ctxt->sc->client_verify_mode, | 889 | ctxt->sc->client_verify_mode, |
| 853 | dc->client_verify_mode); | 890 | dc->client_verify_mode); |
| 854 | 891 | ||
| 855 | /* If we already have a client certificate, there's no point in | 892 | /* If we already have a client certificate, there's no point in |
| 856 | * re-handshaking... */ | 893 | * re-handshaking... */ |
| 857 | rv = mgs_cert_verify(r, ctxt); | 894 | rv = mgs_cert_verify(r, ctxt); |
| 858 | if (rv != DECLINED && rv != HTTP_FORBIDDEN) | 895 | if (rv != DECLINED && rv != HTTP_FORBIDDEN) |
| 859 | return rv; | 896 | return rv; |
| 860 | 897 | ||
| 861 | gnutls_certificate_server_set_request(ctxt->session, | 898 | gnutls_certificate_server_set_request |
| 862 | dc->client_verify_mode); | 899 | (ctxt->session, dc->client_verify_mode); |
| 863 | 900 | ||
| 864 | if (mgs_rehandshake(ctxt) != 0) { | 901 | if (mgs_rehandshake(ctxt) != 0) { |
| 865 | return HTTP_FORBIDDEN; | 902 | return HTTP_FORBIDDEN; |
| 866 | } | 903 | } |
| 867 | } else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) { | 904 | } else if (ctxt->sc->client_verify_mode == |
| 905 | GNUTLS_CERT_IGNORE) { | ||
| 868 | #if MOD_GNUTLS_DEBUG | 906 | #if MOD_GNUTLS_DEBUG |
| 869 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 907 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
| 870 | "GnuTLS: Peer is set to IGNORE"); | 908 | "GnuTLS: Peer is set to IGNORE"); |
| 871 | #endif | 909 | #endif |
| 872 | return DECLINED; | 910 | return DECLINED; |
| 873 | } | 911 | } |
| 874 | rv = mgs_cert_verify(r, ctxt); | 912 | rv = mgs_cert_verify(r, ctxt); |
| 875 | if (rv != DECLINED && | 913 | if (rv != DECLINED && |
| 876 | (rv != HTTP_FORBIDDEN || | 914 | (rv != HTTP_FORBIDDEN || |
| 877 | dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { | 915 | dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { |
| 878 | return rv; | 916 | return rv; |
| 917 | } | ||
| 879 | } | 918 | } |
| 880 | } | ||
| 881 | 919 | ||
| 882 | return DECLINED; | 920 | return DECLINED; |
| 883 | } | 921 | } |
| 884 | 922 | ||
| 885 | /* variables that are not sent by default: | 923 | /* variables that are not sent by default: |
| @@ -895,359 +933,413 @@ static void | |||
| 895 | mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, | 933 | mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, |
| 896 | int export_certificates_enabled) | 934 | int export_certificates_enabled) |
| 897 | { | 935 | { |
| 898 | unsigned char sbuf[64]; /* buffer to hold serials */ | 936 | unsigned char sbuf[64]; /* buffer to hold serials */ |
| 899 | char buf[AP_IOBUFSIZE]; | 937 | char buf[AP_IOBUFSIZE]; |
| 900 | const char *tmp; | 938 | const char *tmp; |
| 901 | char *tmp2; | 939 | char *tmp2; |
| 902 | size_t len; | 940 | size_t len; |
| 903 | int ret, i; | 941 | int ret, i; |
| 904 | 942 | ||
| 905 | if (r == NULL) | 943 | if (r == NULL) |
| 906 | return; | 944 | return; |
| 907 | 945 | ||
| 908 | apr_table_t *env = r->subprocess_env; | 946 | apr_table_t *env = r->subprocess_env; |
| 909 | 947 | ||
| 910 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 948 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 911 | if (export_certificates_enabled != 0) { | 949 | if (export_certificates_enabled != 0) { |
| 912 | char cert_buf[10 * 1024]; | 950 | char cert_buf[10 * 1024]; |
| 913 | len = sizeof(cert_buf); | 951 | len = sizeof(cert_buf); |
| 914 | 952 | ||
| 915 | if (gnutls_x509_crt_export | 953 | if (gnutls_x509_crt_export |
| 916 | (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) | 954 | (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) |
| 917 | apr_table_setn(env, | 955 | apr_table_setn(env, |
| 918 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), | 956 | apr_pstrcat(r->pool, MGS_SIDE, |
| 919 | apr_pstrmemdup(r->pool, cert_buf, len)); | 957 | "_CERT", NULL), |
| 920 | 958 | apr_pstrmemdup(r->pool, cert_buf, | |
| 921 | } | 959 | len)); |
| 922 | 960 | ||
| 923 | len = sizeof(buf); | 961 | } |
| 924 | gnutls_x509_crt_get_dn(cert, buf, &len); | 962 | |
| 925 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), | 963 | len = sizeof(buf); |
| 926 | apr_pstrmemdup(r->pool, buf, len)); | 964 | gnutls_x509_crt_get_dn(cert, buf, &len); |
| 927 | 965 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), | |
| 928 | len = sizeof(buf); | 966 | apr_pstrmemdup(r->pool, buf, len)); |
| 929 | gnutls_x509_crt_get_issuer_dn(cert, buf, &len); | 967 | |
| 930 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), | 968 | len = sizeof(buf); |
| 931 | apr_pstrmemdup(r->pool, buf, len)); | 969 | gnutls_x509_crt_get_issuer_dn(cert, buf, &len); |
| 932 | 970 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), | |
| 933 | len = sizeof(sbuf); | 971 | apr_pstrmemdup(r->pool, buf, len)); |
| 934 | gnutls_x509_crt_get_serial(cert, sbuf, &len); | 972 | |
| 935 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | 973 | len = sizeof(sbuf); |
| 936 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), | 974 | gnutls_x509_crt_get_serial(cert, sbuf, &len); |
| 937 | apr_pstrdup(r->pool, tmp)); | 975 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); |
| 938 | |||
| 939 | ret = gnutls_x509_crt_get_version(cert); | ||
| 940 | if (ret > 0) | ||
| 941 | apr_table_setn(env, | 976 | apr_table_setn(env, |
| 942 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), | 977 | apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), |
| 943 | apr_psprintf(r->pool, "%u", ret)); | 978 | apr_pstrdup(r->pool, tmp)); |
| 944 | 979 | ||
| 945 | apr_table_setn(env, | 980 | ret = gnutls_x509_crt_get_version(cert); |
| 946 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "X.509"); | 981 | if (ret > 0) |
| 947 | |||
| 948 | tmp = | ||
| 949 | mgs_time2sz(gnutls_x509_crt_get_expiration_time | ||
| 950 | (cert), buf, sizeof(buf)); | ||
| 951 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | ||
| 952 | apr_pstrdup(r->pool, tmp)); | ||
| 953 | |||
| 954 | tmp = | ||
| 955 | mgs_time2sz(gnutls_x509_crt_get_activation_time | ||
| 956 | (cert), buf, sizeof(buf)); | ||
| 957 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | ||
| 958 | apr_pstrdup(r->pool, tmp)); | ||
| 959 | |||
| 960 | ret = gnutls_x509_crt_get_signature_algorithm(cert); | ||
| 961 | if (ret >= 0) { | ||
| 962 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", NULL), | ||
| 963 | gnutls_sign_algorithm_get_name(ret)); | ||
| 964 | } | ||
| 965 | |||
| 966 | ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); | ||
| 967 | if (ret >= 0) { | ||
| 968 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), | ||
| 969 | gnutls_pk_algorithm_get_name(ret)); | ||
| 970 | } | ||
| 971 | |||
| 972 | /* export all the alternative names (DNS, RFC822 and URI) */ | ||
| 973 | for (i = 0; !(ret < 0); i++) { | ||
| 974 | len = 0; | ||
| 975 | ret = gnutls_x509_crt_get_subject_alt_name(cert, i, | ||
| 976 | NULL, &len, NULL); | ||
| 977 | |||
| 978 | if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { | ||
| 979 | tmp2 = apr_palloc(r->pool, len + 1); | ||
| 980 | |||
| 981 | ret = | ||
| 982 | gnutls_x509_crt_get_subject_alt_name(cert, i, tmp2, &len, | ||
| 983 | NULL); | ||
| 984 | tmp2[len] = 0; | ||
| 985 | |||
| 986 | if (ret == GNUTLS_SAN_DNSNAME) { | ||
| 987 | apr_table_setn(env, | ||
| 988 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | ||
| 989 | apr_psprintf(r->pool, "DNSNAME:%s", tmp2)); | ||
| 990 | } else if (ret == GNUTLS_SAN_RFC822NAME) { | ||
| 991 | apr_table_setn(env, | 982 | apr_table_setn(env, |
| 992 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | 983 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", |
| 993 | apr_psprintf(r->pool, "RFC822NAME:%s", tmp2)); | 984 | NULL), apr_psprintf(r->pool, |
| 994 | } else if (ret == GNUTLS_SAN_URI) { | 985 | "%u", ret)); |
| 986 | |||
| 987 | apr_table_setn(env, | ||
| 988 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), | ||
| 989 | "X.509"); | ||
| 990 | |||
| 991 | tmp = | ||
| 992 | mgs_time2sz(gnutls_x509_crt_get_expiration_time | ||
| 993 | (cert), buf, sizeof(buf)); | ||
| 994 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | ||
| 995 | apr_pstrdup(r->pool, tmp)); | ||
| 996 | |||
| 997 | tmp = | ||
| 998 | mgs_time2sz(gnutls_x509_crt_get_activation_time | ||
| 999 | (cert), buf, sizeof(buf)); | ||
| 1000 | apr_table_setn(env, | ||
| 1001 | apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | ||
| 1002 | apr_pstrdup(r->pool, tmp)); | ||
| 1003 | |||
| 1004 | ret = gnutls_x509_crt_get_signature_algorithm(cert); | ||
| 1005 | if (ret >= 0) { | ||
| 995 | apr_table_setn(env, | 1006 | apr_table_setn(env, |
| 996 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | 1007 | apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", |
| 997 | apr_psprintf(r->pool, "URI:%s", tmp2)); | 1008 | NULL), |
| 998 | } else { | 1009 | gnutls_sign_algorithm_get_name(ret)); |
| 1010 | } | ||
| 1011 | |||
| 1012 | ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); | ||
| 1013 | if (ret >= 0) { | ||
| 999 | apr_table_setn(env, | 1014 | apr_table_setn(env, |
| 1000 | apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), | 1015 | apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", |
| 1001 | "UNSUPPORTED"); | 1016 | NULL), |
| 1002 | } | 1017 | gnutls_pk_algorithm_get_name(ret)); |
| 1018 | } | ||
| 1019 | |||
| 1020 | /* export all the alternative names (DNS, RFC822 and URI) */ | ||
| 1021 | for (i = 0; !(ret < 0); i++) { | ||
| 1022 | len = 0; | ||
| 1023 | ret = gnutls_x509_crt_get_subject_alt_name(cert, i, | ||
| 1024 | NULL, &len, | ||
| 1025 | NULL); | ||
| 1026 | |||
| 1027 | if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { | ||
| 1028 | tmp2 = apr_palloc(r->pool, len + 1); | ||
| 1029 | |||
| 1030 | ret = | ||
| 1031 | gnutls_x509_crt_get_subject_alt_name(cert, i, | ||
| 1032 | tmp2, | ||
| 1033 | &len, | ||
| 1034 | NULL); | ||
| 1035 | tmp2[len] = 0; | ||
| 1036 | |||
| 1037 | if (ret == GNUTLS_SAN_DNSNAME) { | ||
| 1038 | apr_table_setn(env, | ||
| 1039 | apr_psprintf(r->pool, | ||
| 1040 | "%s_S_AN%u", | ||
| 1041 | MGS_SIDE, i), | ||
| 1042 | apr_psprintf(r->pool, | ||
| 1043 | "DNSNAME:%s", | ||
| 1044 | tmp2)); | ||
| 1045 | } else if (ret == GNUTLS_SAN_RFC822NAME) { | ||
| 1046 | apr_table_setn(env, | ||
| 1047 | apr_psprintf(r->pool, | ||
| 1048 | "%s_S_AN%u", | ||
| 1049 | MGS_SIDE, i), | ||
| 1050 | apr_psprintf(r->pool, | ||
| 1051 | "RFC822NAME:%s", | ||
| 1052 | tmp2)); | ||
| 1053 | } else if (ret == GNUTLS_SAN_URI) { | ||
| 1054 | apr_table_setn(env, | ||
| 1055 | apr_psprintf(r->pool, | ||
| 1056 | "%s_S_AN%u", | ||
| 1057 | MGS_SIDE, i), | ||
| 1058 | apr_psprintf(r->pool, | ||
| 1059 | "URI:%s", | ||
| 1060 | tmp2)); | ||
| 1061 | } else { | ||
| 1062 | apr_table_setn(env, | ||
| 1063 | apr_psprintf(r->pool, | ||
| 1064 | "%s_S_AN%u", | ||
| 1065 | MGS_SIDE, i), | ||
| 1066 | "UNSUPPORTED"); | ||
| 1067 | } | ||
| 1068 | } | ||
| 1003 | } | 1069 | } |
| 1004 | } | ||
| 1005 | } | 1070 | } |
| 1006 | 1071 | ||
| 1007 | static void | 1072 | static void |
| 1008 | mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, | 1073 | mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, |
| 1009 | int export_certificates_enabled) | 1074 | int side, int export_certificates_enabled) |
| 1010 | { | 1075 | { |
| 1011 | unsigned char sbuf[64]; /* buffer to hold serials */ | 1076 | unsigned char sbuf[64]; /* buffer to hold serials */ |
| 1012 | char buf[AP_IOBUFSIZE]; | 1077 | char buf[AP_IOBUFSIZE]; |
| 1013 | const char *tmp; | 1078 | const char *tmp; |
| 1014 | size_t len; | 1079 | size_t len; |
| 1015 | int ret; | 1080 | int ret; |
| 1016 | 1081 | ||
| 1017 | if (r == NULL) | 1082 | if (r == NULL) |
| 1018 | return; | 1083 | return; |
| 1019 | 1084 | ||
| 1020 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 1085 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 1021 | apr_table_t *env = r->subprocess_env; | 1086 | apr_table_t *env = r->subprocess_env; |
| 1022 | 1087 | ||
| 1023 | if (export_certificates_enabled != 0) { | 1088 | if (export_certificates_enabled != 0) { |
| 1024 | char cert_buf[10 * 1024]; | 1089 | char cert_buf[10 * 1024]; |
| 1025 | len = sizeof(cert_buf); | 1090 | len = sizeof(cert_buf); |
| 1026 | 1091 | ||
| 1027 | if (gnutls_openpgp_crt_export | 1092 | if (gnutls_openpgp_crt_export |
| 1028 | (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) | 1093 | (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) |
| 1029 | apr_table_setn(env, | 1094 | apr_table_setn(env, |
| 1030 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), | 1095 | apr_pstrcat(r->pool, MGS_SIDE, |
| 1031 | apr_pstrmemdup(r->pool, cert_buf, len)); | 1096 | "_CERT", NULL), |
| 1032 | 1097 | apr_pstrmemdup(r->pool, cert_buf, | |
| 1033 | } | 1098 | len)); |
| 1034 | 1099 | ||
| 1035 | len = sizeof(buf); | 1100 | } |
| 1036 | gnutls_openpgp_crt_get_name(cert, 0, buf, &len); | 1101 | |
| 1037 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), | 1102 | len = sizeof(buf); |
| 1038 | apr_pstrmemdup(r->pool, buf, len)); | 1103 | gnutls_openpgp_crt_get_name(cert, 0, buf, &len); |
| 1039 | 1104 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), | |
| 1040 | len = sizeof(sbuf); | 1105 | apr_pstrmemdup(r->pool, buf, len)); |
| 1041 | gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); | 1106 | |
| 1042 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); | 1107 | len = sizeof(sbuf); |
| 1043 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), | 1108 | gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); |
| 1044 | apr_pstrdup(r->pool, tmp)); | 1109 | tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); |
| 1045 | |||
| 1046 | ret = gnutls_openpgp_crt_get_version(cert); | ||
| 1047 | if (ret > 0) | ||
| 1048 | apr_table_setn(env, | 1110 | apr_table_setn(env, |
| 1049 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), | 1111 | apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", |
| 1050 | apr_psprintf(r->pool, "%u", ret)); | 1112 | NULL), apr_pstrdup(r->pool, tmp)); |
| 1051 | 1113 | ||
| 1052 | apr_table_setn(env, | 1114 | ret = gnutls_openpgp_crt_get_version(cert); |
| 1053 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); | 1115 | if (ret > 0) |
| 1054 | 1116 | apr_table_setn(env, | |
| 1055 | tmp = | 1117 | apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", |
| 1056 | mgs_time2sz(gnutls_openpgp_crt_get_expiration_time | 1118 | NULL), apr_psprintf(r->pool, |
| 1057 | (cert), buf, sizeof(buf)); | 1119 | "%u", ret)); |
| 1058 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | 1120 | |
| 1059 | apr_pstrdup(r->pool, tmp)); | 1121 | apr_table_setn(env, |
| 1060 | 1122 | apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), | |
| 1061 | tmp = | 1123 | "OPENPGP"); |
| 1062 | mgs_time2sz(gnutls_openpgp_crt_get_creation_time | 1124 | |
| 1063 | (cert), buf, sizeof(buf)); | 1125 | tmp = |
| 1064 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | 1126 | mgs_time2sz(gnutls_openpgp_crt_get_expiration_time |
| 1065 | apr_pstrdup(r->pool, tmp)); | 1127 | (cert), buf, sizeof(buf)); |
| 1066 | 1128 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), | |
| 1067 | ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); | 1129 | apr_pstrdup(r->pool, tmp)); |
| 1068 | if (ret >= 0) { | 1130 | |
| 1069 | apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), | 1131 | tmp = |
| 1070 | gnutls_pk_algorithm_get_name(ret)); | 1132 | mgs_time2sz(gnutls_openpgp_crt_get_creation_time |
| 1071 | } | 1133 | (cert), buf, sizeof(buf)); |
| 1134 | apr_table_setn(env, | ||
| 1135 | apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), | ||
| 1136 | apr_pstrdup(r->pool, tmp)); | ||
| 1137 | |||
| 1138 | ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); | ||
| 1139 | if (ret >= 0) { | ||
| 1140 | apr_table_setn(env, | ||
| 1141 | apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", | ||
| 1142 | NULL), | ||
| 1143 | gnutls_pk_algorithm_get_name(ret)); | ||
| 1144 | } | ||
| 1072 | 1145 | ||
| 1073 | } | 1146 | } |
| 1074 | 1147 | ||
| 1075 | /* TODO: Allow client sending a X.509 certificate chain */ | 1148 | /* TODO: Allow client sending a X.509 certificate chain */ |
| 1076 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) | 1149 | static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) |
| 1077 | { | 1150 | { |
| 1078 | const gnutls_datum_t *cert_list; | 1151 | const gnutls_datum_t *cert_list; |
| 1079 | unsigned int cert_list_size, status; | 1152 | unsigned int cert_list_size, status; |
| 1080 | int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; | 1153 | int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; |
| 1081 | unsigned int ch_size = 0; | 1154 | unsigned int ch_size = 0; |
| 1082 | union { | 1155 | union { |
| 1083 | gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; | 1156 | gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; |
| 1084 | gnutls_openpgp_crt_t pgp; | 1157 | gnutls_openpgp_crt_t pgp; |
| 1085 | } cert; | 1158 | } cert; |
| 1086 | apr_time_t expiration_time, cur_time; | 1159 | apr_time_t expiration_time, cur_time; |
| 1087 | 1160 | ||
| 1088 | if (r == NULL || ctxt == NULL || ctxt->session == NULL) | 1161 | if (r == NULL || ctxt == NULL || ctxt->session == NULL) |
| 1089 | return HTTP_FORBIDDEN; | 1162 | return HTTP_FORBIDDEN; |
| 1090 | 1163 | ||
| 1091 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); | 1164 | _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); |
| 1092 | cert_list = | 1165 | cert_list = |
| 1093 | gnutls_certificate_get_peers(ctxt->session, &cert_list_size); | 1166 | gnutls_certificate_get_peers(ctxt->session, &cert_list_size); |
| 1094 | 1167 | ||
| 1095 | if (cert_list == NULL || cert_list_size == 0) { | 1168 | if (cert_list == NULL || cert_list_size == 0) { |
| 1096 | /* It is perfectly OK for a client not to send a certificate if on REQUEST mode | 1169 | /* It is perfectly OK for a client not to send a certificate if on REQUEST mode |
| 1170 | */ | ||
| 1171 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) | ||
| 1172 | return OK; | ||
| 1173 | |||
| 1174 | /* no certificate provided by the client, but one was required. */ | ||
| 1175 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1176 | "GnuTLS: Failed to Verify Peer: " | ||
| 1177 | "Client did not submit a certificate"); | ||
| 1178 | return HTTP_FORBIDDEN; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { | ||
| 1182 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
| 1183 | "GnuTLS: A Chain of %d certificate(s) was provided for validation", | ||
| 1184 | cert_list_size); | ||
| 1185 | |||
| 1186 | for (ch_size = 0; ch_size < cert_list_size; ch_size++) { | ||
| 1187 | gnutls_x509_crt_init(&cert.x509[ch_size]); | ||
| 1188 | rv = gnutls_x509_crt_import(cert.x509[ch_size], | ||
| 1189 | &cert_list[ch_size], | ||
| 1190 | GNUTLS_X509_FMT_DER); | ||
| 1191 | // When failure to import, leave the loop | ||
| 1192 | if (rv != GNUTLS_E_SUCCESS) { | ||
| 1193 | if (ch_size < 1) { | ||
| 1194 | ap_log_rerror(APLOG_MARK, | ||
| 1195 | APLOG_INFO, 0, r, | ||
| 1196 | "GnuTLS: Failed to Verify Peer: " | ||
| 1197 | "Failed to import peer certificates."); | ||
| 1198 | ret = HTTP_FORBIDDEN; | ||
| 1199 | goto exit; | ||
| 1200 | } | ||
| 1201 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1202 | "GnuTLS: Failed to import some peer certificates. Using %d certificates", | ||
| 1203 | ch_size); | ||
| 1204 | rv = GNUTLS_E_SUCCESS; | ||
| 1205 | break; | ||
| 1206 | } | ||
| 1207 | } | ||
| 1208 | } else if (gnutls_certificate_type_get(ctxt->session) == | ||
| 1209 | GNUTLS_CRT_OPENPGP) { | ||
| 1210 | if (cert_list_size > 1) { | ||
| 1211 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1212 | "GnuTLS: Failed to Verify Peer: " | ||
| 1213 | "Chained Client Certificates are not supported."); | ||
| 1214 | return HTTP_FORBIDDEN; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | gnutls_openpgp_crt_init(&cert.pgp); | ||
| 1218 | rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], | ||
| 1219 | GNUTLS_OPENPGP_FMT_RAW); | ||
| 1220 | |||
| 1221 | } else | ||
| 1222 | return HTTP_FORBIDDEN; | ||
| 1223 | |||
| 1224 | if (rv < 0) { | ||
| 1225 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1226 | "GnuTLS: Failed to Verify Peer: " | ||
| 1227 | "Failed to import peer certificates."); | ||
| 1228 | ret = HTTP_FORBIDDEN; | ||
| 1229 | goto exit; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { | ||
| 1233 | apr_time_ansi_put(&expiration_time, | ||
| 1234 | gnutls_x509_crt_get_expiration_time | ||
| 1235 | (cert.x509[0])); | ||
| 1236 | |||
| 1237 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | ||
| 1238 | "GnuTLS: Verifying list of %d certificate(s)", | ||
| 1239 | ch_size); | ||
| 1240 | rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, | ||
| 1241 | ctxt->sc->ca_list, | ||
| 1242 | ctxt->sc->ca_list_size, | ||
| 1243 | NULL, 0, 0, &status); | ||
| 1244 | } else { | ||
| 1245 | apr_time_ansi_put(&expiration_time, | ||
| 1246 | gnutls_openpgp_crt_get_expiration_time | ||
| 1247 | (cert.pgp)); | ||
| 1248 | |||
| 1249 | rv = gnutls_openpgp_crt_verify_ring(cert.pgp, | ||
| 1250 | ctxt->sc->pgp_list, 0, | ||
| 1251 | &status); | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | if (rv < 0) { | ||
| 1255 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1256 | "GnuTLS: Failed to Verify Peer certificate: (%d) %s", | ||
| 1257 | rv, gnutls_strerror(rv)); | ||
| 1258 | if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) | ||
| 1259 | ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, | ||
| 1260 | "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); | ||
| 1261 | ret = HTTP_FORBIDDEN; | ||
| 1262 | goto exit; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | /* TODO: X509 CRL Verification. */ | ||
| 1266 | /* May add later if anyone needs it. | ||
| 1097 | */ | 1267 | */ |
| 1098 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) | 1268 | /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ |
| 1099 | return OK; | 1269 | |
| 1100 | 1270 | cur_time = apr_time_now(); | |
| 1101 | /* no certificate provided by the client, but one was required. */ | 1271 | |
| 1102 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1272 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { |
| 1103 | "GnuTLS: Failed to Verify Peer: " | 1273 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
| 1104 | "Client did not submit a certificate"); | 1274 | "GnuTLS: Could not find Signer for Peer Certificate"); |
| 1105 | return HTTP_FORBIDDEN; | 1275 | } |
| 1106 | } | 1276 | |
| 1107 | 1277 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) { | |
| 1108 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { | 1278 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
| 1109 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 1279 | "GnuTLS: Peer's Certificate signer is not a CA"); |
| 1110 | "GnuTLS: A Chain of %d certificate(s) was provided for validation", cert_list_size); | 1280 | } |
| 1111 | 1281 | ||
| 1112 | for (ch_size = 0; ch_size<cert_list_size; ch_size++) { | 1282 | if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { |
| 1113 | gnutls_x509_crt_init(&cert.x509[ch_size]); | 1283 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
| 1114 | rv = gnutls_x509_crt_import(cert.x509[ch_size], &cert_list[ch_size], GNUTLS_X509_FMT_DER); | 1284 | "GnuTLS: Peer's Certificate is using insecure algorithms"); |
| 1115 | // When failure to import, leave the loop | 1285 | } |
| 1116 | if ( rv != GNUTLS_E_SUCCESS ) { | 1286 | |
| 1117 | if (ch_size < 1) { | 1287 | if (status & GNUTLS_CERT_EXPIRED |
| 1118 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1288 | || status & GNUTLS_CERT_NOT_ACTIVATED) { |
| 1119 | "GnuTLS: Failed to Verify Peer: " | 1289 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
| 1120 | "Failed to import peer certificates."); | 1290 | "GnuTLS: Peer's Certificate signer is expired or not yet activated"); |
| 1121 | ret = HTTP_FORBIDDEN; | 1291 | } |
| 1122 | goto exit; | 1292 | |
| 1123 | } | 1293 | if (status & GNUTLS_CERT_INVALID) { |
| 1124 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1294 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
| 1125 | "GnuTLS: Failed to import some peer certificates. Using %d certificates", | 1295 | "GnuTLS: Peer Certificate is invalid."); |
| 1126 | ch_size); | 1296 | } else if (status & GNUTLS_CERT_REVOKED) { |
| 1127 | rv = GNUTLS_E_SUCCESS; | 1297 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, |
| 1128 | break; | 1298 | "GnuTLS: Peer Certificate is revoked."); |
| 1129 | } | 1299 | } |
| 1130 | } | 1300 | |
| 1131 | } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) { | 1301 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) |
| 1132 | if (cert_list_size > 1) { | 1302 | mgs_add_common_cert_vars(r, cert.x509[0], 1, |
| 1133 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1303 | ctxt-> |
| 1134 | "GnuTLS: Failed to Verify Peer: " | 1304 | sc->export_certificates_enabled); |
| 1135 | "Chained Client Certificates are not supported."); | 1305 | else if (gnutls_certificate_type_get(ctxt->session) == |
| 1136 | return HTTP_FORBIDDEN; | 1306 | GNUTLS_CRT_OPENPGP) |
| 1137 | } | 1307 | mgs_add_common_pgpcert_vars(r, cert.pgp, 1, |
| 1138 | 1308 | ctxt-> | |
| 1139 | gnutls_openpgp_crt_init(&cert.pgp); | 1309 | sc->export_certificates_enabled); |
| 1140 | rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); | 1310 | |
| 1141 | 1311 | { | |
| 1142 | } else return HTTP_FORBIDDEN; | 1312 | /* days remaining */ |
| 1143 | 1313 | unsigned long remain = | |
| 1144 | if (rv < 0) { | 1314 | (apr_time_sec(expiration_time) - |
| 1145 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1315 | apr_time_sec(cur_time)) / 86400; |
| 1146 | "GnuTLS: Failed to Verify Peer: " | 1316 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", |
| 1147 | "Failed to import peer certificates."); | 1317 | apr_psprintf(r->pool, "%lu", remain)); |
| 1148 | ret = HTTP_FORBIDDEN; | 1318 | } |
| 1149 | goto exit; | 1319 | |
| 1150 | } | 1320 | if (status == 0) { |
| 1151 | 1321 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", | |
| 1152 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { | 1322 | "SUCCESS"); |
| 1153 | apr_time_ansi_put(&expiration_time, | 1323 | ret = OK; |
| 1154 | gnutls_x509_crt_get_expiration_time(cert.x509[0])); | 1324 | } else { |
| 1155 | 1325 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", | |
| 1156 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 1326 | "FAILED"); |
| 1157 | "GnuTLS: Verifying list of %d certificate(s)", ch_size); | 1327 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) |
| 1158 | rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, | 1328 | ret = OK; |
| 1159 | ctxt->sc->ca_list, ctxt->sc->ca_list_size, | 1329 | else |
| 1160 | NULL, 0, 0, &status); | 1330 | ret = HTTP_FORBIDDEN; |
| 1161 | } else { | 1331 | } |
| 1162 | apr_time_ansi_put(&expiration_time, | 1332 | |
| 1163 | gnutls_openpgp_crt_get_expiration_time(cert.pgp)); | 1333 | exit: |
| 1164 | 1334 | if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { | |
| 1165 | rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, | 1335 | int i; |
| 1166 | 0, &status); | 1336 | for (i = 0; i < ch_size; i++) { |
| 1167 | } | 1337 | gnutls_x509_crt_deinit(cert.x509[i]); |
| 1168 | 1338 | } | |
| 1169 | if (rv < 0) { | 1339 | } else if (gnutls_certificate_type_get(ctxt->session) == |
| 1170 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 1340 | GNUTLS_CRT_OPENPGP) |
| 1171 | "GnuTLS: Failed to Verify Peer certificate: (%d) %s", | 1341 | gnutls_openpgp_crt_deinit(cert.pgp); |
| 1172 | rv, gnutls_strerror(rv)); | 1342 | return ret; |
| 1173 | if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) | ||
| 1174 | ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, | ||
| 1175 | "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); | ||
| 1176 | ret = HTTP_FORBIDDEN; | ||
| 1177 | goto exit; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | /* TODO: X509 CRL Verification. */ | ||
| 1181 | /* May add later if anyone needs it. | ||
| 1182 | */ | ||
| 1183 | /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ | ||
| 1184 | |||
| 1185 | cur_time = apr_time_now(); | ||
| 1186 | |||
| 1187 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { | ||
| 1188 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1189 | "GnuTLS: Could not find Signer for Peer Certificate"); | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) { | ||
| 1193 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1194 | "GnuTLS: Peer's Certificate signer is not a CA"); | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { | ||
| 1198 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1199 | "GnuTLS: Peer's Certificate is using insecure algorithms"); | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | if (status & GNUTLS_CERT_EXPIRED || status & GNUTLS_CERT_NOT_ACTIVATED) { | ||
| 1203 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1204 | "GnuTLS: Peer's Certificate signer is expired or not yet activated"); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | if (status & GNUTLS_CERT_INVALID) { | ||
| 1208 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1209 | "GnuTLS: Peer Certificate is invalid."); | ||
| 1210 | } else if (status & GNUTLS_CERT_REVOKED) { | ||
| 1211 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
| 1212 | "GnuTLS: Peer Certificate is revoked."); | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) | ||
| 1216 | mgs_add_common_cert_vars(r, cert.x509[0], 1, | ||
| 1217 | ctxt->sc->export_certificates_enabled); | ||
| 1218 | else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | ||
| 1219 | mgs_add_common_pgpcert_vars(r, cert.pgp, 1, | ||
| 1220 | ctxt->sc->export_certificates_enabled); | ||
| 1221 | |||
| 1222 | { | ||
| 1223 | /* days remaining */ | ||
| 1224 | unsigned long remain = | ||
| 1225 | (apr_time_sec(expiration_time) - | ||
| 1226 | apr_time_sec(cur_time)) / 86400; | ||
| 1227 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", | ||
| 1228 | apr_psprintf(r->pool, "%lu", remain)); | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | if (status == 0) { | ||
| 1232 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "SUCCESS"); | ||
| 1233 | ret = OK; | ||
| 1234 | } else { | ||
| 1235 | apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "FAILED"); | ||
| 1236 | if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) | ||
| 1237 | ret = OK; | ||
| 1238 | else | ||
| 1239 | ret = HTTP_FORBIDDEN; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | exit: | ||
| 1243 | if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { | ||
| 1244 | int i; | ||
| 1245 | for (i=0; i<ch_size; i++) { | ||
| 1246 | gnutls_x509_crt_deinit(cert.x509[i]); | ||
| 1247 | } | ||
| 1248 | } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) | ||
| 1249 | gnutls_openpgp_crt_deinit(cert.pgp); | ||
| 1250 | return ret; | ||
| 1251 | 1343 | ||
| 1252 | 1344 | ||
| 1253 | } | 1345 | } |
diff --git a/src/gnutls_io.c b/src/gnutls_io.c index 174a424..37b73e7 100644 --- a/src/gnutls_io.c +++ b/src/gnutls_io.c | |||
| @@ -32,67 +32,64 @@ | |||
| 32 | alloc) | 32 | alloc) |
| 33 | 33 | ||
| 34 | static apr_status_t gnutls_io_filter_error(ap_filter_t * f, | 34 | static apr_status_t gnutls_io_filter_error(ap_filter_t * f, |
| 35 | apr_bucket_brigade * bb, | 35 | apr_bucket_brigade * bb, |
| 36 | apr_status_t status) | 36 | apr_status_t status) |
| 37 | { | 37 | { |
| 38 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; | 38 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
| 39 | apr_bucket *bucket; | 39 | apr_bucket *bucket; |
| 40 | 40 | ||
| 41 | switch (status) { | 41 | switch (status) { |
| 42 | case HTTP_BAD_REQUEST: | 42 | case HTTP_BAD_REQUEST: |
| 43 | /* log the situation */ | 43 | /* log the situation */ |
| 44 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, | 44 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
| 45 | f->c->base_server, | 45 | f->c->base_server, |
| 46 | "GnuTLS handshake failed: HTTP spoken on HTTPS port; " | 46 | "GnuTLS handshake failed: HTTP spoken on HTTPS port; " |
| 47 | "trying to send HTML error page"); | 47 | "trying to send HTML error page"); |
| 48 | 48 | ||
| 49 | ctxt->status = -1; | 49 | ctxt->status = -1; |
| 50 | 50 | ||
| 51 | /* fake the request line */ | 51 | /* fake the request line */ |
| 52 | bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); | 52 | bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); |
| 53 | break; | 53 | break; |
| 54 | 54 | ||
| 55 | default: | 55 | default: |
| 56 | return status; | 56 | return status; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 59 | APR_BRIGADE_INSERT_TAIL(bb, bucket); |
| 60 | bucket = apr_bucket_eos_create(f->c->bucket_alloc); | 60 | bucket = apr_bucket_eos_create(f->c->bucket_alloc); |
| 61 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 61 | APR_BRIGADE_INSERT_TAIL(bb, bucket); |
| 62 | 62 | ||
| 63 | return APR_SUCCESS; | 63 | return APR_SUCCESS; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, | 66 | static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, int inl) |
| 67 | int inl) | ||
| 68 | { | 67 | { |
| 69 | if (!buffer->length) { | 68 | if (!buffer->length) { |
| 70 | return 0; | 69 | return 0; |
| 71 | } | 70 | } |
| 72 | 71 | ||
| 73 | if (buffer->length > inl) { | 72 | if (buffer->length > inl) { |
| 74 | /* we have have enough to fill the caller's buffer */ | 73 | /* we have have enough to fill the caller's buffer */ |
| 75 | memmove(in, buffer->value, inl); | 74 | memmove(in, buffer->value, inl); |
| 76 | buffer->value += inl; | 75 | buffer->value += inl; |
| 77 | buffer->length -= inl; | 76 | buffer->length -= inl; |
| 78 | } | 77 | } else { |
| 79 | else { | 78 | /* swallow remainder of the buffer */ |
| 80 | /* swallow remainder of the buffer */ | 79 | memmove(in, buffer->value, buffer->length); |
| 81 | memmove(in, buffer->value, buffer->length); | 80 | inl = buffer->length; |
| 82 | inl = buffer->length; | 81 | buffer->value = NULL; |
| 83 | buffer->value = NULL; | 82 | buffer->length = 0; |
| 84 | buffer->length = 0; | 83 | } |
| 85 | } | 84 | |
| 86 | 85 | return inl; | |
| 87 | return inl; | ||
| 88 | } | 86 | } |
| 89 | 87 | ||
| 90 | static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, | 88 | static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, int inl) |
| 91 | int inl) | ||
| 92 | { | 89 | { |
| 93 | buffer->value = in; | 90 | buffer->value = in; |
| 94 | buffer->length = inl; | 91 | buffer->length = inl; |
| 95 | return inl; | 92 | return inl; |
| 96 | } | 93 | } |
| 97 | 94 | ||
| 98 | /** | 95 | /** |
| @@ -101,679 +98,715 @@ static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, | |||
| 101 | * proceeds. It will read at most *len bytes. | 98 | * proceeds. It will read at most *len bytes. |
| 102 | */ | 99 | */ |
| 103 | static apr_status_t brigade_consume(apr_bucket_brigade * bb, | 100 | static apr_status_t brigade_consume(apr_bucket_brigade * bb, |
| 104 | apr_read_type_e block, | 101 | apr_read_type_e block, |
| 105 | char *c, apr_size_t * len) | 102 | char *c, apr_size_t * len) |
| 106 | { | 103 | { |
| 107 | apr_size_t actual = 0; | 104 | apr_size_t actual = 0; |
| 108 | apr_status_t status = APR_SUCCESS; | 105 | apr_status_t status = APR_SUCCESS; |
| 109 | 106 | ||
| 110 | while (!APR_BRIGADE_EMPTY(bb)) { | 107 | while (!APR_BRIGADE_EMPTY(bb)) { |
| 111 | apr_bucket *b = APR_BRIGADE_FIRST(bb); | 108 | apr_bucket *b = APR_BRIGADE_FIRST(bb); |
| 112 | const char *str; | 109 | const char *str; |
| 113 | apr_size_t str_len; | 110 | apr_size_t str_len; |
| 114 | apr_size_t consume; | 111 | apr_size_t consume; |
| 115 | 112 | ||
| 116 | /* Justin points out this is an http-ism that might | 113 | /* Justin points out this is an http-ism that might |
| 117 | * not fit if brigade_consume is added to APR. Perhaps | 114 | * not fit if brigade_consume is added to APR. Perhaps |
| 118 | * apr_bucket_read(eos_bucket) should return APR_EOF? | 115 | * apr_bucket_read(eos_bucket) should return APR_EOF? |
| 119 | * Then this becomes mainline instead of a one-off. | 116 | * Then this becomes mainline instead of a one-off. |
| 120 | */ | 117 | */ |
| 121 | if (APR_BUCKET_IS_EOS(b)) { | 118 | if (APR_BUCKET_IS_EOS(b)) { |
| 122 | status = APR_EOF; | 119 | status = APR_EOF; |
| 123 | break; | 120 | break; |
| 124 | } | 121 | } |
| 125 | 122 | ||
| 126 | /* The reason I'm not offering brigade_consume yet | 123 | /* The reason I'm not offering brigade_consume yet |
| 127 | * across to apr-util is that the following call | 124 | * across to apr-util is that the following call |
| 128 | * illustrates how borked that API really is. For | 125 | * illustrates how borked that API really is. For |
| 129 | * this sort of case (caller provided buffer) it | 126 | * this sort of case (caller provided buffer) it |
| 130 | * would be much more trivial for apr_bucket_consume | 127 | * would be much more trivial for apr_bucket_consume |
| 131 | * to do all the work that follows, based on the | 128 | * to do all the work that follows, based on the |
| 132 | * particular characteristics of the bucket we are | 129 | * particular characteristics of the bucket we are |
| 133 | * consuming here. | 130 | * consuming here. |
| 134 | */ | 131 | */ |
| 135 | status = apr_bucket_read(b, &str, &str_len, block); | 132 | status = apr_bucket_read(b, &str, &str_len, block); |
| 136 | 133 | ||
| 137 | if (status != APR_SUCCESS) { | 134 | if (status != APR_SUCCESS) { |
| 138 | if (APR_STATUS_IS_EOF(status)) { | 135 | if (APR_STATUS_IS_EOF(status)) { |
| 139 | /* This stream bucket was consumed */ | 136 | /* This stream bucket was consumed */ |
| 140 | apr_bucket_delete(b); | 137 | apr_bucket_delete(b); |
| 141 | continue; | 138 | continue; |
| 142 | } | 139 | } |
| 143 | break; | 140 | break; |
| 144 | } | 141 | } |
| 145 | 142 | ||
| 146 | if (str_len > 0) { | 143 | if (str_len > 0) { |
| 147 | /* Do not block once some data has been consumed */ | 144 | /* Do not block once some data has been consumed */ |
| 148 | block = APR_NONBLOCK_READ; | 145 | block = APR_NONBLOCK_READ; |
| 149 | 146 | ||
| 150 | /* Assure we don't overflow. */ | 147 | /* Assure we don't overflow. */ |
| 151 | consume = (str_len + actual > *len) ? *len - actual : str_len; | 148 | consume = |
| 152 | 149 | (str_len + actual > | |
| 153 | memcpy(c, str, consume); | 150 | *len) ? *len - actual : str_len; |
| 154 | 151 | ||
| 155 | c += consume; | 152 | memcpy(c, str, consume); |
| 156 | actual += consume; | 153 | |
| 157 | 154 | c += consume; | |
| 158 | if (consume >= b->length) { | 155 | actual += consume; |
| 159 | /* This physical bucket was consumed */ | 156 | |
| 160 | apr_bucket_delete(b); | 157 | if (consume >= b->length) { |
| 161 | } | 158 | /* This physical bucket was consumed */ |
| 162 | else { | 159 | apr_bucket_delete(b); |
| 163 | /* Only part of this physical bucket was consumed */ | 160 | } else { |
| 164 | b->start += consume; | 161 | /* Only part of this physical bucket was consumed */ |
| 165 | b->length -= consume; | 162 | b->start += consume; |
| 166 | } | 163 | b->length -= consume; |
| 167 | } | 164 | } |
| 168 | else if (b->length == 0) { | 165 | } else if (b->length == 0) { |
| 169 | apr_bucket_delete(b); | 166 | apr_bucket_delete(b); |
| 170 | } | 167 | } |
| 171 | 168 | ||
| 172 | /* This could probably be actual == *len, but be safe from stray | 169 | /* This could probably be actual == *len, but be safe from stray |
| 173 | * photons. */ | 170 | * photons. */ |
| 174 | if (actual >= *len) { | 171 | if (actual >= *len) { |
| 175 | break; | 172 | break; |
| 176 | } | 173 | } |
| 177 | } | 174 | } |
| 178 | 175 | ||
| 179 | *len = actual; | 176 | *len = actual; |
| 180 | return status; | 177 | return status; |
| 181 | } | 178 | } |
| 182 | 179 | ||
| 183 | 180 | ||
| 184 | static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, | 181 | static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, |
| 185 | char *buf, apr_size_t * len) | 182 | char *buf, apr_size_t * len) |
| 186 | { | 183 | { |
| 187 | apr_size_t wanted = *len; | 184 | apr_size_t wanted = *len; |
| 188 | apr_size_t bytes = 0; | 185 | apr_size_t bytes = 0; |
| 189 | int rc; | 186 | int rc; |
| 190 | 187 | ||
| 191 | *len = 0; | 188 | *len = 0; |
| 192 | 189 | ||
| 193 | /* If we have something leftover from last time, try that first. */ | 190 | /* If we have something leftover from last time, try that first. */ |
| 194 | if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) { | 191 | if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) { |
| 195 | *len = bytes; | 192 | *len = bytes; |
| 196 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { | 193 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { |
| 197 | /* We want to rollback this read. */ | 194 | /* We want to rollback this read. */ |
| 198 | if (ctxt->input_cbuf.length > 0) { | 195 | if (ctxt->input_cbuf.length > 0) { |
| 199 | ctxt->input_cbuf.value -= bytes; | 196 | ctxt->input_cbuf.value -= bytes; |
| 200 | ctxt->input_cbuf.length += bytes; | 197 | ctxt->input_cbuf.length += bytes; |
| 201 | } | 198 | } else { |
| 202 | else { | 199 | char_buffer_write(&ctxt->input_cbuf, buf, |
| 203 | char_buffer_write(&ctxt->input_cbuf, buf, (int) bytes); | 200 | (int) bytes); |
| 204 | } | 201 | } |
| 205 | return APR_SUCCESS; | 202 | return APR_SUCCESS; |
| 206 | } | 203 | } |
| 207 | /* This could probably be *len == wanted, but be safe from stray | 204 | /* This could probably be *len == wanted, but be safe from stray |
| 208 | * photons. | 205 | * photons. |
| 209 | */ | 206 | */ |
| 210 | if (*len >= wanted) { | 207 | if (*len >= wanted) { |
| 211 | return APR_SUCCESS; | 208 | return APR_SUCCESS; |
| 212 | } | 209 | } |
| 213 | if (ctxt->input_mode == AP_MODE_GETLINE) { | 210 | if (ctxt->input_mode == AP_MODE_GETLINE) { |
| 214 | if (memchr(buf, APR_ASCII_LF, *len)) { | 211 | if (memchr(buf, APR_ASCII_LF, *len)) { |
| 215 | return APR_SUCCESS; | 212 | return APR_SUCCESS; |
| 216 | } | 213 | } |
| 217 | } | 214 | } else { |
| 218 | else { | 215 | /* Down to a nonblock pattern as we have some data already |
| 219 | /* Down to a nonblock pattern as we have some data already | 216 | */ |
| 220 | */ | 217 | ctxt->input_block = APR_NONBLOCK_READ; |
| 221 | ctxt->input_block = APR_NONBLOCK_READ; | 218 | } |
| 222 | } | 219 | } |
| 223 | } | 220 | |
| 224 | 221 | if (ctxt->session == NULL) { | |
| 225 | if (ctxt->session == NULL) { | 222 | return APR_EGENERAL; |
| 226 | return APR_EGENERAL; | 223 | } |
| 227 | } | 224 | |
| 228 | 225 | while (1) { | |
| 229 | while (1) { | 226 | |
| 230 | 227 | rc = gnutls_record_recv(ctxt->session, buf + bytes, | |
| 231 | rc = gnutls_record_recv(ctxt->session, buf + bytes, wanted - bytes); | 228 | wanted - bytes); |
| 232 | 229 | ||
| 233 | if (rc > 0) { | 230 | if (rc > 0) { |
| 234 | *len += rc; | 231 | *len += rc; |
| 235 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { | 232 | if (ctxt->input_mode == AP_MODE_SPECULATIVE) { |
| 236 | /* We want to rollback this read. */ | 233 | /* We want to rollback this read. */ |
| 237 | char_buffer_write(&ctxt->input_cbuf, buf, rc); | 234 | char_buffer_write(&ctxt->input_cbuf, buf, |
| 238 | } | 235 | rc); |
| 239 | return ctxt->input_rc; | 236 | } |
| 240 | } | 237 | return ctxt->input_rc; |
| 241 | else if (rc == 0) { | 238 | } else if (rc == 0) { |
| 242 | /* If EAGAIN, we will loop given a blocking read, | 239 | /* If EAGAIN, we will loop given a blocking read, |
| 243 | * otherwise consider ourselves at EOF. | 240 | * otherwise consider ourselves at EOF. |
| 244 | */ | 241 | */ |
| 245 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) | 242 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) |
| 246 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { | 243 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { |
| 247 | /* Already read something, return APR_SUCCESS instead. | 244 | /* Already read something, return APR_SUCCESS instead. |
| 248 | * On win32 in particular, but perhaps on other kernels, | 245 | * On win32 in particular, but perhaps on other kernels, |
| 249 | * a blocking call isn't 'always' blocking. | 246 | * a blocking call isn't 'always' blocking. |
| 250 | */ | 247 | */ |
| 251 | if (*len > 0) { | 248 | if (*len > 0) { |
| 252 | ctxt->input_rc = APR_SUCCESS; | 249 | ctxt->input_rc = APR_SUCCESS; |
| 253 | break; | 250 | break; |
| 254 | } | 251 | } |
| 255 | if (ctxt->input_block == APR_NONBLOCK_READ) { | 252 | if (ctxt->input_block == APR_NONBLOCK_READ) { |
| 256 | break; | 253 | break; |
| 257 | } | 254 | } |
| 258 | } | 255 | } else { |
| 259 | else { | 256 | if (*len > 0) { |
| 260 | if (*len > 0) { | 257 | ctxt->input_rc = APR_SUCCESS; |
| 261 | ctxt->input_rc = APR_SUCCESS; | 258 | } else { |
| 262 | } | 259 | ctxt->input_rc = APR_EOF; |
| 263 | else { | 260 | } |
| 264 | ctxt->input_rc = APR_EOF; | 261 | break; |
| 265 | } | 262 | } |
| 266 | break; | 263 | } else { /* (rc < 0) */ |
| 267 | } | 264 | |
| 268 | } | 265 | if (rc == GNUTLS_E_REHANDSHAKE) { |
| 269 | else { /* (rc < 0) */ | 266 | /* A client has asked for a new Hankshake. Currently, we don't do it */ |
| 270 | 267 | ap_log_error(APLOG_MARK, APLOG_INFO, | |
| 271 | if (rc == GNUTLS_E_REHANDSHAKE) { | 268 | ctxt->input_rc, |
| 272 | /* A client has asked for a new Hankshake. Currently, we don't do it */ | 269 | ctxt->c->base_server, |
| 273 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 270 | "GnuTLS: Error reading data. Client Requested a New Handshake." |
| 274 | ctxt->c->base_server, | 271 | " (%d) '%s'", rc, |
| 275 | "GnuTLS: Error reading data. Client Requested a New Handshake." | 272 | gnutls_strerror(rc)); |
| 276 | " (%d) '%s'", rc, gnutls_strerror(rc)); | 273 | } else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { |
| 277 | } | 274 | rc = gnutls_alert_get(ctxt->session); |
| 278 | else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { | 275 | ap_log_error(APLOG_MARK, APLOG_INFO, |
| 279 | rc = gnutls_alert_get(ctxt->session); | 276 | ctxt->input_rc, |
| 280 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 277 | ctxt->c->base_server, |
| 281 | ctxt->c->base_server, | 278 | "GnuTLS: Warning Alert From Client: " |
| 282 | "GnuTLS: Warning Alert From Client: " | 279 | " (%d) '%s'", rc, |
| 283 | " (%d) '%s'", rc, gnutls_alert_get_name(rc)); | 280 | gnutls_alert_get_name(rc)); |
| 284 | } | 281 | } else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { |
| 285 | else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { | 282 | rc = gnutls_alert_get(ctxt->session); |
| 286 | rc = gnutls_alert_get(ctxt->session); | 283 | ap_log_error(APLOG_MARK, APLOG_INFO, |
| 287 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 284 | ctxt->input_rc, |
| 288 | ctxt->c->base_server, | 285 | ctxt->c->base_server, |
| 289 | "GnuTLS: Fatal Alert From Client: " | 286 | "GnuTLS: Fatal Alert From Client: " |
| 290 | "(%d) '%s'", rc, gnutls_alert_get_name(rc)); | 287 | "(%d) '%s'", rc, |
| 291 | ctxt->input_rc = APR_EGENERAL; | 288 | gnutls_alert_get_name(rc)); |
| 292 | break; | 289 | ctxt->input_rc = APR_EGENERAL; |
| 293 | } | 290 | break; |
| 294 | else { | 291 | } else { |
| 295 | /* Some Other Error. Report it. Die. */ | 292 | /* Some Other Error. Report it. Die. */ |
| 296 | if(gnutls_error_is_fatal(rc)) { | 293 | if (gnutls_error_is_fatal(rc)) { |
| 297 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, | 294 | ap_log_error(APLOG_MARK, |
| 298 | ctxt->c->base_server, | 295 | APLOG_INFO, |
| 299 | "GnuTLS: Error reading data. (%d) '%s'", rc, | 296 | ctxt->input_rc, |
| 300 | gnutls_strerror(rc)); | 297 | ctxt->c->base_server, |
| 301 | } | 298 | "GnuTLS: Error reading data. (%d) '%s'", |
| 302 | else if(*len > 0) { | 299 | rc, |
| 303 | ctxt->input_rc = APR_SUCCESS; | 300 | gnutls_strerror(rc)); |
| 304 | break; | 301 | } else if (*len > 0) { |
| 305 | } | 302 | ctxt->input_rc = APR_SUCCESS; |
| 306 | } | 303 | break; |
| 307 | 304 | } | |
| 308 | if (ctxt->input_rc == APR_SUCCESS) { | 305 | } |
| 309 | ctxt->input_rc = APR_EGENERAL; | 306 | |
| 310 | } | 307 | if (ctxt->input_rc == APR_SUCCESS) { |
| 311 | break; | 308 | ctxt->input_rc = APR_EGENERAL; |
| 312 | } | 309 | } |
| 313 | } | 310 | break; |
| 314 | return ctxt->input_rc; | 311 | } |
| 312 | } | ||
| 313 | return ctxt->input_rc; | ||
| 315 | } | 314 | } |
| 316 | 315 | ||
| 317 | static apr_status_t gnutls_io_input_getline(mgs_handle_t * ctxt, | 316 | static apr_status_t gnutls_io_input_getline(mgs_handle_t * ctxt, |
| 318 | char *buf, apr_size_t * len) | 317 | char *buf, apr_size_t * len) |
| 319 | { | 318 | { |
| 320 | const char *pos = NULL; | 319 | const char *pos = NULL; |
| 321 | apr_status_t status; | 320 | apr_status_t status; |
| 322 | apr_size_t tmplen = *len, buflen = *len, offset = 0; | 321 | apr_size_t tmplen = *len, buflen = *len, offset = 0; |
| 323 | 322 | ||
| 324 | *len = 0; | 323 | *len = 0; |
| 325 | 324 | ||
| 326 | while (tmplen > 0) { | 325 | while (tmplen > 0) { |
| 327 | status = gnutls_io_input_read(ctxt, buf + offset, &tmplen); | 326 | status = gnutls_io_input_read(ctxt, buf + offset, &tmplen); |
| 328 | 327 | ||
| 329 | if (status != APR_SUCCESS) { | 328 | if (status != APR_SUCCESS) { |
| 330 | return status; | 329 | return status; |
| 331 | } | 330 | } |
| 332 | 331 | ||
| 333 | *len += tmplen; | 332 | *len += tmplen; |
| 334 | 333 | ||
| 335 | if ((pos = memchr(buf, APR_ASCII_LF, *len))) { | 334 | if ((pos = memchr(buf, APR_ASCII_LF, *len))) { |
| 336 | break; | 335 | break; |
| 337 | } | 336 | } |
| 338 | 337 | ||
| 339 | offset += tmplen; | 338 | offset += tmplen; |
| 340 | tmplen = buflen - offset; | 339 | tmplen = buflen - offset; |
| 341 | } | 340 | } |
| 342 | 341 | ||
| 343 | if (pos) { | 342 | if (pos) { |
| 344 | char *value; | 343 | char *value; |
| 345 | int length; | 344 | int length; |
| 346 | apr_size_t bytes = pos - buf; | 345 | apr_size_t bytes = pos - buf; |
| 347 | 346 | ||
| 348 | bytes += 1; | 347 | bytes += 1; |
| 349 | value = buf + bytes; | 348 | value = buf + bytes; |
| 350 | length = *len - bytes; | 349 | length = *len - bytes; |
| 351 | 350 | ||
| 352 | char_buffer_write(&ctxt->input_cbuf, value, length); | 351 | char_buffer_write(&ctxt->input_cbuf, value, length); |
| 353 | 352 | ||
| 354 | *len = bytes; | 353 | *len = bytes; |
| 355 | } | 354 | } |
| 356 | 355 | ||
| 357 | return APR_SUCCESS; | 356 | return APR_SUCCESS; |
| 358 | } | 357 | } |
| 359 | 358 | ||
| 360 | #define HANDSHAKE_MAX_TRIES 1024 | 359 | #define HANDSHAKE_MAX_TRIES 1024 |
| 361 | static int gnutls_do_handshake(mgs_handle_t * ctxt) | 360 | static int gnutls_do_handshake(mgs_handle_t * ctxt) |
| 362 | { | 361 | { |
| 363 | int ret; | 362 | int ret; |
| 364 | int errcode; | 363 | int errcode; |
| 365 | int maxtries = HANDSHAKE_MAX_TRIES; | 364 | int maxtries = HANDSHAKE_MAX_TRIES; |
| 366 | 365 | ||
| 367 | if (ctxt->status != 0 || ctxt->session == NULL) { | 366 | if (ctxt->status != 0 || ctxt->session == NULL) { |
| 368 | return -1; | 367 | return -1; |
| 369 | } | 368 | } |
| 370 | 369 | ||
| 371 | tryagain: | 370 | tryagain: |
| 372 | do { | 371 | do { |
| 373 | ret = gnutls_handshake(ctxt->session); | 372 | ret = gnutls_handshake(ctxt->session); |
| 374 | maxtries--; | 373 | maxtries--; |
| 375 | } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) && maxtries > 0); | 374 | } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) |
| 376 | 375 | && maxtries > 0); | |
| 377 | if (maxtries < 1) { | 376 | |
| 378 | ctxt->status = -1; | 377 | if (maxtries < 1) { |
| 378 | ctxt->status = -1; | ||
| 379 | #if USING_2_1_RECENT | 379 | #if USING_2_1_RECENT |
| 380 | ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, | 380 | ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, |
| 381 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); | 381 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); |
| 382 | #else | 382 | #else |
| 383 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, | 383 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, |
| 384 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); | 384 | ctxt->c->base_server, |
| 385 | "GnuTLS: Handshake Failed. Hit Maximum Attempts"); | ||
| 385 | #endif | 386 | #endif |
| 386 | if (ctxt->session) { | 387 | if (ctxt->session) { |
| 387 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, | 388 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, |
| 388 | gnutls_error_to_alert(GNUTLS_E_INTERNAL_ERROR, NULL)); | 389 | gnutls_error_to_alert |
| 389 | gnutls_deinit(ctxt->session); | 390 | (GNUTLS_E_INTERNAL_ERROR, NULL)); |
| 390 | } | 391 | gnutls_deinit(ctxt->session); |
| 391 | ctxt->session = NULL; | 392 | } |
| 392 | return -1; | 393 | ctxt->session = NULL; |
| 393 | } | 394 | return -1; |
| 394 | 395 | } | |
| 395 | if (ret < 0) { | 396 | |
| 396 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED | 397 | if (ret < 0) { |
| 397 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { | 398 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED |
| 398 | errcode = gnutls_alert_get(ctxt->session); | 399 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { |
| 399 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, | 400 | errcode = gnutls_alert_get(ctxt->session); |
| 400 | "GnuTLS: Hanshake Alert (%d) '%s'.", errcode, | 401 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
| 401 | gnutls_alert_get_name(errcode)); | 402 | ctxt->c->base_server, |
| 402 | } | 403 | "GnuTLS: Hanshake Alert (%d) '%s'.", |
| 403 | 404 | errcode, | |
| 404 | if (!gnutls_error_is_fatal(ret)) { | 405 | gnutls_alert_get_name(errcode)); |
| 405 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, | 406 | } |
| 406 | "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", ret, | 407 | |
| 407 | gnutls_strerror(ret)); | 408 | if (!gnutls_error_is_fatal(ret)) { |
| 408 | goto tryagain; | 409 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
| 409 | } | 410 | ctxt->c->base_server, |
| 411 | "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", | ||
| 412 | ret, gnutls_strerror(ret)); | ||
| 413 | goto tryagain; | ||
| 414 | } | ||
| 410 | #if USING_2_1_RECENT | 415 | #if USING_2_1_RECENT |
| 411 | ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, | 416 | ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, |
| 412 | "GnuTLS: Handshake Failed (%d) '%s'", ret, | 417 | "GnuTLS: Handshake Failed (%d) '%s'", ret, |
| 413 | gnutls_strerror(ret)); | 418 | gnutls_strerror(ret)); |
| 414 | #else | 419 | #else |
| 415 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, | 420 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
| 416 | "GnuTLS: Handshake Failed (%d) '%s'", ret, | 421 | ctxt->c->base_server, |
| 417 | gnutls_strerror(ret)); | 422 | "GnuTLS: Handshake Failed (%d) '%s'", ret, |
| 423 | gnutls_strerror(ret)); | ||
| 418 | #endif | 424 | #endif |
| 419 | ctxt->status = -1; | 425 | ctxt->status = -1; |
| 420 | if (ctxt->session) { | 426 | if (ctxt->session) { |
| 421 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, | 427 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, |
| 422 | gnutls_error_to_alert(ret, NULL)); | 428 | gnutls_error_to_alert(ret, |
| 423 | gnutls_deinit(ctxt->session); | 429 | NULL)); |
| 424 | } | 430 | gnutls_deinit(ctxt->session); |
| 425 | ctxt->session = NULL; | 431 | } |
| 426 | return ret; | 432 | ctxt->session = NULL; |
| 427 | } | 433 | return ret; |
| 428 | else { | 434 | } else { |
| 429 | /* all done with the handshake */ | 435 | /* all done with the handshake */ |
| 430 | ctxt->status = 1; | 436 | ctxt->status = 1; |
| 431 | /* If the session was resumed, we did not set the correct | 437 | /* If the session was resumed, we did not set the correct |
| 432 | * server_rec in ctxt->sc. Go Find it. (ick!) | 438 | * server_rec in ctxt->sc. Go Find it. (ick!) |
| 433 | */ | 439 | */ |
| 434 | if (gnutls_session_is_resumed(ctxt->session)) { | 440 | if (gnutls_session_is_resumed(ctxt->session)) { |
| 435 | mgs_srvconf_rec* sc; | 441 | mgs_srvconf_rec *sc; |
| 436 | sc = mgs_find_sni_server(ctxt->session); | 442 | sc = mgs_find_sni_server(ctxt->session); |
| 437 | if (sc) { | 443 | if (sc) { |
| 438 | ctxt->sc = sc; | 444 | ctxt->sc = sc; |
| 439 | } | 445 | } |
| 440 | } | 446 | } |
| 441 | return 0; | 447 | return 0; |
| 442 | } | 448 | } |
| 443 | } | 449 | } |
| 444 | 450 | ||
| 445 | int mgs_rehandshake(mgs_handle_t * ctxt) | 451 | int mgs_rehandshake(mgs_handle_t * ctxt) |
| 446 | { | 452 | { |
| 447 | int rv; | 453 | int rv; |
| 448 | 454 | ||
| 449 | if (ctxt->session == NULL) | 455 | if (ctxt->session == NULL) |
| 450 | return -1; | 456 | return -1; |
| 451 | 457 | ||
| 452 | rv = gnutls_rehandshake(ctxt->session); | 458 | rv = gnutls_rehandshake(ctxt->session); |
| 453 | 459 | ||
| 454 | if (rv != 0) { | 460 | if (rv != 0) { |
| 455 | /* the client did not want to rehandshake. goodbye */ | 461 | /* the client did not want to rehandshake. goodbye */ |
| 456 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ctxt->c->base_server, | 462 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, |
| 457 | "GnuTLS: Client Refused Rehandshake request."); | 463 | ctxt->c->base_server, |
| 458 | return -1; | 464 | "GnuTLS: Client Refused Rehandshake request."); |
| 459 | } | 465 | return -1; |
| 460 | 466 | } | |
| 461 | ctxt->status = 0; | 467 | |
| 462 | 468 | ctxt->status = 0; | |
| 463 | rv = gnutls_do_handshake(ctxt); | 469 | |
| 464 | 470 | rv = gnutls_do_handshake(ctxt); | |
| 465 | return rv; | 471 | |
| 472 | return rv; | ||
| 466 | } | 473 | } |
| 467 | 474 | ||
| 468 | 475 | ||
| 469 | apr_status_t mgs_filter_input(ap_filter_t* f, | 476 | apr_status_t mgs_filter_input(ap_filter_t * f, |
| 470 | apr_bucket_brigade * bb, | 477 | apr_bucket_brigade * bb, |
| 471 | ap_input_mode_t mode, | 478 | ap_input_mode_t mode, |
| 472 | apr_read_type_e block, | 479 | apr_read_type_e block, apr_off_t readbytes) |
| 473 | apr_off_t readbytes) | ||
| 474 | { | 480 | { |
| 475 | apr_status_t status = APR_SUCCESS; | 481 | apr_status_t status = APR_SUCCESS; |
| 476 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; | 482 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
| 477 | apr_size_t len = sizeof(ctxt->input_buffer); | 483 | apr_size_t len = sizeof(ctxt->input_buffer); |
| 478 | 484 | ||
| 479 | if (f->c->aborted) { | 485 | if (f->c->aborted) { |
| 480 | apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc); | 486 | apr_bucket *bucket = |
| 481 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 487 | apr_bucket_eos_create(f->c->bucket_alloc); |
| 482 | return APR_ECONNABORTED; | 488 | APR_BRIGADE_INSERT_TAIL(bb, bucket); |
| 483 | } | 489 | return APR_ECONNABORTED; |
| 484 | 490 | } | |
| 485 | if (ctxt->status == 0) { | 491 | |
| 486 | gnutls_do_handshake(ctxt); | 492 | if (ctxt->status == 0) { |
| 487 | } | 493 | gnutls_do_handshake(ctxt); |
| 488 | 494 | } | |
| 489 | if (ctxt->status < 0) { | 495 | |
| 490 | return ap_get_brigade(f->next, bb, mode, block, readbytes); | 496 | if (ctxt->status < 0) { |
| 491 | } | 497 | return ap_get_brigade(f->next, bb, mode, block, readbytes); |
| 492 | 498 | } | |
| 493 | /* XXX: we don't currently support anything other than these modes. */ | 499 | |
| 494 | if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE && | 500 | /* XXX: we don't currently support anything other than these modes. */ |
| 495 | mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) { | 501 | if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE && |
| 496 | return APR_ENOTIMPL; | 502 | mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) { |
| 497 | } | 503 | return APR_ENOTIMPL; |
| 498 | 504 | } | |
| 499 | ctxt->input_mode = mode; | 505 | |
| 500 | ctxt->input_block = block; | 506 | ctxt->input_mode = mode; |
| 501 | 507 | ctxt->input_block = block; | |
| 502 | if (ctxt->input_mode == AP_MODE_READBYTES || | 508 | |
| 503 | ctxt->input_mode == AP_MODE_SPECULATIVE) { | 509 | if (ctxt->input_mode == AP_MODE_READBYTES || |
| 504 | /* Err. This is bad. readbytes *can* be a 64bit int! len.. is NOT */ | 510 | ctxt->input_mode == AP_MODE_SPECULATIVE) { |
| 505 | if (readbytes < len) { | 511 | /* Err. This is bad. readbytes *can* be a 64bit int! len.. is NOT */ |
| 506 | len = (apr_size_t) readbytes; | 512 | if (readbytes < len) { |
| 507 | } | 513 | len = (apr_size_t) readbytes; |
| 508 | status = gnutls_io_input_read(ctxt, ctxt->input_buffer, &len); | 514 | } |
| 509 | } | 515 | status = |
| 510 | else if (ctxt->input_mode == AP_MODE_GETLINE) { | 516 | gnutls_io_input_read(ctxt, ctxt->input_buffer, &len); |
| 511 | status = gnutls_io_input_getline(ctxt, ctxt->input_buffer, &len); | 517 | } else if (ctxt->input_mode == AP_MODE_GETLINE) { |
| 512 | } | 518 | status = |
| 513 | else { | 519 | gnutls_io_input_getline(ctxt, ctxt->input_buffer, |
| 514 | /* We have no idea what you are talking about, so return an error. */ | 520 | &len); |
| 515 | return APR_ENOTIMPL; | 521 | } else { |
| 516 | } | 522 | /* We have no idea what you are talking about, so return an error. */ |
| 517 | 523 | return APR_ENOTIMPL; | |
| 518 | if (status != APR_SUCCESS) { | 524 | } |
| 519 | return gnutls_io_filter_error(f, bb, status); | 525 | |
| 520 | } | 526 | if (status != APR_SUCCESS) { |
| 521 | 527 | return gnutls_io_filter_error(f, bb, status); | |
| 522 | /* Create a transient bucket out of the decrypted data. */ | 528 | } |
| 523 | if (len > 0) { | 529 | |
| 524 | apr_bucket *bucket = | 530 | /* Create a transient bucket out of the decrypted data. */ |
| 525 | apr_bucket_transient_create(ctxt->input_buffer, len, | 531 | if (len > 0) { |
| 526 | f->c->bucket_alloc); | 532 | apr_bucket *bucket = |
| 527 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | 533 | apr_bucket_transient_create(ctxt->input_buffer, len, |
| 528 | } | 534 | f->c->bucket_alloc); |
| 529 | 535 | APR_BRIGADE_INSERT_TAIL(bb, bucket); | |
| 530 | return status; | 536 | } |
| 537 | |||
| 538 | return status; | ||
| 531 | } | 539 | } |
| 532 | 540 | ||
| 533 | apr_status_t mgs_filter_output(ap_filter_t * f, | 541 | apr_status_t mgs_filter_output(ap_filter_t * f, apr_bucket_brigade * bb) |
| 534 | apr_bucket_brigade * bb) | ||
| 535 | { | 542 | { |
| 536 | apr_size_t ret; | 543 | apr_size_t ret; |
| 537 | apr_bucket* e; | 544 | apr_bucket *e; |
| 538 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; | 545 | mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; |
| 539 | apr_status_t status = APR_SUCCESS; | 546 | apr_status_t status = APR_SUCCESS; |
| 540 | apr_read_type_e rblock = APR_NONBLOCK_READ; | 547 | apr_read_type_e rblock = APR_NONBLOCK_READ; |
| 541 | 548 | ||
| 542 | if (f->c->aborted) { | 549 | if (f->c->aborted) { |
| 543 | apr_brigade_cleanup(bb); | 550 | apr_brigade_cleanup(bb); |
| 544 | return APR_ECONNABORTED; | 551 | return APR_ECONNABORTED; |
| 545 | } | 552 | } |
| 546 | 553 | ||
| 547 | if (ctxt->status == 0) { | 554 | if (ctxt->status == 0) { |
| 548 | gnutls_do_handshake(ctxt); | 555 | gnutls_do_handshake(ctxt); |
| 549 | } | 556 | } |
| 550 | 557 | ||
| 551 | if (ctxt->status < 0) { | 558 | if (ctxt->status < 0) { |
| 552 | return ap_pass_brigade(f->next, bb); | 559 | return ap_pass_brigade(f->next, bb); |
| 553 | } | 560 | } |
| 554 | 561 | ||
| 555 | while (!APR_BRIGADE_EMPTY(bb)) { | 562 | while (!APR_BRIGADE_EMPTY(bb)) { |
| 556 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); | 563 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); |
| 557 | 564 | ||
| 558 | if (AP_BUCKET_IS_EOC(bucket)) { | 565 | if (AP_BUCKET_IS_EOC(bucket)) { |
| 559 | if (ctxt->session != NULL) { | 566 | if (ctxt->session != NULL) { |
| 560 | do { | 567 | do { |
| 561 | ret = gnutls_bye( ctxt->session, GNUTLS_SHUT_WR); | 568 | ret = |
| 562 | } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); | 569 | gnutls_bye(ctxt->session, |
| 563 | } | 570 | GNUTLS_SHUT_WR); |
| 564 | 571 | } while (ret == GNUTLS_E_INTERRUPTED | |
| 565 | apr_bucket_copy(bucket, &e); | 572 | || ret == GNUTLS_E_AGAIN); |
| 566 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | 573 | } |
| 567 | 574 | ||
| 568 | if ((status = ap_pass_brigade(f->next, ctxt->output_bb)) != APR_SUCCESS) { | 575 | apr_bucket_copy(bucket, &e); |
| 569 | apr_brigade_cleanup(ctxt->output_bb); | 576 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); |
| 570 | return status; | 577 | |
| 571 | } | 578 | if ((status = |
| 572 | 579 | ap_pass_brigade(f->next, | |
| 573 | apr_brigade_cleanup(ctxt->output_bb); | 580 | ctxt->output_bb)) != |
| 574 | if (ctxt->session) { | 581 | APR_SUCCESS) { |
| 575 | gnutls_deinit(ctxt->session); | 582 | apr_brigade_cleanup(ctxt->output_bb); |
| 576 | ctxt->session = NULL; | 583 | return status; |
| 577 | } | 584 | } |
| 578 | continue; | 585 | |
| 579 | } else if (APR_BUCKET_IS_FLUSH(bucket) || APR_BUCKET_IS_EOS(bucket)) { | 586 | apr_brigade_cleanup(ctxt->output_bb); |
| 580 | 587 | if (ctxt->session) { | |
| 581 | apr_bucket_copy(bucket, &e); | 588 | gnutls_deinit(ctxt->session); |
| 582 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | 589 | ctxt->session = NULL; |
| 583 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { | 590 | } |
| 584 | apr_brigade_cleanup(ctxt->output_bb); | 591 | continue; |
| 585 | return status; | 592 | } else if (APR_BUCKET_IS_FLUSH(bucket) |
| 586 | } | 593 | || APR_BUCKET_IS_EOS(bucket)) { |
| 587 | 594 | ||
| 588 | apr_brigade_cleanup(ctxt->output_bb); | 595 | apr_bucket_copy(bucket, &e); |
| 589 | continue; | 596 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); |
| 590 | } | 597 | if ((status = |
| 591 | else { | 598 | ap_pass_brigade(f->next, |
| 592 | /* filter output */ | 599 | bb)) != APR_SUCCESS) { |
| 593 | const char *data; | 600 | apr_brigade_cleanup(ctxt->output_bb); |
| 594 | apr_size_t len; | 601 | return status; |
| 595 | 602 | } | |
| 596 | status = apr_bucket_read(bucket, &data, &len, rblock); | 603 | |
| 597 | 604 | apr_brigade_cleanup(ctxt->output_bb); | |
| 598 | if (APR_STATUS_IS_EAGAIN(status)) { | 605 | continue; |
| 599 | rblock = APR_BLOCK_READ; | 606 | } else { |
| 600 | continue; /* and try again with a blocking read. */ | 607 | /* filter output */ |
| 601 | } | 608 | const char *data; |
| 602 | 609 | apr_size_t len; | |
| 603 | rblock = APR_NONBLOCK_READ; | 610 | |
| 604 | 611 | status = | |
| 605 | if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) { | 612 | apr_bucket_read(bucket, &data, &len, rblock); |
| 606 | break; | 613 | |
| 607 | } | 614 | if (APR_STATUS_IS_EAGAIN(status)) { |
| 608 | 615 | rblock = APR_BLOCK_READ; | |
| 609 | if (len > 0) { | 616 | continue; /* and try again with a blocking read. */ |
| 610 | 617 | } | |
| 611 | if (ctxt->session == NULL) { | 618 | |
| 612 | ret = GNUTLS_E_INVALID_REQUEST; | 619 | rblock = APR_NONBLOCK_READ; |
| 613 | } else { | 620 | |
| 614 | do { | 621 | if (!APR_STATUS_IS_EOF(status) |
| 615 | ret = gnutls_record_send(ctxt->session, data, len); | 622 | && (status != APR_SUCCESS)) { |
| 616 | } | 623 | break; |
| 617 | while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); | 624 | } |
| 618 | } | 625 | |
| 619 | 626 | if (len > 0) { | |
| 620 | if (ret < 0) { | 627 | |
| 621 | /* error sending output */ | 628 | if (ctxt->session == NULL) { |
| 622 | ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->output_rc, | 629 | ret = GNUTLS_E_INVALID_REQUEST; |
| 623 | ctxt->c->base_server, | 630 | } else { |
| 624 | "GnuTLS: Error writing data." | 631 | do { |
| 625 | " (%d) '%s'", (int)ret, gnutls_strerror(ret)); | 632 | ret = |
| 626 | if (ctxt->output_rc == APR_SUCCESS) { | 633 | gnutls_record_send |
| 627 | ctxt->output_rc = APR_EGENERAL; | 634 | (ctxt->session, data, |
| 628 | } | 635 | len); |
| 629 | } | 636 | } |
| 630 | else if (ret != len) { | 637 | while (ret == GNUTLS_E_INTERRUPTED |
| 631 | /* Not able to send the entire bucket, | 638 | || ret == GNUTLS_E_AGAIN); |
| 632 | split it and send it again. */ | 639 | } |
| 633 | apr_bucket_split(bucket, ret); | 640 | |
| 634 | } | 641 | if (ret < 0) { |
| 635 | } | 642 | /* error sending output */ |
| 636 | 643 | ap_log_error(APLOG_MARK, | |
| 637 | apr_bucket_delete(bucket); | 644 | APLOG_INFO, |
| 638 | 645 | ctxt->output_rc, | |
| 639 | if (ctxt->output_rc != APR_SUCCESS) { | 646 | ctxt->c->base_server, |
| 640 | break; | 647 | "GnuTLS: Error writing data." |
| 641 | } | 648 | " (%d) '%s'", |
| 642 | } | 649 | (int) ret, |
| 643 | } | 650 | gnutls_strerror(ret)); |
| 644 | 651 | if (ctxt->output_rc == APR_SUCCESS) { | |
| 645 | return status; | 652 | ctxt->output_rc = |
| 653 | APR_EGENERAL; | ||
| 654 | } | ||
| 655 | } else if (ret != len) { | ||
| 656 | /* Not able to send the entire bucket, | ||
| 657 | split it and send it again. */ | ||
| 658 | apr_bucket_split(bucket, ret); | ||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | apr_bucket_delete(bucket); | ||
| 663 | |||
| 664 | if (ctxt->output_rc != APR_SUCCESS) { | ||
| 665 | break; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | return status; | ||
| 646 | } | 671 | } |
| 647 | 672 | ||
| 648 | ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, | 673 | ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, |
| 649 | void *buffer, size_t len) | 674 | void *buffer, size_t len) |
| 650 | { | 675 | { |
| 651 | mgs_handle_t *ctxt = ptr; | 676 | mgs_handle_t *ctxt = ptr; |
| 652 | apr_status_t rc; | 677 | apr_status_t rc; |
| 653 | apr_size_t in = len; | 678 | apr_size_t in = len; |
| 654 | apr_read_type_e block = ctxt->input_block; | 679 | apr_read_type_e block = ctxt->input_block; |
| 655 | 680 | ||
| 656 | ctxt->input_rc = APR_SUCCESS; | 681 | ctxt->input_rc = APR_SUCCESS; |
| 657 | 682 | ||
| 658 | /* If Len = 0, we don't do anything. */ | 683 | /* If Len = 0, we don't do anything. */ |
| 659 | if (!len) | 684 | if (!len) |
| 660 | return 0; | 685 | return 0; |
| 661 | 686 | ||
| 662 | if (!ctxt->input_bb) { | 687 | if (!ctxt->input_bb) { |
| 663 | ctxt->input_rc = APR_EOF; | 688 | ctxt->input_rc = APR_EOF; |
| 664 | return -1; | 689 | return -1; |
| 665 | } | 690 | } |
| 666 | 691 | ||
| 667 | if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { | 692 | if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { |
| 668 | 693 | ||
| 669 | rc = ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb, | 694 | rc = ap_get_brigade(ctxt->input_filter->next, |
| 670 | AP_MODE_READBYTES, ctxt->input_block, in); | 695 | ctxt->input_bb, AP_MODE_READBYTES, |
| 671 | 696 | ctxt->input_block, in); | |
| 672 | /* Not a problem, there was simply no data ready yet. | 697 | |
| 673 | */ | 698 | /* Not a problem, there was simply no data ready yet. |
| 674 | if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) | 699 | */ |
| 675 | || (rc == APR_SUCCESS && APR_BRIGADE_EMPTY(ctxt->input_bb))) { | 700 | if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) |
| 676 | 701 | || (rc == APR_SUCCESS | |
| 677 | if (APR_STATUS_IS_EOF(ctxt->input_rc)) { | 702 | && APR_BRIGADE_EMPTY(ctxt->input_bb))) { |
| 678 | return 0; | 703 | |
| 679 | } else { | 704 | if (APR_STATUS_IS_EOF(ctxt->input_rc)) { |
| 680 | if (ctxt->session) | 705 | return 0; |
| 681 | gnutls_transport_set_errno(ctxt->session, EINTR); | 706 | } else { |
| 682 | return -1; | 707 | if (ctxt->session) |
| 683 | } | 708 | gnutls_transport_set_errno(ctxt-> |
| 684 | } | 709 | session, |
| 685 | 710 | EINTR); | |
| 686 | 711 | return -1; | |
| 687 | if (rc != APR_SUCCESS) { | 712 | } |
| 688 | /* Unexpected errors discard the brigade */ | 713 | } |
| 689 | apr_brigade_cleanup(ctxt->input_bb); | 714 | |
| 690 | ctxt->input_bb = NULL; | 715 | |
| 691 | return -1; | 716 | if (rc != APR_SUCCESS) { |
| 692 | } | 717 | /* Unexpected errors discard the brigade */ |
| 693 | } | 718 | apr_brigade_cleanup(ctxt->input_bb); |
| 694 | 719 | ctxt->input_bb = NULL; | |
| 695 | ctxt->input_rc = brigade_consume(ctxt->input_bb, block, buffer, &len); | 720 | return -1; |
| 696 | 721 | } | |
| 697 | if (ctxt->input_rc == APR_SUCCESS) { | 722 | } |
| 698 | return (ssize_t) len; | 723 | |
| 699 | } | 724 | ctxt->input_rc = |
| 700 | 725 | brigade_consume(ctxt->input_bb, block, buffer, &len); | |
| 701 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) | 726 | |
| 702 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { | 727 | if (ctxt->input_rc == APR_SUCCESS) { |
| 703 | if (len == 0) { | 728 | return (ssize_t) len; |
| 704 | if (ctxt->session) | 729 | } |
| 705 | gnutls_transport_set_errno(ctxt->session, EINTR); | 730 | |
| 706 | return -1; | 731 | if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) |
| 707 | } | 732 | || APR_STATUS_IS_EINTR(ctxt->input_rc)) { |
| 708 | 733 | if (len == 0) { | |
| 709 | return (ssize_t) len; | 734 | if (ctxt->session) |
| 710 | } | 735 | gnutls_transport_set_errno(ctxt->session, |
| 711 | 736 | EINTR); | |
| 712 | /* Unexpected errors and APR_EOF clean out the brigade. | 737 | return -1; |
| 713 | * Subsequent calls will return APR_EOF. | 738 | } |
| 714 | */ | 739 | |
| 715 | apr_brigade_cleanup(ctxt->input_bb); | 740 | return (ssize_t) len; |
| 716 | ctxt->input_bb = NULL; | 741 | } |
| 717 | 742 | ||
| 718 | if (APR_STATUS_IS_EOF(ctxt->input_rc) && len) { | 743 | /* Unexpected errors and APR_EOF clean out the brigade. |
| 719 | /* Provide the results of this read pass, | 744 | * Subsequent calls will return APR_EOF. |
| 720 | * without resetting the BIO retry_read flag | 745 | */ |
| 721 | */ | 746 | apr_brigade_cleanup(ctxt->input_bb); |
| 722 | return (ssize_t) len; | 747 | ctxt->input_bb = NULL; |
| 723 | } | 748 | |
| 724 | 749 | if (APR_STATUS_IS_EOF(ctxt->input_rc) && len) { | |
| 725 | return -1; | 750 | /* Provide the results of this read pass, |
| 751 | * without resetting the BIO retry_read flag | ||
| 752 | */ | ||
| 753 | return (ssize_t) len; | ||
| 754 | } | ||
| 755 | |||
| 756 | return -1; | ||
| 726 | } | 757 | } |
| 727 | 758 | ||
| 728 | 759 | ||
| 729 | static ssize_t write_flush(mgs_handle_t * ctxt) | 760 | static ssize_t write_flush(mgs_handle_t * ctxt) |
| 730 | { | 761 | { |
| 731 | apr_bucket *e; | 762 | apr_bucket *e; |
| 732 | 763 | ||
| 733 | if (!(ctxt->output_blen || ctxt->output_length)) { | 764 | if (!(ctxt->output_blen || ctxt->output_length)) { |
| 734 | ctxt->output_rc = APR_SUCCESS; | 765 | ctxt->output_rc = APR_SUCCESS; |
| 735 | return 1; | 766 | return 1; |
| 736 | } | 767 | } |
| 737 | 768 | ||
| 738 | if (ctxt->output_blen) { | 769 | if (ctxt->output_blen) { |
| 739 | e = apr_bucket_transient_create(ctxt->output_buffer, | 770 | e = apr_bucket_transient_create(ctxt->output_buffer, |
| 740 | ctxt->output_blen, | 771 | ctxt->output_blen, |
| 741 | ctxt->output_bb->bucket_alloc); | 772 | ctxt->output_bb-> |
| 742 | /* we filled this buffer first so add it to the | 773 | bucket_alloc); |
| 743 | * head of the brigade | 774 | /* we filled this buffer first so add it to the |
| 744 | */ | 775 | * head of the brigade |
| 745 | APR_BRIGADE_INSERT_HEAD(ctxt->output_bb, e); | 776 | */ |
| 746 | ctxt->output_blen = 0; | 777 | APR_BRIGADE_INSERT_HEAD(ctxt->output_bb, e); |
| 747 | } | 778 | ctxt->output_blen = 0; |
| 748 | 779 | } | |
| 749 | ctxt->output_length = 0; | 780 | |
| 750 | e = apr_bucket_flush_create(ctxt->output_bb->bucket_alloc); | 781 | ctxt->output_length = 0; |
| 751 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | 782 | e = apr_bucket_flush_create(ctxt->output_bb->bucket_alloc); |
| 752 | 783 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); | |
| 753 | ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, | 784 | |
| 754 | ctxt->output_bb); | 785 | ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, |
| 755 | /* clear the brigade to be ready for next time */ | 786 | ctxt->output_bb); |
| 756 | apr_brigade_cleanup(ctxt->output_bb); | 787 | /* clear the brigade to be ready for next time */ |
| 757 | 788 | apr_brigade_cleanup(ctxt->output_bb); | |
| 758 | return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; | 789 | |
| 790 | return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; | ||
| 759 | } | 791 | } |
| 760 | 792 | ||
| 761 | ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, | 793 | ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, |
| 762 | const void *buffer, size_t len) | 794 | const void *buffer, size_t len) |
| 763 | { | 795 | { |
| 764 | mgs_handle_t *ctxt = ptr; | 796 | mgs_handle_t *ctxt = ptr; |
| 765 | 797 | ||
| 766 | /* pass along the encrypted data | 798 | /* pass along the encrypted data |
| 767 | * need to flush since we're using SSL's malloc-ed buffer | 799 | * need to flush since we're using SSL's malloc-ed buffer |
| 768 | * which will be overwritten once we leave here | 800 | * which will be overwritten once we leave here |
| 769 | */ | 801 | */ |
| 770 | apr_bucket *bucket = apr_bucket_transient_create(buffer, len, | 802 | apr_bucket *bucket = apr_bucket_transient_create(buffer, len, |
| 771 | ctxt->output_bb->bucket_alloc); | 803 | ctxt->output_bb-> |
| 772 | ctxt->output_length += len; | 804 | bucket_alloc); |
| 773 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket); | 805 | ctxt->output_length += len; |
| 774 | 806 | APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket); | |
| 775 | if (write_flush(ctxt) < 0) { | 807 | |
| 776 | return -1; | 808 | if (write_flush(ctxt) < 0) { |
| 777 | } | 809 | return -1; |
| 778 | return len; | 810 | } |
| 811 | return len; | ||
| 779 | } | 812 | } |
diff --git a/src/gnutls_lua.c b/src/gnutls_lua.c index 6d80574..4401b61 100644 --- a/src/gnutls_lua.c +++ b/src/gnutls_lua.c | |||
| @@ -25,268 +25,285 @@ | |||
| 25 | 25 | ||
| 26 | static char *MGS_LUA_RRKEY = "request_rec"; | 26 | static char *MGS_LUA_RRKEY = "request_rec"; |
| 27 | 27 | ||
| 28 | static request_rec *mgs_lua_getrr(lua_State *lvm) | 28 | static request_rec *mgs_lua_getrr(lua_State * lvm) |
| 29 | { | 29 | { |
| 30 | request_rec *r; | 30 | request_rec *r; |
| 31 | 31 | ||
| 32 | /* Push the request_rec off the registry, onto the stack. */ | 32 | /* Push the request_rec off the registry, onto the stack. */ |
| 33 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); | 33 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); |
| 34 | lua_gettable(lvm, LUA_REGISTRYINDEX); | 34 | lua_gettable(lvm, LUA_REGISTRYINDEX); |
| 35 | r = lua_touserdata(lvm, -1); | 35 | r = lua_touserdata(lvm, -1); |
| 36 | lua_pop(lvm, 1); | 36 | lua_pop(lvm, 1); |
| 37 | return r; | 37 | return r; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | static int get_request_table(lua_State *lvm, long offset) | 40 | static int get_request_table(lua_State * lvm, long offset) |
| 41 | { | 41 | { |
| 42 | const char *key; | 42 | const char *key; |
| 43 | request_rec *r; | 43 | request_rec *r; |
| 44 | const char *value; | 44 | const char *value; |
| 45 | apr_table_t *t; | 45 | apr_table_t *t; |
| 46 | key = luaL_checkstring(lvm, 1); | 46 | key = luaL_checkstring(lvm, 1); |
| 47 | 47 | ||
| 48 | r = mgs_lua_getrr(lvm); | 48 | r = mgs_lua_getrr(lvm); |
| 49 | 49 | ||
| 50 | t = *(apr_table_t **)((char *)r + offset); | 50 | t = *(apr_table_t **) ((char *) r + offset); |
| 51 | 51 | ||
| 52 | value = apr_table_get(t, key); | 52 | value = apr_table_get(t, key); |
| 53 | 53 | ||
| 54 | if (value) { | 54 | if (value) { |
| 55 | lua_pushstring(lvm, value); | 55 | lua_pushstring(lvm, value); |
| 56 | return 1; | 56 | return 1; |
| 57 | } | 57 | } else { |
| 58 | else { | 58 | return 0; |
| 59 | return 0; | 59 | } |
| 60 | } | ||
| 61 | } | 60 | } |
| 62 | 61 | ||
| 63 | static int mgs_lua_getenv(lua_State *lvm) | 62 | static int mgs_lua_getenv(lua_State * lvm) |
| 64 | { | 63 | { |
| 65 | return get_request_table(lvm, APR_OFFSETOF(request_rec, subprocess_env)); | 64 | return get_request_table(lvm, |
| 65 | APR_OFFSETOF(request_rec, | ||
| 66 | subprocess_env)); | ||
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | static int mgs_lua_getheader(lua_State *lvm) | 69 | static int mgs_lua_getheader(lua_State * lvm) |
| 69 | { | 70 | { |
| 70 | return get_request_table(lvm, APR_OFFSETOF(request_rec, headers_in)); | 71 | return get_request_table(lvm, |
| 71 | } | 72 | APR_OFFSETOF(request_rec, headers_in)); |
| 73 | } | ||
| 72 | 74 | ||
| 73 | static const luaL_reg mgs_lua_reg[] = { | 75 | static const luaL_reg mgs_lua_reg[] = { |
| 74 | {"getenv", mgs_lua_getenv}, | 76 | {"getenv", mgs_lua_getenv}, |
| 75 | {"header", mgs_lua_getheader}, | 77 | {"header", mgs_lua_getheader}, |
| 76 | {NULL, NULL} | 78 | {NULL, NULL} |
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| 79 | lua_State* get_luastate() | 81 | lua_State *get_luastate() |
| 80 | { | 82 | { |
| 81 | lua_State* lvm = lua_open(); | 83 | lua_State *lvm = lua_open(); |
| 82 | luaopen_base(lvm); | 84 | luaopen_base(lvm); |
| 83 | luaopen_io(lvm); | 85 | luaopen_io(lvm); |
| 84 | luaopen_table(lvm); | 86 | luaopen_table(lvm); |
| 85 | luaopen_string(lvm); | 87 | luaopen_string(lvm); |
| 86 | luaopen_math(lvm); | 88 | luaopen_math(lvm); |
| 87 | luaopen_loadlib(lvm); | 89 | luaopen_loadlib(lvm); |
| 88 | luaL_openlib(lvm, "ap", mgs_lua_reg, 0); | 90 | luaL_openlib(lvm, "ap", mgs_lua_reg, 0); |
| 89 | 91 | ||
| 90 | return lvm; | 92 | return lvm; |
| 91 | } | 93 | } |
| 92 | 94 | ||
| 93 | int mgs_authz_lua(request_rec* r) | 95 | int mgs_authz_lua(request_rec * r) |
| 94 | { | 96 | { |
| 95 | int rv; | 97 | int rv; |
| 96 | lua_State* lvm; | 98 | lua_State *lvm; |
| 97 | mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, | 99 | mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, |
| 98 | &gnutls_module); | 100 | &gnutls_module); |
| 99 | 101 | ||
| 100 | if (dc->lua_bytecode_len <= 0) { | 102 | if (dc->lua_bytecode_len <= 0) { |
| 101 | return 0; | 103 | return 0; |
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | lvm = get_luastate(); | 106 | lvm = get_luastate(); |
| 105 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); | 107 | lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); |
| 106 | lua_pushlightuserdata(lvm, r); | 108 | lua_pushlightuserdata(lvm, r); |
| 107 | lua_settable(lvm, LUA_REGISTRYINDEX); | 109 | lua_settable(lvm, LUA_REGISTRYINDEX); |
| 108 | 110 | ||
| 109 | /* Push Bytecode onto the stack */ | 111 | /* Push Bytecode onto the stack */ |
| 110 | rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len, "gnutls-lua"); | 112 | rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len, |
| 111 | 113 | "gnutls-lua"); | |
| 112 | if (rv != 0) { | 114 | |
| 113 | /* Get the Error message */ | 115 | if (rv != 0) { |
| 114 | const char* error = lua_tostring(lvm, -1); | 116 | /* Get the Error message */ |
| 115 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 117 | const char *error = lua_tostring(lvm, -1); |
| 116 | "GnuTLS: Error Loading Lua Bytecode: %s", error); | 118 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
| 117 | lua_pop(lvm, 1); | 119 | "GnuTLS: Error Loading Lua Bytecode: %s", |
| 118 | return -1; | 120 | error); |
| 119 | } | 121 | lua_pop(lvm, 1); |
| 120 | 122 | return -1; | |
| 121 | rv = lua_pcall(lvm, 0, 1, 0); | 123 | } |
| 122 | if (rv != 0) { | 124 | |
| 123 | /* Get the Error message */ | 125 | rv = lua_pcall(lvm, 0, 1, 0); |
| 124 | const char* error = lua_tostring(lvm, -1); | 126 | if (rv != 0) { |
| 125 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 127 | /* Get the Error message */ |
| 126 | "GnuTLS: Error Running Lua: %s", error); | 128 | const char *error = lua_tostring(lvm, -1); |
| 127 | lua_pop(lvm, 1); | 129 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
| 128 | return -1; | 130 | "GnuTLS: Error Running Lua: %s", error); |
| 129 | } | 131 | lua_pop(lvm, 1); |
| 130 | 132 | return -1; | |
| 131 | rv = (int)lua_tonumber(lvm, -1); | 133 | } |
| 132 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, | 134 | |
| 133 | "GnuTLS: (%d) Lua Return: %d", | 135 | rv = (int) lua_tonumber(lvm, -1); |
| 134 | dc->lua_bytecode_len, rv); | 136 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
| 135 | lua_pop(lvm, 1); | 137 | "GnuTLS: (%d) Lua Return: %d", |
| 136 | lua_close(lvm); | 138 | dc->lua_bytecode_len, rv); |
| 137 | return rv; | 139 | lua_pop(lvm, 1); |
| 140 | lua_close(lvm); | ||
| 141 | return rv; | ||
| 138 | } | 142 | } |
| 139 | 143 | ||
| 140 | static apr_size_t config_getstr(ap_configfile_t *cfg, char *buf, size_t bufsiz) | 144 | static apr_size_t config_getstr(ap_configfile_t * cfg, char *buf, |
| 145 | size_t bufsiz) | ||
| 141 | { | 146 | { |
| 142 | apr_size_t i = 0; | 147 | apr_size_t i = 0; |
| 143 | 148 | ||
| 144 | if (cfg->getstr) { | 149 | if (cfg->getstr) { |
| 145 | const char *res = (cfg->getstr)(buf, bufsiz, cfg->param); | 150 | const char *res = (cfg->getstr) (buf, bufsiz, cfg->param); |
| 146 | if (res) { | 151 | if (res) { |
| 147 | i = strlen(buf); | 152 | i = strlen(buf); |
| 148 | if (i && buf[i - 1] == '\n') ++cfg->line_number; | 153 | if (i && buf[i - 1] == '\n') |
| 149 | } | 154 | ++cfg->line_number; |
| 150 | else { | 155 | } else { |
| 151 | buf[0] = '\0'; | 156 | buf[0] = '\0'; |
| 152 | i = 0; | 157 | i = 0; |
| 153 | } | 158 | } |
| 154 | } | 159 | } else { |
| 155 | else { | 160 | while (i < bufsiz) { |
| 156 | while (i < bufsiz) { | 161 | int ch = (cfg->getch) (cfg->param); |
| 157 | int ch = (cfg->getch)(cfg->param); | 162 | if (ch == EOF) |
| 158 | if (ch == EOF) break; | 163 | break; |
| 159 | buf[i++] = ch; | 164 | buf[i++] = ch; |
| 160 | if (ch == '\n') { | 165 | if (ch == '\n') { |
| 161 | ++cfg->line_number; | 166 | ++cfg->line_number; |
| 162 | break; | 167 | break; |
| 163 | } | 168 | } |
| 164 | } | 169 | } |
| 165 | } | 170 | } |
| 166 | return i; | 171 | return i; |
| 167 | } | 172 | } |
| 168 | 173 | ||
| 169 | struct cr_ctx { | 174 | struct cr_ctx { |
| 170 | ap_configfile_t *cfp; | 175 | ap_configfile_t *cfp; |
| 171 | size_t startline; | 176 | size_t startline; |
| 172 | char buf[HUGE_STRING_LEN]; | 177 | char buf[HUGE_STRING_LEN]; |
| 173 | }; | 178 | }; |
| 174 | 179 | ||
| 175 | static const char *LUACMD = "gnutlsrequire"; | 180 | static const char *LUACMD = "gnutlsrequire"; |
| 176 | static const char *lf = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; | 181 | static const char *lf = |
| 182 | "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; | ||
| 177 | #define N_LF 32 | 183 | #define N_LF 32 |
| 178 | 184 | ||
| 179 | static const char *direct_chunkreader(lua_State *lvm, void *udata, size_t *plen) | 185 | static const char *direct_chunkreader(lua_State * lvm, void *udata, |
| 186 | size_t * plen) | ||
| 180 | { | 187 | { |
| 181 | const char *p; | 188 | const char *p; |
| 182 | struct cr_ctx *ctx = udata; | 189 | struct cr_ctx *ctx = udata; |
| 183 | 190 | ||
| 184 | if (ctx->startline) { | 191 | if (ctx->startline) { |
| 185 | *plen = ctx->startline > N_LF ? N_LF : ctx->startline; | 192 | *plen = ctx->startline > N_LF ? N_LF : ctx->startline; |
| 186 | ctx->startline -= *plen; | 193 | ctx->startline -= *plen; |
| 187 | return lf; | 194 | return lf; |
| 188 | } | 195 | } |
| 189 | *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN); | 196 | *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN); |
| 190 | 197 | ||
| 191 | for (p = ctx->buf; isspace(*p); ++p); | 198 | for (p = ctx->buf; isspace(*p); ++p); |
| 192 | if (p[0] == '<' && p[1] == '/') { | 199 | if (p[0] == '<' && p[1] == '/') { |
| 193 | int i = 0; | 200 | int i = 0; |
| 194 | while (i < strlen(LUACMD)) { | 201 | while (i < strlen(LUACMD)) { |
| 195 | if (tolower(p[i + 2]) != LUACMD[i]) return ctx->buf; | 202 | if (tolower(p[i + 2]) != LUACMD[i]) |
| 196 | ++i; | 203 | return ctx->buf; |
| 197 | } | 204 | ++i; |
| 198 | *plen = 0; | 205 | } |
| 199 | return NULL; | 206 | *plen = 0; |
| 200 | } | 207 | return NULL; |
| 201 | return ctx->buf; | 208 | } |
| 209 | return ctx->buf; | ||
| 202 | } | 210 | } |
| 203 | 211 | ||
| 204 | static int ldump_writer (lua_State *L, const void* b, size_t size, void* B) { | 212 | static int ldump_writer(lua_State * L, const void *b, size_t size, void *B) |
| 205 | (void)L; | 213 | { |
| 206 | luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); | 214 | (void) L; |
| 207 | return 1; | 215 | luaL_addlstring((luaL_Buffer *) B, (const char *) b, size); |
| 216 | return 1; | ||
| 208 | } | 217 | } |
| 209 | 218 | ||
| 210 | /* a bytecode buffer*/ | 219 | /* a bytecode buffer*/ |
| 211 | typedef struct bcbuf_ctx { | 220 | typedef struct bcbuf_ctx { |
| 212 | apr_size_t buflen; | 221 | apr_size_t buflen; |
| 213 | char* buf; | 222 | char *buf; |
| 214 | } bcbuf_ctx; | 223 | } bcbuf_ctx; |
| 215 | 224 | ||
| 216 | const char *mgs_set_require_section(cmd_parms *cmd, void *mconfig, const char *arg) | 225 | const char *mgs_set_require_section(cmd_parms * cmd, void *mconfig, |
| 226 | const char *arg) | ||
| 217 | { | 227 | { |
| 218 | apr_size_t bytecode_len; | 228 | apr_size_t bytecode_len; |
| 219 | const char* bytecode; | 229 | const char *bytecode; |
| 220 | bcbuf_ctx* bcbuf; | 230 | bcbuf_ctx *bcbuf; |
| 221 | luaL_Buffer b; | 231 | luaL_Buffer b; |
| 222 | ap_directive_t **current = mconfig; | 232 | ap_directive_t **current = mconfig; |
| 223 | struct cr_ctx ctx[1]; | 233 | struct cr_ctx ctx[1]; |
| 224 | int result; | 234 | int result; |
| 225 | const char *filename = apr_psprintf(cmd->pool, "@%s", cmd->config_file->name); | 235 | const char *filename = |
| 226 | // get a word argument | 236 | apr_psprintf(cmd->pool, "@%s", cmd->config_file->name); |
| 227 | const char *word; | 237 | // get a word argument |
| 228 | apr_size_t wordlen; | 238 | const char *word; |
| 229 | lua_State *lvm = get_luastate(); | 239 | apr_size_t wordlen; |
| 230 | 240 | lua_State *lvm = get_luastate(); | |
| 231 | word = ap_getword_conf(cmd->pool, &arg); | 241 | |
| 232 | wordlen = strlen(word); | 242 | word = ap_getword_conf(cmd->pool, &arg); |
| 233 | do { | 243 | wordlen = strlen(word); |
| 234 | if (wordlen) { | 244 | do { |
| 235 | if (word[wordlen - 1] == '>') { | 245 | if (wordlen) { |
| 236 | --wordlen; | 246 | if (word[wordlen - 1] == '>') { |
| 237 | break; | 247 | --wordlen; |
| 238 | } | 248 | break; |
| 239 | if (*arg == '>') break; | 249 | } |
| 240 | } | 250 | if (*arg == '>') |
| 241 | return apr_pstrcat(cmd->pool, "<", LUACMD, "> takes exactly one argument", NULL); | 251 | break; |
| 242 | } while (0); | 252 | } |
| 243 | 253 | return apr_pstrcat(cmd->pool, "<", LUACMD, | |
| 244 | ctx->cfp = cmd->config_file; | 254 | "> takes exactly one argument", NULL); |
| 245 | ctx->startline = cmd->config_file->line_number; | 255 | } while (0); |
| 246 | lua_settop(lvm, 0); | 256 | |
| 247 | result = lua_load(lvm, direct_chunkreader, ctx, filename); | 257 | ctx->cfp = cmd->config_file; |
| 248 | 258 | ctx->startline = cmd->config_file->line_number; | |
| 249 | if (result != 0) { | 259 | lua_settop(lvm, 0); |
| 250 | word = apr_pstrcat(cmd->pool, "Lua Error:", lua_tostring(lvm, -1), NULL); | 260 | result = lua_load(lvm, direct_chunkreader, ctx, filename); |
| 251 | lua_close(lvm); | 261 | |
| 252 | return word; | 262 | if (result != 0) { |
| 253 | } | 263 | word = |
| 254 | else { | 264 | apr_pstrcat(cmd->pool, "Lua Error:", |
| 255 | luaL_buffinit(lvm, &b); | 265 | lua_tostring(lvm, -1), NULL); |
| 256 | lua_dump(lvm, ldump_writer, &b); | 266 | lua_close(lvm); |
| 257 | luaL_pushresult(&b); | 267 | return word; |
| 258 | bytecode = lua_tostring(lvm, -1); | 268 | } else { |
| 259 | bytecode_len = lua_strlen(lvm, -1); | 269 | luaL_buffinit(lvm, &b); |
| 260 | } | 270 | lua_dump(lvm, ldump_writer, &b); |
| 261 | 271 | luaL_pushresult(&b); | |
| 262 | /* Here, we have to replace our current config node for the next pass */ | 272 | bytecode = lua_tostring(lvm, -1); |
| 263 | if (!*current) { | 273 | bytecode_len = lua_strlen(lvm, -1); |
| 264 | *current = apr_pcalloc(cmd->pool, sizeof(**current)); | 274 | } |
| 265 | } | 275 | |
| 266 | 276 | /* Here, we have to replace our current config node for the next pass */ | |
| 267 | (*current)->filename = cmd->config_file->name; | 277 | if (!*current) { |
| 268 | (*current)->line_num = ctx->startline; | 278 | *current = apr_pcalloc(cmd->pool, sizeof(**current)); |
| 269 | (*current)->directive = apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode"); | 279 | } |
| 270 | (*current)->args = NULL; | 280 | |
| 271 | 281 | (*current)->filename = cmd->config_file->name; | |
| 272 | bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf)); | 282 | (*current)->line_num = ctx->startline; |
| 273 | bcbuf->buflen = bytecode_len; | 283 | (*current)->directive = |
| 274 | bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len); | 284 | apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode"); |
| 275 | 285 | (*current)->args = NULL; | |
| 276 | (*current)->data = bcbuf; | 286 | |
| 277 | lua_close(lvm); | 287 | bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf)); |
| 278 | return NULL; | 288 | bcbuf->buflen = bytecode_len; |
| 289 | bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len); | ||
| 290 | |||
| 291 | (*current)->data = bcbuf; | ||
| 292 | lua_close(lvm); | ||
| 293 | return NULL; | ||
| 279 | } | 294 | } |
| 280 | 295 | ||
| 281 | const char *mgs_set_require_bytecode(cmd_parms *cmd, void *mconfig, const char *arg) | 296 | const char *mgs_set_require_bytecode(cmd_parms * cmd, void *mconfig, |
| 297 | const char *arg) | ||
| 282 | { | 298 | { |
| 283 | bcbuf_ctx* bcbuf; | 299 | bcbuf_ctx *bcbuf; |
| 284 | ap_directive_t *directive = cmd->directive; | 300 | ap_directive_t *directive = cmd->directive; |
| 285 | mgs_dirconf_rec *dc = mconfig; | 301 | mgs_dirconf_rec *dc = mconfig; |
| 286 | 302 | ||
| 287 | bcbuf = directive->data; | 303 | bcbuf = directive->data; |
| 288 | dc->lua_bytecode_len = bcbuf->buflen; | 304 | dc->lua_bytecode_len = bcbuf->buflen; |
| 289 | dc->lua_bytecode = apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen); | 305 | dc->lua_bytecode = |
| 290 | 306 | apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen); | |
| 291 | return NULL; | 307 | |
| 308 | return NULL; | ||
| 292 | } | 309 | } |
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index c95d183..49f4e43 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c | |||
| @@ -19,143 +19,146 @@ | |||
| 19 | 19 | ||
| 20 | static void gnutls_hooks(apr_pool_t * p) | 20 | static void gnutls_hooks(apr_pool_t * p) |
| 21 | { | 21 | { |
| 22 | ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, | 22 | ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, |
| 23 | APR_HOOK_MIDDLE); | 23 | APR_HOOK_MIDDLE); |
| 24 | ap_hook_post_config(mgs_hook_post_config, NULL, NULL, | 24 | ap_hook_post_config(mgs_hook_post_config, NULL, NULL, |
| 25 | APR_HOOK_MIDDLE); | 25 | APR_HOOK_MIDDLE); |
| 26 | ap_hook_child_init(mgs_hook_child_init, NULL, NULL, | 26 | ap_hook_child_init(mgs_hook_child_init, NULL, NULL, |
| 27 | APR_HOOK_MIDDLE); | 27 | APR_HOOK_MIDDLE); |
| 28 | #if USING_2_1_RECENT | 28 | #if USING_2_1_RECENT |
| 29 | ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, | 29 | ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, |
| 30 | APR_HOOK_MIDDLE); | 30 | APR_HOOK_MIDDLE); |
| 31 | #else | 31 | #else |
| 32 | ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, | 32 | ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, |
| 33 | APR_HOOK_MIDDLE); | 33 | APR_HOOK_MIDDLE); |
| 34 | #endif | 34 | #endif |
| 35 | ap_hook_default_port(mgs_hook_default_port, NULL, NULL, | 35 | ap_hook_default_port(mgs_hook_default_port, NULL, NULL, |
| 36 | APR_HOOK_MIDDLE); | 36 | APR_HOOK_MIDDLE); |
| 37 | ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL, | 37 | ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL, |
| 38 | APR_HOOK_MIDDLE); | 38 | APR_HOOK_MIDDLE); |
| 39 | |||
| 40 | ap_hook_access_checker(mgs_hook_authz, NULL, NULL, APR_HOOK_REALLY_FIRST); | ||
| 41 | |||
| 42 | ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); | ||
| 43 | |||
| 44 | /* TODO: HTTP Upgrade Filter */ | ||
| 45 | /* ap_register_output_filter ("UPGRADE_FILTER", | ||
| 46 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); | ||
| 47 | */ | ||
| 48 | 39 | ||
| 49 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, | 40 | ap_hook_access_checker(mgs_hook_authz, NULL, NULL, |
| 50 | mgs_filter_input, NULL, | 41 | APR_HOOK_REALLY_FIRST); |
| 51 | AP_FTYPE_CONNECTION + 5); | 42 | |
| 52 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, | 43 | ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); |
| 53 | mgs_filter_output, NULL, | 44 | |
| 54 | AP_FTYPE_CONNECTION + 5); | 45 | /* TODO: HTTP Upgrade Filter */ |
| 46 | /* ap_register_output_filter ("UPGRADE_FILTER", | ||
| 47 | * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); | ||
| 48 | */ | ||
| 49 | |||
| 50 | ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, | ||
| 51 | mgs_filter_input, NULL, | ||
| 52 | AP_FTYPE_CONNECTION + 5); | ||
| 53 | ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, | ||
| 54 | mgs_filter_output, NULL, | ||
| 55 | AP_FTYPE_CONNECTION + 5); | ||
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | static const command_rec mgs_config_cmds[] = { | 58 | static const command_rec mgs_config_cmds[] = { |
| 58 | AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, | 59 | AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, |
| 59 | NULL, | 60 | NULL, |
| 60 | RSRC_CONF|OR_AUTHCFG, | 61 | RSRC_CONF | OR_AUTHCFG, |
| 61 | "Set Verification Requirements of the Client Certificate"), | 62 | "Set Verification Requirements of the Client Certificate"), |
| 62 | AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file, | 63 | AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file, |
| 63 | NULL, | 64 | NULL, |
| 64 | RSRC_CONF, | 65 | RSRC_CONF, |
| 65 | "Set the CA File to verify Client Certificates"), | 66 | "Set the CA File to verify Client Certificates"), |
| 66 | AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, | 67 | AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, |
| 67 | NULL, | 68 | NULL, |
| 68 | RSRC_CONF, | 69 | RSRC_CONF, |
| 69 | "Set the CA File to verify Client Certificates"), | 70 | "Set the CA File to verify Client Certificates"), |
| 70 | AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, | 71 | AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, |
| 71 | NULL, | 72 | NULL, |
| 72 | RSRC_CONF, | 73 | RSRC_CONF, |
| 73 | "Set the Keyring File to verify Client Certificates"), | 74 | "Set the Keyring File to verify Client Certificates"), |
| 74 | AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, | 75 | AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, |
| 75 | NULL, | 76 | NULL, |
| 76 | RSRC_CONF, | 77 | RSRC_CONF, |
| 77 | "Set the file to read Diffie Hellman parameters from"), | 78 | "Set the file to read Diffie Hellman parameters from"), |
| 78 | AP_INIT_TAKE1("GnuTLSRSAFile", mgs_set_rsa_export_file, | 79 | AP_INIT_TAKE1("GnuTLSRSAFile", mgs_set_rsa_export_file, |
| 79 | NULL, | 80 | NULL, |
| 80 | RSRC_CONF, | 81 | RSRC_CONF, |
| 81 | "Set the file to read RSA-EXPORT parameters from"), | 82 | "Set the file to read RSA-EXPORT parameters from"), |
| 82 | AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, | 83 | AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, |
| 83 | NULL, | 84 | NULL, |
| 84 | RSRC_CONF, | 85 | RSRC_CONF, |
| 85 | "SSL Server X509 Certificate file"), | 86 | "SSL Server X509 Certificate file"), |
| 86 | AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, | 87 | AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, |
| 87 | NULL, | 88 | NULL, |
| 88 | RSRC_CONF, | 89 | RSRC_CONF, |
| 89 | "SSL Server X509 Private Key file"), | 90 | "SSL Server X509 Private Key file"), |
| 90 | AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, | 91 | AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, |
| 91 | NULL, | 92 | NULL, |
| 92 | RSRC_CONF, | 93 | RSRC_CONF, |
| 93 | "SSL Server X509 Certificate file"), | 94 | "SSL Server X509 Certificate file"), |
| 94 | AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, | 95 | AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, |
| 95 | NULL, | 96 | NULL, |
| 96 | RSRC_CONF, | 97 | RSRC_CONF, |
| 97 | "SSL Server X509 Private Key file"), | 98 | "SSL Server X509 Private Key file"), |
| 98 | AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, | 99 | AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, |
| 99 | NULL, | 100 | NULL, |
| 100 | RSRC_CONF, | 101 | RSRC_CONF, |
| 101 | "SSL Server PGP Certificate file"), | 102 | "SSL Server PGP Certificate file"), |
| 102 | AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, | 103 | AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, |
| 103 | NULL, | 104 | NULL, |
| 104 | RSRC_CONF, | 105 | RSRC_CONF, |
| 105 | "SSL Server PGP Private key file"), | 106 | "SSL Server PGP Private key file"), |
| 106 | #ifdef ENABLE_SRP | 107 | #ifdef ENABLE_SRP |
| 107 | AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, | 108 | AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, |
| 108 | NULL, | 109 | NULL, |
| 109 | RSRC_CONF, | 110 | RSRC_CONF, |
| 110 | "SSL Server SRP Password Conf file"), | 111 | "SSL Server SRP Password Conf file"), |
| 111 | AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile", mgs_set_srp_tpasswd_conf_file, | 112 | AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile", |
| 112 | NULL, | 113 | mgs_set_srp_tpasswd_conf_file, |
| 113 | RSRC_CONF, | 114 | NULL, |
| 114 | "SSL Server SRP Parameters file"), | 115 | RSRC_CONF, |
| 116 | "SSL Server SRP Parameters file"), | ||
| 115 | #endif | 117 | #endif |
| 116 | AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout, | 118 | AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout, |
| 117 | NULL, | 119 | NULL, |
| 118 | RSRC_CONF, | 120 | RSRC_CONF, |
| 119 | "Cache Timeout"), | 121 | "Cache Timeout"), |
| 120 | AP_INIT_TAKE2("GnuTLSCache", mgs_set_cache, | 122 | AP_INIT_TAKE2("GnuTLSCache", mgs_set_cache, |
| 121 | NULL, | 123 | NULL, |
| 122 | RSRC_CONF, | 124 | RSRC_CONF, |
| 123 | "Cache Configuration"), | 125 | "Cache Configuration"), |
| 124 | AP_INIT_TAKE1("GnuTLSSessionTickets", mgs_set_tickets, | 126 | AP_INIT_TAKE1("GnuTLSSessionTickets", mgs_set_tickets, |
| 125 | NULL, | 127 | NULL, |
| 126 | RSRC_CONF, | 128 | RSRC_CONF, |
| 127 | "Session Tickets Configuration"), | 129 | "Session Tickets Configuration"), |
| 128 | AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities, | 130 | AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities, |
| 129 | NULL, | 131 | NULL, |
| 130 | RSRC_CONF, | 132 | RSRC_CONF, |
| 131 | "The priorities to enable (ciphers, Key exchange, macs, compression)."), | 133 | "The priorities to enable (ciphers, Key exchange, macs, compression)."), |
| 132 | AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, | 134 | AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, |
| 133 | NULL, | 135 | NULL, |
| 134 | RSRC_CONF, | 136 | RSRC_CONF, |
| 135 | "Whether this server has GnuTLS Enabled. Default: Off"), | 137 | "Whether this server has GnuTLS Enabled. Default: Off"), |
| 136 | AP_INIT_TAKE1("GnuTLSExportCertificates", mgs_set_export_certificates_enabled, | 138 | AP_INIT_TAKE1("GnuTLSExportCertificates", |
| 137 | NULL, | 139 | mgs_set_export_certificates_enabled, |
| 138 | RSRC_CONF, | 140 | NULL, |
| 139 | "Whether to export PEM encoded certificates to CGIs. Default: Off"), | 141 | RSRC_CONF, |
| 142 | "Whether to export PEM encoded certificates to CGIs. Default: Off"), | ||
| 140 | #if 0 | 143 | #if 0 |
| 141 | AP_INIT_RAW_ARGS("<GnuTLSRequire", mgs_set_require_section, | 144 | AP_INIT_RAW_ARGS("<GnuTLSRequire", mgs_set_require_section, |
| 142 | NULL, | 145 | NULL, |
| 143 | EXEC_ON_READ|OR_ALL, | 146 | EXEC_ON_READ | OR_ALL, |
| 144 | "Whether this server has GnuTLS Enabled. Default: Off"), | 147 | "Whether this server has GnuTLS Enabled. Default: Off"), |
| 145 | AP_INIT_RAW_ARGS("GnuTLSRequireByteCode", mgs_set_require_bytecode, | 148 | AP_INIT_RAW_ARGS("GnuTLSRequireByteCode", mgs_set_require_bytecode, |
| 146 | NULL, | 149 | NULL, |
| 147 | OR_ALL, | 150 | OR_ALL, |
| 148 | "Internal Command for reading Lua Bytecode."), | 151 | "Internal Command for reading Lua Bytecode."), |
| 149 | #endif | 152 | #endif |
| 150 | {NULL} | 153 | {NULL} |
| 151 | }; | 154 | }; |
| 152 | 155 | ||
| 153 | module AP_MODULE_DECLARE_DATA gnutls_module = { | 156 | module AP_MODULE_DECLARE_DATA gnutls_module = { |
| 154 | STANDARD20_MODULE_STUFF, | 157 | STANDARD20_MODULE_STUFF, |
| 155 | mgs_config_dir_create, | 158 | mgs_config_dir_create, |
| 156 | mgs_config_dir_merge, | 159 | mgs_config_dir_merge, |
| 157 | mgs_config_server_create, | 160 | mgs_config_server_create, |
| 158 | NULL, | 161 | NULL, |
| 159 | mgs_config_cmds, | 162 | mgs_config_cmds, |
| 160 | gnutls_hooks | 163 | gnutls_hooks |
| 161 | }; | 164 | }; |
