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
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__);
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__);
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__);
}
+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__);
}
-
- // 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) {
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";
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(File(scriptFilename).getRealPath());
+ File scriptFile = File(scriptFilename);
+ File realScriptFile = File(scriptFile.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();