51
52
static int inside_default_hat = 0;
54
const char * hat_name;
59
const char * hat_name;
63
/* immunix_init() gets invoked in the post_config stage of apache.
64
/* aa_init() gets invoked in the post_config stage of apache.
64
65
* Unfortunately, apache reads its config once when it starts up, then
65
66
* it re-reads it when goes into its restart loop, where it starts it's
66
67
* children. This means we cannot call change_hat here, as the modules
67
68
* memory will be wiped out, and the magic_token will be lost, so apache
68
69
* wouldn't be able to change_hat back out. */
70
immunix_init (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
71
aa_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
73
apr_size_t size = sizeof (magic_token);
74
apr_size_t size = sizeof(magic_token);
76
77
ret = apr_file_open (&file, "/dev/urandom", APR_READ, APR_OS_DEFAULT, p);
78
apr_file_read (file, (void *) &magic_token, &size);
79
apr_file_close (file);
79
apr_file_read(file, (void *) &magic_token, &size);
81
82
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
82
"Failed to open /dev/urandom");
83
"Failed to open /dev/urandom");
84
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "Opened /dev/urandom successfully");
85
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
86
"Opened /dev/urandom successfully");
89
91
/* As each child starts up, we'll change_hat into a default hat, mostly
90
92
* to protect ourselves from bugs in parsing network input, but before
91
93
* we change_hat to the uri specific hat. */
93
immunix_child_init (apr_pool_t *p, server_rec *s)
95
aa_child_init(apr_pool_t *p, server_rec *s)
97
99
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
98
"init: calling change_hat with '%s'", DEFAULT_HAT);
100
"init: calling change_hat with '%s'", DEFAULT_HAT);
99
101
ret = aa_change_hat(DEFAULT_HAT, magic_token);
101
103
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
102
"Failed to change_hat to '%s'", DEFAULT_HAT);
104
"Failed to change_hat to '%s'", DEFAULT_HAT);
104
106
inside_default_hat = 1;
109
111
debug_dump_uri(request_rec *r)
111
113
apr_uri_t *uri = &r->parsed_uri;
113
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping uri info "
114
"scheme='%s' host='%s' path='%s' query='%s' fragment='%s'",
115
uri->scheme, uri->hostname, uri->path, uri->query,
115
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping uri info "
116
"scheme='%s' host='%s' path='%s' query='%s' fragment='%s'",
117
uri->scheme, uri->hostname, uri->path, uri->query,
118
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Asked to dump NULL uri");
120
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Asked to dump NULL uri");
123
immunix_enter_hat will attempt to change_hat in the following order:
125
aa_enter_hat will attempt to change_hat in the following order:
124
126
(1) to a hatname in a location directive
126
(3) to a per-server default
128
(5) back to the parent profile
127
(2) to the server name or a defined per-server default
128
(3) to the server name + "-" + uri
131
(6) back to the parent profile
131
immunix_enter_hat (request_rec *r)
134
aa_enter_hat(request_rec *r)
134
immunix_dir_cfg * dcfg = (immunix_dir_cfg *)
135
ap_get_module_config (r->per_dir_config, &apparmor_module);
136
immunix_srv_cfg * scfg = (immunix_srv_cfg *)
137
ap_get_module_config (r->server->module_config, &apparmor_module);
138
const char *aa_hat_array[5] = { NULL, NULL, NULL, NULL, NULL };
137
apparmor_dir_cfg *dcfg = (apparmor_dir_cfg *)
138
ap_get_module_config(r->per_dir_config, &apparmor_module);
139
apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
140
ap_get_module_config(r->server->module_config, &apparmor_module);
141
const char *aa_hat_array[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
140
143
char *aa_con, *aa_mode, *aa_hat;
144
const char *vhost_uri;
142
146
debug_dump_uri(r);
143
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "in immunix_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
144
dcfg->path, (unsigned long) r->next, (unsigned long) r->prev,
145
(unsigned long) r->main);
147
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "aa_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
148
dcfg->path, (unsigned long) r->next, (unsigned long) r->prev,
149
(unsigned long) r->main);
147
151
/* We only call change_hat for the main request, not subrequests */
151
155
if (inside_default_hat) {
152
156
aa_change_hat(NULL, magic_token);
153
inside_default_hat = 0;
157
inside_default_hat = 0;
156
160
if (dcfg != NULL && dcfg->hat_name != NULL) {
157
161
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
158
"[dcfg] adding hat '%s' to aa_change_hat vector", dcfg->hat_name);
162
"[dcfg] adding hat '%s' to aa_change_hat vector", dcfg->hat_name);
159
163
aa_hat_array[i++] = dcfg->hat_name;
162
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
163
"[uri] adding uri '%s' to aa_change_hat vector", r->uri);
164
aa_hat_array[i++] = r->uri;
167
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping scfg info: "
168
"scfg='0x%lx' scfg->hat_name='%s'",
169
(unsigned long) scfg, scfg->hat_name);
167
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping scfg info: "
168
"scfg='0x%lx' scfg->hat_name='%s'",
169
(unsigned long) scfg, scfg->hat_name);
171
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "scfg is null");
171
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "scfg is null");
173
173
if (scfg != NULL) {
174
if (scfg->hat_name != NULL) {
174
if (scfg->hat_name != NULL) {
175
175
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
176
"[scfg] adding hat '%s' to aa_change_hat vector", scfg->hat_name);
176
"[scfg] adding hat '%s' to aa_change_hat vector", scfg->hat_name);
177
177
aa_hat_array[i++] = scfg->hat_name;
179
179
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
180
"[scfg] adding server_name '%s' to aa_change_hat vector",
181
r->server->server_hostname);
180
"[scfg] adding server_name '%s' to aa_change_hat vector",
181
r->server->server_hostname);
182
182
aa_hat_array[i++] = r->server->server_hostname;
185
vhost_uri = apr_pstrcat(r->pool, r->server->server_hostname, "-", r->uri, NULL);
186
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
187
"[vhost+uri] adding vhost+uri '%s' to aa_change_hat vector", vhost_uri);
188
aa_hat_array[i++] = vhost_uri;
186
191
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
187
"[default] adding '%s' to aa_change_hat vector", DEFAULT_URI_HAT);
192
"[uri] adding uri '%s' to aa_change_hat vector", r->uri);
193
aa_hat_array[i++] = r->uri;
195
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
196
"[default] adding '%s' to aa_change_hat vector", DEFAULT_URI_HAT);
188
197
aa_hat_array[i++] = DEFAULT_URI_HAT;
190
sd_ret = aa_change_hatv(aa_hat_array, magic_token);
199
aa_ret = aa_change_hatv(aa_hat_array, magic_token);
192
201
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_change_hatv call failed");
195
204
/* Check to see if a defined AAHatName or AADefaultHatName would
196
205
* apply, but wasn't the hat we landed up in; report a warning if
197
206
* that's the case. */
198
sd_ret = aa_getcon(&aa_con, &aa_mode);
207
aa_ret = aa_getcon(&aa_con, &aa_mode);
200
209
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_getcon call failed");
202
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
203
"AA checks: aa_getcon result is '%s', mode '%s'", aa_con, aa_mode);
204
/* TODO: use libapparmor get hat_name fn here once it is implemented */
205
aa_hat = strstr(aa_con, "//");
206
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
207
aa_hat += 2; /* skip "//" */
208
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
209
"AA checks: apache is in hat '%s', mode '%s'", aa_hat, aa_mode);
210
if (dcfg != NULL && dcfg->hat_name != NULL) {
211
if (strcmp(aa_hat, dcfg->hat_name) != 0)
212
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
213
"AAHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
215
} else if (scfg != NULL && scfg->hat_name != NULL) {
216
if (strcmp(aa_hat, scfg->hat_name) != 0 &&
217
strcmp(aa_hat, r->uri) != 0)
218
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
219
"AADefaultHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
211
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
212
"AA checks: aa_getcon result is '%s', mode '%s'", aa_con, aa_mode);
213
/* TODO: use libapparmor get hat_name fn here once it is implemented */
214
aa_hat = strstr(aa_con, "//");
215
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
216
aa_hat += 2; /* skip "//" */
217
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
218
"AA checks: apache is in hat '%s', mode '%s'", aa_hat, aa_mode);
219
if (dcfg != NULL && dcfg->hat_name != NULL) {
220
if (strcmp(aa_hat, dcfg->hat_name) != 0)
221
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
222
"AAHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
224
} else if (scfg != NULL && scfg->hat_name != NULL) {
225
if (strcmp(aa_hat, scfg->hat_name) != 0 &&
226
strcmp(aa_hat, r->uri) != 0)
227
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
228
"AADefaultHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
230
immunix_exit_hat (request_rec *r)
239
aa_exit_hat(request_rec *r)
233
immunix_dir_cfg * dcfg = (immunix_dir_cfg *)
234
ap_get_module_config (r->per_dir_config, &apparmor_module);
235
/* immunix_srv_cfg * scfg = (immunix_srv_cfg *)
236
ap_get_module_config (r->server->module_config, &apparmor_module); */
242
apparmor_dir_cfg *dcfg = (apparmor_dir_cfg *)
243
ap_get_module_config(r->per_dir_config, &apparmor_module);
244
/* apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
245
ap_get_module_config(r->server->module_config, &apparmor_module); */
237
246
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "exiting change_hat: dir hat %s dir path %s",
238
dcfg->hat_name, dcfg->path);
247
dcfg->hat_name, dcfg->path);
240
249
/* can convert the following back to aa_change_hat() when the
241
250
* aa_change_hat() bug addressed in trunk commit 2329 lands in most
242
251
* system libapparmors */
243
252
aa_change_hatv(NULL, magic_token);
245
sd_ret = aa_change_hat(DEFAULT_HAT, magic_token);
254
aa_ret = aa_change_hat(DEFAULT_HAT, magic_token);
247
256
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
248
"Failed to change_hat to '%s'", DEFAULT_HAT);
257
"Failed to change_hat to '%s'", DEFAULT_HAT);
250
259
inside_default_hat = 1;
326
337
/* XXX: Should figure out an appropriate action to take here, if any
329
immunix_merge_dir_config (apr_pool_t * p, void * parent, void * child)
340
aa_merge_dir_config(apr_pool_t *p, void *parent, void *child)
331
immunix_dir_cfg * newcfg = (immunix_dir_cfg *) apr_pcalloc(p, sizeof(* newcfg));
342
apparmor_dir_cfg *newcfg = (apparmor_dir_cfg *) apr_pcalloc(p, sizeof(*newcfg));
333
344
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_merge_dir ()");
334
345
if (newcfg == NULL)
342
immunix_create_srv_config (apr_pool_t * p, server_rec * srv)
353
aa_create_srv_config(apr_pool_t *p, server_rec *srv)
344
immunix_srv_cfg * newcfg = (immunix_srv_cfg *) apr_pcalloc(p, sizeof(* newcfg));
355
apparmor_srv_cfg *newcfg = (apparmor_srv_cfg *) apr_pcalloc(p, sizeof(*newcfg));
346
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_create_srv");
357
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
358
"in aa_create_srv_config");
347
359
if (newcfg == NULL) {
348
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "immunix_create_srv: couldn't alloc srv config");
360
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
361
"aa_create_srv_config: couldn't alloc srv config");
356
static const command_rec immunix_cmds[] = {
369
static const command_rec mod_apparmor_cmds[] = {
366
379
"ImmDefaultHatName",
380
393
"AADefaultHatName",
390
register_hooks (apr_pool_t *p)
403
register_hooks(apr_pool_t *p)
392
ap_hook_post_config (immunix_init, NULL, NULL, APR_HOOK_MIDDLE);
393
ap_hook_child_init (immunix_child_init, NULL, NULL, APR_HOOK_MIDDLE);
394
ap_hook_access_checker(immunix_enter_hat, NULL, NULL, APR_HOOK_FIRST);
395
/* ap_hook_post_read_request(immunix_enter_hat, NULL, NULL, APR_HOOK_FIRST); */
396
ap_hook_log_transaction(immunix_exit_hat, NULL, NULL, APR_HOOK_LAST);
405
ap_hook_post_config(aa_init, NULL, NULL, APR_HOOK_MIDDLE);
406
ap_hook_child_init(aa_child_init, NULL, NULL, APR_HOOK_MIDDLE);
408
#if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER < 3
409
/* Compatibility with apache 2.2 */
410
ap_hook_access_checker(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST);
412
/* apache 2.4 mod_authz hook */
413
ap_hook_check_access_ex(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_CONF);
416
/* ap_hook_post_read_request(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST); */
417
ap_hook_log_transaction(aa_exit_hat, NULL, NULL, APR_HOOK_LAST);
399
420
module AP_MODULE_DECLARE_DATA apparmor_module = {
400
421
STANDARD20_MODULE_STUFF,
401
immunix_create_dir_config, /* dir config creater */
402
NULL, /* dir merger --- default is to override */
403
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
404
immunix_create_srv_config, /* server config */
405
NULL, /* merge server config */
406
immunix_cmds, /* command table */
407
register_hooks /* register hooks */
422
aa_create_dir_config, /* dir config creater */
423
NULL, /* dir merger --- default is to override */
424
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
425
aa_create_srv_config, /* server config */
426
NULL, /* merge server config */
427
mod_apparmor_cmds, /* command table */
428
register_hooks /* register hooks */