httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From minf...@apache.org
Subject svn commit: r646285 - in /httpd/httpd/trunk: CHANGES docs/manual/mod/mod_auth_form.xml modules/aaa/config.m4 modules/aaa/mod_auth_form.c
Date Wed, 09 Apr 2008 11:46:48 GMT
Author: minfrin
Date: Wed Apr  9 04:46:46 2008
New Revision: 646285

URL: http://svn.apache.org/viewvc?rev=646285&view=rev
Log:
mod_auth_form: Add a module capable of allowing end users to log
in using an HTML form, storing the credentials within mod_session.

Added:
    httpd/httpd/trunk/docs/manual/mod/mod_auth_form.xml   (with props)
    httpd/httpd/trunk/modules/aaa/mod_auth_form.c   (with props)
Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/modules/aaa/config.m4

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=646285&r1=646284&r2=646285&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Wed Apr  9 04:46:46 2008
@@ -2,6 +2,10 @@
 Changes with Apache 2.3.0
 [ When backported to 2.2.x, remove entry from this file ]
 
+  *) mod_auth_form: Add a module capable of allowing end users to log
+     in using an HTML form, storing the credentials within mod_session.
+     [Graham Leggett]
+
   *) Add a function to the http filters that is able to parse an HTML
      form request with the type of application/x-www-form-urlencoded.
      [Graham Leggett]

