mod_intercept_form_submit
Apache module to intercept application's login form submission and run PAM authentication.
Download mod_intercept_form_submit-1.2.0.tar.gz, the latest release. See the source repository.
The module intercepts submission of application login forms. It retrieves the login and password information from the POST HTTP request, runs PAM authentication with those credentials, and sets the REMOTE_USER environment variable if the authentication passes. The internal r->user field is also set so other modules can use it (even if the module is invoked very late in the request processing).
If the REMOTE_USER is already set (presumably by some previous module), no authentication takes place.
If the PAM authentication fails, environment variable EXTERNAL_AUTH_ERROR is set to the string describing the error.
The assumption is that the application will be amended to trust the REMOTE_USER value if it is set and skip its own login/password validation.
Deployment
The following diagram shows typical form-based authentication with mod_intercept_form_submit deployed. Stroked-out items describe original behaviour without the module, underlined items are new actions with the module.
User | Browser | Apache | Application |
---|---|---|---|
1. User accesses application's URL: http://app.example.com/hosts | |||
2. Browser issues HTTP GET request to app.exmple.com for /hosts | |||
- - - GET /hosts - - -> | |||
3. Apache runs or hands the request over to application | |||
4. Application does not find valid session cookie | |||
5. Application redirects the browser to logon page | |||
<- - - 302 Location /login?back=/hosts - - - | |||
6. Browser accesses the logon page /login | |||
- - - GET /login?back=/hosts - - -> | |||
7. Apache runs or hands the request over to application | |||
8. Application does not see POST with login & password | |||
9. Application returns logon form | |||
<- - - 200 + page with logon form, action set back to /login - - - | |||
10. User fills in the login and password and hits "Log in" | |||
11. Browser submits the form | |||
- - - POST /login - - -> | |||
|
|||
12.1. Module mod_intercept_form_submit gets invoked | |||
12.2. Module parses the post data, finds the login & password, and runs pam_authenticate | |||
12.3. If login not in InterceptFormLoginSkip, runs pam_authenticate | |||
12.4. If login in InterceptFormLoginSkip and InterceptFormClearRemoteUserForSkipped on, clears possible existing REMOTE_USER / r->user | |||
12.5. If InterceptFormPasswordRedact on, replaces the password in the POST data with [REDACTED] | |||
12.6. If pam_authenticate passes, module sets the REMOTE_USER environment variable and r->user | |||
12.7. If pam_authenticate passes and mod_lookup_identity loaded, it gets called | |||
12.8. (orig 12) Apache runs or hands the request over to application | |||
|
|||
13.1. Application gets run | |||
13.2. When it sees REMOTE_USER, it trusts it | |||
13.3. (orig 13) Otherwise it validates the login & password; if they are not valid, go to 9 with message "Bad login or password" | |||
14. Application creates session, returns session cookies | |||
<- - - 302 Location /hosts with Set-Cookie - - - | |||
15. Like 2, now with Cookie set | |||
- - - GET /hosts - - -> | |||
16. Apache runs or hands the request over to application | |||
17. Application sees valid session cookie, returns the page | |||
<- - - 200 + the /hosts page that user wanted to see - - - |
Module configuration
Module mod_authnz_pam needs to be installed and loaded with
LoadModule authnz_pam_module modules/mod_authnz_pam.sobecause mod_intercept_form_submit uses it to do the actual PAM operations.
The mod_intercept_form_submit module needs to be configured for Location that the application uses to process the login form POST requests. The configuration has to specify three values:
- InterceptFormPAMService name_of_the_PAM_service
- The PAM service to authenticate against.
- InterceptFormLogin the_login_field_name
- Name of the login field in the login form, and thus the login parameter in the POST request.
- InterceptFormPassword the_password_field_name
- Name of the password field in the login form, and thus the password parameter in the POST request.
All three parameters above need to be specified or the interception will not be enabled.
Optional parameters:
- InterceptFormLoginSkip one_login [or_more_logins]
-
List of logins to ignore (never attempt to authenticate).
By default authentication will be attempted for all logins.
- InterceptFormClearRemoteUserForSkipped on|off
-
When set to on and authentication is skipped for users listed with InterceptFormLoginSkip, clears r->user and REMOTE_USER.
Default is off.
- InterceptFormPasswordRedact on|off
-
When set to on and authentication is attempted (no matter if it passes or fails), the value of the password will be modified in the POST data to string [REDACTED].
Default is off.
- InterceptFormLoginRealms REALM1 [other REALM2]
-
List of realm/domain names to append to the login and try in cycle when the login does not contain the '@' sign. This can be used for force particular realms without users being forced to enter them. Empty string can be used in the list to explicitly try authentication without any realm.
This can be used with mod_auth_kerb's (default) KrbMethodK5Passwd Off to present login names including realms to web applications.
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 LoadModule authnz_pam_module modules/mod_authnz_pam.so <Location /users/login> InterceptFormPAMService http_application_sss InterceptFormLogin login[login] InterceptFormPassword login[password] InterceptFormLoginSkip admin InterceptFormClearRemoteUserForSkipped on InterceptFormPasswordRedact on InterceptFormLoginRealms EXAMPLE.COM LAB.EXAMPLE.COM '' InterceptGETOnSuccess on </Location>
The PAM service needs to be configured. For the above shown http_application_sss example, file /etc/pam.d/http_application_sss could be created with content
auth required pam_sss.so account required pam_sss.soto authenticate against sssd.
On SELinux enabled systems, boolean allow_httpd_mod_auth_pam needs to be enabled:
setsebool -P allow_httpd_mod_auth_pam 1
Building from sources
When building from sources, command
apxs -i -a -c mod_intercept_form_submit.c -Wall -pedanticshould build and install the module.
Dependency on mod_authnz_pam
Module mod_intercept_form_submit has soft (runtime) dependency on
function pam_authenticate_with_login_password with prototype
This function is typically provided by module mod_authnz_pam, and is
called to achieve the actual authentication via the PAM stack. When
mod_authnz_pam is not loaded and thus this function not available,
error
authn_status pam_authenticate_with_login_password(
request_rec * r, const char * pam_service,
const char * login, const char * password,
int steps
);
mod_intercept_form_submit: pam_authenticate_with_login_password not found; perhaps mod_authnz_pam is not loadedis logged and authentication does not take place.
License
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. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.