--- /dev/null
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 04_CVE-2008-1614.dpatch
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Libtool update
+
+@DPATCH@
+--- suphp-0.6.2.orig/src/API_Linux.hpp
++++ suphp-0.6.2/src/API_Linux.hpp
+@@ -169,6 +169,11 @@
+ virtual GroupInfo File_getGroup(const File& file) const
+ throw (SystemException);
+
++ /**
++ * Checks whether a file is a symlink
++ */
++ virtual bool File_isSymlink(const File& file) const throw (SystemException);
++
+ /**
+ * Runs another program (replaces current process)
+ */
+only in patch2:
+unchanged:
+--- suphp-0.6.2.orig/src/File.cpp
++++ suphp-0.6.2/src/File.cpp
+@@ -57,6 +57,9 @@
+ File suPHP::File::getParentDirectory() const {
+ std::string path = this->getPath();
+ path = path.substr(0, path.rfind('/'));
++ if (path.length() == 0) {
++ path = "/";
++ }
+ return File(path);
+ }
+
+@@ -104,3 +107,7 @@
+ GroupInfo suPHP::File::getGroup() const throw (SystemException) {
+ return API_Helper::getSystemAPI().File_getGroup(*this);
+ }
++
++bool suPHP::File::isSymlink() const throw (SystemException) {
++ return API_Helper::getSystemAPI().File_isSymlink(*this);
++}
+only in patch2:
+unchanged:
+--- suphp-0.6.2.orig/src/Application.hpp
++++ suphp-0.6.2/src/Application.hpp
+@@ -107,6 +107,14 @@
+ const Configuration& config) const
+ throw (SoftException);
+
++
++ /**
++ * Checks ownership and permissions for parent directories
++ */
++ void checkParentDirectories(const File& file,
++ const UserInfo& owner,
++ const Configuration& config) const
++ throw (SoftException);
+
+ public:
+ /**
+only in patch2:
+unchanged:
+--- suphp-0.6.2.orig/src/Application.cpp
++++ suphp-0.6.2/src/Application.cpp
+@@ -177,6 +177,7 @@
+ throw (SystemException, SoftException) {
+ Logger& logger = API_Helper::getSystemAPI().getSystemLogger();
+ File scriptFile = File(scriptFilename);
++ File realScriptFile = File(scriptFile.getRealPath());
+
+ // Check wheter file exists
+ if (!scriptFile.exists()) {
+@@ -184,11 +185,13 @@
+ logger.logWarning(error);
+ throw SoftException(error, __FILE__, __LINE__);
+ }
+-
+- // Get full path to script file
+-
+- File realScriptFile = File(scriptFile.getRealPath());
+- File directory = realScriptFile.getParentDirectory();
++ if (!realScriptFile.exists()) {
++ std::string error = "File " + realScriptFile.getPath()
++ + " referenced by symlink " +scriptFile.getPath()
++ + " does not exist";
++ logger.logWarning(error);
++ throw SoftException(error, __FILE__, __LINE__);
++ }
+
+ // Check wheter script is in docroot
+ if (realScriptFile.getPath().find(config.getDocroot()) != 0) {
+@@ -213,8 +216,19 @@
+ logger.logWarning(error);
+ throw SoftException(error, __FILE__, __LINE__);
+ }
++ if (config.getCheckVHostDocroot()
++ && scriptFile.getPath().find(environment.getVar("DOCUMENT_ROOT"))
++ != 0) {
++
++ std::string error = "File \"" + scriptFile.getPath()
++ + "\" is not in document root of Vhost \""
++ + environment.getVar("DOCUMENT_ROOT") + "\"";
++ logger.logWarning(error);
++ throw SoftException(error, __FILE__, __LINE__);
++ }
+
+- // Check script and directory permissions
++ // Check script permissions
++ // Directories will be checked later
+ if (!realScriptFile.hasUserReadBit()) {
+ std::string error = "File \"" + realScriptFile.getPath()
+ + "\" not readable";
+@@ -231,14 +245,6 @@
+ throw SoftException(error, __FILE__, __LINE__);
+ }
+
+- if (!config.getAllowDirectoryGroupWriteable()
+- && directory.hasGroupWriteBit()) {
+- std::string error = "Directory \"" + directory.getPath()
+- + "\" is writeable by group";
+- logger.logWarning(error);
+- throw SoftException(error, __FILE__, __LINE__);
+- }
+-
+ if (!config.getAllowFileOthersWriteable()
+ && realScriptFile.hasOthersWriteBit()) {
+ std::string error = "File \"" + realScriptFile.getPath()
+@@ -247,14 +253,6 @@
+ throw SoftException(error, __FILE__, __LINE__);
+ }
+
+- if (!config.getAllowDirectoryOthersWriteable()
+- && directory.hasOthersWriteBit()) {
+- std::string error = "Directory \"" + directory.getPath()
+- + "\" is writeable by others";
+- logger.logWarning(error);
+- throw SoftException(error, __FILE__, __LINE__);
+- }
+-
+ // Check UID/GID of symlink is matching target
+ if (scriptFile.getUser() != realScriptFile.getUser()
+ || scriptFile.getGroup() != realScriptFile.getGroup()) {
+@@ -274,7 +272,8 @@
+ UserInfo targetUser;
+ GroupInfo targetGroup;
+
+- File scriptFile = File(File(scriptFilename).getRealPath());
++ File scriptFile = File(scriptFilename);
++ File realScriptFile = File(scriptFile.getRealPath());
+ API& api = API_Helper::getSystemAPI();
+ Logger& logger = api.getSystemLogger();
+
+@@ -360,7 +359,11 @@
+ throw SoftException(error, __FILE__, __LINE__);
+ }
+ #endif // OPT_USERGROUP_PARANOID
+-
++
++ // Check directory ownership and permissions
++ checkParentDirectories(realScriptFile, targetUser, config);
++ checkParentDirectories(scriptFile, targetUser, config);
++
+ // Common code used for all modes
+
+ // Set new group first, because we still need super-user privileges
+@@ -480,6 +483,43 @@
+ }
+
+
++void suPHP::Application::checkParentDirectories(const File& file,
++ const UserInfo& owner,
++ const Configuration& config) const throw (SoftException) {
++ File directory = file;
++ Logger& logger = API_Helper::getSystemAPI().getSystemLogger();
++ do {
++ directory = directory.getParentDirectory();
++
++ UserInfo directoryOwner = directory.getUser();
++ if (directoryOwner != owner && !directoryOwner.isSuperUser()) {
++ std::string error = "Directory " + directory.getPath()
++ + " is not owned by " + owner.getUsername();
++ logger.logWarning(error);
++ throw SoftException(error, __FILE__, __LINE__);
++ }
++
++ if (!directory.isSymlink()
++ && !config.getAllowDirectoryGroupWriteable()
++ && directory.hasGroupWriteBit()) {
++ std::string error = "Directory \"" + directory.getPath()
++ + "\" is writeable by group";
++ logger.logWarning(error);
++ throw SoftException(error, __FILE__, __LINE__);
++ }
++
++ if (!directory.isSymlink()
++ && !config.getAllowDirectoryOthersWriteable()
++ && directory.hasOthersWriteBit()) {
++ std::string error = "Directory \"" + directory.getPath()
++ + "\" is writeable by others";
++ logger.logWarning(error);
++ throw SoftException(error, __FILE__, __LINE__);
++ }
++ } while (directory.getPath() != "/");
++}
++
++
+ int main(int argc, char **argv) {
+ try {
+ API& api = API_Helper::getSystemAPI();
+only in patch2:
+unchanged:
+--- suphp-0.6.2.orig/src/API_Linux.cpp
++++ suphp-0.6.2/src/API_Linux.cpp
+@@ -225,10 +225,10 @@
+
+ bool suPHP::API_Linux::File_exists(const File& file) const {
+ struct stat dummy;
+- if (::stat(file.getPath().c_str(), &dummy) == 0)
+- return true;
++ if (::lstat(file.getPath().c_str(), &dummy) == 0)
++ return true;
+ else
+- return false;
++ return false;
+ }
+
+ std::string suPHP::API_Linux::File_getRealPath(const File& file) const
+@@ -304,7 +304,7 @@
+ bool suPHP::API_Linux::File_hasPermissionBit(const File& file, FileMode perm)
+ const throw (SystemException) {
+ struct stat temp;
+- if (stat(file.getPath().c_str(), &temp) == -1) {
++ if (lstat(file.getPath().c_str(), &temp) == -1) {
+ throw SystemException(std::string("Could not stat \"")
+ + file.getPath() + "\": "
+ + ::strerror(errno), __FILE__, __LINE__);
+@@ -362,7 +362,7 @@
+ UserInfo suPHP::API_Linux::File_getUser(const File& file) const
+ throw (SystemException) {
+ struct stat temp;
+- if (stat(file.getPath().c_str(), &temp) == -1) {
++ if (lstat(file.getPath().c_str(), &temp) == -1) {
+ throw SystemException(std::string("Could not stat \"")
+ + file.getPath() + "\": "
+ + ::strerror(errno), __FILE__, __LINE__);
+@@ -373,7 +373,7 @@
+ GroupInfo suPHP::API_Linux::File_getGroup(const File& file) const
+ throw (SystemException) {
+ struct stat temp;
+- if (stat(file.getPath().c_str(), &temp) == -1) {
++ if (lstat(file.getPath().c_str(), &temp) == -1) {
+ throw SystemException(std::string("Could not stat \"")
+ + file.getPath() + "\": "
+ + ::strerror(errno), __FILE__, __LINE__);
+@@ -382,6 +382,11 @@
+ }
+
+
++bool suPHP::API_Linux::File_isSymlink(const File& file) const throw (SystemException) {
++ return this->isSymlink(file.getPath());
++}
++
++
+ void suPHP::API_Linux::execute(std::string program, const CommandLine& cline,
+ const Environment& env) const
+ throw (SystemException) {
+only in patch2:
+unchanged:
+--- suphp-0.6.2.orig/src/File.hpp
++++ suphp-0.6.2/src/File.hpp
+@@ -143,7 +143,11 @@
+ * Returns owning group of file
+ */
+ GroupInfo getGroup() const throw (SystemException);
+-
++
++ /**
++ * Checks whether this file is a symlink
++ */
++ bool isSymlink() const throw (SystemException);
+ };
+ };
+
+only in patch2:
+unchanged:
+--- suphp-0.6.2.orig/src/API.hpp
++++ suphp-0.6.2/src/API.hpp
+@@ -157,6 +157,12 @@
+ virtual GroupInfo File_getGroup(const File& file) const
+ throw (SystemException) =0;
+
++ /**
++ * Checks whether a file is a symlink
++ */
++ virtual bool File_isSymlink(const File& file) const
++ throw (SystemException) =0;
++
+ /**
+ * Runs another program (replaces current process)
+ */
bool suPHP::API_Linux::File_exists(const File& file) const {
struct stat dummy;
- if (::lstat(file.getPath().c_str(), &dummy) == 0)
- return true;
+ if (::stat(file.getPath().c_str(), &dummy) == 0)
+ return true;
else
- return false;
+ return false;
}
std::string suPHP::API_Linux::File_getRealPath(const File& file) const
bool suPHP::API_Linux::File_hasPermissionBit(const File& file, FileMode perm)
const throw (SystemException) {
struct stat temp;
- if (lstat(file.getPath().c_str(), &temp) == -1) {
+ if (stat(file.getPath().c_str(), &temp) == -1) {
throw SystemException(std::string("Could not stat \"")
+ file.getPath() + "\": "
+ ::strerror(errno), __FILE__, __LINE__);
UserInfo suPHP::API_Linux::File_getUser(const File& file) const
throw (SystemException) {
struct stat temp;
- if (lstat(file.getPath().c_str(), &temp) == -1) {
+ if (stat(file.getPath().c_str(), &temp) == -1) {
throw SystemException(std::string("Could not stat \"")
+ file.getPath() + "\": "
+ ::strerror(errno), __FILE__, __LINE__);
GroupInfo suPHP::API_Linux::File_getGroup(const File& file) const
throw (SystemException) {
struct stat temp;
- if (lstat(file.getPath().c_str(), &temp) == -1) {
+ if (stat(file.getPath().c_str(), &temp) == -1) {
throw SystemException(std::string("Could not stat \"")
+ file.getPath() + "\": "
+ ::strerror(errno), __FILE__, __LINE__);
}
-bool suPHP::API_Linux::File_isSymlink(const File& file) const throw (SystemException) {
- return this->isSymlink(file.getPath());
-}
-
-
void suPHP::API_Linux::execute(std::string program, const CommandLine& cline,
const Environment& env) const
throw (SystemException) {
throw (SystemException, SoftException) {
Logger& logger = API_Helper::getSystemAPI().getSystemLogger();
File scriptFile = File(scriptFilename);
- File realScriptFile = File(scriptFile.getRealPath());
// Check wheter file exists
if (!scriptFile.exists()) {
logger.logWarning(error);
throw SoftException(error, __FILE__, __LINE__);
}
- if (!realScriptFile.exists()) {
- std::string error = "File " + realScriptFile.getPath()
- + " referenced by symlink " +scriptFile.getPath()
- + " does not exist";
- logger.logWarning(error);
- throw SoftException(error, __FILE__, __LINE__);
- }
+
+ // Get full path to script file
+
+ File realScriptFile = File(scriptFile.getRealPath());
+ File directory = realScriptFile.getParentDirectory();
// Check wheter script is in docroot
if (realScriptFile.getPath().find(config.getDocroot()) != 0) {
logger.logWarning(error);
throw SoftException(error, __FILE__, __LINE__);
}
- if (config.getCheckVHostDocroot()
- && scriptFile.getPath().find(environment.getVar("DOCUMENT_ROOT"))
- != 0) {
-
- std::string error = "File \"" + scriptFile.getPath()
- + "\" is not in document root of Vhost \""
- + environment.getVar("DOCUMENT_ROOT") + "\"";
- logger.logWarning(error);
- throw SoftException(error, __FILE__, __LINE__);
- }
- // Check script permissions
- // Directories will be checked later
+ // Check script and directory permissions
if (!realScriptFile.hasUserReadBit()) {
std::string error = "File \"" + realScriptFile.getPath()
+ "\" not readable";
throw SoftException(error, __FILE__, __LINE__);
}
+ if (!config.getAllowDirectoryGroupWriteable()
+ && directory.hasGroupWriteBit()) {
+ std::string error = "Directory \"" + directory.getPath()
+ + "\" is writeable by group";
+ logger.logWarning(error);
+ throw SoftException(error, __FILE__, __LINE__);
+ }
+
if (!config.getAllowFileOthersWriteable()
&& realScriptFile.hasOthersWriteBit()) {
std::string error = "File \"" + realScriptFile.getPath()
throw SoftException(error, __FILE__, __LINE__);
}
+ if (!config.getAllowDirectoryOthersWriteable()
+ && directory.hasOthersWriteBit()) {
+ std::string error = "Directory \"" + directory.getPath()
+ + "\" is writeable by others";
+ logger.logWarning(error);
+ throw SoftException(error, __FILE__, __LINE__);
+ }
+
// Check UID/GID of symlink is matching target
if (scriptFile.getUser() != realScriptFile.getUser()
|| scriptFile.getGroup() != realScriptFile.getGroup()) {
UserInfo targetUser;
GroupInfo targetGroup;
- File scriptFile = File(scriptFilename);
- File realScriptFile = File(scriptFile.getRealPath());
+ File scriptFile = File(File(scriptFilename).getRealPath());
API& api = API_Helper::getSystemAPI();
Logger& logger = api.getSystemLogger();
throw SoftException(error, __FILE__, __LINE__);
}
#endif // OPT_USERGROUP_PARANOID
-
- // Check directory ownership and permissions
- checkParentDirectories(realScriptFile, targetUser, config);
- checkParentDirectories(scriptFile, targetUser, config);
-
+
// Common code used for all modes
// Set new group first, because we still need super-user privileges
}
-void suPHP::Application::checkParentDirectories(const File& file,
- const UserInfo& owner,
- const Configuration& config) const throw (SoftException) {
- File directory = file;
- Logger& logger = API_Helper::getSystemAPI().getSystemLogger();
- do {
- directory = directory.getParentDirectory();
-
- UserInfo directoryOwner = directory.getUser();
- if (directoryOwner != owner && !directoryOwner.isSuperUser()) {
- std::string error = "Directory " + directory.getPath()
- + " is not owned by " + owner.getUsername();
- logger.logWarning(error);
- throw SoftException(error, __FILE__, __LINE__);
- }
-
- if (!directory.isSymlink()
- && !config.getAllowDirectoryGroupWriteable()
- && directory.hasGroupWriteBit()) {
- std::string error = "Directory \"" + directory.getPath()
- + "\" is writeable by group";
- logger.logWarning(error);
- throw SoftException(error, __FILE__, __LINE__);
- }
-
- if (!directory.isSymlink()
- && !config.getAllowDirectoryOthersWriteable()
- && directory.hasOthersWriteBit()) {
- std::string error = "Directory \"" + directory.getPath()
- + "\" is writeable by others";
- logger.logWarning(error);
- throw SoftException(error, __FILE__, __LINE__);
- }
- } while (directory.getPath() != "/");
-}
-
-
int main(int argc, char **argv) {
try {
API& api = API_Helper::getSystemAPI();