Added: httpd/httpd/trunk/docs/manual/mod/mod_auth_form.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_auth_form.xml?rev=646285&view=auto
==============================================================================
--- httpd/httpd/trunk/docs/manual/mod/mod_auth_form.xml (added)
+++ httpd/httpd/trunk/docs/manual/mod/mod_auth_form.xml Wed Apr  9 04:46:46 2008
@@ -0,0 +1,719 @@
+<?xml version="1.0"?>
+<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
+<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
+<!-- $LastChangedRevision: 634760 $ -->
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+
+<modulesynopsis metafile="mod_auth_form.xml.meta">
+
+<name>mod_auth_form</name>
+<description>Form authentication</description>
+<status>Base</status>
+<sourcefile>mod_auth_form.c</sourcefile>
+<identifier>auth_form_module</identifier>
+
+<summary>
+    <note type="warning"><title>Warning</title>
+      <p>Form authentication depends on the <module>mod_session</module>
+      modules, and these modules make use of HTTP cookies, and as such can fall
+      victim to Cross Site Scripting attacks, or expose potentially private
+      information to clients. Please ensure that the relevant risks have
+      been taken into account before enabling the session functionality on
+      your server.</p>
+    </note>
+
+    <p>This module allows the use of an HTML login form to restrict access
+    by looking up users in the given providers. HTML forms require
+    significantly more configuration than the alternatives, however an
+    HTML login form can provide a much friendlier experience for end users.
+    </p>
+
+    <p>HTTP Basic authentication is provided by
+    <module>mod_auth_basic</module>, and HTTP Digest Authentication is
+    provided by <module>mod_auth_digest</module>.  This module should
+    usually be combined with at least one authentication module
+    such as <module>mod_authn_file</module> and one authorization
+    module such as <module>mod_authz_user</module>.</p>
+
+    <p>Once the user has been successfully authenticated, the user's login
+    details will be stored in a suitably configured <strong>session</strong>,
+    as provided by the <module>mod_session</module> module.</p>
+    
+</summary>
+<seealso><module>mod_session</module></seealso>
+<seealso><directive module="mod_authn_core">AuthName</directive></seealso>
+<seealso><directive module="mod_authn_core">AuthType</directive></seealso>
+<seealso><directive module="mod_authz_core">Require</directive></seealso>
+<seealso><directive module="mod_authz_core">Reject</directive></seealso>
+<seealso><directive module="mod_access_compat">Satisfy</directive> (Deprecated)</seealso>
+<seealso><directive module="mod_authz_core">&lt;SatisfyAll&gt;</directive></seealso>
+<seealso><directive module="mod_authz_core">&lt;SatisfyOne&gt;</directive></seealso>
+<seealso><a href="../howto/auth.html">Authentication howto</a></seealso>
+
+    <section id="basicconfig"><title>Basic Configuration</title>
+    
+      <p>To protect a particular URL with <module>mod_auth_form</module>, you need to
+      decide where you will store your <var>session</var>, and you will need to
+      decide what method you will use to authenticate. In this simple example, the
+      login details will be stored in a session based on
+      <module>mod_session_cookie</module>, and authentication will be attempted against
+      a file using <module>mod_authn_file</module>. If authentication is unsuccessful,
+      the user will be redirected to the form login page.</p>
+      
+      <example><title>Basic example</title>
+        AuthFormProvider file<br />
+        AuthUserFile conf/passwd<br />
+        AuthType form<br />
+        AuthName realm<br />
+        AuthFormLoginRequiredLocation http://example.com/login.html<br />
+        Session On<br />
+        SessionCookieName session path=/<br />
+        SessionCryptoPassphrase secret<br />
+      </example>
+      
+      <p>The directive <directive module="mod_authn_core">AuthType</directive> will enable
+      the <module>mod_auth_form</module> authentication when set to the value <var>form</var>.
+      The directives <directive module="mod_auth_form">AuthFormProvider</directive> and
+      <directive module="mod_authn_file">AuthUserFile</directive> specify that usernames
+      and passwords should be checked against the chosen file.</p>
+
+      <p>The directives <directive module="mod_session">Session</directive>, 
+      <directive module="mod_session_cookie">SessionCookieName</directive> and
+      <directive module="mod_session_crypto">SessionCryptoPassphrase</directive> create an
+      encrypted session stored within an HTTP cookie on the browser. For more information
+      on the different options for configuring a session, read the documentation for
+      <module>mod_session</module>.</p>
+
+      <p>In the simple example above, a URL has been protected by
+      <module>mod_auth_form</module>, but the user has yet to be given an opportunity to
+      enter their username and password. Options for doing so include providing a
+      dedicated standalone login page for this purpose, or for providing the login
+      page inline.</p>
+    </section>
+    
+    <section id="standalone"><title>Standalone Login</title>
+
+      <p>The login form can be hosted as a standalone page, or can be provided inline on
+      the same page.</p>
+      
+      <p>When configuring the login as a standalone page, unsuccessful authentication
+      attempts should be redirected to a login form created by the website for this purpose,
+      using the <directive module="mod_auth_form">AuthFormLoginRequiredLocation</directive>
+      directive. Typically this login page will contain an HTML form, asking the user to
+      provide their usename and password.</p>
+      
+      <example><title>Example login form</title>
+        &lt;form method="POST" action="/dologin.html"&gt;<br />
+        Username: &lt;input type="text" name="httpd_username" value="" /&gt;<br />
+        Password: &lt;input type="password" name="httpd_password" value="" /&gt;<br />
+        &lt;input type="submit" name="login" value="Login" /&gt;<br />
+        &lt;/form&gt;<br />
+      </example>
+
+      <p>The part that does the actual login is handled by the <var>form-login-handler</var>.
+      The action of the form should point at this handler, which is configured within
+      Apache as follows:</p>
+      
+      <example><title>Form login handler example</title>
+        &lt;Location /dologin.html&gt;
+        <indent>
+          SetHandler form-login-handler<br />
+          AuthFormLoginRequiredLocation http://example.com/login.html<br />
+          AuthFormLoginSuccessLocation http://example.com/success.html<br />
+          AuthFormProvider file<br />
+          AuthUserFile conf/passwd<br />
+          AuthType form<br />
+          AuthName realm<br />
+          Session On<br />
+          SessionCookieName session path=/<br />
+          SessionCryptoPassphrase secret<br />
+        </indent>
+        &lt;/Location&gt;
+      </example>
+
+      <p>The URLs specified by the
+      <directive module="mod_auth_form">AuthFormLoginRequiredLocation</directive> directive will typically
+      point to a page explaining to the user that their login attempt was unsuccessful, and they
+      should try again, while the <directive module="mod_auth_form">AuthFormLoginSuccessLocation</directive>
+      directive specifies the URL the user should be redirected to on success.</p>
+      
+      <p>Alternatively, the URL to redirect the user to on success can be embedded within the login
+      form, as in the example below. As a result, the same <var>form-login-handler</var> can be
+      reused for different areas of a website.</p>
+
+      <example><title>Example login form with location</title>
+        &lt;form method="POST" action="/dologin.html"&gt;<br />
+        <indent>
+          Username: &lt;input type="text" name="httpd_username" value="" /&gt;<br />
+          Password: &lt;input type="password" name="httpd_password" value="" /&gt;<br />
+          &lt;input type="submit" name="login" value="Login" /&gt;<br />
+          &lt;input type="hidden" name="httpd_location" value="http://example.com/success.html" /&gt;<br />
+        </indent>
+        &lt;/form&gt;<br />
+      </example>
+
+    </section>
+
+    <section id="inline"><title>Inline Login</title>
+    
+      <note type="warning"><title>Warning</title>
+        <p>A risk exists that under certain circumstances, the login form configured 
+        using inline login may be submitted more than once, revealing login credentials to
+        the application running underneath. The administrator must ensure that the underlying
+        application is properly secured to prevent abuse. If in doubt, use the
+        standalone login configuration.</p>
+      </note>
+
+      <p>As an alternative to having a dedicated login page for a website, it is possible to
+      configure <module>mod_auth_form</module> to authenticate users inline, without being
+      redirected to another page. This allows the state of the current page to be preserved
+      during the login attempt. This can be useful in a situation where a time limited
+      session is in force, and the session times out in the middle of the user request. The
+      user can be re-authenticated in place, and they can continue where they left off.</p>
+
+      <p>When a page protected by <module>mod_auth_form</module> is accessed, and the user is
+      not logged in, and no <directive module="mod_auth_form">AuthFormLoginRequiredLocation</directive>
+      directive is specified as described in the section above, an <var>HTTP_UNAUTHORIZED</var>
+      status code is returned to the browser in the normal way indicating to the user that
+      they are not authorised to view the page.</p>
+      
+      <p>To configure inline authentication, the administrator overrides the error document
+      returned by the <var>HTTP_UNAUTHORIZED</var> status code with a custom error document,
+      containing the login form, as follows.</p>
+
+      <example><title>Basic inline example</title>
+        AuthFormProvider file<br />
+        <strong>ErrorDocument 401 /login.shtml</strong><br />
+        AuthUserFile conf/passwd<br />
+        AuthType form<br />
+        AuthName realm<br />
+        AuthFormLoginRequiredLocation http://example.com/login.html<br />
+        Session On<br />
+        SessionCookieName session path=/<br />
+        SessionCryptoPassphrase secret<br />
+      </example>
+      
+      <p>The error document file should contain the login form used to log in, as
+      per the example below. The key difference in this form is that the HTML
+      form action is left blank. This has the effect of submitting the form to
+      the original protected URL, without the page having to know what that
+      URL is.</p>
+
+      <example><title>Example inline login form</title>
+        &lt;form method="POST" <strong>action=""</strong>&gt;<br />
+        <indent>
+          Username: &lt;input type="text" name="httpd_username" value="" /&gt;<br />
+          Password: &lt;input type="password" name="httpd_password" value="" /&gt;<br />
+          &lt;input type="submit" name="login" value="Login" /&gt;<br />
+        </indent>
+        &lt;/form&gt;<br />
+      </example>
+
+      <p>When the end user has filled in their login details, the form will make
+      an HTTP POST request to the original password protected URL.
+      <module>mod_auth_form</module> will intercept this POST request, and if
+      HTML fields are found present for the username and password, the user
+      will be logged in, and the original password protected URL will be returned
+      to the user as a GET request.</p>
+
+    </section>
+
+    <section id="inlinepreservebody"><title>Inline Login with Body Preservation</title>
+
+      <p>A limitation of the inline login technique described above is that should an
+      HTML form POST have resulted in the request to authenticate or reauthentiate, the
+      contents of the original form posted by the browser will be lost. Depending on
+      the function of the website, this could present significant inconvenience for the
+      end user.</p>
+
+      <p><module>mod_auth_form</module> addresses this by allowing the method and body
+      of the original request to be embedded in the login form, and if authentication
+      is successful, the original method and body will be retried by Apache, preserving
+      the state of the original request.</p>
+
+      <p>To enable body preservation, add three additional fields to the login form as
+      per the example below.</p>
+
+      <example><title>Example with body preservation</title>
+        &lt;form method="POST" action=""&gt;<br />
+        <indent>
+          Username: &lt;input type="text" name="httpd_username" value="" /&gt;<br />
+          Password: &lt;input type="password" name="httpd_password" value="" /&gt;<br />
+          &lt;input type="submit" name="login" value="Login" /&gt;<br />
+          <strong>&lt;input type="hidden" name="httpd_method" value="POST" /&gt;<br />
+          &lt;input type="hidden" name="httpd_mimetype" value="application/x-www-form-urlencoded" /&gt;<br />
+          &lt;input type="hidden" name="httpd_body" value="name1=value1&amp;name2=value2" /&gt;</strong><br />
+        </indent>
+        &lt;/form&gt;
+      </example>
+
+      <p>How the method, mimetype and body of the original request are embedded within the
+      login form will depend on the platform and technology being used within the website.
+      </p>
+
+      <p>One option is to use the <module>mod_include</module> module along with the
+      <directive module="core">KeptBodySize</directive> directive, along with a suitable
+      CGI script, to embed the variables in the form.</p>
+      
+      <p>Another option is to render the login form using a CGI script or other dynamic
+      technology.</p>
+
+      <example><title>CGI example</title>
+        AuthFormProvider file<br />
+        <strong>ErrorDocument 401 /cgi-bin/login.cgi</strong><br />
+        ...<br />
+      </example>
+
+    </section>
+
+    <section id="loggingout"><title>Logging Out</title>
+
+      <p>To enable a user to log out of a particular session, configure a page to
+      be handled by the <var>form-logout-handler</var>. Any attempt to access this
+      URL will cause the username and password to be removed from the current
+      session, effectively logging the user out.</p>
+
+      <p>By setting the
+      <directive module="mod_auth_form">AuthFormLogoutLocation</directive> directive,
+      a URL can be specified that the browser will be redirected to on successful
+      logout. This URL might explain to the user that they have been logged out, and
+      give the user the option to log in again.</p>
+
+      <example><title>Basic logout example</title>
+        SetHandler form-logout-handler<br />
+        AuthName realm<br />
+        AuthFormLogoutLocation http://example.com/loggedout.html<br />
+        Session On<br />
+        SessionCookieName session path=/<br />
+        SessionCryptoPassphrase secret<br />
+      </example>
+
+      <p>Note that logging a user out does not delete the session, it merely removes
+      the username and password from the session. If this results in an empty session,
+      the nett effect will be the removal of that session, but this is not
+      guaranteed. If you want to guarantee the removal of a session, set the
+      <directive module="mod_session">SessionMaxAge</directive> directive to a small
+      value, like 1. (Setting the directive to zero would mean no session age limit).
+      </p>
+
+      <example><title>Basic session expiry example</title>
+        SetHandler form-logout-handler<br />
+        AuthFormLogoutLocation http://example.com/loggedout.html<br />
+        Session On<br />
+        SessionMaxAge 1<br />
+        SessionCookieName session path=/<br />
+        SessionCryptoPassphrase secret<br />
+      </example>
+
+    </section>
+
+<directivesynopsis>
+<name>AuthFormProvider</name>
+<description>Sets the authentication provider(s) for this location</description>
+<syntax>AuthFormProvider <var>provider-name</var>
+[<var>provider-name</var>] ...</syntax>
+<default>AuthFormProvider file</default>
+<contextlist><context>directory</context><context>.htaccess</context>
+</contextlist>
+<override>AuthConfig</override>
+
+<usage>
+    <p>The <directive>AuthFormProvider</directive> directive sets 
+    which provider is used to authenticate the users for this location.
+    The default <code>file</code> provider is implemented
+    by the <module>mod_authn_file</module> module.  Make sure
+    that the chosen provider module is present in the server.</p>
+
+    <example><title>Example</title>
+      &lt;Location /secure&gt;<br />
+      <indent>
+        AuthType form<br />
+        AuthName "private area"<br />
+        AuthFormProvider  dbm<br />
+        AuthDBMType        SDBM<br />
+        AuthDBMUserFile    /www/etc/dbmpasswd<br />
+        Require            valid-user<br />
+        ...<br />
+      </indent>
+      &lt;/Location&gt;
+    </example>
+
+    <p>Providers are implemented by <module>mod_authn_dbm</module>,
+    <module>mod_authn_file</module>, <module>mod_authn_dbd</module>,
+    and <module>mod_authnz_ldap</module>.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormAuthoritative</name>
+<description>Sets whether authorization and authentication are passed to
+lower level modules</description>
+<syntax>AuthFormAuthoritative On|Off</syntax>
+<default>AuthFormAuthoritative On</default>
+<contextlist><context>directory</context><context>.htaccess</context>
+</contextlist>
+<override>AuthConfig</override>
+
+<usage>
+    <p>Normally, each authorization module listed in <directive
+    module="mod_auth_form">AuthFormProvider</directive> will attempt
+    to verify the user, and if the user is not found in any provider,
+    access will be denied. Setting the
+    <directive>AuthFormAuthoritative</directive> directive explicitly
+    to <code>Off</code> allows for both authentication and
+    authorization to be passed on to other non-provider-based modules
+    if there is <strong>no userID</strong> or <strong>rule</strong>
+    matching the supplied userID.  This should only be necessary when
+    combining <module>mod_auth_form</module> with third-party modules
+    that are not configured with the <directive
+    module="mod_auth_form">AuthFormProvider</directive>
+    directive.  When using such modules, the order of processing
+    is determined in the modules' source code and is not configurable.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormUsername</name>
+<description>The name of a form field carrying the login username</description>
+<syntax>AuthFormUsername <var>fieldname</var></syntax>
+<default>httpd_username</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormUsername</directive> directive specifies
+    the name of an HTML field which, if present, will contain the username to be used to log
+    in.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormPassword</name>
+<description>The name of a form field carrying the login password</description>
+<syntax>AuthFormPassword <var>fieldname</var></syntax>
+<default>httpd_password</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormPassword</directive> directive specifies
+    the name of an HTML field which, if present, will contain the password to be used to log
+    in.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormLocation</name>
+<description>The name of a form field carrying a URL to redirect to on successful login</description>
+<syntax>AuthFormLocation <var>fieldname</var></syntax>
+<default>httpd_location</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormLocation</directive> directive specifies
+    the name of an HTML field which, if present, will contain a URL to redirect the browser to
+    should login be successful.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormMethod</name>
+<description>The name of a form field carrying the method of the request to attempt on successful login</description>
+<syntax>AuthFormMethod <var>fieldname</var></syntax>
+<default>httpd_method</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormMethod</directive> directive specifies
+    the name of an HTML field which, if present, will contain the method of the request to
+    to submit should login be successful.</p>
+    
+    <p>By populating the form with fields described by
+    <directive module="mod_auth_form">AuthFormMethod</directive>, 
+    <directive module="mod_auth_form">AuthFormMimetype</directive> and
+    <directive module="mod_auth_form">AuthFormBody</directive>, a website can retry
+    a request that may have been interrupted by the login screen, or by a session
+    timeout.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormMimetype</name>
+<description>The name of a form field carrying the mimetype of the body of the request to attempt on successful login</description>
+<syntax>AuthFormMimetype <var>fieldname</var></syntax>
+<default>httpd_mimetype</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormMethod</directive> directive specifies
+    the name of an HTML field which, if present, will contain the method of the request to
+    to submit should login be successful.</p>
+
+    <p>By populating the form with fields described by
+    <directive module="mod_auth_form">AuthFormMethod</directive>, 
+    <directive module="mod_auth_form">AuthFormMimetype</directive> and
+    <directive module="mod_auth_form">AuthFormBody</directive>, a website can retry
+    a request that may have been interrupted by the login screen, or by a session
+    timeout.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormBody</name>
+<description>The name of a form field carrying the body of the request to attempt on successful login</description>
+<syntax>AuthFormBody <var>fieldname</var></syntax>
+<default>httpd_body</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormMethod</directive> directive specifies
+    the name of an HTML field which, if present, will contain the method of the request to
+    to submit should login be successful.</p>
+
+    <p>By populating the form with fields described by
+    <directive module="mod_auth_form">AuthFormMethod</directive>, 
+    <directive module="mod_auth_form">AuthFormMimetype</directive> and
+    <directive module="mod_auth_form">AuthFormBody</directive>, a website can retry
+    a request that may have been interrupted by the login screen, or by a session
+    timeout.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormSize</name>
+<description>The largest size of the form in bytes that will be parsed for the login details</description>
+<syntax>AuthFormBody <var>size</var></syntax>
+<default>8192</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormSize</directive> directive specifies
+    the maximum size of the body of the request that will be parsed to find the login form.</p>
+    
+    <p>If a login request arrives that exceeds this size, the whole request will be aborted
+    with the HTTP response code <code>HTTP_REQUEST_TOO_LARGE</code>.</p>
+
+    <p>If you have populated the form with fields described by
+    <directive module="mod_auth_form">AuthFormMethod</directive>, 
+    <directive module="mod_auth_form">AuthFormMimetype</directive> and
+    <directive module="mod_auth_form">AuthFormBody</directive>, you probably want to set this
+    field to a similar size as the <directive module="core">KeptBodySize</directive>
+    directive.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormLoginRequiredLocation</name>
+<description>The URL of the page to be redirected to should login be required</description>
+<syntax>AuthFormLoginRequiredLocation <var>url</var></syntax>
+<default>none</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormLoginRequiredLocation</directive> directive
+    specifies the URL to redirect to should the user not be authorised to view a page. By default,
+    if a user is not authorised to view a page, the HTTP response code <code>HTTP_UNAUTHORIZED</code>
+    will be returned with the page specified by the
+    <directive module="mod_core">ErrorDocument</directive> directive. This directive overrides this
+    default.</p>
+    
+    <p>Use this directive if you have a dedicated login page to redirect users to.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormLoginSuccessLocation</name>
+<description>The URL of the page to be redirected to should login be successful</description>
+<syntax>AuthFormLoginSuccessLocation <var>url</var></syntax>
+<default>none</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormLoginSuccessLocation</directive> directive
+    specifies the URL to redirect to should the user have logged in successfully. This directive
+    can be overridden if a form field has been defined containing another URL using the
+    <directive module="mod_auth_form">AuthFormLocation</directive> directive.</p>
+    
+    <p>Use this directive if you have a dedicated login URL, and you have not embedded the
+    destination page in the login form.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormLogoutLocation</name>
+<description>The URI of the page on the server to redirect to after a user has logged out</description>
+<syntax>AuthFormLogoutLocation <var>uri</var></syntax>
+<default>none</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormLogoutLocation</directive> directive
+    specifies the URI of a page on the server to redirect to internally should the user
+    attempt log out.</p>
+    
+    <p>When a URI is accessed that is served by the handler <code>form-logout-handler</code>,
+    the page specified by this directive will be shown to the end user. For example:</p>
+    
+    <example><title>Example</title>
+      &lt;Location /logout&gt;<br />
+      <indent>
+        SetHandler form-logout-handler<br />
+        AuthFormLogoutLocation /logout.html<br />
+        Session on<br />
+        ...
+      </indent>
+      &lt;/Location&gt;
+    </example>
+    
+    <p>An attempt to access the URI <var>/logout/</var> will result in the user being logged
+    out, and the page <var>/logout.html</var> will be displayed. Make sure that the page
+    <var>logout.html</var> is not password protected, otherwise the page will not be
+    displayed.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormFakeBasicAuth</name>
+<description>Fake a Basic Authentication header</description>
+<syntax>AuthFormFakeBasicAuth <var>On|Off</var></syntax>
+<default>AuthFormFakeBasicAuth Off</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormFakeBasicAuth</directive> flag
+    determines whether a <code>Basic Authentication</code> header will be added to
+    the request headers. This can be used to expose the username and password to
+    an underlying application, without the underlying application having to be aware
+    of how the login was achieved.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormLogoutLocation</name>
+<description>The URL to redirect to after a user has logged out</description>
+<syntax>AuthFormLogoutLocation <var>uri</var></syntax>
+<default>none</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormLogoutLocation</directive> directive
+    specifies the URL of a page on the server to redirect to should the user attempt to log out.</p>
+
+    <p>When a URI is accessed that is served by the handler <code>form-logout-handler</code>,
+    the page specified by this directive will be shown to the end user. For example:</p>
+    
+    <example><title>Example</title>
+      &lt;Location /logout&gt;<br />
+      <indent>
+        SetHandler form-logout-handler<br />
+        AuthFormLogoutLocation http://example.com/loggedout.html<br />
+        Session on<br />
+        ...
+      </indent>
+      &lt;/Location&gt;
+    </example>
+    
+    <p>An attempt to access the URI <var>/logout/</var> will result in the user being logged
+    out, and the page <var>/logout.html</var> will be displayed. Make sure that the page
+    <var>logout.html</var> is not password protected, otherwise the page will not be
+    displayed.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormDisableNoStore</name>
+<description>Disable the CacheControl no-store header on the login page</description>
+<syntax>AuthFormDisableNoStore <var>On|Off</var></syntax>
+<default>AuthFormDisableNoStore Off</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormDisableNoStore</directive> flag
+    disables the sending of a <code>Cache-Control no-store</code> header with the
+    error 401 page returned when the user is not yet logged in. The purpose of the header
+    is to make it difficult for an ecmascript application to attempt to resubmit the
+    login form, and reveal the username and password to the backend application. Disable
+    at your own risk.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>AuthFormSitePassphrase</name>
+<description>Bypass authentication checks for high traffic sites</description>
+<syntax>AuthFormSitePassphrase <var>secret</var></syntax>
+<default>none</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive module="mod_auth_form">AuthFormSitePassphrase</directive> directive
+    specifies a passphrase which, if present in the user session, causes Apache to
+    bypass authentication checks for the given URL. It can be used on high traffic websites
+    to reduce the load induced on authentication infrastructure.</p>
+    
+    <p>The passphrase can be inserted into a user session by adding this directive to the
+    configuration for the <var>form-login-handler</var>. The <var>form-login-handler</var>
+    itself will always run the authentication checks, regardless of whether a passphrase
+    is specified or not.</p>
+
+    <note type="warning"><title>Warning</title>
+      <p>If the session is exposed to the user through the use of
+      <module>mod_session_cookie</module>, and the session is not protected with
+      <module>mod_session_crypto</module>, the passphrase is open to potential exposure
+      through a dictionary attack. Regardless of how the session is configured,
+      ensure that this directive is not used within URL spaces where private user data
+      could be exposed, or sensitive transactions can be conducted. Use at own risk.</p>
+    </note>
+
+</usage>
+</directivesynopsis>
+
+</modulesynopsis>

