1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 | // Copyright (C) 2021-2025 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef KEA_UTIL_FILESYSTEM_H
#define KEA_UTIL_FILESYSTEM_H
#include <exceptions/exceptions.h>
#include <sys/stat.h>
#include <string>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace util {
namespace file {
/// @brief A generic exception that is thrown if a parameter given
/// violates security check but enforcement is lax.
class SecurityWarn : public Exception {
public:
SecurityWarn(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief A generic exception that is thrown if a parameter given
/// violates security and enforcement is true.
class SecurityError : public Exception {
public:
SecurityError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Get the content of a regular file.
///
/// @param file_name The file name.
///
/// @return The content of the file.
/// @throw BadValue when the file can't be opened or is not a regular one.
std::string
getContent(const std::string& file_name);
/// @brief Check if there is a file or directory at the given path.
///
/// @param path The path being checked.
///
/// @return True if the path points to a file or a directory, false otherwise.
bool
exists(const std::string& path);
/// @brief Fetches the file permissions mask.
///
/// @param path The path being checked.
/// @return File permissios mask or 0 if the path does not exist.
mode_t
getPermissions(const std::string path);<--- Function parameter 'path' should be passed by const reference.
/// @brief Check if there if file or directory has the given permissions.
///
/// @param path The path being checked.
/// @param permissions mask of expected permissions.
///
/// @return True if the path points to a file or a directory, false otherwise.
bool
hasPermissions(const std::string path, const mode_t& permissions);<--- Function parameter 'path' should be passed by const reference.
/// @brief Check if there is a directory at the given path.
///
/// @param path The path being checked.
///
/// @return True if the path points to a directory, false otherwise including
/// if the pointed location does not exist.
bool
isDir(const std::string& path);
/// @brief Check if there is a file at the given path.
///
/// @param path The path being checked.
///
/// @return True if the path points to a file, false otherwise including
/// if the pointed location does not exist.
bool
isFile(const std::string& path);
/// @brief Check if there is a socket at the given path.
///
/// @param path The path being checked.
///
/// @return True if the path points to a socket, false otherwise including
/// if the pointed location does not exist.
bool
isSocket(const std::string& path);
/// @brief Set umask (at least 0027 i.e. no group write and no other access).
void
setUmask();
/// @brief Indicates if current user is root
///
/// @return True if either the uid or the effective
/// uid is root.
bool
amRunningAsRoot();
/// @brief Paths on a filesystem
struct Path {
/// @brief Constructor
///
/// Splits the full name into components.
Path(std::string const& path);<--- Struct 'Path' has a constructor with 1 argument that is not explicit. [+]Struct 'Path' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions.
/// @brief Get the path in textual format.
///
/// Counterpart for std::filesystem::path::string.
///
/// @return stored filename.
std::string str() const;
/// @brief Get the parent path.
///
/// Counterpart for std::filesystem::path::parent_path.
///
/// @return parent path of current path.
std::string parentPath() const;
/// @brief Get the parent directory.
///
/// Empty if no directory is present, the parent path follwed by
/// a slash otherwise.
///
/// @return parent directory of current path.
std::string parentDirectory() const;
/// @brief Get the base name of the file without the extension.
///
/// Counterpart for std::filesystem::path::stem.
///
/// @return the base name of current path without the extension.
std::string stem() const;
/// @brief Get the extension of the file.
///
/// Counterpart for std::filesystem::path::extension.
///
/// @return extension of current path.
std::string extension() const;
/// @brief Get the name of the file, extension included.
///
/// Counterpart for std::filesystem::path::filename.
///
/// @return name + extension of current path.
std::string filename() const;
/// @brief Identifies the extension in {replacement}, trims it, and
/// replaces this instance's extension with it.
///
/// Counterpart for std::filesystem::path::replace_extension.
///
/// The change is done in the members and {this} is returned to allow call
/// chaining.
///
/// @param replacement The extension to replace with.
///
/// @return The current instance after the replacement was done.
Path& replaceExtension(std::string const& replacement = std::string());
/// @brief Trims {replacement} and replaces this instance's parent path with
/// it.
///
/// The change is done in the members and {this} is returned to allow call
/// chaining.
///
/// @param replacement The parent path to replace with.
///
/// @return The current instance after the replacement was done.
Path& replaceParentPath(std::string const& replacement = std::string());
private:
/// @brief Is a directory present.
bool dir_present_;
/// @brief Parent path.
std::string parent_path_;
/// @brief Stem.
std::string stem_;
/// @brief File name extension.
std::string extension_;
};
struct TemporaryDirectory {
TemporaryDirectory();
~TemporaryDirectory();
std::string dirName();
private:
std::string dir_name_;
};
/// @brief Embodies a supported path against which file paths can be validated.
class PathChecker {
public:
/// @brief Constructor.
///
/// Makes a call to getPath(true) to initialize the supported path.
///
/// @param default_path path to use unless overridden by explicitly or via
/// environment variable.
/// @param env_name name of environment variable (if one), that can override
/// the default path.
PathChecker(const std::string default_path, const std::string env_name = "");<--- Class 'PathChecker' has a constructor with 1 argument that is not explicit. [+]Class 'PathChecker' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions. <--- Function parameter 'default_path' should be passed by const reference.<--- Function parameter 'env_name' should be passed by const reference.
/// @brief Destructor.
virtual ~PathChecker() {};
/// @brief Fetches the supported path.
///
/// When called with reset=true it will calculate the supported path as
/// follows:
///
/// 1. Use the value of explicit_path parameter if not blank
/// 2. Use the value of the environment variable, if one is provided and it
/// is defined in the environment
/// 3. Use the value of default path.
///
/// @param reset recalculate when true, defaults to false.
/// @param explicit_path set the default path to this value. This is
/// for testing purposes only.
///
/// @return String containing the default path.
std::string getPath(bool reset = false, const std::string explicit_path = "");<--- Function parameter 'explicit_path' should be passed by const reference.
/// @brief Validates a file path against a supported path.
///
/// If the input path specifies a parent path and file name, the parent path
/// is validated against the supported path. If they match, the function returns
/// the validated path. If the input path contains only a file name the function
/// returns valid path using the supported path and the input path name.
///
/// @param input_path_str file path to validate.
/// @param enforce_path If true throw SecurityError when validation against the
/// supported path fails, if false throw SecurityWarn.
///
/// @return validated path as a string (supported path + input file name)
///
/// @throw BadValue if the input path does not include a file name.
/// @throw SecurityError if the parent path does not path the supported path and
/// security is being enforced, SecurityWarn if it is not being enforced.
std::string validatePath(const std::string input_path_str,<--- Function parameter 'input_path_str' should be passed by const reference.
bool enforce_path = shouldEnforceSecurity()) const;
/// @brief Validates a directory against a supported path.
///
/// Used to validate a string that represents a directory that may or
/// may not end with a "/" (i.e "/foo/bar", bar is assumed to be the
/// a directory, not a file.
///
/// If the input is empty or it matches the supported path, it returns
/// the supported path. Otherwise it throws an error.
///
/// @param input_path_str file path to validate.
/// @param enforce_path If true throw SecurityError when validation against the
/// supported path fails, if false throw SecurityWarn.
///
/// @return validated path
///
/// @throw SecurityError if the path does not match the supported path and
/// security is being enforced, SecurityWarn if it is not being enforced.
std::string validateDirectory(const std::string input_path_str,<--- Function parameter 'input_path_str' should be passed by const reference.
bool enforce_path = shouldEnforceSecurity()) const;
/// @brief Check if the path has expected permissions.
///
/// @param permissions The expected permissions.
/// @param enforce_perms Enables permsissions check. If false the function
/// simply returns true.
///
/// @return True if the path points to a file or a directory, false otherwise.
bool pathHasPermissions(mode_t permissions,
bool enforce_perms = shouldEnforceSecurity()) const;
/// @brief Fetches the default path.
std::string getDefaultPath() const {<--- Function 'getDefaultPath()' should return member 'default_path_' by const reference.
return (default_path_);
}
/// @brief Fetches the environment variable name.
std::string getEnvName() const {<--- Function 'getEnvName()' should return member 'env_name_' by const reference.<--- The function 'getEnvName' is never used.
return (env_name_);
}
/// @brief Indicates if the default path has been overridden.
bool isDefaultOverridden();
/// @brief Indicates security checks should be enforced.
static bool shouldEnforceSecurity();
/// @brief Enables or disables security enforcment checks.
///
/// @param enable true to enable security checks, false to disable.
static void enableEnforcement(bool enable);
private:
/// @brief Default supported path.
std::string default_path_;
/// @brief Name of environment variable (if one) that can override the default.
std::string env_name_;
/// @brief The supported path currently in effect.
std::string path_;
/// @brief Tracks if default has been overridden.
bool default_overridden_;
/// @brief True if security checks should be enforced, false if not.
static bool enforce_security_;
};
/// @brief Defines a pointer to a PathChecker.
typedef boost::shared_ptr<PathChecker> PathCheckerPtr;
} // namespace file
} // namespace util
} // namespace isc
#endif // KEA_UTIL_FILESYSTEM_H
|