Apache HTTPD
tls_var.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <assert.h>
17#include <apr_lib.h>
18#include <apr_strings.h>
19
20#include <httpd.h>
21#include <http_connection.h>
22#include <http_core.h>
23#include <http_main.h>
24#include <http_log.h>
25#include <ap_socache.h>
26
27#include <rustls.h>
28
29#include "tls_conf.h"
30#include "tls_core.h"
31#include "tls_cert.h"
32#include "tls_util.h"
33#include "tls_var.h"
34#include "tls_version.h"
35
36
37extern module AP_MODULE_DECLARE_DATA tls_module;
39
50
51typedef const char *var_lookup(const tls_var_lookup_ctx_t *ctx);
52
54{
55 return ctx->cc->tls_protocol_name;
56}
57
59{
60 return ctx->cc->tls_cipher_name;
61}
62
64{
65 return ctx->cc->sni_hostname;
66}
67
73
75{
77 return sc->global->crustls_version;
78}
79
80static const char *var_get_false(const tls_var_lookup_ctx_t *ctx)
81{
82 (void)ctx;
83 return "false";
84}
85
86static const char *var_get_null(const tls_var_lookup_ctx_t *ctx)
87{
88 (void)ctx;
89 return "NULL";
90}
91
93{
94 /* There is no support in the crustls/rustls/webpki APIs to
95 * parse X.509 certificates and extract information about
96 * subject, issuer, etc. */
97 if (!ctx->cc->peer_certs || !ctx->cc->peer_certs->nelts) return NULL;
98 return "Not Implemented";
99}
100
102{
103 return ctx->cc->peer_certs? "SUCCESS" : "NONE";
104}
105
107{
108 return ctx->cc->session_id_cache_hit? "Resumed" : "Initial";
109}
110
112{
114 const char *pem;
115 apr_status_t rv;
116 int cert_idx = 0;
117
118 if (ctx->arg_s) {
119 if (strcmp(ctx->arg_s, "chain")) return NULL;
120 /* ctx->arg_i'th chain cert, which is in out list as */
121 cert_idx = ctx->arg_i + 1;
122 }
123 if (!ctx->cc->peer_certs || cert_idx >= ctx->cc->peer_certs->nelts) return NULL;
124 cert = APR_ARRAY_IDX(ctx->cc->peer_certs, cert_idx, const rustls_certificate*);
125 if (APR_SUCCESS != (rv = tls_cert_to_pem(&pem, ctx->p, cert))) {
127 "Failed to create client certificate PEM");
128 return NULL;
129 }
130 return pem;
131}
132
134{
136 const char *pem;
137 apr_status_t rv;
138
139 if (!ctx->cc->key) return NULL;
141 if (!cert) return NULL;
142 if (APR_SUCCESS != (rv = tls_cert_to_pem(&pem, ctx->p, cert))) {
144 "Failed to create server certificate PEM");
145 return NULL;
146 }
147 return pem;
148}
149
150typedef struct {
151 const char *name;
153 const char *arg_s;
154 int arg_i;
155} var_def_t;
156
157static const var_def_t VAR_DEFS[] = {
158 { "SSL_PROTOCOL", var_get_ssl_protocol, NULL, 0 },
159 { "SSL_CIPHER", var_get_ssl_cipher, NULL, 0 },
160 { "SSL_TLS_SNI", var_get_sni_hostname, NULL, 0 },
161 { "SSL_CLIENT_S_DN_CN", var_get_client_s_dn_cn, NULL, 0 },
162 { "SSL_VERSION_INTERFACE", var_get_version_interface, NULL, 0 },
163 { "SSL_VERSION_LIBRARY", var_get_version_library, NULL, 0 },
164 { "SSL_SECURE_RENEG", var_get_false, NULL, 0 },
165 { "SSL_COMPRESS_METHOD", var_get_null, NULL, 0 },
166 { "SSL_CIPHER_EXPORT", var_get_false, NULL, 0 },
167 { "SSL_CLIENT_VERIFY", var_get_client_verify, NULL, 0 },
168 { "SSL_SESSION_RESUMED", var_get_session_resumed, NULL, 0 },
169 { "SSL_CLIENT_CERT", var_get_client_cert, NULL, 0 },
170 { "SSL_CLIENT_CHAIN_0", var_get_client_cert, "chain", 0 },
171 { "SSL_CLIENT_CHAIN_1", var_get_client_cert, "chain", 1 },
172 { "SSL_CLIENT_CHAIN_2", var_get_client_cert, "chain", 2 },
173 { "SSL_CLIENT_CHAIN_3", var_get_client_cert, "chain", 3 },
174 { "SSL_CLIENT_CHAIN_4", var_get_client_cert, "chain", 4 },
175 { "SSL_CLIENT_CHAIN_5", var_get_client_cert, "chain", 5 },
176 { "SSL_CLIENT_CHAIN_6", var_get_client_cert, "chain", 6 },
177 { "SSL_CLIENT_CHAIN_7", var_get_client_cert, "chain", 7 },
178 { "SSL_CLIENT_CHAIN_8", var_get_client_cert, "chain", 8 },
179 { "SSL_CLIENT_CHAIN_9", var_get_client_cert, "chain", 9 },
180 { "SSL_SERVER_CERT", var_get_server_cert, NULL, 0 },
181};
182
183static const char *const TlsAlwaysVars[] = {
184 "SSL_TLS_SNI",
185 "SSL_PROTOCOL",
186 "SSL_CIPHER",
187 "SSL_CLIENT_S_DN_CN",
188};
189
190/* what mod_ssl defines, plus server cert and client cert DN and SAN entries */
191static const char *const StdEnvVars[] = {
192 "SSL_VERSION_INTERFACE", /* implemented: module version string */
193 "SSL_VERSION_LIBRARY", /* implemented: crustls/rustls version string */
194 "SSL_SECURE_RENEG", /* implemented: always "false" */
195 "SSL_COMPRESS_METHOD", /* implemented: always "NULL" */
196 "SSL_CIPHER_EXPORT", /* implemented: always "false" */
197 "SSL_CIPHER_USEKEYSIZE",
198 "SSL_CIPHER_ALGKEYSIZE",
199 "SSL_CLIENT_VERIFY", /* implemented: always "SUCCESS" or "NONE" */
200 "SSL_CLIENT_M_VERSION",
201 "SSL_CLIENT_M_SERIAL",
202 "SSL_CLIENT_V_START",
203 "SSL_CLIENT_V_END",
204 "SSL_CLIENT_V_REMAIN",
205 "SSL_CLIENT_S_DN",
206 "SSL_CLIENT_I_DN",
207 "SSL_CLIENT_A_KEY",
208 "SSL_CLIENT_A_SIG",
209 "SSL_CLIENT_CERT_RFC4523_CEA",
210 "SSL_SERVER_M_VERSION",
211 "SSL_SERVER_M_SERIAL",
212 "SSL_SERVER_V_START",
213 "SSL_SERVER_V_END",
214 "SSL_SERVER_S_DN",
215 "SSL_SERVER_I_DN",
216 "SSL_SERVER_A_KEY",
217 "SSL_SERVER_A_SIG",
218 "SSL_SESSION_ID", /* not implemented: highly sensitive data we do not expose */
219 "SSL_SESSION_RESUMED", /* implemented: if our cache was hit successfully */
220};
221
222/* Cert related variables, export when TLSOption ExportCertData is set */
223static const char *const ExportCertVars[] = {
224 "SSL_CLIENT_CERT", /* implemented: */
225 "SSL_CLIENT_CHAIN_0", /* implemented: */
226 "SSL_CLIENT_CHAIN_1", /* implemented: */
227 "SSL_CLIENT_CHAIN_2", /* implemented: */
228 "SSL_CLIENT_CHAIN_3", /* implemented: */
229 "SSL_CLIENT_CHAIN_4", /* implemented: */
230 "SSL_CLIENT_CHAIN_5", /* implemented: */
231 "SSL_CLIENT_CHAIN_6", /* implemented: */
232 "SSL_CLIENT_CHAIN_7", /* implemented: */
233 "SSL_CLIENT_CHAIN_8", /* implemented: */
234 "SSL_CLIENT_CHAIN_9", /* implemented: */
235 "SSL_SERVER_CERT", /* implemented: */
236};
237
239{
240 const var_def_t *def;
242
243 (void)pool;
244 for (i = 0; i < TLS_DIM(VAR_DEFS); ++i) {
245 def = &VAR_DEFS[i];
246 apr_hash_set(map, def->name, APR_HASH_KEY_STRING, def);
247 }
248}
249
250static const char *invoke(var_def_t* def, tls_var_lookup_ctx_t *ctx)
251{
252 if (TLS_CONN_ST_IS_ENABLED(ctx->cc)) {
253 const char *val = ctx->cc->subprocess_env?
254 apr_table_get(ctx->cc->subprocess_env, def->name) : NULL;
255 if (val && *val) return val;
256 ctx->arg_s = def->arg_s;
257 ctx->arg_i = def->arg_i;
258 return def->fn(ctx);
259 }
260 return NULL;
261}
262
263static void set_var(
265{
267 if (def) {
268 const char *val = invoke(def, ctx);
269 if (val && *val) {
270 apr_table_setn(table, ctx->name, val);
271 }
272 }
273}
274
275const char *tls_var_lookup(
276 apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *name)
277{
278 const char *val = NULL;
280 var_def_t* def;
281
282 ap_assert(p);
284 s = s? s : (r? r->server : (c? c->base_server : NULL));
285 c = c? c : (r? r->connection : NULL);
286
289 if (def) {
291 ctx.p = p;
292 ctx.s = s;
293 ctx.c = c;
294 ctx.r = r;
295 ctx.cc = c? tls_conf_conn_get(c->master? c->master : c) : NULL;
296 ctx.cc = c? tls_conf_conn_get(c->master? c->master : c) : NULL;
297 ctx.name = name;
298 val = invoke(def, &ctx);
299 ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, "tls lookup of var '%s' -> '%s'", name, val);
300 }
301 return val;
302}
303
305{
307 tls_conf_dir_t *dc, *sdc;
310 int overlap;
311
315 ctx.p = r? r->pool : c->pool;
316 ctx.s = s;
317 ctx.c = c;
318 ctx.r = r;
319 ctx.cc = tls_conf_conn_get(c->master? c->master : c);
320 /* Can we re-use the precomputed connection values? */
321 overlap = (r && ctx.cc->subprocess_env && r->server == ctx.cc->server);
322 if (overlap) {
323 apr_table_overlap(env, ctx.cc->subprocess_env, APR_OVERLAP_TABLES_SET);
324 }
325 else {
326 apr_table_setn(env, "HTTPS", "on");
327 for (i = 0; i < TLS_DIM(TlsAlwaysVars); ++i) {
328 ctx.name = TlsAlwaysVars[i];
330 }
331 }
332 if (dc->std_env_vars == TLS_FLAG_TRUE) {
333 for (i = 0; i < TLS_DIM(StdEnvVars); ++i) {
334 ctx.name = StdEnvVars[i];
336 }
337 }
338 else if (overlap && sdc->std_env_vars == TLS_FLAG_TRUE) {
339 /* Remove variables added on connection init that are disabled here */
340 for (i = 0; i < TLS_DIM(StdEnvVars); ++i) {
342 }
343 }
344 if (dc->export_cert_vars == TLS_FLAG_TRUE) {
345 for (i = 0; i < TLS_DIM(ExportCertVars); ++i) {
346 ctx.name = ExportCertVars[i];
348 }
349 }
350 else if (overlap && sdc->std_env_vars == TLS_FLAG_TRUE) {
351 /* Remove variables added on connection init that are disabled here */
352 for (i = 0; i < TLS_DIM(ExportCertVars); ++i) {
354 }
355 }
356 }
357
359{
360 tls_conf_conn_t *cc;
363
364 cc = tls_conf_conn_get(c);
365 if (!TLS_CONN_ST_IS_ENABLED(cc)) goto cleanup;
366
367 sc = tls_conf_server_get(cc->server);
368 if (cc->peer_certs && sc->var_user_name) {
369 cc->user_name = tls_var_lookup(c->pool, cc->server, c, NULL, sc->var_user_name);
370 if (!cc->user_name) {
372 "Failed to set r->user to '%s'", sc->var_user_name);
373 }
374 }
375 cc->subprocess_env = apr_table_make(c->pool, 5);
376 add_vars(cc->subprocess_env, c, cc->server, NULL);
377
378cleanup:
379 return rv;
380}
381
383{
385 tls_conf_conn_t *cc;
386
387 cc = tls_conf_conn_get(c->master? c->master : c);
388 if (!TLS_CONN_ST_IS_ENABLED(cc)) goto cleanup;
389 if (cc->user_name) {
390 /* why is r->user a char* and not const? */
391 r->user = apr_pstrdup(r->pool, cc->user_name);
392 }
394
395cleanup:
396 return DECLINED;
397}
Small object cache provider interface.
APR general purpose library routines.
APR Strings library.
#define APLOG_USE_MODULE(foo)
request_rec * r
#define DECLINED
Definition httpd.h:457
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_TRACE3
Definition http_log.h:74
#define ap_log_error
Definition http_log.h:370
#define ap_log_cerror
Definition http_log.h:498
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
#define APLOG_DEBUG
Definition http_log.h:71
server_rec * ap_server_conf
Definition config.c:62
apr_brigade_flush void * ctx
#define ap_assert(exp)
Definition httpd.h:2271
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void const char apr_status_t(* cleanup)(void *))
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
apr_vformatter_buff_t * c
Definition apr_lib.h:175
char const *const char const *const ** env
const char * s
Definition apr_strings.h:95
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
#define APR_OVERLAP_TABLES_SET
Definition apr_tables.h:437
Apache connection library.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * name
Structure to store things which are per connection.
Definition httpd.h:1152
A structure that represents the current request.
Definition httpd.h:845
char * user
Definition httpd.h:1005
apr_pool_t * pool
Definition httpd.h:847
conn_rec * connection
Definition httpd.h:849
apr_table_t * subprocess_env
Definition httpd.h:983
server_rec * server
Definition httpd.h:851
A structure to store information for each virtual server.
Definition httpd.h:1322
server_rec * server
Definition tls_core.h:40
const char * user_name
Definition tls_core.h:69
apr_array_header_t * peer_certs
Definition tls_core.h:57
apr_table_t * subprocess_env
Definition tls_core.h:70
int export_cert_vars
Definition tls_conf.h:131
const char * module_version
Definition tls_conf.h:68
apr_hash_t * var_lookups
Definition tls_conf.h:78
const char * crustls_version
Definition tls_conf.h:69
const char * var_user_name
Definition tls_conf.h:110
tls_conf_global_t * global
Definition tls_conf.h:97
server_rec * s
Definition tls_var.c:42
request_rec * r
Definition tls_var.c:44
tls_conf_conn_t * cc
Definition tls_var.c:45
const char * arg_s
Definition tls_var.c:47
const char * name
Definition tls_var.c:46
apr_pool_t * p
Definition tls_var.c:41
var_lookup * fn
Definition tls_var.c:152
int arg_i
Definition tls_var.c:154
const char * arg_s
Definition tls_var.c:153
const char * name
Definition tls_var.c:151
apr_status_t tls_cert_to_pem(const char **ppem, apr_pool_t *p, const rustls_certificate *cert)
Definition tls_cert.c:121
tls_conf_server_t * tls_conf_server_get(server_rec *s)
Definition tls_conf.c:68
tls_conf_dir_t * tls_conf_dir_get(request_rec *r)
Definition tls_conf.c:124
tls_conf_dir_t * tls_conf_dir_server_get(server_rec *s)
Definition tls_conf.c:131
#define TLS_FLAG_TRUE
Definition tls_conf.h:22
tls_conf_conn_t * tls_conf_conn_get(conn_rec *c)
Definition tls_core.c:45
#define TLS_CONN_ST_IS_ENABLED(cc)
Definition tls_core.h:31
#define TLS_DIM(a)
Definition tls_util.h:19
int tls_var_request_fixup(request_rec *r)
Definition tls_var.c:382
static const char * var_get_client_verify(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:101
const char * tls_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *name)
Definition tls_var.c:275
static const char * var_get_session_resumed(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:106
static const char *const ExportCertVars[]
Definition tls_var.c:223
static const char * var_get_ssl_cipher(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:58
static const char * var_get_false(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:80
static const char * var_get_sni_hostname(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:63
static void set_var(tls_var_lookup_ctx_t *ctx, apr_hash_t *lookups, apr_table_t *table)
Definition tls_var.c:263
static const var_def_t VAR_DEFS[]
Definition tls_var.c:157
static const char * invoke(var_def_t *def, tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:250
static const char *const TlsAlwaysVars[]
Definition tls_var.c:183
apr_status_t tls_var_handshake_done(conn_rec *c)
Definition tls_var.c:358
static const char * var_get_server_cert(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:133
static const char * var_get_client_s_dn_cn(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:92
void tls_var_init_lookup_hash(apr_pool_t *pool, apr_hash_t *map)
Definition tls_var.c:238
static const char *const StdEnvVars[]
Definition tls_var.c:191
const char * var_lookup(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:51
static void add_vars(apr_table_t *env, conn_rec *c, server_rec *s, request_rec *r)
Definition tls_var.c:304
static const char * var_get_version_interface(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:68
static const char * var_get_null(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:86
static const char * var_get_version_library(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:74
static const char * var_get_client_cert(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:111
static const char * var_get_ssl_protocol(const tls_var_lookup_ctx_t *ctx)
Definition tls_var.c:53