diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README.fedora | 25 | ||||
-rw-r--r-- | mod_suphp-0.6.1-AddHandler.patch | 13 | ||||
-rw-r--r-- | mod_suphp-0.6.1-DoubleFree.patch | 68 | ||||
-rw-r--r-- | mod_suphp-0.6.1-apr.patch | 97 | ||||
-rw-r--r-- | mod_suphp-0.6.1-chroot.patch | 252 | ||||
-rw-r--r-- | mod_suphp-0.6.1-userdir.patch | 248 | ||||
-rw-r--r-- | mod_suphp-0.6.3-userdir.patch | 217 | ||||
-rw-r--r-- | mod_suphp.conf | 24 | ||||
-rw-r--r-- | mod_suphp.module.conf | 5 | ||||
-rw-r--r-- | mod_suphp.spec | 201 | ||||
-rw-r--r-- | suphp.conf | 49 |
12 files changed, 1203 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1e65467 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +SRCDIR := $(shell pwd) +NAME := $(shell basename $(SRCDIR)) +include ../common/Makefile + diff --git a/README.fedora b/README.fedora new file mode 100644 index 0000000..e193257 --- /dev/null +++ b/README.fedora @@ -0,0 +1,25 @@ +In order to activate mod_suphp support, /etc/httpd/conf.d/mod_suphp.conf +has to be edited. + +The commented line "suPHP_AddHandler ###HANDLER###" has to be uncommented, +for mod_suphp to work. + +After a restart of the httpd, php scripts should be executed with the +rights of the user owning them. + +In case you do need mod_php support for a certain virtual host or directory, +you can selectively disable mod_suphp and fall back to mod_php: + +<Directory "/var/www/html"> + suPHP_Engine off + suPHP_RemoveHandler .php + php_admin_flag engine on + php_admin_flag register_globals on +</Directory> + +This should do the trick nicely. The register_globals flag is purely optional +and should be avoided if possibly. + +Should you require mod_userdir support, in order to enable ~user URLs, you should set +check_vhost_docroot=false in the /etc/suphp.conf file, as currently suphp would fail +with an incorrect vhost. diff --git a/mod_suphp-0.6.1-AddHandler.patch b/mod_suphp-0.6.1-AddHandler.patch new file mode 100644 index 0000000..0e77f2a --- /dev/null +++ b/mod_suphp-0.6.1-AddHandler.patch @@ -0,0 +1,13 @@ +--- suphp-0.6.1/src/apache2/mod_suphp.c.orig 2006-02-06 16:08:30.591794312 +0100 ++++ suphp-0.6.1/src/apache2/mod_suphp.c 2006-02-06 16:08:36.532891128 +0100 +@@ -313,8 +313,8 @@ + AP_INIT_TAKE2("suPHP_UserGroup", suphp_handle_cmd_user_group, NULL, RSRC_CONF | ACCESS_CONF, + "User and group scripts shall be run as"), + #endif +- AP_INIT_ITERATE("suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, ACCESS_CONF, "Tells mod_suphp to handle these MIME-types"), +- AP_INIT_ITERATE("suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, ACCESS_CONF, "Tells mod_suphp not to handle these MIME-types"), ++ AP_INIT_ITERATE("suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, RSRC_CONF | ACCESS_CONF, "Tells mod_suphp to handle these MIME-types"), ++ AP_INIT_ITERATE("suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, RSRC_CONF | ACCESS_CONF, "Tells mod_suphp not to handle these MIME-types"), + {NULL} + }; + diff --git a/mod_suphp-0.6.1-DoubleFree.patch b/mod_suphp-0.6.1-DoubleFree.patch new file mode 100644 index 0000000..fc709b1 --- /dev/null +++ b/mod_suphp-0.6.1-DoubleFree.patch @@ -0,0 +1,68 @@ +diff -urNp suphp-0.6.1.orig/src/API_Linux.cpp suphp-0.6.1/src/API_Linux.cpp +--- suphp-0.6.1.orig/src/API_Linux.cpp 2006-06-19 18:39:17.000000000 +0100 ++++ suphp-0.6.1/src/API_Linux.cpp 2006-06-19 18:37:38.000000000 +0100 +@@ -42,7 +42,7 @@ extern char **environ; + + using namespace suPHP; + +-SmartPtr<API_Linux_Logger> suPHP::API_Linux::logger; ++SmartPtr<API_Linux_Logger>* suPHP::API_Linux::logger; + + bool suPHP::API_Linux::isSymlink(const std::string path) const + throw (SystemException) { +@@ -139,10 +139,10 @@ GroupInfo suPHP::API_Linux::getRealProce + + + Logger& suPHP::API_Linux::getSystemLogger() { +- if (suPHP::API_Linux::logger.get() == NULL) { +- suPHP::API_Linux::logger.reset(new API_Linux_Logger()); ++ if (suPHP::API_Linux::logger->get() == NULL) { ++ suPHP::API_Linux::logger->reset(new API_Linux_Logger()); + } +- return *(suPHP::API_Linux::logger); ++ return **(suPHP::API_Linux::logger); + } + + +diff -urNp suphp-0.6.1.orig/src/API_Linux.hpp suphp-0.6.1/src/API_Linux.hpp +--- suphp-0.6.1.orig/src/API_Linux.hpp 2006-06-19 18:39:17.000000000 +0100 ++++ suphp-0.6.1/src/API_Linux.hpp 2006-06-19 18:43:23.000000000 +0100 +@@ -41,9 +41,10 @@ namespace suPHP { + */ + class API_Linux : public API { + private: +- static SmartPtr<API_Linux_Logger> logger; ++ /* Try and avoid the "static initialization order fiasco" */ ++ static SmartPtr<API_Linux_Logger>* logger; + /** +- * Internal function for checking wheter path ++ * Internal function for checking whether path + * points to a symlink + */ + bool isSymlink(const std::string path) const +@@ -57,6 +58,25 @@ namespace suPHP { + + public: + /** ++ * Constructor ++ */ ++ API_Linux() { ++ logger = NULL; ++ logger = new SmartPtr<API_Linux_Logger>; ++ }; ++ ++ /** ++ * Destructor ++ */ ++ ~API_Linux() { ++ if (logger != NULL) { ++ delete logger; ++ } ++ logger = NULL; ++ }; ++ ++ ++ /** + * Get environment variable + */ + virtual Environment getProcessEnvironment(); diff --git a/mod_suphp-0.6.1-apr.patch b/mod_suphp-0.6.1-apr.patch new file mode 100644 index 0000000..f168c4f --- /dev/null +++ b/mod_suphp-0.6.1-apr.patch @@ -0,0 +1,97 @@ +From peter.wullinger at gmail.com Sat Jan 7 19:29:36 2006 +From: peter.wullinger at gmail.com (Peter Wullinger) +Date: Sat Jan 7 19:29:43 2006 +Subject: [suPHP] Patches for apr 1.0 (apache 2.2.0) +Message-ID: <20060107182936.GA1807@kaliope.csn.tu-chemnitz.de> + + +Good evening, + +APR_BRIGAGE_FOREACH() was deprecated in the apr bucket API, +so suphp breaks, when using apache >= 2.2.0 and the new +apr API. APR_STATUS_IS_SUCCESS() is also gone. + +The following patch remedies this problem by completely +removing all uses of the macros in question alltogether. + +I have tested these with apache 2.2.0 and apr 1.2.2. + +NOTE: + These patches also add the often ACCESS_CONF support + for suPHP_AddHandler and suPHP_RemoveHandler. + Remove these lines from the patch, if you don't want them. + +Cheers, + Peter + +-- +--- src/apache2/mod_suphp.c.orig Sat Jan 7 19:03:59 2006 ++++ src/apache2/mod_suphp.c Sat Jan 7 19:20:32 2006 +@@ -56,7 +56,7 @@ + return -1; + + rv = apr_bucket_read(b, &bucket_data, &bucket_data_len, APR_BLOCK_READ); +- if (!APR_STATUS_IS_SUCCESS(rv) || (bucket_data_len == 0)) ++ if ((rv != APR_SUCCESS) || (bucket_data_len == 0)) + { + return 0; + } +@@ -558,7 +558,9 @@ + return rv; + } + +- APR_BRIGADE_FOREACH(bucket, bb) ++ ++ bucket = APR_BRIGADE_FIRST(bb); ++ while (bucket != APR_BRIGADE_SENTINEL(bb)) + { + const char *data; + apr_size_t len; +@@ -582,6 +584,8 @@ + { + child_stopped_reading = 1; + } ++ ++ bucket = APR_BUCKET_NEXT(bucket); + } + apr_brigade_cleanup(bb); + } +@@ -634,12 +638,15 @@ + + const char *buf; + apr_size_t blen; +- APR_BRIGADE_FOREACH(b, bb) ++ b = APR_BRIGADE_FIRST(bb); ++ while (b != APR_BRIGADE_SENTINEL(bb)) + { + if (APR_BUCKET_IS_EOS(b)) + break; + if (apr_bucket_read(b, &buf, &blen, APR_BLOCK_READ) != APR_SUCCESS) + break; ++ ++ b = APR_BUCKET_NEXT(b); + } + apr_brigade_destroy(bb); + suphp_log_script_err(r, proc->err); +@@ -655,12 +662,14 @@ + /* empty brigade (script output) */ + const char *buf; + apr_size_t blen; +- APR_BRIGADE_FOREACH(b, bb) ++ b = APR_BRIGADE_FIRST(bb); ++ while (b != APR_BRIGADE_SENTINEL(bb)) + { + if (APR_BUCKET_IS_EOS(b)) + break; + if (apr_bucket_read(b, &buf, &blen, APR_BLOCK_READ) != APR_SUCCESS) + break; ++ b = APR_BUCKET_NEXT(b); + } + apr_brigade_destroy(bb); + return HTTP_MOVED_TEMPORARILY; +-- + +-- +Gl?cklich ist nicht, wer anderen so vorkommt, +sondern wer sich selbst daf?r h?lt. + -- Lucius Annaeus Seneca diff --git a/mod_suphp-0.6.1-chroot.patch b/mod_suphp-0.6.1-chroot.patch new file mode 100644 index 0000000..337fb81 --- /dev/null +++ b/mod_suphp-0.6.1-chroot.patch @@ -0,0 +1,252 @@ +Hello list! + +I've written a patch around the chroot() function in +suPHP 0.6.1. First I'll explain our old setup and why +we find this patch useful. + +Since we are improving our webserver security at the +moment, we were looking for a possibility to +chroot() some users. + +Our old setup consists of mod_php and PHP per VirtualHost +configurations like: + php_admin_value open_basedir ... + php_admin_value upload_tmp_dir ... + ... +With disable_functions we disabled functions like exec(), +system(), etc to let the user stay in his open_basedir +(executed programs don't got the open_basedir +restrictions). + +Some users requested the possibility to exec programs like +the ImageMagick tools, needed for Typo3 or other PHP +programs like PHP gallery. I know about the possibility to +configure a safe_mode_exec_dir within the php.ini, but it +is not the best solution. + +The new suPHP version 0.6.1 offers the possibility to +chroot and it works nice. Though there are some problems: +- There is only one configuration file and the chroot-path + is configured within the global config. If you want to + chroot each virtual host into it's own chroot-jail it + isn't possible. +- When chrooted the path of the php script stays like + outsite the chroot environment. + Example: + before suPHP chroot() + SCRIPT_FILENAME = /chroot/YOUR_SITE/var/www/index.php + CURRENT_ROOT = / + CHROOT = /chroot/YOUR_SITE/ + + after suPHP chroot() + SCRIPT_FILENAME = /chroot/YOUR_SITE/var/www/index.php + CURRENT_ROOT = /chroot/YOUR_SITE/ + + PHP will look for a file called + /chroot/YOUR_SITE/var/www/index.php + inside the chroot environment. + Infact the file is + /var/www/index.php + inside the chroot environment. + +What the attached patch does: +- It adds a mod_suphp configuration option called + "suPHP_Options" (the name might not be the best, but + since suPHP_ConfigPath was already in use, I've choosen + this name) +- It "translates" the script path after chroot() so that + PHP will find the right script. + +Here are the steps I used to build a chroot environment for +a virtual host: +- Create a directory structure for the chroot directory: + $ mkdir -p /chroot/YOUR_SITE/\ +{bin,etc,lib,tmp,usr/bin,usr/lib/,var/www} + +- Copy the php binary and depending libraries into the + chroot directory: + $ ldd /usr/bin/php-cgi | sed -e \ +'s,.*=> /\(.*\) (0x.*,\1,' | while read lib; \ +do + LIBDIR="/chroot/YOUR_SITE/`dirname ${lib}`"; \ + test ! -d $LIBDIR && mkdir -p $LIBDIR; \ + cp -v /${lib} /chroot/YOUR_SITE/${lib}; \ +done + +- Copy a php.ini into the chroot directory and change the + doc_root configuration parameter. + $ cat /chroot/YOUR_SITE/etc/php.ini | + sed -e 's,^doc_root.*$,doc_root ="/var/www/",' > \ + /chroot/YOUR_SITE/etc/php.ini + +- Create a apache VirtualHost: + <VirtualHost *> + ServerName YOUR_SITE.EXAMPLE + ServerAdmin [11]YOU at YOUR_SITE.EXAMPLE + + DocumentRoot /chroot/YOUR_SITE/var/www/ + <Directory /chroot/YOUR_SITE/var/www> + suPHP_Engine On + suPHP_Options /chroot/YOUR_SITE-suphp.conf + + # chrooted view + suPHP_ConfigPath /etc/ + </Directory> + </VirtualHost> + +- Create a suPHP configuration file. + Just pick the default file and set + chroot=/chroot/YOUR_SITE/ + +WARNING there are some limitations with this patch: +- First, I'm not the best C, C++ developer and this is my + first apache module work +- The code is mostly quick and dirty hacked, because I + wanted to try if this would work. +- Only the apache2 module was patched. + +I'd appreciate if you review this patch and post your +comments on this. + +Greetings, +Jan + +--- suphp-0.6.1/src/apache2/mod_suphp.c.orig 2006-05-24 04:31:35.000000000 +0200 ++++ suphp-0.6.1/src/apache2/mod_suphp.c 2006-05-24 04:34:58.000000000 +0200 +@@ -114,6 +114,7 @@ + char *target_user; + char *target_group; + #endif ++ char *suphp_options; + apr_table_t *handlers; + } suphp_conf; + +@@ -130,7 +131,9 @@ + cfg->target_user = NULL; + cfg->target_group = NULL; + #endif +- ++ ++ cfg->suphp_options = NULL; ++ + /* Create table with 0 initial elements */ + /* This size may be increased for performance reasons */ + cfg->handlers = apr_table_make(p, 0); +@@ -175,6 +178,13 @@ + else + merged->target_group = NULL; + #endif ++ ++ if (child->suphp_options) ++ merged->suphp_options = apr_pstrdup(p, child->suphp_options); ++ else if (parent->suphp_options) ++ merged->suphp_options = apr_pstrdup(p, parent->suphp_options); ++ else ++ merged->suphp_options = NULL; + + merged->handlers = apr_table_overlay(p, child->handlers, parent->handlers); + +@@ -265,6 +275,17 @@ + return NULL; + } + ++static const char *suphp_handle_cmd_options(cmd_parms *cmd, void *mconfig, ++ const char *arg) ++{ ++ suphp_conf *cfg; ++ cfg = (suphp_conf *) mconfig; ++ ++ cfg->suphp_options = apr_pstrdup(cmd->pool, arg); ++ ++ return NULL; ++} ++ + + #ifdef SUPHP_USE_USERGROUP + static const char *suphp_handle_cmd_user_group(cmd_parms *cmd, void *mconfig, +@@ -315,6 +336,7 @@ + #endif + AP_INIT_ITERATE("suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, RSRC_CONF | ACCESS_CONF, "Tells mod_suphp to handle these MIME-types"), + AP_INIT_ITERATE("suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, RSRC_CONF | ACCESS_CONF, "Tells mod_suphp not to handle these MIME-types"), ++ AP_INIT_TAKE1("suPHP_Options", suphp_handle_cmd_options, NULL, OR_OPTIONS, "The configuration file suPHP should use for this virtual host"), + {NULL} + }; + +@@ -436,6 +458,11 @@ + { + apr_table_setn(r->subprocess_env, "SUPHP_PHP_CONFIG", apr_pstrdup(p, dconf->php_config)); + } ++ ++ if (dconf->suphp_options) ++ { ++ apr_table_setn(r->subprocess_env, "SUPHP_OPTIONS", apr_pstrdup(p, dconf->suphp_options)); ++ } + + apr_table_setn(r->subprocess_env, "SUPHP_HANDLER", r->handler); + +--- suphp-0.6.1/src/Application.cpp.orig 2006-05-24 04:31:35.000000000 +0200 ++++ suphp-0.6.1/src/Application.cpp 2006-05-24 04:34:13.000000000 +0200 +@@ -50,16 +50,23 @@ + API& api = API_Helper::getSystemAPI(); + Logger& logger = api.getSystemLogger(); + +-#ifdef OPT_CONFIGFILE +- File cfgFile = File(OPT_CONFIGFILE); +-#else +- File cfgFile = File("/etc/suphp.conf"); +-#endif + + std::string interpreter; + TargetMode targetMode; + Environment newEnv; + ++ File cfgFile = File(""); ++ ++ try { ++ cfgFile = File(env.getVar("SUPHP_OPTIONS").c_str()); ++ } catch (KeyNotFoundException &e) { ++#ifdef OPT_CONFIGFILE ++ cfgFile = File(OPT_CONFIGFILE); ++#else ++ cfgFile = File("/etc/suphp.conf"); ++#endif ++ } ++ + // Begin try block - soft exception cannot really be handled before + // initialization + try { +@@ -88,14 +95,23 @@ + return 1; + } + +- this->checkScriptFile(scriptFilename, config, env); +- + // Root privileges are needed for chroot() + // so do this before changing process permissions + if (config.getChrootPath().length() > 0) { + api.chroot(config.getChrootPath()); ++ ++ // after chroot() the SCRIPT_FILENAME path has changed ++ // and needs to get "translated" ++ std::string strChrootPath(config.getChrootPath()); ++ ++ // TODO: check if there is a "/" at the beginning of scriptFilename ++ scriptFilename.replace(scriptFilename.find(strChrootPath), strChrootPath.length(), ""); ++ env.setVar("DOCUMENT_ROOT", "/"); ++ env.setVar("SCRIPT_FILENAME", scriptFilename); + } + ++ this->checkScriptFile(scriptFilename, config, env); ++ + this->changeProcessPermissions(scriptFilename, config, env); + + interpreter = this->getInterpreter(env, config); +@@ -396,6 +412,8 @@ + env.deleteVar("SUPHP_AUTH_PW"); + if (env.hasVar("SUPHP_PHP_CONFIG")) + env.deleteVar("SUPHP_PHP_CONFIG"); ++ if (env.hasVar("SUPHP_OPTIONS")) ++ env.deleteVar("SUPHP_OPTIONS"); + + // Reset PATH + env.putVar("PATH", config.getEnvPath()); diff --git a/mod_suphp-0.6.1-userdir.patch b/mod_suphp-0.6.1-userdir.patch new file mode 100644 index 0000000..fab7dfa --- /dev/null +++ b/mod_suphp-0.6.1-userdir.patch @@ -0,0 +1,248 @@ +From miles at lubin.us Sat Dec 3 01:21:51 2005 +From: miles at lubin.us (Miles Lubin) +Date: Sat Dec 3 01:23:25 2005 +Subject: [suPHP] mod_userdir patch for 0.6.1 +Message-ID: <4390E51F.3080506@lubin.us> + +Attached is the mod_userdir patch updated to 0.6.1. + +The patch allows suphp to correctly handle permissions with user sites, +generated by mod_suphp; instead of using the permissions of the main +site for force and paranoid mode, it will use the permissions of the +correct user. + +Changes from 0.6.0 patch: +- handle_userdir is enabled by default, set handle_userdir=false in +/etc/suphp.conf to disable it +- check the length of the url argument in checkUserDir() (a theoretical +security issue, though not exploitable) +- made the code more conforming to the suphp's coding style + + +Miles Lubin + +-------------- next part -------------- +diff -ur suphp-0.6.1/doc/CONFIG suphp-0.6.1-userdir/doc/CONFIG +--- suphp-0.6.1/doc/CONFIG 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/doc/CONFIG 2005-12-02 15:07:41.000000000 -0500 +@@ -95,6 +95,11 @@ + Minimum GID allowed to execute scripts. + Defaults to compile-time value. + ++handle_userdir: ++ Handle sites created by mod_userdir. ++ Scripts on userdir sites will be executed with the permissions ++ of the owner of the site. This option only affects force and paranoid mode. ++ This option is enabled by default. + + 3. Handlers + +diff -ur suphp-0.6.1/doc/suphp.conf-example suphp-0.6.1-userdir/doc/suphp.conf-example +--- suphp-0.6.1/doc/suphp.conf-example 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/doc/suphp.conf-example 2005-12-02 15:07:41.000000000 -0500 +@@ -38,6 +38,8 @@ + ; Minimum GID + min_gid=100 + ++; Use correct permissions for mod_userdir sites ++handle_userdir=true + + [handlers] + ;Handler for php-scripts +diff -ur suphp-0.6.1/src/Application.cpp suphp-0.6.1-userdir/src/Application.cpp +--- suphp-0.6.1/src/Application.cpp 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/src/Application.cpp 2005-12-02 17:18:27.000000000 -0500 +@@ -19,6 +19,7 @@ + */ + + #include <iostream> ++#include <sstream> + + #include "config.h" + +@@ -300,29 +301,33 @@ + // Paranoid and force mode + + #if (defined(OPT_USERGROUP_PARANOID) || defined(OPT_USERGROUP_FORCE)) +- std::string targetUsername, targetGroupname; +- try { +- targetUsername = environment.getVar("SUPHP_USER"); +- targetGroupname = environment.getVar("SUPHP_GROUP"); +- } catch (KeyNotFoundException& e) { +- throw SecurityException( ++ if (config.getHandleUserdir() && checkUserDir(environment.getVar("SUPHP_URI"),targetUser)) { ++ targetGroup = targetUser.getGroupInfo(); ++ } else { ++ std::string targetUsername, targetGroupname; ++ try { ++ targetUsername = environment.getVar("SUPHP_USER"); ++ targetGroupname = environment.getVar("SUPHP_GROUP"); ++ } catch (KeyNotFoundException& e) { ++ throw SecurityException( + "Environment variable SUPHP_USER or SUPHP_GROUP not set", + __FILE__, __LINE__); +- } ++ } + +- if (targetUsername[0] == '#' && targetUsername.find_first_not_of( ++ if (targetUsername[0] == '#' && targetUsername.find_first_not_of( + "0123456789", 1) == std::string::npos) { +- targetUser = api.getUserInfo(Util::strToInt(targetUsername.substr(1))); +- } else { +- targetUser = api.getUserInfo(targetUsername); +- } ++ targetUser = api.getUserInfo(Util::strToInt(targetUsername.substr(1))); ++ } else { ++ targetUser = api.getUserInfo(targetUsername); ++ } + +- if (targetGroupname[0] == '#' && targetGroupname.find_first_not_of( ++ if (targetGroupname[0] == '#' && targetGroupname.find_first_not_of( + "0123456789", 1) == std::string::npos) { +- targetGroup = api.getGroupInfo( ++ targetGroup = api.getGroupInfo( + Util::strToInt(targetGroupname.substr(1))); +- } else { +- targetGroup = api.getGroupInfo(targetGroupname); ++ } else { ++ targetGroup = api.getGroupInfo(targetGroupname); ++ } + } + #endif // OPT_USERGROUP_PARANOID || OPT_USERGROUP_FORCE + +@@ -473,6 +478,28 @@ + } + } + ++bool suPHP::Application::checkUserDir(const std::string& url, UserInfo& user) const { ++ ++ if (url.length() <= 2 || url[1] != '~') ++ return false; ++ ++ API& api = API_Helper::getSystemAPI(); ++ std::string topDir; ++ std::istringstream strm(url); ++ ++ for (int i = 0; i < 2; i++) ++ if (!std::getline(strm, topDir, '/')) ++ return false; ++ ++ std::string userName = topDir.substr(1,topDir.length()); ++ ++ try { ++ user = api.getUserInfo(userName); ++ return true; ++ } catch (LookupException& e) { ++ return false; ++ } ++} + + int main(int argc, char **argv) { + try { +diff -ur suphp-0.6.1/src/Application.hpp suphp-0.6.1-userdir/src/Application.hpp +--- suphp-0.6.1/src/Application.hpp 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/src/Application.hpp 2005-12-02 15:07:41.000000000 -0500 +@@ -39,6 +39,7 @@ + #include "SystemException.hpp" + #include "SoftException.hpp" + #include "SecurityException.hpp" ++#include "UserInfo.hpp" + + namespace suPHP { + /** +@@ -107,6 +108,12 @@ + const Configuration& config) const + throw (SoftException); + ++ /** ++ * Checks if a given URL is a userdir ++ * associated user is assigned to the user parameter ++ */ ++ bool checkUserDir(const std::string& url, ++ UserInfo& user) const; + + public: + /** +diff -ur suphp-0.6.1/src/Configuration.cpp suphp-0.6.1-userdir/src/Configuration.cpp +--- suphp-0.6.1/src/Configuration.cpp 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/src/Configuration.cpp 2005-12-02 17:22:46.000000000 -0500 +@@ -112,6 +112,7 @@ + #endif + this->umask = 0077; + this->chroot_path = ""; ++ this->handle_userdir = true; + } + + void suPHP::Configuration::readFromFile(File& file) +@@ -157,6 +158,8 @@ + this->umask = Util::octalStrToInt(value); + else if (key == "chroot") + this->chroot_path = value; ++ else if (key == "handle_userdir") ++ this->handle_userdir = this->strToBool(value); + else + throw ParsingException("Unknown option \"" + key + + "\" in section [global]", +@@ -250,3 +253,7 @@ + std::string suPHP::Configuration::getChrootPath() const { + return this->chroot_path; + } ++ ++bool suPHP::Configuration::getHandleUserdir() const { ++ return this->handle_userdir; ++} +diff -ur suphp-0.6.1/src/Configuration.hpp suphp-0.6.1-userdir/src/Configuration.hpp +--- suphp-0.6.1/src/Configuration.hpp 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/src/Configuration.hpp 2005-12-02 15:07:41.000000000 -0500 +@@ -57,7 +57,8 @@ + int min_gid; + int umask; + std::string chroot_path; +- ++ bool handle_userdir; ++ + /** + * Converts string to bool + */ +@@ -165,6 +166,12 @@ + * Return chroot path + */ + std::string getChrootPath() const; ++ ++ /** ++ * Return whether to correctly handle mod_userdir sites ++ */ ++ bool getHandleUserdir() const; ++ + }; + }; + +diff -ur suphp-0.6.1/src/apache/mod_suphp.c suphp-0.6.1-userdir/src/apache/mod_suphp.c +--- suphp-0.6.1/src/apache/mod_suphp.c 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/src/apache/mod_suphp.c 2005-12-02 15:07:41.000000000 -0500 +@@ -444,7 +444,10 @@ + } + } + } +- ++ ++ /* for mod_userdir checking */ ++ apr_table_setn(r->subprocess_env, "SUPHP_URI", apr_pstrdup(p, r->uri)); ++ + if (auth_user && auth_pass) { + ap_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); + ap_table_setn(r->subprocess_env, "SUPHP_AUTH_PW", auth_pass); +diff -ur suphp-0.6.1/src/apache2/mod_suphp.c suphp-0.6.1-userdir/src/apache2/mod_suphp.c +--- suphp-0.6.1/src/apache2/mod_suphp.c 2005-11-26 14:45:49.000000000 -0500 ++++ suphp-0.6.1-userdir/src/apache2/mod_suphp.c 2005-12-02 15:07:41.000000000 -0500 +@@ -461,6 +461,10 @@ + } + } + ++ /* for mod_userdir checking */ ++ apr_table_setn(r->subprocess_env, "SUPHP_URI", ++ apr_pstrdup(r->pool, r->uri)); ++ + if (auth_user && auth_pass) + { + apr_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); diff --git a/mod_suphp-0.6.3-userdir.patch b/mod_suphp-0.6.3-userdir.patch new file mode 100644 index 0000000..1791b41 --- /dev/null +++ b/mod_suphp-0.6.3-userdir.patch @@ -0,0 +1,217 @@ +--- suphp-0.6.3/doc/suphp.conf-example.userdir 2005-11-26 20:29:02.000000000 +0100 ++++ suphp-0.6.3/doc/suphp.conf-example 2008-03-31 02:08:13.000000000 +0200 +@@ -38,6 +38,8 @@ + ; Minimum GID + min_gid=100 + ++; Use correct permissions for mod_userdir sites ++handle_userdir=true + + [handlers] + ;Handler for php-scripts +--- suphp-0.6.3/doc/CONFIG.userdir 2005-11-26 20:29:02.000000000 +0100 ++++ suphp-0.6.3/doc/CONFIG 2008-03-31 02:08:13.000000000 +0200 +@@ -95,6 +95,11 @@ + Minimum GID allowed to execute scripts. + Defaults to compile-time value. + ++handle_userdir: ++ Handle sites created by mod_userdir. ++ Scripts on userdir sites will be executed with the permissions ++ of the owner of the site. This option only affects force and paranoid mode. ++ This option is enabled by default. + + 3. Handlers + +--- suphp-0.6.3/src/Configuration.cpp.userdir 2006-03-15 21:21:52.000000000 +0100 ++++ suphp-0.6.3/src/Configuration.cpp 2008-03-31 02:08:13.000000000 +0200 +@@ -112,6 +112,7 @@ + #endif + this->umask = 0077; + this->chroot_path = ""; ++ this->handle_userdir = true; + } + + void suPHP::Configuration::readFromFile(File& file) +@@ -157,6 +158,8 @@ + this->umask = Util::octalStrToInt(value); + else if (key == "chroot") + this->chroot_path = value; ++ else if (key == "handle_userdir") ++ this->handle_userdir = this->strToBool(value); + else + throw ParsingException("Unknown option \"" + key + + "\" in section [global]", +@@ -250,3 +253,7 @@ + std::string suPHP::Configuration::getChrootPath() const { + return this->chroot_path; + } ++ ++bool suPHP::Configuration::getHandleUserdir() const { ++ return this->handle_userdir; ++} +--- suphp-0.6.3/src/apache2/mod_suphp.c.userdir 2006-11-06 01:57:12.000000000 +0100 ++++ suphp-0.6.3/src/apache2/mod_suphp.c 2008-03-31 02:08:13.000000000 +0200 +@@ -656,6 +656,10 @@ + } + } + ++ /* for mod_userdir checking */ ++ apr_table_setn(r->subprocess_env, "SUPHP_URI", ++ apr_pstrdup(r->pool, r->uri)); ++ + if (auth_user && auth_pass) + { + apr_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); +--- suphp-0.6.3/src/Configuration.hpp.userdir 2005-11-26 20:29:02.000000000 +0100 ++++ suphp-0.6.3/src/Configuration.hpp 2008-03-31 02:08:13.000000000 +0200 +@@ -57,7 +57,8 @@ + int min_gid; + int umask; + std::string chroot_path; +- ++ bool handle_userdir; ++ + /** + * Converts string to bool + */ +@@ -165,6 +166,12 @@ + * Return chroot path + */ + std::string getChrootPath() const; ++ ++ /** ++ * Return whether to correctly handle mod_userdir sites ++ */ ++ bool getHandleUserdir() const; ++ + }; + }; + +--- suphp-0.6.3/src/Application.hpp.userdir 2008-03-29 23:58:58.000000000 +0100 ++++ suphp-0.6.3/src/Application.hpp 2008-03-31 02:09:27.000000000 +0200 +@@ -39,6 +39,7 @@ + #include "SystemException.hpp" + #include "SoftException.hpp" + #include "SecurityException.hpp" ++#include "UserInfo.hpp" + + namespace suPHP { + /** +@@ -116,6 +117,13 @@ + const Configuration& config) const + throw (SoftException); + ++ /** ++ * Checks if a given URL is a userdir ++ * associated user is assigned to the user parameter ++ */ ++ bool checkUserDir(const std::string& url, ++ UserInfo& user) const; ++ + public: + /** + * Constructer +--- suphp-0.6.3/src/apache/mod_suphp.c.userdir 2006-09-23 19:04:36.000000000 +0200 ++++ suphp-0.6.3/src/apache/mod_suphp.c 2008-03-31 02:08:13.000000000 +0200 +@@ -491,7 +491,10 @@ + } + } + } +- ++ ++ /* for mod_userdir checking */ ++ apr_table_setn(r->subprocess_env, "SUPHP_URI", apr_pstrdup(p, r->uri)); ++ + if (auth_user && auth_pass) { + ap_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); + ap_table_setn(r->subprocess_env, "SUPHP_AUTH_PW", auth_pass); +--- suphp-0.6.3/src/Application.cpp.userdir 2008-03-30 13:43:38.000000000 +0200 ++++ suphp-0.6.3/src/Application.cpp 2008-03-31 02:08:13.000000000 +0200 +@@ -19,6 +19,7 @@ + */ + + #include <iostream> ++#include <sstream> + + #include "config.h" + +@@ -305,29 +306,33 @@ + // Paranoid and force mode + + #if (defined(OPT_USERGROUP_PARANOID) || defined(OPT_USERGROUP_FORCE)) +- std::string targetUsername, targetGroupname; +- try { +- targetUsername = environment.getVar("SUPHP_USER"); +- targetGroupname = environment.getVar("SUPHP_GROUP"); +- } catch (KeyNotFoundException& e) { +- throw SecurityException( ++ if (config.getHandleUserdir() && checkUserDir(environment.getVar("SUPHP_URI"),targetUser)) { ++ targetGroup = targetUser.getGroupInfo(); ++ } else { ++ std::string targetUsername, targetGroupname; ++ try { ++ targetUsername = environment.getVar("SUPHP_USER"); ++ targetGroupname = environment.getVar("SUPHP_GROUP"); ++ } catch (KeyNotFoundException& e) { ++ throw SecurityException( + "Environment variable SUPHP_USER or SUPHP_GROUP not set", + __FILE__, __LINE__); +- } ++ } + +- if (targetUsername[0] == '#' && targetUsername.find_first_not_of( ++ if (targetUsername[0] == '#' && targetUsername.find_first_not_of( + "0123456789", 1) == std::string::npos) { +- targetUser = api.getUserInfo(Util::strToInt(targetUsername.substr(1))); +- } else { +- targetUser = api.getUserInfo(targetUsername); +- } ++ targetUser = api.getUserInfo(Util::strToInt(targetUsername.substr(1))); ++ } else { ++ targetUser = api.getUserInfo(targetUsername); ++ } + +- if (targetGroupname[0] == '#' && targetGroupname.find_first_not_of( ++ if (targetGroupname[0] == '#' && targetGroupname.find_first_not_of( + "0123456789", 1) == std::string::npos) { +- targetGroup = api.getGroupInfo( ++ targetGroup = api.getGroupInfo( + Util::strToInt(targetGroupname.substr(1))); +- } else { +- targetGroup = api.getGroupInfo(targetGroupname); ++ } else { ++ targetGroup = api.getGroupInfo(targetGroupname); ++ } + } + #endif // OPT_USERGROUP_PARANOID || OPT_USERGROUP_FORCE + +@@ -519,6 +524,28 @@ + } while (directory.getPath() != "/"); + } + ++bool suPHP::Application::checkUserDir(const std::string& url, UserInfo& user) const { ++ ++ if (url.length() <= 2 || url[1] != '~') ++ return false; ++ ++ API& api = API_Helper::getSystemAPI(); ++ std::string topDir; ++ std::istringstream strm(url); ++ ++ for (int i = 0; i < 2; i++) ++ if (!std::getline(strm, topDir, '/')) ++ return false; ++ ++ std::string userName = topDir.substr(1,topDir.length()); ++ ++ try { ++ user = api.getUserInfo(userName); ++ return true; ++ } catch (LookupException& e) { ++ return false; ++ } ++} + + int main(int argc, char **argv) { + try { diff --git a/mod_suphp.conf b/mod_suphp.conf new file mode 100644 index 0000000..05bd971 --- /dev/null +++ b/mod_suphp.conf @@ -0,0 +1,24 @@ +# This is the Apache server configuration file providing suPHP support.. +# It contains the configuration directives to instruct the server how to +# serve php pages while switching to the user context before rendering. + +### Uncomment to activate mod_suphp +#suPHP_AddHandler ###HANDLER### + + +# This option tells mod_suphp if a PHP-script requested on this server (or +# VirtualHost) should be run with the PHP-interpreter or returned to the +# browser "as it is". +suPHP_Engine on + + +# This option tells mod_suphp which path to pass on to the PHP-interpreter +# (by setting the PHPRC environment variable). +# Do *NOT* refer to a file but to the directory the file resists in. +# +# E.g.: If you want to use "/path/to/server/config/php.ini", use "suPHP_Config +# /path/to/server/config". +# +# If you don't use this option, PHP will use its compiled in default path. +#suPHP_ConfigPath /etc + diff --git a/mod_suphp.module.conf b/mod_suphp.module.conf new file mode 100644 index 0000000..2b87216 --- /dev/null +++ b/mod_suphp.module.conf @@ -0,0 +1,5 @@ +# This is the Apache server configuration file providing suPHP support.. +# It contains the configuration directives to instruct the server how to +# serve php pages while switching to the user context before rendering. + +LoadModule suphp_module modules/mod_suphp.so diff --git a/mod_suphp.spec b/mod_suphp.spec new file mode 100644 index 0000000..e3495fa --- /dev/null +++ b/mod_suphp.spec @@ -0,0 +1,201 @@ +# Depending on what version of Fedora we're on, use a different php binary, different apr +# and also different handler. +%if 0%{?fedora} + %if 0%{fedora} >= 5 + %define php /usr/bin/php-cgi + %define handler php5-script + %define apr /usr/bin/apr-1-config + %endif + %if 0%{fedora} == 4 + %define php /usr/bin/php-cgi + %define handler x-httpd-php + %define apr /usr/bin/apr-config + %endif + %if 0%{fedora} <= 3 + %define php /usr/bin/php + %define handler x-httpd-php + %define apr /usr/bin/apr-config + %endif +%else + %define php /usr/bin/php + %define handler x-httpd-php + %define apr /usr/bin/apr-config +%endif + +%{!?_httpd_apxs: %{expand: %%global _httpd_apxs %%{_sbindir}/apxs}} +%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn || echo missing-httpd-devel)}} + +Summary: An apache2 module for executing PHP scripts with the permissions of their owners +Name: mod_suphp +Version: 0.6.3 +Release: 9%{?dist} +License: GPLv2+ +Group: System Environment/Daemons +Source0: http://www.suphp.org/download/suphp-%{version}.tar.gz +Source1: suphp.conf +Source2: mod_suphp.conf +Source3: README.fedora +Source4: mod_suphp.module.conf +Patch0: mod_suphp-0.6.3-userdir.patch +Patch1: mod_suphp-0.6.1-AddHandler.patch +Patch3: mod_suphp-0.6.1-chroot.patch +URL: http://www.suphp.org/ +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Requires: httpd >= 2.0, php +Requires: httpd-mmn = %{_httpd_mmn} +BuildRequires: httpd-devel >= 2.0, apr-devel + + +%description +suPHP is an apache module for executing PHP scripts with the permissions of +their owners. It consists of an Apache module (mod_suphp) and a setuid root +binary (suphp) that is called by the Apache module to change the uid of the +process executing the PHP interpreter. + +Please take a look at %{_docdir}/%{name}-%{version}/README.fedora for +installation instructions. + +%prep +%setup -q -n suphp-%{version} +%patch0 -p 1 -b .userdir +%patch1 -p 1 -b .AddHandler +%patch3 -p 1 -b .chroot + + +# fill placeholders +sed -e 's|###PHP-BIN###|%{php}|g; s|###HANDLER###|%{handler}|g;' %{SOURCE1} > suphp.conf +sed -e 's|###HANDLER###|%{handler}|g;' %{SOURCE2} > mod_suphp.conf +sed -e 's|###HANDLER###|%{handler}|g;' %{SOURCE3} > README.fedora +cp -a %{SOURCE4} mod_suphp.module.conf + + +%build +echo "Building mod_suphp with %{php} as PHP interpreter and %{apr} for the apr configuration script." +echo "%{handler} is used as a AddHandler." +%configure \ + --with-apr=%{apr} \ + --with-apxs=%{_httpd_apxs} \ + --with-apache-user=apache \ + --with-min-uid=500 \ + --with-min-gid=500 \ + --with-php=%{php} \ + --with-logfile=/var/log/httpd/suphp_log \ + --with-setid-mode=owner + +pushd src +make %{?_smp_mflags} suphp +popd + +pushd src/apache2 +%{_httpd_apxs} -c mod_suphp.c +mv .libs/mod_suphp.so . +popd + + +%install +rm -rf %{buildroot} + +%{__install} -c -m 4755 -D src/suphp %{buildroot}%{_sbindir}/suphp +%{__install} -m 755 -D src/apache2/mod_suphp.so %{buildroot}%{_libdir}/httpd/modules/mod_suphp.so + +# Install the config files +%{__install} -m 644 -D suphp.conf %{buildroot}%{_sysconfdir}/suphp.conf +%{__install} -m 644 -D mod_suphp.conf %{buildroot}%{_sysconfdir}/httpd/conf.d/mod_suphp.conf +%{__install} -m 644 -D mod_suphp.module.conf %{buildroot}%{_sysconfdir}/httpd/conf.modules.d/02-mod_suphp.conf + +# Rename docs +cp doc/CONFIG CONFIG.suphp +cp doc/apache/CONFIG CONFIG.apache + + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%doc README COPYING CONFIG.suphp CONFIG.apache README.fedora +%attr (4550, root, apache) %{_sbindir}/suphp +%{_libdir}/httpd/modules/*.so +%config(noreplace) %{_sysconfdir}/suphp.conf +%config(noreplace) %{_sysconfdir}/httpd/conf.d/mod_suphp.conf +%config(noreplace) %{_sysconfdir}/httpd/conf.modules.d/02-mod_suphp.conf + + +%changelog +* Mon Apr 16 2012 Remi Collet <RPMS@FamilleCollet.com> - 0.6.3-9 +- rebuild for remi repo and httpd 2.4 + +* Thu Apr 05 2012 Jan Kaluza <jkaluza@redhat.com> - 0.6.3-9 +- Fix compilation issues with httpd-2.4 (#809750) + +* Tue Feb 28 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.6.3-8 +- Rebuilt for c++ ABI breakage + +* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.6.3-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.6.3-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Sat Jul 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.6.3-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.6.3-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Sun Sep 07 2008 Andreas Thienemann <andreas@bawue.net> - 0.6.3-3 +- Fix conditionals, fix FTBFS #449578 + +* Mon Aug 11 2008 Tom "spot" Callaway <tcallawa@redhat.com> - 0.6.3-2 +- fix license tag + +* Sun Mar 30 2008 Andreas Thienemann <andreas@bawue.net> - 0.6.3-1 +- Updated to 0.6.3 fixing two security problems. #439687 + +* Tue Feb 19 2008 Fedora Release Engineering <rel-eng@fedoraproject.org> - 0.6.2-2 +- Autorebuild for GCC 4.3 + +* Sat Mar 10 2007 Andreas Thienemann <andreas@bawue.net> - 0.6.2-1 +- Updated to 0.6.2 +- Reverted our double free patch. Upstream fixed their SmartPointer + implementation. +- Reverted our apr Patch, upstream is working correctly with Apache 2.2 now + +* Fri Nov 10 2006 Andreas Thienemann <andreas@bawue.net> - 0.6.1-4 +- Fix double free corruption. For real this time. :-/ + +* Fri Sep 08 2006 Andreas Thienemann <andreas@bawue.net> - 0.6.1-3 +- Finally fixed double free corruption #192415 +- Fixed up configuration creation + +* Wed May 24 2006 Andreas Thienemann <andreas@bawue.net> - 0.6.1-2 +- Corrected handler for mod_suphp.conf +- Minor cleanups and fixes + +* Mon Feb 06 2006 Andreas Thienemann <andreas@bawue.net> 0.6.1-1 +- Updated to 0.6.1 + +* Tue Jul 09 2005 Andreas Thienemann <andreas@bawue.net> 0.5.2-8 +- Added a dependency on a specific httpd-mmn + +* Tue Jul 05 2005 Andreas Thienemann <andreas@bawue.net> 0.5.2-7 +- Bumped up the releasever + +* Tue Jul 05 2005 Andreas Thienemann <andreas@bawue.net> 0.5.2-6 +- Added correct name to %%setup macro + +* Thu Jun 30 2005 Andreas Thienemann <andreas@bawue.net> 0.5.2-5 +- Rollback of namechange. Now we're mod_suphp again. + +* Thu Jun 30 2005 Andreas Thienemann <andreas@bawue.net> 0.5.2-4 +- Cleanup of specfile, incorporated suggestions from "spot" +- Modified configure command to use cgi-php for FC4, php otherwise + +* Sat Nov 13 2004 Andreas Thienemann <andreas@bawue.net> 0.5.2-3 +- Added "--disable-checkpath" in order to allow /~user URLs + +* Sat Nov 13 2004 Andreas Thienemann <andreas@bawue.net> 0.5.2-2 +- Fixed the wrong path in the logfile directive + +* Sat Nov 13 2004 Andreas Thienemann <andreas@bawue.net> 0.5.2-1 +- initial package diff --git a/suphp.conf b/suphp.conf new file mode 100644 index 0000000..9b94246 --- /dev/null +++ b/suphp.conf @@ -0,0 +1,49 @@ +[global] +;Path to logfile +logfile=/var/log/suphp.log + +;Loglevel +loglevel=info + +;User Apache is running as +webserver_user=apache + +;Path all scripts have to be in +docroot=/ + +;Path to chroot() to before executing script +;chroot=/mychroot + +; Security options +allow_file_group_writeable=false +allow_file_others_writeable=false +allow_directory_group_writeable=false +allow_directory_others_writeable=false + +;Check wheter script is within DOCUMENT_ROOT +check_vhost_docroot=true + +;Send minor error messages to browser +errors_to_browser=true + +;PATH environment variable +env_path=/bin:/usr/bin + +;Umask to set, specify in octal notation +umask=0077 + +; Minimum UID +min_uid=500 + +; Minimum GID +min_gid=500 + +; Use correct permissions for mod_userdir sites +handle_userdir=true + +[handlers] +;Handler for php-scripts +###HANDLER###=php:###PHP-BIN### + +;Handler for CGI-scripts +x-suphp-cgi=execute:!self |