summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Pazdziora <jpazdziora@redhat.com>2016-03-29 15:56:29 +0200
committerJan Pazdziora <jpazdziora@redhat.com>2016-05-06 14:04:23 +0200
commita2a7d80a6ad126877c372df59537ba6482f6b93a (patch)
treec177e214ea7c725c625b4b1c385ae91826716546
parent163256e21b1728195034f067913a33f0f09d86d8 (diff)
downloadmod_intercept_form_submit-a2a7d80a6ad126877c372df59537ba6482f6b93a.tar.gz
mod_intercept_form_submit-a2a7d80a6ad126877c372df59537ba6482f6b93a.tar.xz
mod_intercept_form_submit-a2a7d80a6ad126877c372df59537ba6482f6b93a.zip
Add InterceptGETOnSuccess on|off.mod_intercept_form_submit-1.0.1
When the authentication using the POST data passes, the method of the request is internally changed to GET. This stops applications and frameworks that insist on running their own authentication on POST irrespective of REMOTE_USER value to think that they process GET method.
-rw-r--r--Makefile21
-rw-r--r--README11
-rw-r--r--mod_intercept_form_submit.c34
-rw-r--r--mod_intercept_form_submit.spec5
4 files changed, 59 insertions, 12 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..67c41e2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+
+NAME=mod_intercept_form_submit
+
+SOURCE0 := $(shell spectool $(NAME).spec)
+SOURCE := $(shell echo $(SOURCE0) | sed 's%^.*/%%')
+NAME_VER := $(shell echo $(SOURCE) | sed 's%\.tar\.gz$$%%')
+
+all:
+ @echo 'Usage: make dist to build the .tar.gz'
+ @echo ' make timestamps set file timestamps to match commit times'
+
+timestamps:
+ git ls-files | while read -r f ; do touch -ch -d "$$(git log -1 --format=%ci "$$f")" "$$f" ; done
+
+dist:
+ @if test -f ../$(SOURCE) ; then ( echo "The source [../$(SOURCE)] already exists." >&2 ; exit 1 ) ; fi
+ @mkdir .dist
+ @mkdir .dist/$(NAME_VER) && cp -rp * .dist/$(NAME_VER)
+ tar cvzf ../$(SOURCE) -C .dist $(NAME_VER)
+ @rm -rf .dist
+
diff --git a/README b/README
index d58b1f5..4b229ac 100644
--- a/README
+++ b/README
@@ -87,6 +87,14 @@ Optional parameters:
By default, no modifications to login happens.
+ InterceptGETOnSuccess on|off
+
+ When the authentication using the POST data passes, the
+ method of the request is internally changed to GET. This
+ stops applications and frameworks that insist on running
+ their own authentication on POST irrespective of REMOTE_USER
+ value to think that they process GET.
+
Example:
LoadModule intercept_form_submit_module modules/mod_intercept_form_submit.so
@@ -99,6 +107,7 @@ Example:
InterceptFormClearRemoteUserForSkipped on
InterceptFormPasswordRedact on
InterceptFormLoginRealms EXAMPLE.COM LAB.EXAMPLE.COM ''
+ InterceptGETOnSuccess on
</Location>
The PAM service needs to be configured. For the above shown
@@ -149,7 +158,7 @@ is logged and authentication does not take place.
License
-------
-Copyright 2013--2014 Jan Pazdziora
+Copyright 2013--2016 Jan Pazdziora
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/mod_intercept_form_submit.c b/mod_intercept_form_submit.c
index eaba481..bc6ca38 100644
--- a/mod_intercept_form_submit.c
+++ b/mod_intercept_form_submit.c
@@ -1,6 +1,6 @@
/*
- * Copyright 2013--2014 Jan Pazdziora
+ * Copyright 2013--2016 Jan Pazdziora
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ typedef struct ifs_config {
char * pam_service;
apr_hash_t * login_blacklist;
int clear_blacklisted;
+ int success_to_get;
apr_array_header_t * realms;
} ifs_config;
@@ -78,6 +79,7 @@ static const command_rec directives[] = {
AP_INIT_TAKE1("InterceptFormPAMService", ap_set_string_slot, (void *)APR_OFFSETOF(ifs_config, pam_service), ACCESS_CONF, "PAM service to authenticate against"),
AP_INIT_ITERATE("InterceptFormLoginSkip", add_login_to_blacklist, NULL, ACCESS_CONF, "Login name(s) for which no PAM authentication will be done"),
AP_INIT_FLAG("InterceptFormClearRemoteUserForSkipped", ap_set_flag_slot, (void *)APR_OFFSETOF(ifs_config, clear_blacklisted), ACCESS_CONF, "When authentication is skipped for users listed with InterceptFormLoginSkip, clear r->user and REMOTE_USER"),
+ AP_INIT_FLAG("InterceptGETOnSuccess", ap_set_flag_slot, (void *)APR_OFFSETOF(ifs_config, success_to_get), ACCESS_CONF, "When authentication passes, turn the POST request to GET internally"),
AP_INIT_ITERATE("InterceptFormLoginRealms", add_realm, NULL, ACCESS_CONF, "Realm(s) that will be appended to login name which does not have one"),
{ NULL }
};
@@ -234,7 +236,7 @@ static void intercept_form_redact_password(ap_filter_t * f, ifs_config * config)
}
static int intercept_form_submit_process_buffer(ap_filter_t * f, ifs_config * config, char ** login_value, char ** password_value,
- const char * buffer, int buffer_length, apr_bucket * fragment_start_bucket, int fragment_start_bucket_offset) {
+ const char * buffer, int buffer_length, apr_bucket * fragment_start_bucket, int fragment_start_bucket_offset, authn_status * out_status) {
char * sep = memchr(buffer, '=', buffer_length);
if (! sep) {
return 0;
@@ -280,7 +282,7 @@ static int intercept_form_submit_process_buffer(ap_filter_t * f, ifs_config * co
ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "mod_intercept_form_submit: pam_authenticate_with_login_password not found; perhaps mod_authnz_pam is not loaded");
return 0;
}
- pam_authenticate_in_realms(r, config->pam_service, *login_value, *password_value, config->realms, 3);
+ (*out_status) = pam_authenticate_in_realms(r, config->pam_service, *login_value, *password_value, config->realms, 3);
if (config->password_redact > 0) {
intercept_form_redact_password(f, config);
}
@@ -301,9 +303,9 @@ static apr_status_t intercept_form_submit_filter(ap_filter_t * f, apr_bucket_bri
return ap_get_brigade(f->next, bb, mode, block, readbytes);
}
-static void intercept_form_submit_filter_prefetch(request_rec * r, ifs_config * config, ap_filter_t * f) {
+static apr_status_t intercept_form_submit_filter_prefetch(request_rec * r, ifs_config * config, ap_filter_t * f) {
if (r->status != 200)
- return;
+ return DECLINED;
ifs_filter_ctx_t * ctx = f->ctx;
if (! ctx) {
@@ -319,6 +321,8 @@ static void intercept_form_submit_filter_prefetch(request_rec * r, ifs_config *
apr_bucket * fragment_start_bucket = NULL;
int fragment_start_bucket_offset = 0;
+ authn_status out_status = AUTH_GENERAL_ERROR;
+
apr_bucket_brigade * bb = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
int fetch_more = 1;
while (fetch_more) {
@@ -334,7 +338,7 @@ static void intercept_form_submit_filter_prefetch(request_rec * r, ifs_config *
if (APR_BUCKET_IS_EOS(b)) {
if (fragment)
intercept_form_submit_process_buffer(f, config, &login_value, &password_value,
- fragment, fragment_length, fragment_start_bucket, fragment_start_bucket_offset);
+ fragment, fragment_length, fragment_start_bucket, fragment_start_bucket_offset, &out_status);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "hit EOS");
fetch_more = 0;
break;
@@ -357,7 +361,7 @@ static void intercept_form_submit_filter_prefetch(request_rec * r, ifs_config *
fragment = realloc(fragment, new_length);
memcpy(fragment + fragment_length, p, e - p);
if (intercept_form_submit_process_buffer(f, config, &login_value, &password_value,
- fragment, new_length, fragment_start_bucket, fragment_start_bucket_offset)) {
+ fragment, new_length, fragment_start_bucket, fragment_start_bucket_offset, &out_status)) {
fetch_more = 0;
break;
}
@@ -365,7 +369,7 @@ static void intercept_form_submit_filter_prefetch(request_rec * r, ifs_config *
fragment = NULL;
} else {
if (intercept_form_submit_process_buffer(f, config, &login_value, &password_value,
- p, e - p, b, (p - buffer))) {
+ p, e - p, b, (p - buffer), &out_status)) {
fetch_more = 0;
break;
}
@@ -384,7 +388,7 @@ static void intercept_form_submit_filter_prefetch(request_rec * r, ifs_config *
} else if (APR_BUCKET_NEXT(b) && APR_BUCKET_IS_EOS(APR_BUCKET_NEXT(b))) {
/* shortcut if this is the last bucket, slurp the rest */
intercept_form_submit_process_buffer(f, config, &login_value, &password_value,
- p, nbytes, b, (p - buffer));
+ p, nbytes, b, (p - buffer), &out_status);
fetch_more = 0;
} else {
fragment = malloc(nbytes);
@@ -398,6 +402,7 @@ static void intercept_form_submit_filter_prefetch(request_rec * r, ifs_config *
}
if (fragment)
free(fragment);
+ return out_status == AUTH_GRANTED ? OK : DECLINED;
}
#define _INTERCEPT_CONTENT_TYPE "application/x-www-form-urlencoded"
@@ -427,7 +432,14 @@ static apr_status_t intercept_form_submit_init(request_rec * r) {
if (!apr_strnatcasecmp(content_type_pure, _INTERCEPT_CONTENT_TYPE)) {
ap_filter_t * the_filter = ap_add_input_filter("intercept_form_submit_filter", NULL, r, r->connection);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "inserted filter intercept_form_submit_filter, starting intercept_form_submit_filter_prefetch");
- intercept_form_submit_filter_prefetch(r, config, the_filter);
+ apr_status_t status = intercept_form_submit_filter_prefetch(r, config, the_filter);
+ if (status == OK && config->success_to_get >= 0) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "intercept_form_submit_filter_prefetch returned OK, turning the method to GET");
+ r->status_line = NULL;
+ r->method = "GET";
+ r->method_number = M_GET;
+ apr_table_unset(r->headers_in, "Content-Length");
+ }
return DECLINED;
}
}
@@ -439,6 +451,7 @@ static void * create_dir_conf(apr_pool_t * pool, char * dir) {
ifs_config * cfg = apr_pcalloc(pool, sizeof(ifs_config));
cfg->password_redact = -1;
cfg->clear_blacklisted = -1;
+ cfg->success_to_get = -1;
return cfg;
}
@@ -449,6 +462,7 @@ static void * merge_dir_conf(apr_pool_t * pool, void * base_void, void * add_voi
cfg->login_name = add->login_name ? add->login_name : base->login_name;
cfg->password_name = add->password_name ? add->password_name : base->password_name;
cfg->password_redact = add->password_redact >= 0 ? add->password_redact : base->password_redact;
+ cfg->success_to_get = add->success_to_get >= 0 ? add->success_to_get : base->success_to_get;
cfg->clear_blacklisted = add->clear_blacklisted >= 0 ? add->clear_blacklisted : base->clear_blacklisted;
cfg->pam_service = add->pam_service ? add->pam_service : base->pam_service;
if (add->login_blacklist) {
diff --git a/mod_intercept_form_submit.spec b/mod_intercept_form_submit.spec
index 8779510..0f123b4 100644
--- a/mod_intercept_form_submit.spec
+++ b/mod_intercept_form_submit.spec
@@ -7,7 +7,7 @@
Summary: Apache module to intercept login form submission and run PAM authentication
Name: mod_intercept_form_submit
-Version: 1.0.0
+Version: 1.0.1
Release: 1%{?dist}
License: ASL 2.0
Group: System Environment/Daemons
@@ -62,6 +62,9 @@ install -Dp -m 0644 intercept_form_submit.confx $RPM_BUILD_ROOT%{_httpd_confdir}
%{_httpd_moddir}/*.so
%changelog
+* Fri May 06 2016 Jan Pazdziora <jpazdziora@redhat.com> - 1.0.1-1
+- Add support for InterceptGETOnSuccess.
+
* Mon Mar 21 2016 Jan Pazdziora <jpazdziora@redhat.com> - 1.0.0-1
- 1319094 - the Requires(pre) httpd does not seem to be needed.