1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-08 15:02:10 +03:00

This patch solves several specific issues:

1.3.x truncated any open/command arguments following the %1 arg.
           so this patch adds the char** arguments to several functions

     1.3.x did not expand environment strings (%userprofile% etc.)
           *) This patch may still not do so, if we are running with a
              subset of the 'normal' environment for security reasons.

     1.3.x did not parse the extension itself (eg. the .pl key itself)
           for the command, failing the 'named' type (eg. perlscript),
           so this patch first tests the 'named' key, then the .ext key

PR:
Obtained from:
Submitted by:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@85623 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
William A. Rowe Jr
2000-06-20 03:48:25 +00:00
parent e7a6e84486
commit fd3e806b92
3 changed files with 129 additions and 52 deletions

View File

@@ -164,7 +164,9 @@ typedef enum { eFileTypeUNKNOWN, eFileTypeBIN, eFileTypeEXE16, eFileTypeEXE32,
eFileTypeSCRIPT } file_type_e; eFileTypeSCRIPT } file_type_e;
typedef enum { INTERPRETER_SOURCE_UNSET, INTERPRETER_SOURCE_REGISTRY, typedef enum { INTERPRETER_SOURCE_UNSET, INTERPRETER_SOURCE_REGISTRY,
INTERPRETER_SOURCE_SHEBANG } interpreter_source_e; INTERPRETER_SOURCE_SHEBANG } interpreter_source_e;
API_EXPORT(file_type_e) ap_get_win32_interpreter(const request_rec *, char **); API_EXPORT(file_type_e) ap_get_win32_interpreter(const request_rec *,
char **interpreter,
char **arguments);
#endif #endif
#ifdef CORE_PRIVATE #ifdef CORE_PRIVATE

View File

