mod_cgid.c revision 8f9e3d3dc602155a189ed2f30ad4707af56a8368
* 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 * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * 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 * ==================================================================== * 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 * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. * http_script: keeps all script-related ramblings together. * Compliant to cgi/1.1 spec * Adapted by rst from original NCSA code by Rob McCool * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for * custom error responses, and DOCUMENT_ROOT because we found it useful. * It also adds SERVER_ADMIN - useful for scripts to know who to mail when /* ### should be tossed in favor of APR */ #
include <
sys/
un.h>
/* for sockaddr_un *//* Read and discard the data in the brigade produced by a CGI script */ /* KLUDGE --- for back-combatibility, we don't have to check Execcgid * in ScriptAliased directories, which means we need to know if this * request came through ScriptAlias or not... so the Alias module /* Configuration stuff */ /* DEFAULT_CGID_LISTENBACKLOG controls the max depth on the unix socket's * pending connection queue. If a bunch of cgi requests arrive at about * in the queue while the cgid process slowly forks off a child to process * each connection on the unix socket. If the queue is too short, the * httpd process will get ECONNREFUSED when trying to connect. /* DEFAULT_CONNECT_ATTEMPTS controls how many times we'll try to connect * to the cgi daemon from the thread/process handling the cgi request. * Generally we want to retry when we get ECONNREFUSED since it is * probably because the listen queue is full. We need to try harder so * the client doesn't see it as a 503 error. * Set this to 0 to continually retry until the connect works or Apache /* If a request includes query info in the URL (stuff after "?"), and * the query info does not contain "=" (indicative of a FORM submission), * then this routine is called to create the argument list to be passed * to the CGI script. When suexec is enabled, the suexec path, user, and * group are the first three arguments to be passed; if not, all three * must be NULL. The query info is split into separate arguments, where * "+" is the separator between keyword arguments. /* count the number of keywords */ /* don't do anything; server is stopping or restarting */ /* it would be better to restart just the cgid child * process but for now we'll gracefully restart the entire * server by sending AP_SIG_GRACEFUL to ourself, the httpd /* we get here when pcgi is cleaned up; pcgi gets cleaned * up when pconf gets cleaned up kill(*
sd,
SIGHUP);
/* send signal to daemon telling it to die */ for (i = 0; i < j; i++) {
/* add 1, so that if i == 0, we still malloc something. */ /* For right now, just make the notes table. At some point we will need * to actually fill this out, but for now we just don't want suexec to for (i =0;
env[i]; i++) {
/* Write the request type (SSI "exec cmd" or cgi). */ "write to cgi daemon process");
/* Write the number of entries in the environment. */ if (
write(
fd, &i,
sizeof(
int)) < 0) {
"write to cgi daemon process");
for (i = 0;
env[i]; i++) {
/* Write the length of the concatenated env string. */ "write to cgi daemon process");
/* Write the concatted env string. */ "write to cgi daemon process");
/* Write module_index id value. */ "write to cgi daemon process");
"Couldn't unlink unix domain socket %s",
/* just a warning; don't bail out */ "Couldn't create unix domain socket");
omask =
umask(00
77);
/* so that only Apache can use socket */ umask(
omask);
/* can't fail, so can't clobber errno */ "Couldn't bind unix domain socket %s",
"Couldn't listen on unix domain socket");
"Couldn't change owner of unix domain socket %s",
const char *
const *
argv;
"Error accepting on cgid socket");
"Error reading request on cgid socket");
/* XXX apr_procattr_child_*_set() is creating an unnecessary * pipe between this process and the child being created... * It is cleaned up with the temporary pool for this request. /* Something bad happened, tell the world. */ "couldn't set child process attributes: %s", r->
filename);
/* We want to close sd2 for the new CGI process too. * If it is left open it'll make ap_pass_brigade() block * waiting for EOF if CGI forked something running long. * close(sd2) here should be okay, as CGI channel * is already dup()ed by apr_procattr_child_{in,out}_set() (
const char *
const *)
env,
/* Bad things happened. Everyone should have cleaned up. */ "couldn't create child process: %d: %s",
rc, r->
filename);
"Couldn't spawn cgid daemon process");
/* XXX should we return a failure here ? */ /* Required by mod_include filter. This is how mod_cgid registers * with mod_include to provide processing of the exec directive. "the name of a log for script debugging info"),
"the maximum length (in bytes) of the script debug log"),
"the maximum size (in bytes) to record of a POST request"),
"the name of the socket to use for communication with " /* XXX Very expensive mainline case! Open, then getfileinfo! */ /* XXX Very expensive mainline case! Open, then getfileinfo! */ /* Soak up script output */ "unable to create socket to cgi daemon");
"connect #%d to cgi daemon failed, sleeping before retry",
"unable to connect to cgi daemon after multiple tries");
break;
/* we got connected! */ /* gotta try again, but make sure the cgid daemon is still around */ "cgid daemon is gone; is Apache terminating?");
/**************************************************************** * Actual cgid handling... /* 99 out of 100 cgid scripts, this is all they support */ "Options ExecCGI is off in this directory");
"attempt to include NPH CGI script");
"script not found or unable to stat");
"attempt to invoke directory as script");
"AcceptPathInfo off disallows user's path");
if (!ap_suexec_enabled) { if (!ap_can_exec(&r->finfo)) return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, "file permissions deny server execution"); /* We are putting the socket discriptor into an apr_file_t so that we can * use a pipe bucket to send the data to the client. * Note that this does not register a cleanup for the socket. We did * that explicitly right after we created the socket. /* Transfer any put/post args, CERN style... * Note that we already ignore SIGPIPE in the core server. /* silly script stopped reading, soak up remaining message */ /* we're done writing, or maybe we didn't write at all; * force EOF on child's stdin so that the cgi detects end (or /* Handle script return... */ /* Soak up all the script output */ /* This redirect needs to be a GET no matter what the original /* We already read the message body (if any), so don't allow * the redirected request to think it has one. We can ignore * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR. /* XX Note that if a script wants to produce its own Redirect * body, it now has to explicitly *say* "Status: 302" /* Passing our socket down the filter chain in a pipe bucket * gives up the responsibility of closing the socket, so * get rid of the cleanup. /* Passing our socket down the filter chain in a pipe bucket * gives up the responsibility of closing the socket, so * get rid of the cleanup. /* get rid of all filters up through protocol... since we * haven't parsed off the headers, there is no way they can return OK;
/* NOT r->status, even if it has changed. */ /*============================================================================ *============================================================================ * This is the beginning of the cgi filter code moved from mod_include. This * is the code required to handle the "exec" SSI directive. *============================================================================ *============================================================================*/ /* No hardwired path info or query allowed */ /* Script gets parameters of the *document*, for back compatibility */ /* Force sub_req to be treated as a CGI request, even if ordinary * typing rules would have called it something else. /* XXX: if most of this stuff is going to get copied anyway, * it'd be more efficient to pstrcat it into a single pool buffer * and a single pool bucket */ sizeof(
"<A HREF=\"") -
1,
/* This is the special environment used for running the "exec cmd=" * variety of SSI directives. /* We are putting the socket discriptor into an apr_file_t so that we can * use a pipe bucket to send the data to the client. * Note that this does not register a cleanup for the socket. We did * that explicitly right after we created the socket. /* Soak up all the script output */ /* This redirect needs to be a GET no matter what the original /* We already read the message body (if any), so don't allow * the redirected request to think it has one. We can ignore * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR. /* XX Note that if a script wants to produce its own Redirect * body, it now has to explicitly *say* "Status: 302" /* Passing our socket down the filter chain in a pipe bucket * gives up the responsibility of closing the socket, so * get rid of the cleanup. "exec used but not allowed in %s", r->
filename);
"execution failure for parameter \"%s\" " /* just in case some stooge changed directories */ "unknown parameter \"%s\" to tag exec in %s",
tag,
file);
/*============================================================================ *============================================================================ * This is the end of the cgi filter code moved from mod_include. *============================================================================ *============================================================================*/ NULL,
/* dir config creater */ NULL,
/* dir merger --- default is to override */