1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## 04_CVE-2008-1614.dpatch
4 ## All lines beginning with `## DP:' are a description of the patch.
8 --- suphp-0.6.2.orig/src/API_Linux.hpp
9 +++ suphp-0.6.2/src/API_Linux.hpp
11 virtual GroupInfo File_getGroup(const File& file) const
12 throw (SystemException);
15 + * Checks whether a file is a symlink
17 + virtual bool File_isSymlink(const File& file) const throw (SystemException);
20 * Runs another program (replaces current process)
24 --- suphp-0.6.2.orig/src/File.cpp
25 +++ suphp-0.6.2/src/File.cpp
27 File suPHP::File::getParentDirectory() const {
28 std::string path = this->getPath();
29 path = path.substr(0, path.rfind('/'));
30 + if (path.length() == 0) {
37 GroupInfo suPHP::File::getGroup() const throw (SystemException) {
38 return API_Helper::getSystemAPI().File_getGroup(*this);
41 +bool suPHP::File::isSymlink() const throw (SystemException) {
42 + return API_Helper::getSystemAPI().File_isSymlink(*this);
46 --- suphp-0.6.2.orig/src/Application.hpp
47 +++ suphp-0.6.2/src/Application.hpp
49 const Configuration& config) const
50 throw (SoftException);
54 + * Checks ownership and permissions for parent directories
56 + void checkParentDirectories(const File& file,
57 + const UserInfo& owner,
58 + const Configuration& config) const
59 + throw (SoftException);
65 --- suphp-0.6.2.orig/src/Application.cpp
66 +++ suphp-0.6.2/src/Application.cpp
68 throw (SystemException, SoftException) {
69 Logger& logger = API_Helper::getSystemAPI().getSystemLogger();
70 File scriptFile = File(scriptFilename);
71 + File realScriptFile = File(scriptFile.getRealPath());
73 // Check wheter file exists
74 if (!scriptFile.exists()) {
76 logger.logWarning(error);
77 throw SoftException(error, __FILE__, __LINE__);
80 - // Get full path to script file
82 - File realScriptFile = File(scriptFile.getRealPath());
83 - File directory = realScriptFile.getParentDirectory();
84 + if (!realScriptFile.exists()) {
85 + std::string error = "File " + realScriptFile.getPath()
86 + + " referenced by symlink " +scriptFile.getPath()
87 + + " does not exist";
88 + logger.logWarning(error);
89 + throw SoftException(error, __FILE__, __LINE__);
92 // Check wheter script is in docroot
93 if (realScriptFile.getPath().find(config.getDocroot()) != 0) {
95 logger.logWarning(error);
96 throw SoftException(error, __FILE__, __LINE__);
98 + if (config.getCheckVHostDocroot()
99 + && scriptFile.getPath().find(environment.getVar("DOCUMENT_ROOT"))
102 + std::string error = "File \"" + scriptFile.getPath()
103 + + "\" is not in document root of Vhost \""
104 + + environment.getVar("DOCUMENT_ROOT") + "\"";
105 + logger.logWarning(error);
106 + throw SoftException(error, __FILE__, __LINE__);
109 - // Check script and directory permissions
110 + // Check script permissions
111 + // Directories will be checked later
112 if (!realScriptFile.hasUserReadBit()) {
113 std::string error = "File \"" + realScriptFile.getPath()
116 throw SoftException(error, __FILE__, __LINE__);
119 - if (!config.getAllowDirectoryGroupWriteable()
120 - && directory.hasGroupWriteBit()) {
121 - std::string error = "Directory \"" + directory.getPath()
122 - + "\" is writeable by group";
123 - logger.logWarning(error);
124 - throw SoftException(error, __FILE__, __LINE__);
127 if (!config.getAllowFileOthersWriteable()
128 && realScriptFile.hasOthersWriteBit()) {
129 std::string error = "File \"" + realScriptFile.getPath()
131 throw SoftException(error, __FILE__, __LINE__);
134 - if (!config.getAllowDirectoryOthersWriteable()
135 - && directory.hasOthersWriteBit()) {
136 - std::string error = "Directory \"" + directory.getPath()
137 - + "\" is writeable by others";
138 - logger.logWarning(error);
139 - throw SoftException(error, __FILE__, __LINE__);
142 // Check UID/GID of symlink is matching target
143 if (scriptFile.getUser() != realScriptFile.getUser()
144 || scriptFile.getGroup() != realScriptFile.getGroup()) {
147 GroupInfo targetGroup;
149 - File scriptFile = File(File(scriptFilename).getRealPath());
150 + File scriptFile = File(scriptFilename);
151 + File realScriptFile = File(scriptFile.getRealPath());
152 API& api = API_Helper::getSystemAPI();
153 Logger& logger = api.getSystemLogger();
156 throw SoftException(error, __FILE__, __LINE__);
158 #endif // OPT_USERGROUP_PARANOID
161 + // Check directory ownership and permissions
162 + checkParentDirectories(realScriptFile, targetUser, config);
163 + checkParentDirectories(scriptFile, targetUser, config);
165 // Common code used for all modes
167 // Set new group first, because we still need super-user privileges
172 +void suPHP::Application::checkParentDirectories(const File& file,
173 + const UserInfo& owner,
174 + const Configuration& config) const throw (SoftException) {
175 + File directory = file;
176 + Logger& logger = API_Helper::getSystemAPI().getSystemLogger();
178 + directory = directory.getParentDirectory();
180 + UserInfo directoryOwner = directory.getUser();
181 + if (directoryOwner != owner && !directoryOwner.isSuperUser()) {
182 + std::string error = "Directory " + directory.getPath()
183 + + " is not owned by " + owner.getUsername();
184 + logger.logWarning(error);
185 + throw SoftException(error, __FILE__, __LINE__);
188 + if (!directory.isSymlink()
189 + && !config.getAllowDirectoryGroupWriteable()
190 + && directory.hasGroupWriteBit()) {
191 + std::string error = "Directory \"" + directory.getPath()
192 + + "\" is writeable by group";
193 + logger.logWarning(error);
194 + throw SoftException(error, __FILE__, __LINE__);
197 + if (!directory.isSymlink()
198 + && !config.getAllowDirectoryOthersWriteable()
199 + && directory.hasOthersWriteBit()) {
200 + std::string error = "Directory \"" + directory.getPath()
201 + + "\" is writeable by others";
202 + logger.logWarning(error);
203 + throw SoftException(error, __FILE__, __LINE__);
205 + } while (directory.getPath() != "/");
209 int main(int argc, char **argv) {
211 API& api = API_Helper::getSystemAPI();
214 --- suphp-0.6.2.orig/src/API_Linux.cpp
215 +++ suphp-0.6.2/src/API_Linux.cpp
216 @@ -225,10 +225,10 @@
218 bool suPHP::API_Linux::File_exists(const File& file) const {
220 - if (::stat(file.getPath().c_str(), &dummy) == 0)
222 + if (::lstat(file.getPath().c_str(), &dummy) == 0)
229 std::string suPHP::API_Linux::File_getRealPath(const File& file) const
231 bool suPHP::API_Linux::File_hasPermissionBit(const File& file, FileMode perm)
232 const throw (SystemException) {
234 - if (stat(file.getPath().c_str(), &temp) == -1) {
235 + if (lstat(file.getPath().c_str(), &temp) == -1) {
236 throw SystemException(std::string("Could not stat \"")
237 + file.getPath() + "\": "
238 + ::strerror(errno), __FILE__, __LINE__);
240 UserInfo suPHP::API_Linux::File_getUser(const File& file) const
241 throw (SystemException) {
243 - if (stat(file.getPath().c_str(), &temp) == -1) {
244 + if (lstat(file.getPath().c_str(), &temp) == -1) {
245 throw SystemException(std::string("Could not stat \"")
246 + file.getPath() + "\": "
247 + ::strerror(errno), __FILE__, __LINE__);
249 GroupInfo suPHP::API_Linux::File_getGroup(const File& file) const
250 throw (SystemException) {
252 - if (stat(file.getPath().c_str(), &temp) == -1) {
253 + if (lstat(file.getPath().c_str(), &temp) == -1) {
254 throw SystemException(std::string("Could not stat \"")
255 + file.getPath() + "\": "
256 + ::strerror(errno), __FILE__, __LINE__);
261 +bool suPHP::API_Linux::File_isSymlink(const File& file) const throw (SystemException) {
262 + return this->isSymlink(file.getPath());
266 void suPHP::API_Linux::execute(std::string program, const CommandLine& cline,
267 const Environment& env) const
268 throw (SystemException) {
271 --- suphp-0.6.2.orig/src/File.hpp
272 +++ suphp-0.6.2/src/File.hpp
274 * Returns owning group of file
276 GroupInfo getGroup() const throw (SystemException);
280 + * Checks whether this file is a symlink
282 + bool isSymlink() const throw (SystemException);
288 --- suphp-0.6.2.orig/src/API.hpp
289 +++ suphp-0.6.2/src/API.hpp
291 virtual GroupInfo File_getGroup(const File& file) const
292 throw (SystemException) =0;
295 + * Checks whether a file is a symlink
297 + virtual bool File_isSymlink(const File& file) const
298 + throw (SystemException) =0;
301 * Runs another program (replaces current process)