Propchange: httpd/httpd/trunk/docs/manual/mod/mod_auth_form.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: httpd/httpd/trunk/modules/aaa/config.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/config.m4?rev=646285&r1=646284&r2=646285&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/aaa/config.m4 (original)
+++ httpd/httpd/trunk/modules/aaa/config.m4 Wed Apr  9 04:46:46 2008
@@ -56,6 +56,7 @@
 dnl these are the front-end authentication modules
 
 APACHE_MODULE(auth_basic, basic authentication, , , yes)
+APACHE_MODULE(auth_form, form authentication, , , yes)
 APACHE_MODULE(auth_digest, RFC2617 Digest authentication, , , most, [
   APR_CHECK_APR_DEFINE(APR_HAS_RANDOM)
   if test $ac_cv_define_APR_HAS_RANDOM = "no"; then

Added: httpd/httpd/trunk/modules/aaa/mod_auth_form.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_auth_form.c?rev=646285&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/aaa/mod_auth_form.c (added)
+++ httpd/httpd/trunk/modules/aaa/mod_auth_form.c Wed Apr  9 04:46:46 2008
@@ -0,0 +1,1133 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+#include "apr_strings.h"
+#include "apr_md5.h"                /* for apr_password_validate */
+#include "apr_lib.h"                /* for apr_isspace */
+#include "apr_base64.h"             /* for apr_base64_decode et al */
+#define APR_WANT_STRFUNC            /* for strcasecmp */
+#include "apr_want.h"
+
+#include "ap_config.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_request.h"
+#include "ap_provider.h"
+#include "util_md5.h"
+
+#include "mod_auth.h"
+#include "mod_session.h"
+
+#define LOG_PREFIX "mod_auth_form: "
+#define FORM_LOGIN_HANDLER "form-login-handler"
+#define FORM_LOGOUT_HANDLER "form-logout-handler"
+#define FORM_REDIRECT_HANDLER "form-redirect-handler"
+#define MOD_AUTH_FORM_HASH "site"
+
+static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL;
+static void (*ap_session_get_fn) (request_rec * r, session_rec * z,
+                                  const char *key, const char **value) = NULL;
+static void (*ap_session_set_fn) (request_rec * r, session_rec * z,
+                                  const char *key, const char *value) = NULL;
+
+typedef struct {
+    authn_provider_list *providers;
+    char *dir;
+    int authoritative;
+    int authoritative_set;
+    const char *site;
+    int site_set;
+    const char *username;
+    int username_set;
+    const char *password;
+    int password_set;
+    apr_off_t form_size;
+    int form_size_set;
+    int fakebasicauth;
+    int fakebasicauth_set;
+    const char *location;
+    int location_set;
+    const char *method;
+    int method_set;
+    const char *mimetype;
+    int mimetype_set;
+    const char *body;
+    int body_set;
+    int disable_no_store;
+    int disable_no_store_set;
+    const char *loginsuccess;
+    int loginsuccess_set;
+    const char *loginrequired;
+    int loginrequired_set;
+    const char *logout;
+    int logout_set;
+} auth_form_config_rec;
+
+static void *create_auth_form_dir_config(apr_pool_t * p, char *d)
+{
+    auth_form_config_rec *conf = apr_pcalloc(p, sizeof(*conf));
+
+    conf->dir = d;
+    /* Any failures are fatal. */
+    conf->authoritative = 1;
+
+    /* form size defaults to 8k */
+    conf->form_size = HUGE_STRING_LEN;
+
+    /* default form field names */
+    conf->username = "httpd_username";
+    conf->password = "httpd_password";
+    conf->location = "httpd_location";
+    conf->method = "httpd_method";
+    conf->mimetype = "httpd_mimetype";
+    conf->body = "httpd_body";
+    
+    return conf;
+}
+
+static void *merge_auth_form_dir_config(apr_pool_t * p, void *basev, void *addv)
+{
+    auth_form_config_rec *new = (auth_form_config_rec *) apr_pcalloc(p, sizeof(auth_form_config_rec));
+    auth_form_config_rec *add = (auth_form_config_rec *) addv;
+    auth_form_config_rec *base = (auth_form_config_rec *) basev;
+
+    new->providers = !add->providers ? base->providers : add->providers;
+    new->authoritative = (add->authoritative_set == 0) ? base->authoritative : add->authoritative;
+    new->authoritative_set = add->authoritative_set || base->authoritative_set;
+    new->site = (add->site_set == 0) ? base->site : add->site;
+    new->site_set = add->site_set || base->site_set;
+    new->username = (add->username_set == 0) ? base->username : add->username;
+    new->username_set = add->username_set || base->username_set;
+    new->password = (add->password_set == 0) ? base->password : add->password;
+    new->password_set = add->password_set || base->password_set;
+    new->location = (add->location_set == 0) ? base->location : add->location;
+    new->location_set = add->location_set || base->location_set;
+    new->form_size = (add->form_size_set == 0) ? base->form_size : add->form_size;
+    new->form_size_set = add->form_size_set || base->form_size_set;
+    new->fakebasicauth = (add->fakebasicauth_set == 0) ? base->fakebasicauth : add->fakebasicauth;
+    new->fakebasicauth_set = add->fakebasicauth_set || base->fakebasicauth_set;
+    new->method = (add->method_set == 0) ? base->method : add->method;
+    new->method_set = add->method_set || base->method_set;
+    new->mimetype = (add->mimetype_set == 0) ? base->mimetype : add->mimetype;
+    new->mimetype_set = add->mimetype_set || base->mimetype_set;
+    new->body = (add->body_set == 0) ? base->body : add->body;
+    new->body_set = add->body_set || base->body_set;
+    new->disable_no_store = (add->disable_no_store_set == 0) ? base->disable_no_store : add->disable_no_store;
+    new->disable_no_store_set = add->disable_no_store_set || base->disable_no_store_set;
+    new->loginsuccess = (add->loginsuccess_set == 0) ? base->loginsuccess : add->loginsuccess;
+    new->loginsuccess_set = add->loginsuccess_set || base->loginsuccess_set;
+    new->loginrequired = (add->loginrequired_set == 0) ? base->loginrequired : add->loginrequired;
+    new->loginrequired_set = add->loginrequired_set || base->loginrequired_set;
+    new->logout = (add->logout_set == 0) ? base->logout : add->logout;
+    new->logout_set = add->logout_set || base->logout_set;
+
+    return new;
+}
+
+static const char *add_authn_provider(cmd_parms * cmd, void *config,
+                                           const char *arg)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    authn_provider_list *newp;
+
+    newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list));
+    newp->provider_name = apr_pstrdup(cmd->pool, arg);
+
+    /* lookup and cache the actual provider now */
+    newp->provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP,
+                                        newp->provider_name, "0");
+
+    if (newp->provider == NULL) {
+        /*
+         * by the time they use it, the provider should be loaded and
+         * registered with us.
+         */
+        return apr_psprintf(cmd->pool,
+                            "Unknown Authn provider: %s",
+                            newp->provider_name);
+    }
+
+    if (!newp->provider->check_password) {
+        /* if it doesn't provide the appropriate function, reject it */
+        return apr_psprintf(cmd->pool,
+                            "The '%s' Authn provider doesn't support "
+                            "Form Authentication", newp->provider_name);
+    }
+
+    if (!ap_session_load_fn || !ap_session_get_fn || !ap_session_set_fn) {
+        ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load);
+        ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get);
+        ap_session_set_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_set);
+        if (!ap_session_load_fn || !ap_session_get_fn || !ap_session_set_fn) {
+            return "You must load mod_session to enable the mod_auth_form "
+                "functions";
+        }
+    }
+
+    /* Add it to the list now. */
+    if (!conf->providers) {
+        conf->providers = newp;
+    }
+    else {
+        authn_provider_list *last = conf->providers;
+
+        while (last->next) {
+            last = last->next;
+        }
+        last->next = newp;
+    }
+
+    return NULL;
+}
+
+/**
+ * Sanity check a given string that it exists, is not empty,
+ * and does not contain special characters.
+ */
+static const char *check_string(cmd_parms * cmd, const char *string)
+{
+    if (!string || !*string || ap_strchr_c(string, '=') || ap_strchr_c(string, '&')) {
+        return apr_pstrcat(cmd->pool, cmd->directive->directive,
+                           " cannot be empty, or contain '=' or '&'.",
+                           NULL);
+    }
+    return NULL;
+}
+
+static const char *set_cookie_form_location(cmd_parms * cmd, void *config, const char *location)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->location = location;
+    conf->location_set = 1;
+    return check_string(cmd, location);
+}
+
+static const char *set_cookie_form_username(cmd_parms * cmd, void *config, const char *username)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->username = username;
+    conf->username_set = 1;
+    return check_string(cmd, username);
+}
+
+static const char *set_cookie_form_password(cmd_parms * cmd, void *config, const char *password)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->password = password;
+    conf->password_set = 1;
+    return check_string(cmd, password);
+}
+
+static const char *set_cookie_form_method(cmd_parms * cmd, void *config, const char *method)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->method = method;
+    conf->method_set = 1;
+    return check_string(cmd, method);
+}
+
+static const char *set_cookie_form_mimetype(cmd_parms * cmd, void *config, const char *mimetype)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->mimetype = mimetype;
+    conf->mimetype_set = 1;
+    return check_string(cmd, mimetype);
+}
+
+static const char *set_cookie_form_body(cmd_parms * cmd, void *config, const char *body)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->body = body;
+    conf->body_set = 1;
+    return check_string(cmd, body);
+}
+
+static const char *set_cookie_form_size(cmd_parms * cmd, void *config,
+                                             const char *arg)
+{
+    auth_form_config_rec *conf = config;
+
+    if (APR_SUCCESS != apr_strtoff(&(conf->form_size), arg, NULL, 0)
+        || conf->form_size < 0) {
+        return "AuthCookieFormSize must be a size in bytes, or zero.";
+    }
+    conf->form_size_set = 1;
+
+    return NULL;
+}
+
+static const char *set_login_required_location(cmd_parms * cmd, void *config, const char *loginrequired)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->loginrequired = loginrequired;
+    conf->loginrequired_set = 1;
+    return NULL;
+}
+
+static const char *set_login_success_location(cmd_parms * cmd, void *config, const char *loginsuccess)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->loginsuccess = loginsuccess;
+    conf->loginsuccess_set = 1;
+    return NULL;
+}
+
+static const char *set_logout_location(cmd_parms * cmd, void *config, const char *logout)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->logout = logout;
+    conf->logout_set = 1;
+    return NULL;
+}
+
+static const char *set_site_passphrase(cmd_parms * cmd, void *config, const char *site)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->site = site;
+    conf->site_set = 1;
+    return NULL;
+}
+
+static const char *set_authoritative(cmd_parms * cmd, void *config, int flag)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->authoritative = flag;
+    conf->authoritative_set = 1;
+    return NULL;
+}
+
+static const char *set_fake_basic_auth(cmd_parms * cmd, void *config, int flag)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->fakebasicauth = flag;
+    conf->fakebasicauth_set = 1;
+    return NULL;
+}
+
+static const char *set_disable_no_store(cmd_parms * cmd, void *config, int flag)
+{
+    auth_form_config_rec *conf = (auth_form_config_rec *) config;
+    conf->disable_no_store = flag;
+    conf->disable_no_store_set = 1;
+    return NULL;
+}
+
+static const command_rec auth_form_cmds[] =
+{
+    AP_INIT_ITERATE("AuthFormProvider", add_authn_provider, NULL, OR_AUTHCFG,
+                    "specify the auth providers for a directory or location"),
+    AP_INIT_TAKE1("AuthFormUsername", set_cookie_form_username, NULL, OR_AUTHCFG,
+                  "The field of the login form carrying the username"),
+    AP_INIT_TAKE1("AuthFormPassword", set_cookie_form_password, NULL, OR_AUTHCFG,
+                  "The field of the login form carrying the password"),
+    AP_INIT_TAKE1("AuthFormLocation", set_cookie_form_location, NULL, OR_AUTHCFG,
+                  "The field of the login form carrying the URL to redirect on "
+                  "successful login."),
+    AP_INIT_TAKE1("AuthFormMethod", set_cookie_form_method, NULL, OR_AUTHCFG,
+                  "The field of the login form carrying the original request method."),
+    AP_INIT_TAKE1("AuthFormMimetype", set_cookie_form_mimetype, NULL, OR_AUTHCFG,
+                  "The field of the login form carrying the original request mimetype."),
+    AP_INIT_TAKE1("AuthFormBody", set_cookie_form_body, NULL, OR_AUTHCFG,
+                  "The field of the login form carrying the urlencoded original request "
+                  "body."),
+    AP_INIT_TAKE1("AuthFormSize", set_cookie_form_size, NULL, ACCESS_CONF,
+                  "Maximum size of body parsed by the form parser"),
+    AP_INIT_TAKE1("AuthFormLoginRequiredLocation", set_login_required_location,
+                  NULL, OR_AUTHCFG,
+                  "If set, redirect the browser to this URL rather than "
+                  "return 401 Not Authorized."),
+    AP_INIT_TAKE1("AuthFormLoginSuccessLocation", set_login_success_location,
+                  NULL, OR_AUTHCFG,
+                  "If set, redirect the browser to this URL when a login "
+                  "processed by the login handler is successful."),
+    AP_INIT_TAKE1("AuthFormLogoutLocation", set_logout_location,
+                  NULL, OR_AUTHCFG,
+                  "The URL of the logout successful page. An attempt to access an "
+                  "URL handled by the handler " FORM_LOGOUT_HANDLER " will result "
+                  "in an redirect to this page after logout."),
+    AP_INIT_TAKE1("AuthFormSitePassphrase", set_site_passphrase,
+                  NULL, OR_AUTHCFG,
+                  "If set, use this passphrase to determine whether the user should "
+                  "be authenticated. Bypasses the user authentication check on "
+                  "every website hit, and is useful for high traffic sites."),
+    AP_INIT_FLAG("AuthFormAuthoritative", set_authoritative,
+                 NULL, OR_AUTHCFG,
+                 "Set to 'Off' to allow access control to be passed along to "
+                 "lower modules if the UserID is not known to this module"),
+    AP_INIT_FLAG("AuthFormFakeBasicAuth", set_fake_basic_auth,
+                 NULL, OR_AUTHCFG,
+                 "Set to 'On' to pass through authentication to the rest of the "
+                 "server as a basic authentication header."),
+    AP_INIT_FLAG("AuthFormDisableNoStore", set_disable_no_store,
+                 NULL, OR_AUTHCFG,
+                 "Set to 'on' to stop the sending of a Cache-Control no-store header with "
+                 "the login screen. This allows the browser to cache the credentials, but "
+                 "at the risk of it being possible for the login form to be resubmitted "
+                 "and revealed to the backend server through XSS. Use at own risk."),
+    {NULL}
+};
+
+module AP_MODULE_DECLARE_DATA auth_form_module;
+
+/* These functions return 0 if client is OK, and proper error status
+ * if not... either HTTP_UNAUTHORIZED, if we made a check, and it failed, or
+ * HTTP_INTERNAL_SERVER_ERROR, if things are so totally confused that we
+ * couldn't figure out how to tell if the client is authorized or not.
+ *
+ * If they return DECLINED, and all other modules also decline, that's
+ * treated by the server core as a configuration error, logged and
+ * reported as such.
+ */
+
+static void note_cookie_auth_failure(request_rec * r)
+{
+    auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config,
+                                                      &auth_form_module);
+
+    if (conf->location && ap_strchr_c(conf->location, ':')) {
+        apr_table_setn(r->err_headers_out, "Location", conf->location);
+    }
+}
+
+/**
+ * Set the auth username and password into the main request
+ * notes table.
+ */
+static void set_notes_auth(request_rec * r,
+                                const char *user, const char *pw,
+                                const char *method, const char *mimetype)
+{
+    apr_table_t *notes = NULL;
+    const char *authname;
+
+    /* find the main request */
+    while (r->main) {
+        r = r->main;
+    }
+    /* find the first redirect */
+    while (r->prev) {
+        r = r->prev;
+    }
+    notes = r->notes;
+
+    /* have we isolated the user and pw before? */
+    authname = ap_auth_name(r);
+    if (user) {
+        apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-user", NULL), user);
+    }
+    if (pw) {
+        apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-pw", NULL), pw);
+    }
+    if (method) {
+        apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-method", NULL), method);
+    }
+    if (mimetype) {
+        apr_table_setn(notes, apr_pstrcat(r->pool, authname, "-mimetype", NULL), mimetype);
+    }
+
+}
+
+/**
+ * Get the auth username and password from the main request
+ * notes table, if present.
+ */
+static void get_notes_auth(request_rec * r,
+                           const char **user, const char **pw,
+                           const char **method, const char **mimetype)
+{
+    const char *authname;
+
+    /* find the main request */
+    while (r->main) {
+        r = r->main;
+    }
+    /* find the first redirect */
+    while (r->prev) {
+        r = r->prev;
+    }
+
+    /* have we isolated the user and pw before? */
+    authname = ap_auth_name(r);
+    if (user) {
+        *user = (char *) apr_table_get(r->notes, apr_pstrcat(r->pool, authname, "-user", NULL));
+    }
+    if (pw) {
+        *pw = (char *) apr_table_get(r->notes, apr_pstrcat(r->pool, authname, "-pw", NULL));
+    }
+    if (method) {
+        *method = (char *) apr_table_get(r->notes, apr_pstrcat(r->pool, authname, "-method", NULL));
+    }
+    if (mimetype) {
+        *mimetype = (char *) apr_table_get(r->notes, apr_pstrcat(r->pool, authname, "-mimetype", NULL));
+    }
+
+}
+
+/**
+ * Set the auth username and password into the session.
+ *
+ * If either the username, or the password are NULL, the username
+ * and/or password will be removed from the session.
+ */
+static apr_status_t set_session_auth(request_rec * r,
+                                     const char *user, const char *pw, const char *site)
+{
+    const char *hash = NULL;
+    const char *authname = ap_auth_name(r);
+    session_rec *z = NULL;
+
+    if (site) {
+        hash = ap_md5(r->pool,
+                      (unsigned char *) apr_pstrcat(r->pool, user, ":", site, NULL));
+    }
+
+    ap_session_load_fn(r, &z);
+    ap_session_set(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_USER, NULL), user);
+    ap_session_set(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_PW, NULL), pw);
+    ap_session_set(r, z, apr_pstrcat(r->pool, authname, "-" MOD_AUTH_FORM_HASH, NULL), hash);
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * Get the auth username and password from the main request
+ * notes table, if present.
+ */
+static apr_status_t get_session_auth(request_rec * r,
+                                     const char **user, const char **pw, const char **hash)
+{
+    const char *authname = ap_auth_name(r);
+    session_rec *z = NULL;
+    ap_session_load_fn(r, &z);
+
+    if (user) {
+        ap_session_get(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_USER, NULL), user);
+    }
+    if (pw) {
+        ap_session_get(r, z, apr_pstrcat(r->pool, authname, "-" MOD_SESSION_PW, NULL), pw);
+    }
+    if (hash) {
+        ap_session_get(r, z, apr_pstrcat(r->pool, authname, "-" MOD_AUTH_FORM_HASH, NULL), hash);
+    }
+
+    return APR_SUCCESS;
+
+}
+
+/**
+ * Isolate the username and password in a POSTed form with the
+ * username in the "username" field, and the password in the
+ * "password" field.
+ *
+ * If either the username or the password is missing, this
+ * function will return HTTP_UNAUTHORIZED.
+ *
+ * The location field is considered optional, and will be returned
+ * if present.
+ */
+static int get_form_auth(request_rec * r,
+                             const char *username,
+                             const char *password,
+                             const char *location,
+                             const char *method,
+                             const char *mimetype,
+                             const char *body,
+                             const char **sent_user,
+                             const char **sent_pw,
+                             const char **sent_loc,
+                             const char **sent_method,
+                             const char **sent_mimetype,
+                             auth_form_config_rec * conf)
+{
+    /* sanity check - are we a POST request? */
+
+    /* find the username and password in the form */
+    apr_array_header_t *pairs = NULL;
+    apr_off_t len;
+    apr_size_t size;
+    apr_bucket_brigade *kept_body = NULL;
+
+    /* have we isolated the user and pw before? */
+    get_notes_auth(r, sent_user, sent_pw, sent_method, sent_mimetype);
+    if (*sent_user && *sent_pw) {
+        return OK;
+    }
+
+    int res = ap_parse_request_form(r, &pairs, -1, conf->form_size);
+    if (res != OK) {
+        return res;
+    }
+    while (pairs && !apr_is_empty_array(pairs)) {
+        ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
+        if (username && !strcmp(pair->name, username) && sent_user) {
+            apr_brigade_length(pair->value, 1, &len);
+            char *buffer = apr_palloc(r->pool, len + 1);
+            size = (apr_size_t) len;
+            apr_brigade_flatten(pair->value, buffer, &size);
+            buffer[len] = 0;
+            *sent_user = buffer;
+        }
+        else if (password && !strcmp(pair->name, password) && sent_pw) {
+            apr_brigade_length(pair->value, 1, &len);
+            char *buffer = apr_palloc(r->pool, len + 1);
+            size = (apr_size_t) len;
+            apr_brigade_flatten(pair->value, buffer, &size);
+            buffer[len] = 0;
+            *sent_pw = buffer;
+        }
+        else if (location && !strcmp(pair->name, location) && sent_loc) {
+            apr_brigade_length(pair->value, 1, &len);
+            char *buffer = apr_palloc(r->pool, len + 1);
+            size = (apr_size_t) len;
+            apr_brigade_flatten(pair->value, buffer, &size);
+            buffer[len] = 0;
+            *sent_loc = buffer;
+        }
+        else if (method && !strcmp(pair->name, method) && sent_method) {
+            apr_brigade_length(pair->value, 1, &len);
+            char *buffer = apr_palloc(r->pool, len + 1);
+            size = (apr_size_t) len;
+            apr_brigade_flatten(pair->value, buffer, &size);
+            buffer[len] = 0;
+            *sent_method = buffer;
+        }
+        else if (mimetype && !strcmp(pair->name, mimetype) && sent_mimetype) {
+            apr_brigade_length(pair->value, 1, &len);
+            char *buffer = apr_palloc(r->pool, len + 1);
+            size = (apr_size_t) len;
+            apr_brigade_flatten(pair->value, buffer, &size);
+            buffer[len] = 0;
+            *sent_mimetype = buffer;
+        }
+        else if (body && !strcmp(pair->name, body)) {
+            kept_body = pair->value;
+        }
+    }
+
+    /* set the user, even though the user is unauthenticated at this point */
+    if (*sent_user) {
+        r->user = (char *) *sent_user;
+    }
+
+    /* a missing username or missing password means auth denied */
+    if (!sent_user || !*sent_user || !sent_pw || !*sent_pw) {
+        return HTTP_UNAUTHORIZED;
+    }
+
+    /* was a body specified? */
+    if (kept_body && sent_mimetype && *sent_mimetype) {
+        apr_off_t length = 0;
+
+        /*
+         * replace the body, the content-type of the body, and the
+         * content-length of the body specified in the form to the current
+         * request. This is safe because in order to get here at all, the
+         * existing body must already be completely read in.
+         */
+        apr_table_set(r->headers_in, "Content-Type", *sent_mimetype);
+        apr_brigade_length(kept_body, 1, &length);
+        apr_table_set(r->headers_in, "Content-Length", apr_off_t_toa(r->pool, length));
+        r->kept_body = kept_body;
+
+    }
+
+    /*
+     * save away the username, password, mimetype and method, so that they
+     * are available should the auth need to be run again.
+     */
+    set_notes_auth(r, *sent_user, *sent_pw, *sent_method, *sent_mimetype);
+
+    return OK;
+}
+
+/**
+ * Given a username and site passphrase hash from the session, determine
+ * whether the site passphrase is valid for this session.
+ * 
+ * If the site passphrase is NULL, or if the sent_hash is NULL, this
+ * function returns DECLINED.
+ * 
+ * If the site passphrase hash does not match the sent hash, this function
+ * returns AUTH_USER_NOT_FOUND.
+ * 
+ * On success, returns OK.
+ */
+static int check_site(request_rec * r, const char *site, const char *sent_user, const char *sent_hash)
+{
+
+    if (site && sent_user && sent_hash) {
+        const char *hash = ap_md5(r->pool,
+                      (unsigned char *) apr_pstrcat(r->pool, sent_user, ":", site, NULL));
+        
+//        if (APR_SUCCESS == apr_password_validate(apr_pstrcat(r->pool, sent_user, ":", site, NULL),
+//                                                 sent_hash)) {
+        if (!strcmp(sent_hash, hash)) {
+            return OK;
+        }
+        else {
+            return AUTH_USER_NOT_FOUND;
+        }
+    }
+
+    return DECLINED;
+
+}
+
+/**
+ * Given a username and password (extracted externally from a cookie), run
+ * the authnz hooks to determine whether this request is authorized.
+ *
+ * Return an HTTP code.
+ */
+static int check_auth(request_rec * r, const char *sent_user, const char *sent_pw)
+{
+    authn_status auth_result;
+    authn_provider_list *current_provider;
+    auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config,
+                                                      &auth_form_module);
+
+    current_provider = conf->providers;
+    do {
+        const authn_provider *provider;
+
+        /*
+         * For now, if a provider isn't set, we'll be nice and use the file
+         * provider.
+         */
+        if (!current_provider) {
+            provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP,
+                                          AUTHN_DEFAULT_PROVIDER, "0");
+
+            if (!provider || !provider->check_password) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX
+                              "no authn provider configured");
+                auth_result = AUTH_GENERAL_ERROR;
+                break;
+            }
+            apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER);
+        }
+        else {
+            provider = current_provider->provider;
+            apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name);
+        }
+
+        if (!sent_user || !sent_pw) {
+            auth_result = AUTH_USER_NOT_FOUND;
+            break;
+        }
+
+        auth_result = provider->check_password(r, sent_user, sent_pw);
+
+        apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+
+        /* Something occured. Stop checking. */
+        if (auth_result != AUTH_USER_NOT_FOUND) {
+            break;
+        }
+
+        /* If we're not really configured for providers, stop now. */
+        if (!conf->providers) {
+            break;
+        }
+
+        current_provider = current_provider->next;
+    } while (current_provider);
+
+    if (auth_result != AUTH_GRANTED) {
+        int return_code;
+
+        /* If we're not authoritative, then any error is ignored. */
+        if (!(conf->authoritative) && auth_result != AUTH_DENIED) {
+            return DECLINED;
+        }
+
+        switch (auth_result) {
+        case AUTH_DENIED:
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX
+                          "user '%s': authentication failure for \"%s\": "
+                          "password Mismatch",
+                          sent_user, r->uri);
+            return_code = HTTP_UNAUTHORIZED;
+            break;
+        case AUTH_USER_NOT_FOUND:
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX
+                          "user '%s' not found: %s", sent_user, r->uri);
+            return_code = HTTP_UNAUTHORIZED;
+            break;
+        case AUTH_GENERAL_ERROR:
+        default:
+            /*
+             * We'll assume that the module has already said what its error
+             * was in the logs.
+             */
+            return_code = HTTP_INTERNAL_SERVER_ERROR;
+            break;
+        }
+
+        /* If we're returning 403, tell them to try again. */
+        if (return_code == HTTP_UNAUTHORIZED) {
+            note_cookie_auth_failure(r);
+        }
+
+/* TODO: Flag the user somehow as to the reason for the failure */
+
+        return return_code;
+    }
+
+    return OK;
+
+}
+
+/* fake the basic authentication header if configured to do so */
+static void fake_basic_authentication(request_rec *r, auth_form_config_rec *conf,
+                                      const char *user, const char *pw)
+{
+    if (conf->fakebasicauth) {
+        char *basic = apr_pstrcat(r->pool, user, ":", pw, NULL);
+        apr_size_t size = (apr_size_t) strlen(basic);
+        char *base64 = apr_palloc(r->pool,
+                                  apr_base64_encode_len(size + 1) * sizeof(char));
+        apr_base64_encode(base64, basic, size);
+        apr_table_set(r->headers_in, "Authorization",
+                      apr_pstrcat(r->pool, "Basic ", base64, NULL));
+    }
+}
+
+/**
+ * Must we use form authentication? If so, extract the cookie and run
+ * the authnz hooks to determine if the login is valid.
+ *
+ * If the login is not valid, a 401 Not Authorized will be returned. It
+ * is up to the webmaster to ensure this screen displays a suitable login
+ * form to give the user the opportunity to log in.
+ */
+static int authenticate_form_user(request_rec * r)
+{
+    auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config,
+                                                      &auth_form_module);
+    const char *sent_user = NULL, *sent_pw = NULL, *sent_loc = NULL, *sent_method = NULL,
+        *sent_mimetype = NULL, *sent_hash = NULL;
+    const char *current_auth = NULL;
+    apr_status_t res;
+    int rv = HTTP_UNAUTHORIZED;
+    int rv2 = HTTP_UNAUTHORIZED;
+
+    /* Are we configured to be Form auth? */
+    current_auth = ap_auth_type(r);
+    if (!current_auth || strcasecmp(current_auth, "form")) {
+        return DECLINED;
+    }
+
+    /*
+     * XSS security warning: using cookies to store private data only works
+     * when the administrator has full control over the source website. When
+     * in forward-proxy mode, websites are public by definition, and so can
+     * never be secure. Abort the auth attempt in this case.
+     */
+    if (PROXYREQ_PROXY == r->proxyreq) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR,
+                      0, r, LOG_PREFIX "form auth cannot be used for proxy "
+                      "requests due to XSS risk, access denied: %s", r->uri);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    /* We need an authentication realm. */
+    if (!ap_auth_name(r)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR,
+                      0, r, LOG_PREFIX "need AuthName: %s", r->uri);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    r->ap_auth_type = (char *) current_auth;
+
+    /* try get the username and password from a session, if present */
+    res = get_session_auth(r, &sent_user, &sent_pw, &sent_hash);
+
+    /* first test whether the site passphrase matches */
+    if (APR_SUCCESS == res && sent_user && sent_hash && sent_pw) {
+        rv = check_site(r, conf->site, sent_user, sent_hash);
+        if (OK == rv) {
+            fake_basic_authentication(r, conf, sent_user, sent_pw);
+            return OK;
+        }
+    }
+
+    /* otherwise test for a normal password match */
+    if (APR_SUCCESS == res && sent_user && sent_pw) {
+        rv = check_auth(r, sent_user, sent_pw);
+        if (OK == rv) {
+            fake_basic_authentication(r, conf, sent_user, sent_pw);
+            return OK;
+        }
+    }
+
+    /*
+     * If we reach this point, the request should fail with access denied,
+     * except for one potential scenario:
+     *
+     * If the request is a POST, and the posted form contains user defined fields
+     * for a username and a password, and the username and password are correct,
+     * then return the response obtained by a GET to this URL.
+     *
+     * If an additional user defined location field is present in the form,
+     * instead of a GET of the current URL, redirect the browser to the new
+     * location.
+     *
+     * As a further option, if the user defined fields for the type of request,
+     * the mime type of the body of the request, and the body of the request
+     * itself are present, replace this request with a new request of the given
+     * type and with the given body.
+     *
+     * Otherwise access is denied.
+     */
+    if (r->method_number == M_POST) {
+        rv2 = get_form_auth(r, conf->username, conf->password, conf->location,
+                            conf->method, conf->mimetype, conf->body,
+                            &sent_user, &sent_pw, &sent_loc, &sent_method,
+                            &sent_mimetype, conf);
+        if (OK == rv2) {
+            rv = check_auth(r, sent_user, sent_pw);
+            if (OK == rv) {
+                fake_basic_authentication(r, conf, sent_user, sent_pw);
+                set_session_auth(r, sent_user, sent_pw, conf->site);
+            }
+        }
+    }
+
+    /*
+     * did the admin prefer to be redirected to the login page on failure
+     * instead?
+     */
+    if (HTTP_UNAUTHORIZED == rv && conf->loginrequired) {
+        apr_table_set(r->headers_out, "Location", conf->loginrequired);
+        return HTTP_MOVED_PERMANENTLY;
+    }
+
+    /* did the user ask to be redirected on login success? */
+    if (sent_loc) {
+        apr_table_set(r->headers_out, "Location", sent_loc);
+        rv = HTTP_MOVED_PERMANENTLY;
+    }
+
+    /*
+     * If the user has submitted a sent method along with their form, switch
+     * in the redirect handler. The redirect handler will replace the form
+     * login request with the request given inside the login form.
+     */
+    if (OK == rv) {
+        if (sent_method && sent_mimetype && r->kept_body) {
+            r->handler = FORM_REDIRECT_HANDLER;
+        }
+        else if (sent_method || sent_mimetype || r->kept_body) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR,
+             0, r, LOG_PREFIX "the login form must contain a field for all "
+                          "three of the method, mimetype and body for the original request "
+                          "to be redirected, reverting to GET: %s", r->uri);
+        }
+    }
+
+    /*
+     * potential security issue: if we return a login to the browser, we must
+     * send a no-store to make sure a well behaved browser will not try and
+     * send the login details a second time if the back button is pressed.
+     * 
+     * if the user has full control over the backend, the
+     * AuthCookieDisableNoStore can be used to turn this off.
+     */
+    if (HTTP_UNAUTHORIZED == rv && !conf->disable_no_store) {
+        apr_table_addn(r->headers_out, "Cache-Control", "no-store");
+        apr_table_addn(r->err_headers_out, "Cache-Control", "no-store");
+    }
+
+    return rv;
+
+}
+
+/**
+ * Handle a login attempt.
+ *
+ * If the login session is either missing or form authnz is unsuccessful, a
+ * 401 Not Authorized will be returned to the browser. The webmaster
+ * is expected to insert a login form into the 401 Not Authorized
+ * error screen.
+ *
+ * If the webmaster wishes, they can point the form submission at this
+ * handler, which will redirect the user to the correct page on success.
+ * On failure, the 401 Not Authorized error screen will be redisplayed,
+ * where the login attempt can be repeated.
+ *
+ */
+static int authenticate_form_login_handler(request_rec * r)
+{
+
+    auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config,
+                                                      &auth_form_module);
+
+    const char *sent_user = NULL, *sent_pw = NULL, *sent_loc = NULL;
+    int rv;
+
+    if (strcmp(r->handler, FORM_LOGIN_HANDLER)) {
+        return DECLINED;
+    }
+
+    if (r->method_number != M_POST) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX
+          "the " FORM_LOGIN_HANDLER " only supports the POST method for %s",
+                      r->uri);
+        return HTTP_METHOD_NOT_ALLOWED;
+    }
+
+    rv = get_form_auth(r, conf->username, conf->password, conf->location,
+                       NULL, NULL, NULL,
+                       &sent_user, &sent_pw, &sent_loc,
+                       NULL, NULL, conf);
+    if (OK == rv) {
+        rv = check_auth(r, sent_user, sent_pw);
+        if (OK == rv) {
+            set_session_auth(r, sent_user, sent_pw, conf->site);
+            if (sent_loc) {
+                apr_table_set(r->headers_out, "Location", sent_loc);
+                return HTTP_MOVED_PERMANENTLY;
+            }
+            if (conf->loginsuccess) {
+                apr_table_set(r->headers_out, "Location", conf->loginsuccess);
+                return HTTP_MOVED_PERMANENTLY;
+            }
+            return HTTP_OK;
+        }
+    }
+
+    /* did we prefer to be redirected to the login page on failure instead? */
+    if (HTTP_UNAUTHORIZED == rv && conf->loginrequired) {
+        apr_table_set(r->headers_out, "Location", conf->loginrequired);
+        return HTTP_MOVED_PERMANENTLY;
+    }
+
+    return rv;
+
+}
+
+/**
+ * Handle a logout attempt.
+ *
+ * If an attempt is made to access this URL, any username and password
+ * embedded in the session is deleted.
+ *
+ * This has the effect of logging the person out.
+ *
+ * If a logout URI has been specified, this function will create an
+ * internal redirect to this page.
+ */
+static int authenticate_form_logout_handler(request_rec * r)
+{
+
+    auth_form_config_rec *conf = ap_get_module_config(r->per_dir_config,
+                                                      &auth_form_module);
+
+    if (strcmp(r->handler, FORM_LOGOUT_HANDLER)) {
+        return DECLINED;
+    }
+
+    /* remove the username and password, effectively logging the user out */
+    set_session_auth(r, NULL, NULL, NULL);
+
+    /*
+     * make sure the logout page is never cached - otherwise the logout won't
+     * work!
+     */
+    apr_table_addn(r->headers_out, "Cache-Control", "no-store");
+    apr_table_addn(r->err_headers_out, "Cache-Control", "no-store");
+
+    /* if set, internal redirect to the logout page */
+    if (conf->logout) {
+        apr_table_addn(r->headers_out, "Location", conf->logout);
+        return HTTP_TEMPORARY_REDIRECT;
+    }
+
+    return HTTP_OK;
+
+}
+
+/**
+ * Handle a redirect attempt.
+ *
+ * If during a form login, the method, mimetype and request body are
+ * specified, this handler will ensure that this request is included
+ * as an internal redirect.
+ *
+ */
+static int authenticate_form_redirect_handler(request_rec * r)
+{
+
+    request_rec *rr = NULL;
+    const char *sent_method = NULL, *sent_mimetype = NULL;
+
+    if (strcmp(r->handler, FORM_REDIRECT_HANDLER)) {
+        return DECLINED;
+    }
+
+    /* get the method and mimetype from the notes */
+    get_notes_auth(r, NULL, NULL, &sent_method, &sent_mimetype);
+
+    if (r->kept_body && sent_method && sent_mimetype) {
+
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, LOG_PREFIX
+          "internal redirect to method '%s' and body mimetype '%s' for the "
+                      "uri: %s", sent_method, sent_mimetype, r->uri);
+
+        rr = ap_sub_req_method_uri(sent_method, r->uri, r, r->output_filters);
+        r->status = ap_run_sub_req(rr);
+
+    }
+    else {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX
+        "internal redirect requested but one or all of method, mimetype or "
+                      "body are NULL: %s", r->uri);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    /* return the underlying error, or OK on success */
+    return r->status == HTTP_OK || r->status == OK ? OK : r->status;
+
+}
+
+static void register_hooks(apr_pool_t * p)
+{
+#if AP_MODULE_MAGIC_AT_LEAST(20080403,1)
+    ap_hook_check_authn(authenticate_form_user, NULL, NULL, APR_HOOK_MIDDLE,
+                        AP_AUTH_INTERNAL_PER_CONF);
+#else
+    ap_hook_check_user_id(authenticate_form_user, NULL, NULL, APR_HOOK_MIDDLE);
+#endif
+    ap_hook_handler(authenticate_form_login_handler, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_handler(authenticate_form_logout_handler, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_handler(authenticate_form_redirect_handler, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA auth_form_module =
+{
+    STANDARD20_MODULE_STUFF,
+    create_auth_form_dir_config, /* dir config creater */
+    merge_auth_form_dir_config,  /* dir merger --- default is to override */
+    NULL,                        /* server config */
+    NULL,                        /* merge server config */
+    auth_form_cmds,              /* command apr_table_t */
+    register_hooks               /* register hooks */
+};

Propchange: httpd/httpd/trunk/modules/aaa/mod_auth_form.c
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message