diff options
45 files changed, 124 insertions, 11718 deletions
@@ -1,5 +1,8 @@ Changes with Apache 2.0.28 + *) Fix infinite loop in mod_cgid.c. + [Dale Ghent <daleg@elemental.org>, Brian Pane <bpane@pacbell.net>] + *) When no port is given in a "ServerName host" directive, the server_rec->port is now set to zero, not 80. That allows for run-time deduction of the correct server port (depending on @@ -23,6 +23,9 @@ you wish to try a threaded Apache on FreeBSD anyway, use "./configure --enable-threads". + * If you are building on Mac OS X (Darwin), make sure to + use libtool 1.4.2 or newer. + * If you are a developer building Apache directly from CVS, you will need to run ./buildconf before running configure. diff --git a/build/httpd_roll_release b/build/httpd_roll_release index 79d6208c8e..8fb8fd0ec5 100755 --- a/build/httpd_roll_release +++ b/build/httpd_roll_release @@ -39,7 +39,7 @@ echo "Updating the site's FAQ" # Now update the FAQ in the tarball rm -f docs/manual/faq/*.html -cp /www/www.apache.org/docs-2.0/faq/*.html docs/manual/faq/ +cp /www/httpd.apache.org/docs-2.0/faq/*.html docs/manual/faq/ # Create the configure scripts echo "Creating the configure script" diff --git a/docs/conf/httpd-std.conf b/docs/conf/httpd-std.conf index b31af5a393..93d7449816 100644 --- a/docs/conf/httpd-std.conf +++ b/docs/conf/httpd-std.conf @@ -217,7 +217,6 @@ Listen @@Port@@ # <IfModule !mpm_winnt.c> -<IfModule !beos.c> # # If you wish httpd to run as a different user or group, you must run # httpd as root initially and it will switch. @@ -232,7 +231,7 @@ Listen @@Port@@ # User nobody Group #-1 -</IfModule> # !mpm_winnt.c && beos.c # +</IfModule> # # ServerAdmin: Your address, where problems with the server should be diff --git a/docs/manual/bind.html.en b/docs/manual/bind.html.en deleted file mode 100644 index d587810315..0000000000 --- a/docs/manual/bind.html.en +++ /dev/null @@ -1,75 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Setting which addresses and ports Apache uses</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Setting which addresses and ports Apache - uses</h1> - - <p>When Apache starts, it connects to some port and address on - the local machine and waits for incoming requests. By default, - it listens to all addresses on the machine. However, it needs to - be told to listen to specific ports, or to listen to only selected - addresses, or a combination. This is often combined with the - Virtual Host feature which determines how Apache responds to - different IP addresses, hostnames and ports.</p> - - <p>The <code>Listen</code> directive tells the server to accept - incoming requests only on the specified port or - address-and-port combinations. If only a port number is - specified in the <code>Listen</code> directive, the server - listens to the given port on all interfaces. If an IP address - is given as well as a port, the server will listen on the given - port and interface. Multiple Listen directives may be used to - specify a number of addresses and ports to listen to. The - server will respond to requests from any of the listed - addresses and ports.</p> - - <p>For example, to make the server accept connections on both - port 80 and port 8000, use:</p> -<pre> - Listen 80 - Listen 8000 -</pre> - To make the server accept connections on two specified - interfaces and port numbers, use -<pre> - Listen 192.170.2.1:80 - Listen 192.170.2.5:8000 -</pre> - - <h2>How this works with Virtual Hosts</h2> - - <p>Listen does not implement Virtual Hosts. It only tells the - main server what addresses and ports to listen to. If no - <VirtualHost> directives are used, the server will behave - the same for all accepted requests. However, - <VirtualHost> can be used to specify a different behavior - for one or more of the addresses and ports. To implement a - VirtualHost, the server must first be told to listen to the - address and port to be used. Then a <VirtualHost> section - should be created for a specified address and port to set the - behavior of this virtual host. Note that if the - <VirtualHost> is set for an address and port that the - server is not listening to, it cannot be accessed.</p> - - <h2>See also</h2> - See also the documentation on <a - href="mod/mpm_common.html#listen">Listen directive</a>, <a - href="vhosts/">Virtual Hosts</a>, <a - href="dns-caveats.html">DNS Issues</a> and <a - href="mod/core.html#virtualhost"><VirtualHost> - section</a>. <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/cgi_path.html.en b/docs/manual/cgi_path.html.en deleted file mode 100644 index 4ed74ade20..0000000000 --- a/docs/manual/cgi_path.html.en +++ /dev/null @@ -1,98 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>PATH_INFO Changes in the CGI Environment</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">PATH_INFO Changes in the CGI - Environment</h1> - <hr /> - - <h2><a id="over" name="over">Overview</a></h2> - - <p>As implemented in Apache 1.1.1 and earlier versions, the - method Apache used to create PATH_INFO in the CGI environment - was counterintuitive, and could result in crashes in certain - cases. In Apache 1.2 and beyond, this behavior has changed. - Although this results in some compatibility problems with - certain legacy CGI applications, the Apache 1.2 behavior is - still compatible with the CGI/1.1 specification, and CGI - scripts can be easily modified (<a href="#compat">see - below</a>).</p> - - <h2><a id="prob" name="prob">The Problem</a></h2> - - <p>Apache 1.1.1 and earlier implemented the PATH_INFO and - SCRIPT_NAME environment variables by looking at the filename, - not the URL. While this resulted in the correct values in many - cases, when the filesystem path was overloaded to contain path - information, it could result in errant behavior. For example, - if the following appeared in a config file:</p> -<pre> - Alias /cgi-ralph /usr/local/httpd/cgi-bin/user.cgi/ralph -</pre> - - <p>In this case, <code>user.cgi</code> is the CGI script, the - "/ralph" is information to be passed onto the CGI. If this - configuration was in place, and a request came for - "<code>/cgi-ralph/script/</code>", the code would set PATH_INFO - to "<code>/ralph/script</code>", and SCRIPT_NAME to - "<code>/cgi-</code>". Obviously, the latter is incorrect. In - certain cases, this could even cause the server to crash.</p> - - <h2><a id="solution" name="solution">The Solution</a></h2> - - <p>Apache 1.2 and later now determine SCRIPT_NAME and PATH_INFO - by looking directly at the URL, and determining how much of the - URL is client-modifiable, and setting PATH_INFO to it. To use - the above example, PATH_INFO would be set to - "<code>/script</code>", and SCRIPT_NAME to - "<code>/cgi-ralph</code>". This makes sense and results in no - server behavior problems. It also permits the script to be - guaranteed that - "<code>http://$SERVER_NAME:$SERVER_PORT$SCRIPT_NAME$PATH_INFO</code>" - will always be an accessible URL that points to the current - script, something which was not necessarily true with previous - versions of Apache.</p> - - <p>However, the "<code>/ralph</code>" information from the - <code>Alias</code> directive is lost. This is unfortunate, but - we feel that using the filesystem to pass along this sort of - information is not a recommended method, and a script making - use of it "deserves" not to work. Apache 1.2b3 and later, - however, do provide <a href="#compat">a workaround.</a></p> - - <h2><a id="compat" name="compat">Compatibility with Previous - Servers</a></h2> - - <p>It may be necessary for a script that was designed for - earlier versions of Apache or other servers to need the - information that the old PATH_INFO variable provided. For this - purpose, Apache 1.2 (1.2b3 and later) sets an additional - variable, FILEPATH_INFO. This environment variable contains the - value that PATH_INFO would have had with Apache 1.1.1.</p> - - <p>A script that wishes to work with both Apache 1.2 and - earlier versions can simply test for the existence of - FILEPATH_INFO, and use it if available. Otherwise, it can use - PATH_INFO. For example, in Perl, one might use:</p> -<pre> - $path_info = $ENV{'FILEPATH_INFO'} || $ENV{'PATH_INFO'}; -</pre> - - <p>By doing this, a script can work with all servers supporting - the CGI/1.1 specification, including all versions of - Apache.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/content-negotiation.html.en b/docs/manual/content-negotiation.html.en deleted file mode 100644 index b5af8bf892..0000000000 --- a/docs/manual/content-negotiation.html.en +++ /dev/null @@ -1,651 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Apache Content Negotiation</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Content Negotiation</h1> - - <p>Apache's support for content negotiation has been updated to - meet the HTTP/1.1 specification. It can choose the best - representation of a resource based on the browser-supplied - preferences for media type, languages, character set and - encoding. It is also implements a couple of features to give - more intelligent handling of requests from browsers which send - incomplete negotiation information.</p> - - <p>Content negotiation is provided by the <a - href="mod/mod_negotiation.html">mod_negotiation</a> module, - which is compiled in by default.</p> - <hr /> - - <h2>About Content Negotiation</h2> - - <p>A resource may be available in several different - representations. For example, it might be available in - different languages or different media types, or a combination. - One way of selecting the most appropriate choice is to give the - user an index page, and let them select. However it is often - possible for the server to choose automatically. This works - because browsers can send as part of each request information - about what representations they prefer. For example, a browser - could indicate that it would like to see information in French, - if possible, else English will do. Browsers indicate their - preferences by headers in the request. To request only French - representations, the browser would send</p> -<pre> - Accept-Language: fr -</pre> - - <p>Note that this preference will only be applied when there is - a choice of representations and they vary by language.</p> - - <p>As an example of a more complex request, this browser has - been configured to accept French and English, but prefer - French, and to accept various media types, preferring HTML over - plain text or other text types, and preferring GIF or JPEG over - other media types, but also allowing any other media type as a - last resort:</p> -<pre> - Accept-Language: fr; q=1.0, en; q=0.5 - Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, - image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1 -</pre> - Apache 1.2 supports 'server driven' content negotiation, as - defined in the HTTP/1.1 specification. It fully supports the - Accept, Accept-Language, Accept-Charset and Accept-Encoding - request headers. Apache 1.3.4 also supports 'transparent' - content negotiation, which is an experimental negotiation - protocol defined in RFC 2295 and RFC 2296. It does not offer - support for 'feature negotiation' as defined in these RFCs. - - <p>A <strong>resource</strong> is a conceptual entity - identified by a URI (RFC 2396). An HTTP server like Apache - provides access to <strong>representations</strong> of the - resource(s) within its namespace, with each representation in - the form of a sequence of bytes with a defined media type, - character set, encoding, etc. Each resource may be associated - with zero, one, or more than one representation at any given - time. If multiple representations are available, the resource - is referred to as <strong>negotiable</strong> and each of its - representations is termed a <strong>variant</strong>. The ways - in which the variants for a negotiable resource vary are called - the <strong>dimensions</strong> of negotiation.</p> - - <h2>Negotiation in Apache</h2> - - <p>In order to negotiate a resource, the server needs to be - given information about each of the variants. This is done in - one of two ways:</p> - - <ul> - <li>Using a type map (<em>i.e.</em>, a <code>*.var</code> - file) which names the files containing the variants - explicitly, or</li> - - <li>Using a 'MultiViews' search, where the server does an - implicit filename pattern match and chooses from among the - results.</li> - </ul> - - <h3>Using a type-map file</h3> - - <p>A type map is a document which is associated with the - handler named <code>type-map</code> (or, for - backwards-compatibility with older Apache configurations, the - mime type <code>application/x-type-map</code>). Note that to - use this feature, you must have a handler set in the - configuration that defines a file suffix as - <code>type-map</code>; this is best done with a</p> -<pre> - AddHandler type-map .var -</pre> - in the server configuration file. - - <p>Type map files should have the same name as the resource - which they are describing, and have an entry for each available - variant; these entries consist of contiguous HTTP-format header - lines. Entries for different variants are separated by blank - lines. Blank lines are illegal within an entry. It is - conventional to begin a map file with an entry for the combined - entity as a whole (although this is not required, and if - present will be ignored). An example map file is shown below. - This file would be named <code>foo.html</code>, as it describes - a resource named <code>foo</code>.</p> -<pre> - URI: foo - - URI: foo.en.html - Content-type: text/html - Content-language: en - - URI: foo.fr.de.html - Content-type: text/html;charset=iso-8859-2 - Content-language: fr, de -</pre> - Note also that a typemap file will take precedence over the - filename's extension, even when Multiviews is on. If the - variants have different source qualities, that may be indicated - by the "qs" parameter to the media type, as in this picture - (available as jpeg, gif, or ASCII-art): -<pre> - URI: foo - - URI: foo.jpeg - Content-type: image/jpeg; qs=0.8 - - URI: foo.gif - Content-type: image/gif; qs=0.5 - - URI: foo.txt - Content-type: text/plain; qs=0.01 -</pre> - - <p>qs values can vary in the range 0.000 to 1.000. Note that - any variant with a qs value of 0.000 will never be chosen. - Variants with no 'qs' parameter value are given a qs factor of - 1.0. The qs parameter indicates the relative 'quality' of this - variant compared to the other available variants, independent - of the client's capabilities. For example, a jpeg file is - usually of higher source quality than an ascii file if it is - attempting to represent a photograph. However, if the resource - being represented is an original ascii art, then an ascii - representation would have a higher source quality than a jpeg - representation. A qs value is therefore specific to a given - variant depending on the nature of the resource it - represents.</p> - - <p>The full list of headers recognized is:</p> - - <dl> - <dt><code>URI:</code></dt> - - <dd>uri of the file containing the variant (of the given - media type, encoded with the given content encoding). These - are interpreted as URLs relative to the map file; they must - be on the same server (!), and they must refer to files to - which the client would be granted access if they were to be - requested directly.</dd> - - <dt><code>Content-Type:</code></dt> - - <dd>media type --- charset, level and "qs" parameters may be - given. These are often referred to as MIME types; typical - media types are <code>image/gif</code>, - <code>text/plain</code>, or - <code>text/html; level=3</code>.</dd> - - <dt><code>Content-Language:</code></dt> - - <dd>The languages of the variant, specified as an Internet - standard language tag from RFC 1766 (<em>e.g.</em>, - <code>en</code> for English, <code>kr</code> for Korean, - <em>etc.</em>).</dd> - - <dt><code>Content-Encoding:</code></dt> - - <dd>If the file is compressed, or otherwise encoded, rather - than containing the actual raw data, this says how that was - done. Apache only recognizes encodings that are defined by an - <a href="mod/mod_mime.html#addencoding">AddEncoding</a> - directive. This normally includes the encodings - <code>x-compress</code> for compress'd files, and - <code>x-gzip</code> for gzip'd files. The <code>x-</code> - prefix is ignored for encoding comparisons.</dd> - - <dt><code>Content-Length:</code></dt> - - <dd>The size of the file in bytes. Specifying content lengths - in the type-map allows the server to compare file sizes - without checking the actual files.</dd> - - <dt><code>Description:</code></dt> - - <dd>A human-readable textual description of the variant. If - Apache cannot find any appropriate variant to return, it will - return an error response which lists all available variants - instead. Such a variant list will include the human-readable - variant descriptions.</dd> - </dl> - Using a type map file is preferred over <code>MultiViews</code> - because it requires less CPU time, and less file access, to - parse a file explicitly listing the various resource variants, - than to have to look at every matching file, and parse its file - extensions. - - <h3>Multiviews</h3> - - <p><code>MultiViews</code> is a per-directory option, meaning - it can be set with an <code>Options</code> directive within a - <code><Directory></code>, <code><Location></code> - or <code><Files></code> section in - <code>access.conf</code>, or (if <code>AllowOverride</code> is - properly set) in <code>.htaccess</code> files. Note that - <code>Options All</code> does not set <code>MultiViews</code>; - you have to ask for it by name.</p> - - <p>The effect of <code>MultiViews</code> is as follows: if the - server receives a request for <code>/some/dir/foo</code>, if - <code>/some/dir</code> has <code>MultiViews</code> enabled, and - <code>/some/dir/foo</code> does <em>not</em> exist, then the - server reads the directory looking for files named foo.*, and - effectively fakes up a type map which names all those files, - assigning them the same media types and content-encodings it - would have if the client had asked for one of them by name. It - then chooses the best match to the client's requirements.</p> - - <p><code>MultiViews</code> may also apply to searches for the - file named by the <code>DirectoryIndex</code> directive, if the - server is trying to index a directory. If the configuration - files specify</p> -<pre> - DirectoryIndex index -</pre> - then the server will arbitrate between <code>index.html</code> - and <code>index.html3</code> if both are present. If neither - are present, and <code>index.cgi</code> is there, the server - will run it. - - <p>If one of the files found when reading the directive is a - CGI script, it's not obvious what should happen. The code gives - that case special treatment --- if the request was a POST, or a - GET with QUERY_ARGS or PATH_INFO, the script is given an - extremely high quality rating, and generally invoked; otherwise - it is given an extremely low quality rating, which generally - causes one of the other views (if any) to be retrieved.</p> - - <h2>The Negotiation Methods</h2> - After Apache has obtained a list of the variants for a given - resource, either from a type-map file or from the filenames in - the directory, it invokes one of two methods to decide on the - 'best' variant to return, if any. It is not necessary to know - any of the details of how negotiation actually takes place in - order to use Apache's content negotiation features. However the - rest of this document explains the methods used for those - interested. - - <p>There are two negotiation methods:</p> - - <ol> - <li><strong>Server driven negotiation with the Apache - algorithm</strong> is used in the normal case. The Apache - algorithm is explained in more detail below. When this - algorithm is used, Apache can sometimes 'fiddle' the quality - factor of a particular dimension to achieve a better result. - The ways Apache can fiddle quality factors is explained in - more detail below.</li> - - <li><strong>Transparent content negotiation</strong> is used - when the browser specifically requests this through the - mechanism defined in RFC 2295. This negotiation method gives - the browser full control over deciding on the 'best' variant, - the result is therefore dependent on the specific algorithms - used by the browser. As part of the transparent negotiation - process, the browser can ask Apache to run the 'remote - variant selection algorithm' defined in RFC 2296.</li> - </ol> - - <h3>Dimensions of Negotiation</h3> - - <table> - <tr valign="top"> - <th>Dimension</th> - - <th>Notes</th> - </tr> - - <tr valign="top"> - <td>Media Type</td> - - <td>Browser indicates preferences with the Accept header - field. Each item can have an associated quality factor. - Variant description can also have a quality factor (the - "qs" parameter).</td> - </tr> - - <tr valign="top"> - <td>Language</td> - - <td>Browser indicates preferences with the Accept-Language - header field. Each item can have a quality factor. Variants - can be associated with none, one or more than one - language.</td> - </tr> - - <tr valign="top"> - <td>Encoding</td> - - <td>Browser indicates preference with the Accept-Encoding - header field. Each item can have a quality factor.</td> - </tr> - - <tr valign="top"> - <td>Charset</td> - - <td>Browser indicates preference with the Accept-Charset - header field. Each item can have a quality factor. Variants - can indicate a charset as a parameter of the media - type.</td> - </tr> - </table> - - <h3>Apache Negotiation Algorithm</h3> - - <p>Apache can use the following algorithm to select the 'best' - variant (if any) to return to the browser. This algorithm is - not further configurable. It operates as follows:</p> - - <ol> - <li>First, for each dimension of the negotiation, check the - appropriate <em>Accept*</em> header field and assign a - quality to each variant. If the <em>Accept*</em> header for - any dimension implies that this variant is not acceptable, - eliminate it. If no variants remain, go to step 4.</li> - - <li> - Select the 'best' variant by a process of elimination. Each - of the following tests is applied in order. Any variants - not selected at each test are eliminated. After each test, - if only one variant remains, select it as the best match - and proceed to step 3. If more than one variant remains, - move on to the next test. - - <ol> - <li>Multiply the quality factor from the Accept header - with the quality-of-source factor for this variant's - media type, and select the variants with the highest - value.</li> - - <li>Select the variants with the highest language quality - factor.</li> - - <li>Select the variants with the best language match, - using either the order of languages in the - Accept-Language header (if present), or else the order of - languages in the <code>LanguagePriority</code> directive - (if present).</li> - - <li>Select the variants with the highest 'level' media - parameter (used to give the version of text/html media - types).</li> - - <li>Select variants with the best charset media - parameters, as given on the Accept-Charset header line. - Charset ISO-8859-1 is acceptable unless explicitly - excluded. Variants with a <code>text/*</code> media type - but not explicitly associated with a particular charset - are assumed to be in ISO-8859-1.</li> - - <li>Select those variants which have associated charset - media parameters that are <em>not</em> ISO-8859-1. If - there are no such variants, select all variants - instead.</li> - - <li>Select the variants with the best encoding. If there - are variants with an encoding that is acceptable to the - user-agent, select only these variants. Otherwise if - there is a mix of encoded and non-encoded variants, - select only the unencoded variants. If either all - variants are encoded or all variants are not encoded, - select all variants.</li> - - <li>Select the variants with the smallest content - length.</li> - - <li>Select the first variant of those remaining. This - will be either the first listed in the type-map file, or - when variants are read from the directory, the one whose - file name comes first when sorted using ASCII code - order.</li> - </ol> - </li> - - <li>The algorithm has now selected one 'best' variant, so - return it as the response. The HTTP response header Vary is - set to indicate the dimensions of negotiation (browsers and - caches can use this information when caching the resource). - End.</li> - - <li>To get here means no variant was selected (because none - are acceptable to the browser). Return a 406 status (meaning - "No acceptable representation") with a response body - consisting of an HTML document listing the available - variants. Also set the HTTP Vary header to indicate the - dimensions of variance.</li> - </ol> - - <h2><a id="better" name="better">Fiddling with Quality - Values</a></h2> - - <p>Apache sometimes changes the quality values from what would - be expected by a strict interpretation of the Apache - negotiation algorithm above. This is to get a better result - from the algorithm for browsers which do not send full or - accurate information. Some of the most popular browsers send - Accept header information which would otherwise result in the - selection of the wrong variant in many cases. If a browser - sends full and correct information these fiddles will not be - applied.</p> - - <h3>Media Types and Wildcards</h3> - - <p>The Accept: request header indicates preferences for media - types. It can also include 'wildcard' media types, such as - "image/*" or "*/*" where the * matches any string. So a request - including:</p> -<pre> - Accept: image/*, */* -</pre> - would indicate that any type starting "image/" is acceptable, - as is any other type (so the first "image/*" is redundant). - Some browsers routinely send wildcards in addition to explicit - types they can handle. For example: -<pre> - Accept: text/html, text/plain, image/gif, image/jpeg, */* -</pre> - The intention of this is to indicate that the explicitly listed - types are preferred, but if a different representation is - available, that is ok too. However under the basic algorithm, - as given above, the */* wildcard has exactly equal preference - to all the other types, so they are not being preferred. The - browser should really have sent a request with a lower quality - (preference) value for *.*, such as: -<pre> - Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01 -</pre> - The explicit types have no quality factor, so they default to a - preference of 1.0 (the highest). The wildcard */* is given a - low preference of 0.01, so other types will only be returned if - no variant matches an explicitly listed type. - - <p>If the Accept: header contains <em>no</em> q factors at all, - Apache sets the q value of "*/*", if present, to 0.01 to - emulate the desired behavior. It also sets the q value of - wildcards of the format "type/*" to 0.02 (so these are - preferred over matches against "*/*". If any media type on the - Accept: header contains a q factor, these special values are - <em>not</em> applied, so requests from browsers which send the - correct information to start with work as expected.</p> - - <h3>Variants with no Language</h3> - - <p>If some of the variants for a particular resource have a - language attribute, and some do not, those variants with no - language are given a very low language quality factor of - 0.001.</p> - - <p>The reason for setting this language quality factor for - variant with no language to a very low value is to allow for a - default variant which can be supplied if none of the other - variants match the browser's language preferences. For example, - consider the situation with three variants:</p> - - <ul> - <li>foo.en.html, language en</li> - - <li>foo.fr.html, language en</li> - - <li>foo.html, no language</li> - </ul> - - <p>The meaning of a variant with no language is that it is - always acceptable to the browser. If the request - Accept-Language header includes either en or fr (or both) one - of foo.en.html or foo.fr.html will be returned. If the browser - does not list either en or fr as acceptable, foo.html will be - returned instead.</p> - - <h2>Extensions to Transparent Content Negotiation</h2> - Apache extends the transparent content negotiation protocol - (RFC 2295) as follows. A new <code>{encoding ..}</code> element - is used in variant lists to label variants which are available - with a specific content-encoding only. The implementation of - the RVSA/1.0 algorithm (RFC 2296) is extended to recognize - encoded variants in the list, and to use them as candidate - variants whenever their encodings are acceptable according to - the Accept-Encoding request header. The RVSA/1.0 implementation - does not round computed quality factors to 5 decimal places - before choosing the best variant. - - <h2>Note on hyperlinks and naming conventions</h2> - - <p>If you are using language negotiation you can choose between - different naming conventions, because files can have more than - one extension, and the order of the extensions is normally - irrelevant (see the <a - href="mod/mod_mime.html#multipleext">mod_mime</a> documentation - for details).</p> - - <p>A typical file has a MIME-type extension (<em>e.g.</em>, - <samp>html</samp>), maybe an encoding extension (<em>e.g.</em>, - <samp>gz</samp>), and of course a language extension - (<em>e.g.</em>, <samp>en</samp>) when we have different - language variants of this file.</p> - - <p>Examples:</p> - - <ul> - <li>foo.en.html</li> - - <li>foo.html.en</li> - - <li>foo.en.html.gz</li> - </ul> - - <p>Here some more examples of filenames together with valid and - invalid hyperlinks:</p> - - <table border="1" cellpadding="8" cellspacing="0"> - <tr> - <th>Filename</th> - - <th>Valid hyperlink</th> - - <th>Invalid hyperlink</th> - </tr> - - <tr> - <td><em>foo.html.en</em></td> - - <td>foo<br /> - foo.html</td> - - <td>-</td> - </tr> - - <tr> - <td><em>foo.en.html</em></td> - - <td>foo</td> - - <td>foo.html</td> - </tr> - - <tr> - <td><em>foo.html.en.gz</em></td> - - <td>foo<br /> - foo.html</td> - - <td>foo.gz<br /> - foo.html.gz</td> - </tr> - - <tr> - <td><em>foo.en.html.gz</em></td> - - <td>foo</td> - - <td>foo.html<br /> - foo.html.gz<br /> - foo.gz</td> - </tr> - - <tr> - <td><em>foo.gz.html.en</em></td> - - <td>foo<br /> - foo.gz<br /> - foo.gz.html</td> - - <td>foo.html</td> - </tr> - - <tr> - <td><em>foo.html.gz.en</em></td> - - <td>foo<br /> - foo.html<br /> - foo.html.gz</td> - - <td>foo.gz</td> - </tr> - </table> - - <p>Looking at the table above you will notice that it is always - possible to use the name without any extensions in an hyperlink - (<em>e.g.</em>, <samp>foo</samp>). The advantage is that you - can hide the actual type of a document rsp. file and can change - it later, <em>e.g.</em>, from <samp>html</samp> to - <samp>shtml</samp> or <samp>cgi</samp> without changing any - hyperlink references.</p> - - <p>If you want to continue to use a MIME-type in your - hyperlinks (<em>e.g.</em> <samp>foo.html</samp>) the language - extension (including an encoding extension if there is one) - must be on the right hand side of the MIME-type extension - (<em>e.g.</em>, <samp>foo.html.en</samp>).</p> - - <h2>Note on Caching</h2> - - <p>When a cache stores a representation, it associates it with - the request URL. The next time that URL is requested, the cache - can use the stored representation. But, if the resource is - negotiable at the server, this might result in only the first - requested variant being cached and subsequent cache hits might - return the wrong response. To prevent this, Apache normally - marks all responses that are returned after content negotiation - as non-cacheable by HTTP/1.0 clients. Apache also supports the - HTTP/1.1 protocol features to allow caching of negotiated - responses.</p> - - <p>For requests which come from a HTTP/1.0 compliant client - (either a browser or a cache), the directive - <tt>CacheNegotiatedDocs</tt> can be used to allow caching of - responses which were subject to negotiation. This directive can - be given in the server config or virtual host, and takes no - arguments. It has no effect on requests from HTTP/1.1 clients. - <!--#include virtual="footer.html" --> - </p> - </body> -</html> - diff --git a/docs/manual/custom-error.html.en b/docs/manual/custom-error.html.en deleted file mode 100644 index 3cbb570436..0000000000 --- a/docs/manual/custom-error.html.en +++ /dev/null @@ -1,182 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Custom error responses</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Custom error responses</h1> - - <dl> - <dt>Purpose</dt> - - <dd> - Additional functionality. Allows webmasters to configure - the response of Apache to some error or problem. - - <p>Customizable responses can be defined to be activated in - the event of a server detected error or problem.</p> - - <p>e.g. if a script crashes and produces a "500 Server - Error" response, then this response can be replaced with - either some friendlier text or by a redirection to another - URL (local or external).</p> - </dd> - - <dt>Old behavior</dt> - - <dd>NCSA httpd 1.3 would return some boring old error/problem - message which would often be meaningless to the user, and - would provide no means of logging the symptoms which caused - it.<br /> - </dd> - - <dt>New behavior</dt> - - <dd> - The server can be asked to; - - <ol> - <li>Display some other text, instead of the NCSA hard - coded messages, or</li> - - <li>redirect to a local URL, or</li> - - <li>redirect to an external URL.</li> - </ol> - - <p>Redirecting to another URL can be useful, but only if - some information can be passed which can then be used to - explain and/or log the error/problem more clearly.</p> - - <p>To achieve this, Apache will define new CGI-like - environment variables, <em>e.g.</em></p> - - <blockquote> - <code>REDIRECT_HTTP_ACCEPT=*/*, image/gif, - image/x-xbitmap, image/jpeg<br /> - REDIRECT_HTTP_USER_AGENT=Mozilla/1.1b2 (X11; I; HP-UX - A.09.05 9000/712)<br /> - REDIRECT_PATH=.:/bin:/usr/local/bin:/etc<br /> - REDIRECT_QUERY_STRING=<br /> - REDIRECT_REMOTE_ADDR=121.345.78.123<br /> - REDIRECT_REMOTE_HOST=ooh.ahhh.com<br /> - REDIRECT_SERVER_NAME=crash.bang.edu<br /> - REDIRECT_SERVER_PORT=80<br /> - REDIRECT_SERVER_SOFTWARE=Apache/0.8.15<br /> - REDIRECT_URL=/cgi-bin/buggy.pl<br /> - </code> - </blockquote> - - <p>note the <code>REDIRECT_</code> prefix.</p> - - <p>At least <code>REDIRECT_URL</code> and - <code>REDIRECT_QUERY_STRING</code> will be passed to the - new URL (assuming it's a cgi-script or a cgi-include). The - other variables will exist only if they existed prior to - the error/problem. <strong>None</strong> of these will be - set if your ErrorDocument is an <em>external</em> redirect - (<em>i.e.</em>, anything starting with a scheme name like - <code>http:</code>, even if it refers to the same host as - the server).</p> - </dd> - - <dt>Configuration</dt> - - <dd> - Use of "ErrorDocument" is enabled for .htaccess files when - the <a href="mod/core.html#allowoverride">"FileInfo" - override</a> is allowed. - - <p>Here are some examples...</p> - - <blockquote> - <code>ErrorDocument 500 /cgi-bin/crash-recover<br /> - ErrorDocument 500 "Sorry, our script crashed. Oh - dear<br /> - ErrorDocument 500 http://xxx/<br /> - ErrorDocument 404 /Lame_excuses/not_found.html<br /> - ErrorDocument 401 - /Subscription/how_to_subscribe.html</code> - </blockquote> - - <p>The syntax is,</p> - - <p><code><a - href="mod/core.html#errordocument">ErrorDocument</a></code> - <3-digit-code> action</p> - - <p>where the action can be,</p> - - <ol> - <li>Text to be displayed. Prefix the text with a quote - ("). Whatever follows the quote is displayed. <em>Note: - the (") prefix isn't displayed.</em></li> - - <li>An external URL to redirect to.</li> - - <li>A local URL to redirect to.</li> - </ol> - </dd> - </dl> - <hr /> - - <h2>Custom error responses and redirects</h2> - - <dl> - <dt>Purpose</dt> - - <dd>Apache's behavior to redirected URLs has been modified so - that additional environment variables are available to a - script/server-include.</dd> - - <dt>Old behavior</dt> - - <dd>Standard CGI vars were made available to a script which - has been redirected to. No indication of where the - redirection came from was provided.</dd> - - <dt>New behavior</dt> - - <dd>A new batch of environment variables will be initialized - for use by a script which has been redirected to. Each new - variable will have the prefix <code>REDIRECT_</code>. - <code>REDIRECT_</code> environment variables are created from - the CGI environment variables which existed prior to the - redirect, they are renamed with a <code>REDIRECT_</code> - prefix, <em>i.e.</em>, <code>HTTP_USER_AGENT</code> becomes - <code>REDIRECT_HTTP_USER_AGENT</code>. In addition to these - new variables, Apache will define <code>REDIRECT_URL</code> - and <code>REDIRECT_STATUS</code> to help the script trace its - origin. Both the original URL and the URL being redirected to - can be logged in the access log.</dd> - </dl> - - <p>If the ErrorDocument specifies a local redirect to a CGI - script, the script should include a "<samp>Status:</samp>" - header field in its output in order to ensure the propagation - all the way back to the client of the error condition that - caused it to be invoked. For instance, a Perl ErrorDocument - script might include the following:</p> -<pre> - : - print "Content-type: text/html\n"; - printf "Status: %s Condition Intercepted\n", $ENV{"REDIRECT_STATUS"}; - : -</pre> - - <p>If the script is dedicated to handling a particular error - condition, such as <samp>404 Not Found</samp>, it can - use the specific code and error text instead.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/developer/modules.html.en b/docs/manual/developer/modules.html.en deleted file mode 100644 index ebf7c33da2..0000000000 --- a/docs/manual/developer/modules.html.en +++ /dev/null @@ -1,258 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Converting Modules from Apache 1.3 to Apache 2.0</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">From Apache 1.3 to Apache 2.0<br /> - Modules</h1> - - <p>This is a first attempt at writing the lessons I learned - when trying to convert the mod_mmap_static module to Apache - 2.0. It's by no means definitive and probably won't even be - correct in some ways, but it's a start.</p> - <hr /> - - <h2>The easier changes...</h2> - - <h3>Cleanup Routines</h3> - - <p>These now need to be of type apr_status_t and return a value - of that type. Normally the return value will be APR_SUCCESS - unless there is some need to signal an error in the cleanup. Be - aware that even though you signal an error not all code yet - checks and acts upon the error.</p> - - <h3>Initialisation Routines</h3> - - <p>These should now be renamed to better signify where they sit - in the overall process. So the name gets a small change from - mmap_init to mmap_post_config. The arguments passed have - undergone a radical change and now look like</p> - - <ul style="list-style:none"> - <li>apr_pool_t *p,</li> - - <li>apr_pool_t *plog,</li> - - <li>apr_pool_t *ptemp,</li> - - <li>server_rec *s</li> - </ul> - - <h3>Data Types</h3> - - <p>A lot of the data types have been moved into the APR. This - means that some have had a name change, such as the one shown - above. The following is a brief list of some of the changes - that you are likely to have to make.</p> - - <ul style="list-style:none"> - <li>pool becomes apr_pool_t</li> - - <li>table becomes apr_table_t</li> - </ul> - <hr /> - - <h2>The <em>messier</em> changes...</h2> - - <h3>Register Hooks</h3> - - <p>The new architecture uses a series of hooks to provide for - calling your functions. These you'll need to add to your module - by way of a new function, static void register_hooks(void). The - function is really reasonably straightforward once you - understand what needs to be done. Each function that needs - calling at some stage in the processing of a request needs to - be registered, handlers do not. There are a number of phases - where functions can be added, and for each you can specify with - a high degree of control the relative order that the function - will be called in.</p> - - <p>This is the code that was added to mod_mmap_static:</p> -<pre> -static void register_hooks(void) -{ - static const char * const aszPre[]={ "http_core.c",NULL }; - ap_hook_post_config(mmap_post_config,NULL,NULL,HOOK_MIDDLE); - ap_hook_translate_name(mmap_static_xlat,aszPre,NULL,HOOK_LAST); -}; -</pre> - - <p>This registers 2 functions that need to be called, one in - the post_config stage (virtually every module will need this - one) and one for the translate_name phase. note that while - there are different function names the format of each is - identical. So what is the format?</p> - - <p><strong>ap_hook_[phase_name](function_name, predecessors, - successors, position);</strong></p> - - <p>There are 3 hook positions defined...</p> - - <ul style="list-style:none"> - <li>HOOK_FIRST</li> - - <li>HOOK_MIDDLE</li> - - <li>HOOK_LAST</li> - </ul> - - <p>To define the position you use the position and then modify - it with the predecessors and successors. each of the modifiers - can be a list of functions that should be called, either before - the function is run (predecessors) or after the function has - run (successors).</p> - - <p>In the mod_mmap_static case I didn't care about the - post_config stage, but the mmap_static_xlat MUST be called - after the core module had done it's name translation, hence the - use of the aszPre to define a modifier to the position - HOOK_LAST.</p> - - <h3>Module Definition</h3> - - <p>There are now a lot fewer stages to worry about when - creating your module definition. The old defintion looked - like</p> -<pre> -module MODULE_VAR_EXPORT [module_name]_module = -{ - STANDARD_MODULE_STUFF, - /* initializer */ - /* dir config creater */ - /* dir merger --- default is to override */ - /* server config */ - /* merge server config */ - /* command handlers */ - /* handlers */ - /* filename translation */ - /* check_user_id */ - /* check auth */ - /* check access */ - /* type_checker */ - /* fixups */ - /* logger */ - /* header parser */ - /* child_init */ - /* child_exit */ - /* post read-request */ -}; -</pre> - - <p>The new structure is a great deal simpler...</p> -<pre> -module MODULE_VAR_EXPORT [module_name]_module = -{ - STANDARD20_MODULE_STUFF, - /* create per-directory config structures */ - /* merge per-directory config structures */ - /* create per-server config structures */ - /* merge per-server config structures */ - /* command handlers */ - /* handlers */ - /* register hooks */ - }; -</pre> - - <p>Some of these read directly across, some don't. I'll try to - summarise what should be done below.</p> - - <p>The stages that read directly across :</p> - - <ul style="list-style:none"> - <li>/* dir config creater */ ==> /* create per-directory - config structures */</li> - - <li>/* server config */ ==> /* create per-server config - structures */</li> - - <li>/* dir merger */ ==> /* merge per-directory config - structures */</li> - - <li>/* merge server config */ ==> /* merge per-server - config structures */</li> - - <li>/* command table */ ==> /* command apr_table_t */</li> - - <li>/* handlers */ ==> /* handlers */</li> - </ul> - - <p>The remainder of the old functions should be registered as - hooks. There are the following hook stages defined so - far...</p> - - <ul style="list-style:none"> - <li>ap_hook_post_config <em>(this is where the old _init - routines get registered)</em></li> - - <li>ap_hook_http_method <em>(retrieve the http method from a - request. (legacy))</em></li> - - <li>ap_hook_open_logs <em>(open any specified logs)</em></li> - - <li>ap_hook_auth_checker <em>(check if the resource requires - authorization)</em></li> - - <li>ap_hook_access_checker <em>(check for module-specific - restrictions)</em></li> - - <li>ap_hook_check_user_id <em>(check the user-id and - password)</em></li> - - <li>ap_hook_default_port <em>(retrieve the default port for - the server)</em></li> - - <li>ap_hook_pre_connection <em>(do any setup required just - before processing, but after accepting)</em></li> - - <li>ap_hook_process_connection <em>(run the correct - protocol)</em></li> - - <li>ap_hook_child_init <em>(call as soon as the child is - started)</em></li> - - <li>ap_hook_create_request <em>(??)</em></li> - - <li>ap_hook_fixups <em>(last chance to modify things before - generating content)</em></li> - - <li>ap_hook_handler <em>(generate the content)</em></li> - - <li>ap_hook_header_parser <em>(let's modules look at the - headers, not used by most modules, because they use - post_read_request for this.)</em></li> - - <li>ap_hook_insert_filter <em>(to insert filters into the - filter chain)</em></li> - - <li>ap_hook_log_transaction <em>(log information about the - request)</em></li> - - <li>ap_hook_optional_fn_retrieve <em>(retrieve any functions - registered as optional)</em></li> - - <li>ap_hook_post_read_request <em>(called after reading the - request, before any other phase)</em></li> - - <li>ap_hook_quick_handler <em>(??)</em></li> - - <li>ap_hook_translate_name <em>(translate the URI into a - filename)</em></li> - - <li>ap_hook_type_checker <em>(determine and/or set the doc - type)</em> <!--#include virtual="footer.html" --> - </li> - </ul> - </body> -</html> - diff --git a/docs/manual/dso.html.en b/docs/manual/dso.html.en deleted file mode 100644 index 38d28ba2a8..0000000000 --- a/docs/manual/dso.html.en +++ /dev/null @@ -1,344 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Dynamic Shared Object (DSO) support</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="center">Dynamic Shared Object (DSO) Support</h1> - - <p>The Apache HTTP Server is a modular program where the - administrator can choose the functionality to include in the - server by selecting a set of modules. The modules can be - statically compiled into the <code>httpd</code> binary when the - server is built. Alternatively, modules can be compiled as - Dynamic Shared Objects (DSOs) that exist separately from the - main <code>httpd</code> binary file. DSO modules may be - compiled at the time the server is built, or they may be - compiled and added at a later time using the Apache Extension - Tool (<a href="programs/apxs.html">apxs</a>).</p> - - <p>This document describes how to use DSO modules as well as - the theory behind their use.</p> - - <ul> - <li><a href="#implementation">Implementation</a></li> - - <li><a href="#usage">Usage Summary</a></li> - - <li><a href="#background">Background</a></li> - - <li><a href="#advantages">Advantages and - Disadvantages</a></li> - </ul> - <hr /> - - <table border="1"> - <tr> - <td valign="top"><strong>Related Modules</strong><br /> - <br /> - <a href="mod/mod_so.html">mod_so</a><br /> - </td> - - <td valign="top"><strong>Related Directives</strong><br /> - <br /> - <a href="mod/mod_so.html#loadmodule">LoadModule</a><br /> - </td> - </tr> - </table> - - <h2><a id="implementation" - name="implementation">Implementation</a></h2> - - <p>The DSO support for loading individual Apache modules is - based on a module named <a - href="mod/mod_so.html"><code>mod_so.c</code></a> which must be - statically compiled into the Apache core. It is the only module - besides <code>core.c</code> which cannot be put into a DSO - itself. Practically all other distributed Apache modules then - can then be placed into a DSO by individually enabling the DSO - build for them via <code>configure</code>'s - <code>--enable-<i>module</i>=shared</code> option as disucussed - in the <a href="install.html">install documentation</a>. After - a module is compiled into a DSO named <code>mod_foo.so</code> - you can use <a href="mod/mod_so.html"><code>mod_so</code></a>'s - <a - href="mod/mod_so.html#loadmodule"><code>LoadModule</code></a> - command in your <code>httpd.conf</code> file to load this - module at server startup or restart.</p> - - <p>To simplify this creation of DSO files for Apache modules - (especially for third-party modules) a new support program - named <a href="programs/apxs.html">apxs</a> (<em>APache - eXtenSion</em>) is available. It can be used to build DSO based - modules <em>outside of</em> the Apache source tree. The idea is - simple: When installing Apache the <code>configure</code>'s - <code>make install</code> procedure installs the Apache C - header files and puts the platform-dependent compiler and - linker flags for building DSO files into the <code>apxs</code> - program. This way the user can use <code>apxs</code> to compile - his Apache module sources without the Apache distribution - source tree and without having to fiddle with the - platform-dependent compiler and linker flags for DSO - support.</p> - - <h2><a id="usage" name="usage">Usage Summary</a></h2> - - <p>To give you an overview of the DSO features of Apache 2.0, - here is a short and concise summary:</p> - - <ol> - <li> - Build and install a <em>distributed</em> Apache module, say - <code>mod_foo.c</code>, into its own DSO - <code>mod_foo.so</code>: - - <table bgcolor="#f0f0f0" cellpadding="10"> - <tr> - <td> -<pre> -$ ./configure --prefix=/path/to/install - --enable-foo=shared -$ make install -</pre> - </td> - </tr> - </table> - </li> - - <li> - Build and install a <em>third-party</em> Apache module, say - <code>mod_foo.c</code>, into its own DSO - <code>mod_foo.so</code>: - - <table bgcolor="#f0f0f0" cellpadding="10"> - <tr> - <td> -<pre> -$ ./configure --add-module=module_type:/path/to/3rdparty/mod_foo.c - --enable-foo=shared -$ make install -</pre> - </td> - </tr> - </table> - </li> - - <li> - Configure Apache for <em>later installation</em> of shared - modules: - - <table bgcolor="#f0f0f0" cellpadding="10"> - <tr> - <td> -<pre> -$ ./configure --enable-so -$ make install -</pre> - </td> - </tr> - </table> - </li> - - <li> - Build and install a <em>third-party</em> Apache module, say - <code>mod_foo.c</code>, into its own DSO - <code>mod_foo.so</code> <em>outside of</em> the Apache - source tree using <a href="programs/apxs.html">apxs</a>: - - <table bgcolor="#f0f0f0" cellpadding="10"> - <tr> - <td> -<pre> -$ cd /path/to/3rdparty -$ apxs -c mod_foo.c -$ apxs -i -a -n foo mod_foo.so -</pre> - </td> - </tr> - </table> - </li> - </ol> - - <p>In all cases, once the shared module is compiled, you must - use a <a - href="mod/mod_so.html#loadmodule"><code>LoadModule</code></a> - directive in <code>httpd.conf</code> to tell Apache to activate - the module.</p> - - <h2><a id="background" name="background">Background</a></h2> - - <p>On modern Unix derivatives there exists a nifty mechanism - usually called dynamic linking/loading of <em>Dynamic Shared - Objects</em> (DSO) which provides a way to build a piece of - program code in a special format for loading it at run-time - into the address space of an executable program.</p> - - <p>This loading can usually be done in two ways: Automatically - by a system program called <code>ld.so</code> when an - executable program is started or manually from within the - executing program via a programmatic system interface to the - Unix loader through the system calls - <code>dlopen()/dlsym()</code>.</p> - - <p>In the first way the DSO's are usually called <em>shared - libraries</em> or <em>DSO libraries</em> and named - <code>libfoo.so</code> or <code>libfoo.so.1.2</code>. They - reside in a system directory (usually <code>/usr/lib</code>) - and the link to the executable program is established at - build-time by specifying <code>-lfoo</code> to the linker - command. This hard-codes library references into the executable - program file so that at start-time the Unix loader is able to - locate <code>libfoo.so</code> in <code>/usr/lib</code>, in - paths hard-coded via linker-options like <code>-R</code> or in - paths configured via the environment variable - <code>LD_LIBRARY_PATH</code>. It then resolves any (yet - unresolved) symbols in the executable program which are - available in the DSO.</p> - - <p>Symbols in the executable program are usually not referenced - by the DSO (because it's a reusable library of general code) - and hence no further resolving has to be done. The executable - program has no need to do anything on its own to use the - symbols from the DSO because the complete resolving is done by - the Unix loader. (In fact, the code to invoke - <code>ld.so</code> is part of the run-time startup code which - is linked into every executable program which has been bound - non-static). The advantage of dynamic loading of common library - code is obvious: the library code needs to be stored only once, - in a system library like <code>libc.so</code>, saving disk - space for every program.</p> - - <p>In the second way the DSO's are usually called <em>shared - objects</em> or <em>DSO files</em> and can be named with an - arbitrary extension (although the canonical name is - <code>foo.so</code>). These files usually stay inside a - program-specific directory and there is no automatically - established link to the executable program where they are used. - Instead the executable program manually loads the DSO at - run-time into its address space via <code>dlopen()</code>. At - this time no resolving of symbols from the DSO for the - executable program is done. But instead the Unix loader - automatically resolves any (yet unresolved) symbols in the DSO - from the set of symbols exported by the executable program and - its already loaded DSO libraries (especially all symbols from - the ubiquitous <code>libc.so</code>). This way the DSO gets - knowledge of the executable program's symbol set as if it had - been statically linked with it in the first place.</p> - - <p>Finally, to take advantage of the DSO's API the executable - program has to resolve particular symbols from the DSO via - <code>dlsym()</code> for later use inside dispatch tables - <em>etc.</em> In other words: The executable program has to - manually resolve every symbol it needs to be able to use it. - The advantage of such a mechanism is that optional program - parts need not be loaded (and thus do not spend memory) until - they are needed by the program in question. When required, - these program parts can be loaded dynamically to extend the - base program's functionality.</p> - - <p>Although this DSO mechanism sounds straightforward there is - at least one difficult step here: The resolving of symbols from - the executable program for the DSO when using a DSO to extend a - program (the second way). Why? Because "reverse resolving" DSO - symbols from the executable program's symbol set is against the - library design (where the library has no knowledge about the - programs it is used by) and is neither available under all - platforms nor standardized. In practice the executable - program's global symbols are often not re-exported and thus not - available for use in a DSO. Finding a way to force the linker - to export all global symbols is the main problem one has to - solve when using DSO for extending a program at run-time.</p> - - <p>The shared library approach is the typical one, because it - is what the DSO mechanism was designed for, hence it is used - for nearly all types of libraries the operating system - provides. On the other hand using shared objects for extending - a program is not used by a lot of programs.</p> - - <p>As of 1998 there are only a few software packages available - which use the DSO mechanism to actually extend their - functionality at run-time: Perl 5 (via its XS mechanism and the - DynaLoader module), Netscape Server, <em>etc.</em> Starting - with version 1.3, Apache joined the crew, because Apache - already uses a module concept to extend its functionality and - internally uses a dispatch-list-based approach to link external - modules into the Apache core functionality. So, Apache is - really predestined for using DSO to load its modules at - run-time.</p> - - <h2><a id="advantages" name="advantages">Advantages and - Disadvantages</a></h2> - - <p>The above DSO based features have the following - advantages:</p> - - <ul> - <li>The server package is more flexible at run-time because - the actual server process can be assembled at run-time via <a - href="mod/mod_so.html#loadmodule"><code>LoadModule</code></a> - <code>httpd.conf</code> configuration commands instead of - <code>configure</code> options at build-time. For instance - this way one is able to run different server instances - (standard & SSL version, minimalistic & powered up - version [mod_perl, PHP3], <em>etc.</em>) with only one Apache - installation.</li> - - <li>The server package can be easily extended with - third-party modules even after installation. This is at least - a great benefit for vendor package maintainers who can create - a Apache core package and additional packages containing - extensions like PHP3, mod_perl, mod_fastcgi, - <em>etc.</em></li> - - <li>Easier Apache module prototyping because with the - DSO/<code>apxs</code> pair you can both work outside the - Apache source tree and only need an <code>apxs -i</code> - command followed by an <code>apachectl restart</code> to - bring a new version of your currently developed module into - the running Apache server.</li> - </ul> - - <p>DSO has the following disadvantages:</p> - - <ul> - <li>The DSO mechanism cannot be used on every platform - because not all operating systems support dynamic loading of - code into the address space of a program.</li> - - <li>The server is approximately 20% slower at startup time - because of the symbol resolving overhead the Unix loader now - has to do.</li> - - <li>The server is approximately 5% slower at execution time - under some platforms because position independent code (PIC) - sometimes needs complicated assembler tricks for relative - addressing which are not necessarily as fast as absolute - addressing.</li> - - <li>Because DSO modules cannot be linked against other - DSO-based libraries (<code>ld -lfoo</code>) on all platforms - (for instance a.out-based platforms usually don't provide - this functionality while ELF-based platforms do) you cannot - use the DSO mechanism for all types of modules. Or in other - words, modules compiled as DSO files are restricted to only - use symbols from the Apache core, from the C library - (<code>libc</code>) and all other dynamic or static libraries - used by the Apache core, or from static library archives - (<code>libfoo.a</code>) containing position independent code. - The only chances to use other code is to either make sure the - Apache core itself already contains a reference to it or - loading the code yourself via <code>dlopen()</code>.</li> - </ul> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/filter.html.en b/docs/manual/filter.html.en deleted file mode 100644 index 9d176661c9..0000000000 --- a/docs/manual/filter.html.en +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Filters - Apache HTTPD</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Filters</h1> - - <table border="1"> - <tr> - <td valign="top"><strong>Related Modules</strong><br /> - <br /> - <a href="mod/mod_ext_filter.html">mod_ext_filter</a><br /> - <a href="mod/mod_include.html">mod_include</a><br /> - </td> - - <td valign="top"><strong>Related Directives</strong><br /> - <br /> - <a - href="mod/mod_mime.html#addinputfilter">AddInputFilter</a><br /> - <a - href="mod/mod_mime.html#addoutputfilter">AddOutputFilter</a><br /> - <a - href="mod/mod_ext_filter.html#extfilterdefine">ExtFilterDefine</a><br /> - <a - href="mod/mod_ext_filter.html#extfilteroptions">ExtFilterOptions</a><br /> - <a - href="mod/core.html#setinputfilter">SetInputFilter</a><br /> - <a - href="mod/core.html#setoutputfilter">SetOutputFilter</a><br /> - </td> - </tr> - </table> - - <p>A <em>filter</em> is a process which is applied to data that - is sent or received by the server. Data sent by clients to the - server is processed by <em>input filters</em> while data sent - by the server to the client is processed by <em>output - filters</em>. Multiple filters can be applied to the data, and - the order of the filters can be explicitly specified.</p> - - <p>Filters are used internally by Apache to perform functions - such as chunking and byte-range request handling. In addition, - modules can provide filters which are selectable using run-time - configuration directives. The set of filters which apply to - data can be manipulated with the <code>SetInputFilter</code> - and <code>SetOutputFilter</code> directives.</p> - - <p>The only configurable filter currently included with the - Apache distribution is the <code>INCLUDES</code> filter which - is provided by <a href="mod/mod_include.html">mod_include</a> - to process output for Server Side Includes. There is also an - experimental module called <a - href="mod/mod_ext_filter.html">mod_ext_filter</a> which allows - for external programs to be defined as filters.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/howto/auth.html.en b/docs/manual/howto/auth.html.en deleted file mode 100644 index baea08c4bd..0000000000 --- a/docs/manual/howto/auth.html.en +++ /dev/null @@ -1,382 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Authentication</title> - <link rev="made" href="mailto:rbowen@rcbowen.com" /> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Authentication</h1> - <a id="__index__" name="__index__"></a> <!-- INDEX BEGIN --> - - - <ul> - <li><a href="#introduction">Introduction</a></li> - - <li><a href="#the prerequisites">The prerequisites</a></li> - - <li><a href="#getting it working">Getting it working</a></li> - - <li><a href="#letting more than one person in">Letting more - than one person in</a></li> - - <li><a href="#possible problems">Possible problems</a></li> - - <li><a href="#what other neat stuff can i do">What other neat - stuff can I do?</a></li> - - <li><a href="#more information">More information</a></li> - </ul> - <!-- INDEX END --> - <hr /> - - <table border="1"> - <tr> - <td valign="top"><strong>Related Modules</strong><br /> - <br /> - <a href="../mod/mod_auth.html">mod_auth</a><br /> - <a href="../mod/mod_access.html">mod_access</a><br /> - </td> - - <td valign="top"><strong>Related Directives</strong><br /> - <br /> - <a href="../mod/mod_access.html#allow">Allow</a><br /> - <a - href="../mod/mod_auth.html#authgroupfile">AuthGroupFile</a><br /> - <a href="../mod/core.html#authname">AuthName</a><br /> - <a href="../mod/core.html#authtype">AuthType</a><br /> - <a - href="../mod/mod_auth.html#authuserfile">AuthUserFile</a><br /> - <a href="../mod/mod_access.html#deny">Deny</a><br /> - <a href="../mod/core.html#options">Options</a><br /> - <a href="../mod/core.html#require">Require</a><br /> - </td> - </tr> - </table> - - <h1><a id="authentication" - name="authentication">Authentication</a></h1> - - <p>Authentication is any process by which you verify that - someone is who they claim they are. Authorization is any - process by which someone is allowed to be where they want to - go, or to have information that they want to have.</p> - - <h2><a id="introduction" - name="introduction">Introduction</a></h2> - - <p>If you have information on your web site that is sensitive - or intended for only a small group of people, the techniques in - this article will help you make sure that the people that see - those pages are the people that you wanted to see them.</p> - - <p>This article covers the "standard" way of protecting parts - of your web site that most of you are going to use.</p> - - <h2><a id="the prerequisites" name="the prerequisites">The - prerequisites</a></h2> - - <p>The directives discussed in this article will need to go - either in your main server configuration file (typically in a - <Directory> section), or in per-directory configuration - files (<code>.htaccess</code> files).</p> - - <p>If you plan to use <code>.htaccess</code> files, you will - need to have a server configuration that permits putting - authentication directives in these files. This is done with the - <code><a - href="../mod/core.html#allowoverride">AllowOverride</a></code> - directive, which specifies which directives, if any, may be put - in per-directory configuration files.</p> - - <p>Since we're talking here about authentication, you will need - an <code>AllowOverride</code> directive like the following:</p> -<pre> - AllowOverride AuthConfig -</pre> - - <p>Or, if you are just going to put the directives directly in - your main server configuration file, you will of course need to - have write permission to that file.</p> - - <p>And you'll need to know a little bit about the directory - structure of your server, in order to know where some files are - kept. This should not be terribly difficult, and I'll try to - make this clear when we come to that point.</p> - - <h2><a id="getting it working" - name="getting it working">Getting it working</a></h2> - - <p>Here's the basics of password protecting a directory on your - server.</p> - - <p>You'll need to create a password file. This file should be - placed somewhere not accessible from the web. This is so that - folks cannot download the password file. For example, if your - documents are served out of - <code>/usr/local/apache/htdocs</code> you might want to put the - password file(s) in <code>/usr/local/apache/passwd</code>.</p> - - <p>To create the file, use the <a - href="../programs/htpasswd.html">htpasswd</a> utility that came - with Apache. This be located in the <code>bin</code> directory - of wherever you installed Apache. To create the file, type:</p> -<pre> - htpasswd -c /usr/local/apache/passwd/password rbowen -</pre> - - <p><code>htpasswd</code> will ask you for the password, and - then ask you to type it again to confirm it:</p> -<pre> - # htpasswd -c /usr/local/apache/passwd/passwords rbowen - New password: mypassword - Re-type new password: mypassword - Adding password for user rbowen -</pre> - - <p>If <code>htpasswd</code> is not in your path, of course - you'll have to type the full path to the file to get it to run. - On my server, it's located at - <code>/usr/local/apache/bin/htpasswd</code></p> - - <p>Next, you'll need to configure the server to request a - password and tell the server which users are allowed access. - You can do this either by editing the <code>httpd.conf</code> - file or using an <code>.htaccess</code> file. For example, if - you wish to protect the directory - <code>/usr/local/apache/htdocs/secret</code>, you can use the - following directives, either placed in the file - <code>/usr/local/apache/htdocs/secret/.htaccess</code>, or - placed in httpd.conf inside a <Directory - /usr/local/apache/apache/htdocs/secret> section.</p> -<pre> - AuthType Basic - AuthName "Restricted Files" - AuthUserFile /usr/local/apache/passwd/passwords - require user rbowen -</pre> - - <p>Let's examine each of those directives individually. The <a - href="../mod/core.html#authtype">AuthType</a> directive selects - that method that is used to authenticate the user. The most - common method is <code>Basic</code>, and this is the method - implemented by <a href="../mod/mod_auth.html">mod_auth</a>. It - is important to be aware, however, that Basic authentication - sends the password from the client to the browser unencrypted. - This method should therefore not be used for highly sensitive - data. Apache supports one other authentication method: - <code>AuthType Digest</code>. This method is implemented by <a - href="../mod/mod_auth_digest.html">mod_auth_digest</a> and is - much more secure. Only the most recent versions of clients are - known to support Digest authentication.</p> - - <p>The <a href="../mod/core.html#authname">AuthName</a> - directive sets the <em>Realm</em> to be used in the - authentication. The realm serves two major functions. First, - the client often presents this information to the user as part - of the password dialog box. Second, it is used by the client to - determine what password to send for a given authenticated area. - So, for example, once a client has authenticated in the - <code>"Restricted Files"</code> area, it will automatically - retry the same password for any area on the same server that is - marked with the <code>"Restricted Files"</code> Realm. - Therefore, you can prevent a user from being prompted more than - once for a password by letting multiple restricted areas share - the same realm. Of course, for security reasons, the client - will always need to ask again for the password whenever the - hostname of the server changes.</p> - - <p>The <a - href="../mod/mod_auth.html#authuserfile">AuthUserFile</a> - directive sets the path to the password file that we just - created with <code>htpasswd</code>. If you have a large number - of users, it can be quite slow to search through a plain text - file to authenticate the user on each request. Apache also has - the ability to store user information in fast database files. - The modules <a href="../mod/mod_auth_db.html">mod_auth_db</a> - and <a href="../mod/mod_auth_dbm.html">mod_auth_dbm</a> provide - the <a - href="../mod/mod_auth_db.html#authdbuserfile">AuthDBUserFile</a> - and <a - href="../mod/mod_auth_dbm.html#authdbmuserfile">AuthDBMUserFile</a> - directives respectively. These files can be created and - manipulated with the <a - href="../programs/dbmmanage.html">dbmmanage</a> program. Many - other types of authentication options are available from third - party modules in the <a - href="http://modules.apache.org/">Apache Modules - Database</a>.</p> - - <p>Finally, the <a href="../mod/core.html#require">require</a> - directive provides the authorization part of the process by - setting the user that is allowed to access this region of the - server. In the next section, we discuss various ways to use the - <code>require</code> directive.</p> - - <h2><a id="letting more than one person in" - name="letting more than one person in">Letting more than one - person in</a></h2> - - <p>The directives above only let one person (specifically - someone with a username of <code>rbowen</code>) into the - directory. In most cases, you'll want to let more than one - person in. This is where the <a - href="../mod/mod_auth.html#authgroupfile">AuthGroupFile</a> - comes in.</p> - - <p>If you want to let more than one person in, you'll need to - create a group file that associates group names with a list of - users in that group. The format of this file is pretty simple, - and you can create it with your favorite editor. The contents - of the file will look like this:</p> -<pre> - GroupName: rbowen dpitts sungo rshersey -</pre> - - <p>That's just a list of the members of the group in a long - line separated by spaces.</p> - - <p>To add a user to your already existing password file, - type:</p> -<pre> - htpasswd /usr/local/apache/passwd/password dpitts -</pre> - - <p>You'll get the same response as before, but it will be - appended to the existing file, rather than creating a new file. - (It's the <code>-c</code> that makes it create a new password - file.</p> - - <p>Now, you need to modify your <code>.htaccess</code> file to - look like the following:</p> -<pre> - AuthType Basic - AuthName "By Invitation Only" - AuthUserFile /usr/local/apache/passwd/passwords - AuthGroupFile /usr/local/apache/passwd/groups - require group GroupName -</pre> - - <p>Now, anyone that is listed in the group - <code>GroupName</code>, and has an entry in the - <code>password</code> file, will be let in, if they type the - correct password.</p> - - <p>There's another way to let multiple users in that is less - specific. Rather than creating a group file, you can just use - the following directive:</p> -<pre> - require valid-user -</pre> - - <p>Using that rather than the <code>require user rbowen</code> - line will allow anyone in that is listed in the password file, - and who correctly enters their password. You can even emulate - the group behavior here, by just keeping a separate password - file for each group. The advantage of this approach is that - Apache only has to check one file, rather than two. The - disadvantage is that you have to maintain a bunch of password - files, and remember to reference th right one in the - <code>AuthUserFile</code> directive.</p> - - <h2><a id="possible problems" name="possible problems">Possible - problems</a></h2> - - <p>Because of the way that Basic authentication is specified, - your username and password must be verified every time you - request a document from the server. This is even if you're - reloading the same page, and for every image on the page (if - they come from a protected directory). As you can imagine, this - slows things down a little. The amount that it slows things - down is proportional to the size of the password file, because - it has to open up that file, and go down the list of users - until it gets to your name. And it has to do this every time a - page is loaded.</p> - - <p>A consequence of this is that there's a practical limit to - how many users you can put in one password file. This limit - will vary depending on the performance of your particular - server machine, but you can expect to see slowdowns once you - get above a few hundred entries, and may wish to consider a - different authentication method at that time.</p> - - <h2><a id="what other neat stuff can i do" - name="what other neat stuff can i do">What other neat stuff can - I do?</a></h2> - - <p>Authentication by username and password is only part of the - story. Frequently you want to let people in based on something - other than who they are. Something such as where they are - coming from.</p> - - <p>The <code>allow</code> and <code>deny</code> directives let - you allow and deny access based on the host name, or host - address, of the machine requesting a document. The directive - goes hand-in-hand with these is the <code>order</code> - directive, which tells Apache in which order to apply the - filters.</p> - - <p>The usage of these directives is:</p> -<pre> - allow from address -</pre> - - <p>where <em>address</em> is an IP address (or a partial IP - address) or a fully qualified domain name (or a partial domain - name).</p> - - <p>For example, if you have someone spamming your message - board, and you want to keep them out, you could do the - following:</p> -<pre> - deny from 205.252.46.165 -</pre> - - <p>Visitors coming from that address will not be able to see - the content behind this directive. If, instead, you have a - machine name, rather than an IP address, you can use that.</p> -<pre> - deny from host.example.com -</pre> - - <p>And, if you'd like to block access from an entire domain, - you can specify just part of an address or domain name:</p> -<pre> - deny from 192.101.205 - deny from cyberthugs.com - deny from ke -</pre> - - <p>Using <code>order</code> will let you be sure that you are - actually restricting things to the group that you want to let - in, by combining a <code>deny</code> and an <code>allow</code> - directive:</p> -<pre> - order deny,allow - deny from all - allow from dev.example.com -</pre> - - <p>Listing just the <code>allow</code> directive would not do - what you want, because it will let folks from that host in, in - addition to letting everyone in. What you want is to let - <em>only</em> those folks in.</p> - - <h2><a id="more information" name="more information">More - information</a></h2> - - <p>You should also read the documentation for <code><a - href="../mod/mod_auth.html">mod_auth</a></code> and <code><a - href="../mod/mod_access.html">mod_access</a></code> which - contain some more information about how this all works.</p> - </body> -</html> - diff --git a/docs/manual/install.html.en b/docs/manual/install.html.en deleted file mode 100644 index b9103318d1..0000000000 --- a/docs/manual/install.html.en +++ /dev/null @@ -1,634 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Compiling and Installing Apache</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Compiling and Installing</h1> - - <p>This document covers compilation and installation of Apache - on Unix and Unix-like systems only. For compiling and - installation on Windows, see <a - href="platform/windows.html">Using Apache with Microsoft - Windows</a>. For other platforms, see the <a - href="platform/">platform</a> documentation.</p> - - <p>Apache 2.0's configuration and installation environment has - changed completely from Apache 1.3. Apache 1.3 used a custom - set of scripts to achieve easy installation. Apache 2.0 now - uses libtool and autoconf to create an environment that looks - like many other Open Source projects.</p> - - <ul> - <li><a href="#overview">Overview for the impatient</a></li> - - <li><a href="#requirements">Requirements</a></li> - - <li><a href="#download">Download</a></li> - - <li><a href="#extract">Extract</a></li> - - <li> - <a href="#configure">Configuring the source tree</a> - - <ul> - <li><a href="#environment">Environment Variables</a></li> - - <li><a href="#output">autoconf Output Options</a></li> - - <li><a href="#pathnames">Pathnames</a></li> - - <li><a href="#modules">Modules</a></li> - - <li><a href="#suexec">Suexec</a></li> - </ul> - </li> - - <li><a href="#compile">Build</a></li> - - <li><a href="#install">Install</a></li> - - <li><a href="#customize">Customize</a></li> - - <li><a href="#test">Test</a></li> - </ul> - <hr /> - - <h3><a id="overview" name="overview">Overview for the - impatient</a></h3> - - <table> - <tr> - <td><a href="#download">Download</a></td> - - <td><code>$ lynx - http://www.apache.org/dist/httpd/httpd-2_0_<em>NN</em>.tar.gz</code> - </td> - </tr> - - <tr> - <td><a href="#extract">Extract</a></td> - - <td><code>$ gzip -d httpd-2_0_<em>NN</em>.tar.gz<br /> - $ tar xvf httpd-2_0_<em>NN</em>.tar</code> </td> - </tr> - - <tr> - <td><a href="#configure">Configure</a></td> - - <td><code>$ ./configure --prefix=<em>PREFIX</em></code> - </td> - </tr> - - <tr> - <td><a href="#compile">Compile</a></td> - - <td><code>$ make</code> </td> - </tr> - - <tr> - <td><a href="#install">Install</a></td> - - <td><code>$ make install</code> </td> - </tr> - - <tr> - <td><a href="#customize">Customize</a></td> - - <td><code>$ vi <em>PREFIX</em>/conf/httpd.conf</code> </td> - </tr> - - <tr> - <td><a href="#test">Test</a></td> - - <td><code>$ <em>PREFIX</em>/bin/apachectl start</code> - </td> - </tr> - </table> - - <p><em>NN</em> must be replaced with the current minor version - number, and <em>PREFIX</em> must be replaced with the - filesystem path under which the server should be installed. If - <em>PREFIX</em> is not specified, it defaults to - <code>/usr/local/apache2</code>.</p> - - <p>Each section of the compilation and installation process is - described in more detail below, beginning with the requirements - for compiling and installing Apache HTTPD.</p> - - <h3><a id="requirements" - name="requirements">Requirements</a></h3> - - <p>The following requirements exist for building Apache:</p> - - <ul> - <li>Disk Space<br /> - <br /> - Make sure you have at least 50 MB of temporary free disk - space available. After installation Apache occupies - approximately 10 MB of disk space. The actual disk space - requirements will vary considerably based on your chosen - configuration options and any third-party modules.<br /> - <br /> - </li> - - <li>ANSI-C Compiler and Build System<br /> - <br /> - Make sure you have an ANSI-C compiler installed. The <a - href="http://www.gnu.org/software/gcc/gcc.html">GNU C - compiler (GCC)</a> from the <a - href="http://www.gnu.org/">Free Software Foundation (FSF)</a> - is recommended (version 2.7.2 is fine). If you don't have GCC - then at least make sure your vendor's compiler is ANSI - compliant. In addition, your <code>PATH</code> must contain - basic build tools such as <code>make</code>.<br /> - <br /> - </li> - - <li>Accurate time keeping<br /> - <br /> - Elements of the HTTP protocol are expressed as the time of - day. So, it's time to investigate setting some time - synchronization facility on your system. Usually the ntpdate - or xntpd programs are used for this purpose which are based - on the Network Time Protocol (NTP). See the Usenet newsgroup - <a - href="news:comp.protocols.time.ntp">comp.protocols.time.ntp</a> - and the <a href="http://www.eecis.udel.edu/~ntp/">NTP - homepage</a> for more details about NTP software and public - time servers.<br /> - <br /> - </li> - - <li><a href="http://www.perl.org/">Perl 5</a> - [OPTIONAL]<br /> - <br /> - For some of the support scripts like <a - href="programs/apxs.html">apxs</a> or <a - href="programs/dbmmanage.html">dbmmanage</a> (which are - written in Perl) the Perl 5 interpreter is required (versions - 5.003 and 5.004 are fine). If no such interpreter is found by - the `configure' script there is no harm. Of course, you still - can build and install Apache 2.0. Only those support scripts - cannot be used. If you have multiple Perl interpreters - installed (perhaps a Perl 4 from the vendor and a Perl 5 from - your own), then it is recommended to use the --with-perl - option (see below) to make sure the correct one is selected - by ./configure.<br /> - <br /> - </li> - </ul> - - <h3><a id="download" name="download">Download</a></h3> - - <p>Apache can be downloaded from the <a - href="http://www.apache.org/dist/httpd/">Apache Software - Foundation download site</a> or from a <a - href="http://www.apache.org/dyn/closer.cgi">nearby - mirror</a>.</p> - - <p>Version numbers that end in <code>alpha</code> indicate - early pre-test versions which may or may not work. Version - numbers ending in <code>beta</code> indicate more reliable - releases that still require further testing or bug fixing. If - you wish to download the best available production release of - the Apache HTTP Server, you should choose the latest version - with neither <code>alpha</code> nor <code>beta</code> in its - filename.</p> - - <p>After downloading, especially if a mirror site is used, it - is important to verify that you have a complete and unmodified - version of the Apache HTTP Server. This can be accomplished by - testing the downloaded tarball against the PGP signature. This, - in turn, is a two step procedure. First, you must obtain the - <code>KEYS</code> file from the <a - href="http://www.apache.org/dist/">Apache distribution - site</a>. (To assure that the <code>KEYS</code> file itself has - not been modified, it may be a good idea to use a file from a - previous distribution of Apache or import the keys from a - public key server.) The keys are imported into your personal - key ring using one of the following commands (depending on your - pgp version):</p> - - <blockquote> - <code>$ pgp < KEYS</code> - </blockquote> - or - - <blockquote> - <code>$ gpg --import KEYS</code> - </blockquote> - - <p>The next step is to test the tarball against the PGP - signature, which should always be obtained from the <a - href="http://www.apache.org/dist/httpd">main Apache - website</a>. The signature file has a filename identical to the - source tarball with the addition of <code>.asc</code>. Then you - can check the distribution with one of the following commands - (again, depending on your pgp version):</p> - - <blockquote> - <code>$ pgp httpd-2_0_<em>NN</em>.tar.gz.asc</code> - </blockquote> - or - - <blockquote> - <code>$ gpg --verify httpd-2_0_<em>NN</em>.tar.gz.asc</code> - </blockquote> - You should receive a message like<br /> - <br /> - - - <blockquote> - <code>Good signature from user "Martin Kraemer - <martin@apache.org>".</code> - </blockquote> - - <p>Depending on the trust relationships contained in your key - ring, you may also receive a message saying that the - relationship between the key and the signer of the key cannot - be verified. This is not a problem if you trust the - authenticity of the <code>KEYS</code> file.</p> - - <h3><a id="extract" name="extract">Extract</a></h3> - - <p>Extracting the source from the Apache HTTPD tarball is a - simple matter of uncompressing, and then untarring:</p> - - <blockquote> - <code>$ gzip -d httpd-2_0_<em>NN</em>.tar.gz<br /> - $ tar xvf httpd-2_0_<em>NN</em>.tar</code> - </blockquote> - - <p>This will create a new directory under the current directory - containing the source code for the distribution. You should - <code>cd</code> into that directory before proceeding with - compiling the server.</p> - - <h3><a id="configure" name="configure">Configuring the source - tree</a></h3> - - <p>The next step is to configure the Apache source tree for - your particular platform and personal requirements. This is - done using the script <code>configure</code> included in the - root directory of the distribution. (Developers downloading the - CVS version of the Apache source tree will need to have - <code>autoconf</code> and <code>libtool</code> installed and - will need to run <code>buildconf</code> before proceeding with - the next steps. This is not necessary for official - releases.)</p> - - <p>To configure the source tree using all the default options, - simply type <code>./configure</code>. To change the default - options, <code>configure</code> accepts a variety of variables - and command line options. Environment variables are generally - placed before the <code>./configure</code> command, while other - options are placed after. The most important option here is the - location prefix where Apache is to be installed later, because - Apache has to be configured for this location to work - correctly. But there are a lot of other options available for - your pleasure.</p> - - <p>For a short impression of what possibilities you have, here - is a typical example which compiles Apache for the installation - tree /sw/pkg/apache with a particular compiler and flags plus - the two additional modules mod_rewrite and mod_speling for - later loading through the DSO mechanism:</p> - - <blockquote> - <code>$ CC="pgcc" CFLAGS="-O2" \<br /> - ./configure --prefix=/sw/pkg/apache \<br /> - --enable-rewrite=shared \<br /> - --enable-speling=shared</code> - </blockquote> - - <p>When configure is run it will take several minutes to test - for the availability of features on your system and build - Makefiles which will later be used to compile the server.</p> - - <p>The easiest way to find all of the configuration flags for - Apache is to run ./configure --help. What follows is a brief - description of most of the arguments and environment - variables.</p> - - <h4><a id="environment" name="environment">Environment - Variables</a></h4> - - <p>The autoconf build process uses several environment - variables to configure the build environment. In general, these - variables change the method used to build Apache, but not the - eventual features of the server. These variables can be placed - in the environment before invoking <code>configure</code>, but - it is usually easier to specify them on the - <code>configure</code> command line as demonstrated in the - example above.</p> - - <dl> - <dt><code>CC=...</code></dt> - - <dd>The name of the C compiler command.</dd> - - <dt><code>CPPFLAGS=...</code></dt> - - <dd>Miscellaneous C preprocessor and compiler options.</dd> - - <dt><code>CFLAGS=...</code></dt> - - <dd>Debugging and optimization options for the C - compiler.</dd> - - <dt><code>LDFLAGS=...</code></dt> - - <dd>Miscellaneous options to be passed to the linker.</dd> - - <dt><code>LIBS=...</code></dt> - - <dd>Library location information ("-L" and "-l" options) to - pass to the linker.</dd> - - <dt><code>INCLUDES=...</code></dt> - - <dd>Header file search directories ("-I<em>dir</em>").</dd> - - <dt><code>TARGET=...</code> [Default: apache]</dt> - - <dd>Name of the executable which will be built.</dd> - - <dt><code>NOTEST_CPPFLAGS=...</code></dt> - - <dt><code>NOTEST_CFLAGS=...</code></dt> - - <dt><code>NOTEST_LDFLAGS=...</code></dt> - - <dt><code>NOTEST_LIBS=...</code></dt> - - <dd>These variables share the same function as their - non-NOTEST namesakes. However, the variables are applied to - the build process only after autoconf has performed its - feature testing. This allows the inclusion of flags which - will cause problems during feature testing, but must be used - for the final compilation.</dd> - - <dt><code>SHLIB_PATH=...</code></dt> - - <dd>Options which specify shared library paths for the - compiler and linker.</dd> - </dl> - - <h4><a id="output" name="output">autoconf Output - Options</a></h4> - - <dl> - <dt><code>--help</code></dt> - - <dd>Prints the usage message including all available options, - but does not actually configure anything.</dd> - - <dt><code>--quiet</code></dt> - - <dd>Prevents the printing of the usual "checking..." - messages.</dd> - - <dt><code>--verbose</code></dt> - - <dd>Prints much more information during the configuration - process, including the names of all the files examined.</dd> - </dl> - - <h4><a id="pathnames" name="pathnames">Pathnames</a></h4> - - <p>There are currently two ways to configure the pathnames - under which Apache will install its files. First, you can - specify a directory and have Apache install itself under that - directory in its default locations.</p> - - <dl> - <dt><code>--prefix=<em>PREFIX</em></code> [Default: - /usr/local/apache2]</dt> - - <dd>Specifies the directory under which the Apache files will - be installed.</dd> - </dl> - - <p>It is possible to specify that architecture-dependent files - should be placed under a different directory.</p> - - <dl> - <dt><code>--exec-prefix=<em>EPREFIX</em></code> [Default: - <em>PREFIX</em>]</dt> - - <dd>Specifies the directory under which - architecture-dependent files will be placed.</dd> - </dl> - - <p>The second, and more flexible way to configure the install - path locations for Apache is using the - <code>config.layout</code> file. Using this method, it is - possible to separately specify the location for each type of - file within the Apache installation. The - <code>config.layout</code> file contains several example - configurations, and you can also create your own custom - configuration following the examples. The different layouts in - this file are grouped into <code><Layout - FOO>...</Layout></code> sections and referred to by - name as in <code>FOO</code>.</p> - - <dl> - <dt><code>--enable-layout=<em>LAYOUT</em></code></dt> - - <dd>Use the named layout in the <code>config.layout</code> - file to specify the installation paths.</dd> - </dl> - - <p>Presently it is not possible to mix the - <code>--enable-layout</code> and <code>--prefix</code> options. - Nor is it possible to individually specify detailed pathnames - on the <code>configure</code> command line. If you want just a - basic install, you can simply use the <code>--prefix</code> - option on its own. If you want to customize your install, you - should edit the <code>config.layout</code> file and use the - <code>--enable-layout</code> option.</p> - - <h4><a id="modules" name="modules">Modules</a></h4> - - <p>Apache is a modular server. Only the most basic - functionality is included in the core server. Extended features - are available in various modules. During the configuration - process, you must select which modules to compile for use with - your server. You can view a <a - href="mod/index-bytype.html">list of modules</a> included in - the documentation. Those modules with a <a - href="mod/module-dict.html#Status">status</a> of "Base" are - included by default and must be specifically disabled if you do - not want them. Modules with any other status must be - specifically enabled if you wish to use them.</p> - - <p>There are two ways for a module to be compiled and used with - Apache. Modules may be <em>statically compiled</em>, which - means that they are permanently included in the Apache binary. - Alternatively, if your operating system supports Dynamic Shared - Objects (DSOs) and autoconf can detect that support, then - modules may be <em>dynamically compiled</em>. DSO modules are - stored separately from the Apache binary, and may be included - or excluded from the server using the run-time configuration - directives provided by <a href="mod/mod_so.html">mod_so</a>. - The mod_so is automatically included in the server if any - dynamic modules are included in the compilation. If you would - like to make your server capable of loading DSOs without - actually compiling any dynamic modules, you can explicitly - <code>--enable-so</code>.</p> - - <dl> - <dt><code>--enable-<em>MODULE</em>[=shared]</code></dt> - - <dd>Compile and include the module <em>MODULE</em>. The - identifier <em>MODULE</em> is the <a - href="mod/module-dict.html#ModuleIdentifier">Module - Identifier</a> from the module documentation without the - "_module" string. To compile the module as a DSO, add the - option <code>=shared</code>.</dd> - - <dt><code>--disable-<em>MODULE</em></code></dt> - - <dd>Remove the module <em>MODULE</em> which would otherwise - be compiled and included.</dd> - - <dt><code>--enable-modules=<em>MODULE-LIST</em></code></dt> - - <dd>Compile and include the modules listed in the - space-separated <em>MODULE-LIST</em>.</dd> - - <dt> - <code>--enable-mods-shared=<em>MODULE-LIST</em></code></dt> - - <dd>Compile and include the modules in the space-separated - <em>MODULE-LIST</em> as dynamically loadable (DSO) - modules.</dd> - </dl> - - <p>The <em>MODULE-LIST</em> in the - <code>--enable-modules</code> and - <code>--enable-mods-shared</code> options is usually a - space-separated list of module identifiers. For example, to - enable mod_dav and mod_info, you can either use</p> - - <blockquote> - <code>./configure --enable-dav --enable-info</code> - </blockquote> - - <p>or, equivalently,</p> - - <blockquote> - <code>./configure --enable-modules="dav info"</code> - </blockquote> - - <p>In addition, the special keywords <code>all</code> or - <code>most</code> can be used to add all or most of the modules - in one step. You can then remove any modules that you do not - want with the <code>--disable-<em>MODULE</em></code> option. - For example, to include all modules as DSOs with the exception - of mod_info, you can use</p> - - <blockquote> - <code>./configure --enable-mods-shared=all - --disable-info</code> - </blockquote> - - <p>In addition to the standard set of modules, Apache 2.0 also - includes a choice of <a href="mpm.html">Multi-Processing - Modules</a> (MPMs). One, and only one MPM must be included in - the compilation process. The default MPMs for each platform are - listed on the <a href="mpm.html">MPM documentation page</a>, - but can be overridden on the <code>configure</code> command - line.</p> - - <dl> - <dt><code>--with-mpm=<em>NAME</em></code></dt> - - <dd>Choose the mpm <em>NAME</em>.</dd> - </dl> - - <h4><a id="suexec" name="suexec">Suexec</a></h4> - - <p>Apache includes a support program called <a - href="suexec.html">suexec</a> which can be used to isolate user - CGI programs. However, if suexec is improperly configured, it - can cause serious security problems. Therefore, you should - carefully read and consider the <a href="suexec.html">suexec - documentation</a> before implementing this feature.</p> - - <h3><a id="compile" name="compile">Build</a></h3> - - <p>Now you can build the various parts which form the Apache - package by simply running the command:</p> - - <blockquote> - <code>$ make</code> - </blockquote> - - <p>Please be patient here, since a base configuration takes - approximately 3 minutes to compile under a Pentium III/Linux - 2.2 system, but this will vary widely depending on your - hardware and the number of modules which you have enabled.</p> - - <h3><a id="install" name="install">Install</a></h3> - - <p>Now its time to install the package under the configured - installation <em>PREFIX</em> (see <code>--prefix</code> option - above) by running:</p> - - <blockquote> - <code>$ make install</code> - </blockquote> - - <p>If you are upgrading, the installation will not overwrite - your configuration files or documents.</p> - - <h3><a id="customize" name="customize">Customize</a></h3> - - <p>Next, you can customize your Apache HTTP server by editing - the <a href="configuring.html">configuration files</a> under - <em>PREFIX</em>/conf/.</p> - - <blockquote> - <code>$ vi <em>PREFIX</em>/conf/httpd.conf</code> - </blockquote> - - <p>Have a look at the Apache manual under <a - href="./">docs/manual/</a> or <a - href="http://httpd.apache.org/docs/">http://httpd.apache.org/docs/</a> - for a complete reference of available <a - href="mod/directives.html">configuration directives</a>.</p> - - <h3><a id="test" name="test">Test</a></h3> - - <p>Now you can <a href="invoking.html">start</a> your Apache - HTTP server by immediately running:</p> - - <blockquote> - <code>$ <em>PREFIX</em>/bin/apachectl start</code> - </blockquote> - - <p>and then you should be able to request your first document - via URL http://localhost/. The web page you see is located - under the <a href="mod/core.html#documentroot">DocumentRoot</a> - which will usually be <code><em>PREFIX</em>/htdocs/</code>. - Then <a href="stopping.html">stop</a> the server again by - running:</p> - - <blockquote> - <code>$ <em>PREFIX</em>/bin/apachectl stop</code> - </blockquote> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/invoking.html.en b/docs/manual/invoking.html.en deleted file mode 100644 index a9c625551f..0000000000 --- a/docs/manual/invoking.html.en +++ /dev/null @@ -1,139 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Starting Apache</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Starting Apache</h1> - - <ul> - <li><a href="#windows">Starting Apache on Windows</a></li> - - <li> - <a href="#unix">Starting Apache on Unix</a> - - <ul> - <li><a href="#errors">Errors During Start-up</a></li> - - <li><a href="#boot">Starting at Boot-Time</a></li> - - <li><a href="#info">Additional Information</a></li> - </ul> - </li> - </ul> - <hr /> - - <h2><a id="windows" name="windows">Starting Apache On - Windows</a></h2> - - <p>On Windows, Apache is normally run as a service on Windows - NT, or as a console application on Windows 95. For details, see - <a href="platform/windows.html#run">running Apache for - Windows</a>.</p> - - <h2><a id="unix" name="unix">Starting Apache on Unix</a></h2> - - <p>On Unix, the <a href="programs/httpd.html">httpd</a> program - is run as a daemon which executes continuously in the - background to handle requests.</p> - - <p>If the <a href="mod/mpm_common.html#Listen">Listen</a> specified in - the configuration file is default of 80 (or any other port - below 1024), then it is necessary to have root privileges in - order to start apache, so that it can bind to this privileged - port. Once the server has started and performed a few - preliminary activities such as opening its log files, it will - launch several <em>child</em> processes which do the work of - listening for and answering requests from clients. The main - <code>httpd</code> process continues to run as the root user, - but the child processes run as a less privileged user. This is - controlled by the selected <a href="mpm.html">Multi-Processing - Module</a>.</p> - - <p>The first thing that <code>httpd</code> does when it is - invoked is to locate and read the <a - href="configuring.html">configuration file</a> - <code>httpd.conf</code>. The location of this file is set at - compile-time, but it is possible to specify its location at run - time using the <code>-f</code> command-line option as in</p> - - <blockquote> - <code>/usr/local/apache/bin/httpd -f - /usr/local/apache/conf/httpd.conf</code> - </blockquote> - - <p>As an alternative to invoking the <code>httpd</code> binary - directly, a shell script called <a - href="programs/apachectl.html">apachectl</a> is provided which - can be used to control the daemon process with simple commands - such as <code>apachectl start</code> and <code>apachectl - stop</code>.</p> - - <p>If all goes well during startup, the server will detach from - the terminal and the command prompt will return almost - immediately. This indicates that the server is up and running. - You can then use your browser to connect to the server and view - the test page in the <a - href="mod/core.html#documentroot">DocumentRoot</a> directory - and the local copy of the documentation linked from that - page.</p> - - <h3><a id="errors" name="errors">Errors During - Start-up</a></h3> - - <p>If Apache suffers a fatal problem during startup, it will - write a message describing the problem either to the console or - to the <a href="mod/core.html#errorlog">ErrorLog</a> before - exiting. One of the most common error messages is "<code>Unable - to bind to Port ...</code>". This message is usually caused by - either:</p> - - <ul> - <li>Trying to start the server on a privileged port when not - logged in as the root user; or</li> - - <li>Trying to start the server when there is another instance - of Apache or some other web server already bound to the same - Port.</li> - </ul> - - <p>For further trouble-shooting instructions, consult the - Apache <a href="faq/">FAQ</a>.</p> - - <h3><a id="boot" name="boot">Starting at Boot-Time</a></h3> - - <p>If you want your server to continue running after a system - reboot, you should add a call to <code>httpd</code> or - <code>apachectl</code> to your system startup files (typically - <code>rc.local</code> or a file in an <code>rc.N</code> - directory). This will start Apache as root. Before doing this - ensure that your server is properly configured for security and - access restrictions. The <code>apachectl</code> script is - designed so that it can often be linked directly as an init - script, but be sure to check the exact requirements of your - system.</p> - - <h3><a id="info" name="info">Additional Information</a></h3> - - <p>Additional information about the command-line options of <a - href="programs/httpd.html">httpd</a> and <a - href="programs/apachectl.html">apachectl</a> as well as other - support programs included with the server is available on the - <a href="programs/">Server and Supporting Programs</a> page. - There is also documentation on all the <a - href="mod/">modules</a> included with the Apache distribution - and the <a href="mod/directives.html">directives</a> that they - provide.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/logs.html.en b/docs/manual/logs.html.en deleted file mode 100644 index a45a96ef16..0000000000 --- a/docs/manual/logs.html.en +++ /dev/null @@ -1,667 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Log Files - Apache HTTP Server</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="center">Log Files</h1> - - <p>In order to effectively manage a web server, it is necessary - to get feedback about the activity and performance of the - server as well as any problems that may be occuring. The Apache - HTTP Server provides very comprehensive and flexible logging - capabilities. This document describes how to configure its - logging capabilities, and how to understand what the logs - contain.</p> - - <ul> - <li><a href="#security">Security Warning</a></li> - - <li><a href="#errorlog">Error Log</a></li> - - <li> - <a href="#accesslog">Access Log</a> - - <ul> - <li><a href="#common">Common Log Format</a></li> - - <li><a href="#combined">Combined Log Format</a></li> - - <li><a href="#multiple">Multiple Access Logs</a></li> - - <li><a href="#conditional">Conditional Logging</a></li> - </ul> - </li> - - <li><a href="#rotation">Log Rotation</a></li> - - <li><a href="#piped">Piped Logs</a></li> - - <li><a href="#virtualhosts">VirtualHosts</a></li> - - <li> - <a href="#other">Other Log Files</a> - - <ul> - <li><a href="#pidfile">PID File</a></li> - - <li><a href="#scriptlog">Script Log</a></li> - - <li><a href="#rewritelog">Rewrite Log</a></li> - </ul> - </li> - </ul> - <hr /> - - <h2><a id="security" name="security">Security Warning</a></h2> - - <p>Anyone who can write to the directory where Apache is - writing a log file can almost certainly gain access to the uid - that the server is started as, which is normally root. Do - <em>NOT</em> give people write access to the directory the logs - are stored in without being aware of the consequences; see the - <a href="misc/security_tips.html">security tips</a> document - for details.</p> - - <p>In addition, log files may contain information supplied - directly by the client, without escaping. Therefore, it is - possible for malicious clients to insert control-characters in - the log files, so care must be taken in dealing with raw - logs.</p> - <hr /> - - <h2><a id="errorlog" name="errorlog">Error Log</a></h2> - - <table border="1"> - <tr> - <td valign="top"><strong>Related Directives</strong><br /> - <br /> - <a href="mod/core.html#errorlog">ErrorLog</a><br /> - <a href="mod/core.html#loglevel">LogLevel</a> </td> - </tr> - </table> - - <p>The server error log, whose name and location is set by the - <a href="mod/core.html#errorlog">ErrorLog</a> directive, is the - most important log file. This is the place where Apache httpd - will send diagnostic information and record any errors that it - encounters in processing requests. It is the first place to - look when a problem occurs with starting the server or with the - operation of the server, since it will often contain details of - what went wrong and how to fix it.</p> - - <p>The error log is usually written to a file (typically - <code>error_log</code> on unix systems and - <code>error.log</code> on Windows and OS/2). On unix systems it - is also possible to have the server send errors to - <code>syslog</code> or <a href="#pipe">pipe them to a - program</a>.</p> - - <p>The format of the error log is relatively free-form and - descriptive. But there is certain information that is contained - in most error log entries. For example, here is a typical - message.</p> - - <blockquote> - <code>[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] - client denied by server configuration: - /export/home/live/ap/htdocs/test</code> - </blockquote> - - <p>The first item in the log entry is the date and time of the - message. The second entry lists the severity of the error being - reported. The <a href="mod/core.html#loglevel">LogLevel</a> - directive is used to control the types of errors that are sent - to the error log by restricting the severity level. The third - entry gives the IP address of the client that generated the - error. Beyond that is the message itself, which in this case - indicates that the server has been configured to deny the - client access. The server reports the file-system path (as - opposed to the web path) of the requested document.</p> - - <p>A very wide variety of different messages can appear in the - error log. Most look similar to the example above. The error - log will also contain debugging output from CGI scripts. Any - information written to <code>stderr</code> by a CGI script will - be copied directly to the error log.</p> - - <p>It is not possible to customize the error log by adding or - removing information. However, error log entries dealing with - particular requests have corresponding entries in the <a - href="accesslog">access log</a>. For example, the above example - entry corresponds to an access log entry with status code 403. - Since it is possible to customize the access log, you can - obtain more information about error conditions using that log - file.</p> - - <p>During testing, it is often useful to continuously monitor - the error log for any problems. On unix systems, you can - accomplish this using:</p> - - <blockquote> - <code>tail -f error_log</code> - </blockquote> - <hr /> - - <h2><a id="accesslog" name="accesslog">Access Log</a></h2> - - <table border="1"> - <tr> - <td valign="top"><strong>Related Modules</strong><br /> - <br /> - <a href="mod/mod_log_config.html">mod_log_config</a><br /> - </td> - - <td valign="top"><strong>Related Directives</strong><br /> - <br /> - <a - href="mod/mod_log_config.html#customlog">CustomLog</a><br /> - <a - href="mod/mod_log_config.html#logformat">LogFormat</a><br /> - <a href="mod/mod_setenvif.html#setenvif">SetEnvIf</a> - </td> - </tr> - </table> - - <p>The server access log records all requests processed by the - server. The location and content of the access log are - controlled by the <a - href="mod/mod_log_config.html#customlog">CustomLog</a> - directive. The <a - href="mod/mod_log_config.html#logformat">LogFormat</a> - directive can be used to simplify the selection of the contents - of the logs. This section describes how to configure the server - to record information in the access log.</p> - - <p>Of course, storing the information in the access log is only - the start of log management. The next step is to analyze this - information to produce useful statistics. Log analysis in - general is beyond the scope of this document, and not really - part of the job of the web server itself. For more information - about this topic, and for applications which perform log - analysis, check the <a - href="http://dmoz.org/Computers/Software/Internet/Site_Management/Log_analysis/"> - Open Directory</a> or <a - href="http://dir.yahoo.com/Computers_and_Internet/Software/Internet/World_Wide_Web/Servers/Log_Analysis_Tools/"> - Yahoo</a>.</p> - - <p>Various versions of Apache httpd have used other modules and - directives to control access logging, including - mod_log_referer, mod_log_agent, and the - <code>TransferLog</code> directive. The <code>CustomLog</code> - directive now subsumes the functionality of all the older - directives.</p> - - <p>The format of the access log is highly configurable. The - format is specified using a <a - href="mod/mod_log_config.html#format">format string</a> that - looks much like a C-style printf(1) format string. Some - examples are presented in the next sections. For a complete - list of the possible contents of the format string, see the <a - href="mod/mod_log_config.html">mod_log_config - documentation</a>.</p> - - <h3><a id="common" name="common">Common Log Format</a></h3> - - <p>A typical configuration for the access log might look as - follows.</p> - - <blockquote> - <code>LogFormat "%h %l %u %t \"%r\" %>s %b" common<br /> - CustomLog logs/access_log common</code> - </blockquote> - - <p>This defines the <em>nickname</em> <code>common</code> and - associates it with a particular log format string. The format - string consists of percent directives, each of which tell the - server to log a particular piece of information. Literal - characters may also be placed in the format string and will be - copied directly into the log output. The quote character - (<code>"</code>) must be escaped by placing a back-slash before - it to prevent it from being interpreted as the end of the - format string. The format string may also contain the special - control characters "<code>\n</code>" for new-line and - "<code>\t</code>" for tab.</p> - - <p>The <code>CustomLog</code> directive sets up a new log file - using the defined <em>nickname</em>. The filename for the - access log is relative to the <a - href="mod/core.html#serverroot">ServerRoot</a> unless it begins - with a slash.</p> - - <p>The above configuration will write log entries in a format - known as the Common Log Format (CLF). This standard format can - be produced by many different web servers and read by many log - analysis programs. The log file entries produced in CLF will - look something like this:</p> - - <blockquote> - <code>127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET - /apache_pb.gif HTTP/1.0" 200 2326</code> - </blockquote> - - <p>Each part of this log entry is described below.</p> - - <dl> - <dt><code>127.0.0.1</code> (<code>%h</code>)</dt> - - <dd>This is the IP address of the client (remote host) which - made the request to the server. If <a - href="mod/core.html#hostnamelookups">HostNameLookups</a> is - set to <code>On</code>, then the server will try to determine - the hostname and log it in place of the IP address. However, - this configuration is not recommended since it can - significantly slow the server. Instead, it is best to use a - log post-processor such as <a - href="programs/logresolve.html">logresolve</a> to determine - the hostnames. The IP address reported here is not - necessarily the address of the machine at which the user is - sitting. If a proxy server exists between the user and the - server, this address will be the address of the proxy, rather - than the originating machine.</dd> - - <dt><code>-</code> (<code>%l</code>)</dt> - - <dd>The "hyphen" in the output indicates that the requested - piece of information is not available. In this case, the - information that is not available is the RFC 1413 identity of - the client determined by <code>identd</code> on the clients - machine. This information is highly unreliable and should - almost never be used except on tightly controlled internal - networks. Apache httpd will not even attempt to determine - this information unless <a - href="mod/core.html#identitycheck">IdentityCheck</a> is set - to <code>On</code>.</dd> - - <dt><code>frank</code> (<code>%u</code>)</dt> - - <dd>This is the userid of the person requesting the document - as determined by HTTP authentication. The same value is - typically provided to CGI scripts in the - <code>REMOTE_USER</code> environment variable. If the status - code for the request (see below) is 401, then this value - should not be trusted because the user is not yet - authenticated. If the document is not password protected, - this entry will be "<code>-</code>" just like the previous - one.</dd> - - <dt><code>[10/Oct/2000:13:55:36 -0700]</code> - (<code>%t</code>)</dt> - - <dd> - The time that the server finished processing the request. - The format is: - - <blockquote> - <code>[day/month/year:hour:minute:second zone]<br /> - day = 2*digit<br /> - month = 3*letter<br /> - year = 4*digit<br /> - hour = 2*digit<br /> - minute = 2*digit<br /> - second = 2*digit<br /> - zone = (`+' | `-') 4*digit</code> - </blockquote> - It is possible to have the time displayed in another format - by specifying <code>%{format}t</code> in the log format - string, where <code>format</code> is as in - <code>strftime(3)</code> from the C standard library. - </dd> - - <dt><code>"GET /apache_pb.gif HTTP/1.0"</code> - (<code>\"%r\"</code>)</dt> - - <dd>The request line from the client is given in double - quotes. The request line contains a great deal of useful - information. First, the method used by the client is - <code>GET</code>. Second, the client requested the resource - <code>/apache_pb.gif</code>, and third, the client used the - protocol <code>HTTP/1.0</code>. It is also possible to log - one or more parts of the request line independently. For - example, the format string "<code>%m %U%q %H</code>" will log - the method, path, query-string, and protocol, resulting in - exactly the same output as "<code>%r</code>".</dd> - - <dt><code>200</code> (<code>%>s</code>)</dt> - - <dd>This is the status code that the server sends back to the - client. This information is very valuable, because it reveals - whether the request resulted in a successful response (codes - beginning in 2), a redirection (codes beginning in 3), an - error caused by the client (codes beginning in 4), or an - error in the server (codes beginning in 5). The full list of - possible status codes can be found in the <a - href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt">HTTP - specification</a> (RFC2616 section 10).</dd> - - <dt><code>2326</code> (<code>%b</code>)</dt> - - <dd>The last entry indicates the size of the object returned - to the client, not including the response headers. If no - content was returned to the client, this value will be - "<code>-</code>". To log "<code>0</code>" for no content, use - <code>%B</code> instead.</dd> - </dl> - - <h4><a id="combined" name="combined">Combined Log - Format</a></h4> - - <p>Another commonly used format string is called the Combined - Log Format. It can be used as follows.</p> - - <blockquote> - <code>LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" - \"%{User-agent}i\"" combined<br /> - CustomLog log/acces_log combined</code> - </blockquote> - - <p>This format is exactly the same as the Common Log Format, - with the addition of two more fields. Each of the additional - fields uses the percent-directive - <code>%{<em>header</em>}i</code>, where <em>header</em> can be - any HTTP request header. The access log under this format will - look like:</p> - - <blockquote> - <code>127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET - /apache_pb.gif HTTP/1.0" 200 2326 - "http://www.example.com/start.html" "Mozilla/4.08 [en] - (Win98; I ;Nav)"</code> - </blockquote> - - <p>The additional fields are:</p> - - <dl> - <dt><code>"http://www.example.com/start.html"</code> - (<code>\"%{Referer}i\"</code>)</dt> - - <dd>The "Referer" (sic) HTTP request header. This gives the - site that the client reports having been referred from. (This - should be the page that links to or includes - <code>/apache_pb.gif</code>).</dd> - - <dt><code>"Mozilla/4.08 [en] (Win98; I ;Nav)"</code> - (<code>\"%{User-agent}i\"</code>)</dt> - - <dd>The User-Agent HTTP request header. This is the - identifying information that the client browser reports about - itself.</dd> - </dl> - - <h3><a id="multiple" name="multiple">Multiple Access - Logs</a></h3> - - <p>Multiple access logs can be created simply by specifying - multiple <code>CustomLog</code> directives in the configuration - file. For example, the following directives will create three - access logs. The first contains the basic CLF information, - while the second and third contain referer and browser - information. The last two <code>CustomLog</code> lines show how - to mimic the effects of the <code>ReferLog</code> and - <code>AgentLog</code> directives.</p> - - <blockquote> - <code>LogFormat "%h %l %u %t \"%r\" %>s %b" common<br /> - CustomLog logs/access_log common<br /> - CustomLog logs/referer_log "%{Referer}i -> %U"<br /> - CustomLog logs/agent_log "%{User-agent}i"</code> - </blockquote> - - <p>This example also shows that it is not necessary to define a - nickname with the <code>LogFormat</code> directive. Instead, - the log format can be specified directly in the - <code>CustomLog</code> directive.</p> - - <h3><a id="conditional" name="conditional">Conditional - Logging</a></h3> - - <p>There are times when it is convenient to exclude certain - entries from the access logs based on characteristics of the - client request. This is easily accomplished with the help of <a - href="env.html">environment variables</a>. First, an - environment variable must be set to indicate that the request - meets certain conditions. This is usually accomplished with <a - href="mod/mod_setenvif.html#setenvif">SetEnvIf</a>. Then the - <code>env=</code> clause of the <code>CustomLog</code> - directive is used to include or exclude requests where the - environment variable is set. Some examples:</p> - - <blockquote> - <code># Mark requests from the loop-back interface<br /> - SetEnvIf Remote_Addr "127\.0\.0\.1" dontlog<br /> - # Mark requests for the robots.txt file<br /> - SetEnvIf Request_URI "^/robots\.txt$" dontlog<br /> - # Log what remains<br /> - CustomLog logs/access_log common env=!dontlog</code> - </blockquote> - - <p>As another example, consider logging requests from - english-speakers to one log file, and non-english speakers to a - different log file.</p> - - <blockquote> - <code>SetEnvIf Accept-Language "en" english<br /> - CustomLog logs/english_log common env=english<br /> - CustomLog logs/non_english_log common env=!english</code> - </blockquote> - - <p>Although we have just shown that conditional logging is very - powerful and flexibly, it is not the only way to control the - contents of the logs. Log files are more useful when they - contain a complete record of server activity. It is often - easier to simply post-process the log files to remove requests - that you do not want to consider.</p> - <hr /> - - <h2><a id="rotation" name="rotation">Log Rotation</a></h2> - - <p>On even a moderately busy server, the quantity of - information stored in the log files is very large. The access - log file typically grows 1 MB or more per 10,000 requests. It - will consequently be necessary to periodically rotate the log - files by moving or deleting the existing logs. This cannot be - done while the server is running, because Apache will continue - writing to the old log file as long as it holds the file open. - Instead, the server must be <a - href="stopping.html">restarted</a> after the log files are - moved or deleted so that it will open new log files.</p> - - <p>By using a <em>graceful</em> restart, the server can be - instructed to open new log files without losing any existing or - pending connections from clients. However, in order to - accomplish this, the server must continue to write to the old - log files while it finishes serving old requests. It is - therefore necessary to wait for some time after the restart - before doing any processing on the log files. A typical - scenario that simply rotates the logs and compresses the old - logs to save space is:</p> - - <blockquote> - <code>mv access_log access_log.old<br /> - mv error_log error_log.old<br /> - apachectl graceful<br /> - sleep 600<br /> - gzip access_log.old error_log.old</code> - </blockquote> - - <p>Another way to perform log rotation is using <a - href="#piped">piped logs</a> as discussed in the next - section.</p> - <hr /> - - <h2><a id="piped" name="piped">Piped Logs</a></h2> - - <p>Apache httpd is capable of writing error and access log - files through a pipe to another process, rather than directly - to a file. This capability dramatically increases the - flexibility of logging, without adding code to the main server. - In order to write logs to a pipe, simply replace the filename - with the pipe character "<code>|</code>", followed by the name - of the executable which should accept log entries on its - standard input. Apache will start the piped-log process when - the server starts, and will restart it if it crashes while the - server is running. (This last feature is why we can refer to - this technique as "reliable piped logging".)</p> - - <p>Piped log processes are spawned by the parent Apache httpd - process, and inherit the userid of that process. This means - that piped log programs usually run as root. It is therefore - very important to keep the programs simple and secure.</p> - - <p>Some simple examples using piped logs:</p> - - <blockquote> - <code># compressed logs<br /> - CustomLog "|/usr/bin/gzip -c >> - /var/log/access_log.gz" common<br /> - # almost-real-time name resolution<br /> - CustomLog "|/usr/local/apache/bin/logresolve >> - /var/log/access_log" common</code> - </blockquote> - - <p>Notice that quotes are used to enclose the entire command - that will be called for the pipe. Although these examples are - for the access log, the same technique can be used for the - error log.</p> - - <p>One important use of piped logs is to allow log rotation - without having to restart the server. The Apache HTTP Server - includes a simple program called <a - href="programs/rotatelogs.html">rotatelogs</a> for this - purpose. For example, to rotate the logs every 24 hours, you - can use:</p> - - <blockquote> - <code>CustomLog "|/usr/local/apache/bin/rotatelogs - /var/log/access_log 86400" common</code> - </blockquote> - - <p>A similar, but much more flexible log rotation program - called <a - href="http://www.ford-mason.co.uk/resources/cronolog/">cronolog</a> - is available at an external site.</p> - - <p>As with conditional logging, piped logs are a very powerful - tool, but they should not be used where a simpler solution like - off-line post-processing is available.</p> - <hr /> - - <h2><a id="virtualhosts" name="virtualhosts">Virtual - Hosts</a></h2> - - <p>When running a server with many <a href="vhosts/">virtual - hosts</a>, there are several options for dealing with log - files. First, it is possible to use logs exactly as in a - single-host server. Simply by placing the logging directives - outside the <code><VirtualHost></code> sections in the - main server context, it is possible to log all requests in the - same access log and error log. This technique does not allow - for easy collection of statistics on individual virtual - hosts.</p> - - <p>If <code>CustomLog</code> or <code>ErrorLog</code> - directives are placed inside a <code><VirtualHost></code> - section, all requests or errors for that virtual host will be - logged only to the specified file. Any virtual host which does - not have logging directives will still have its requests sent - to the main server logs. This technique is very useful for a - small number of virtual hosts, but if the number of hosts is - very large, it can be complicated to manage. In addition, it - can often create problems with <a - href="vhosts/fd-limits.html">insufficient file - descriptors</a>.</p> - - <p>For the access log, there is a very good compromise. By - adding information on the virtual host to the log format - string, it is possible to log all hosts to the same log, and - later split the log into individual files. For example, - consider the following directives.</p> - - <blockquote> - <code>LogFormat "%v %l %u %t \"%r\" %>s %b" - comonvhost<br /> - CustomLog logs/access_log comonvhost</code> - </blockquote> - - <p>The <code>%v</code> is used to log the name of the virtual - host that is serving the request. Then a program like <a - href="programs/other.html">split-logfile</a> can be used to - post-process the access log in order to split it into one file - per virtual host.</p> - - <p>Unfortunately, no similar technique is available for the - error log, so you must choose between mixing all virtual hosts - in the same error log and using one error log per virtual - host.</p> - <hr /> - - <h2><a id="other" name="other">Other Log Files</a></h2> - - <table border="1"> - <tr> - <td valign="top"><strong>Related Modules</strong><br /> - <br /> - <a href="mod/mod_cgi.html">mod_cgi</a><br /> - <a href="mod/mod_rewrite.html">mod_rewrite</a> </td> - - <td valign="top"><strong>Related Directives</strong><br /> - <br /> - <a href="mod/core.html#pidfile">PidFile</a><br /> - <a - href="mod/mod_rewrite.html#RewriteLog">RewriteLog</a><br /> - <a - href="mod/mod_rewrite.html#RewriteLogLevel">RewriteLogLevel</a><br /> - <a href="mod/mod_cgi.html#scriptlog">ScriptLog</a><br /> - <a - href="mod/mod_cgi.html#scriptloglength">ScriptLogLength</a><br /> - <a - href="mod/mod_cgi.html#scriptlogbuffer">ScriptLogBuffer</a> - </td> - </tr> - </table> - - <h3><a id="pidfile" name="pidfile">PID File</a></h3> - - <p>On startup, Apache httpd saves the process id of the parent - httpd process to the file <code>logs/httpd.pid</code>. This - filename can be changed with the <a - href="mod/core.html#pidfile">PidFile</a> directive. The - process-id is for use by the administrator in restarting and - terminating the daemon by sending signals to the parent - process; on Windows, use the -k command line option instead. - For more information see the <a href="stopping.html">Stopping - and Restarting</a> page.</p> - - <h3><a id="scriptlog" name="scriptlog">Script Log</a></h3> - - <p>In order to aid in debugging, the <a - href="mod/mod_cgi.html#scriptlog">ScriptLog</a> directive - allows you to record the input to and output from CGI scripts. - This should only be used in testing - not for live servers. - More information is available in the <a - href="mod/mod_cgi.html">mod_cgi documentation</a>.</p> - - <h3><a id="rewritelog" name="rewritelog">Rewrite Log</a></h3> - - <p>When using the powerful and complex features of <a - href="mod/mod_rewrite.html">mod_rewrite</a>, it is almost - always necessary to use the <a - href="mod/mod_rewrite.html#RewriteLog">RewriteLog</a> to help - in debugging. This log file produces a detailed analysis of how - the rewriting engine transforms requests. The level of detail - is controlled by the <a - href="mod/mod_rewrite.html#RewriteLogLevel">RewriteLogLevel</a> - directive.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/mod/directive-dict.html.en b/docs/manual/mod/directive-dict.html.en deleted file mode 100644 index deedf08aca..0000000000 --- a/docs/manual/mod/directive-dict.html.en +++ /dev/null @@ -1,327 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Definitions of terms used to describe Apache - directives</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Terms Used to Describe Apache - Directives</h1> - - <p>Each Apache configuration directive is described using a - common format that looks like this:</p> - - <dl> - <dd><a href="#Syntax" rel="Help"><strong>Syntax:</strong></a> - <em>directive-name</em> <em>some args</em><br /> - <a href="#Default" rel="Help"><strong>Default:</strong></a> - <samp><em>directive-name default-value</em></samp><br /> - <a href="#Context" rel="Help"><strong>Context:</strong></a> - <em>context-list</em><br /> - <a href="#Override" - rel="Help"><strong>Override:</strong></a> - <em>override</em><br /> - <a href="#Status" rel="Help"><strong>Status:</strong></a> - <em>status</em><br /> - <a href="#Module" rel="Help"><strong>Module:</strong></a> - <em>module-name</em><br /> - <a href="#Compatibility" - rel="Help"><strong>Compatibility:</strong></a> - <em>compatibility notes</em><br /> - <a href="#Deprecated" - rel="Help"><strong>Deprecated:</strong></a> <em>see - other</em></dd> - </dl> - - <p>Each of the directive's attributes, complete with possible - values where possible, are described in this document.</p> - - <h2>Directive Terms</h2> - - <ul> - <li><a href="#Syntax">Syntax</a></li> - - <li><a href="#Default">Default</a></li> - - <li><a href="#Context">Context</a></li> - - <li><a href="#Override">Override</a></li> - - <li><a href="#Status">Status</a></li> - - <li><a href="#Module">Module</a></li> - - <li><a href="#Compatibility">Compatibility</a></li> - - <li><a href="#Deprecated">Deprecated</a></li> - </ul> - <hr /> - - <h2><a id="Syntax" name="Syntax">Syntax</a></h2> - - <p>This indicates the format of the directive as it would - appear in a configuration file. This syntax is extremely - directive-specific, and is described in detail in the - directive's definition. Generally, the directive name is - followed by a series of one or more space-separated arguments. - If an argument contains a space, the argument must be enclosed - in double quotes. Optional arguments are enclosed in square - brackets. Where an argument can take on more than one possible - value, the possible values are separated by vertical bars "|". - Literal text is presented in the default font, while - argument-types for which substitution is necessary are - <em>emphasized</em>. Directives which can take a variable - number of arguments will end in "..." indicating that the last - argument is repeated.</p> - - <p>Directives use a great number of different argument types. A - few common ones are defined below.</p> - - <dl> - <dt><em>URL</em></dt> - - <dd>A complete Uniform Resource Locator including a scheme, - hostname, and optional pathname as in - <code>http://www.example.com/path/to/file.html</code></dd> - - <dt><em>URL-path</em></dt> - - <dd>The part of a <em>url</em> which follows the scheme and - hostname as in <code>/path/to/file.html</code>. The - <em>url-path</em> represents a web-view of a resource, as - opposed to a file-system view.</dd> - - <dt><em>file-path</em></dt> - - <dd>The path to a file in the local file-system beginning - with the root directory as in - <code>/usr/local/apache/htdocs/path/to/file.html</code>. - Unless otherwise specified, a <em>file-path</em> which does - not begin with a slash will be treated as relative to the <a - href="core.html#serverroot">ServerRoot</a>.</dd> - - <dt><em>directory-path</em></dt> - - <dd>The path to a directory in the local file-system - beginning with the root directory as in - <code>/usr/local/apache/htdocs/path/to/</code>.</dd> - - <dt><em>filename</em></dt> - - <dd>The name of a file with no accompanying path information - as in <code>file.html</code>.</dd> - - <dt><em>regex</em></dt> - - <dd>A regular expression, which is a way of describing a - pattern to match in text. The directive definition will - specify what the <em>regex</em> is matching against.</dd> - - <dt><em>extension</em></dt> - - <dd>In general, this is the part of the <em>filename</em> - which follows the last dot. However, Apache recognizes - multiple filename extensions, so if a <em>filename</em> - contains more than one dot, each dot-separated part of the - filename following the first dot is an <em>extension</em>. - For example, the <em>filename</em> <code>file.html.en</code> - contains two extensions: <code>.html</code> and - <code>.en</code>. For Apache directives, you may specify - <em>extension</em>s with or without the leading dot. In - addition, <em>extension</em>s are not case sensitive.</dd> - - <dt><em>MIME-type</em></dt> - - <dd>A method of describing the format of a file which - consists of a major format type and a minor format type, - separated by a slash as in <code>text/html</code>.</dd> - - <dt><em>env-variable</em></dt> - - <dd>The name of an <a href="../env.html">environment - variable</a> defined in the Apache configuration process. - Note this is not necessarily the same as an operating system - environment variable. See the <a - href="../env.html">environment variable documentation</a> for - more details.</dd> - </dl> - <hr /> - - <h2><a id="Default" name="Default">Default</a></h2> - - <p>If the directive has a default value (<em>i.e.</em>, if you - omit it from your configuration entirely, the Apache Web server - will behave as though you set it to a particular value), it is - described here. If there is no default value, this section - should say "<em>None</em>". Note that the default listed here - is not necessarily the same as the value the directive takes in - the default httpd.conf distributed with the server.</p> - <hr /> - - <h2><a id="Context" name="Context">Context</a></h2> - - <p>This indicates where in the server's configuration files the - directive is legal. It's a comma-separated list of one or more - of the following values:</p> - - <dl> - <dt><strong>server config</strong></dt> - - <dd>This means that the directive may be used in the server - configuration files (<em>e.g.</em>, <samp>httpd.conf</samp>, - <samp>srm.conf</samp>, and <samp>access.conf</samp>), but - <strong>not</strong> within any - <samp><VirtualHost></samp> or <Directory> - containers. It is not allowed in <samp>.htaccess</samp> files - at all.</dd> - - <dt><strong>virtual host</strong></dt> - - <dd>This context means that the directive may appear inside - <samp><VirtualHost></samp> containers in the server - configuration files.</dd> - - <dt><strong>directory</strong></dt> - - <dd>A directive marked as being valid in this context may be - used inside <samp><Directory></samp>, - <samp><Location></samp>, and <samp><Files></samp> - containers in the server configuration files, subject to the - restrictions outlined in <a href="../sections.html">How - Directory, Location and Files sections work</a>.</dd> - - <dt><strong>.htaccess</strong></dt> - - <dd>If a directive is valid in this context, it means that it - can appear inside <em>per</em>-directory - <samp>.htaccess</samp> files. It may not be processed, though - depending upon the <a href="#Override" - rel="Help">overrides</a> currently active.</dd> - </dl> - - <p>The directive is <em>only</em> allowed within the designated - context; if you try to use it elsewhere, you'll get a - configuration error that will either prevent the server from - handling requests in that context correctly, or will keep the - server from operating at all -- <em>i.e.</em>, the server won't - even start.</p> - - <p>The valid locations for the directive are actually the - result of a Boolean OR of all of the listed contexts. In other - words, a directive that is marked as being valid in - "<samp>server config, .htaccess</samp>" can be used in the - <samp>httpd.conf</samp> file and in <samp>.htaccess</samp> - files, but not within any <Directory> or - <VirtualHost> containers.</p> - <hr /> - - <h2><a id="Override" name="Override">Override</a></h2> - - <p>This directive attribute indicates which configuration - override must be active in order for the directive to be - processed when it appears in a <samp>.htaccess</samp> file. If - the directive's <a href="#Context" rel="Help">context</a> - doesn't permit it to appear in <samp>.htaccess</samp> files, - this attribute should say "<em>Not applicable</em>".</p> - - <p>Overrides are activated by the <a - href="core.html#allowoverride" - rel="Help"><samp>AllowOverride</samp></a> directive, and apply - to a particular scope (such as a directory) and all - descendants, unless further modified by other - <samp>AllowOverride</samp> directives at lower levels. The - documentation for that directive also lists the possible - override names available.</p> - <hr /> - - <h2><a id="Status" name="Status">Status</a></h2> - - <p>This indicates how tightly bound into the Apache Web server - the directive is; in other words, you may need to recompile the - server with an enhanced set of modules in order to gain access - to the directive and its functionality. Possible values for - this attribute are:</p> - - <dl> - <dt><strong>Core</strong></dt> - - <dd>If a directive is listed as having "Core" status, that - means it is part of the innermost portions of the Apache Web - server, and is always available.</dd> - - <dt><strong>MPM</strong></dt> - - <dd>A directive labeled as having "MPM" status is provided by - a <a href="../mpm.html">Multi-Processing Module</a>. This - type of directive will be available if and only if you are - using one of the MPMs listed on the <a - href="#Module">Module</a> line of the directive - definition.</dd> - - <dt><strong>Base</strong></dt> - - <dd>A directive labeled as having "Base" status is supported - by one of the standard Apache modules which is compiled into - the server by default, and is therefore normally available - unless you've taken steps to remove the module from your - configuration.</dd> - - <dt><strong>Extension</strong></dt> - - <dd>A directive with "Extension" status is provided by one of - the modules included with the Apache server kit, but the - module isn't normally compiled into the server. To enable the - directive and its functionality, you will need to change the - server build configuration files and re-compile Apache.</dd> - - <dt><strong>Experimental</strong></dt> - - <dd>"Experimental" status indicates that the directive is - available as part of the Apache kit, but you're on your own - if you try to use it. The directive is being documented for - completeness, and is not necessarily supported. The module - which provides the directive may or may not be compiled in by - default; check the top of the page which describes the - directive and its module to see if it remarks on the - availability.</dd> - </dl> - <hr /> - - <h2><a id="Module" name="Module">Module</a></h2> - - <p>This quite simply lists the name of the source module which - defines the directive.</p> - <hr /> - - <h2><a id="Compatibility" - name="Compatibility">Compatibility</a></h2> - - <p>If the directive wasn't part of the original Apache version - 1 distribution, the version in which it was introduced should - be listed here. If the directive has the same name as one from - the NCSA HTTPd server, any inconsistencies in behavior between - the two should also be mentioned. Otherwise, this attribute - should say "<em>No compatibility issues.</em>"</p> - <hr /> - - <h2><a id="Deprecated" name="Deprecated">Deprecated</a></h2> - - <p>If this directive is eliminated since the Apache version 1 - distribution, the directive or option that replaces the - behavior should be cited here. In general, directives, - features, and options are only deprecated to minimize debugging - of conflicting features, or if the feature can only continue to - be supported in an alternate manner.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/mod/module-dict.html.en b/docs/manual/mod/module-dict.html.en deleted file mode 100644 index 5e7cadb821..0000000000 --- a/docs/manual/mod/module-dict.html.en +++ /dev/null @@ -1,123 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Definitions of terms used to describe Apache - modules</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Terms Used to Describe Apache Modules</h1> - - <p>Each Apache module is described using a common format that - looks like this:</p> - - <dl> - <dd><a href="#Status" rel="Help"><strong>Status:</strong></a> - <em>status</em><br /> - <a href="#SourceFile" rel="Help"><strong>Source - File:</strong></a> <em>source-file</em><br /> - <a href="#ModuleIdentifier" rel="Help"><strong>Module - Identifier:</strong></a> <em>module-identifier</em><br /> - <a href="#Compatibility" - rel="Help"><strong>Compatibility:</strong></a> - <em>compatibility notes</em></dd> - </dl> - - <p>Each of the attributes, complete with values where possible, - are described in this document.</p> - - <h2>Module Terms</h2> - - <ul> - <li><a href="#Status">Status</a></li> - - <li><a href="#SourceFile">Source File</a></li> - - <li><a href="#ModuleIdentifier">Module Identifier</a></li> - - <li><a href="#Compatibility">Compatibility</a></li> - </ul> - <hr /> - - <h2><a id="Status" name="Status">Status</a></h2> - - <p>This indicates how tightly bound into the Apache Web server - the module is; in other words, you may need to recompile the - server in order to gain access to the module and its - functionality. Possible values for this attribute are:</p> - - <dl> - <dt><strong>MPM</strong></dt> - - <dd>A module with status "MPM" is a <a - href="../mpm.html">Multi-Processing Module</a>. Unlike the - other types of modules, Apache must have one and only one MPM - in use at any time. This type of module is responsible for - basic request handling and dispatching.</dd> - - <dt><strong>Base</strong></dt> - - <dd>A module labeled as having "Base" status is compiled and - loaded into the server by default, and is therefore normally - available unless you have taken steps to remove the module - from your configuration.</dd> - - <dt><strong>Extension</strong></dt> - - <dd>A module with "Extension" status is not normally compiled - and loaded into the server. To enable the module and its - functionality, you may need to change the server build - configuration files and re-compile Apache.</dd> - - <dt><strong>Experimental</strong></dt> - - <dd>"Experimental" status indicates that the module is - available as part of the Apache kit, but you are on your own - if you try to use it. The module is being documented for - completeness, and is not necessarily supported.</dd> - - <dt><strong>External</strong></dt> - - <dd>Modules which are not included with the base Apache - distribution ("third-party modules") may use the "External" - status. We are not responsible for, nor do we support such - modules.</dd> - </dl> - <hr /> - - <h2><a id="SourceFile" name="SourceFile">Source File</a></h2> - - <p>This quite simply lists the name of the source file which - contains the code for the module. This is also the name used by - the <a - href="core.html#ifmodule"><code><IfModule></code></a> - directive.</p> - <hr /> - - <h2><a id="ModuleIdentifier" name="ModuleIdentifier">Module - Identifier</a></h2> - - <p>This is a string which identifies the module for use in the - <a href="mod_so.html#loadmodule">LoadModule</a> directive when - dynamically loading modules. In particular, it is the name of - the external variable of type module in the source file.</p> - <hr /> - - <h2><a id="Compatibility" - name="Compatibility">Compatibility</a></h2> - - <p>If the module was not part of the original Apache version 2 - distribution, the version in which it was introduced should be - listed here.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/mpm.html.en b/docs/manual/mpm.html.en deleted file mode 100644 index 31aa554695..0000000000 --- a/docs/manual/mpm.html.en +++ /dev/null @@ -1,95 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Apache Multi-Processing Modules (MPMs)</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="center">Apache Multi-Processing Modules</h1> - - <p>The Apache HTTP Server is designed to be a powerful and - flexible web server that can work on a very wide variety of - platforms in a range of different environments. Different - platforms and different environments often require different - features, or may have different ways of implementing the same - feature most efficiently. Apache has always accommodated a wide - variety of environments through its modular design. This design - allows the webmaster to choose which features will be included - in the server by selecting which modules to load either at - compile-time or at run-time.</p> - - <p>Apache 2.0 extends this modular design to the most basic - functions of a web server. The server ships with a selection of - Multi-Processing Modules (MPMs) which are responsible for - binding to network ports on the machine, accepting requests, - and dispatching children to handle the requests.</p> - - <p>Extending the modular design to this level of the server - allows two important benefits:</p> - - <ul> - <li>Apache can more cleanly and efficiently support a wide - variety of operating systems. In particular, the Windows - version of Apache is now much more efficient, since <a - href="mod/mpm_winnt.html">mpm_winnt</a> can use native - networking features in place of the POSIX layer used in - Apache 1.3. This benefit also extends to other operating - systems that implement specialized MPMs.</li> - - <li>The server can be better customized for the needs of the - particular site. For example, sites that need a great deal of - scalability can choose to use a threaded MPM like <a - href="mod/threaded.html">threaded</a>, while sites requiring - stability or compatibility with older software can use a <a - href="mod/prefork.html">preforking MPM</a>. In addition, - special features like serving different hosts under different - userids (<a href="mod/perchild.html">perchild</a>) can be - provided.</li> - </ul> - - <p>At the user level, MPMs appear much like other Apache - modules. The main difference is that one and only one MPM must - be loaded into the server at any time. The list of available - MPMs appears on the <a href="mod/">module index page</a>.</p> - - <h2 align="center">Choosing an MPM</h2> - - <p>MPMs must be chosen during configuration, and compiled into - the server. Compilers are capable of optimizing a lot of - functions if threads are used, but only if they know that - threads are being used. Because some MPMs use threads on Unix - and others don't, Apache will always perform better if the MPM - is chosen at configuration time and built into Apache.</p> - - <p>To actually choose the desired MPM, use the argument - --with-mpm= <em>NAME</em> with the ./configure script. - <em>NAME</em> is the name of the desired MPM.</p> - - <p>Once the server has been compiled, it is possible to - determine which MPM was chosen by using <code>./httpd - -l</code>. This command will list every module that is compiled - into the server, including the MPM.</p> - - <h2 align="center">MPM Defaults</h2> - - <ul> - <li>BeOS: mpmt_beos</li> - - <li>OS/2: mpmt_os2</li> - - <li>Unix: prefork</li> - - <li>Windows: winnt</li> - </ul> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/sections.html.en b/docs/manual/sections.html.en deleted file mode 100644 index 9782a63a7b..0000000000 --- a/docs/manual/sections.html.en +++ /dev/null @@ -1,152 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>How Directory, Location and Files sections work</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">How Directory, Location and Files sections - work</h1> - - <p>The sections <a - href="mod/core.html#directory"><code><Directory></code></a>, - <a - href="mod/core.html#location"><code><Location></code></a> - and <a - href="mod/core.html#files"><code><Files></code></a> can - contain directives which only apply to specified directories, - URLs or files respectively. Also htaccess files can be used - inside a directory to apply directives to that directory. This - document explains how these different sections differ and how - they relate to each other when Apache decides which directives - apply for a particular directory or request URL.</p> - - <h2>Directives allowed in the sections</h2> - - <p>Everything that is syntactically allowed in - <code><Directory></code> is also allowed in - <code><Location></code> (except a - sub-<code><Files></code> section). Semantically, however - some things, most notably <code>AllowOverride</code> and the - two options <code>FollowSymLinks</code> and - <code>SymLinksIfOwnerMatch</code>, make no sense in - <code><Location></code>, - <code><LocationMatch></code> or - <code><DirectoryMatch></code>. The same for - <code><Files></code> -- syntactically everything is fine, - but semantically some things are different.</p> - - <h2>How the sections are merged</h2> - - <p>The order of merging is:</p> - - <ol> - <li><code><Directory></code> (except regular - expressions) and .htaccess done simultaneously (with - .htaccess, if allowed, overriding - <code><Directory></code>)</li> - - <li><code><DirectoryMatch></code>, and - <code><Directory></code> with regular expressions</li> - - <li><code><Files></code> and - <code><FilesMatch></code> done simultaneously</li> - - <li><code><Location></code> and - <code><LocationMatch></code> done simultaneously</li> - </ol> - - <p>Apart from <code><Directory></code>, each group is - processed in the order that they appear in the configuration - files. <code><Directory></code> (group 1 above) is - processed in the order shortest directory component to longest. - If multiple <code><Directory></code> sections apply to - the same directory they they are processed in the configuration - file order. The configuration files are read in the order - httpd.conf, srm.conf and access.conf. Configurations included - via the <code>Include</code> directive will be treated as if - they were inside the including file at the location of the - <code>Include</code> directive.</p> - - <p>Sections inside <code><VirtualHost></code> sections - are applied <em>after</em> the corresponding sections outside - the virtual host definition. This allows virtual hosts to - override the main server configuration.</p> - - <p>Later sections override earlier ones.</p> - - <h2>Notes about using sections</h2> - - <p>The general guidelines are:</p> - - <ul> - <li>If you are attempting to match objects at the filesystem - level then you must use <code><Directory></code> and/or - <code><Files></code>.</li> - - <li>If you are attempting to match objects at the URL level - then you must use <code><Location></code></li> - </ul> - - <p>But a notable exception is:</p> - - <ul> - <li>proxy control is done via <code><Directory></code>. - This is a legacy mistake because the proxy existed prior to - <code><Location></code>. A future version of the config - language should probably switch this to - <code><Location></code>.</li> - </ul> - - <p>Note about .htaccess parsing:</p> - - <ul> - <li>Modifying .htaccess parsing during Location doesn't do - anything because .htaccess parsing has already occurred.</li> - </ul> - - <p><code><Location></code> and symbolic links:</p> - - <ul> - <li>It is not possible to use "<code>Options - FollowSymLinks</code>" or "<code>Options - SymLinksIfOwnerMatch</code>" inside a - <code><Location></code>, - <code><LocationMatch></code> or - <code><DirectoryMatch></code> section (the options are - simply ignored). Using the options in question is only - possible inside a <code><Directory></code> section (or - a <code>.htaccess</code> file).</li> - </ul> - - <p><code><Files></code> and <code>Options</code>:</p> - - <ul> - <li>Apache won't check for it, but using an - <code>Options</code> directive inside a - <code><Files></code> section has no effect.</li> - </ul> - - <p>Another note:</p> - - <ul> - <li>There is actually a - <code><Location></code>/<code><LocationMatch></code> - sequence performed just before the name translation phase - (where <code>Aliases</code> and <code>DocumentRoots</code> - are used to map URLs to filenames). The results of this - sequence are completely thrown away after the translation has - completed.</li> - </ul> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/ssl/index.html.en b/docs/manual/ssl/index.html.en deleted file mode 100644 index 971686a1b7..0000000000 --- a/docs/manual/ssl/index.html.en +++ /dev/null @@ -1,36 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> -<title>Apache SSL/TLS Encryption</title> -</head> - -<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#000080" alink="#FF0000"> -<!--#include virtual="header.html" --> - -<h1 align="CENTER">SSL/TLS Strong Encryption</h1> - -<p>The Apache HTTP Server module <a href="../mod/mod_ssl.html">mod_ssl</a> -provides an interface to the <a -href="http://www.openssl.org/">OpenSSL</a> library, which provides -Strong Encryption using the Secure Sockets Layer and Transport Layer -Security protocols. The module and this documentation are based on -Ralf S. Engelschall's mod_ssl project.</p> - -<ul> -<li><a href="ssl_intro.html">Introduction</a></li> -<li><a href="ssl_compat.html">Compatibility</a></li> -<li><a href="ssl_howto.html">How-To</a></li> -<li><a href="ssl_faq.html">Frequently Asked Questions</a></li> -<li><a href="ssl_glossary.html">Glossary</a></li> -</ul> - -<p>Extensive documentation on the directives and environment variables -provided by this module is provided in the <a -href="../mod/mod_ssl.html">mod_ssl reference documentation</a>.</p> - - -<p><!--#include virtual="footer.html" --> </p> - </body> -</html> diff --git a/docs/manual/stopping.html.en b/docs/manual/stopping.html.en deleted file mode 100644 index 89c1a58a3e..0000000000 --- a/docs/manual/stopping.html.en +++ /dev/null @@ -1,209 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Stopping and Restarting the Server</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Stopping and Restarting the Server</h1> - - <p>This document covers stopping and restarting Apache on - Unix-like systems. Windows users should see <a - href="platform/windows.html#signal">Signalling Apache when - running</a>.</p> - - <p>You will notice many <code>httpd</code> executables running - on your system, but you should not send signals to any of them - except the parent, whose pid is in the <a - href="mod/core.html#pidfile">PidFile</a>. That is to say you - shouldn't ever need to send signals to any process except the - parent. There are three signals that you can send the parent: - <code>TERM</code>, <code>HUP</code>, and <code>USR1</code>, - which will be described in a moment.</p> - - <p>To send a signal to the parent you should issue a command - such as:</p> - - <blockquote> -<pre> - kill -TERM `cat /usr/local/apache/logs/httpd.pid` -</pre> - </blockquote> - You can read about its progress by issuing: - - <blockquote> -<pre> - tail -f /usr/local/apache/logs/error_log -</pre> - </blockquote> - Modify those examples to match your <a - href="mod/core.html#serverroot">ServerRoot</a> and <a - href="mod/core.html#pidfile">PidFile</a> settings. - - <p>A shell script called <a - href="programs/apachectl.html">apachectl</a> is provided which - automates the processing of signalling Apache. For details - about this script, see the documentation on <a - href="invoking.html">starting Apache</a>.</p> - - <h3>Stop Now</h3> - - <p><strong>Signal:</strong> TERM<br /> - <code>apachectl stop</code></p> - - <p>Sending the <code>TERM</code> signal to the parent causes it - to immediately attempt to kill off all of its children. It may - take it several seconds to complete killing off its children. - Then the parent itself exits. Any requests in progress are - terminated, and no further requests are served.</p> - - <h3>Graceful Restart</h3> - - <p><strong>Signal:</strong> USR1<br /> - <code>apachectl graceful</code></p> - - <p>The <code>USR1</code> signal causes the parent process to - <em>advise</em> the children to exit after their current - request (or to exit immediately if they're not serving - anything). The parent re-reads its configuration files and - re-opens its log files. As each child dies off the parent - replaces it with a child from the new <em>generation</em> of - the configuration, which begins serving new requests - immediately.</p> - <i>On certain platforms that do not allow USR1 to be used for a - graceful restart, an alternative signal may be used (such as - WINCH). apachectl graceful will send the right signal for your - platform.</i> - - <p>This code is designed to always respect the <a - href="mod/mpm_common.html#maxclients">MaxClients</a>, <a - href="mod/prefork.html#minspareservers">MinSpareServers</a>, - and <a - href="mod/prefork.html#maxspareservers">MaxSpareServers</a> - settings. Furthermore, it respects <a - href="mod/mpm_common.html#startservers">StartServers</a> in the - following manner: if after one second at least StartServers new - children have not been created, then create enough to pick up - the slack. This is to say that the code tries to maintain both - the number of children appropriate for the current load on the - server, and respect your wishes with the StartServers - parameter.</p> - - <p>Users of the <a href="mod/mod_status.html">status module</a> - will notice that the server statistics are <strong>not</strong> - set to zero when a <code>USR1</code> is sent. The code was - written to both minimize the time in which the server is unable - to serve new requests (they will be queued up by the operating - system, so they're not lost in any event) and to respect your - tuning parameters. In order to do this it has to keep the - <em>scoreboard</em> used to keep track of all children across - generations.</p> - - <p>The status module will also use a <code>G</code> to indicate - those children which are still serving requests started before - the graceful restart was given.</p> - - <p>At present there is no way for a log rotation script using - <code>USR1</code> to know for certain that all children writing - the pre-restart log have finished. We suggest that you use a - suitable delay after sending the <code>USR1</code> signal - before you do anything with the old log. For example if most of - your hits take less than 10 minutes to complete for users on - low bandwidth links then you could wait 15 minutes before doing - anything with the old log.</p> - - <p><strong>Note:</strong> If your configuration file has errors - in it when you issue a restart then your parent will not - restart, it will exit with an error. In the case of graceful - restarts it will also leave children running when it exits. - (These are the children which are "gracefully exiting" by - handling their last request.) This will cause problems if you - attempt to restart the server -- it will not be able to bind to - its listening ports. Before doing a restart, you can check the - syntax of the configuration files with the <code>-t</code> - command line argument (see <a - href="programs/httpd.html">httpd</a>). This still will not - guarantee that the server will restart correctly. To check the - semantics of the configuration files as well as the syntax, you - can try starting httpd as a non-root user. If there are no - errors it will attempt to open its sockets and logs and fail - because it's not root (or because the currently running httpd - already has those ports bound). If it fails for any other - reason then it's probably a config file error and the error - should be fixed before issuing the graceful restart.</p> - - <h3>Restart Now</h3> - - <p><strong>Signal:</strong> HUP<br /> - <code>apachectl restart</code></p> - - <p>Sending the <code>HUP</code> signal to the parent causes it - to kill off its children like in <code>TERM</code> but the - parent doesn't exit. It re-reads its configuration files, and - re-opens any log files. Then it spawns a new set of children - and continues serving hits.</p> - - <p>Users of the <a href="mod/mod_status.html">status module</a> - will notice that the server statistics are set to zero when a - <code>HUP</code> is sent.</p> - - <p><strong>Note:</strong> If your configuration file has errors - in it when you issue a restart then your parent will not - restart, it will exit with an error. See below for a method of - avoiding this.</p> - - <h3>Appendix: signals and race conditions</h3> - - <p>Prior to Apache 1.2b9 there were several <em>race - conditions</em> involving the restart and die signals (a simple - description of race condition is: a time-sensitive problem, as - in if something happens at just the wrong time it won't behave - as expected). For those architectures that have the "right" - feature set we have eliminated as many as we can. But it should - be noted that there still do exist race conditions on certain - architectures.</p> - - <p>Architectures that use an on disk <a - href="mod/core.html#scoreboardfile">ScoreBoardFile</a> have the - potential to corrupt their scoreboards. This can result in the - "bind: Address already in use" (after <code>HUP</code>) or - "long lost child came home!" (after <code>USR1</code>). The - former is a fatal error, while the latter just causes the - server to lose a scoreboard slot. So it might be advisable to - use graceful restarts, with an occasional hard restart. These - problems are very difficult to work around, but fortunately - most architectures do not require a scoreboard file. See the <a - href="mod/core.html#scoreboardfile">ScoreBoardFile</a> - documentation for a architecture uses it.</p> - - <p><code>NEXT</code> and <code>MACHTEN</code> (68k only) have - small race conditions which can cause a restart/die signal to - be lost, but should not cause the server to do anything - otherwise problematic. - <!-- they don't have sigaction, or we're not using it -djg --> - </p> - - <p>All architectures have a small race condition in each child - involving the second and subsequent requests on a persistent - HTTP connection (KeepAlive). It may exit after reading the - request line but before reading any of the request headers. - There is a fix that was discovered too late to make 1.2. In - theory this isn't an issue because the KeepAlive client has to - expect these events because of network latencies and server - timeouts. In practice it doesn't seem to affect anything either - -- in a test case the server was restarted twenty times per - second and clients successfully browsed the site without - getting broken images or empty documents. - <!--#include virtual="footer.html" --> - </p> - </body> -</html> - diff --git a/docs/manual/suexec.html.en b/docs/manual/suexec.html.en deleted file mode 100644 index 42098e6a03..0000000000 --- a/docs/manual/suexec.html.en +++ /dev/null @@ -1,620 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Apache suEXEC Support</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Apache suEXEC Support</h1> - - <ol> - <li><big><strong>CONTENTS</strong></big></li> - - <li><a href="#what">What is suEXEC?</a></li> - - <li><a href="#before">Before we begin.</a></li> - - <li><a href="#model">suEXEC Security Model.</a></li> - - <li><a href="#install">Configuring & Installing - suEXEC</a></li> - - <li><a href="#enable">Enabling & Disabling - suEXEC</a></li> - - <li><a href="#usage">Using suEXEC</a></li> - - <li><a href="#debug">Debugging suEXEC</a></li> - - <li><a href="#jabberwock">Beware the Jabberwock: Warnings - & Examples</a></li> - </ol> - <br /> - <br /> - - - <h3><a id="what" name="what">What is suEXEC?</a></h3> - - <p align="LEFT">The <strong>suEXEC</strong> feature -- - introduced in Apache 1.2 -- provides Apache users the ability - to run <strong>CGI</strong> and <strong>SSI</strong> programs - under user IDs different from the user ID of the calling - web-server. Normally, when a CGI or SSI program executes, it - runs as the same user who is running the web server.</p> - - <p align="LEFT">Used properly, this feature can reduce - considerably the security risks involved with allowing users to - develop and run private CGI or SSI programs. However, if suEXEC - is improperly configured, it can cause any number of problems - and possibly create new holes in your computer's security. If - you aren't familiar with managing setuid root programs and the - security issues they present, we highly recommend that you not - consider using suEXEC.</p> - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - - <h3><a id="before" name="before">Before we begin.</a></h3> - - <p align="LEFT">Before jumping head-first into this document, - you should be aware of the assumptions made on the part of the - Apache Group and this document.</p> - - <p align="LEFT">First, it is assumed that you are using a UNIX - derivate operating system that is capable of - <strong>setuid</strong> and <strong>setgid</strong> operations. - All command examples are given in this regard. Other platforms, - if they are capable of supporting suEXEC, may differ in their - configuration.</p> - - <p align="LEFT">Second, it is assumed you are familiar with - some basic concepts of your computer's security and its - administration. This involves an understanding of - <strong>setuid/setgid</strong> operations and the various - effects they may have on your system and its level of - security.</p> - - <p align="LEFT">Third, it is assumed that you are using an - <strong>unmodified</strong> version of suEXEC code. All code - for suEXEC has been carefully scrutinized and tested by the - developers as well as numerous beta testers. Every precaution - has been taken to ensure a simple yet solidly safe base of - code. Altering this code can cause unexpected problems and new - security risks. It is <strong>highly</strong> recommended you - not alter the suEXEC code unless you are well versed in the - particulars of security programming and are willing to share - your work with the Apache Group for consideration.</p> - - <p align="LEFT">Fourth, and last, it has been the decision of - the Apache Group to <strong>NOT</strong> make suEXEC part of - the default installation of Apache. To this end, suEXEC - configuration requires of the administrator careful attention - to details. After due consideration has been given to the - various settings for suEXEC, the administrator may install - suEXEC through normal installation methods. The values for - these settings need to be carefully determined and specified by - the administrator to properly maintain system security during - the use of suEXEC functionality. It is through this detailed - process that the Apache Group hopes to limit suEXEC - installation only to those who are careful and determined - enough to use it.</p> - - <p align="LEFT">Still with us? Yes? Good. Let's move on!</p> - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - - <h3><a id="model" name="model">suEXEC Security Model</a></h3> - - <p align="LEFT">Before we begin configuring and installing - suEXEC, we will first discuss the security model you are about - to implement. By doing so, you may better understand what - exactly is going on inside suEXEC and what precautions are - taken to ensure your system's security.</p> - - <p align="LEFT"><strong>suEXEC</strong> is based on a setuid - "wrapper" program that is called by the main Apache web server. - This wrapper is called when an HTTP request is made for a CGI - or SSI program that the administrator has designated to run as - a userid other than that of the main server. When such a - request is made, Apache provides the suEXEC wrapper with the - program's name and the user and group IDs under which the - program is to execute.</p> - - <p align="LEFT">The wrapper then employs the following process - to determine success or failure -- if any one of these - conditions fail, the program logs the failure and exits with an - error, otherwise it will continue:</p> - - <ol> - <li> - <strong>Was the wrapper called with the proper number of - arguments?</strong> - - <blockquote> - The wrapper will only execute if it is given the proper - number of arguments. The proper argument format is known - to the Apache web server. If the wrapper is not receiving - the proper number of arguments, it is either being - hacked, or there is something wrong with the suEXEC - portion of your Apache binary. - </blockquote> - </li> - - <li> - <strong>Is the user executing this wrapper a valid user of - this system?</strong> - - <blockquote> - This is to ensure that the user executing the wrapper is - truly a user of the system. - </blockquote> - </li> - - <li> - <strong>Is this valid user allowed to run the - wrapper?</strong> - - <blockquote> - Is this user the user allowed to run this wrapper? Only - one user (the Apache user) is allowed to execute this - program. - </blockquote> - </li> - - <li> - <strong>Does the target program have an unsafe hierarchical - reference?</strong> - - <blockquote> - Does the target program contain a leading '/' or have a - '..' backreference? These are not allowed; the target - program must reside within the Apache webspace. - </blockquote> - </li> - - <li> - <strong>Is the target user name valid?</strong> - - <blockquote> - Does the target user exist? - </blockquote> - </li> - - <li> - <strong>Is the target group name valid?</strong> - - <blockquote> - Does the target group exist? - </blockquote> - </li> - - <li> - <strong>Is the target user <em>NOT</em> superuser?</strong> - - - <blockquote> - Presently, suEXEC does not allow 'root' to execute - CGI/SSI programs. - </blockquote> - </li> - - <li> - <strong>Is the target userid <em>ABOVE</em> the minimum ID - number?</strong> - - <blockquote> - The minimum user ID number is specified during - configuration. This allows you to set the lowest possible - userid that will be allowed to execute CGI/SSI programs. - This is useful to block out "system" accounts. - </blockquote> - </li> - - <li> - <strong>Is the target group <em>NOT</em> the superuser - group?</strong> - - <blockquote> - Presently, suEXEC does not allow the 'root' group to - execute CGI/SSI programs. - </blockquote> - </li> - - <li> - <strong>Is the target groupid <em>ABOVE</em> the minimum ID - number?</strong> - - <blockquote> - The minimum group ID number is specified during - configuration. This allows you to set the lowest possible - groupid that will be allowed to execute CGI/SSI programs. - This is useful to block out "system" groups. - </blockquote> - </li> - - <li> - <strong>Can the wrapper successfully become the target user - and group?</strong> - - <blockquote> - Here is where the program becomes the target user and - group via setuid and setgid calls. The group access list - is also initialized with all of the groups of which the - user is a member. - </blockquote> - </li> - - <li> - <strong>Does the directory in which the program resides - exist?</strong> - - <blockquote> - If it doesn't exist, it can't very well contain files. - </blockquote> - </li> - - <li> - <strong>Is the directory within the Apache - webspace?</strong> - - <blockquote> - If the request is for a regular portion of the server, is - the requested directory within the server's document - root? If the request is for a UserDir, is the requested - directory within the user's document root? - </blockquote> - </li> - - <li> - <strong>Is the directory <em>NOT</em> writable by anyone - else?</strong> - - <blockquote> - We don't want to open up the directory to others; only - the owner user may be able to alter this directories - contents. - </blockquote> - </li> - - <li> - <strong>Does the target program exist?</strong> - - <blockquote> - If it doesn't exists, it can't very well be executed. - </blockquote> - </li> - - <li> - <strong>Is the target program <em>NOT</em> writable by - anyone else?</strong> - - <blockquote> - We don't want to give anyone other than the owner the - ability to change the program. - </blockquote> - </li> - - <li> - <strong>Is the target program <em>NOT</em> setuid or - setgid?</strong> - - <blockquote> - We do not want to execute programs that will then change - our UID/GID again. - </blockquote> - </li> - - <li> - <strong>Is the target user/group the same as the program's - user/group?</strong> - - <blockquote> - Is the user the owner of the file? - </blockquote> - </li> - - <li> - <strong>Can we successfully clean the process environment - to ensure safe operations?</strong> - - <blockquote> - suEXEC cleans the process' environment by establishing a - safe execution PATH (defined during configuration), as - well as only passing through those variables whose names - are listed in the safe environment list (also created - during configuration). - </blockquote> - </li> - - <li> - <strong>Can we successfully become the target program and - execute?</strong> - - <blockquote> - Here is where suEXEC ends and the target program begins. - </blockquote> - </li> - </ol> - <br /> - <br /> - - - <p align="LEFT">This is the standard operation of the the - suEXEC wrapper's security model. It is somewhat stringent and - can impose new limitations and guidelines for CGI/SSI design, - but it was developed carefully step-by-step with security in - mind.</p> - - <p align="LEFT">For more information as to how this security - model can limit your possibilities in regards to server - configuration, as well as what security risks can be avoided - with a proper suEXEC setup, see the <a - href="#jabberwock">"Beware the Jabberwock"</a> section of this - document.</p> - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - - <h3><a id="install" name="install">Configuring & Installing - suEXEC</a></h3> - - <p align="LEFT">Here's where we begin the fun. If you use - Apache 1.2 or prefer to configure Apache 1.3 with the - "<code>src/Configure</code>" script you have to edit the suEXEC - header file and install the binary in its proper location - manually. The following sections describe the configuration and - installation for Apache 1.3 with the AutoConf-style interface - (APACI).</p> - - <p align="LEFT"><strong>APACI's suEXEC configuration - options</strong><br /> - </p> - - <dl> - <dt><code>--enable-suexec</code></dt> - - <dd>This option enables the suEXEC feature which is never - installed or activated by default. At least one - --suexec-xxxxx option has to be provided together with the - --enable-suexec option to let APACI accept your request for - using the suEXEC feature.</dd> - - <dt><code>--suexec-caller=<em>UID</em></code></dt> - - <dd>The <a href="mod/mpm_common.html#user">username</a> under which - Apache normally runs. This is the only user allowed to - execute this program.</dd> - - <dt><code>--suexec-docroot=<em>DIR</em></code></dt> - - <dd>Define as the DocumentRoot set for Apache. This will be - the only hierarchy (aside from UserDirs) that can be used for - suEXEC behavior. The default directory is the --datadir value - with the suffix "/htdocs", <em>e.g.</em> if you configure - with "<code>--datadir=/home/apache</code>" the directory - "/home/apache/htdocs" is used as document root for the suEXEC - wrapper.</dd> - - <dt><code>--suexec-logfile=<em>FILE</em></code></dt> - - <dd>This defines the filename to which all suEXEC - transactions and errors are logged (useful for auditing and - debugging purposes). By default the logfile is named - "suexec_log" and located in your standard logfile directory - (--logfiledir).</dd> - - <dt><code>--suexec-userdir=<em>DIR</em></code></dt> - - <dd>Define to be the subdirectory under users' home - directories where suEXEC access should be allowed. All - executables under this directory will be executable by suEXEC - as the user so they should be "safe" programs. If you are - using a "simple" UserDir directive (ie. one without a "*" in - it) this should be set to the same value. suEXEC will not - work properly in cases where the UserDir directive points to - a location that is not the same as the user's home directory - as referenced in the passwd file. Default value is - "public_html".<br /> - If you have virtual hosts with a different UserDir for each, - you will need to define them to all reside in one parent - directory; then name that parent directory here. <strong>If - this is not defined properly, "~userdir" cgi requests will - not work!</strong></dd> - - <dt><code>--suexec-uidmin=<em>UID</em></code></dt> - - <dd>Define this as the lowest UID allowed to be a target user - for suEXEC. For most systems, 500 or 100 is common. Default - value is 100.</dd> - - <dt><code>--suexec-gidmin=<em>GID</em></code></dt> - - <dd>Define this as the lowest GID allowed to be a target - group for suEXEC. For most systems, 100 is common and - therefore used as default value.</dd> - - <dt><code>--suexec-safepath=<em>PATH</em></code></dt> - - <dd>Define a safe PATH environment to pass to CGI - executables. Default value is - "/usr/local/bin:/usr/bin:/bin".</dd> - </dl> - <br /> - <br /> - - - <p align="LEFT"><strong>Checking your suEXEC - setup</strong><br /> - Before you compile and install the suEXEC wrapper you can - check the configuration with the --layout option.<br /> - Example output:</p> -<pre> - suEXEC setup: - suexec binary: /usr/local/apache/sbin/suexec - document root: /usr/local/apache/share/htdocs - userdir suffix: public_html - logfile: /usr/local/apache/var/log/suexec_log - safe path: /usr/local/bin:/usr/bin:/bin - caller ID: www - minimum user ID: 100 - minimum group ID: 100 -</pre> - <br /> - <br /> - - - <p align="LEFT"><strong>Compiling and installing the suEXEC - wrapper</strong><br /> - If you have enabled the suEXEC feature with the - --enable-suexec option the suexec binary (together with Apache - itself) is automatically built if you execute the command - "make".<br /> - After all components have been built you can execute the - command "make install" to install them. The binary image - "suexec" is installed in the directory defined by the --sbindir - option. Default location is - "/usr/local/apache/sbin/suexec".<br /> - Please note that you need <strong><em>root - privileges</em></strong> for the installation step. In order - for the wrapper to set the user ID, it must be installed as - owner <code><em>root</em></code> and must have the setuserid - execution bit set for file modes.</p> - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - - <h3><a id="enable" name="enable">Enabling & Disabling - suEXEC</a></h3> - - <p align="LEFT">Upon startup of Apache, it looks for the file - "suexec" in the "sbin" directory (default is - "/usr/local/apache/sbin/suexec"). If Apache finds a properly - configured suEXEC wrapper, it will print the following message - to the error log:</p> -<pre> - [notice] suEXEC mechanism enabled (wrapper: <em>/path/to/suexec</em>) -</pre> - If you don't see this message at server startup, the server is - most likely not finding the wrapper program where it expects - it, or the executable is not installed <em>setuid root</em>. - <br /> - If you want to enable the suEXEC mechanism for the first time - and an Apache server is already running you must kill and - restart Apache. Restarting it with a simple HUP or USR1 signal - will not be enough. <br /> - If you want to disable suEXEC you should kill and restart - Apache after you have removed the "suexec" file. <br /> - <br /> - - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - - <h3><a id="usage" name="usage">Using suEXEC</a></h3> - - <p align="LEFT"><strong>Virtual Hosts:</strong><br /> - One way to use the suEXEC wrapper is through the <a - href="mod/mpm_common.html#user">User</a> and <a - href="mod/mpm_common.html#group">Group</a> directives in <a - href="mod/core.html#virtualhost">VirtualHost</a> definitions. - By setting these directives to values different from the main - server user ID, all requests for CGI resources will be executed - as the <em>User</em> and <em>Group</em> defined for that - <code><VirtualHost></code>. If only one or neither of - these directives are specified for a - <code><VirtualHost></code> then the main server userid is - assumed.</p> - - <p><strong>User directories:</strong><br /> - The suEXEC wrapper can also be used to execute CGI programs as - the user to which the request is being directed. This is - accomplished by using the "<strong><code>~</code></strong>" - character prefixing the user ID for whom execution is desired. - The only requirement needed for this feature to work is for CGI - execution to be enabled for the user and that the script must - meet the scrutiny of the <a href="#model">security checks</a> - above.</p> - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - - <h3><a id="debug" name="debug">Debugging suEXEC</a></h3> - - <p align="LEFT">The suEXEC wrapper will write log information - to the file defined with the --suexec-logfile option as - indicated above. If you feel you have configured and installed - the wrapper properly, have a look at this log and the error_log - for the server to see where you may have gone astray.</p> - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - - <h3><a id="jabberwock" name="jabberwock">Beware the Jabberwock: - Warnings & Examples</a></h3> - - <p align="LEFT"><strong>NOTE!</strong> This section may not be - complete. For the latest revision of this section of the - documentation, see the Apache Group's <a - href="http://www.apache.org/docs/suexec.html">Online - Documentation</a> version.</p> - - <p align="LEFT">There are a few points of interest regarding - the wrapper that can cause limitations on server setup. Please - review these before submitting any "bugs" regarding suEXEC.</p> - - <ul> - <li><strong>suEXEC Points Of Interest</strong></li> - - <li> - Hierarchy limitations - - <blockquote> - For security and efficiency reasons, all suexec requests - must remain within either a top-level document root for - virtual host requests, or one top-level personal document - root for userdir requests. For example, if you have four - VirtualHosts configured, you would need to structure all - of your VHosts' document roots off of one main Apache - document hierarchy to take advantage of suEXEC for - VirtualHosts. (Example forthcoming.) - </blockquote> - </li> - - <li> - suEXEC's PATH environment variable - - <blockquote> - This can be a dangerous thing to change. Make certain - every path you include in this define is a - <strong>trusted</strong> directory. You don't want to - open people up to having someone from across the world - running a trojan horse on them. - </blockquote> - </li> - - <li> - Altering the suEXEC code - - <blockquote> - Again, this can cause <strong>Big Trouble</strong> if you - try this without knowing what you are doing. Stay away - from it if at all possible. - </blockquote> - </li> - </ul> - - <p align="CENTER"><strong><a href="suexec.html">BACK TO - CONTENTS</a></strong></p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/urlmapping.html.en b/docs/manual/urlmapping.html.en deleted file mode 100755 index 627dcf053f..0000000000 --- a/docs/manual/urlmapping.html.en +++ /dev/null @@ -1,296 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Mapping URLs to Filesystem Locations - Apache HTTP - Server</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="center">Mapping URLs to Filesystem Locations</h1> - - <p>This document explains how Apache uses the URL of a request - to determine the filesystem location from which to serve a - file.</p> - - <ul> - <li><a href="#documentroot">DocumentRoot</a></li> - - <li><a href="#outside">Files Outside the - DocumentRoot</a></li> - - <li><a href="#user">User Directories</a></li> - - <li><a href="#redirect">URL Redirection</a></li> - - <li><a href="#rewrite">Rewrite Engine</a></li> - - <li><a href="#notfound">File Not Found</a></li> - </ul> - <hr /> - - <table border="1"> - <tr> - <td valign="top"><strong>Related Modules</strong><br /> - <br /> - <a href="mod/mod_alias.html">mod_alias</a><br /> - <a href="mod/mod_rewrite.html">mod_rewrite</a><br /> - <a href="mod/mod_userdir.html">mod_userdir</a><br /> - <a href="mod/mod_speling.html">mod_speling</a><br /> - <a - href="mod/mod_vhost_alias.html">mod_vhost_alias</a><br /> - </td> - - <td valign="top"><strong>Related Directives</strong><br /> - <br /> - <a href="mod/mod_alias.html#alias">Alias</a><br /> - <a - href="mod/mod_alias.html#aliasmatch">AliasMatch</a><br /> - <a - href="mod/mod_speling.html#checkspelling">CheckSpelling</a><br /> - <a - href="mod/core.html#documentroot">DocumentRoot</a><br /> - <a - href="mod/core.html#errordocument">ErrorDocument</a><br /> - <a href="mod/core.html#options">Options</a><br /> - <a href="mod/mod_alias.html#redirect">Redirect</a><br /> - <a - href="mod/mod_alias.html#redirectmatch">RedirectMatch</a><br /> - <a - href="mod/mod_rewrite.html#RewriteCond">RewriteCond</a><br /> - <a - href="mod/mod_rewrite.html#RewriteRule">RewriteRule</a><br /> - <a - href="mod/mod_alias.html#scriptalias">ScriptAlias</a><br /> - <a - href="mod/mod_alias.html#scriptaliasmatch">ScriptAliasMatch</a><br /> - <a href="mod/mod_userdir.html#userdir">UserDir</a><br /> - </td> - </tr> - </table> - - <h2><a id="documentroot" - name="documentroot">DocumentRoot</a></h2> - - <p>In deciding what file to serve for a given request, Apache's - default behavior is to take the URL-Path for the request (the - part of the URL following the hostname and port) and add it to - the end of the <a - href="mod/core.html#documentroot">DocumentRoot</a> specified in - your configuration files. Therefore, the files and directories - underneath the <code>DocumentRoot</code> make up the basic - document tree which will be visible from the web.</p> - - <p>Apache is also capable of <a href="vhosts/">Virtual - Hosting</a>, where the server receives requests for more than - one host. In this case, a different <code>DocumentRoot</code> - can be specified for each virtual host, or alternatively, the - directives provided by the module <a - href="mod/mod_vhost_alias.html">mod_vhost_alias</a> can be used - to dynamically determine the appropriate place from which to - serve content based on the requested IP address or - hostname.</p> - - <h2><a id="outside" name="outside">Files Outside the - DocumentRoot</a></h2> - - <p>There are frequently circumstances where it is necessary to - allow web access to parts of the filesystem that are not - strictly underneath the <a - href="mod/core.html#documentroot">DocumentRoot</a>. Apache - offers several different ways to accomplish this. On Unix - systems, symbolic links can bring other parts of the filesystem - under the <code>DocumentRoot</code>. For security reasons, - Apache will follow symbolic links only if the <a - href="mod/core.html#options">Options</a> setting for the - relevant directory includes <code>FollowSymLinks</code> or - <code>SymLinksIfOwnerMatch</code>.</p> - - <p>Alternatively, the <a - href="mod/mod_alias.html#alias">Alias</a> directive will map - any part of the filesystem into the web space. For example, - with</p> - - <blockquote> - <code>Alias /docs /var/web/</code> - </blockquote> - - <p>the URL - <code>http://www.example.com/docs/dir/file.html</code> will be - served from <code>/var/web/dir/file.html</code>. The <a - href="mod/mod_alias.html#scriptalias">ScriptAlias</a> directive - works the same way, with the additional effect that all content - located at the target path is treated as CGI scripts.</p> - - <p>For situations where you require additional flexibility, you - can use the <a - href="mod/mod_alias.html#aliasmatch">AliasMatch</a> and <a - href="mod/mod_alias.html#scriptaliasmatch">ScriptAliasMatch</a> - directives to do powerful regular-expression based matching and - substitution. For example,</p> - - <blockquote> - <code>ScriptAliasMatch ^/~([^/]*)/cgi-bin/(.*) - /home/$1/cgi-bin/$2</code> - </blockquote> - - <p>will map a request to - <code>http://example.com/~user/cgi-bin/script.cgi</code> to the - path <code>/home/user/cgi-bin/script.cgi</code> and will treat - the resulting file as a CGI script.</p> - - <h2><a id="user" name="user">User Directories</a></h2> - - <p>Traditionally on Unix systems, the home directory of a - particular <em>user</em> can be referred to as - <code>~user/</code>. The module <a - href="mod/mod_userdir.html">mod_userdir</a> extends this idea - to the web by allowing files under each user's home directory - to be accessed using URLs such as the following.</p> - - <blockquote> - <code>http://www.example.com/~user/file.html</code> - </blockquote> - - <p>For security reasons, it is inappropriate to give direct - access to a user's home directory from the web. Therefore, the - <a href="mod/mod_userdir.html#userdir">UserDir</a> directive - specifies a directory underneath the user's home directory - where web files are located. Using the default setting of - <code>Userdir public_html</code>, the above URL maps to a file - at a directory like - <code>/home/user/public_html/file.html</code> where - <code>/home/user/</code> is the user's home directory as - specified in <code>/etc/passwd</code>.</p> - - <p>There are also several other forms of the - <code>Userdir</code> directive which you can use on systems - where <code>/etc/passwd</code> does not contain the location of - the home directory.</p> - - <p>Some people find the "~" symbol (which is often encoded on - the web as <code>%7e</code>) to be awkward and prefer to use an - alternate string to represent user directories. This - functionality is not supported by mod_userdir. However, if - users' home directories are structured in a regular way, then - it is possible to use the <a - href="mod/mod_alias.html#aliasmatch">AliasMatch</a> directive - to achieve the desired effect. For example, to make - <code>http://www.example.com/upages/user/file.html</code> map - to <code>/home/user/public_html/file.html</code>, use the - following <code>AliasMatch</code> directive:</p> - - <blockquote> - <code>AliasMatch ^/upages/([^/]*)/?(.*) - /home/$1/public_html/$2</code> - </blockquote> - - <h2><a id="redirect" name="redirect">URL Redirection</a></h2> - - <p>The configuration directives discussed in the above sections - tell Apache to get content from a specific place in the - filesystem and return it to the client. Sometimes, it is - desirable instead to inform the client that the requested - content is located at a different URL, and instruct the client - to make a new request with the new URL. This is called - <em>redirection</em> and is implemented by the <a - href="mod/mod_alias.html#redirect">Redirect</a> directive. For - example, if the contents of the directory <code>/foo/</code> - under the <code>DocumentRoot</code> are moved to the new - directory <code>/bar/</code>, you can instruct clients to - request the content at the new location as follows:</p> - - <blockquote> - <code>Redirect permanent /foo/ - http://www.example.com/bar/</code> - </blockquote> - - <p>This will redirect any URL-Path starting in - <code>/foo/</code> to the same URL path on the - <code>www.example.com</code> server with <code>/bar/</code> - substituted for <code>/foo/</code>. You can redirect clients to - any server, not only the origin server.</p> - - <p>Apache also provides a <a - href="mod/mod_alias.html#redirectmatch">RedirectMatch</a> - directive for more complicated rewriting problems. For example, - to redirect requests for the site home page to a different - site, but leave all other requests alone, use the following - configuration:</p> - - <blockquote> - <code>RedirectMatch permanent ^/$ - http://www.example.com/startpage.html</code> - </blockquote> - - <p>Alternatively, to temporarily redirect all pages on a site - to one particular page, use the following:</p> - - <blockquote> - <code>RedirectMatch temp .* - http://www.example.com/startpage.html</code> - </blockquote> - - <h2><a id="rewrite" name="rewrite">Rewriting Engine</a></h2> - - <p>When even more powerful substitution is required, the - rewriting engine provided by <a - href="mod/mod_rewrite.html">mod_rewrite</a> can be useful. The - directives provided by this module use characteristics of the - request such as browser type or source IP address in deciding - from where to serve content. In addition, mod_rewrite can use - external database files or programs to determine how to handle - a request. Many practical examples employing mod_rewrite are - discussed in the <a href="misc/rewriteguide.html">URL Rewriting - Guide</a>.</p> - - <h2><a id="notfound" name="notfound">File Not Found</a></h2> - - <p>Inevitably, URLs will be requested for which no matching - file can be found in the filesystem. This can happen for - several reasons. In some cases, it can be a result of moving - documents from one location to another. In this case, it is - best to use <a href="#redirect">URL redirection</a> to inform - clients of the new location of the resource. In this way, you - can assure that old bookmarks and links will continue to work, - even though the resource is at a new location.</p> - - <p>Another common cause of "File Not Found" errors is - accidental mistyping of URLs, either directly in the browser, - or in HTML links. Apache provides the module <a - href="mod/mod_speling.html">mod_speling</a> (sic) to help with - this problem. When this module is activated, it will intercept - "File Not Found" errors and look for a resource with a similar - filename. If one such file is found, mod_speling will send an - HTTP redirect to the client informing it of the correct - location. If several "close" files are found, a list of - available alternatives will be presented to the client.</p> - - <p>An especially useful feature of mod_speling, is that it will - compare filenames without respect to case. This can help - systems where users are unaware of the case-sensitive nature of - URLs and the unix filesystem. But using mod_speling for - anything more than the occasional URL correction can place - additional load on the server, since each "incorrect" request - is followed by a URL redirection and a new request from the - client.</p> - - <p>If all attempts to locate the content fail, Apache returns - an error page with HTTP status code 404 (file not found). The - appearance of this page is controlled with the <a - href="mod/core.html#errordocument">ErrorDocument</a> directive - and can be customized in a flexible manner as discussed in the - <a href="custom-error.html">Custom error responses</a> and <a - href="misc/custom_errordocs.html">International Server Error - Responses</a> documents.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/vhosts/fd-limits.html.en b/docs/manual/vhosts/fd-limits.html.en deleted file mode 100644 index dc09fb2d57..0000000000 --- a/docs/manual/vhosts/fd-limits.html.en +++ /dev/null @@ -1,73 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Apache Server Virtual Host Support</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">File Descriptor Limits</h1> - - <p>When using a large number of Virtual Hosts, Apache may run - out of available file descriptors (sometimes called <cite>file - handles</cite> if each Virtual Host specifies different log - files. The total number of file descriptors used by Apache is - one for each distinct error log file, one for every other log - file directive, plus 10-20 for internal use. Unix operating - systems limit the number of file descriptors that may be used - by a process; the limit is typically 64, and may usually be - increased up to a large hard-limit.</p> - - <p>Although Apache attempts to increase the limit as required, - this may not work if:</p> - - <ol> - <li>Your system does not provide the setrlimit() system - call.</li> - - <li>The setrlimit(RLIMIT_NOFILE) call does not function on - your system (such as Solaris 2.3)</li> - - <li>The number of file descriptors required exceeds the hard - limit.</li> - - <li>Your system imposes other limits on file descriptors, - such as a limit on stdio streams only using file descriptors - below 256. (Solaris 2)</li> - </ol> - In the event of problems you can: - - <ul> - <li>Reduce the number of log files; don't specify log files - in the VirtualHost sections, but only log to the main log - files.</li> - - <li> - If you system falls into 1 or 2 (above), then increase the - file descriptor limit before starting Apache, using a - script like - - <blockquote> - <code>#!/bin/sh<br /> - ulimit -S -n 100<br /> - exec httpd</code> - </blockquote> - </li> - </ul> - - <p>Please see the <a - href="../misc/descriptors.html">Descriptors and Apache</a> - document containing further details about file descriptor - problems and how they can be solved on your operating - system.</p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/docs/manual/vhosts/index.html.en b/docs/manual/vhosts/index.html.en deleted file mode 100644 index 7cb19b8092..0000000000 --- a/docs/manual/vhosts/index.html.en +++ /dev/null @@ -1,84 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta name="generator" content="HTML Tidy, see www.w3.org" /> - - <title>Apache Virtual Host documentation</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Apache Virtual Host documentation</h1> - - <p>The term <cite>Virtual Host</cite> refers to the practice of - maintaining more than one server on one machine, as - differentiated by their apparent hostname. For example, it is - often desirable for companies sharing a web server to have - their own domains, with web servers accessible as - <samp>www.company1.com</samp> and - <samp>www.company2.com</samp>, without requiring the user to - know any extra path information.</p> - - <p>Apache was one of the first servers to support IP-based - virtual hosts right out of the box. Versions 1.1 and later of - Apache support both, IP-based and name-based virtual hosts - (vhosts). The latter variant of virtual hosts is sometimes also - called host-based or non-IP virtual hosts.</p> - - <p>Below is a list of documentation pages which explain all - details of virtual host support in Apache version 1.3 and - later.</p> - <hr /> - - <h2>Virtual Host Support</h2> - - <ul> - <li><a href="name-based.html">Name-based Virtual - Hosts</a></li> - - <li><a href="ip-based.html">IP-based Virtual Hosts</a></li> - - <li><a href="examples.html">Virtual Host examples for common - setups</a></li> - - <li><a href="details.html">In-Depth Discussion of Virtual - Host Matching</a></li> - - <li><a href="fd-limits.html">File Descriptor Limits</a></li> - - <li><a href="mass.html">Dynamically Configured Mass Virtual - Hosting</a></li> - </ul> - - <h2>Configuration directives</h2> - - <ul> - <li><a - href="../mod/core.html#virtualhost"><VirtualHost></a></li> - - <li><a - href="../mod/core.html#namevirtualhost">NameVirtualHost</a></li> - - <li><a href="../mod/core.html#servername">ServerName</a></li> - - <li><a - href="../mod/core.html#serveralias">ServerAlias</a></li> - - <li><a href="../mod/core.html#serverpath">ServerPath</a></li> - </ul> - - <p>Folks trying to debug their virtual host configuration may - find the Apache <code>-t -D DUMP_VHOSTS</code> command line switch - useful. It will dump out a description of how Apache parsed the - configuration file. Careful examination of the IP addresses and - server names may help uncover configuration mistakes. - <!--#include virtual="footer.html" --> - </p> - </body> -</html> - diff --git a/docs/manual/vhosts/name-based.html.en b/docs/manual/vhosts/name-based.html.en deleted file mode 100644 index 075140a6bf..0000000000 --- a/docs/manual/vhosts/name-based.html.en +++ /dev/null @@ -1,231 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <title>Name-based Virtual Hosts</title> - </head> - <!-- Background white, links blue (unvisited), navy (visited), red (active) --> - - <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" - vlink="#000080" alink="#FF0000"> - <!--#include virtual="header.html" --> - - <h1 align="CENTER">Name-based Virtual Host Support</h1> - -<p>This document describes when and how to use name-based virtual hosts.</p> - -<ul> -<li><a href="#namevip">Name-based vs. IP-based Virtual Hosts</a></li> -<li><a href="#using">Using Name-based Virtual Hosts</a></li> -<li><a href="#compat">Compatibility With Older Browsers</a></li> -</ul> - -<p>See also: <a href="examples.html">Virtual Host examples for common -setups</a>, <a href="ip-based.html">IP-based Virtual Host Support</a>, -<a href="details.html">An In-Depth Discussion of Virtual Host -Matching</a>, and <a href="mass.html">Dynamically configured mass -virtual hosting</a>.</p> - -<hr /> - -<h2><a name="namevip">Name-based vs. IP-based Virtual Hosts</a></h2> - -<p>IP-based virtual hosts use the IP address of the connection to -determine the correct virtual host to serve. Therefore you need to -have a separate IP address for each host. With name-based virtual -hosting, the server relies on the client to report the hostname as -part of the HTTP headers. Using this technique, many different hosts -can share the same IP address.</p> - -<p>Name-based virtual hosting is usually simpler, since you need -only configure your DNS server to map each hostname to the correct -IP address and then configure the Apache HTTP Server to recognize -the different hostnames. Name-based virtual hosting also eases -the demand for scarce IP addresses. Therefore you should use -name-based virtual hosting unless there is a specific reason to -choose IP-based virtual hosting. Some reasons why you might consider -using IP-based virtual hosting:</p> - -<ul> - -<li>Some ancient clients are not compatible with name-based virtual -hosting. For name-based virtual hosting to work, the client must send -the HTTP Host header. This is required by HTTP/1.1, and is -implemented by all modern HTTP/1.0 browsers as an extension. If you -need to support obsolete clients and still use name-based virtual -hosting, a possible technique is discussed at the end of this -document.</li> - -<li>Name-based virtual hosting cannot be used with SSL secure servers -because of the nature of the SSL protocol.</li> - -<li>Some operating systems and network equipment implement bandwidth -management techniques that cannot differentiate between hosts unless -they are on separate IP addresses.</li> - -</ul> - -<h2><a name="using">Using Name-based Virtual Hosts</a></h2> - -<table border="1"> -<tr><td align="top"> -<strong>Related Directives</strong><br><br> - -<a href="../mod/core.html#documentroot">DocumentRoot</a><br /> -<a href="../mod/core.html#namevirtualhost">NameVirtualHost</a><br /> -<a href="../mod/core.html#serveralias">ServerAlias</a><br /> -<a href="../mod/core.html#servername">ServerName</a><br /> -<a href="../mod/core.html#serverpath">ServerPath</a><br /> -<a href="../mod/core.html#virtualhost">VirtualHost</a><br /> -</td></tr></table> - -<p>To use name-based virtual hosting, you must designate the IP -address (and possibly port) on the server that will be accepting -requests for the hosts. This is configured using the <a -href="../mod/core.html#namevirtualhost">NameVirtualHost</a> directive. -In the normal case where any and all IP addresses on the server should -be used, you can use <code>*</code> as the argument to -<code>NameVirtualHost</code>. Note that mentioning an IP address in a -<code>NameVirtualHost</code> directive does not automatically make the -server listen to that IP address. See <a href="../bind.html">Setting -which addresses and ports Apache uses</a> for more details. In addition, -any IP address specified here must be associated with a network interface -on the server.</p> - -<p>The next step is to create a <a -href="../mod/core.html#virtualhost"><VirtualHost></a> block for -each different host that you would like to serve. The argument to the -<code><VirtualHost></code> directive should be the same as the -argument to the <code>NameVirtualHost</code> directive (ie, an IP -address, or <code>*</code> for all addresses). Inside each -<code><VirtualHost></code> block, you will need at minimum a <a -href="../mod/core.html#servername">ServerName</a> directive to -designate which host is served and a <a -href="../mod/core.html#documentroot">DocumentRoot</a> directive to -show where in the filesystem the content for that host lives.</p> - -<p>For example, suppose that both <samp>www.domain.tld</samp> and -<samp>www.otherdomain.tld</samp> point at an IP address -that the server is listening to. Then you simply add the following -to <code>httpd.conf</code>:</p> - -<pre> - NameVirtualHost * - - <VirtualHost *> - ServerName www.domain.tld - DocumentRoot /www/domain - </VirtualHost> - - <VirtualHost *> - ServerName www.otherdomain.tld - DocumentRoot /www/otherdomain - </VirtualHost> -</pre> - -<p>You can alternatively specify an explicit IP address in place of -the * in both the <code>NameVirtualHost</code> and -<code><VirtualHost></code> directives.</p> - -<p>Many servers want to be accessible by more than one name. This is -possible with the <a -href="../mod/core.html#serveralias"><code>ServerAlias</code></a> -directive, placed inside the <VirtualHost> section. For -example if you add this to the first <VirtualHost> block -above</p> - -<blockquote><code> -ServerAlias domain.tld *.domain.tld -</code></blockquote> - -<p>then requests for all hosts in the <code>domain.tld</code> domain -will be served by the <code>www.domain.tld</code> virtual host. The -wildcard characters * and ? can be used to match names. Of course, -you can't just make up names and place them in <code>ServerName</code> -or <code>ServerAlias</code>. You must first have your DNS server -properly configured to map those names to an IP address associated -with your server.</p> - -<p>Finally, you can fine-tune the configuration of the virtual hosts -by placing other directives inside the -<code><VirtualHost></code> containers. Most directives can be -placed in these containers and will then change the configuration only -of the relevant virtual host. To find out if a particular directive -is allowed, check the <a -href="../mod/directive-dist.html#Context">Context</a> of the -directive. Configuration directives set in the <em>main server -context</em> (outside any <code><VirtualHost></code> container) -will be used only if they are not overriden by the virtual host -settings.</p> - -<p>Now when a request arrives, the server will first check if it is -using an IP address that matches the <code>NameVirtualHost</code>. If -it is, then it will look at each <code><VirtualHost></code> -section with a matching IP address and try to find one where the -<code>ServerName</code> or <code>ServerAlias</code> matches the -requested hostname. If it finds one, then it uses the configuration -for that server. If no matching virtual host is found, then -<strong>the first listed virtual host</strong> that matches the IP -address will be used.</p> - -<p>As a consequence, the first listed virtual host is the -<em>default</em> virtual host. The <code>DocumentRoot</code> from the -<em>main server</em> will <strong>never</strong> be used when an IP -address matches the <code>NameVirtualHost</code> directive. If you -would like to have a special configuration for requests that do not -match any particular virtual host, simply put that configuration in a -<code><VirtualHost></code> container and list it first in the -configuration file.</p> - -<h2><a name="compat">Compatibility with Older Browsers</a></h2> - - <p>As mentioned earlier, there are some clients - who do not send the required data for the name-based virtual - hosts to work properly. These clients will always be sent the - pages from the first virtual host listed for that IP address - (the <cite>primary</cite> name-based virtual host).</p> - - <p>There is a possible workaround with the <a - href="../mod/core.html#serverpath"><code>ServerPath</code></a> - directive, albeit a slightly cumbersome one:</p> - - <p>Example configuration:</p> -<pre> - NameVirtualHost 111.22.33.44 - - <VirtualHost 111.22.33.44> - ServerName www.domain.tld - ServerPath /domain - DocumentRoot /web/domain - </VirtualHost> -</pre> - - <p>What does this mean? It means that a request for any URI - beginning with "<samp>/domain</samp>" will be served from the - virtual host <samp>www.domain.tld</samp> This means that the - pages can be accessed as - <code>http://www.domain.tld/domain/</code> for all clients, - although clients sending a <samp>Host:</samp> header can also - access it as <code>http://www.domain.tld/</code>.</p> - - <p>In order to make this work, put a link on your primary - virtual host's page to - <samp>http://www.domain.tld/domain/</samp> Then, in the virtual - host's pages, be sure to use either purely relative links - (<em>e.g.</em>, "<samp>file.html</samp>" or - "<samp>../icons/image.gif</samp>" or links containing the - prefacing <samp>/domain/</samp> (<em>e.g.</em>, - "<samp>http://www.domain.tld/domain/misc/file.html</samp>" or - "<samp>/domain/misc/file.html</samp>").</p> - - <p>This requires a bit of discipline, but adherence to these - guidelines will, for the most part, ensure that your pages will - work with all browsers, new and old.</p> - - <p>See also: <a href="examples.html#serverpath">ServerPath - configuration example</a></p> - <!--#include virtual="footer.html" --> - </body> -</html> - diff --git a/modules/experimental/mod_auth_ldap.c b/modules/experimental/mod_auth_ldap.c deleted file mode 100644 index 6be891cf17..0000000000 --- a/modules/experimental/mod_auth_ldap.c +++ /dev/null @@ -1,862 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ - -/* - * mod_auth_ldap.c: LDAP authentication module - * - * Original code from auth_ldap module for Apache v1.3: - * Copyright 1998, 1999 Enbridge Pipelines Inc. - * Copyright 1999-2001 Dave Carrigan - */ - -#include <apr_ldap.h> -#include <apr_strings.h> - -#include "ap_config.h" -#if APR_HAVE_UNISTD_H -/* for getpid() */ -#include <unistd.h> -#endif -#include <ctype.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 "util_ldap.h" - -/* per directory configuration */ -typedef struct { - apr_pool_t *pool; /* Pool that this config is allocated from */ - apr_lock_t *lock; /* Lock for this config */ - int auth_authoritative; /* Is this auth method the one and only? */ - int enabled; /* Is auth_ldap enabled in this directory? */ - - /* These parameters are all derived from the AuthLDAPURL directive */ - char *url; /* String representation of the URL */ - - char *host; /* Name of the LDAP server (or space separated list) */ - int port; /* Port of the LDAP server */ - char *basedn; /* Base DN to do all searches from */ - char *attribute; /* Attribute to search for */ - char **attributes; /* Array of all the attributes to return */ - int scope; /* Scope of the search */ - char *filter; /* Filter to further limit the search */ - deref_options deref; /* how to handle alias dereferening */ - char *binddn; /* DN to bind to server (can be NULL) */ - char *bindpw; /* Password to bind to server (can be NULL) */ - - int frontpage_hack; /* Hack for frontpage support */ - int user_is_dn; /* If true, connection->user is DN instead of userid */ - int compare_dn_on_server; /* If true, will use server to do DN compare */ - - int have_ldap_url; /* Set if we have found an LDAP url */ - - apr_array_header_t *groupattr; /* List of Group attributes */ - int group_attrib_is_dn; /* If true, the group attribute is the DN, otherwise, - it's the exact string passed by the HTTP client */ - - int netscapessl; /* True if Netscape SSL is enabled */ - int starttls; /* True if StartTLS is enabled */ -} mod_auth_ldap_config_t; - -typedef struct mod_auth_ldap_request_t { - char *dn; /* The saved dn from a successful search */ - char *user; /* The username provided by the client */ -} mod_auth_ldap_request_t; - -/* maximum group elements supported */ -#define GROUPATTR_MAX_ELTS 10 - -struct mod_auth_ldap_groupattr_entry_t { - char *name; -}; - -module AP_MODULE_DECLARE_DATA auth_ldap_module; - -/* function prototypes */ -void mod_auth_ldap_build_filter(char *filtbuf, - request_rec *r, - mod_auth_ldap_config_t *sec); -int mod_auth_ldap_check_user_id(request_rec *r); -int mod_auth_ldap_auth_checker(request_rec *r); -void *mod_auth_ldap_create_dir_config(apr_pool_t *p, char *d); - -/* ---------------------------------------- */ - - -/* - * Build the search filter, or at least as much of the search filter that - * will fit in the buffer. We don't worry about the buffer not being able - * to hold the entire filter. If the buffer wasn't big enough to hold the - * filter, ldap_search_s will complain, but the only situation where this - * is likely to happen is if the client sent a really, really long - * username, most likely as part of an attack. - * - * The search filter consists of the filter provided with the URL, - * combined with a filter made up of the attribute provided with the URL, - * and the actual username passed by the HTTP client. For example, assume - * that the LDAP URL is - * - * ldap://ldap.airius.com/ou=People, o=Airius?uid??(posixid=*) - * - * Further, assume that the userid passed by the client was `userj'. The - * search filter will be (&(posixid=*)(uid=userj)). - */ -#define FILTER_LENGTH MAX_STRING_LEN -void mod_auth_ldap_build_filter(char *filtbuf, - request_rec *r, - mod_auth_ldap_config_t *sec) -{ - char *p, *q, *filtbuf_end; - /* - * Create the first part of the filter, which consists of the - * config-supplied portions. - */ - apr_snprintf(filtbuf, FILTER_LENGTH, "(&(%s)(%s=", sec->filter, sec->attribute); - - /* - * Now add the client-supplied username to the filter, ensuring that any - * LDAP filter metachars are escaped. - */ - filtbuf_end = filtbuf + FILTER_LENGTH - 1; - for (p = r->user, q=filtbuf + strlen(filtbuf); - *p && q < filtbuf_end; *q++ = *p++) { - if (strchr("*()\\", *p) != NULL) { - *q++ = '\\'; - if (q >= filtbuf_end) { - break; - } - } - } - *q = '\0'; - - /* - * Append the closing parens of the filter, unless doing so would - * overrun the buffer. - */ - if (q + 2 <= filtbuf_end) - strcat(filtbuf, "))"); -} - - -/* - * Authentication Phase - * -------------------- - * - * This phase authenticates the credentials the user has sent with - * the request (ie the username and password are checked). This is done - * by making an attempt to bind to the LDAP server using this user's - * DN and the supplied password. - * - */ -int mod_auth_ldap_check_user_id(request_rec *r) -{ - const char **vals = NULL; - char filtbuf[FILTER_LENGTH]; - mod_auth_ldap_config_t *sec = - (mod_auth_ldap_config_t *)ap_get_module_config(r->per_dir_config, &auth_ldap_module); - - util_ldap_connection_t *ldc = NULL; - const char *sent_pw; - int result = 0; - const char *dn = NULL; - - mod_auth_ldap_request_t *req = - (mod_auth_ldap_request_t *)apr_pcalloc(r->pool, sizeof(mod_auth_ldap_request_t)); - ap_set_module_config(r->request_config, &auth_ldap_module, req); - - if (!sec->enabled) { - return DECLINED; - } - - /* - * Basic sanity checks before any LDAP operations even happen. - */ - if (!sec->have_ldap_url) { - return DECLINED; - } - - /* There is a good AuthLDAPURL, right? */ - if (sec->host) { - ldc = util_ldap_connection_find(r, sec->host, sec->port, - sec->binddn, sec->bindpw, sec->deref, - sec->netscapessl, sec->starttls); - } - else { - ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authenticate: no sec->host - weird...?", getpid()); - return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED; - } - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authenticate: using URL %s", getpid(), sec->url); - - /* Get the password that the client sent */ - if ((result = ap_get_basic_auth_pw(r, &sent_pw))) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authenticate: " - "ap_get_basic_auth_pw() returns %d", getpid(), result); - util_ldap_connection_close(ldc); - return result; - } - - /* build the username filter */ - mod_auth_ldap_build_filter(filtbuf, r, sec); - - /* do the user search */ - result = util_ldap_cache_checkuserid(r, ldc, sec->url, sec->basedn, sec->scope, - sec->attributes, filtbuf, sent_pw, &dn, &vals); - util_ldap_connection_close(ldc); - - if (result != LDAP_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authenticate: " - "user %s authentication failed; URI %s [%s][%s]", - getpid(), r->user, r->uri, ldc->reason, ldap_err2string(result)); - if (LDAP_INVALID_CREDENTIALS == result) { - ap_note_basic_auth_failure(r); - return HTTP_UNAUTHORIZED; - } - else { - return sec->auth_authoritative? HTTP_UNAUTHORIZED: DECLINED; - } - } - - /* mark the user and DN */ - req->dn = apr_pstrdup(r->pool, dn); - req->user = r->user; - if (sec->user_is_dn) { - r->user = req->dn; - } - - /* add environment variables */ - if (sec->attributes && vals) { - apr_table_t *e = r->subprocess_env; - int i = 0; - while (sec->attributes[i]) { - char *str = apr_pstrcat(r->pool, "AUTHENTICATE_", sec->attributes[i], NULL); - int j = 13; - while (str[j]) { - if (str[j] >= 'a' && str[j] <= 'z') { - str[j] = str[j] - ('a' - 'A'); - } - j++; - } - apr_table_setn(e, str, vals[i]); - i++; - } - } - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authenticate: accepting %s", getpid(), r->user); - - return OK; -} - - -/* - * Authorisation Phase - * ------------------- - * - * After checking whether the username and password are correct, we need - * to check whether that user is authorised to view this resource. The - * require directive is used to do this: - * - * require valid-user Any authenticated is allowed in. - * require user <username> This particular user is allowed in. - * require group <groupname> The user must be a member of this group - * in order to be allowed in. - * require dn <dn> The user must have the following DN in the - * LDAP tree to be let in. - * - */ -int mod_auth_ldap_auth_checker(request_rec *r) -{ - int result = 0; - mod_auth_ldap_request_t *req = - (mod_auth_ldap_request_t *)ap_get_module_config(r->request_config, - &auth_ldap_module); - mod_auth_ldap_config_t *sec = - (mod_auth_ldap_config_t *)ap_get_module_config(r->per_dir_config, - &auth_ldap_module); - - util_ldap_connection_t *ldc = NULL; - int m = r->method_number; - - const apr_array_header_t *reqs_arr = ap_requires(r); - require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL; - - register int x; - const char *t; - char *w; - int method_restricted = 0; - - if (!sec->enabled) { - return DECLINED; - } - - if (!sec->have_ldap_url) { - return DECLINED; - } - - if (sec->host) { - ldc = util_ldap_connection_find(r, sec->host, sec->port, - sec->binddn, sec->bindpw, sec->deref, - sec->netscapessl, sec->starttls); - } - else { - ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: no sec->host - weird...?", getpid()); - return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED; - } - - /* - * If there are no elements in the group attribute array, the default should be - * member and uniquemember; populate the array now. - */ - if (sec->groupattr->nelts == 0) { - struct mod_auth_ldap_groupattr_entry_t *grp; - apr_lock_acquire(sec->lock); - grp = apr_array_push(sec->groupattr); - grp->name = "member"; - grp = apr_array_push(sec->groupattr); - grp->name = "uniquemember"; - apr_lock_release(sec->lock); - } - - if (!reqs_arr) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: no requirements array", getpid()); - return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED; - } - - /* Loop through the requirements array until there's no elements - * left, or something causes a return from inside the loop */ - for(x=0; x < reqs_arr->nelts; x++) { - if (! (reqs[x].method_mask & (1 << m))) { - continue; - } - method_restricted = 1; - - t = reqs[x].requirement; - w = ap_getword(r->pool, &t, ' '); - - if (strcmp(w, "valid-user") == 0) { - /* - * Valid user will always be true if we authenticated with ldap, - * but when using front page, valid user should only be true if - * he exists in the frontpage password file. This hack will get - * auth_ldap to look up the user in the the pw file to really be - * sure that he's valid. Naturally, it requires mod_auth to be - * compiled in, but if mod_auth wasn't in there, then the need - * for this hack wouldn't exist anyway. - */ - if (sec->frontpage_hack) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "deferring authorisation to mod_auth (FP Hack)", - getpid()); - return OK; - } - else { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "successful authorisation because user " - "is valid-user", getpid()); - return OK; - } - } - else if (strcmp(w, "user") == 0) { - if (req->dn == NULL || strlen(req->dn) == 0) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "require user: user's DN has not been defined; failing authorisation", - getpid()); - return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED; - } - /* - * First do a whole-line compare, in case it's something like - * require user Babs Jensen - */ - result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, t); - switch(result) { - case LDAP_COMPARE_TRUE: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "require user: authorisation successful", getpid()); - return OK; - } - default: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: require user: " - "authorisation failed [%s][%s]", getpid(), - ldc->reason, ldap_err2string(result)); - } - } - /* - * Now break apart the line and compare each word on it - */ - while (t[0]) { - w = ap_getword_conf(r->pool, &t); - result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w); - switch(result) { - case LDAP_COMPARE_TRUE: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "require user: authorisation successful", getpid()); - return OK; - } - default: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "require user: authorisation failed [%s][%s]", - getpid(), ldc->reason, ldap_err2string(result)); - } - } - } - } - else if (strcmp(w, "dn") == 0) { - if (req->dn == NULL || strlen(req->dn) == 0) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "require dn: user's DN has not been defined; failing authorisation", - getpid()); - return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED; - } - - result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, t, sec->compare_dn_on_server); - switch(result) { - case LDAP_COMPARE_TRUE: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "require dn: authorisation successful", getpid()); - return OK; - } - default: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: " - "require dn: LDAP error [%s][%s]", - getpid(), ldc->reason, ldap_err2string(result)); - } - } - } - else if (strcmp(w, "group") == 0) { - struct mod_auth_ldap_groupattr_entry_t *ent = (struct mod_auth_ldap_groupattr_entry_t *) sec->groupattr->elts; - int i; - - if (sec->group_attrib_is_dn) { - if (req->dn == NULL || strlen(req->dn) == 0) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: require group: user's DN has not been defined; failing authorisation", - getpid()); - return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED; - } - } - else { - if (req->user == NULL || strlen(req->user) == 0) { - /* We weren't called in the authentication phase, so we didn't have a - * chance to set the user field. Do so now. */ - req->user = r->user; - } - } - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: require group: testing for group membership in `%s'", - getpid(), t); - - for (i = 0; i < sec->groupattr->nelts; i++) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: require group: testing for %s: %s (%s)", getpid(), - ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, t); - - result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name, - sec->group_attrib_is_dn ? req->dn : req->user); - switch(result) { - case LDAP_COMPARE_TRUE: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: require group: " - "authorisation successful (attribute %s) [%s][%s]", - getpid(), ent[i].name, ldc->reason, ldap_err2string(result)); - return OK; - } - default: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: require group: " - "authorisation failed [%s][%s]", - getpid(), ldc->reason, ldap_err2string(result)); - } - } - } - } - } - - if (!method_restricted) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: agreeing because non-restricted", - getpid()); - return OK; - } - - if (!sec->auth_authoritative) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: declining to authorise", getpid()); - return DECLINED; - } - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, - "[%d] auth_ldap authorise: authorisation denied", getpid()); - ap_note_basic_auth_failure (r); - - return HTTP_UNAUTHORIZED; -} - - -/* ---------------------------------------- */ -/* config directives */ - - -void *mod_auth_ldap_create_dir_config(apr_pool_t *p, char *d) -{ - mod_auth_ldap_config_t *sec = - (mod_auth_ldap_config_t *)apr_pcalloc(p, sizeof(mod_auth_ldap_config_t)); - - sec->pool = p; - apr_lock_create(&sec->lock, APR_MUTEX, APR_INTRAPROCESS, NULL, p); - sec->auth_authoritative = 1; - sec->enabled = 1; - sec->groupattr = apr_array_make(p, GROUPATTR_MAX_ELTS, - sizeof(struct mod_auth_ldap_groupattr_entry_t)); - - sec->have_ldap_url = 0; - sec->url = ""; - sec->host = NULL; - sec->binddn = NULL; - sec->bindpw = NULL; - sec->deref = always; - sec->group_attrib_is_dn = 1; - - sec->frontpage_hack = 0; - sec->netscapessl = 0; - sec->starttls = 0; - - sec->user_is_dn = 0; - sec->compare_dn_on_server = 0; - - return sec; -} - -/* - * Use the ldap url parsing routines to break up the ldap url into - * host and port. - */ -static const char *mod_auth_ldap_parse_url(cmd_parms *cmd, - void *config, - const char *url) -{ - int result; - LDAPURLDesc *urld; - - mod_auth_ldap_config_t *sec = config; - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap url parse: `%s'", - getpid(), url); - - result = ldap_url_parse(url, &(urld)); - if (result != LDAP_SUCCESS) { - switch (result) { - case LDAP_URL_ERR_NOTLDAP: - return "LDAP URL does not begin with ldap://"; - case LDAP_URL_ERR_NODN: - return "LDAP URL does not have a DN"; - case LDAP_URL_ERR_BADSCOPE: - return "LDAP URL has an invalid scope"; - case LDAP_URL_ERR_MEM: - return "Out of memory parsing LDAP URL"; - default: - return "Could not parse LDAP URL"; - } - } - sec->url = apr_pstrdup(cmd->pool, url); - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap url parse: Host: %s", getpid(), urld->lud_host); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap url parse: Port: %d", getpid(), urld->lud_port); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap url parse: DN: %s", getpid(), urld->lud_dn); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap url parse: attrib: %s", getpid(), urld->lud_attrs? urld->lud_attrs[0] : "(null)"); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap url parse: scope: %s", getpid(), - (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" : - urld->lud_scope == LDAP_SCOPE_BASE? "base" : - urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown")); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap url parse: filter: %s", getpid(), urld->lud_filter); - - /* Set all the values, or at least some sane defaults */ - if (sec->host) { - char *p = apr_palloc(cmd->pool, strlen(sec->host) + strlen(urld->lud_host) + 2); - strcpy(p, urld->lud_host); - strcat(p, " "); - strcat(p, sec->host); - sec->host = p; - } - else { - sec->host = urld->lud_host? apr_pstrdup(cmd->pool, urld->lud_host) : "localhost"; - } - sec->basedn = urld->lud_dn? apr_pstrdup(cmd->pool, urld->lud_dn) : ""; - if (urld->lud_attrs && urld->lud_attrs[0]) { - int i = 1; - while (urld->lud_attrs[i]) { - i++; - } - sec->attributes = apr_pcalloc(cmd->pool, sizeof(char *) * (i+1)); - i = 0; - while (urld->lud_attrs[i]) { - sec->attributes[i] = apr_pstrdup(cmd->pool, urld->lud_attrs[i]); - i++; - } - sec->attribute = sec->attributes[0]; - } - else { - sec->attribute = "uid"; - } - - sec->scope = urld->lud_scope == LDAP_SCOPE_ONELEVEL ? - LDAP_SCOPE_ONELEVEL : LDAP_SCOPE_SUBTREE; - - if (urld->lud_filter) { - if (urld->lud_filter[0] == '(') { - /* - * Get rid of the surrounding parens; later on when generating the - * filter, they'll be put back. - */ - sec->filter = apr_pstrdup(cmd->pool, urld->lud_filter+1); - sec->filter[strlen(sec->filter)-1] = '\0'; - } - else { - sec->filter = apr_pstrdup(cmd->pool, urld->lud_filter); - } - } - else { - sec->filter = "objectclass=*"; - } - if (strncmp(url, "ldaps", 5) == 0) { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap parse url: requesting secure LDAP", getpid()); -#ifdef APU_HAS_LDAP_STARTTLS - sec->port = urld->lud_port? urld->lud_port : LDAPS_PORT; - sec->starttls = 1; -#else -#ifdef APU_HAS_LDAP_NETSCAPE_SSL - sec->port = urld->lud_port? urld->lud_port : LDAPS_PORT; - sec->netscapessl = 1; -#else - return "Secure LDAP (ldaps://) not supported. Rebuild APR-Util"; -#endif -#endif - } - else { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, - cmd->server, "[%d] auth_ldap parse url: not requesting secure LDAP", getpid()); - sec->netscapessl = 0; - sec->starttls = 0; - sec->port = urld->lud_port? urld->lud_port : LDAP_PORT; - } - - sec->have_ldap_url = 1; - ldap_free_urldesc(urld); - return NULL; -} - -static const char *mod_auth_ldap_set_deref(cmd_parms *cmd, void *config, const char *arg) -{ - mod_auth_ldap_config_t *sec = config; - - if (strcmp(arg, "never") == 0 || strcasecmp(arg, "off") == 0) { - sec->deref = never; - } - else if (strcmp(arg, "searching") == 0) { - sec->deref = searching; - } - else if (strcmp(arg, "finding") == 0) { - sec->deref = finding; - } - else if (strcmp(arg, "always") == 0 || strcasecmp(arg, "on") == 0) { - sec->deref = always; - } - else { - return "Unrecognized value for AuthLDAPAliasDereference directive"; - } - return NULL; -} - -static const char *mod_auth_ldap_add_group_attribute(cmd_parms *cmd, void *config, const char *arg) -{ - struct mod_auth_ldap_groupattr_entry_t *new; - - mod_auth_ldap_config_t *sec = config; - - if (sec->groupattr->nelts > GROUPATTR_MAX_ELTS) - return "Too many AuthLDAPGroupAttribute directives"; - - new = apr_array_push(sec->groupattr); - new->name = apr_pstrdup(cmd->pool, arg); - - return NULL; -} - -command_rec mod_auth_ldap_cmds[] = { - AP_INIT_TAKE1("AuthLDAPURL", mod_auth_ldap_parse_url, NULL, OR_AUTHCFG, - "URL to define LDAP connection. This should be an RFC 2255 complaint\n" - "URL of the form ldap://host[:port]/basedn[?attrib[?scope[?filter]]].\n" - "<ul>\n" - "<li>Host is the name of the LDAP server. Use a space separated list of hosts \n" - "to specify redundant servers.\n" - "<li>Port is optional, and specifies the port to connect to.\n" - "<li>basedn specifies the base DN to start searches from\n" - "<li>Attrib specifies what attribute to search for in the directory. If not " - "provided, it defaults to <b>uid</b>.\n" - "<li>Scope is the scope of the search, and can be either <b>sub</b> or " - "<b>one</b>. If not provided, the default is <b>sub</b>.\n" - "<li>Filter is a filter to use in the search. If not provided, " - "defaults to <b>(objectClass=*)</b>.\n" - "</ul>\n" - "Searches are performed using the attribute and the filter combined. " - "For example, assume that the\n" - "LDAP URL is <b>ldap://ldap.airius.com/ou=People, o=Airius?uid?sub?(posixid=*)</b>. " - "Searches will\n" - "be done using the filter <b>(&((posixid=*))(uid=<i>username</i>))</b>, " - "where <i>username</i>\n" - "is the user name passed by the HTTP client. The search will be a subtree " - "search on the branch <b>ou=People, o=Airius</b>."), - - AP_INIT_TAKE1("AuthLDAPBindDN", ap_set_string_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, binddn), OR_AUTHCFG, - "DN to use to bind to LDAP server. If not provided, will do an anonymous bind."), - - AP_INIT_TAKE1("AuthLDAPBindPassword", ap_set_string_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, bindpw), OR_AUTHCFG, - "Password to use to bind to LDAP server. If not provided, will do an anonymous bind."), - - AP_INIT_FLAG("AuthLDAPRemoteUserIsDN", ap_set_flag_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, user_is_dn), OR_AUTHCFG, - "Set to 'on' to set the REMOTE_USER environment variable to be the full " - "DN of the remote user. By default, this is set to off, meaning that " - "the REMOTE_USER variable will contain whatever value the remote user sent."), - - AP_INIT_FLAG("AuthLDAPAuthoritative", ap_set_flag_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, auth_authoritative), OR_AUTHCFG, - "Set to 'off' to allow access control to be passed along to lower modules if " - "the UserID and/or group is not known to this module"), - - AP_INIT_FLAG("AuthLDAPCompareDNOnServer", ap_set_flag_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, compare_dn_on_server), OR_AUTHCFG, - "Set to 'on' to force auth_ldap to do DN compares (for the \"require dn\" " - "directive) using the server, and set it 'off' to do the compares locally " - "(at the expense of possible false matches). See the documentation for " - "a complete description of this option."), - - AP_INIT_ITERATE("AuthLDAPGroupAttribute", mod_auth_ldap_add_group_attribute, NULL, OR_AUTHCFG, - "A list of attributes used to define group membership - defaults to " - "member and uniquemember"), - - AP_INIT_FLAG("AuthLDAPGroupAttributeIsDN", ap_set_flag_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, group_attrib_is_dn), OR_AUTHCFG, - "If set to 'on', auth_ldap uses the DN that is retrieved from the server for" - "subsequent group comparisons. If set to 'off', auth_ldap uses the string" - "provided by the client directly. Defaults to 'on'."), - - AP_INIT_TAKE1("AuthLDAPDereferenceAliases", mod_auth_ldap_set_deref, NULL, OR_AUTHCFG, - "Determines how aliases are handled during a search. Can bo one of the" - "values \"never\", \"searching\", \"finding\", or \"always\". " - "Defaults to always."), - - AP_INIT_FLAG("AuthLDAPEnabled", ap_set_flag_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, enabled), OR_AUTHCFG, - "Set to off to disable auth_ldap, even if it's been enabled in a higher tree"), - - AP_INIT_FLAG("AuthLDAPFrontPageHack", ap_set_flag_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, frontpage_hack), OR_AUTHCFG, - "Set to 'on' to support Microsoft FrontPage"), - -#ifdef APU_HAS_LDAP_STARTTLS - AP_INIT_FLAG("AuthLDAPStartTLS", ap_set_flag_slot, - (void *)APR_XtOffsetOf(mod_auth_ldap_config_t, starttls), OR_AUTHCFG, - "Set to 'on' to start TLS after connecting to the LDAP server."), -#endif /* APU_HAS_LDAP_STARTTLS */ - - {NULL} -}; - -static void mod_auth_ldap_register_hooks(apr_pool_t *p) -{ - ap_hook_check_user_id(mod_auth_ldap_check_user_id, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_auth_checker(mod_auth_ldap_auth_checker, NULL, NULL, APR_HOOK_MIDDLE); -} - -module auth_ldap_module = { - STANDARD20_MODULE_STUFF, - mod_auth_ldap_create_dir_config, /* dir config creater */ - NULL, /* dir merger --- default is to override */ - NULL, /* server config */ - NULL, /* merge server config */ - mod_auth_ldap_cmds, /* command table */ - mod_auth_ldap_register_hooks, /* set up request processing hooks */ -}; diff --git a/modules/experimental/util_ldap.c b/modules/experimental/util_ldap.c deleted file mode 100644 index 4e9ca0e501..0000000000 --- a/modules/experimental/util_ldap.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ - -/* - * util_ldap.c: LDAP things - * - * Original code from auth_ldap module for Apache v1.3: - * Copyright 1998, 1999 Enbridge Pipelines Inc. - * Copyright 1999-2001 Dave Carrigan - */ - -#include <apr_ldap.h> - -#ifdef APU_HAS_LDAP - -#include <apr_lock.h> -#include <apr_strings.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 "util_ldap.h" -#include "util_ldap_cache.h" - -#if APR_HAVE_UNISTD_H -#include <unistd.h> -#endif - -module AP_MODULE_DECLARE_DATA ldap_module; - -int util_ldap_handler(request_rec *r); -void *util_ldap_create_config(apr_pool_t *p, server_rec *s); - - -/* - * Some definitions to help between various versions of apache. - */ - -#ifndef DOCTYPE_HTML_2_0 -#define DOCTYPE_HTML_2_0 "<!DOCTYPE HTML PUBLIC \"-//IETF//" \ - "DTD HTML 2.0//EN\">\n" -#endif - -#ifndef DOCTYPE_HTML_3_2 -#define DOCTYPE_HTML_3_2 "<!DOCTYPE HTML PUBLIC \"-//W3C//" \ - "DTD HTML 3.2 Final//EN\">\n" -#endif - -#ifndef DOCTYPE_HTML_4_0S -#define DOCTYPE_HTML_4_0S "<!DOCTYPE HTML PUBLIC \"-//W3C//" \ - "DTD HTML 4.0//EN\"\n" \ - "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" -#endif - -#ifndef DOCTYPE_HTML_4_0T -#define DOCTYPE_HTML_4_0T "<!DOCTYPE HTML PUBLIC \"-//W3C//" \ - "DTD HTML 4.0 Transitional//EN\"\n" \ - "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n" -#endif - -#ifndef DOCTYPE_HTML_4_0F -#define DOCTYPE_HTML_4_0F "<!DOCTYPE HTML PUBLIC \"-//W3C//" \ - "DTD HTML 4.0 Frameset//EN\"\n" \ - "\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n" -#endif - -/* - * Status Handler - * -------------- - * - * This handler generates a status page about the current performance of - * the LDAP cache. It is enabled as follows: - * - * <Location /ldap-status> - * SetHandler ldap-status - * </Location> - * - */ -int util_ldap_handler(request_rec *r) -{ - - r->allowed |= (1 << M_GET); - if (r->method_number != M_GET) - return DECLINED; - - if (strcmp(r->handler, "ldap-status")) { - return DECLINED; - } - - r->content_type = "text/html"; - if (r->header_only) - return OK; - - ap_rputs(DOCTYPE_HTML_3_2 - "<html><head><title>LDAP Cache Information</title></head>\n", r); - ap_rputs("<body bgcolor='#ffffff'><h1 align=center>LDAP Cache Information</h1>\n", r); - - ap_rputs("<p>\n" - "<table border='0'>\n" - "<tr bgcolor='#000000'>\n" - "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Cache Name</b></font></td>" - "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Entries</b></font></td>" - "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg. Chain Len.</b></font></td>" - "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Hits</b></font></td>" - "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Ins/Rem</b></font></td>" - "<td colspan='2'><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Purges</b></font></td>" - "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Avg Purge Time</b></font></td>" - "</tr>\n", r - ); - - ap_rputs(util_ald_cache_display(r->pool), r); - - ap_rputs("</table>\n</p>\n", r); - - return OK; -} - -/* ------------------------------------------------------------------ */ - - -/* - * Closes an LDAP connection by unlocking it. The next time - * util_ldap_connection_find() is called this connection will be - * available for reuse. - */ -void util_ldap_connection_close(util_ldap_connection_t *ldc) -{ - - /* - * QUESTION: - * - * Is it safe leaving bound connections floating around between the - * different modules? Keeping the user bound is a performance boost, - * but it is also a potential security problem - maybe. - * - * For now we unbind the user when we finish with a connection, but - * we don't have to... - */ - - /* mark our connection as available for reuse */ - apr_lock_release(ldc->lock); - -} - - -/* - * Destroys an LDAP connection by unbinding. This function is registered - * with the pool cleanup function - causing the LDAP connections to be - * shut down cleanly on graceful restart. - */ -apr_status_t util_ldap_connection_destroy(void *param) -{ - util_ldap_connection_t *ldc = param; - - /* unbinding from the LDAP server */ - if (ldc->ldap) { - ldap_unbind_s(ldc->ldap); - ldc->bound = 0; - ldc->ldap = NULL; - } - - /* release the lock we were using */ - apr_lock_release(ldc->lock); - - return APR_SUCCESS; -} - - -/* - * Connect to the LDAP server and binds. Does not connect if already - * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound. - * - * Returns LDAP_SUCCESS on success; and an error code on failure - */ -int util_ldap_connection_open(util_ldap_connection_t *ldc) -{ - int result = 0; - int failures = 0; - - -start_over: - if (failures++ > 10) { - /* too many failures - leave */ - return result; - } - - if (!ldc->ldap) { - ldc->bound = 0; - - /* opening connection to LDAP server */ - if ((ldc->ldap = ldap_init(ldc->host, ldc->port)) == NULL) { - /* couldn't connect */ - ldc->reason = "ldap_init() failed"; - return -1; - } - - /* add the cleanup to the pool */ - apr_pool_cleanup_register(ldc->pool, ldc, - util_ldap_connection_destroy, - apr_pool_cleanup_null); - - /* Set the alias dereferencing option */ -#if LDAP_VERSION_MAX == 2 - ldc->ldap->ld_deref = ldc->deref; -#else - result = ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &(ldc->deref)); - if (result != LDAP_SUCCESS) { - /* setting LDAP dereference option failed */ - /* we ignore this error */ - } -#endif /* LDAP_VERSION_MAX */ - -#ifdef APU_HAS_LDAP_NETSCAPE_SSL - if (ldc->netscapessl) { - if (!ldc->certdb) { - /* secure LDAP requested, but no CA cert defined */ - ldc->reason = "secure LDAP requested, but no CA cert defined"; - return -1; - } else { - result = ldapssl_install_routines(ldc->ldap); - if (result != LDAP_SUCCESS) { - /* SSL initialisation failed */ - ldc->reason = "ldapssl_install_routines() failed"; - return result; - } - result = ldap_set_option(ldc->ldap, LDAP_OPT_SSL, LDAP_OPT_ON); - if (result != LDAP_SUCCESS) { - /* SSL option failed */ - ldc->reason = "ldap_set_option() failed trying to set LDAP_OPT_SSL"; - return result; - } - } - } -#endif /* APU_HAS_LDAP_NETSCAPE_SSL */ - -#ifdef APU_HAS_LDAP_STARTTLS - if (ldc->starttls) { - int version = LDAP_VERSION3; - - /* Also we have to set the connection to use protocol version 3, - * since we're using TLS. */ - if ((result = ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, - &version)) != LDAP_SUCCESS) { - /* setting LDAP version failed - ignore error */ - } - - /* - * In util_ldap_connection_find, we compare ldc->withtls to - * sec->starttls to see if we have a cache match. On the off - * chance that apache's config processing rotines set starttls to - * some other true value besides 1, we set it to 1 here to ensure - * that the comparison succeeds. - */ - ldc->starttls = 1; - - result = ldap_start_tls_s(ldc->ldap, NULL, NULL); - if (result != LDAP_SUCCESS) { - /* start TLS failed */ - ldc->withtls = 0; - ldc->reason = "ldap_start_tls_s() failed"; - return result; - } - ldc->withtls = 1; - } else { - ldc->withtls = 0; - } -#endif /* APU_HAS_LDAP_STARTTLS */ - } - - /* - * At this point the LDAP connection is guaranteed alive. If bound says - * that we're bound already, we can just return. - */ - if (ldc->bound) { - ldc->reason = "LDAP connection open successful (already bound)"; - return LDAP_SUCCESS; - } - - /* - * Now bind with the username/password provided by the - * configuration. It will be an anonymous bind if no u/p was - * provided. - */ - if ((result = ldap_simple_bind_s(ldc->ldap, ldc->binddn, ldc->bindpw)) - == LDAP_SERVER_DOWN) { - /* couldn't connect - try again */ - ldc->reason = "ldap_simple_bind_s() failed with server down"; - goto start_over; - } - - if (result != LDAP_SUCCESS) { - /* LDAP fatal error occured */ - ldc->reason = "ldap_simple_bind_s() failed"; - return result; - } - - /* note how we are bound */ - ldc->bound = 1; - - ldc->reason = "LDAP connection open successful"; - return LDAP_SUCCESS; -} - - -/* - * Find an existing ldap connection struct that matches the - * provided ldap connection parameters. - * - * If not found in the cache, a new ldc structure will be allocated from st->pool - * and returned to the caller. If found in the cache, a pointer to the existing - * ldc structure will be returned. - */ -util_ldap_connection_t *util_ldap_connection_find(request_rec *r, const char *host, int port, - const char *binddn, const char *bindpw, deref_options deref, - int netscapessl, int starttls) -{ - struct util_ldap_connection_t *l, *p; /* To traverse the linked list */ - - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(r->server->module_config, - &ldap_module); - - - /* mutex lock this function */ - if (!st->mutex) { - apr_lock_create(&st->mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, st->pool); - } - apr_lock_acquire(st->mutex); - - /* Search for an exact connection match in the list that is not - * being used. - */ - for (l=st->connections,p=NULL; l; l=l->next) { - if ( (APR_SUCCESS == apr_lock_tryacquire(l->lock)) - && l->port == port - && strcmp(l->host, host) == 0 - && ( (!l->binddn && !binddn) || (l->binddn && binddn && !strcmp(l->binddn, binddn)) ) - && ( (!l->bindpw && !bindpw) || (l->bindpw && bindpw && !strcmp(l->bindpw, bindpw)) ) - && l->deref == deref -#ifdef APU_HAS_LDAP_NETSCAPE_SSL - && l->netscapessl == netscapessl -#endif -#ifdef APU_HAS_LDAP_STARTTLS - && l->withtls == starttls -#endif - ) - break; - p = l; - } - - /* If nothing found, search again, but we don't care about the - * binddn and bindpw this time. - */ - if (!l) { - for (l=st->connections,p=NULL; l; l=l->next) { - if ( (APR_SUCCESS == apr_lock_tryacquire(l->lock)) - && l->port == port - && strcmp(l->host, host) == 0 - && l->deref == deref -#ifdef APU_HAS_LDAP_NETSCAPE_SSL - && l->netscapessl == netscapessl -#endif -#ifdef APU_HAS_LDAP_STARTTLS - && l->withtls == starttls -#endif - ) { - /* the bind credentials have changed */ - l->bound = 0; - l->binddn = apr_pstrdup(st->pool, binddn); - l->bindpw = apr_pstrdup(st->pool, bindpw); - break; - } - p = l; - } - } - -/* artificially disable cache */ -//l = NULL; - - /* If no connection what found after the second search, we - * must create one. - */ - if (!l) { - - /* - * Add the new connection entry to the linked list. Note that we - * don't actually establish an LDAP connection yet; that happens - * the first time authentication is requested. - */ - /* create the details to the pool in st */ - l = apr_pcalloc(st->pool, sizeof(util_ldap_connection_t)); - apr_lock_create(&l->lock, APR_MUTEX, APR_INTRAPROCESS, NULL, st->pool); - apr_lock_acquire(l->lock); - l->pool = st->pool; - l->bound = 0; - l->host = apr_pstrdup(st->pool, host); - l->port = port; - l->deref = deref; - l->binddn = apr_pstrdup(st->pool, binddn); - l->bindpw = apr_pstrdup(st->pool, bindpw); - l->netscapessl = netscapessl; - l->starttls = starttls; - l->withtls = 0; - - if (p) { - p->next = l; - } - else { - st->connections = l; - } - } - - apr_lock_release(st->mutex); - return l; -} - -/* ------------------------------------------------------------------ */ - -/* - * Compares two DNs to see if they're equal. The only way to do this correctly is to - * search for the dn and then do ldap_get_dn() on the result. This should match the - * initial dn, since it would have been also retrieved with ldap_get_dn(). This is - * expensive, so if the configuration value compare_dn_on_server is - * false, just does an ordinary strcmp. - * - * The lock for the ldap cache should already be acquired. - */ -int util_ldap_cache_comparedn(request_rec *r, util_ldap_connection_t *ldc, - const char *url, const char *dn, const char *reqdn, - int compare_dn_on_server) -{ - int result = 0; - util_url_node_t *curl; - util_url_node_t curnode; - util_dn_compare_node_t *node; - util_dn_compare_node_t newnode; - int failures = 0; - LDAPMessage *res, *entry; - char *searchdn; - - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(r->server->module_config, - &ldap_module); - - - /* read lock this function */ - if (!util_ldap_cache_lock) { - apr_lock_create(&util_ldap_cache_lock, APR_READWRITE, APR_INTRAPROCESS, NULL, st->pool); - } - - /* get cache entry (or create one) */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_WRITER); - curnode.url = url; - curl = util_ald_cache_fetch(util_ldap_cache, &curnode); - if (curl == NULL) { - curl = util_ald_create_caches(st, url); - } - apr_lock_release(util_ldap_cache_lock); - - /* a simple compare? */ - if (!compare_dn_on_server) { - /* unlock this read lock */ - if (strcmp(dn, reqdn)) { - ldc->reason = "DN Comparison FALSE (direct strcmp())"; - return LDAP_COMPARE_FALSE; - } - else { - ldc->reason = "DN Comparison TRUE (direct strcmp())"; - return LDAP_COMPARE_TRUE; - } - } - - /* no - it's a server side compare */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_READER); - - /* is it in the compare cache? */ - newnode.reqdn = (char *)reqdn; - node = util_ald_cache_fetch(curl->dn_compare_cache, &newnode); - if (node != NULL) { - /* If it's in the cache, it's good */ - /* unlock this read lock */ - apr_lock_release(util_ldap_cache_lock); - ldc->reason = "DN Comparison TRUE (cached)"; - return LDAP_COMPARE_TRUE; - } - - /* unlock this read lock */ - apr_lock_release(util_ldap_cache_lock); - -start_over: - if (failures++ > 10) { - /* too many failures */ - return result; - } - - /* make a server connection */ - if (LDAP_SUCCESS != (result = util_ldap_connection_open(ldc))) { - /* connect to server failed */ - return result; - } - - /* search for reqdn */ - if ((result = ldap_search_ext_s(ldc->ldap, const_cast(reqdn), LDAP_SCOPE_BASE, - "(objectclass=*)", NULL, 1, - NULL, NULL, NULL, -1, &res)) == LDAP_SERVER_DOWN) { - util_ldap_connection_close(ldc); - ldc->reason = "DN Comparison ldap_search_ext_s() failed with server down"; - goto start_over; - } - if (result != LDAP_SUCCESS) { - /* search for reqdn failed - no match */ - ldc->reason = "DN Comparison ldap_search_ext_s() failed"; - return result; - } - - entry = ldap_first_entry(ldc->ldap, res); - searchdn = ldap_get_dn(ldc->ldap, entry); - - ldap_msgfree(res); - if (strcmp(dn, searchdn) != 0) { - /* compare unsuccessful */ - ldc->reason = "DN Comparison FALSE (checked on server)"; - result = LDAP_COMPARE_FALSE; - } - else { - /* compare successful - add to the compare cache */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_READER); - newnode.reqdn = (char *)reqdn; - newnode.dn = (char *)dn; - util_ald_cache_insert(curl->dn_compare_cache, &newnode); - apr_lock_release(util_ldap_cache_lock); - ldc->reason = "DN Comparison TRUE (checked on server)"; - result = LDAP_COMPARE_TRUE; - } - ldap_memfree(searchdn); - return result; - -} - -/* - * Does an generic ldap_compare operation. It accepts a cache that it will use - * to lookup the compare in the cache. We cache two kinds of compares - * (require group compares) and (require user compares). Each compare has a different - * cache node: require group includes the DN; require user does not because the - * require user cache is owned by the - * - */ -int util_ldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc, - const char *url, const char *dn, - const char *attrib, const char *value) -{ - int result = 0; - util_url_node_t *curl; - util_url_node_t curnode; - util_compare_node_t *compare_nodep; - util_compare_node_t the_compare_node; - apr_time_t curtime; - int failures = 0; - - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(r->server->module_config, - &ldap_module); - - - /* read lock this function */ - if (!util_ldap_cache_lock) { - apr_lock_create(&util_ldap_cache_lock, APR_READWRITE, APR_INTRAPROCESS, NULL, st->pool); - } - - /* get cache entry (or create one) */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_WRITER); - curnode.url = url; - curl = util_ald_cache_fetch(util_ldap_cache, &curnode); - if (curl == NULL) { - curl = util_ald_create_caches(st, url); - } - apr_lock_release(util_ldap_cache_lock); - - /* make a comparison to the cache */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_READER); - curtime = apr_time_now(); - - the_compare_node.dn = (char *)dn; - the_compare_node.attrib = (char *)attrib; - the_compare_node.value = (char *)value; - the_compare_node.result = 0; - - compare_nodep = util_ald_cache_fetch(curl->compare_cache, &the_compare_node); - - if (compare_nodep != NULL) { - /* found it... */ - if (curtime - compare_nodep->lastcompare > st->compare_cache_ttl) { - /* ...but it is too old */ - util_ald_cache_remove(curl->compare_cache, compare_nodep); - } - else { - /* ...and it is good */ - /* unlock this read lock */ - apr_lock_release(util_ldap_cache_lock); - if (LDAP_COMPARE_TRUE == compare_nodep->result) { - ldc->reason = "Comparison true (cached)"; - return compare_nodep->result; - } - else if (LDAP_COMPARE_FALSE == compare_nodep->result) { - ldc->reason = "Comparison false (cached)"; - return compare_nodep->result; - } - else if (LDAP_NO_SUCH_ATTRIBUTE == compare_nodep->result) { - ldc->reason = "Comparison no such attribute (cached)"; - return compare_nodep->result; - } - else { - ldc->reason = "Comparison undefined (cached)"; - return compare_nodep->result; - } - } - } - /* unlock this read lock */ - apr_lock_release(util_ldap_cache_lock); - - -start_over: - if (failures++ > 10) { - /* too many failures */ - return result; - } - if (LDAP_SUCCESS != (result = util_ldap_connection_open(ldc))) { - /* connect failed */ - return result; - } - - if ((result = ldap_compare_s(ldc->ldap, const_cast(dn), - const_cast(attrib), const_cast(value))) - == LDAP_SERVER_DOWN) { - /* connection failed - try again */ - util_ldap_connection_close(ldc); - ldc->reason = "ldap_compare_s() failed with server down"; - goto start_over; - } - - ldc->reason = "Comparison complete"; - if ((LDAP_COMPARE_TRUE == result) || - (LDAP_COMPARE_FALSE == result) || - (LDAP_NO_SUCH_ATTRIBUTE == result)) { - /* compare completed; caching result */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_WRITER); - the_compare_node.lastcompare = curtime; - the_compare_node.result = result; - util_ald_cache_insert(curl->compare_cache, &the_compare_node); - apr_lock_release(util_ldap_cache_lock); - if (LDAP_COMPARE_TRUE == result) { - ldc->reason = "Comparison true (adding to cache)"; - return LDAP_COMPARE_TRUE; - } - else if (LDAP_COMPARE_FALSE == result) { - ldc->reason = "Comparison false (adding to cache)"; - return LDAP_COMPARE_FALSE; - } - else { - ldc->reason = "Comparison no such attribute (adding to cache)"; - return LDAP_NO_SUCH_ATTRIBUTE; - } - } - return result; -} - -int util_ldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc, - const char *url, const char *basedn, int scope, char **attrs, - const char *filter, const char *bindpw, const char **binddn, - const char ***retvals) -{ - const char **vals = NULL; - int result = 0; - LDAPMessage *res, *entry; - char *dn; - int count; - int failures = 0; - util_url_node_t *curl; /* Cached URL node */ - util_url_node_t curnode; - util_search_node_t *search_nodep; /* Cached search node */ - util_search_node_t the_search_node; - apr_time_t curtime; - - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(r->server->module_config, - &ldap_module); - - /* read lock this function */ - if (!util_ldap_cache_lock) { - apr_lock_create(&util_ldap_cache_lock, APR_READWRITE, APR_INTRAPROCESS, NULL, st->pool); - } - - /* Get the cache node for this url */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_WRITER); - curnode.url = url; - curl = (util_url_node_t *)util_ald_cache_fetch(util_ldap_cache, &curnode); - if (curl == NULL) { - curl = util_ald_create_caches(st, url); - } - apr_lock_release(util_ldap_cache_lock); - - apr_lock_acquire_rw(util_ldap_cache_lock, APR_READER); - the_search_node.username = filter; - search_nodep = util_ald_cache_fetch(curl->search_cache, &the_search_node); - if (search_nodep != NULL && search_nodep->bindpw) { - - /* found entry in search cache... */ - curtime = apr_time_now(); - - /* - * Remove this item from the cache if its expired, or if the - * sent password doesn't match the storepassword. - */ - if ((curtime - search_nodep->lastbind) > st->search_cache_ttl) { - /* ...but entry is too old */ - util_ald_cache_remove(curl->search_cache, search_nodep); - } - else if (strcmp(search_nodep->bindpw, bindpw) != 0) { - /* ...but cached password doesn't match sent password */ - util_ald_cache_remove(curl->search_cache, search_nodep); - } - else { - /* ...and entry is valid */ - *binddn = search_nodep->dn; - *retvals = search_nodep->vals; - apr_lock_release(util_ldap_cache_lock); - ldc->reason = "Authentication successful (cached)"; - return LDAP_SUCCESS; - } - } - /* unlock this read lock */ - apr_lock_release(util_ldap_cache_lock); - - - /* - * At this point, there is no valid cached search, so lets do the search. - */ - - /* - * If any LDAP operation fails due to LDAP_SERVER_DOWN, control returns here. - */ -start_over: - if (failures++ > 10) { - return result; - } - if (LDAP_SUCCESS != (result = util_ldap_connection_open(ldc))) { - return result; - } - - /* try do the search */ - if ((result = ldap_search_ext_s(ldc->ldap, - basedn, scope, - filter, attrs, 0, - NULL, NULL, NULL, -1, &res)) == LDAP_SERVER_DOWN) { - ldc->reason = "ldap_search_ext_s() for user failed with server down"; - goto start_over; - } - - /* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */ - if (result != LDAP_SUCCESS) { - ldc->reason = "ldap_search_ext_s() for user failed"; - return result; - } - - /* - * We should have found exactly one entry; to find a different - * number is an error. - */ - count = ldap_count_entries(ldc->ldap, res); - if (count != 1) { - ldap_msgfree(res); - ldc->reason = "User is not unique (search found two or more matches)"; - return LDAP_NO_SUCH_OBJECT; - } - - entry = ldap_first_entry(ldc->ldap, res); - - /* Grab the dn, copy it into the pool, and free it again */ - dn = ldap_get_dn(ldc->ldap, entry); - *binddn = apr_pstrdup(st->pool, dn); - ldap_memfree(dn); - - /* - * A bind to the server with an empty password always succeeds, so - * we check to ensure that the password is not empty. This implies - * that users who actually do have empty passwords will never be - * able to authenticate with this module. I don't see this as a big - * problem. - */ - if (strlen(bindpw) <= 0) { - ldap_msgfree(res); - ldc->reason = "Empty password not allowed"; - return LDAP_INVALID_CREDENTIALS; - } - - /* - * Attempt to bind with the retrieved dn and the password. If the bind - * fails, it means that the password is wrong (the dn obviously - * exists, since we just retrieved it) - */ - if ((result = - ldap_simple_bind_s(ldc->ldap, *binddn, bindpw)) == - LDAP_SERVER_DOWN) { - ldc->reason = "ldap_simple_bind_s() to check user credentials failed with server down"; - goto start_over; - } - - /* failure? if so - return */ - if (result != LDAP_SUCCESS) { - ldc->reason = "ldap_simple_bind_s() to check user credentials failed"; - return result; - } - - /* - * Get values for the provided attributes. - */ - if (attrs) { - int k = 0; - int i = 0; - while (attrs[k++]); - vals = apr_pcalloc(r->pool, sizeof(char *) * (k+1)); - while (attrs[i]) { - char **values; - int j = 0; - char *str = NULL; - /* get values */ - values = ldap_get_values(ldc->ldap, entry, attrs[i]); - while (values && values[j]) { - str = str ? apr_pstrcat(r->pool, str, "; ", values[j], NULL) : apr_pstrdup(r->pool, values[j]); - j++; - } - vals[i] = str; - i++; - } - *retvals = vals; - } - - /* - * Add the new username to the search cache. - */ - apr_lock_acquire_rw(util_ldap_cache_lock, APR_WRITER); - the_search_node.username = filter; - the_search_node.dn = *binddn; - the_search_node.bindpw = bindpw; - the_search_node.lastbind = apr_time_now(); - the_search_node.vals = vals; - util_ald_cache_insert(curl->search_cache, &the_search_node); - ldap_msgfree(res); - apr_lock_release(util_ldap_cache_lock); - - ldc->reason = "Authentication successful"; - return LDAP_SUCCESS; -} - -#endif /* APU_HAS_LDAP */ - - - -/* ---------------------------------------- */ -/* config directives */ - - -static const char *util_ldap_set_cache_bytes(cmd_parms *cmd, void *dummy, const char *bytes) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config, - &ldap_module); - - st->cache_bytes = atol(bytes); - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "[%d] ldap cache: Setting shared memory cache size to %d bytes.", - getpid(), st->cache_bytes); - - return NULL; -} - -static const char *util_ldap_set_cache_ttl(cmd_parms *cmd, void *dummy, const char *ttl) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config, - &ldap_module); - - st->search_cache_ttl = atol(ttl) * 1000000; - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "[%d] ldap cache: Setting cache TTL to %ld microseconds.", - getpid(), st->search_cache_ttl); - - return NULL; -} - -static const char *util_ldap_set_cache_entries(cmd_parms *cmd, void *dummy, const char *size) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config, - &ldap_module); - - - st->search_cache_size = atol(size); - if (st->search_cache_size < 0) { - st->search_cache_size = 0; - } - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "[%d] ldap cache: Setting search cache size to %ld entries.", - getpid(), st->search_cache_size); - - return NULL; -} - -static const char *util_ldap_set_opcache_ttl(cmd_parms *cmd, void *dummy, const char *ttl) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config, - &ldap_module); - - st->compare_cache_ttl = atol(ttl) * 1000000; - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "[%d] ldap cache: Setting operation cache TTL to %ld microseconds.", - getpid(), st->compare_cache_ttl); - - return NULL; -} - -static const char *util_ldap_set_opcache_entries(cmd_parms *cmd, void *dummy, const char *size) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config, - &ldap_module); - - st->compare_cache_size = atol(size); - if (st->compare_cache_size < 0) { - st->compare_cache_size = 0; - } - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "[%d] ldap cache: Setting operation cache size to %ld entries.", - getpid(), st->compare_cache_size); - - return NULL; -} - -#ifdef APU_HAS_LDAPSSL_CLIENT_INIT -static const char *util_ldap_set_certdbpath(cmd_parms *cmd, void *dummy, const char *path) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config, - &ldap_module); - - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, - "[%d] ldap cache: Setting LDAP SSL client certificate dbpath to %s.", - getpid(), path); - - st->have_certdb = 1; - if (ldapssl_client_init(path, NULL) != 0) { - return "Could not initialize SSL client"; - } - else { - return NULL; - } -} -#endif - -void *util_ldap_create_config(apr_pool_t *p, server_rec *s) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)apr_pcalloc(p, sizeof(util_ldap_state_t)); - - st->pool = p; - - st->cache_bytes = 100000; - st->search_cache_ttl = 600000000; - st->search_cache_size = 1024; - st->compare_cache_ttl = 600000000; - st->compare_cache_size = 1024; - - st->connections = NULL; -#ifdef APU_HAS_LDAP_NETSCAPE_SSL - st->have_certdb = 0; -#endif - - return st; -} - -static void util_ldap_init_module(apr_pool_t *pool, server_rec *s) -{ - util_ldap_state_t *st = - (util_ldap_state_t *)ap_get_module_config(s->module_config, - &ldap_module); - - apr_status_t result = util_ldap_cache_init(pool, st->cache_bytes); - char buf[MAX_STRING_LEN]; - - apr_strerror(result, buf, sizeof(buf)); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, result, s, - "[%d] ldap cache init: %s", - getpid(), buf); -} - - -command_rec util_ldap_cmds[] = { - AP_INIT_TAKE1("LDAPSharedCacheSize", util_ldap_set_cache_bytes, NULL, RSRC_CONF, - "Sets the size of the shared memory cache in bytes. " - "Zero means disable the shared memory cache. Defaults to 100KB."), - - AP_INIT_TAKE1("LDAPCacheEntries", util_ldap_set_cache_entries, NULL, RSRC_CONF, - "Sets the maximum number of entries that are possible in the LDAP " - "search cache. " - "Zero means no limit; -1 disables the cache. Defaults to 1024 entries."), - - AP_INIT_TAKE1("LDAPCacheTTL", util_ldap_set_cache_ttl, NULL, RSRC_CONF, - "Sets the maximum time (in seconds) that an item can be cached in the LDAP " - "search cache. Zero means no limit. Defaults to 600 seconds (10 minutes)."), - - AP_INIT_TAKE1("LDAPOpCacheEntries", util_ldap_set_opcache_entries, NULL, RSRC_CONF, - "Sets the maximum number of entries that are possible in the LDAP " - "compare cache. " - "Zero means no limit; -1 disables the cache. Defaults to 1024 entries."), - - AP_INIT_TAKE1("LDAPOpCacheTTL", util_ldap_set_opcache_ttl, NULL, RSRC_CONF, - "Sets the maximum time (in seconds) that an item is cached in the LDAP " - "operation cache. Zero means no limit. Defaults to 600 seconds (10 minutes)."), - -#ifdef APU_HAS_LDAPSSL_CLIENT_INIT - AP_INIT_TAKE1("LDAPCertDBPath", util_ldap_set_certdbpath, NULL, RSRC_CONF, - "Specifies the file containing Certificate Authority certificates " - "for validating secure LDAP server certificates. This file must be the " - "cert7.db database used by Netscape Communicator"), -#endif - - {NULL} -}; - -static void util_ldap_register_hooks(apr_pool_t *p) -{ - ap_hook_child_init(util_ldap_init_module, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_handler(util_ldap_handler, NULL, NULL, APR_HOOK_MIDDLE); -} - -module ldap_module = { - STANDARD20_MODULE_STUFF, - NULL, /* dir config creater */ - NULL, /* dir merger --- default is to override */ - util_ldap_create_config, /* server config */ - NULL, /* merge server config */ - util_ldap_cmds, /* command table */ - util_ldap_register_hooks, /* set up request processing hooks */ -}; diff --git a/modules/experimental/util_ldap_cache.c b/modules/experimental/util_ldap_cache.c deleted file mode 100644 index 9d9844ddd6..0000000000 --- a/modules/experimental/util_ldap_cache.c +++ /dev/null @@ -1,309 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ - -/* - * util_ldap_cache.c: LDAP cache things - * - * Original code from auth_ldap module for Apache v1.3: - * Copyright 1998, 1999 Enbridge Pipelines Inc. - * Copyright 1999-2001 Dave Carrigan - */ - -#include <apr_ldap.h> -#include "util_ldap.h" -#include "util_ldap_cache.h" - -#ifdef APU_HAS_LDAP - - - - -/* ------------------------------------------------------------------ */ - -unsigned long util_ldap_url_node_hash(void *n) -{ - util_url_node_t *node = (util_url_node_t *)n; - return util_ald_hash_string(1, node->url); -} - -int util_ldap_url_node_compare(void *a, void *b) -{ - util_url_node_t *na = (util_url_node_t *)a; - util_url_node_t *nb = (util_url_node_t *)b; - - return(strcmp(na->url, nb->url) == 0); -} - -void *util_ldap_url_node_copy(void *c) -{ - util_url_node_t *n = (util_url_node_t *)c; - util_url_node_t *node = (util_url_node_t *)util_ald_alloc(sizeof(util_url_node_t)); - - if (node) { - if (!(node->url = util_ald_strdup(n->url))) { - util_ald_free(node->url); - return NULL; - } - node->search_cache = n->search_cache; - node->compare_cache = n->compare_cache; - node->dn_compare_cache = n->dn_compare_cache; - return node; - } - else { - return NULL; - } -} - -void util_ldap_url_node_free(void *n) -{ - util_url_node_t *node = (util_url_node_t *)n; - - util_ald_free(node->url); - util_ald_destroy_cache(node->search_cache); - util_ald_destroy_cache(node->compare_cache); - util_ald_destroy_cache(node->dn_compare_cache); - util_ald_free(node); -} - -/* ------------------------------------------------------------------ */ - -/* Cache functions for search nodes */ -unsigned long util_ldap_search_node_hash(void *n) -{ - util_search_node_t *node = (util_search_node_t *)n; - return util_ald_hash_string(1, ((util_search_node_t *)(node))->username); -} - -int util_ldap_search_node_compare(void *a, void *b) -{ - return(strcmp(((util_search_node_t *)a)->username, - ((util_search_node_t *)b)->username) == 0); -} - -void *util_ldap_search_node_copy(void *c) -{ - util_search_node_t *node = (util_search_node_t *)c; - util_search_node_t *newnode = util_ald_alloc(sizeof(util_search_node_t)); - - /* safety check */ - if (newnode) { - - /* copy vals */ - if (node->vals) { - int k = 0; - int i = 0; - while (node->vals[k++]); - if (!(newnode->vals = util_ald_alloc(sizeof(char *) * (k+1)))) { - util_ldap_search_node_free(newnode); - return NULL; - } - while (node->vals[i]) { - if (!(newnode->vals[i] = util_ald_strdup(node->vals[i]))) { - util_ldap_search_node_free(newnode); - return NULL; - } - i++; - } - } - else { - newnode->vals = NULL; - } - if (!(newnode->username = util_ald_strdup(node->username)) || - !(newnode->dn = util_ald_strdup(node->dn)) || - !(newnode->bindpw = util_ald_strdup(node->bindpw)) ) { - util_ldap_search_node_free(newnode); - return NULL; - } - newnode->lastbind = node->lastbind; - - } - return (void *)newnode; -} - -void util_ldap_search_node_free(void *n) -{ - int i = 0; - util_search_node_t *node = (util_search_node_t *)n; - if (node->vals) { - while (node->vals[i]) { - util_ald_free(node->vals[i++]); - } - util_ald_free(node->vals); - } - util_ald_free(node->username); - util_ald_free(node->dn); - util_ald_free(node->bindpw); - util_ald_free(node); -} - -/* ------------------------------------------------------------------ */ - -unsigned long util_ldap_compare_node_hash(void *n) -{ - util_compare_node_t *node = (util_compare_node_t *)n; - return util_ald_hash_string(3, node->dn, node->attrib, node->value); -} - -int util_ldap_compare_node_compare(void *a, void *b) -{ - util_compare_node_t *na = (util_compare_node_t *)a; - util_compare_node_t *nb = (util_compare_node_t *)b; - return (strcmp(na->dn, nb->dn) == 0 && - strcmp(na->attrib, nb->attrib) == 0 && - strcmp(na->value, nb->value) == 0); -} - -void *util_ldap_compare_node_copy(void *c) -{ - util_compare_node_t *n = (util_compare_node_t *)c; - util_compare_node_t *node = (util_compare_node_t *)util_ald_alloc(sizeof(util_compare_node_t)); - - if (node) { - if (!(node->dn = util_ald_strdup(n->dn)) || - !(node->attrib = util_ald_strdup(n->attrib)) || - !(node->value = util_ald_strdup(n->value))) { - util_ldap_compare_node_free(node); - return NULL; - } - node->lastcompare = n->lastcompare; - node->result = n->result; - return node; - } - else { - return NULL; - } -} - -void util_ldap_compare_node_free(void *n) -{ - util_compare_node_t *node = (util_compare_node_t *)n; - util_ald_free(node->dn); - util_ald_free(node->attrib); - util_ald_free(node->value); - util_ald_free(node); -} - -/* ------------------------------------------------------------------ */ - -unsigned long util_ldap_dn_compare_node_hash(void *n) -{ - return util_ald_hash_string(1, ((util_dn_compare_node_t *)n)->reqdn); -} - -int util_ldap_dn_compare_node_compare(void *a, void *b) -{ - return (strcmp(((util_dn_compare_node_t *)a)->reqdn, - ((util_dn_compare_node_t *)b)->reqdn) == 0); -} - -void *util_ldap_dn_compare_node_copy(void *c) -{ - util_dn_compare_node_t *n = (util_dn_compare_node_t *)c; - util_dn_compare_node_t *node = (util_dn_compare_node_t *)util_ald_alloc(sizeof(util_dn_compare_node_t)); - if (node) { - if (!(node->reqdn = util_ald_strdup(n->reqdn)) || - !(node->dn = util_ald_strdup(n->dn))) { - util_ldap_dn_compare_node_free(node); - return NULL; - } - return node; - } - else { - return NULL; - } -} - -void util_ldap_dn_compare_node_free(void *n) -{ - util_dn_compare_node_t *node = (util_dn_compare_node_t *)n; - util_ald_free(node->reqdn); - util_ald_free(node->dn); - util_ald_free(node); -} - - -/* ------------------------------------------------------------------ */ -apr_status_t util_ldap_cache_child_kill(void *data); -apr_status_t util_ldap_cache_module_kill(void *data); - -apr_status_t util_ldap_cache_module_kill(void *data) -{ -#if APR_HAS_SHARED_MEMORY - if (util_ldap_shm != NULL) { - apr_status_t result = apr_shm_destroy(util_ldap_shm); - util_ldap_shm = NULL; - return result; - } -#endif - return APR_SUCCESS; -} - -apr_status_t util_ldap_cache_init(apr_pool_t *pool, apr_size_t reqsize) -{ - apr_status_t result = APR_SUCCESS; - apr_pool_cleanup_register(pool, NULL, util_ldap_cache_module_kill, apr_pool_cleanup_null); - -#if APR_HAS_SHARED_MEMORY - result = apr_shm_init(&util_ldap_shm, reqsize, "/tmp/ldap_cache", pool); -#endif - util_ldap_cache = util_ald_create_cache(50, - util_ldap_url_node_hash, - util_ldap_url_node_compare, - util_ldap_url_node_copy, - util_ldap_url_node_free); - return result; -} - - -#endif /* APU_HAS_LDAP */ diff --git a/modules/experimental/util_ldap_cache.h b/modules/experimental/util_ldap_cache.h deleted file mode 100644 index 18790eb854..0000000000 --- a/modules/experimental/util_ldap_cache.h +++ /dev/null @@ -1,214 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ - - -#ifndef APU_LDAP_CACHE_H -#define APU_LDAP_CACHE_H - -/* - * This switches LDAP support on or off. - */ - -/* this whole thing disappears if LDAP is not enabled */ -#ifdef APU_HAS_LDAP - - -/* - * LDAP Cache Manager - */ - -#include <apr_shmem.h> - -typedef struct util_cache_node_t { - void *payload; /* Pointer to the payload */ - time_t add_time; /* Time node was added to cache */ - struct util_cache_node_t *next; -} util_cache_node_t; - -typedef struct util_ald_cache_t { - unsigned long size; /* Size of cache array */ - unsigned long maxentries; /* Maximum number of cache entries */ - unsigned long numentries; /* Current number of cache entries */ - unsigned long fullmark; /* Used to keep track of when cache becomes 3/4 full */ - time_t marktime; /* Time that the cache became 3/4 full */ - unsigned long (*hash)(void *); /* Func to hash the payload */ - int (*compare)(void *, void *); /* Func to compare two payloads */ - void * (*copy)(void *); /* Func to alloc mem and copy payload to new mem */ - void (*free)(void *); /* Func to free mem used by the payload */ - util_cache_node_t **nodes; - - unsigned long numpurges; /* No. of times the cache has been purged */ - double avg_purgetime; /* Average time to purge the cache */ - time_t last_purge; /* Time of the last purge */ - unsigned long npurged; /* Number of elements purged in last purge. This is not - obvious: it won't be 3/4 the size of the cache if - there were a lot of expired entries. */ - - unsigned long fetches; /* Number of fetches */ - unsigned long hits; /* Number of cache hits */ - unsigned long inserts; /* Number of inserts */ - unsigned long removes; /* Number of removes */ -} util_ald_cache_t; - -#if APR_HAS_SHARED_MEMORY -apr_shmem_t *util_ldap_shm; -#endif -util_ald_cache_t *util_ldap_cache; -apr_lock_t *util_ldap_cache_lock; - -#ifndef WIN32 -#define ALD_MM_FILE_MODE ( S_IRUSR|S_IWUSR ) -#else -#define ALD_MM_FILE_MODE ( _S_IREAD|_S_IWRITE ) -#endif - - -/* - * LDAP Cache - */ - -/* - * Maintain a cache of LDAP URLs that the server handles. Each node in - * the cache contains the search cache for that URL, and a compare cache - * for the URL. The compare cash is populated when doing require group - * compares. - */ -typedef struct util_url_node_t { - const char *url; - util_ald_cache_t *search_cache; - util_ald_cache_t *compare_cache; - util_ald_cache_t *dn_compare_cache; -} util_url_node_t; - -/* - * We cache every successful search and bind operation, using the username - * as the key. Each node in the cache contains the returned DN, plus the - * password used to bind. - */ -typedef struct util_search_node_t { - const char *username; /* Cache key */ - const char *dn; /* DN returned from search */ - const char *bindpw; /* The most recently used bind password; - NULL if the bind failed */ - apr_time_t lastbind; /* Time of last successful bind */ - const char **vals; /* Values of queried attributes */ -} util_search_node_t; - -/* - * We cache every successful compare operation, using the DN, attrib, and - * value as the key. - */ -typedef struct util_compare_node_t { - const char *dn; /* DN, attrib and value combine to be the key */ - const char *attrib; - const char *value; - apr_time_t lastcompare; - int result; -} util_compare_node_t; - -/* - * We cache every successful compare dn operation, using the dn in the require - * statement and the dn fetched based on the client-provided username. - */ -typedef struct util_dn_compare_node_t { - const char *reqdn; /* The DN in the require dn statement */ - const char *dn; /* The DN found in the search */ -} util_dn_compare_node_t; - - -/* - * Function prototypes for LDAP cache - */ - -/* util_ldap_cache.c */ -unsigned long util_ldap_url_node_hash(void *n); -int util_ldap_url_node_compare(void *a, void *b); -void *util_ldap_url_node_copy(void *c); -void util_ldap_url_node_free(void *n); -unsigned long util_ldap_search_node_hash(void *n); -int util_ldap_search_node_compare(void *a, void *b); -void *util_ldap_search_node_copy(void *c); -void util_ldap_search_node_free(void *n); -unsigned long util_ldap_compare_node_hash(void *n); -int util_ldap_compare_node_compare(void *a, void *b); -void *util_ldap_compare_node_copy(void *c); -void util_ldap_compare_node_free(void *n); -unsigned long util_ldap_dn_compare_node_hash(void *n); -int util_ldap_dn_compare_node_compare(void *a, void *b); -void *util_ldap_dn_compare_node_copy(void *c); -void util_ldap_dn_compare_node_free(void *n); - - -/* util_ldap_cache_mgr.c */ - -void util_ald_free(const void *ptr); -void *util_ald_alloc(unsigned long size); -const char *util_ald_strdup(const char *s); -unsigned long util_ald_hash_string(int nstr, ...); -void util_ald_cache_purge(util_ald_cache_t *cache); -util_url_node_t *util_ald_create_caches(util_ldap_state_t *s, const char *url); -util_ald_cache_t *util_ald_create_cache(unsigned long maxentries, - unsigned long (*hashfunc)(void *), - int (*comparefunc)(void *, void *), - void * (*copyfunc)(void *), - void (*freefunc)(void *)); -void util_ald_destroy_cache(util_ald_cache_t *cache); -void *util_ald_cache_fetch(util_ald_cache_t *cache, void *payload); -void util_ald_cache_insert(util_ald_cache_t *cache, void *payload); -void util_ald_cache_remove(util_ald_cache_t *cache, void *payload); -char *util_ald_cache_display_stats(apr_pool_t *p, util_ald_cache_t *cache, - char *name); - -#endif /* APU_HAS_LDAP */ -#endif /* APU_LDAP_CACHE_H */ diff --git a/modules/experimental/util_ldap_cache_mgr.c b/modules/experimental/util_ldap_cache_mgr.c deleted file mode 100644 index 49eece8958..0000000000 --- a/modules/experimental/util_ldap_cache_mgr.c +++ /dev/null @@ -1,537 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ - -/* - * util_ldap_cache_mgr.c: LDAP cache manager things - * - * Original code from auth_ldap module for Apache v1.3: - * Copyright 1998, 1999 Enbridge Pipelines Inc. - * Copyright 1999-2001 Dave Carrigan - */ - -#include <apr_ldap.h> -#include "util_ldap.h" -#include "util_ldap_cache.h" -#include <apr_strings.h> - -#ifdef APU_HAS_LDAP - -/* only here until strdup is gone */ -#include <string.h> - -/* here till malloc is gone */ -#include <stdlib.h> - -static const int primes[] = -{ - 11, - 19, - 37, - 73, - 109, - 163, - 251, - 367, - 557, - 823, - 1237, - 1861, - 2777, - 4177, - 6247, - 9371, - 14057, - 21089, - 31627, - 47431, - 71143, - 106721, - 160073, - 240101, - 360163, - 540217, - 810343, - 1215497, - 1823231, - 2734867, - 4102283, - 6153409, - 9230113, - 13845163, - 0 -}; - -void util_ald_free(const void *ptr) -{ -#if APR_HAS_SHARED_MEMORY - if (util_ldap_shm) { - if (ptr) - apr_shm_free(util_ldap_shm, (void *)ptr); - } else { - if (ptr) - free((void *)ptr); - } -#else - if (ptr) - free((void *)ptr); -#endif -} - -void *util_ald_alloc(unsigned long size) -{ - if (0 == size) - return NULL; -#if APR_HAS_SHARED_MEMORY - if (util_ldap_shm) { - return (void *)apr_shm_calloc(util_ldap_shm, size); - } else { - return (void *)calloc(sizeof(char), size); - } -#else - return (void *)calloc(sizeof(char), size); -#endif -} - -const char *util_ald_strdup(const char *s) -{ -#if APR_HAS_SHARED_MEMORY - if (util_ldap_shm) { - char *buf = apr_shm_malloc(util_ldap_shm, strlen(s)+1); - if (buf) { - strcpy(buf, s); - return buf; - } - else { - return NULL; - } - } else { - return strdup(s); - } -#else - return strdup(s); -#endif -} - - -/* - * Computes the hash on a set of strings. The first argument is the number - * of strings to hash, the rest of the args are strings. - * Algorithm taken from glibc. - */ -unsigned long util_ald_hash_string(int nstr, ...) -{ - int i; - va_list args; - unsigned long h=0, g; - char *str, *p; - - va_start(args, nstr); - for (i=0; i < nstr; ++i) { - str = va_arg(args, char *); - for (p = str; *p; ++p) { - h = ( h << 4 ) + *p; - if ( ( g = h & 0xf0000000 ) ) { - h = h ^ (g >> 24); - h = h ^ g; - } - } - } - va_end(args); - - return h; -} - - -/* - Purges a cache that has gotten full. We keep track of the time that we - added the entry that made the cache 3/4 full, then delete all entries - that were added before that time. It's pretty simplistic, but time to - purge is only O(n), which is more important. -*/ -void util_ald_cache_purge(util_ald_cache_t *cache) -{ - int i; - util_cache_node_t *p, *q; - apr_time_t t; - - if (!cache) - return; - - cache->last_purge = apr_time_now(); - cache->npurged = 0; - cache->numpurges++; - - for (i=0; i < cache->size; ++i) { - p = cache->nodes[i]; - while (p != NULL) { - if (p->add_time < cache->marktime) { - q = p->next; - (*cache->free)(p->payload); - util_ald_free(p); - cache->numentries--; - cache->npurged++; - p = q; - } - else { - p = p->next; - } - } - } - - t = apr_time_now(); - cache->avg_purgetime = - ((t - cache->last_purge) + (cache->avg_purgetime * (cache->numpurges-1))) / - cache->numpurges; -} - - -/* - * create caches - */ -util_url_node_t *util_ald_create_caches(util_ldap_state_t *st, const char *url) -{ - util_url_node_t *curl = NULL; - util_ald_cache_t *search_cache; - util_ald_cache_t *compare_cache; - util_ald_cache_t *dn_compare_cache; - - /* create the three caches */ - search_cache = util_ald_create_cache(st->search_cache_size, - util_ldap_search_node_hash, - util_ldap_search_node_compare, - util_ldap_search_node_copy, - util_ldap_search_node_free); - compare_cache = util_ald_create_cache(st->compare_cache_size, - util_ldap_compare_node_hash, - util_ldap_compare_node_compare, - util_ldap_compare_node_copy, - util_ldap_compare_node_free); - dn_compare_cache = util_ald_create_cache(st->compare_cache_size, - util_ldap_dn_compare_node_hash, - util_ldap_dn_compare_node_compare, - util_ldap_dn_compare_node_copy, - util_ldap_dn_compare_node_free); - - /* check that all the caches initialised successfully */ - if (search_cache && compare_cache && dn_compare_cache) { - - curl = (util_url_node_t *)apr_pcalloc(st->pool, sizeof(util_url_node_t)); - curl->url = url; - curl->search_cache = search_cache; - curl->compare_cache = compare_cache; - curl->dn_compare_cache = dn_compare_cache; - - util_ald_cache_insert(util_ldap_cache, curl); - - } - - return curl; -} - - -util_ald_cache_t *util_ald_create_cache(unsigned long maxentries, - unsigned long (*hashfunc)(void *), - int (*comparefunc)(void *, void *), - void * (*copyfunc)(void *), - void (*freefunc)(void *)) -{ - util_ald_cache_t *cache; - int i; - - if (maxentries <= 0) - return NULL; - - cache = (util_ald_cache_t *)util_ald_alloc(sizeof(util_ald_cache_t)); - if (!cache) - return NULL; - - cache->maxentries = maxentries; - cache->numentries = 0; - cache->size = maxentries / 3; - if (cache->size < 64) cache->size = 64; - for (i = 0; primes[i] && primes[i] < cache->size; ++i) ; - cache->size = primes[i]? primes[i] : primes[i-1]; - - cache->nodes = (util_cache_node_t **)util_ald_alloc(cache->size * sizeof(util_cache_node_t *)); - if (!cache->nodes) { - util_ald_free(cache); - return NULL; - } - - for (i=0; i < cache->size; ++i) - cache->nodes[i] = NULL; - - cache->hash = hashfunc; - cache->compare = comparefunc; - cache->copy = copyfunc; - cache->free = freefunc; - - cache->fullmark = cache->maxentries / 4 * 3; - cache->marktime = 0; - cache->avg_purgetime = 0.0; - cache->numpurges = 0; - cache->last_purge = 0; - cache->npurged = 0; - - cache->fetches = 0; - cache->hits = 0; - cache->inserts = 0; - cache->removes = 0; - - return cache; -} - -void util_ald_destroy_cache(util_ald_cache_t *cache) -{ - int i; - util_cache_node_t *p, *q; - - if (cache == NULL) - return; - - for (i = 0; i < cache->size; ++i) { - p = cache->nodes[i]; - q = NULL; - while (p != NULL) { - q = p->next; - (*cache->free)(p->payload); - util_ald_free(p); - p = q; - } - } - util_ald_free(cache->nodes); -} - -void *util_ald_cache_fetch(util_ald_cache_t *cache, void *payload) -{ - int hashval; - util_cache_node_t *p; - - if (cache == NULL) - return NULL; - - cache->fetches++; - - hashval = (*cache->hash)(payload) % cache->size; - for (p = cache->nodes[hashval]; - p && !(*cache->compare)(p->payload, payload); - p = p->next) ; - - if (p != NULL) { - cache->hits++; - return p->payload; - } - else { - return NULL; - } -} - -/* - * Insert an item into the cache. - * *** Does not catch duplicates!!! *** - */ -void util_ald_cache_insert(util_ald_cache_t *cache, void *payload) -{ - int hashval; - util_cache_node_t *node; - - if (cache == NULL || payload == NULL) - return; - - cache->inserts++; - hashval = (*cache->hash)(payload) % cache->size; - node = (util_cache_node_t *)util_ald_alloc(sizeof(util_cache_node_t)); - node->add_time = apr_time_now(); - node->payload = (*cache->copy)(payload); - node->next = cache->nodes[hashval]; - cache->nodes[hashval] = node; - if (++cache->numentries == cache->fullmark) - cache->marktime=apr_time_now(); - if (cache->numentries >= cache->maxentries) - util_ald_cache_purge(cache); -} - -void util_ald_cache_remove(util_ald_cache_t *cache, void *payload) -{ - int hashval; - util_cache_node_t *p, *q; - - if (cache == NULL) - return; - - cache->removes++; - hashval = (*cache->hash)(payload) % cache->size; - for (p = cache->nodes[hashval], q=NULL; - p && !(*cache->compare)(p->payload, payload); - p = p->next) { - q = p; - } - - /* If p is null, it means that we couldn't find the node, so just return */ - if (p == NULL) - return; - - if (q == NULL) { - /* We found the node, and it's the first in the list */ - cache->nodes[hashval] = p->next; - } - else { - /* We found the node and it's not the first in the list */ - q->next = p->next; - } - (*cache->free)(p->payload); - util_ald_free(p); - cache->numentries--; -} - -char *util_ald_cache_display_stats(apr_pool_t *p, util_ald_cache_t *cache, char *name) -{ - int i; - int totchainlen = 0; - int nchains = 0; - double chainlen; - util_cache_node_t *n; - char *buf; - - if (cache == NULL) { - return ""; - } - - for (i=0; i < cache->size; ++i) { - if (cache->nodes[i] != NULL) { - nchains++; - for (n = cache->nodes[i]; n != NULL; n = n->next) - totchainlen++; - } - } - chainlen = nchains? (double)totchainlen / (double)nchains : 0; - - buf = apr_psprintf(p, - "<tr valign='top'>" - "<td nowrap>%s</td>" - "<td align='right' nowrap>%lu (%.0f%% full)</td>" - "<td align='right'>%.1f</td>" - "<td align='right'>%lu/%lu</td>" - "<td align='right'>%.0f%%</td>" - "<td align='right'>%lu/%lu</td>", - name, - cache->numentries, - (double)cache->numentries / (double)cache->maxentries * 100.0, - chainlen, - cache->hits, - cache->fetches, - (cache->fetches > 0 ? (double)(cache->hits) / (double)(cache->fetches) * 100.0 : 100.0), - cache->inserts, - cache->removes); - - if (cache->numpurges) { - char str_ctime[APR_CTIME_LEN]; - - apr_ctime(str_ctime, cache->last_purge); - buf = apr_psprintf(p, - "%s" - "<td align='right'>%lu</td>\n" - "<td align='right' nowrap>%s</td>\n", - buf, - cache->numpurges, - str_ctime); - } - else { - buf = apr_psprintf(p, - "%s<td colspan='2' align='center'>(none)</td>\n", - buf); - } - - buf = apr_psprintf(p, "%s<td align='right'>%.2g</td>\n</tr>", buf, cache->avg_purgetime); - - return buf; -} - -char *util_ald_cache_display(apr_pool_t *pool) -{ - int i; - char *buf, *t1, *t2, *t3; - - if (!util_ldap_cache) { - return "<tr valign='top'><td nowrap colspan=7>Cache has not been enabled/initialised.</td></tr>"; - } - - buf = util_ald_cache_display_stats(pool, util_ldap_cache, "LDAP URL Cache"); - - for (i=0; i < util_ldap_cache->size; ++i) { - util_cache_node_t *p; - for (p = util_ldap_cache->nodes[i]; p != NULL; p = p->next) { - util_url_node_t *n; - - n = (util_url_node_t *)p->payload; - - t1 = apr_psprintf(pool, "%s (Searches)", n->url); - t2 = apr_psprintf(pool, "%s (Compares)", n->url); - t3 = apr_psprintf(pool, "%s (DNCompares)", n->url); - - buf = apr_psprintf(pool, "%s\n\n" - "%s\n\n" - "%s\n\n" - "%s\n\n", - buf, - util_ald_cache_display_stats(pool, n->search_cache, t1), - util_ald_cache_display_stats(pool, n->compare_cache, t2), - util_ald_cache_display_stats(pool, n->dn_compare_cache, t3) - ); - } - } - return buf; -} - -#endif /* APU_HAS_LDAP */ diff --git a/modules/generators/mod_cgid.c b/modules/generators/mod_cgid.c index 5d3c4e7006..91bfd76bff 100644 --- a/modules/generators/mod_cgid.c +++ b/modules/generators/mod_cgid.c @@ -764,10 +764,12 @@ static int log_script(request_rec *r, cgid_server_conf * conf, int ret, (apr_file_open(&f, conf->logname, APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) { /* Soak up script output */ - while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0) + while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, + script_in) == APR_SUCCESS) continue; if (script_err) { - while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0) + while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, + script_err) == APR_SUCCESS) continue; } return ret; @@ -804,19 +806,22 @@ static int log_script(request_rec *r, cgid_server_conf * conf, int ret, if (sbuf && *sbuf) apr_file_printf(f, "%s\n", sbuf); - if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0) { + if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == APR_SUCCESS) { apr_file_puts("%stdout\n", f); apr_file_puts(argsbuffer, f); - while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0) + while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, + script_in) == APR_SUCCESS) apr_file_puts(argsbuffer, f); apr_file_puts("\n", f); } if (script_err) { - if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0) { + if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, + script_err) == APR_SUCCESS) { apr_file_puts("%stderr\n", f); apr_file_puts(argsbuffer, f); - while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0) + while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, + script_err) == APR_SUCCESS) apr_file_puts(argsbuffer, f); apr_file_puts("\n", f); } @@ -990,7 +995,8 @@ static int cgid_handler(request_rec *r) if (location && location[0] == '/' && r->status == 200) { /* Soak up all the script output */ - while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, tempsock) > 0) { + while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, + tempsock) == APR_SUCCESS) { continue; } /* This redirect needs to be a GET no matter what the original @@ -1196,7 +1202,8 @@ static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *comman char argsbuffer[HUGE_STRING_LEN]; /* Soak up all the script output */ - while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, tempsock) > 0) { + while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, + tempsock) == APR_SUCCESS) { continue; } /* This redirect needs to be a GET no matter what the original diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c index 2c3c727f53..2d356780bd 100644 --- a/modules/metadata/mod_headers.c +++ b/modules/metadata/mod_headers.c @@ -190,7 +190,7 @@ static const char *header_request_time(request_rec *r, char *a) } static const char *header_request_env_var(request_rec *r, char *a) { - char *s = apr_table_get(r->subprocess_env,a); + const char *s = apr_table_get(r->subprocess_env,a); if (s) return s; diff --git a/server/mpm/experimental/perchild/.cvsignore b/server/mpm/experimental/perchild/.cvsignore deleted file mode 100644 index 84df257214..0000000000 --- a/server/mpm/experimental/perchild/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -.deps -.libs -*.lo -*.la -Makefile diff --git a/server/mpm/experimental/perchild/Makefile.in b/server/mpm/experimental/perchild/Makefile.in deleted file mode 100644 index 374f130646..0000000000 --- a/server/mpm/experimental/perchild/Makefile.in +++ /dev/null @@ -1,5 +0,0 @@ - -LTLIBRARY_NAME = libperchild.la -LTLIBRARY_SOURCES = perchild.c - -include $(top_srcdir)/build/ltlib.mk diff --git a/server/mpm/experimental/perchild/config5.m4 b/server/mpm/experimental/perchild/config5.m4 deleted file mode 100644 index bd179baed9..0000000000 --- a/server/mpm/experimental/perchild/config5.m4 +++ /dev/null @@ -1,6 +0,0 @@ -dnl ## XXX - Need a more thorough check of the proper flags to use - -if test "$MPM_NAME" = "perchild" ; then - - APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile) -fi diff --git a/server/mpm/experimental/perchild/mpm.h b/server/mpm/experimental/perchild/mpm.h deleted file mode 100644 index c1bbf0ae8f..0000000000 --- a/server/mpm/experimental/perchild/mpm.h +++ /dev/null @@ -1,99 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -#include "httpd.h" -#include "mpm_default.h" -#include "unixd.h" - -#ifndef APACHE_MPM_PERCHILD_H -#define APACHE_MPM_PERCHILD_H - -#define PERCHILD_MPM - -#define MPM_NAME "Perchild" - -#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES -#define AP_MPM_WANT_WAIT_OR_TIMEOUT -#define AP_MPM_WANT_PROCESS_CHILD_STATUS -#define AP_MPM_WANT_SET_PIDFILE -#define AP_MPM_WANT_SET_SCOREBOARD -#define AP_MPM_WANT_SET_LOCKFILE -#define AP_MPM_WANT_SET_MAX_REQUESTS -#define AP_MPM_WANT_SET_COREDUMPDIR -#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH - -#define MPM_SYNC_CHILD_TABLE() -#define MPM_CHILD_PID(i) (ap_child_table[i].pid) -#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0) - -/* Table of child status */ -#define SERVER_DEAD 0 -#define SERVER_DYING 1 -#define SERVER_ALIVE 2 - -typedef struct ap_ctable{ - pid_t pid; - unsigned char status; -} ap_ctable; - -extern int ap_threads_per_child; -extern int ap_max_daemons_limit; -extern ap_ctable ap_child_table[HARD_SERVER_LIMIT]; -extern server_rec *ap_server_conf; - -#endif /* APACHE_MPM_PERCHILD_H */ diff --git a/server/mpm/experimental/perchild/mpm_default.h b/server/mpm/experimental/perchild/mpm_default.h deleted file mode 100644 index f462ea8f90..0000000000 --- a/server/mpm/experimental/perchild/mpm_default.h +++ /dev/null @@ -1,147 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -#ifndef APACHE_MPM_DEFAULT_H -#define APACHE_MPM_DEFAULT_H - -#define AP_ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t) -#define AP_CHILD_THREAD_FROM_ID(i) (i / HARD_THREAD_LIMIT), (i % HARD_THREAD_LIMIT) - -/* Number of threads to spawn off by default --- also, if fewer than - * this free when the caretaker checks, it will spawn more. - */ -#ifndef DEFAULT_START_THREAD -#define DEFAULT_START_THREAD 5 -#endif - -/* Maximum number of *free* server threads --- more than this, and - * they will die off. - */ - -#ifndef DEFAULT_MAX_SPARE_THREAD -#define DEFAULT_MAX_SPARE_THREAD 10 -#endif - -/* Minimum --- fewer than this, and more will be created */ - -#ifndef DEFAULT_MIN_SPARE_THREAD -#define DEFAULT_MIN_SPARE_THREAD 5 -#endif - -/* Limit on the threads per process. Clients will be locked out if more than - * this * HARD_SERVER_LIMIT are needed. - * - * We keep this for one reason it keeps the size of the scoreboard file small - * enough that we can read the whole thing without worrying too much about - * the overhead. - */ -#ifndef HARD_THREAD_LIMIT -#define HARD_THREAD_LIMIT 64 -#endif - -/* Number of servers to spawn off by default - */ -#ifndef DEFAULT_NUM_DAEMON -#define DEFAULT_NUM_DAEMON 2 -#endif - -/* Limit on the total --- clients will be locked out if more servers than - * this are needed. It is intended solely to keep the server from crashing - * when things get out of hand. - * - * We keep a hard maximum number of servers, for two reasons --- first off, - * in case something goes seriously wrong, we want to stop the fork bomb - * short of actually crashing the machine we're running on by filling some - * kernel table. Secondly, it keeps the size of the scoreboard file small - * enough that we can read the whole thing without worrying too much about - * the overhead. - */ -#ifndef HARD_SERVER_LIMIT -#define HARD_SERVER_LIMIT 8 -#endif - -/* File used for accept locking, when we use a file */ -#ifndef DEFAULT_LOCKFILE -#define DEFAULT_LOCKFILE "logs/accept.lock" -#endif - -/* Scoreboard file, if there is one */ -#ifndef DEFAULT_SCOREBOARD -#define DEFAULT_SCOREBOARD "logs/apache_runtime_status" -#endif - -/* Where the main/parent process's pid is logged */ -#ifndef DEFAULT_PIDLOG -#define DEFAULT_PIDLOG "logs/httpd.pid" -#endif - -/* - * Interval, in microseconds, between scoreboard maintenance. - */ -#ifndef SCOREBOARD_MAINTENANCE_INTERVAL -#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000 -#endif - -/* Number of requests to try to handle in a single process. If <= 0, - * the children don't die off. - */ -#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD -#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000 -#endif - -#endif /* AP_MPM_DEFAULT_H */ diff --git a/server/mpm/experimental/perchild/perchild.c b/server/mpm/experimental/perchild/perchild.c deleted file mode 100644 index f2cb943ee7..0000000000 --- a/server/mpm/experimental/perchild/perchild.c +++ /dev/null @@ -1,1782 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -#include "apr_hash.h" -#include "apr_strings.h" -#include "apr_pools.h" -#include "apr_portable.h" -#include "apr_file_io.h" -#include "apr_signal.h" - -#define APR_WANT_IOVEC -#include "apr_want.h" - -#if APR_HAVE_UNISTD_H -#include <unistd.h> -#endif -#if APR_HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif - -#if !APR_HAS_THREADS -#error The perchild MPM requires APR threads, but they are unavailable. -#endif - -#define CORE_PRIVATE - -#include "ap_config.h" -#include "httpd.h" -#include "http_main.h" -#include "http_log.h" -#include "http_config.h" /* for read_config */ -#include "http_core.h" /* for get_remote_host */ -#include "http_protocol.h" -#include "http_connection.h" -#include "ap_mpm.h" -#include "unixd.h" -#include "mpm_common.h" -#include "ap_listen.h" -#include "mpm_default.h" -#include "mpm.h" -#include "scoreboard.h" -#include "util_filter.h" - -/* ### should be APR-ized */ -#include <poll.h> -#include <grp.h> -#include <pwd.h> -#include <sys/stat.h> -#include <sys/un.h> -#include <setjmp.h> -#ifdef HAVE_SYS_PROCESSOR_H -#include <sys/processor.h> /* for bindprocessor() */ -#endif - -/* - * Actual definitions of config globals - */ - -static int threads_to_start = 0; /* Worker threads per child */ -static int min_spare_threads = 0; -static int max_spare_threads = 0; -static int max_threads = 0; -static int max_requests_per_child = 0; -static int num_daemons = 0; -static int curr_child_num = 0; -static int workers_may_exit = 0; -static int requests_this_child; -static int num_listenfds = 0; -static apr_socket_t **listenfds; -static jmp_buf jmpbuffer; - -struct child_info_t { - uid_t uid; - gid_t gid; - int sd; -}; - -typedef struct { - const char *sockname; /* The base name for the socket */ - const char *fullsockname; /* socket base name + extension */ - int sd; /* The socket descriptor */ - int sd2; /* The socket descriptor */ -} perchild_server_conf; - -typedef struct child_info_t child_info_t; - -/* Tables used to determine the user and group each child process should - * run as. The hash table is used to correlate a server name with a child - * process. - */ -static child_info_t child_info_table[HARD_SERVER_LIMIT]; -static int thread_socket_table[HARD_THREAD_LIMIT]; - - -struct ap_ctable ap_child_table[HARD_SERVER_LIMIT]; - -/* - * The max child slot ever assigned, preserved across restarts. Necessary - * to deal with NumServers changes across AP_SIG_GRACEFUL restarts. We - * use this value to optimize routines that have to scan the entire child - * table. - * - * XXX - It might not be worth keeping this code in. There aren't very - * many child processes in this MPM. - */ -int ap_max_daemons_limit = -1; -int ap_threads_per_child = HARD_THREAD_LIMIT; - -module AP_MODULE_DECLARE_DATA mpm_perchild_module; - -static apr_file_t *pipe_of_death_in = NULL; -static apr_file_t *pipe_of_death_out = NULL; -static apr_lock_t *pipe_of_death_mutex; - -/* *Non*-shared http_main globals... */ - -server_rec *ap_server_conf; - -/* one_process --- debugging mode variable; can be set from the command line - * with the -X flag. If set, this gets you the child_main loop running - * in the process which originally started up (no detach, no make_child), - * which is a pretty nice debugging environment. (You'll get a SIGHUP - * early in standalone_main; just continue through. This is the server - * trying to kill off any child processes which it might have lying - * around --- Apache doesn't keep track of their pids, it just sends - * SIGHUP to the process group, ignoring it in the root process. - * Continue through and you'll be fine.). - */ - -static int one_process = 0; - -#ifdef DEBUG_SIGSTOP -int raise_sigstop_flags; -#endif - -static apr_pool_t *pconf; /* Pool for config stuff */ -static apr_pool_t *pchild; /* Pool for httpd child stuff */ -static apr_pool_t *thread_pool_parent; /* Parent of per-thread pools */ -static apr_lock_t *thread_pool_parent_mutex; - -static int child_num; -static unsigned int my_pid; /* Linux getpid() doesn't work except in - main thread. Use this instead */ -/* Keep track of the number of worker threads currently active */ -static int worker_thread_count; -static apr_lock_t *worker_thread_count_mutex; -static int worker_thread_free_ids[HARD_THREAD_LIMIT]; -static apr_threadattr_t *worker_thread_attr; - -/* Keep track of the number of idle worker threads */ -static int idle_thread_count; -static apr_lock_t *idle_thread_count_mutex; - -/* Locks for accept serialization */ -#ifdef NO_SERIALIZED_ACCEPT -#define SAFE_ACCEPT(stmt) APR_SUCCESS -#else -#define SAFE_ACCEPT(stmt) (stmt) -static apr_lock_t *process_accept_mutex; -#endif /* NO_SERIALIZED_ACCEPT */ -static apr_lock_t *thread_accept_mutex; - -AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) -{ - switch(query_code){ - case AP_MPMQ_MAX_DAEMON_USED: - *result = ap_max_daemons_limit; - return APR_SUCCESS; - case AP_MPMQ_IS_THREADED: - *result = AP_MPMQ_DYNAMIC; - return APR_SUCCESS; - case AP_MPMQ_IS_FORKED: - *result = AP_MPMQ_STATIC; - return APR_SUCCESS; - case AP_MPMQ_HARD_LIMIT_DAEMONS: - *result = HARD_SERVER_LIMIT; - return APR_SUCCESS; - case AP_MPMQ_HARD_LIMIT_THREADS: - *result = HARD_THREAD_LIMIT; - return APR_SUCCESS; - case AP_MPMQ_MAX_THREADS: - *result = max_threads; - return APR_SUCCESS; - case AP_MPMQ_MIN_SPARE_DAEMONS: - *result = 0; - return APR_SUCCESS; - case AP_MPMQ_MIN_SPARE_THREADS: - *result = min_spare_threads; - return APR_SUCCESS; - case AP_MPMQ_MAX_SPARE_DAEMONS: - *result = 0; - return APR_SUCCESS; - case AP_MPMQ_MAX_SPARE_THREADS: - *result = max_spare_threads; - return APR_SUCCESS; - case AP_MPMQ_MAX_REQUESTS_DAEMON: - *result = max_requests_per_child; - return APR_SUCCESS; - case AP_MPMQ_MAX_DAEMONS: - *result = num_daemons; - return APR_SUCCESS; - } - return APR_ENOTIMPL; -} - -/* a clean exit from a child with proper cleanup */ -static void clean_child_exit(int code) -{ - if (pchild) { - apr_pool_destroy(pchild); - } - exit(code); -} - -/* handle all varieties of core dumping signals */ -static void sig_coredump(int sig) -{ - chdir(ap_coredump_dir); - apr_signal(sig, SIG_DFL); - kill(getpid(), sig); - /* At this point we've got sig blocked, because we're still inside - * the signal handler. When we leave the signal handler it will - * be unblocked, and we'll take the signal... and coredump or whatever - * is appropriate for this particular Unix. In addition the parent - * will see the real signal we received -- whereas if we called - * abort() here, the parent would only see SIGABRT. - */ -} - -static void just_die(int sig) -{ - clean_child_exit(0); -} - -/***************************************************************** - * Connection structures and accounting... - */ - -/* volatile just in case */ -static int volatile shutdown_pending; -static int volatile restart_pending; -static int volatile is_graceful; -/* we don't currently track ap_my_generation, but mod_status - * references it so it must be defined */ -ap_generation_t volatile ap_my_generation=0; - -/* - * ap_start_shutdown() and ap_start_restart(), below, are a first stab at - * functions to initiate shutdown or restart without relying on signals. - * Previously this was initiated in sig_term() and restart() signal handlers, - * but we want to be able to start a shutdown/restart from other sources -- - * e.g. on Win32, from the service manager. Now the service manager can - * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that - * these functions can also be called by the child processes, since global - * variables are no longer used to pass on the required action to the parent. - * - * These should only be called from the parent process itself, since the - * parent process will use the shutdown_pending and restart_pending variables - * to determine whether to shutdown or restart. The child process should - * call signal_parent() directly to tell the parent to die -- this will - * cause neither of those variable to be set, which the parent will - * assume means something serious is wrong (which it will be, for the - * child to force an exit) and so do an exit anyway. - */ - -static void ap_start_shutdown(void) -{ - if (shutdown_pending == 1) { - /* Um, is this _probably_ not an error, if the user has - * tried to do a shutdown twice quickly, so we won't - * worry about reporting it. - */ - return; - } - shutdown_pending = 1; -} - -/* do a graceful restart if graceful == 1 */ -static void ap_start_restart(int graceful) -{ - - if (restart_pending == 1) { - /* Probably not an error - don't bother reporting it */ - return; - } - restart_pending = 1; - is_graceful = graceful; - if (is_graceful) { - apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard); - } -} - -static void sig_term(int sig) -{ - ap_start_shutdown(); -} - -static void restart(int sig) -{ -#ifndef WIN32 - ap_start_restart(sig == AP_SIG_GRACEFUL); -#else - ap_start_restart(1); -#endif -} - -static void set_signals(void) -{ -#ifndef NO_USE_SIGACTION - struct sigaction sa; - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - - if (!one_process) { - sa.sa_handler = sig_coredump; -#if defined(SA_ONESHOT) - sa.sa_flags = SA_ONESHOT; -#elif defined(SA_RESETHAND) - sa.sa_flags = SA_RESETHAND; -#endif - if (sigaction(SIGSEGV, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)"); -#ifdef SIGBUS - if (sigaction(SIGBUS, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)"); -#endif -#ifdef SIGABORT - if (sigaction(SIGABORT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)"); -#endif -#ifdef SIGABRT - if (sigaction(SIGABRT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)"); -#endif -#ifdef SIGILL - if (sigaction(SIGILL, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)"); -#endif - sa.sa_flags = 0; - } - sa.sa_handler = sig_term; - if (sigaction(SIGTERM, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)"); -#ifdef SIGINT - if (sigaction(SIGINT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)"); -#endif -#ifdef SIGXCPU - sa.sa_handler = SIG_DFL; - if (sigaction(SIGXCPU, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)"); -#endif -#ifdef SIGXFSZ - sa.sa_handler = SIG_DFL; - if (sigaction(SIGXFSZ, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)"); -#endif -#ifdef SIGPIPE - sa.sa_handler = SIG_IGN; - if (sigaction(SIGPIPE, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)"); -#endif - - /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy - * processing one */ - sigaddset(&sa.sa_mask, SIGHUP); - sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL); - sa.sa_handler = restart; - if (sigaction(SIGHUP, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)"); - if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")"); -#else - if (!one_process) { - apr_signal(SIGSEGV, sig_coredump); -#ifdef SIGBUS - apr_signal(SIGBUS, sig_coredump); -#endif /* SIGBUS */ -#ifdef SIGABORT - apr_signal(SIGABORT, sig_coredump); -#endif /* SIGABORT */ -#ifdef SIGABRT - apr_signal(SIGABRT, sig_coredump); -#endif /* SIGABRT */ -#ifdef SIGILL - apr_signal(SIGILL, sig_coredump); -#endif /* SIGILL */ -#ifdef SIGXCPU - apr_signal(SIGXCPU, SIG_DFL); -#endif /* SIGXCPU */ -#ifdef SIGXFSZ - apr_signal(SIGXFSZ, SIG_DFL); -#endif /* SIGXFSZ */ - } - - apr_signal(SIGTERM, sig_term); -#ifdef SIGHUP - apr_signal(SIGHUP, restart); -#endif /* SIGHUP */ -#ifdef AP_SIG_GRACEFUL - apr_signal(AP_SIG_GRACEFUL, restart); -#endif /* AP_SIG_GRACEFUL */ -#ifdef SIGPIPE - apr_signal(SIGPIPE, SIG_IGN); -#endif /* SIGPIPE */ - -#endif -} - -/***************************************************************** - * Here follows a long bunch of generic server bookkeeping stuff... - */ - -int ap_graceful_stop_signalled(void) -{ - /* XXX - Does this really work? - Manoj */ - return is_graceful; -} - -/***************************************************************** - * Child process main loop. - */ - -static void process_socket(apr_pool_t *p, apr_socket_t *sock, long conn_id) -{ - conn_rec *current_conn; - int csd; - apr_status_t rv; - int thread_num = conn_id % HARD_THREAD_LIMIT; - - if ((rv = apr_os_sock_get(&csd, sock)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "apr_os_sock_get"); - } - - if (csd >= FD_SETSIZE) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL, - "new file descriptor %d is too large; you probably need " - "to rebuild Apache with a larger FD_SETSIZE " - "(currently %d)", - csd, FD_SETSIZE); - apr_socket_close(sock); - return; - } - - if (thread_socket_table[thread_num] < 0) { - ap_sock_disable_nagle(sock); - } - - current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id); - if (current_conn) { - ap_process_connection(current_conn); - ap_lingering_close(current_conn); - } -} - -static void *worker_thread(apr_thread_t *, void *); - -/* Starts a thread as long as we're below max_threads */ -static int start_thread(void) -{ - apr_thread_t *thread; - int rc; - - apr_lock_acquire(worker_thread_count_mutex); - if (worker_thread_count < max_threads - 1) { - if ((rc = apr_thread_create(&thread, worker_thread_attr, worker_thread, - &worker_thread_free_ids[worker_thread_count], pchild))) { - ap_log_error(APLOG_MARK, APLOG_ALERT, rc, ap_server_conf, - "apr_thread_create: unable to create worker thread"); - /* In case system resources are maxxed out, we don't want - Apache running away with the CPU trying to fork over and - over and over again if we exit. */ - sleep(10); - workers_may_exit = 1; - apr_lock_release(worker_thread_count_mutex); - return 0; - } - else { - worker_thread_count++; - } - } - else { - static int reported = 0; - - if (!reported) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf, - "server reached MaxThreadsPerChild setting, consider raising the" - " MaxThreadsPerChild or NumServers settings"); - reported = 1; - } - apr_lock_release(worker_thread_count_mutex); - return 0; - } - apr_lock_release(worker_thread_count_mutex); - return 1; - -} -/* Sets workers_may_exit if we received a character on the pipe_of_death */ -static void check_pipe_of_death(void) -{ - apr_lock_acquire(pipe_of_death_mutex); - if (!workers_may_exit) { - int ret; - char pipe_read_char; - apr_size_t n = 1; - - ret = apr_recv(listenfds[0], &pipe_read_char, &n); - if (APR_STATUS_IS_EAGAIN(ret)) { - /* It lost the lottery. It must continue to suffer - * through a life of servitude. */ - } - else { - /* It won the lottery (or something else is very - * wrong). Embrace death with open arms. */ - workers_may_exit = 1; - } - } - apr_lock_release(pipe_of_death_mutex); -} - -/* idle_thread_count should be incremented before starting a worker_thread */ - -static void *worker_thread(apr_thread_t *thd, void *arg) -{ - apr_socket_t *csd = NULL; - apr_pool_t *tpool; /* Pool for this thread */ - apr_pool_t *ptrans; /* Pool for per-transaction stuff */ - apr_socket_t *sd = NULL; - volatile int last_pollfd = 0; - volatile int thread_just_started = 1; - int srv; - int curr_pollfd; - int thread_num = *((int *) arg); - long conn_id = child_num * HARD_THREAD_LIMIT + thread_num; - apr_pollfd_t *pollset; - int n; - apr_status_t rv; - - apr_lock_acquire(thread_pool_parent_mutex); - apr_pool_create(&tpool, thread_pool_parent); - apr_lock_release(thread_pool_parent_mutex); - apr_pool_create(&ptrans, tpool); - - (void) ap_update_child_status(child_num, thread_num, SERVER_STARTING, - (request_rec *) NULL); - - apr_poll_setup(&pollset, num_listenfds+1, tpool); - for(n=0 ; n <= num_listenfds ; ++n) { - apr_poll_socket_add(pollset, listenfds[n], APR_POLLIN); - } - - while (!workers_may_exit) { - workers_may_exit |= (max_requests_per_child != 0) && (requests_this_child <= 0); - if (workers_may_exit) break; - if (!thread_just_started) { - apr_lock_acquire(idle_thread_count_mutex); - if (idle_thread_count < max_spare_threads) { - idle_thread_count++; - apr_lock_release(idle_thread_count_mutex); - } - else { - apr_lock_release(idle_thread_count_mutex); - break; - } - } - else { - thread_just_started = 0; - } - - (void) ap_update_child_status(child_num, thread_num, SERVER_READY, - (request_rec *) NULL); - - apr_lock_acquire(thread_accept_mutex); - if (workers_may_exit) { - apr_lock_release(thread_accept_mutex); - break; - } - if ((rv = SAFE_ACCEPT(apr_lock_acquire(process_accept_mutex))) - != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, - "apr_lock_acquire failed. Attempting to shutdown " - "process gracefully."); - workers_may_exit = 1; - } - - while (!workers_may_exit) { - apr_int16_t event; - srv = apr_poll(pollset, &n, -1); - - if (srv != APR_SUCCESS) { - if (APR_STATUS_IS_EINTR(srv)) { - continue; - } - - /* apr_poll() will only return errors in catastrophic - * circumstances. Let's try exiting gracefully, for now. */ - ap_log_error(APLOG_MARK, APLOG_ERR, srv, (const server_rec *) - ap_server_conf, "apr_poll: (listen)"); - workers_may_exit = 1; - } - if (workers_may_exit) break; - - apr_poll_revents_get(&event, listenfds[0], pollset); - if (event & APR_POLLIN) { - /* A process got a signal on the shutdown pipe. Check if we're - * the lucky process to die. */ - check_pipe_of_death(); - continue; - } - - apr_poll_revents_get(&event, listenfds[1], pollset); - if (event & APR_POLLIN || event & APR_POLLOUT) { - /* This request is from another child in our current process. - * We should set a flag here, and then below we will read - * two bytes (the socket number and the NULL byte. - */ - thread_socket_table[thread_num] = -2; - goto got_from_other_child; - } - - if (num_listenfds == 1) { - sd = ap_listeners->sd; - goto got_fd; - } - else { - /* find a listener */ - curr_pollfd = last_pollfd; - do { - curr_pollfd++; - if (curr_pollfd > num_listenfds) { - curr_pollfd = 1; - } - /* XXX: Should we check for POLLERR? */ - apr_poll_revents_get(&event, listenfds[curr_pollfd], pollset); - if (event & APR_POLLIN) { - last_pollfd = curr_pollfd; - sd = listenfds[curr_pollfd]; - goto got_fd; - } - } while (curr_pollfd != last_pollfd); - } - } - got_fd: - if (!workers_may_exit) { - if ((rv = apr_accept(&csd, sd, ptrans)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "apr_accept"); - } - if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex))) - != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, - "apr_lock_release failed. Attempting to shutdown " - "process gracefully."); - workers_may_exit = 1; - } - apr_lock_release(thread_accept_mutex); - apr_lock_acquire(idle_thread_count_mutex); - if (idle_thread_count > min_spare_threads) { - idle_thread_count--; - } - else { - if (!start_thread()) { - idle_thread_count--; - } - } - apr_lock_release(idle_thread_count_mutex); - got_from_other_child: - if (thread_socket_table[thread_num] == -2) { - struct msghdr msg; - struct cmsghdr *cmsg; - char sockname[80]; - struct iovec iov; - int ret, sd, dp; - - iov.iov_base = sockname; - iov.iov_len = 80; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - cmsg = apr_palloc(ptrans, sizeof(*cmsg) + sizeof(sd)); - cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sd); - msg.msg_control = (caddr_t)cmsg; - msg.msg_controllen = cmsg->cmsg_len; - msg.msg_flags = 0; - - ret = recvmsg(child_info_table[child_num].sd, &msg, 0); - - memcpy(&dp, CMSG_DATA(cmsg), sizeof(dp)); - - thread_socket_table[thread_num] = dp; - apr_os_sock_put(&csd, &child_info_table[child_num].sd, ptrans); - } - if (setjmp(jmpbuffer) != 1) { - process_socket(ptrans, csd, conn_id); - } - else { - thread_socket_table[thread_num] = -1; - } - requests_this_child--; - } else { - if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex))) - != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, - "apr_lock_release failed. Attempting to shutdown " - "process gracefully."); - workers_may_exit = 1; - } - apr_lock_release(thread_accept_mutex); - apr_lock_acquire(idle_thread_count_mutex); - idle_thread_count--; - apr_lock_release(idle_thread_count_mutex); - break; - } - apr_pool_clear(ptrans); - } - - apr_lock_acquire(thread_pool_parent_mutex); - ap_update_child_status(child_num, thread_num, SERVER_DEAD, - (request_rec *) NULL); - apr_pool_destroy(tpool); - apr_lock_release(thread_pool_parent_mutex); - apr_lock_acquire(worker_thread_count_mutex); - worker_thread_count--; - worker_thread_free_ids[worker_thread_count] = thread_num; - if (worker_thread_count == 0) { - /* All the threads have exited, now finish the shutdown process - * by signalling the sigwait thread */ - kill(my_pid, SIGTERM); - } - apr_lock_release(worker_thread_count_mutex); - - return NULL; -} - -/* Set group privileges. - * - * Note that we use the username as set in the config files, rather than - * the lookup of to uid --- the same uid may have multiple passwd entries, - * with different sets of groups for each. - */ - -static int set_group_privs(uid_t uid, gid_t gid) -{ - if (!geteuid()) { - const char *name; - - /* Get username if passed as a uid */ - - struct passwd *ent; - - if ((ent = getpwuid(uid)) == NULL) { - ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, - "getpwuid: couldn't determine user name from uid %u, " - "you probably need to modify the User directive", - (unsigned)uid); - return -1; - } - - name = ent->pw_name; - - /* - * Set the GID before initgroups(), since on some platforms - * setgid() is known to zap the group list. - */ - if (setgid(gid) == -1) { - ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, - "setgid: unable to set group id to Group %u", - (unsigned)gid); - return -1; - } - - /* Reset `groups' attributes. */ - - if (initgroups(name, gid) == -1) { - ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, - "initgroups: unable to set groups for User %s " - "and Group %u", name, (unsigned)gid); - return -1; - } - } - return 0; -} - - -static int perchild_setup_child(int childnum) -{ - child_info_t *ug = &child_info_table[childnum]; - - if (ug->uid == -1 && ug->gid == -1) { - return unixd_setup_child(); - } - if (set_group_privs(ug->uid, ug->gid)) { - return -1; - } - /* Only try to switch if we're running as root */ - if (!geteuid() && ( -#ifdef _OSD_POSIX - os_init_job_environment(server_conf, unixd_config.user_name, one_process) != 0 || -#endif - setuid(ug->uid) == -1)) { - ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, - "setuid: unable to change to uid: %ld", - (long) ug->uid); - return -1; - } - return 0; -} - -static int check_signal(int signum) -{ - switch (signum) { - case SIGTERM: - case SIGINT: - just_die(signum); - return 1; - } - return 0; -} - -static void child_main(int child_num_arg) -{ - int i; - ap_listen_rec *lr; - apr_status_t rv; - - my_pid = getpid(); - child_num = child_num_arg; - apr_pool_create(&pchild, pconf); - - /*stuff to do before we switch id's, so we have permissions.*/ - - rv = SAFE_ACCEPT(apr_lock_child_init(&process_accept_mutex, ap_lock_fname, - pchild)); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, - "Couldn't initialize cross-process lock in child"); - clean_child_exit(APEXIT_CHILDFATAL); - } - - if (perchild_setup_child(child_num)) { - clean_child_exit(APEXIT_CHILDFATAL); - } - - ap_run_child_init(pchild, ap_server_conf); - - /*done with init critical section */ - - apr_setup_signal_thread(); - - requests_this_child = max_requests_per_child; - - /* Set up the pollfd array, num_listenfds + 1 for the pipe and 1 for - * the child socket. - */ - listenfds = apr_pcalloc(pchild, sizeof(*listenfds) * (num_listenfds + 2)); -#if APR_FILES_AS_SOCKETS - apr_socket_from_file(&listenfds[0], pipe_of_death_in); -#endif - - /* The child socket */ - apr_os_sock_put(&listenfds[1], &child_info_table[child_num].sd, pchild); - - num_listenfds++; - for (lr = ap_listeners, i = 2; i <= num_listenfds; lr = lr->next, ++i) - listenfds[i]=lr->sd; - - /* Setup worker threads */ - - if (threads_to_start > max_threads) { - threads_to_start = max_threads; - } - idle_thread_count = threads_to_start; - worker_thread_count = 0; - for (i = 0; i < max_threads; i++) { - worker_thread_free_ids[i] = i; - } - apr_pool_create(&thread_pool_parent, pchild); - apr_lock_create(&thread_pool_parent_mutex, APR_MUTEX, APR_INTRAPROCESS, - NULL, pchild); - apr_lock_create(&idle_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS, - NULL, pchild); - apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS, - NULL, pchild); - apr_lock_create(&pipe_of_death_mutex, APR_MUTEX, APR_INTRAPROCESS, - NULL, pchild); - apr_lock_create(&thread_accept_mutex, APR_MUTEX, APR_INTRAPROCESS, - NULL, pchild); - - apr_threadattr_create(&worker_thread_attr, pchild); - apr_threadattr_detach_set(worker_thread_attr, 1); - - /* We are creating worker threads right now */ - for (i=0; i < threads_to_start; i++) { - /* start_thread shouldn't fail here */ - if (!start_thread()) { - break; - } - } - - apr_signal_thread(check_signal); -} - -static int make_child(server_rec *s, int slot) -{ - int pid; - - if (slot + 1 > ap_max_daemons_limit) { - ap_max_daemons_limit = slot + 1; - } - - if (one_process) { - set_signals(); - ap_child_table[slot].pid = getpid(); - ap_child_table[slot].status = SERVER_ALIVE; - child_main(slot); - } - (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL); - - if ((pid = fork()) == -1) { - ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, - "fork: Unable to fork new process"); - /* In case system resources are maxxed out, we don't want - Apache running away with the CPU trying to fork over and - over and over again. */ - sleep(10); - - return -1; - } - - if (!pid) { -#ifdef HAVE_BINDPROCESSOR - /* By default, AIX binds to a single processor. This bit unbinds - * children which will then bind to another CPU. - */ - int status = bindprocessor(BINDPROCESS, (int)getpid(), - PROCESSOR_CLASS_ANY); - if (status != OK) - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, - ap_server_conf, "processor unbind failed %d", status); -#endif - - RAISE_SIGSTOP(MAKE_CHILD); - - /* XXX - For an unthreaded server, a signal handler will be necessary - apr_signal(SIGTERM, just_die); - */ - child_main(slot); - clean_child_exit(0); - } - /* else */ - ap_child_table[slot].pid = pid; - ap_child_table[slot].status = SERVER_ALIVE; - - return 0; -} - -/* start up a bunch of children */ -static int startup_children(int number_to_start) -{ - int i; - - for (i = 0; number_to_start && i < num_daemons; ++i) { - if (ap_child_table[i].pid) { - continue; - } - if (make_child(ap_server_conf, i) < 0) { - break; - } - --number_to_start; - } - return number_to_start; -} - - -/* - * spawn_rate is the number of children that will be spawned on the - * next maintenance cycle if there aren't enough servers. It is - * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by - * without the need to spawn. - */ -static int spawn_rate = 1; -#ifndef MAX_SPAWN_RATE -#define MAX_SPAWN_RATE (32) -#endif -static int hold_off_on_exponential_spawning; - -static void perform_child_maintenance(void) -{ - int i; - int free_length; - int free_slots[MAX_SPAWN_RATE]; - int last_non_dead = -1; - - /* initialize the free_list */ - free_length = 0; - - for (i = 0; i < num_daemons; ++i) { - if (ap_child_table[i].pid == 0) { - if (free_length < spawn_rate) { - free_slots[free_length] = i; - ++free_length; - } - } - else { - last_non_dead = i; - } - - if (i >= ap_max_daemons_limit && free_length >= spawn_rate) { - break; - } - } - ap_max_daemons_limit = last_non_dead + 1; - - if (free_length > 0) { - for (i = 0; i < free_length; ++i) { - make_child(ap_server_conf, free_slots[i]); - } - /* the next time around we want to spawn twice as many if this - * wasn't good enough, but not if we've just done a graceful - */ - if (hold_off_on_exponential_spawning) { - --hold_off_on_exponential_spawning; - } - else if (spawn_rate < MAX_SPAWN_RATE) { - spawn_rate *= 2; - } - } - else { - spawn_rate = 1; - } -} - -static void server_main_loop(int remaining_children_to_start) -{ - int child_slot; - apr_exit_why exitwhy; - int status; - apr_proc_t pid; - int i; - - while (!restart_pending && !shutdown_pending) { - ap_wait_or_timeout(&exitwhy, &status, &pid, pconf); - - if (pid.pid != -1) { - ap_process_child_status(&pid, exitwhy, status); - /* non-fatal death... note that it's gone in the child table and - * clean out the status table. */ - child_slot = -1; - for (i = 0; i < ap_max_daemons_limit; ++i) { - if (ap_child_table[i].pid == pid.pid) { - child_slot = i; - break; - } - } - if (child_slot >= 0) { - ap_child_table[child_slot].pid = 0; - ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL); - - - if (remaining_children_to_start - && child_slot < num_daemons) { - /* we're still doing a 1-for-1 replacement of dead - * children with new children - */ - make_child(ap_server_conf, child_slot); - --remaining_children_to_start; - } -#if APR_HAS_OTHER_CHILD - } - else if (apr_proc_other_child_read(&pid, status) == 0) { - /* handled */ -#endif - } - else if (is_graceful) { - /* Great, we've probably just lost a slot in the - * child table. Somehow we don't know about this - * child. - */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, - ap_server_conf, - "long lost child came home! (pid %ld)", - (long)pid.pid); - } - /* Don't perform idle maintenance when a child dies, - * only do it when there's a timeout. Remember only a - * finite number of children can die, and it's pretty - * pathological for a lot to die suddenly. - */ - continue; - } - else if (remaining_children_to_start) { - /* we hit a 1 second timeout in which none of the previous - * generation of children needed to be reaped... so assume - * they're all done, and pick up the slack if any is left. - */ - remaining_children_to_start = \ - startup_children(remaining_children_to_start); - /* In any event we really shouldn't do the code below because - * few of the servers we just started are in the IDLE state - * yet, so we'd mistakenly create an extra server. - */ - continue; - } - - perform_child_maintenance(); - } -} - -int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) -{ - int remaining_children_to_start; - int i; - apr_status_t rv; - apr_size_t one = 1; - - pconf = _pconf; - ap_server_conf = s; - if ((rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out, pconf)) - != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, - (const server_rec*) ap_server_conf, - "apr_file_pipe_create (pipe_of_death)"); - exit(1); - } - if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, - (const server_rec*) ap_server_conf, - "apr_file_pipe_timeout_set (pipe_of_death)"); - exit(1); - } - ap_server_conf = s; - if ((num_listenfds = ap_setup_listeners(ap_server_conf)) < 1) { - /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s, - "no listening sockets available, shutting down"); - return 1; - } - ap_log_pid(pconf, ap_pid_fname); - - /* Initialize cross-process accept lock */ - ap_lock_fname = apr_psprintf(_pconf, "%s.%u", - ap_server_root_relative(_pconf, ap_lock_fname), - my_pid); - rv = SAFE_ACCEPT(apr_lock_create_np(&process_accept_mutex, APR_MUTEX, - APR_CROSS_PROCESS, ap_accept_lock_mech, - ap_lock_fname, _pconf)); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, - "Couldn't create cross-process lock"); - return 1; - } - - if (!is_graceful) { - ap_run_pre_mpm(pconf, SB_SHARED); - } - /* Initialize the child table */ - if (!is_graceful) { - for (i = 0; i < HARD_SERVER_LIMIT; i++) { - ap_child_table[i].pid = 0; - } - } - - set_signals(); - - /* If we're doing a graceful_restart then we're going to see a lot - * of children exiting immediately when we get into the main loop - * below (because we just sent them AP_SIG_GRACEFUL). This happens - * pretty rapidly... and for each one that exits we'll start a new one - * until we reach at least daemons_min_free. But we may be permitted to - * start more than that, so we'll just keep track of how many we're - * supposed to start up without the 1 second penalty between each fork. - */ - remaining_children_to_start = num_daemons; - if (!is_graceful) { - remaining_children_to_start = \ - startup_children(remaining_children_to_start); - } - else { - /* give the system some time to recover before kicking into - * exponential mode */ - hold_off_on_exponential_spawning = 10; - } - - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf, - "%s configured -- resuming normal operations", - ap_get_server_version()); - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf, - "Server built: %s", ap_get_server_built()); - restart_pending = shutdown_pending = 0; - - server_main_loop(remaining_children_to_start); - - if (shutdown_pending) { - /* Time to gracefully shut down: - * Kill child processes, tell them to call child_exit, etc... - */ - if (unixd_killpg(getpgrp(), SIGTERM) < 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "killpg SIGTERM"); - } - ap_reclaim_child_processes(1); /* Start with SIGTERM */ - - /* cleanup pid file on normal shutdown */ - { - const char *pidfile = NULL; - pidfile = ap_server_root_relative (pconf, ap_pid_fname); - if ( pidfile != NULL && unlink(pidfile) == 0) - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, - ap_server_conf, - "removed PID file %s (pid=%ld)", - pidfile, (long)getpid()); - } - - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, - ap_server_conf, "caught SIGTERM, shutting down"); - - return 1; - } - - /* we've been told to restart */ - apr_signal(SIGHUP, SIG_IGN); - - if (one_process) { - /* not worth thinking about */ - return 1; - } - - if (is_graceful) { - char char_of_death = '!'; - - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf, - AP_SIG_GRACEFUL_STRING " received. Doing graceful restart"); - - /* This is mostly for debugging... so that we know what is still - * gracefully dealing with existing request. - */ - - for (i = 0; i < num_daemons; ++i) { - if (ap_child_table[i].pid) { - ap_child_table[i].status = SERVER_DYING; - } - } - /* give the children the signal to die */ - for (i = 0; i < num_daemons;) { - if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) { - if (APR_STATUS_IS_EINTR(rv)) continue; - ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, - "write pipe_of_death"); - } - i++; - } - } - else { - /* Kill 'em all. Since the child acts the same on the parents SIGTERM - * and a SIGHUP, we may as well use the same signal, because some user - * pthreads are stealing signals from us left and right. - */ - if (unixd_killpg(getpgrp(), SIGTERM) < 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "killpg SIGTERM"); - } - ap_reclaim_child_processes(1); /* Start with SIGTERM */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, - ap_server_conf, "SIGHUP received. Attempting to restart"); - } - return 0; -} - -static void perchild_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) -{ - static int restart_num = 0; - int no_detach, debug; - int i; - - debug = ap_exists_config_define("DEBUG"); - - if (debug) - no_detach = one_process = 1; - else - { - one_process = ap_exists_config_define("ONE_PROCESS"); - no_detach = ap_exists_config_define("NO_DETACH"); - } - - /* sigh, want this only the second time around */ - if (restart_num++ == 1) { - is_graceful = 0; - - if (!one_process && !no_detach) { - apr_proc_detach(); - } - - my_pid = getpid(); - } - - unixd_pre_config(ptemp); - ap_listen_pre_config(); - num_daemons = DEFAULT_NUM_DAEMON; - threads_to_start = DEFAULT_START_THREAD; - min_spare_threads = DEFAULT_MIN_SPARE_THREAD; - max_spare_threads = DEFAULT_MAX_SPARE_THREAD; - max_threads = HARD_THREAD_LIMIT; - ap_pid_fname = DEFAULT_PIDLOG; - ap_scoreboard_fname = DEFAULT_SCOREBOARD; - ap_lock_fname = DEFAULT_LOCKFILE; - max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; - curr_child_num = 0; - - apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); - - for (i = 0; i < HARD_SERVER_LIMIT; i++) { - child_info_table[i].uid = -1; - child_info_table[i].gid = -1; - child_info_table[i].sd = -1; - } - for (i = 0; i < HARD_THREAD_LIMIT; i++) { - thread_socket_table[i] = -1; - } -} - -static int pass_request(request_rec *r) -{ - apr_socket_t *thesock = r->connection->client_socket; - struct msghdr msg; - struct cmsghdr *cmsg; - int sfd; - struct iovec iov; - apr_bucket_brigade *bb = apr_brigade_create(r->pool); - perchild_server_conf *sconf = (perchild_server_conf *) - ap_get_module_config(r->server->module_config, - &mpm_perchild_module); - char *foo; - apr_size_t len; - apr_off_t zero = 0; - - apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool); - len = strlen(foo); - - apr_pool_userdata_set(NULL, "PERCHILD_BUFFER", apr_pool_cleanup_null, - r->connection->pool); - - apr_os_sock_get(&sfd, thesock); - - iov.iov_base = NULL; - iov.iov_len = 0; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd)); - cmsg->cmsg_len = sizeof(*cmsg) + sizeof(int); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - - memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd)); - - msg.msg_control = (caddr_t)cmsg; - msg.msg_controllen = cmsg->cmsg_len; - msg.msg_flags=0; - - if (sendmsg(sconf->sd2, &msg, 0) == -1) { - apr_pool_destroy(r->pool); - return -1; - } - - write(sconf->sd2, foo, len); - - /* ### this "read one line" doesn't seem right... shouldn't we be - ### reading large chunks of data or something? - */ - while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING, - &zero /* read one line */) == APR_SUCCESS) { - apr_bucket *e; - APR_BRIGADE_FOREACH(e, bb) { - const char *str; - - apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ); - write(sconf->sd2, str, len); - } - } - - apr_pool_destroy(r->pool); - return 1; -} - -static char *make_perchild_socket(const char *fullsockname, int sd[2]) -{ - socketpair(PF_UNIX, SOCK_STREAM, 0, sd); - return NULL; -} - - -static void perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) -{ - int i; - server_rec *sr; - perchild_server_conf *sconf; - int def_sd[2]; - - def_sd[0] = -1; - def_sd[1] = -1; - - for (sr = s; sr; sr = sr->next) { - sconf = (perchild_server_conf *)ap_get_module_config(sr->module_config, - &mpm_perchild_module); - - if (sconf->sd == -1) { - sconf->fullsockname = apr_pstrcat(sr->process->pool, - sconf->sockname, ".DEFAULT", NULL); - if (def_sd[0] == -1) { - if (!make_perchild_socket(sconf->fullsockname, def_sd)) { - /* log error */ - } - } - sconf->sd = def_sd[0]; - sconf->sd2 = def_sd[1]; - } - } - - for (i = 0; i < num_daemons; i++) { - if (child_info_table[i].uid == -1) { - child_info_table[i].sd = def_sd[0]; - } - } -} - -static int perchild_post_read(request_rec *r) -{ - ap_filter_t *f = r->connection->input_filters; - int thread_num = r->connection->id % HARD_THREAD_LIMIT; - perchild_server_conf *sconf = (perchild_server_conf *) - ap_get_module_config(r->server->module_config, - &mpm_perchild_module); - - while (f) { - if (!strcasecmp("PERCHILD_BUFFER", f->frec->name)) { - ap_remove_output_filter(f); - break; - } - f = f->next; - } - - if (thread_socket_table[thread_num] != -1) { - apr_socket_t *csd = NULL; - - apr_os_sock_put(&csd, &thread_socket_table[thread_num], - r->connection->pool); - ap_sock_disable_nagle(csd); - r->connection->client_socket = csd; - return OK; - } - else { - if (sconf->sd != child_info_table[child_num].sd) { - if (pass_request(r) == -1) { - ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, - ap_server_conf, "Could not pass request to proper " - "child, request will not be honored."); - } - longjmp(jmpbuffer, 1); - } - return OK; - } - return OK; -} - -static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_off_t *readbytes) -{ - apr_bucket *e; - apr_status_t rv; - char *buffer = NULL; - const char *str; - apr_size_t len; - - if ((rv = ap_get_brigade(f->next, b, mode, readbytes)) != APR_SUCCESS) { - return rv; - } - - apr_pool_userdata_get((void **)&buffer, "PERCHILD_BUFFER", f->c->pool); - - APR_BRIGADE_FOREACH(e, b) { - if (e->length != 0) { - apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ); - - if (buffer == NULL) { - buffer = apr_pstrndup(f->c->pool, str, len); - } - else { - buffer = apr_pstrcat(f->c->pool, buffer, - apr_pstrndup(f->c->pool, str, len), NULL); - } - } - } - apr_pool_userdata_set(buffer, "PERCHILD_BUFFER", apr_pool_cleanup_null, f->c->pool); - - return APR_SUCCESS; -} - -static int perchild_pre_connection(conn_rec *c) -{ - ap_add_input_filter("PERCHILD_BUFFER", NULL, NULL, c); - return OK; -} - -static void perchild_hooks(apr_pool_t *p) -{ - one_process = 0; - - ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_pre_connection(perchild_pre_connection,NULL,NULL, APR_HOOK_MIDDLE); - - /* This must be run absolutely first. If this request isn't for this - * server then we need to forward it to the proper child. No sense - * tying up this server running more post_read request hooks if it is - * just going to be forwarded along. - */ - ap_hook_post_read_request(perchild_post_read, NULL, NULL, APR_HOOK_REALLY_FIRST); - ap_register_input_filter("PERCHILD_BUFFER", perchild_buffer, AP_FTYPE_CONTENT); -} - -static const char *set_num_daemons (cmd_parms *cmd, void *dummy, const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err != NULL) { - return err; - } - - num_daemons = atoi(arg); - if (num_daemons > HARD_SERVER_LIMIT) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "WARNING: NumServers of %d exceeds compile time limit " - "of %d servers,", num_daemons, HARD_SERVER_LIMIT); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - " lowering NumServers to %d. To increase, please " - "see the", HARD_SERVER_LIMIT); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - " HARD_SERVER_LIMIT define in %s.", - AP_MPM_HARD_LIMITS_FILE); - num_daemons = HARD_SERVER_LIMIT; - } - else if (num_daemons < 1) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "WARNING: Require NumServers > 0, setting to 1"); - num_daemons = 1; - } - return NULL; -} - -static const char *set_threads_to_start (cmd_parms *cmd, void *dummy, const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err != NULL) { - return err; - } - - threads_to_start = atoi(arg); - if (threads_to_start > HARD_THREAD_LIMIT) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "WARNING: StartThreads of %d exceeds compile time" - " limit of %d threads,", threads_to_start, - HARD_THREAD_LIMIT); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - " lowering StartThreads to %d. To increase, please" - " see the", HARD_THREAD_LIMIT); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - " HARD_THREAD_LIMIT define in %s.", - AP_MPM_HARD_LIMITS_FILE); - } - else if (threads_to_start < 1) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "WARNING: Require StartThreads > 0, setting to 1"); - threads_to_start = 1; - } - return NULL; -} - -static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err != NULL) { - return err; - } - - min_spare_threads = atoi(arg); - if (min_spare_threads <= 0) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "WARNING: detected MinSpareThreads set to non-positive."); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "Resetting to 1 to avoid almost certain Apache failure."); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "Please read the documentation."); - min_spare_threads = 1; - } - - return NULL; -} - -static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err != NULL) { - return err; - } - - max_spare_threads = atoi(arg); - if (max_spare_threads >= HARD_THREAD_LIMIT) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "WARNING: detected MinSpareThreads set higher than"); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT); - max_spare_threads = HARD_THREAD_LIMIT; - } - return NULL; -} - -static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err != NULL) { - return err; - } - - max_threads = atoi(arg); - if (max_threads > HARD_THREAD_LIMIT) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "WARNING: detected MaxThreadsPerChild set higher than"); - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, - "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT); - max_threads = HARD_THREAD_LIMIT; - } - return NULL; -} - -static const char *set_child_per_uid(cmd_parms *cmd, void *dummy, const char *u, - const char *g, const char *num) -{ - int i; - int max_this_time = atoi(num) + curr_child_num; - for (i = curr_child_num; i < max_this_time; i++, curr_child_num++); { - child_info_t *ug = &child_info_table[i - 1]; - - if (i > num_daemons) { - return "Trying to use more child ID's than NumServers. Increase " - "NumServers in your config file."; - } - - ug->uid = atoi(u); - ug->gid = atoi(g); - } - return NULL; -} - -static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid, - const char *gid) -{ - int i; - int u = atoi(uid); - int g = atoi(gid); - const char *errstr; - int socks[2]; - perchild_server_conf *sconf = (perchild_server_conf *) - ap_get_module_config(cmd->server->module_config, - &mpm_perchild_module); - - sconf->fullsockname = apr_pstrcat(cmd->pool, sconf->sockname, ".", uid, ":", gid, NULL); - - if ((errstr = make_perchild_socket(sconf->fullsockname, socks))) { - return errstr; - } - - sconf->sd = socks[0]; - sconf->sd2 = socks[1]; - - for (i = 0; i < num_daemons; i++) { - if (u == child_info_table[i].uid && g == child_info_table[i].gid) { - child_info_table[i].sd = sconf->sd; - } - } - - return NULL; -} - -static const command_rec perchild_cmds[] = { -UNIX_DAEMON_COMMANDS -LISTEN_COMMANDS -AP_INIT_TAKE1("NumServers", set_num_daemons, NULL, RSRC_CONF, - "Number of children alive at the same time"), -AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF, - "Number of threads each child creates"), -AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF, - "Minimum number of idle threads per child, to handle request spikes"), -AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF, - "Maximum number of idle threads per child"), -AP_INIT_TAKE1("MaxThreadsPerChild", set_max_threads, NULL, RSRC_CONF, - "Maximum number of threads per child"), -AP_INIT_TAKE3("ChildperUserID", set_child_per_uid, NULL, RSRC_CONF, - "Specify a User and Group for a specific child process."), -AP_INIT_TAKE2("AssignUserID", assign_childuid, NULL, RSRC_CONF, - "Tie a virtual host to a specific child process."), -{ NULL } -}; - -static void *perchild_create_config(apr_pool_t *p, server_rec *s) -{ - perchild_server_conf *c = - (perchild_server_conf *) apr_pcalloc(p, sizeof(perchild_server_conf)); - - c->sd = -1; - return c; -} - -module AP_MODULE_DECLARE_DATA mpm_perchild_module = { - MPM20_MODULE_STUFF, - NULL, /* hook to run before apache parses args */ - NULL, /* create per-directory config structure */ - NULL, /* merge per-directory config structures */ - perchild_create_config, /* create per-server config structure */ - NULL, /* merge per-server config structures */ - perchild_cmds, /* command apr_table_t */ - perchild_hooks /* register_hooks */ -}; - diff --git a/server/request.c b/server/request.c index 78ff50ecfc..75c1e6fb06 100644 --- a/server/request.c +++ b/server/request.c @@ -472,10 +472,9 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) return OK; } - /* - * r->path_info tracks the remaining source path. - * r->filename tracks the path as we build it. - * we begin our adventure at the root... + /* Canonicalize the file path without resolving filename case or aliases + * so we can begin by checking the cache for a recent directory walk. + * This call will ensure we have an absolute path in the same pass. */ if ((rv = apr_filepath_merge(&entry_dir, NULL, r->filename, APR_FILEPATH_NOTRELATIVE, r->pool)) @@ -486,16 +485,29 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) r->filename, r->uri); return OK; } - r->filename = entry_dir; - /* - * - * Go down the directory hierarchy. Where we have to check for symlinks, - * do so. Where a .htaccess file has permission to override anything, - * try to find one. + /* XXX Notice that this forces path_info to be canonical. That might + * not be desired by all apps. However, some of those same apps likely + * have significant security holes. */ + r->filename = entry_dir; + cache = prep_walk_cache("ap_directory_walk::cache", r); - + + /* If this is not a dirent subrequest with a preconstructed + * r->finfo value, then we can simply stat the filename to + * save burning mega-cycles with unneeded stats - if this is + * an exact file match. We don't care about failure... we + * will stat by component failing this meager attempt. + * + * It would be nice to distinguish APR_ENOENT from other + * types of failure, such as APR_ENOTDIR. We can do something + * with APR_ENOENT, knowing that the path is good. + */ + if (!r->finfo.filetype || r->finfo.filetype == APR_LNK) { + apr_stat(&r->finfo, r->filename, APR_FINFO_MIN, r->pool); + } + if (r->finfo.filetype == APR_REG) { entry_dir = ap_make_dirstr_parent(r->pool, entry_dir); } @@ -541,6 +553,8 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) allow_options_t opts_remove; overrides_t override; + apr_finfo_t thisinfo; + char *save_path_info; apr_size_t buflen; char *buf; unsigned int seg, startseg; @@ -548,7 +562,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) /* Invariant: from the first time filename_len is set until * it goes out of scope, filename_len==strlen(r->filename) */ - size_t filename_len; + apr_size_t filename_len; /* * We must play our own mimi-merge game here, for the few @@ -562,15 +576,19 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) opts_remove = this_dir->opts_remove; override = this_dir->override; - /* XXX: Remerge path_info, or we are broken. Needs more thought. + /* Save path_info to merge back onto path_info later. If this + * isn't really path_info, what would it be doing here? */ - if (r->path_info) { - r->path_info = ap_make_full_path(r->pool, r->filename, - r->path_info); - } - else { - r->path_info = r->filename; - } + save_path_info = r->path_info; + + /* Now begin to build r->filename from components, set aside the + * segments we have yet to work with in r->path_info (where they + * will stay when the current element resolves to a regular file.) + * + * r->path_info tracks the remaining source path. + * r->filename tracks the path as we build it. + */ + r->path_info = r->filename; rv = apr_filepath_root((const char **)&r->filename, (const char **)&r->path_info, APR_FILEPATH_TRUENAME, r->pool); @@ -580,8 +598,8 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) buf = apr_palloc(r->pool, buflen); memcpy(buf, r->filename, filename_len + 1); r->filename = buf; - r->finfo.valid = APR_FINFO_TYPE; - r->finfo.filetype = APR_DIR; /* It's the root, of course it's a dir */ + thisinfo.valid = APR_FINFO_TYPE; + thisinfo.filetype = APR_DIR; /* It's the root, of course it's a dir */ /* * seg keeps track of which segment we've copied. @@ -590,6 +608,12 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) */ startseg = seg = ap_count_dirs(r->filename); sec_idx = 0; + + /* + * Go down the directory hierarchy. Where we have to check for symlinks, + * do so. Where a .htaccess file has permission to override anything, + * try to find one. + */ do { int res; char *seg_name; @@ -807,30 +831,41 @@ minimerge2: break; } - /* XXX: Optimization required: - * If...we have allowed symlinks, and - * if...we find the segment exists in the directory list - * skip the lstat and dummy up an APR_DIR value for r->finfo - * this means case sensitive platforms go quite quickly. - * Case insensitive platforms might be given the wrong path, - * but if it's not found in the cache, then we know we have - * something to test (the misspelling is never cached.) + /* First optimization; + * If...we knew r->filename was a file, and + * if...we have strict (case-sensitive) filenames, or + * we know the canonical_filename matches to _this_ name, and + * if...we have allowed symlinks + * skip the lstat and dummy up an APR_DIR value for thisinfo. */ + if (r->finfo.filetype +#ifdef CASE_BLIND_FILESYSTEM + && (r->canonical_filename + && (strncmp(r->filename, + r->canonical_filename, filename_len) == 0)) +#endif + && ((opts & (OPT_SYM_OWNER | OPT_SYM_LINKS)) == OPT_SYM_LINKS)) + { + + thisinfo.filetype = APR_DIR; + ++seg; + continue; + } /* We choose apr_lstat here, rather that apr_stat, so that we * capture this path object rather than its target. We will * replace the info with our target's info below. We especially * want the name of this 'link' object, not the name of its - * target, if we are fixing case. + * target, if we are fixing the filename case/resolving aliases. */ - rv = apr_lstat(&r->finfo, r->filename, + rv = apr_lstat(&thisinfo, r->filename, APR_FINFO_MIN | APR_FINFO_NAME, r->pool); if (APR_STATUS_IS_ENOENT(rv)) { /* Nothing? That could be nice. But our directory * walk is done. */ - r->finfo.filetype = APR_NOFILE; + thisinfo.filetype = APR_NOFILE; break; } else if (APR_STATUS_IS_EACCES(rv)) { @@ -839,7 +874,7 @@ minimerge2: return r->status = HTTP_FORBIDDEN; } else if ((rv != APR_SUCCESS && rv != APR_INCOMPLETE) - || !(r->finfo.valid & APR_FINFO_TYPE)) { + || !(thisinfo.valid & APR_FINFO_TYPE)) { /* If we hit ENOTDIR, we must have over-optimized, deny * rather than assume not found. */ @@ -847,29 +882,29 @@ minimerge2: "access to %s failed", r->uri); return r->status = HTTP_FORBIDDEN; } - else if ((res = check_safe_file(r))) { + + if ((res = check_safe_file(r))) { r->status = res; return res; } /* Fix up the path now if we have a name, and they don't agree */ - if ((r->finfo.valid & APR_FINFO_NAME) - && strcmp(seg_name, r->finfo.name)) { + if ((thisinfo.valid & APR_FINFO_NAME) + && strcmp(seg_name, thisinfo.name)) { /* TODO: provide users an option that an internal/external * redirect is required here? We need to walk the URI and * filename in tandem to properly correlate these. */ - strcpy(seg_name, r->finfo.name); + strcpy(seg_name, thisinfo.name); filename_len = strlen(r->filename); } - if (r->finfo.filetype == APR_LNK) { - /* Is this an possibly acceptable symlink? + if (thisinfo.filetype == APR_LNK) { + /* Is this a possibly acceptable symlink? */ - if ((res = resolve_symlink(r->filename, &r->finfo, - opts, r->pool)) - != OK) { + if ((res = resolve_symlink(r->filename, &thisinfo, + opts, r->pool)) != OK) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, "Symbolic link not allowed: %s", r->filename); @@ -878,12 +913,12 @@ minimerge2: /* Ok, we are done with the link's info, test the real target */ - if (r->finfo.filetype == APR_REG) { + if (thisinfo.filetype == APR_REG) { /* That was fun, nothing left for us here */ break; } - else if (r->finfo.filetype != APR_DIR) { + else if (thisinfo.filetype != APR_DIR) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, "symlink doesn't point to a file or directory: %s", r->filename); @@ -892,7 +927,26 @@ minimerge2: } ++seg; - } while (r->finfo.filetype == APR_DIR); + } while (thisinfo.filetype == APR_DIR); + + /* If we have _not_ optimized, this is the time to recover + * the final stat result. + */ + if (!r->finfo.filetype || r->finfo.filetype == APR_LNK) { + r->finfo = thisinfo; + } + + /* Now splice the saved path_info back onto any new path_info + */ + if (save_path_info) { + if (r->path_info && *r->path_info) { + r->path_info = ap_make_full_path(r->pool, r->path_info, + save_path_info); + } + else { + r->path_info = save_path_info; + } + } /* * Now we'll deal with the regexes, note we pick up sec_idx diff --git a/support/dbmmanage b/support/dbmmanage deleted file mode 100644 index ad9a4aca76..0000000000 --- a/support/dbmmanage +++ /dev/null @@ -1,350 +0,0 @@ -#!/usr/bin/perl -# ==================================================================== -# The Apache Software License, Version 1.1 -# -# Copyright (c) 2000-2001 The Apache Software Foundation. All rights -# reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# 3. The end-user documentation included with the redistribution, -# if any, must include the following acknowledgment: -# "This product includes software developed by the -# Apache Software Foundation (http://www.apache.org/)." -# Alternately, this acknowledgment may appear in the software itself, -# if and wherever such third-party acknowledgments normally appear. -# -# 4. The names "Apache" and "Apache Software Foundation" must -# not be used to endorse or promote products derived from this -# software without prior written permission. For written -# permission, please contact apache@apache.org. -# -# 5. Products derived from this software may not be called "Apache", -# nor may "Apache" appear in their name, without prior written -# permission of the Apache Software Foundation. -# -# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR -# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# ==================================================================== -# -# This software consists of voluntary contributions made by many -# individuals on behalf of the Apache Software Foundation. For more -# information on the Apache Software Foundation, please see -# <http://www.apache.org/>. -# - -#for more functionality see the HTTPD::UserAdmin module: -# http://www.perl.com/CPAN/modules/by-module/HTTPD/HTTPD-Tools-x.xx.tar.gz -# -# usage: dbmmanage <DBMfile> <command> <user> <password> <groups> <comment> - -package dbmmanage; -# -ldb -lndbm -lgdbm -lsdbm -BEGIN { @AnyDBM_File::ISA = qw(DB_File NDBM_File GDBM_File SDBM_File) } -use strict; -use Fcntl; -use AnyDBM_File (); - -sub usage { - my $cmds = join "|", sort keys %dbmc::; - die <<SYNTAX; -Usage: dbmmanage [enc] dbname command [username [pw [group[,group] [comment]]]] - - where enc is -d for crypt encryption (default except on Win32, Netware) - -m for MD5 encryption (default on Win32, Netware) - -s for SHA1 encryption - -p for plaintext - - command is one of: $cmds - - pw of . for update command retains the old password - pw of - (or blank) for update command prompts for the password - - groups or comment of . (or blank) for update command retains old values - groups or comment of - for update command clears the existing value - groups or comment of - for add and adduser commands is the empty value -SYNTAX -} - -sub need_sha1_crypt { - if (!eval ('require "Digest/SHA1.pm";')) { - print STDERR <<SHAERR; -dbmmanage SHA1 passwords require the interface or the module Digest::SHA1 -available from CPAN: - - http://www.cpan.org/modules/by-module/Digest/Digest-MD5-2.12.tar.gz - -Please install Digest::SHA1 and try again, or use a different crypt option: - -SHAERR - usage(); - } -} - -sub need_md5_crypt { - if (!eval ('require "Crypt/PasswdMD5.pm";')) { - print STDERR <<MD5ERR; -dbmmanage MD5 passwords require the module Crypt::PasswdMD5 available from CPAN - - http://www.cpan.org/modules/by-module/Crypt/Crypt-PasswdMD5-1.1.tar.gz - -Please install Crypt::PasswdMD5 and try again, or use a different crypt option: - -MD5ERR - usage(); - } -} - -# if your osname is in $newstyle_salt, then use new style salt (starts with '_' and contains -# four bytes of iteration count and four bytes of salt). Otherwise, just use -# the traditional two-byte salt. -# see the man page on your system to decide if you have a newer crypt() lib. -# I believe that 4.4BSD derived systems do (at least BSD/OS 2.0 does). -# The new style crypt() allows up to 20 characters of the password to be -# significant rather than only 8. -# -my $newstyle_salt_platforms = join '|', qw{bsdos}; #others? -my $newstyle_salt = $^O =~ /(?:$newstyle_salt_platforms)/; - -# Some platforms just can't crypt() for Apache -# -my $crypt_not_supported_platforms = join '|', qw{MSWin32 NetWare}; #others? -my $crypt_not_supported = $^O =~ /(?:$crypt_not_supported_platforms)/; - -my $crypt_method = "crypt"; - -if ($crypt_not_supported) { - $crypt_method = "md5"; -} - -# Some platforms won't jump through our favorite hoops -# -my $not_unix_platforms = join '|', qw{MSWin32 NetWare}; #others? -my $not_unix = $^O =~ /(?:$not_unix_platforms)/; - -if ($crypt_not_supported) { - $crypt_method = "md5"; -} - -if (@ARGV[0] eq "-d") { - shift @ARGV; - if ($crypt_not_supported) { - print STDERR - "Warning: Apache/$^O does not support crypt()ed passwords!\n\n"; - } - $crypt_method = "crypt"; -} - -if (@ARGV[0] eq "-m") { - shift @ARGV; - $crypt_method = "md5"; -} - -if (@ARGV[0] eq "-p") { - shift @ARGV; - if (!$crypt_not_supported) { - print STDERR - "Warning: Apache/$^O does not support plaintext passwords!\n\n"; - } - $crypt_method = "plain"; -} - -if (@ARGV[0] eq "-s") { - shift @ARGV; - need_sha1_crypt(); - $crypt_method = "sha1"; -} - -if ($crypt_method eq "md5") { - need_md5_crypt(); -} - -my($file,$command,$key,$crypted_pwd,$groups,$comment) = @ARGV; - -usage() unless $file and $command and defined &{$dbmc::{$command}}; - -# remove extension if any -my $chop = join '|', qw{db.? pag dir}; -$file =~ s/\.($chop)$//; - -my $is_update = $command eq "update"; -my %DB = (); -my @range = (); -my($mode, $flags) = $command =~ - /^(?:view|check)$/ ? (0644, O_RDONLY) : (0644, O_RDWR|O_CREAT); - -tie (%DB, "AnyDBM_File", $file, $flags, $mode) || die "Can't tie $file: $!"; -dbmc->$command(); -untie %DB; - - -my $x; -sub genseed { - my $psf; - if ($not_unix) { - srand (time ^ $$ or time ^ ($$ + ($$ << 15))); - } - else { - for (qw(-xlwwa -le)) { - `ps $_ 2>/dev/null`; - $psf = $_, last unless $?; - } - srand (time ^ $$ ^ unpack("%L*", `ps $psf | gzip -f`)); - } - @range = (qw(. /), '0'..'9','a'..'z','A'..'Z'); - $x = int scalar @range; -} - -sub randchar { - join '', map $range[rand $x], 1..shift||1; -} - -sub saltpw_crypt { - genseed() unless @range; - return $newstyle_salt ? - join '', "_", randchar, "a..", randchar(4) : - randchar(2); -} - -sub cryptpw_crypt { - my ($pw, $salt) = @_; - $salt = saltpw_crypt unless $salt; - crypt $pw, $salt; -} - -sub saltpw_md5 { - genseed() unless @range; - randchar(8); -} - -sub cryptpw_md5 { - my($pw, $salt) = @_; - $salt = saltpw_md5 unless $salt; - Crypt::PasswdMD5::apache_md5_crypt($pw, $salt); -} - -sub cryptpw_sha1 { - my($pw, $salt) = @_; - '{SHA}' . Digest::SHA1::sha1_base64($pw) . "="; -} - -sub cryptpw { - if ($crypt_method eq "md5") { - return cryptpw_md5(@_); - } elsif ($crypt_method eq "sha1") { - return cryptpw_sha1(@_); - } elsif ($crypt_method eq "crypt") { - return cryptpw_crypt(@_); - } - @_[0]; # otherwise return plaintext -} - -sub getpass { - my $prompt = shift || "Enter password:"; - - unless($not_unix) { - open STDIN, "/dev/tty" or warn "couldn't open /dev/tty $!\n"; - system "stty -echo;"; - } - - my($c,$pwd); - print STDERR $prompt; - while (($c = getc(STDIN)) ne '' and $c ne "\n" and $c ne "\r") { - $pwd .= $c; - } - - system "stty echo" unless $not_unix; - print STDERR "\n"; - die "Can't use empty password!\n" unless length $pwd; - return $pwd; -} - -sub dbmc::update { - die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key}; - $crypted_pwd = (split /:/, $DB{$key}, 3)[0] if $crypted_pwd eq '.'; - $groups = (split /:/, $DB{$key}, 3)[1] if !$groups || $groups eq '.'; - $comment = (split /:/, $DB{$key}, 3)[2] if !$comment || $comment eq '.'; - if (!$crypted_pwd || $crypted_pwd eq '-') { - dbmc->adduser; - } - else { - dbmc->add; - } -} - -sub dbmc::add { - die "Can't use empty password!\n" unless $crypted_pwd; - unless($is_update) { - die "Sorry, user `$key' already exists!\n" if $DB{$key}; - } - $groups = '' if $groups eq '-'; - $comment = '' if $comment eq '-'; - $groups .= ":" . $comment if $comment; - $crypted_pwd .= ":" . $groups if $groups; - $DB{$key} = $crypted_pwd; - my $action = $is_update ? "updated" : "added"; - print "User $key $action with password encrypted to $DB{$key} using $crypt_method\n"; -} - -sub dbmc::adduser { - my $value = getpass "New password:"; - die "They don't match, sorry.\n" unless getpass("Re-type new password:") eq $value; - $crypted_pwd = cryptpw $value; - dbmc->add; -} - -sub dbmc::delete { - die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key}; - delete $DB{$key}, print "`$key' deleted\n"; -} - -sub dbmc::view { - print $key ? "$key:$DB{$key}\n" : map { "$_:$DB{$_}\n" if $DB{$_} } keys %DB; -} - -sub dbmc::check { - die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key}; - my $chkpass = (split /:/, $DB{$key}, 3)[0]; - my $testpass = getpass(); - if (substr($chkpass, 0, 6) eq '$apr1$') { - need_md5_crypt; - $crypt_method = "md5"; - } elsif (substr($chkpass, 0, 5) eq '{SHA}') { - need_sha1_crypt; - $crypt_method = "sha1"; - } elsif (length($chkpass) == 13 && $chkpass ne $testpass) { - $crypt_method = "crypt"; - } else { - $crypt_method = "plain"; - } - print $crypt_method . (cryptpw($testpass, $chkpass) eq $chkpass - ? " password ok\n" : " password mismatch\n"); -} - -sub dbmc::import { - while(defined($_ = <STDIN>) and chomp) { - ($key,$crypted_pwd,$groups,$comment) = split /:/, $_, 4; - dbmc->add; - } -} - diff --git a/support/log_server_status b/support/log_server_status deleted file mode 100644 index e32280c912..0000000000 --- a/support/log_server_status +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/perl -# ==================================================================== -# The Apache Software License, Version 1.1 -# -# Copyright (c) 2000-2001 The Apache Software Foundation. All rights -# reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# 3. The end-user documentation included with the redistribution, -# if any, must include the following acknowledgment: -# "This product includes software developed by the -# Apache Software Foundation (http://www.apache.org/)." -# Alternately, this acknowledgment may appear in the software itself, -# if and wherever such third-party acknowledgments normally appear. -# -# 4. The names "Apache" and "Apache Software Foundation" must -# not be used to endorse or promote products derived from this -# software without prior written permission. For written -# permission, please contact apache@apache.org. -# -# 5. Products derived from this software may not be called "Apache", -# nor may "Apache" appear in their name, without prior written -# permission of the Apache Software Foundation. -# -# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR -# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# ==================================================================== -# -# This software consists of voluntary contributions made by many -# individuals on behalf of the Apache Software Foundation. For more -# information on the Apache Software Foundation, please see -# <http://www.apache.org/>. -# -# Log Server Status -# Mark J Cox, UK Web Ltd 1996, mark@ukweb.com -# -# This script is designed to be run at a frequent interval by something -# like cron. It connects to the server and downloads the status -# information. It reformats the information to a single line and logs -# it to a file. Make sure the directory $wherelog is writable by the -# user who runs this script. -# -require 'sys/socket.ph'; - -$wherelog = "/var/log/graph/"; # Logs will be like "/var/log/graph/19960312" -$server = "localhost"; # Name of server, could be "www.foo.com" -$port = "80"; # Port on server -$request = "/status/?auto"; # Request to send - -sub tcp_connect -{ - local($host,$port) =@_; - $sockaddr='S n a4 x8'; - chop($hostname=`hostname`); - $port=(getservbyname($port, 'tcp'))[2] unless $port =~ /^\d+$/; - $me=pack($sockaddr,&AF_INET,0,(gethostbyname($hostname))[4]); - $them=pack($sockaddr,&AF_INET,$port,(gethostbyname($host))[4]); - socket(S,&PF_INET,&SOCK_STREAM,(getprotobyname('tcp'))[2]) || - die "socket: $!"; - bind(S,$me) || return "bind: $!"; - connect(S,$them) || return "connect: $!"; - select(S); - $| = 1; - select(stdout); - return ""; -} - -### Main - -{ - $year=`date +%y`; - chomp($year); - $year += ($year < 70) ? 2000 : 1900; - $date = $year . `date +%m%d:%H%M%S`; - chomp($date); - ($day,$time)=split(/:/,$date); - $res=&tcp_connect($server,$port); - open(OUT,">>$wherelog$day"); - if ($res) { - print OUT "$time:-1:-1:-1:-1:$res\n"; - exit 1; - } - print S "GET $request\n"; - while (<S>) { - $requests=$1 if ( m|^BusyServers:\ (\S+)|); - $idle=$1 if ( m|^IdleServers:\ (\S+)|); - $number=$1 if ( m|sses:\ (\S+)|); - $cpu=$1 if (m|^CPULoad:\ (\S+)|); - } - print OUT "$time:$requests:$idle:$number:$cpu\n"; -} - - diff --git a/support/logresolve.pl b/support/logresolve.pl deleted file mode 100644 index ab5a7322ab..0000000000 --- a/support/logresolve.pl +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/perl -# ==================================================================== -# The Apache Software License, Version 1.1 -# -# Copyright (c) 2000-2001 The Apache Software Foundation. All rights -# reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# 3. The end-user documentation included with the redistribution, -# if any, must include the following acknowledgment: -# "This product includes software developed by the -# Apache Software Foundation (http://www.apache.org/)." -# Alternately, this acknowledgment may appear in the software itself, -# if and wherever such third-party acknowledgments normally appear. -# -# 4. The names "Apache" and "Apache Software Foundation" must -# not be used to endorse or promote products derived from this -# software without prior written permission. For written -# permission, please contact apache@apache.org. -# -# 5. Products derived from this software may not be called "Apache", -# nor may "Apache" appear in their name, without prior written -# permission of the Apache Software Foundation. -# -# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR -# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# ==================================================================== -# -# This software consists of voluntary contributions made by many -# individuals on behalf of the Apache Software Foundation. For more -# information on the Apache Software Foundation, please see -# <http://www.apache.org/>. -# -# logresolve.pl -# -# v 1.2 by robh @ imdb.com -# -# usage: logresolve.pl <infile >outfile -# -# input = Apache/NCSA/.. logfile with IP numbers at start of lines -# output = same logfile with IP addresses resolved to hostnames where -# name lookups succeeded. -# -# this differs from the C based 'logresolve' in that this script -# spawns a number ($CHILDREN) of subprocesses to resolve addresses -# concurrently and sets a short timeout ($TIMEOUT) for each lookup in -# order to keep things moving quickly. -# -# the parent process handles caching of IP->hostnames using a Perl hash -# it also avoids sending the same IP to multiple child processes to be -# resolved multiple times concurrently. -# -# Depending on the settings of $CHILDREN and $TIMEOUT you should see -# significant reductions in the overall time taken to resolve your -# logfiles. With $CHILDREN=40 and $TIMEOUT=5 I've seen 200,000 - 300,000 -# logfile lines processed per hour compared to ~45,000 per hour -# with 'logresolve'. -# -# I haven't yet seen any noticable reduction in the percentage of IPs -# that fail to get resolved. Your mileage will no doubt vary. 5s is long -# enough to wait IMO. -# -# Known to work with FreeBSD 2.2 -# Known to have problems with Solaris -# -# 980417 - use 'sockaddr_un' for bind/connect to make the script work -# with linux. Fix from Luuk de Boer <luuk_de_boer@pi.net> - -require 5.004; - -$|=1; - -use FileHandle; -use Socket; - -use strict; -no strict 'refs'; - -use vars qw($PROTOCOL); -$PROTOCOL = 0; - -my $CHILDREN = 40; -my $TIMEOUT = 5; - -my $filename; -my %hash = (); -my $parent = $$; - -my @children = (); -for (my $child = 1; $child <=$CHILDREN; $child++) { - my $f = fork(); - if (!$f) { - $filename = "./.socket.$parent.$child"; - if (-e $filename) { unlink($filename) || warn "$filename .. $!\n";} - &child($child); - exit(0); - } - push(@children, $f); -} - -&parent; -&cleanup; - -## remove all temporary files before shutting down -sub cleanup { - # die kiddies, die - kill(15, @children); - for (my $child = 1; $child <=$CHILDREN; $child++) { - if (-e "./.socket.$parent.$child") { - unlink("./.socket.$parent.$child") - || warn ".socket.$parent.$child $!"; - } - } -} - -sub parent { - # Trap some possible signals to trigger temp file cleanup - $SIG{'KILL'} = $SIG{'INT'} = $SIG{'PIPE'} = \&cleanup; - - my %CHILDSOCK; - my $filename; - - ## fork child processes. Each child will create a socket connection - ## to this parent and use an unique temp filename to do so. - for (my $child = 1; $child <=$CHILDREN; $child++) { - $CHILDSOCK{$child}= FileHandle->new; - - if (!socket($CHILDSOCK{$child}, AF_UNIX, SOCK_STREAM, $PROTOCOL)) { - warn "parent socket to child failed $!"; - } - $filename = "./.socket.$parent.$child"; - my $response; - do { - $response = connect($CHILDSOCK{$child}, sockaddr_un($filename)); - if ($response != 1) { - sleep(1); - } - } while ($response != 1); - $CHILDSOCK{$child}->autoflush; - } - ## All child processes should now be ready or at worst warming up - - my (@buffer, $child, $ip, $rest, $hostname, $response); - ## read the logfile lines from STDIN - while(<STDIN>) { - @buffer = (); # empty the logfile line buffer array. - $child = 1; # children are numbered 1..N, start with #1 - - # while we have a child to talk to and data to give it.. - do { - push(@buffer, $_); # buffer the line - ($ip, $rest) = split(/ /, $_, 2); # separate IP form rest - - unless ($hash{$ip}) { # resolve if unseen IP - $CHILDSOCK{$child}->print("$ip\n"); # pass IP to next child - $hash{$ip} = $ip; # don't look it up again. - $child++; - } - } while (($child < ($CHILDREN-1)) and ($_ = <STDIN>)); - - ## now poll each child for a response - while (--$child > 0) { - $response = $CHILDSOCK{$child}->getline; - chomp($response); - # child sends us back both the IP and HOSTNAME, no need for us - # to remember what child received any given IP, and no worries - # what order we talk to the children - ($ip, $hostname) = split(/\|/, $response, 2); - $hash{$ip} = $hostname; - } - - # resolve all the logfiles lines held in the log buffer array.. - for (my $line = 0; $line <=$#buffer; $line++) { - # get next buffered line - ($ip, $rest) = split(/ /, $buffer[$line], 2); - # separate IP from rest and replace with cached hostname - printf STDOUT ("%s %s", $hash{$ip}, $rest); - } - } -} - -######################################## - -sub child { - # arg = numeric ID - how the parent refers to me - my $me = shift; - - # add trap for alarm signals. - $SIG{'ALRM'} = sub { die "alarmed"; }; - - # create a socket to communicate with parent - socket(INBOUND, AF_UNIX, SOCK_STREAM, $PROTOCOL) - || die "Error with Socket: !$\n"; - $filename = "./.socket.$parent.$me"; - bind(INBOUND, sockaddr_un($filename)) - || die "Error Binding $filename: $!\n"; - listen(INBOUND, 5) || die "Error Listening: $!\n"; - - my ($ip, $send_back); - my $talk = FileHandle->new; - - # accept a connection from the parent process. We only ever have - # have one connection where we exchange 1 line of info with the - # parent.. 1 line in (IP address), 1 line out (IP + hostname). - accept($talk, INBOUND) || die "Error Accepting: $!\n"; - # disable I/O buffering just in case - $talk->autoflush; - # while the parent keeps sending data, we keep responding.. - while(($ip = $talk->getline)) { - chomp($ip); - # resolve the IP if time permits and send back what we found.. - $send_back = sprintf("%s|%s", $ip, &nslookup($ip)); - $talk->print($send_back."\n"); - } -} - -# perform a time restricted hostname lookup. -sub nslookup { - # get the IP as an arg - my $ip = shift; - my $hostname = undef; - - # do the hostname lookup inside an eval. The eval will use the - # already configured SIGnal handler and drop out of the {} block - # regardless of whether the alarm occured or not. - eval { - alarm($TIMEOUT); - $hostname = gethostbyaddr(gethostbyname($ip), AF_INET); - alarm(0); - }; - if ($@ =~ /alarm/) { - # useful for debugging perhaps.. - # print "alarming, isn't it? ($ip)"; - } - - # return the hostname or the IP address itself if there is no hostname - $hostname ne "" ? $hostname : $ip; -} - - diff --git a/support/phf_abuse_log.cgi b/support/phf_abuse_log.cgi deleted file mode 100644 index 87543ce5f4..0000000000 --- a/support/phf_abuse_log.cgi +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/perl - -# This script is used to detect people trying to abuse the security hole which -# existed in A CGI script direstributed with Apache 1.0.3 and earlier versions. -# You can redirect them to here using the "<Location /cgi-bin/phf*>" suggestion -# in httpd.conf. -# -# The format logged to is -# "[date] remote_addr remote_host [date] referrer user_agent". - -$LOG = "/var/log/phf_log"; - -require "ctime.pl"; -$when = &ctime(time); -$when =~ s/\n//go; -$ENV{HTTP_USER_AGENT} .= " via $ENV{HTTP_VIA}" if($ENV{HTTP_VIA}); - -open(LOG, ">>$LOG") || die "boo hoo, phf_log $!"; -print LOG "[$when] $ENV{REMOTE_ADDR} $ENV{REMOTE_HOST} $ENV{$HTTP_REFERER} $ENV{HTTP_USER_AGENT}\n"; -close(LOG); - -print "Content-type: text/html\r\n\r\n<BLINK>Smile, you're on Candid Camera.</BLINK>\n"; diff --git a/support/split-logfile b/support/split-logfile deleted file mode 100644 index c0f34861aa..0000000000 --- a/support/split-logfile +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/perl -# ==================================================================== -# The Apache Software License, Version 1.1 -# -# Copyright (c) 2000-2001 The Apache Software Foundation. All rights -# reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# 3. The end-user documentation included with the redistribution, -# if any, must include the following acknowledgment: -# "This product includes software developed by the -# Apache Software Foundation (http://www.apache.org/)." -# Alternately, this acknowledgment may appear in the software itself, -# if and wherever such third-party acknowledgments normally appear. -# -# 4. The names "Apache" and "Apache Software Foundation" must -# not be used to endorse or promote products derived from this -# software without prior written permission. For written -# permission, please contact apache@apache.org. -# -# 5. Products derived from this software may not be called "Apache", -# nor may "Apache" appear in their name, without prior written -# permission of the Apache Software Foundation. -# -# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR -# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# ==================================================================== -# -# This software consists of voluntary contributions made by many -# individuals on behalf of the Apache Software Foundation. For more -# information on the Apache Software Foundation, please see -# <http://www.apache.org/>. - -# This script will take a combined Web server access -# log file and break its contents into separate files. -# It assumes that the first field of each line is the -# virtual host identity (put there by "%v"), and that -# the logfiles should be named that+".log" in the current -# directory. -# -# The combined log file is read from stdin. Records read -# will be appended to any existing log files. -# -%is_open = (); - -while ($log_line = <STDIN>) { - # - # Get the first token from the log record; it's the - # identity of the virtual host to which the record - # applies. - # - ($vhost) = split (/\s/, $log_line); - # - # Normalize the virtual host name to all lowercase. - # If it's blank, the request was handled by the default - # server, so supply a default name. This shouldn't - # happen, but caution rocks. - # - $vhost = lc ($vhost) or "access"; - # - # If the log file for this virtual host isn't opened - # yet, do it now. - # - if (! $is_open{$vhost}) { - open $vhost, ">>${vhost}.log" - or die ("Can't open ${vhost}.log"); - $is_open{$vhost} = 1; - } - # - # Strip off the first token (which may be null in the - # case of the default server), and write the edited - # record to the current log file. - # - $log_line =~ s/^\S*\s+//; - printf $vhost "%s", $log_line; -} -exit 0; |