You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2010/01/27 11:00:35 UTC
svn commit: r903586 - in /commons/sandbox/runtime/trunk/src/main/native:
Makefile.in configure support/suexec.c support/suexec.h
support/win32/suexec.c
Author: mturk
Date: Wed Jan 27 10:00:34 2010
New Revision: 903586
URL: http://svn.apache.org/viewvc?rev=903586&view=rev
Log:
Add Httpd's suEXEC. Modified from httpd trunk
Added:
commons/sandbox/runtime/trunk/src/main/native/support/suexec.c (with props)
commons/sandbox/runtime/trunk/src/main/native/support/suexec.h (with props)
Modified:
commons/sandbox/runtime/trunk/src/main/native/Makefile.in
commons/sandbox/runtime/trunk/src/main/native/configure
commons/sandbox/runtime/trunk/src/main/native/support/win32/suexec.c
Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.in?rev=903586&r1=903585&r2=903586&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.in Wed Jan 27 10:00:34 2010
@@ -38,13 +38,15 @@
ASFLAGS=@asflags@
RANLIB=@ranlib@
PREFIX=@prefix@
+BINDIR=@bindir@
LIBDIR=@libdir@
TOPDIR=@topdir@
CPP=@cpp@
CXX=@cxx@
CFLAGS=@ccflags@
CSFLAGS=@ccshare@
-EXLFLAGS=@exflags@
+LDRPATH=@ldrpath@
+LDARCH=@lddarch@
CPPFLAGS=@cppopts@
CXXFLAGS=@cxxopts@
LDFLAGS=@ldflags@
@@ -62,6 +64,7 @@
SHAREDLIB=lib$(NAME)$(SO)
SSLMODLIB=lib$(NAME)ssl$(SO)
SQLMODLIB=lib$(NAME)sql$(SO)
+SUEXECBIN=suexec$(EXE)
TESTSUITE=testsuite$(EXE)
SRCDIR=$(TOPDIR)
@@ -383,6 +386,9 @@
$(SRCDIR)/modules/network/ssl/%.$(OBJ) : $(SRCDIR)/modules/network/ssl/%.c
$(CC) $(CFLAGS) $(CSFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $<
+$(SRCDIR)/support/%.$(OBJ) : $(SRCDIR)/support/%.c
+ $(CC) $(CFLAGS) $(CSFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $<
+
$(SRCDIR)/test/%.$(OBJ) : $(SRCDIR)/test/%.c
$(CC) $(CFLAGS) $(CSFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $<
@@ -397,21 +403,24 @@
$(CC) $(SHFLAGS) $(PPORT_OBJS) $(COMMON_OBJS) $(@platform@_OBJS) $(REGEX_OBJS) $(BZIP2_OBJS) $(EXPAT_OBJS) $(ZLIB_OBJS) @testobjs@ $(LDFLAGS) -o $@
$(SSLMODLIB): $(SHAREDLIB) $(OPENSSL_OBJS)
- $(CC) $(EXLFLAGS) $(SHFLAGS) $(OPENSSL_OBJS) $(LDFLAGS) $(SSLFLAGS) -L. -l$(NAME) -o $@
+ $(CC) $(LDARCH) $(LDRPATH) $(SHFLAGS) $(OPENSSL_OBJS) $(LDFLAGS) $(SSLFLAGS) -L. -l$(NAME) -o $@
$(SQLMODLIB): $(SHAREDLIB) $(SQLITE_OBJS) @sqliteobjs@
- $(CC) $(EXLFLAGS) $(SHFLAGS) $(SQLITE_OBJS) @sqliteobjs@ $(LDFLAGS) $(SQLFLAGS) -L. -l$(NAME) -o $@
+ $(CC) $(LDARCH) $(LDRPATH) $(SHFLAGS) $(SQLITE_OBJS) @sqliteobjs@ $(LDFLAGS) $(SQLFLAGS) -L. -l$(NAME) -o $@
+
+$(SUEXECBIN): $(SRCDIR)/support/suexec.$(OBJ)
+ $(CC) $(LDARCH) $(SRCDIR)/support/suexec.$(OBJ) -o $@
$(TESTSUITE): $(STATICLIB) $(SHAREDLIB) @modules@ $(SRCDIR)/test/testsuite.$(OBJ)
- $(CC) $(EXLFLAGS) $(SRCDIR)/test/testsuite.$(OBJ) $(LDFLAGS) -L. -l$(NAME) -o $@
+ $(CC) $(LDARCH) $(LDRPATH) $(SRCDIR)/test/testsuite.$(OBJ) $(LDFLAGS) -L. -l$(NAME) -o $@
test: $(TESTSUITE)
clean:
- for i in $(SRCDIR) $(ARCH_DIRS) ; do rm -f $$i/*.$(OBJ) ; done
+ for i in $(SRCDIR) $(SRCDIR)/support $(ARCH_DIRS) ; do rm -f $$i/*.$(OBJ) ; done
+ for i in $(TESTSUITE) $(SUEXECBIN) ; do rm -f $$i ; done
rm -f *$(SO)
rm -f *$(LIB)
- rm -f $(TESTSUITE)
distclean: clean
rm -f $(TOPDIR)/Makefile
@@ -420,6 +429,7 @@
install: all
@mkdir -p $(DESTDIR)/include
@mkdir -p $(DESTDIR)/$(LIBDIR)
+ @mkdir -p $(DESTDIR)/$(BINDIR)
cp -rf $(INCDIR)/* $(DESTDIR)/include/
cp -f *$(LIB) $(DESTDIR)/lib/
cp -f *$(SO) $(DESTDIR)/lib/
Modified: commons/sandbox/runtime/trunk/src/main/native/configure
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/configure?rev=903586&r1=903585&r2=903586&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/configure (original)
+++ commons/sandbox/runtime/trunk/src/main/native/configure Wed Jan 27 10:00:34 2010
@@ -75,7 +75,8 @@
ldflags="$LDFLAGS"
shflags="$SHFLAGS"
rcflags="$RCFLAGS"
-exflags=""
+ldrpath=""
+lddarch=""
includes="-I$topdir/include -I$topdir/port -I$topdir/srclib"
ssldflags=""
modules=""
@@ -120,12 +121,10 @@
mach=unknown
has_legacy_code=no
-with_suexec_root=/var/www
-with_suexec_log=/var/log/apachecommons/suexec.log
with_suexec_user=www
-with_suexec_uid_min=100
-with_suexec_gid_min=100
-with_suexec_user_dir=public_html
+with_suexec_uidmin=100
+with_suexec_gidmin=100
+with_suexec_userdir=public_html
for o
do
@@ -324,6 +323,34 @@
will be used.
If DIR equals 'embedded' local sqlite sources will
be used
+ --enable-suexec Enable compilation of suEXEC utility
+ [disabled]
+ --enable-suexec-log Enable suEXEC error logging
+ [disabled]
+ --with-suexec-logfile Defines the filename of the suEXEC logfile.
+ [/var/log/suexec.log]
+ --with-suexec-user Defines the user allowed to call suEXEC. It should be
+ the same as the user under which the service usually
+ runs.
+ [www]
+ --with-suexec-userdir Defines the subdirectory under the user's directory
+ that contains all executables for which suEXEC access
+ is allowed.
+ [public_html]
+ --with-suexec-docroot Defines the directory tree under which suEXEC access
+ is allowed for executables.
+ [/var/www]
+ --with-suexec-umask Set umask for processes started by suEXEC.
+ [Platform default]
+ --with-suexec-uidmin Define this as the lowest UID allowed to be a target
+ user for suEXEC
+ [100]
+ --with-suexec-gidmin Define this as the lowest GID allowed to be a target
+ group for suEXEC
+ [100]
+ --with-suexec-safepath Define the value of the environment variable
+ PATH to be set for processes started by suEXEC.
+ [/usr/local/bin:/usr/bin:/bin]
EOH
exit 1
@@ -507,7 +534,7 @@
varadds asflags -c -fPIC -g -D$mcpu
varadds ldflags -lrt -lpthread -ldl
varadds shflags -shared -fPIC -Wl,-soname '-Wl,??@'
- varadds exflags '-Wl,-rpath,??(PREFIX)/??(LIBDIR):????ORIGIN'
+ varadds ldrpath '-Wl,-rpath,??(PREFIX)/??(LIBDIR):????ORIGIN'
as=gcc
test ".$java_pinc" = . && java_pinc=linux
;;
@@ -522,7 +549,7 @@
varadds asflags -c -KPIC -D$mcpu
varadds ldflags -lpthread -ldl
varadds shflags -G -KPIC -dy
- varadds exflags '-R:??(PREFIX)/??(LIBDIR):.'
+ varadds ldrpath '-R:??(PREFIX)/??(LIBDIR):.'
test ".$cxx_set" = .no && cxx=CC
cpp="cc -E"
as=cc
@@ -535,7 +562,7 @@
varadds ccshare -fPIC -g
varadds asflags -c -fPIC -g -D$mcpu
varadds ldflags -lpthread -ldl
- varadds exflags '-Wl,-rpath,??(PREFIX)/??(LIBDIR):.'
+ varadds ldrpath '-Wl,-rpath,??(PREFIX)/??(LIBDIR):.'
if [ ".$has_jni" = .yes ]; then so=".jnilib"; else so=".dynlib"; fi
varadds shflags -dynamiclib -flat_namespace -undefined suppress -fPIC -Wl,-dylib_install_name '-Wl,??@'
as=gcc
@@ -560,7 +587,7 @@
varadds ccshare -KPIC
varadds ldflags -lrt -ldl -lthread -lsendfile -lsocket -lnsl
varadds shflags -G -KPIC -dy
- varadds exflags '-R:??(PREFIX)/??(LIBDIR):.'
+ varadds ldrpath '-R:??(PREFIX)/??(LIBDIR):.'
test ".$cxx_set" = .no && cxx=CC
cpp="cc -E"
as=cc
@@ -609,7 +636,7 @@
varadds ccshare -fPIC -g
varadds ldflags -lrt -lpthreads -lnsl
varadds shflags -shared -fPIC -Wl,-soname '-Wl,??@' -Wl,-brtl
- varadds exflags '-Wl,-rpath,??(PREFIX)/??(LIBDIR):????ORIGIN'
+ varadds ldrpath '-Wl,-rpath,??(PREFIX)/??(LIBDIR):????ORIGIN'
echo "Warning : WORK IN PROGRESS"
;;
* )
@@ -648,11 +675,11 @@
varadds ccflags +DD64
varadds asflags +DD64
varadds shflags +DD64
- varadds exflags +DD64
+ varadds lddarch +DD64
if [ ".$mach" = .parisc64 ]; then
varadds ccflags +DA2.0W
varadds asflags +DA2.0W
- varadds exflags +DA2.0W
+ varadds lddarch +DA2.0W
varadds asflags +DA2.0W
fi
;;
@@ -660,7 +687,7 @@
varadds ccflags +DD32
varadds asflags +DD32
varadds shflags +DD32
- varadds exflags +DD32
+ varadds lddarch +DD32
;;
windows-cl|windows32-cl )
varadds asflags -coff -Cx -Zm -Di386 -DQUIET -D?QUIET
@@ -686,13 +713,13 @@
varadds ccflags -m64
varadds asflags -m64
varadds shflags -m64
- varadds exflags -m64
+ varadds lddarch -m64
;;
*32-* )
varadds ccflags -m32
varadds asflags -m32
varadds shflags -m32
- varadds exflags -m32
+ varadds lddarch -m32
;;
esac
@@ -1146,9 +1173,12 @@
sqliteobjs=""
fi
+have_suexec_log=0
if [ ".$has_suexec" = .yes ]; then
varadds modules '??(SUEXECBIN)'
have_suexec=1
+ test ".$has_suexec_log" = .yes && have_suexec_log=1
+ varadds includes "-I$topdir/support"
else
have_suexec=0
fi
@@ -1200,6 +1230,7 @@
#define HAVE_PORT_H $have_port
#define HAVE_SQLITE3 $have_sqlite3
#define HAVE_SUEXEC $have_suexec
+#define HAVE_SUEXEC_LOG $have_suexec_log
#define HAVE_UNISTD_H `have_include x unistd`
#define HAVE_STRING_H `have_include w string`
@@ -1277,16 +1308,29 @@
if [ ".$has_suexec" = .yes ]; then
cat >> $topdir/include/acr_cc$bits.h << EOF
-#define AC_SUEXEC_ROOT "$with_suexec_root"
+#define AC_SUEXEC_UID_MIN $with_suexec_uidmin
+#define AC_SUEXEC_GID_MIN $with_suexec_gidmin
#define AC_SUEXEC_USER "$with_suexec_user"
-#define AC_SUEXEC_USERDIR "$with_suexec_user_dir"
-#define AC_SUEXEC_LOG_EXEC "$with_suexec_log"
-#define AC_SUEXEC_UID_MIN $with_suexec_uid_min
-#define AC_SUEXEC_GID_MIN $with_suexec_gid_min
+#define AC_SUEXEC_USERDIR "$with_suexec_userdir"
+EOF
+ if [ ".$have_suexec_docroot" = .yes ]; then
+cat >> $topdir/include/acr_cc$bits.h << EOF
+#define AC_SUEXEC_DOCROOT "$with_suexec_docroot"
EOF
- if [ ".$have_suexec_safe_path" = .yes ]; then
+ fi
+ if [ ".$have_suexec_logfile" = .yes ]; then
+cat >> $topdir/include/acr_cc$bits.h << EOF
+#define AC_SUEXEC_LOGFILE "$with_suexec_logfile"
+EOF
+ fi
+ if [ ".$have_suexec_safepath" = .yes ]; then
+cat >> $topdir/include/acr_cc$bits.h << EOF
+#define AC_SUEXEC_SAFE_PATH "$with_suexec_safepath"
+EOF
+ fi
+ if [ ".$have_suexec_umask" = .yes ]; then
cat >> $topdir/include/acr_cc$bits.h << EOF
-#define AC_SUEXEC_SAFE_PATH "$with_suexec_safe_path"
+#define AC_SUEXEC_UMASK $with_suexec_umask
EOF
fi
fi
@@ -1322,7 +1366,8 @@
fi
shflags=`echo $shflags | sed 's/??/\\$/g'`
-exflags=`echo $exflags | sed 's/??/\\$/g'`
+ldrpath=`echo $ldrpath | sed 's/??/\\$/g'`
+lddarch=`echo $lddarch | sed 's/??/\\$/g'`
modules=`echo $modules | sed 's/??/\\$/g'`
includes=`echo $includes | sed 's/??/\\$/g'`
sslflags=`echo $sslflags | sed 's/??/\\$/g'`
@@ -1355,7 +1400,8 @@
-e 's|@asflags@|'"$asflags"'|g' \
-e 's|@ccflags@|'"$ccflags"'|g' \
-e 's|@ccshare@|'"$ccshare"'|g' \
- -e 's|@exflags@|'"$exflags"'|g' \
+ -e 's|@ldrpath@|'"$ldrpath"'|g' \
+ -e 's|@lddarch@|'"$lddarch"'|g' \
-e 's|@cppopts@|'"$cppopts"'|g' \
-e 's|@cxxopts@|'"$cxxopts"'|g' \
-e 's|@ldflags@|'"$ldflags"'|g' \
Added: commons/sandbox/runtime/trunk/src/main/native/support/suexec.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/support/suexec.c?rev=903586&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/support/suexec.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/support/suexec.c Wed Jan 27 10:00:34 2010
@@ -0,0 +1,556 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * suexec.c -- "Wrapper" support program for suEXEC behaviour for Apache
+ *
+ ***********************************************************************
+ *
+ * NOTE! : DO NOT edit this code!!! Unless you know what you are doing,
+ * editing this code might open up your system in unexpected
+ * ways to would-be crackers. Every precaution has been taken
+ * to make this code as safe as possible; alter it at your own
+ * risk.
+ *
+ ***********************************************************************
+ *
+ *
+ */
+
+/*
+ * Apache Common Runtime NOTE:
+ * The code is copy of Httpd suexec with modified #defines so it fits
+ * our configure system. Other then that, there is no functional change
+ * from the Httpd's suexec util.
+ */
+
+#include "acr.h"
+#include "acr_private.h"
+#include "acr_arch.h"
+#include "suexec.h"
+
+#include <pwd.h>
+#include <grp.h>
+
+#define SUEXEC_ENVBUF 256
+
+extern char **environ;
+
+static const char *const safe_env_lst[] =
+{
+ /* variable name starts with */
+ "HTTP_",
+ "SSL_",
+
+ /* variable name is */
+ "AUTH_TYPE=",
+ "CONTENT_LENGTH=",
+ "CONTENT_TYPE=",
+ "DATE_GMT=",
+ "DATE_LOCAL=",
+ "DOCUMENT_NAME=",
+ "DOCUMENT_PATH_INFO=",
+ "DOCUMENT_ROOT=",
+ "DOCUMENT_URI=",
+ "GATEWAY_INTERFACE=",
+ "HTTPS=",
+ "LAST_MODIFIED=",
+ "PATH_INFO=",
+ "PATH_TRANSLATED=",
+ "QUERY_STRING=",
+ "QUERY_STRING_UNESCAPED=",
+ "REMOTE_ADDR=",
+ "REMOTE_HOST=",
+ "REMOTE_IDENT=",
+ "REMOTE_PORT=",
+ "REMOTE_USER=",
+ "REDIRECT_HANDLER=",
+ "REDIRECT_QUERY_STRING=",
+ "REDIRECT_REMOTE_USER=",
+ "REDIRECT_STATUS=",
+ "REDIRECT_URL=",
+ "REQUEST_METHOD=",
+ "REQUEST_URI=",
+ "SCRIPT_FILENAME=",
+ "SCRIPT_NAME=",
+ "SCRIPT_URI=",
+ "SCRIPT_URL=",
+ "SERVER_ADMIN=",
+ "SERVER_NAME=",
+ "SERVER_ADDR=",
+ "SERVER_PORT=",
+ "SERVER_PROTOCOL=",
+ "SERVER_SIGNATURE=",
+ "SERVER_SOFTWARE=",
+ "UNIQUE_ID=",
+ "USER_NAME=",
+ "TZ=",
+ NULL
+};
+
+#if HAVE_SUEXEC_LOG
+static FILE *log = NULL;
+static void err_output(int is_error, const char *fmt, va_list ap)
+{
+ time_t timevar;
+ struct tm *lt;
+
+ if (!log) {
+ if ((log = fopen(AC_SUEXEC_LOGFILE, "a")) == NULL) {
+ fprintf(stderr, "suexec failure: could not open log file\n");
+ perror("fopen");
+ exit(1);
+ }
+ }
+
+ if (is_error) {
+ fprintf(stderr, "suexec policy violation: see suexec log for more "
+ "details\n");
+ }
+
+ time(&timevar);
+ lt = localtime(&timevar);
+
+ fprintf(log, "[%d-%.2d-%.2d %.2d:%.2d:%.2d]: ",
+ lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday,
+ lt->tm_hour, lt->tm_min, lt->tm_sec);
+
+ vfprintf(log, fmt, ap);
+
+ fflush(log);
+ return;
+}
+
+static void log_err(const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ err_output(1, fmt, ap); /* 1 == is_error */
+ va_end(ap);
+ return;
+}
+
+static void log_no_err(const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ err_output(0, fmt, ap); /* 0 == !is_error */
+ va_end(ap);
+ return;
+}
+
+#define LOG_ERR(x) log_err x
+#define LOG_INFO(x) log_no_err x
+
+#else
+
+#define LOG_ERR(x) (void)0
+#define LOG_INFO(x) (void)0
+
+#endif /* HAVE_SUEXEC_LOG */
+
+static void clean_env(void)
+{
+ char pathbuf[512];
+ char **cleanenv;
+ char **ep;
+ int cidx = 0;
+ int idx;
+
+ /* While cleaning the environment, the environment should be clean.
+ * (e.g. malloc() may get the name of a file for writing debugging info.
+ * Bad news if MALLOC_DEBUG_FILE is set to /etc/passwd. Sprintf() may be
+ * susceptible to bad locale settings....)
+ * (from PR 2790)
+ */
+ char **envp = environ;
+ char *empty_ptr = NULL;
+
+ environ = &empty_ptr; /* VERY safe environment */
+
+ if ((cleanenv = (char **) calloc(SUEXEC_ENVBUF, sizeof(char *))) == NULL) {
+ LOG_ERR(("failed to malloc memory for environment\n"));
+ exit(120);
+ }
+
+ sprintf(pathbuf, "PATH=%s", AC_SUEXEC_SAFE_PATH);
+ cleanenv[cidx] = strdup(pathbuf);
+ cidx++;
+
+ for (ep = envp; *ep && cidx < SUEXEC_ENVBUF-1; ep++) {
+ for (idx = 0; safe_env_lst[idx]; idx++) {
+ if (!strncmp(*ep, safe_env_lst[idx],
+ strlen(safe_env_lst[idx]))) {
+ cleanenv[cidx] = *ep;
+ cidx++;
+ break;
+ }
+ }
+ }
+
+ cleanenv[cidx] = NULL;
+
+ environ = cleanenv;
+}
+
+int main(int argc, char *argv[])
+{
+ int userdir = 0; /* ~userdir flag */
+ uid_t uid; /* user information */
+ gid_t gid; /* target group placeholder */
+ char *target_uname; /* target user name */
+ char *target_gname; /* target group name */
+ char *target_homedir; /* target home directory */
+ char *actual_uname; /* actual user name */
+ char *actual_gname; /* actual group name */
+ char *prog; /* name of this program */
+ char *cmd; /* command to be executed */
+ char cwd[PATH_MAX]; /* current working directory */
+ char dwd[PATH_MAX]; /* docroot working directory */
+ struct passwd *pw; /* password entry holder */
+ struct group *gr; /* group entry holder */
+ struct_stat_t dir_info; /* directory info holder */
+ struct_stat_t prg_info; /* program info holder */
+
+ /*
+ * Start with a "clean" environment
+ */
+ clean_env();
+
+ prog = argv[0];
+ /*
+ * Check existence/validity of the UID of the user
+ * running this program. Error out if invalid.
+ */
+ uid = getuid();
+ if ((pw = getpwuid(uid)) == NULL) {
+ LOG_ERR(("crit: invalid uid: (%ld)\n", uid));
+ exit(102);
+ }
+ /*
+ * See if this is a 'how were you compiled' request, and
+ * comply if so.
+ */
+ if ((argc > 1)
+ && (! strcmp(argv[1], "-V"))
+ && ((uid == 0)
+ || (! strcmp(AC_SUEXEC_USER, pw->pw_name)))) {
+#ifdef AC_SUEXEC_DOCROOT
+ fprintf(stderr, " -D SUEXEC_DOCROOT=\"%s\"\n", AC_SUEXEC_DOCROOT);
+#endif
+#ifdef AC_SUEXEC_GID_MIN
+ fprintf(stderr, " -D SUEXEC_GID_MIN=%d\n", AC_SUEXEC_GID_MIN);
+#endif
+#ifdef AC_SUEXEC_USER
+ fprintf(stderr, " -D SUEXEC_USER=\"%s\"\n", AC_SUEXEC_USER);
+#endif
+#if HAVE_SUEXEC_LOG
+#ifdef AC_SUEXEC_LOGFILE
+ fprintf(stderr, " -D SUEXEC_LOGFILE=\"%s\"\n", AC_SUEXEC_LOGFILE);
+#endif
+#endif
+#ifdef AC_SUEXEC_SAFE_PATH
+ fprintf(stderr, " -D SUEXEC_SAFE_PATH=\"%s\"\n", AC_SUEXEC_SAFE_PATH);
+#endif
+#ifdef AP_SUEXEC_UMASK
+ fprintf(stderr, " -D SUEXEC_UMASK=%03o\n", AP_SUEXEC_UMASK);
+#endif
+#ifdef AC_SUEXEC_UID_MIN
+ fprintf(stderr, " -D SUEXEC_UID_MIN=%d\n", AC_SUEXEC_UID_MIN);
+#endif
+#ifdef AC_SUEXEC_USERDIR
+ fprintf(stderr, " -D SUEXEC_USERDIR=\"%s\"\n", AC_SUEXEC_USERDIR);
+#endif
+ exit(0);
+ }
+ /*
+ * If there are a proper number of arguments, set
+ * all of them to variables. Otherwise, error out.
+ */
+ if (argc < 4) {
+ LOG_ERR(("too few arguments\n"));
+ exit(101);
+ }
+ target_uname = argv[1];
+ target_gname = argv[2];
+ cmd = argv[3];
+
+ /*
+ * Check to see if the user running this program
+ * is the user allowed to do so as defined in
+ * suexec.h. If not the allowed user, error out.
+ */
+ if (strcmp(AC_SUEXEC_USER, pw->pw_name)) {
+ LOG_ERR(("user mismatch (%s instead of %s)\n",
+ pw->pw_name, AC_SUEXEC_USER));
+ exit(103);
+ }
+
+ /*
+ * Check for a leading '/' (absolute path) in the command to be executed,
+ * or attempts to back up out of the current directory,
+ * to protect against attacks. If any are
+ * found, error out. Naughty naughty crackers.
+ */
+ if ((cmd[0] == '/') || (!strncmp(cmd, "../", 3))
+ || (strstr(cmd, "/../") != NULL)) {
+ LOG_ERR(("invalid command (%s)\n", cmd));
+ exit(104);
+ }
+
+ /*
+ * Check to see if this is a ~userdir request. If
+ * so, set the flag, and remove the '~' from the
+ * target username.
+ */
+ if (!strncmp("~", target_uname, 1)) {
+ target_uname++;
+ userdir = 1;
+ }
+
+ /*
+ * Error out if the target username is invalid.
+ */
+ if (strspn(target_uname, "1234567890") != strlen(target_uname)) {
+ if ((pw = getpwnam(target_uname)) == NULL) {
+ LOG_ERR(("invalid target user name: (%s)\n", target_uname));
+ exit(105);
+ }
+ }
+ else {
+ if ((pw = getpwuid(atoi(target_uname))) == NULL) {
+ LOG_ERR(("invalid target user id: (%s)\n", target_uname));
+ exit(121);
+ }
+ }
+
+ /*
+ * Error out if the target group name is invalid.
+ */
+ if (strspn(target_gname, "1234567890") != strlen(target_gname)) {
+ if ((gr = getgrnam(target_gname)) == NULL) {
+ LOG_ERR(("invalid target group name: (%s)\n", target_gname));
+ exit(106);
+ }
+ }
+ else {
+ if ((gr = getgrgid(atoi(target_gname))) == NULL) {
+ LOG_ERR(("invalid target group id: (%s)\n", target_gname));
+ exit(106);
+ }
+ }
+ gid = gr->gr_gid;
+ actual_gname = strdup(gr->gr_name);
+
+ /*
+ * Save these for later since initgroups will hose the struct
+ */
+ uid = pw->pw_uid;
+ actual_uname = strdup(pw->pw_name);
+ target_homedir = strdup(pw->pw_dir);
+
+ /*
+ * Log the transaction here to be sure we have an open log
+ * before we setuid().
+ */
+ LOG_INFO(("uid: (%s/%s) gid: (%s/%s) cmd: %s\n",
+ target_uname, actual_uname,
+ target_gname, actual_gname,
+ cmd));
+
+ /*
+ * Error out if attempt is made to execute as root or as
+ * a UID less than AC_SUEXEC_UID_MIN. Tsk tsk.
+ */
+ if ((uid == 0) || (uid < AC_SUEXEC_UID_MIN)) {
+ LOG_ERR(("cannot run as forbidden uid (%d/%s)\n", uid, cmd));
+ exit(107);
+ }
+
+ /*
+ * Error out if attempt is made to execute as root group
+ * or as a GID less than AC_SUEXEC_GID_MIN. Tsk tsk.
+ */
+ if ((gid == 0) || (gid < AC_SUEXEC_GID_MIN)) {
+ LOG_ERR(("cannot run as forbidden gid (%d/%s)\n", gid, cmd));
+ exit(108);
+ }
+
+ /*
+ * Change UID/GID here so that the following tests work over NFS.
+ *
+ * Initialize the group access list for the target user,
+ * and setgid() to the target group. If unsuccessful, error out.
+ */
+ if (((setgid(gid)) != 0) || (initgroups(actual_uname, gid) != 0)) {
+ LOG_ERR(("failed to setgid (%ld: %s)\n", gid, cmd));
+ exit(109);
+ }
+
+ /*
+ * setuid() to the target user. Error out on fail.
+ */
+ if ((setuid(uid)) != 0) {
+ LOG_ERR(("failed to setuid (%ld: %s)\n", uid, cmd));
+ exit(110);
+ }
+
+ /*
+ * Get the current working directory, as well as the proper
+ * document root (dependant upon whether or not it is a
+ * ~userdir request). Error out if we cannot get either one,
+ * or if the current working directory is not in the docroot.
+ * Use chdir()s and getcwd()s to avoid problems with symlinked
+ * directories. Yuck.
+ */
+ if (getcwd(cwd, PATH_MAX) == NULL) {
+ LOG_ERR(("cannot get current working directory\n"));
+ exit(111);
+ }
+
+ if (userdir) {
+ if (((chdir(target_homedir)) != 0) ||
+ ((chdir(AC_SUEXEC_USERDIR)) != 0) ||
+ ((getcwd(dwd, PATH_MAX)) == NULL) ||
+ ((chdir(cwd)) != 0)) {
+ LOG_ERR(("cannot get docroot information (%s)\n", target_homedir));
+ exit(112);
+ }
+ }
+ else {
+ if (((chdir(AC_SUEXEC_DOCROOT)) != 0) ||
+ ((getcwd(dwd, PATH_MAX)) == NULL) ||
+ ((chdir(cwd)) != 0)) {
+ LOG_ERR(("cannot get docroot information (%s)\n", AC_SUEXEC_DOCROOT));
+ exit(113);
+ }
+ }
+
+ if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
+ LOG_ERR(("command not in docroot (%s/%s)\n", cwd, cmd));
+ exit(114);
+ }
+
+ /*
+ * Stat the cwd and verify it is a directory, or error out.
+ */
+ if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) {
+ LOG_ERR(("cannot stat directory: (%s)\n", cwd));
+ exit(115);
+ }
+
+ /*
+ * Error out if cwd is writable by others.
+ */
+ if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
+ LOG_ERR(("directory is writable by others: (%s)\n", cwd));
+ exit(116);
+ }
+
+ /*
+ * Error out if we cannot stat the program.
+ */
+ if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
+ LOG_ERR(("cannot stat program: (%s)\n", cmd));
+ exit(117);
+ }
+
+ /*
+ * Error out if the program is writable by others.
+ */
+ if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
+ LOG_ERR(("file is writable by others: (%s/%s)\n", cwd, cmd));
+ exit(118);
+ }
+
+ /*
+ * Error out if the file is setuid or setgid.
+ */
+ if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) {
+ LOG_ERR(("file is either setuid or setgid: (%s/%s)\n", cwd, cmd));
+ exit(119);
+ }
+
+ /*
+ * Error out if the target name/group is different from
+ * the name/group of the cwd or the program.
+ */
+ if ((uid != dir_info.st_uid) ||
+ (gid != dir_info.st_gid) ||
+ (uid != prg_info.st_uid) ||
+ (gid != prg_info.st_gid)) {
+ LOG_ERR(("target uid/gid (%ld/%ld) mismatch "
+ "with directory (%ld/%ld) or program (%ld/%ld)\n",
+ uid, gid,
+ dir_info.st_uid, dir_info.st_gid,
+ prg_info.st_uid, prg_info.st_gid));
+ exit(120);
+ }
+ /*
+ * Error out if the program is not executable for the user.
+ * Otherwise, she won't find any error in the logs except for
+ * "[error] Premature end of script headers: ..."
+ */
+ if (!(prg_info.st_mode & S_IXUSR)) {
+ LOG_ERR(("file has no execute permission: (%s/%s)\n", cwd, cmd));
+ exit(121);
+ }
+
+#ifdef AC_SUEXEC_UMASK
+ /*
+ * umask() uses inverse logic; bits are CLEAR for allowed access.
+ */
+ if ((~AP_SUEXEC_UMASK) & 0022) {
+ LOG_ERR(("notice: AP_SUEXEC_UMASK of %03o allows "
+ "write permission to group and/or other\n", AC_SUEXEC_UMASK));
+ }
+ umask(AC_SUEXEC_UMASK);
+#endif /* AC_SUEXEC_UMASK */
+
+#if HAVE_SUEXEC_LOG
+ /* Be sure to close the log file so the CGI can't mess with it. */
+ if (log != NULL) {
+ /*
+ * ask fcntl(2) to set the FD_CLOEXEC flag on the log file,
+ * so it'll be automagically closed if the exec() call succeeds.
+ */
+ fflush(log);
+ setbuf(log, NULL);
+ if ((fcntl(fileno(log), F_SETFD, FD_CLOEXEC) == -1)) {
+ LOG_ERR(("error: can't set close-on-exec flag"));
+ exit(122);
+ }
+ }
+#endif
+
+ /*
+ * Execute the command, replacing our image with its own.
+ */
+ execv(cmd, &argv[3]);
+ /*
+ * (I can't help myself...sorry.)
+ *
+ * Uh oh. Still here. Where's the kaboom? There was supposed to be an
+ * EARTH-shattering kaboom!
+ *
+ * Oh well, log the failure and error out.
+ */
+ LOG_ERR(("(%d)%s: exec failed (%s)\n", errno, strerror(errno), cmd));
+ exit(255);
+}
+
Propchange: commons/sandbox/runtime/trunk/src/main/native/support/suexec.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/runtime/trunk/src/main/native/support/suexec.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/support/suexec.h?rev=903586&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/support/suexec.h (added)
+++ commons/sandbox/runtime/trunk/src/main/native/support/suexec.h Wed Jan 27 10:00:34 2010
@@ -0,0 +1,116 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file suexec.h
+ * @brief user-definable variables for the suexec wrapper code.
+ * (See README.configure on how to customize these variables.)
+ */
+
+
+#ifndef _SUEXEC_H
+#define _SUEXEC_H
+
+/*
+ * SUEXEC_USER -- Define as the username under which Apache normally
+ * runs. This is the only user allowed to execute
+ * this program.
+ */
+#ifndef AC_SUEXEC_USER
+#define AC_SUEXEC_USER "www"
+#endif
+
+/*
+ * UID_MIN -- Define this as the lowest UID allowed to be a target user
+ * for suEXEC. For most systems, 500 or 100 is common.
+ */
+#ifndef AC_SUEXEC_UID_MIN
+#define AC_SUEXEC_UID_MIN 100
+#endif
+
+/*
+ * GID_MIN -- Define this as the lowest GID allowed to be a target group
+ * for suEXEC. For most systems, 100 is common.
+ */
+#ifndef AC_SUEXEC_GID_MIN
+#define AC_SUEXEC_GID_MIN 100
+#endif
+
+/*
+ * SUEXEC_USERDIR -- 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.
+ *
+ * If you have VirtualHosts 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. IF THIS IS NOT DEFINED
+ * PROPERLY, ~USERDIR CGI REQUESTS WILL NOT WORK!
+ * See the suEXEC documentation for more detailed
+ * information.
+ */
+#ifndef AC_SUEXEC_USERDIR
+#define AC_SUEXEC_USERDIR "public_html"
+#endif
+
+/*
+ * SUEXEC_LOG -- Define this as a filename if you want all suEXEC
+ * transactions and errors logged for auditing and
+ * debugging purposes.
+ */
+#ifndef AC_SUEXEC_LOGFILE
+#if defined(WIN32)
+#define AC_SUEXEC_LOGFILE "%SystemRoot%\\Logs\\ApacheCommons\\suexec.log"
+#else
+#define AC_SUEXEC_LOGFILE "/var/log/suexec.log"
+#endif
+#endif
+
+/*
+ * SUEXEC_ROOT -- Define as the DocumentRoot set for Apache. This
+ * will be the only hierarchy (aside from UserDirs)
+ * that can be used for suEXEC behavior.
+ */
+#ifndef AC_SUEXEC_DOCROOT
+#if defined(WIN32)
+#define AC_SUEXEC_DOCROOT "%ProgramFiles%\\Apache Software Foundation\\Apache Commons"
+#else
+#define AC_SUEXEC_DOCROOT "/var/www"
+#endif
+#endif
+
+/*
+ * SAFE_PATH -- Define a safe PATH environment to pass to CGI executables.
+ *
+ */
+#ifndef AC_SUEXEC_SAFE_PATH
+#if defined(WIN32)
+#define AC_SUEXEC_SAFE_PATH "%SystemRoot%\\System32;%SystemRoot%"
+#else
+#define AC_SUEXEC_SAFE_PATH "/usr/local/bin:/usr/bin:/bin"
+#endif
+#endif
+
+#endif /* _SUEXEC_H */
+
Propchange: commons/sandbox/runtime/trunk/src/main/native/support/suexec.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/sandbox/runtime/trunk/src/main/native/support/win32/suexec.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/support/win32/suexec.c?rev=903586&r1=903585&r2=903586&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/support/win32/suexec.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/support/win32/suexec.c Wed Jan 27 10:00:34 2010
@@ -34,6 +34,7 @@
#include "acr.h"
#include "acr_private.h"
#include "acr_arch.h"
+#include "suexec.h"
/*
* ---------------------------------------------------------------------