@@ -436,15 +436,16 @@ static ap_status_t build_argv_list(char ***argv, request_rec *r, ap_pool_t *p)
return APR_SUCCESS; return APR_SUCCESS;
} }
static ap_status_t build_command_line(char **c, request_rec *r, ap_pool_t *p) static ap_status_t build_command_line(char **cmd, request_rec *r, ap_pool_t *p)
{ {
#ifdef WIN32 #ifdef WIN32
char *quoted_filename = NULL; char *quoted_filename = NULL;
char *interpreter = NULL; char *interpreter = NULL;
char *arguments = NULL;
file_type_e fileType; file_type_e fileType;
*c = NULL; *cmd = NULL;
fileType = ap_get_win32_interpreter(r, &interpreter); fileType = ap_get_win32_interpreter(r, &interpreter, &arguments);
if (fileType == eFileTypeUNKNOWN) { if (fileType == eFileTypeUNKNOWN) {
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
@@ -459,13 +460,20 @@ static ap_status_t build_command_line(char **c, request_rec *r, ap_pool_t *p)
*/ */
quoted_filename = ap_pstrcat(p, "\"", r->filename, "\"", NULL); quoted_filename = ap_pstrcat(p, "\"", r->filename, "\"", NULL);
if (interpreter && *interpreter) { if (interpreter && *interpreter) {
*c = ap_pstrcat(p, interpreter, " ", quoted_filename, " ", NULL); if (arguments && *arguments)
*cmd = ap_pstrcat(p, interpreter, " ", quoted_filename, " ",
arguments, NULL);
else
*cmd = ap_pstrcat(p, interpreter, " ", quoted_filename, " ", NULL);
}
else if (arguments && *arguments) {
*cmd = ap_pstrcat(p, quoted_filename, " ", arguments, NULL);
} }
else { else {
*c = ap_pstrcat(p, quoted_filename, " ", NULL); *cmd = ap_pstrcat(p, quoted_filename, NULL);
} }
#else #else
*c = ap_pstrcat(p, r->filename, NULL); *cmd = ap_pstrcat(p, r->filename, NULL);
#endif #endif
return APR_SUCCESS; return APR_SUCCESS;
} }

View File

@@ -770,16 +770,62 @@ API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r)
} }
#ifdef WIN32 #ifdef WIN32
static char* get_interpreter_from_win32_registry(ap_pool_t *p, const char* ext) static DWORD get_win32_registry_default_value(ap_pool_t *p, HKEY hkey,
char* relativepath, char **value)
{ {
char extension_path[] = "SOFTWARE\\Classes\\";
char executable_path[] = "\\SHELL\\OPEN\\COMMAND";
HKEY hkeyOpen; HKEY hkeyOpen;
DWORD type; DWORD type;
DWORD size = 0;
DWORD result = RegOpenKeyEx(hkey, relativepath, 0,
KEY_QUERY_VALUE, &hkeyOpen);
if (result != ERROR_SUCCESS)
return result;
/* Read to NULL buffer to determine value size */
result = RegQueryValueEx(hkeyOpen, "", 0, &type, NULL, &size);
if (result == ERROR_SUCCESS) {
if ((size < 2) || (type != REG_SZ && type != REG_EXPAND_SZ)) {
result = ERROR_INVALID_PARAMETER;
}
else {
*value = ap_palloc(p, size);
/* Read value based on size query above */
result = RegQueryValueEx(hkeyOpen, "", 0, &type, *value, &size);
}
}
/* TODO: This might look fine, but we need to provide some warning
* somewhere that some environment variables may -not- be translated,
* seeing as we may have chopped the environment table down somewhat.
*/
if ((result == ERROR_SUCCESS) && (type == REG_EXPAND_SZ))
{
char *tmp = *value;
size = ExpandEnvironmentStrings(tmp, *value, 0);
if (size) {
*value = ap_palloc(p, size);
size = ExpandEnvironmentStrings(tmp, *value, size);
}
}
RegCloseKey(hkeyOpen);
return result;
}
static char* get_interpreter_from_win32_registry(ap_pool_t *p, const char* ext,
char** arguments)
{
char execcgi_path[] = "SHELL\\EXECCGI\\COMMAND";
char execopen_path[] = "SHELL\\OPEN\\COMMAND";
char typeName[MAX_PATH];
int cmdOfName = FALSE;
HKEY hkeyName;
HKEY hkeyType;
DWORD type;
int size; int size;
int result; int result;
char *keyName;
char *buffer; char *buffer;
char *s; char *s;
@@ -787,52 +833,50 @@ static char* get_interpreter_from_win32_registry(ap_pool_t *p, const char* ext)
return NULL; return NULL;
/* /*
* Future optimization: * Future optimization:
* When the registry is successfully searched, store the interpreter * When the registry is successfully searched, store the strings for
* string in a ap_table_t to make subsequent look-ups faster * interpreter and arguments in an ext hash to speed up subsequent look-ups
*/ */
/* Open the key associated with the script extension */ /* Open the key associated with the script filetype extension */
keyName = ap_pstrcat(p, extension_path, ext, NULL); result = RegOpenKeyEx(HKEY_CLASSES_ROOT, ext, 0, KEY_QUERY_VALUE,
&hkeyType);
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE,
&hkeyOpen);
if (result != ERROR_SUCCESS) if (result != ERROR_SUCCESS)
return NULL; return NULL;
/* Read to NULL buffer to find value size */ /* Retrieve the name of the script filetype extension */
size = 0; size = sizeof(typeName);
result = RegQueryValueEx(hkeyOpen, "", NULL, &type, NULL, &size); result = RegQueryValueEx(hkeyType, "", NULL, &type, typeName, &size);
if (result == ERROR_SUCCESS && type == REG_SZ && typeName[0]) {
/* Open the key associated with the script filetype extension */
result = RegOpenKeyEx(HKEY_CLASSES_ROOT, typeName, 0,
KEY_QUERY_VALUE, &hkeyName);
if (result == ERROR_SUCCESS) { if (result == ERROR_SUCCESS)
buffer = ap_palloc(p, size); cmdOfName = TRUE;
result = RegQueryValueEx(hkeyOpen, "", NULL, &type, buffer, &size);
} }
RegCloseKey(hkeyOpen); /* Open the key for the script command path by:
*
if (result != ERROR_SUCCESS) * 1) the 'named' filetype key for Open/Command
return NULL; * 2) the extension's type key for Open/Command
*/
/* Open the key associated with the interpreter path */
keyName = ap_pstrcat(p, extension_path, buffer, executable_path, NULL); if (cmdOfName) {
result = get_win32_registry_default_value(p, hkeyName,
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, execopen_path, &buffer);
&hkeyOpen);
if (result != ERROR_SUCCESS)
return NULL;
/* Read to NULL buffer to find value size */
size = 0;
result = RegQueryValueEx(hkeyOpen, "", 0, &type, NULL, &size);
if (result == ERROR_SUCCESS) {
buffer = ap_palloc(p, size);
result = RegQueryValueEx(hkeyOpen, "", 0, &type, buffer, &size);
} }
RegCloseKey(hkeyOpen); if (result != ERROR_SUCCESS) {
result = get_win32_registry_default_value(p, hkeyType,
execopen_path, &buffer);
}
if (cmdOfName)
RegCloseKey(hkeyName);
RegCloseKey(hkeyType);
if (result != ERROR_SUCCESS) if (result != ERROR_SUCCESS)
return NULL; return NULL;
@@ -840,7 +884,7 @@ static char* get_interpreter_from_win32_registry(ap_pool_t *p, const char* ext)
/* /*
* The canonical way shell command entries are entered in the Win32 * The canonical way shell command entries are entered in the Win32
* registry is as follows: * registry is as follows:
* shell [options] "%1" * shell [options] "%1" [args]
* where * where
* shell - full path name to interpreter or shell to run. * shell - full path name to interpreter or shell to run.
* E.g., c:\usr\local\ntreskit\perl\bin\perl.exe * E.g., c:\usr\local\ntreskit\perl\bin\perl.exe
@@ -848,21 +892,34 @@ static char* get_interpreter_from_win32_registry(ap_pool_t *p, const char* ext)
* E.g., \C * E.g., \C
* "%1" - Place holder for file to run the shell against. * "%1" - Place holder for file to run the shell against.
* Typically quoted. * Typically quoted.
* options - additional arguments
* E.g., /silent
* *
* If we find a %1 or a quoted %1, lop it off. * If we find a %1 or a quoted %1, lop it off.
*/ */
if (buffer && *buffer) { if (buffer && *buffer) {
if ((s = strstr(buffer, "\"%1"))) if ((s = strstr(buffer, "\"%1")))
{
*s = '\0'; *s = '\0';
*arguments = s + 4;
}
else if ((s = strstr(buffer, "%1"))) else if ((s = strstr(buffer, "%1")))
{
*s = '\0'; *s = '\0';
*arguments = buffer + 2;
}
else
*arguments = strchr(buffer, '\0');
while (**arguments && isspace(**arguments))
++*arguments;
} }
return buffer; return buffer;
} }
API_EXPORT (file_type_e) ap_get_win32_interpreter(const request_rec *r, API_EXPORT (file_type_e) ap_get_win32_interpreter(const request_rec *r,
char** interpreter ) char** interpreter,
char** arguments)
{ {
HANDLE hFile; HANDLE hFile;
DWORD nBytesRead; DWORD nBytesRead;
@@ -890,8 +947,17 @@ API_EXPORT (file_type_e) ap_get_win32_interpreter(const request_rec *r,
} }
ext = strrchr(exename, '.'); ext = strrchr(exename, '.');
if (ext && (!strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd"))) { if (ext && (!strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd")))
return eFileTypeEXE32; {
char *comspec = getenv("COMSPEC");
if (comspec) {
*interpreter = ap_pstrcat(r->pool, "\"", comspec, "\" /c ", NULL);
return eFileTypeSCRIPT;
}
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r->server,
"Failed to start a '%s' file as a script.\n\t"
"COMSPEC variable is missing from the environment.", ext);
return eFileTypeUNKNOWN;
} }
/* If the file has an extension and it is not .com and not .exe and /* If the file has an extension and it is not .com and not .exe and
@@ -900,7 +966,8 @@ API_EXPORT (file_type_e) ap_get_win32_interpreter(const request_rec *r,
if (ext && strcasecmp(ext,".exe") && strcasecmp(ext,".com") && if (ext && strcasecmp(ext,".exe") && strcasecmp(ext,".com") &&
d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY) { d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY) {
/* Check the registry */ /* Check the registry */
*interpreter = get_interpreter_from_win32_registry(r->pool, ext); *interpreter = get_interpreter_from_win32_registry(r->pool, ext,
arguments);
if (*interpreter) if (*interpreter)
return eFileTypeSCRIPT; return eFileTypeSCRIPT;
else { else {