r9183@datura: manu | 2008-06-04 09:59:07 +0200
[manu/suphp.git] / debian / patches / 04_CVE-2008-1614.dpatch
1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## 04_CVE-2008-1614.dpatch
3 ##
4 ## All lines beginning with `## DP:' are a description of the patch.
5 ## DP: Libtool update
6
7 @DPATCH@
8 --- suphp-0.6.2.orig/src/API_Linux.hpp
9 +++ suphp-0.6.2/src/API_Linux.hpp
10 @@ -169,6 +169,11 @@
11         virtual GroupInfo File_getGroup(const File& file) const
12             throw (SystemException);
13  
14 +        /**
15 +         * Checks whether a file is a symlink
16 +         */
17 +        virtual bool File_isSymlink(const File& file) const throw (SystemException);
18 +        
19         /**
20          * Runs another program (replaces current process)
21          */
22 only in patch2:
23 unchanged:
24 --- suphp-0.6.2.orig/src/File.cpp
25 +++ suphp-0.6.2/src/File.cpp
26 @@ -57,6 +57,9 @@
27  File suPHP::File::getParentDirectory() const {
28      std::string path = this->getPath();
29      path = path.substr(0, path.rfind('/'));
30 +    if (path.length() == 0) {
31 +        path = "/";
32 +    }
33      return File(path);
34  }
35  
36 @@ -104,3 +107,7 @@
37  GroupInfo suPHP::File::getGroup() const throw (SystemException) {
38      return API_Helper::getSystemAPI().File_getGroup(*this);
39  }
40 +
41 +bool suPHP::File::isSymlink() const throw (SystemException) {
42 +    return API_Helper::getSystemAPI().File_isSymlink(*this);
43 +}
44 only in patch2:
45 unchanged:
46 --- suphp-0.6.2.orig/src/Application.hpp
47 +++ suphp-0.6.2/src/Application.hpp
48 @@ -107,6 +107,14 @@
49                            const Configuration& config) const
50             throw (SoftException);
51  
52 +         
53 +         /**
54 +          * Checks ownership and permissions for parent directories
55 +          */
56 +         void checkParentDirectories(const File& file,
57 +                                     const UserInfo& owner,
58 +                                     const Configuration& config) const
59 +             throw (SoftException);
60  
61      public:
62         /**
63 only in patch2:
64 unchanged:
65 --- suphp-0.6.2.orig/src/Application.cpp
66 +++ suphp-0.6.2/src/Application.cpp
67 @@ -177,6 +177,7 @@
68      throw (SystemException, SoftException) {
69      Logger& logger = API_Helper::getSystemAPI().getSystemLogger();
70      File scriptFile = File(scriptFilename);
71 +    File realScriptFile = File(scriptFile.getRealPath());
72  
73      // Check wheter file exists
74      if (!scriptFile.exists()) {
75 @@ -184,11 +185,13 @@
76         logger.logWarning(error);
77         throw SoftException(error, __FILE__, __LINE__);
78      }
79 -    
80 -    // Get full path to script file
81 -
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__);
90 +    }
91      
92      // Check wheter script is in docroot
93      if (realScriptFile.getPath().find(config.getDocroot()) != 0) {
94 @@ -213,8 +216,19 @@
95         logger.logWarning(error);
96         throw SoftException(error, __FILE__, __LINE__);
97      }
98 +    if (config.getCheckVHostDocroot()
99 +        && scriptFile.getPath().find(environment.getVar("DOCUMENT_ROOT")) 
100 +        != 0) {
101 +        
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__);
107 +    }
108  
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()
114             + "\" not readable";
115 @@ -231,14 +245,6 @@
116         throw SoftException(error, __FILE__, __LINE__);
117      }
118      
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__);
125 -    }
126 -
127      if (!config.getAllowFileOthersWriteable()
128         && realScriptFile.hasOthersWriteBit()) {
129         std::string error = "File \"" + realScriptFile.getPath()
130 @@ -247,14 +253,6 @@
131         throw SoftException(error, __FILE__, __LINE__);
132      }
133      
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__);
140 -    }
141 -
142      // Check UID/GID of symlink is matching target
143      if (scriptFile.getUser() != realScriptFile.getUser()
144         || scriptFile.getGroup() != realScriptFile.getGroup()) {
145 @@ -274,7 +272,8 @@
146      UserInfo targetUser;
147      GroupInfo targetGroup;
148  
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();
154  
155 @@ -360,7 +359,11 @@
156         throw SoftException(error, __FILE__, __LINE__);
157      }
158  #endif // OPT_USERGROUP_PARANOID    
159 -
160 +    
161 +    // Check directory ownership and permissions
162 +    checkParentDirectories(realScriptFile, targetUser, config);
163 +    checkParentDirectories(scriptFile, targetUser, config);
164 +    
165      // Common code used for all modes
166  
167      // Set new group first, because we still need super-user privileges
168 @@ -480,6 +483,43 @@
169  }
170  
171  
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();
177 +    do {
178 +        directory = directory.getParentDirectory();
179 +        
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__);
186 +        }
187 +        
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__);
195 +        }
196 +        
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__);
204 +        }
205 +    } while (directory.getPath() != "/");
206 +}
207 +
208 +
209  int main(int argc, char **argv) {
210      try {
211         API& api = API_Helper::getSystemAPI();
212 only in patch2:
213 unchanged:
214 --- suphp-0.6.2.orig/src/API_Linux.cpp
215 +++ suphp-0.6.2/src/API_Linux.cpp
216 @@ -225,10 +225,10 @@
217  
218  bool suPHP::API_Linux::File_exists(const File& file) const {
219      struct stat dummy;
220 -    if (::stat(file.getPath().c_str(), &dummy) == 0)
221 -       return true;
222 +    if (::lstat(file.getPath().c_str(), &dummy) == 0)
223 +        return true;
224      else
225 -       return false;
226 +        return false;
227  }
228  
229  std::string suPHP::API_Linux::File_getRealPath(const File& file) const
230 @@ -304,7 +304,7 @@
231  bool suPHP::API_Linux::File_hasPermissionBit(const File& file, FileMode perm) 
232      const throw (SystemException) {
233      struct stat temp;
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__);
239 @@ -362,7 +362,7 @@
240  UserInfo suPHP::API_Linux::File_getUser(const File& file) const
241      throw (SystemException) {
242      struct stat temp;
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__);
248 @@ -373,7 +373,7 @@
249  GroupInfo suPHP::API_Linux::File_getGroup(const File& file) const
250      throw (SystemException) {
251      struct stat temp;
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__);
257 @@ -382,6 +382,11 @@
258  }
259  
260  
261 +bool suPHP::API_Linux::File_isSymlink(const File& file) const throw (SystemException) {
262 +    return this->isSymlink(file.getPath());
263 +}
264 +
265 +
266  void suPHP::API_Linux::execute(std::string program, const CommandLine& cline,
267                                const Environment& env) const
268      throw (SystemException) {
269 only in patch2:
270 unchanged:
271 --- suphp-0.6.2.orig/src/File.hpp
272 +++ suphp-0.6.2/src/File.hpp
273 @@ -143,7 +143,11 @@
274          * Returns owning group of file
275          */
276         GroupInfo getGroup() const throw (SystemException);
277 -       
278 +
279 +        /**
280 +         * Checks whether this file is a symlink
281 +         */
282 +        bool isSymlink() const throw (SystemException);
283      };
284  };
285  
286 only in patch2:
287 unchanged:
288 --- suphp-0.6.2.orig/src/API.hpp
289 +++ suphp-0.6.2/src/API.hpp
290 @@ -157,6 +157,12 @@
291         virtual GroupInfo File_getGroup(const File& file) const
292             throw (SystemException) =0;
293         
294 +        /**
295 +         * Checks whether a file is a symlink
296 +         */
297 +        virtual bool File_isSymlink(const File& file) const 
298 +            throw (SystemException) =0;
299 +        
300         /**
301          * Runs another program (replaces current process)
302          */