Skip to content

Commit db81019

Browse files
committed
SECURITY: CVE-2015-3185 (cve.mitre.org)
Replacement of ap_some_auth_required (unusable in Apache httpd 2.4) with new ap_some_authn_required and ap_force_authn hook. Submitted by: breser git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1684524 13f79535-47bb-0310-9956-ffa450edef68
1 parent a6027e5 commit db81019

File tree

3 files changed

+83
-19
lines changed

3 files changed

+83
-19
lines changed

Diff for: include/ap_mmn.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -482,14 +482,16 @@
482482
* 20150222.0 (2.5.0-dev) ssl pre_handshake hook now indicates proxy|client
483483
* 20150222.1 (2.5.0-dev) Add keep_alive_timeout_set to server_rec
484484
* 20150222.2 (2.5.0-dev) Add response code 418 as per RFC2324/RFC7168
485+
* 20150222.3 (2.5.0-dev) Add ap_some_authn_required, ap_force_authn hook.
486+
* Deprecate broken ap_some_auth_required.
485487
*/
486488

487489
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
488490

489491
#ifndef MODULE_MAGIC_NUMBER_MAJOR
490492
#define MODULE_MAGIC_NUMBER_MAJOR 20150222
491493
#endif
492-
#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */
494+
#define MODULE_MAGIC_NUMBER_MINOR 3 /* 0...n */
493495

494496
/**
495497
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Diff for: include/http_request.h

+24
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *sub_req, request_rec *r)
185185
* is required for the current request
186186
* @param r The current request
187187
* @return 1 if authentication is required, 0 otherwise
188+
* @bug Behavior changed in 2.4.x refactoring, API no longer usable
189+
* @deprecated @see ap_some_authn_required()
190+
*
188191
*/
189192
AP_DECLARE(int) ap_some_auth_required(request_rec *r);
190193

@@ -541,6 +544,16 @@ AP_DECLARE_HOOK(void,insert_filter,(request_rec *r))
541544
*/
542545
AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r))
543546

547+
/**
548+
* This hook allows a module to force authn to be required when
549+
* processing a request.
550+
* This hook should be registered with ap_hook_force_authn().
551+
* @param r The current request
552+
* @return OK (force authn), DECLINED (let later modules decide)
553+
* @ingroup hooks
554+
*/
555+
AP_DECLARE_HOOK(int,force_authn,(request_rec *r))
556+
544557
/**
545558
* This hook allows modules to handle/emulate the apr_stat() calls
546559
* needed for directory walk.
@@ -587,6 +600,17 @@ AP_DECLARE(apr_bucket *) ap_bucket_eor_make(apr_bucket *b, request_rec *r);
587600
AP_DECLARE(apr_bucket *) ap_bucket_eor_create(apr_bucket_alloc_t *list,
588601
request_rec *r);
589602

603+
/**
604+
* Can be used within any handler to determine if any authentication
605+
* is required for the current request. Note that if used with an
606+
* access_checker hook, an access_checker_ex hook or an authz provider; the
607+
* caller should take steps to avoid a loop since this function is
608+
* implemented by calling these hooks.
609+
* @param r The current request
610+
* @return TRUE if authentication is required, FALSE otherwise
611+
*/
612+
AP_DECLARE(int) ap_some_authn_required(request_rec *r);
613+
590614
#ifdef __cplusplus
591615
}
592616
#endif

Diff for: server/request.c

+56-18
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ APR_HOOK_STRUCT(
7171
APR_HOOK_LINK(create_request)
7272
APR_HOOK_LINK(post_perdir_config)
7373
APR_HOOK_LINK(dirwalk_stat)
74+
APR_HOOK_LINK(force_authn)
7475
)
7576

7677
AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name,
@@ -97,6 +98,8 @@ AP_IMPLEMENT_HOOK_RUN_ALL(int, post_perdir_config,
9798
AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t,dirwalk_stat,
9899
(apr_finfo_t *finfo, request_rec *r, apr_int32_t wanted),
99100
(finfo, r, wanted), AP_DECLINED)
101+
AP_IMPLEMENT_HOOK_RUN_FIRST(int,force_authn,
102+
(request_rec *r), (r), DECLINED)
100103

101104
static int auth_internal_per_conf = 0;
102105
static int auth_internal_per_conf_hooks = 0;
@@ -118,6 +121,39 @@ static int decl_die(int status, const char *phase, request_rec *r)
118121
}
119122
}
120123

124+
AP_DECLARE(int) ap_some_authn_required(request_rec *r)
125+
{
126+
int access_status;
127+
128+
switch (ap_satisfies(r)) {
129+
case SATISFY_ALL:
130+
case SATISFY_NOSPEC:
131+
if ((access_status = ap_run_access_checker(r)) != OK) {
132+
break;
133+
}
134+
135+
access_status = ap_run_access_checker_ex(r);
136+
if (access_status == DECLINED) {
137+
return TRUE;
138+
}
139+
140+
break;
141+
case SATISFY_ANY:
142+
if ((access_status = ap_run_access_checker(r)) == OK) {
143+
break;
144+
}
145+
146+
access_status = ap_run_access_checker_ex(r);
147+
if (access_status == DECLINED) {
148+
return TRUE;
149+
}
150+
151+
break;
152+
}
153+
154+
return FALSE;
155+
}
156+
121157
/* This is the master logic for processing requests. Do NOT duplicate
122158
* this logic elsewhere, or the security model will be broken by future
123159
* API changes. Each phase must be individually optimized to pick up
@@ -236,15 +272,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
236272
}
237273

238274
access_status = ap_run_access_checker_ex(r);
239-
if (access_status == OK) {
240-
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
241-
"request authorized without authentication by "
242-
"access_checker_ex hook: %s", r->uri);
243-
}
244-
else if (access_status != DECLINED) {
245-
return decl_die(access_status, "check access", r);
246-
}
247-
else {
275+
if (access_status == DECLINED
276+
|| (access_status == OK && ap_run_force_authn(r) == OK)) {
248277
if ((access_status = ap_run_check_user_id(r)) != OK) {
249278
return decl_die(access_status, "check user", r);
250279
}
@@ -262,6 +291,14 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
262291
return decl_die(access_status, "check authorization", r);
263292
}
264293
}
294+
else if (access_status == OK) {
295+
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
296+
"request authorized without authentication by "
297+
"access_checker_ex hook: %s", r->uri);
298+
}
299+
else {
300+
return decl_die(access_status, "check access", r);
301+
}
265302
break;
266303
case SATISFY_ANY:
267304
if ((access_status = ap_run_access_checker(r)) == OK) {
@@ -273,15 +310,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
273310
}
274311

275312
access_status = ap_run_access_checker_ex(r);
276-
if (access_status == OK) {
277-
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
278-
"request authorized without authentication by "
279-
"access_checker_ex hook: %s", r->uri);
280-
}
281-
else if (access_status != DECLINED) {
282-
return decl_die(access_status, "check access", r);
283-
}
284-
else {
313+
if (access_status == DECLINED
314+
|| (access_status == OK && ap_run_force_authn(r) == OK)) {
285315
if ((access_status = ap_run_check_user_id(r)) != OK) {
286316
return decl_die(access_status, "check user", r);
287317
}
@@ -299,6 +329,14 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
299329
return decl_die(access_status, "check authorization", r);
300330
}
301331
}
332+
else if (access_status == OK) {
333+
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
334+
"request authorized without authentication by "
335+
"access_checker_ex hook: %s", r->uri);
336+
}
337+
else {
338+
return decl_die(access_status, "check access", r);
339+
}
302340
break;
303341
}
304342
}

0 commit comments

Comments
 (0)