util_script.c revision d936d7dcfc1a35dec2a026d23053f8230301cdff
252N/A/* ==================================================================== 252N/A * Copyright (c) 1995-1999 The Apache Group. All rights reserved. 252N/A * Redistribution and use in source and binary forms, with or without 252N/A * modification, are permitted provided that the following conditions 252N/A * 1. Redistributions of source code must retain the above copyright 252N/A * notice, this list of conditions and the following disclaimer. 252N/A * 2. Redistributions in binary form must reproduce the above copyright 252N/A * notice, this list of conditions and the following disclaimer in 252N/A * the documentation and/or other materials provided with the 252N/A * 3. All advertising materials mentioning features or use of this 252N/A * software must display the following acknowledgment: 252N/A * "This product includes software developed by the Apache Group 252N/A * 4. The names "Apache Server" and "Apache Group" must not be used to 252N/A * endorse or promote products derived from this software without 252N/A * prior written permission. For written permission, please contact 252N/A * 5. Products derived from this software may not be called "Apache" 252N/A * nor may "Apache" appear in their names without prior written 252N/A * permission of the Apache Group. 252N/A * 6. Redistributions of any form whatsoever must retain the following 252N/A * "This product includes software developed by the Apache Group 252N/A * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY 252N/A * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 252N/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 252N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR 252N/A * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 252N/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 252N/A * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 252N/A * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 252N/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 252N/A * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 252N/A * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 252N/A * OF THE POSSIBILITY OF SUCH DAMAGE. 252N/A * ==================================================================== 252N/A * This software consists of voluntary contributions made by many 252N/A * individuals on behalf of the Apache Group and was originally based 252N/A * on public domain software written at the National Center for 252N/A * Supercomputing Applications, University of Illinois, Urbana-Champaign. 252N/A * For more information on the Apache Group and the Apache HTTP server 252N/A * Various utility functions which are common to a whole lot of 252N/A * script-type extensions mechanisms, and might as well be gathered 252N/A * in one place (if only to avoid creating inter-module dependancies 252N/A * where there don't have to be). 252N/A/* If a request includes query info in the URL (stuff after "?"), and 252N/A * the query info does not contain "=" (indicative of a FORM submission), 252N/A * then this routine is called to create the argument list to be passed 252N/A * to the CGI script. When suexec is enabled, the suexec path, user, and 252N/A * 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. * XXXX: note that the WIN32 code uses one of the suexec strings * to pass an interpreter name. Remember this if changing the way they * are handled in create_argv. /* count the number of keywords */ /* use a temporary ap_table_t which we'll overlap onto * r->subprocess_env later /* First, add environment vars from headers... this is as per * CGI specs, though other sorts of scripting interfaces see /* A few headers are special cased --- Authorization to prevent * rogue scripts from capturing passwords; content-type and -length * for no particular reason. * You really don't want to disable this check, since it leaves you * wide open to CGIs stealing passwords and people viewing them * in the environment with "ps -e". But, if you must... /* Apache custom error responses. If we have redirected set two new vars */ /* This "cute" little function comes about because the path info on * filenames and URLs aren't always the same. So we take the two, * and find as much of the two that match as possible. /* Obtain the Request-URI from the original request-line, returning * a new string from the request ap_context_t containing the URI or "". ++
first;
/* skip over the method */ ++
first;
/* and the space(s) */ ++
last;
/* end at next whitespace */ /* Note that the code below special-cases scripts run from includes, * because it "knows" that the sub_request has been hacked to have the * args and path_info of the original request, and not any that may have * come with the script URI in the include command. Ugh. * To get PATH_TRANSLATED, treat PATH_INFO as a URI path. * Need to re-escape it for this, since the entire URI was * un-escaped before we determined where the PATH_INFO began. /* We need to make this a real Windows path name */ /* temporary place to hold headers to merge in later */ /* The HTTP specification says that it is legal to merge duplicate * headers into one. Some browsers that support Cookies don't like * merged headers and prefer that each Set-Cookie header is sent * separately. Lets humour those browsers by not merging. "Premature end of script headers: %s", r->
filename);
/* Delete terminal (CR?)LF */ if (p > 0 && w[p -
1] ==
'\n') {
if (p >
1 && w[p -
2] ==
'\015') {
* If we've finished reading the headers, check to make sure any * HTTP/1.1 conditions are met. If so, we're done; normal processing * will handle the script's output. If not, just return the error. * The appropriate thing to do would be to send the script process a * SIGPIPE to let it know we're ignoring it, close the channel to the * script process, and *then* return the failed-to-meet-condition * error. Otherwise we'd be waiting for the script to finish * blithering before telling the client the output was no good. * However, we don't have the information to do that, so we have to * leave it to an upper layer. /* the cookies have already been copied to the cookie_table */ /* if we see a bogus header don't ignore it. Shout and scream */ /* Chances are that we received an ASCII header text instead of * the expected EBCDIC header lines. Try to auto-detect: for (
cp = w; *
cp !=
'\0'; ++
cp) {
"CGI Interface Error: Script headers apparently ASCII: (CGI = %s)", r->
filename);
/* Soak up all the script output - may save an outright kill */ /* Nuke trailing whitespace */ * If the script returned a specific status, that's what * we'll use - otherwise we assume 200 OK. * If the script gave us a Last-Modified header, we can't just * pass it on blindly because of restrictions on future values. /* XXX: this -1 thing is a gross hack */ else if (
size <
1048576) {
else if (
size <
103809024) {
for (x = 0, n =
2;
args[x]; x++) {
/* Add extra strings to array. */ /* Now insert the extra strings we made room for above. */ for (x = (
1 +
2); x < n; x++) {
/* ZZZ need to look at this in more depth and convert to an AP func so we can get rid of OS specific code. /* the fd on r->server->error_log is closed, but we need somewhere to * put the error messages from the log_* functions. So, we use stderr, * since that is better than allowing errors to go unnoticed. Don't do * this on Win32, though, since we haven't fork()'d. /* TODO: all that RLimit stuff should become part of the spawning API, * and not something in the core_dir_config... define a special rlimit * structure and pass it in here. /* Additions by Alec Kloss, to allow exec'ing of scripts under OS/2 */ char interpreter[
2048];
/* hope it's enough for the interpreter path */ /* Special case to allow use of REXX commands as scripts. */ if (
args_end -
args >
4000) {
/* cmd.exe won't handle lines longer than 4k */ /* +4 = 1 space between progname and args, 2 for double null at end, 2 for possible quote on first arg */ *(++
cmdline_pos) = 0;
/* Add required second terminator */ /* Create environment block from list of envariables */ *
env_block_pos = 0;
/* environment block is terminated by a double null */ /* Adapted from Alec Kloss' work for OS/2 */ "%s is not executable; ensure interpreted scripts have " * Look at the arguments... /* If we are in this leg, there are some other arguments * that we must include in the execution of the CGI. * Because CreateProcess is the way it is, we have to * create a command line like format for the execution * of the CGI. This means we need to create on long * string with the executable and arguments. * The arguments string comes in the request structure, * and each argument is separated by a '+'. We'll replace * these pluses with spaces. * Duplicate the request structure string so we don't change it. * We need to unescape any characters that are * We have the interpreter (if there is one) and we have * the arguments (if there are any). * Build the command string to pass to CreateProcess. * Use CMD.EXE for NT, COMMAND.COM for WIN95 * Make child process use hPipeOutputWrite as standard out, * and make sure it does not show on screen. * Win32's CreateProcess call requires that the environment * be passed in an environment block, a null terminated block of * null terminated strings. /* Hack to get 16-bit CGI's working. It works for all the * standard modules shipped with Apache. pi.dwProcessId is 0 * for 16-bit CGIs and all the Unix specific code that calls * ap_call_exec interprets this as a failure case. And we can't * use -1 either because it is mapped to 0 by the caller. * We must close the handles to the new process and its main thread * to prevent handle and memory leaks. /* TODO: re ap_context_t mplement suexec */ "getpwnam: invalid username %s",
username);
"getpwuid: invalid userid %ld",
"getgrgid: invalid groupid %ld",