48
48
throw (SystemException) {
50
50
if (lstat(path.c_str(), &temp) == -1) {
51
throw SystemException(std::string("Could not stat \"")
53
+ ::strerror(errno), __FILE__, __LINE__);
51
throw SystemException(std::string("Could not stat \"")
53
+ ::strerror(errno), __FILE__, __LINE__);
55
55
if ((temp.st_mode & S_IFLNK) == S_IFLNK) {
61
61
std::string suPHP::API_Linux::readSymlink(const std::string path) const
62
62
throw (SystemException) {
63
63
char buf[1024] = {0};
64
64
if (::readlink(path.c_str(), buf, 1023) == -1) {
65
throw SystemException(std::string("Could not read symlink \"")
67
+ ::strerror(errno), __FILE__, __LINE__);
65
throw SystemException(std::string("Could not read symlink \"")
67
+ ::strerror(errno), __FILE__, __LINE__);
70
70
if (buf[0] == '/') {
71
return std::string(buf);
71
return std::string(buf);
73
if (path.rfind('/') == std::string::npos)
74
return std::string(buf);
75
return path.substr(0, path.rfind('/') + 1) + std::string(buf);
73
if (path.rfind('/') == std::string::npos)
74
return std::string(buf);
75
return path.substr(0, path.rfind('/') + 1) + std::string(buf);
81
81
char **entry = ::environ;
82
82
while (*entry != NULL) {
83
std::string estr = std::string(*entry);
84
int eqpos = estr.find("=");
85
std::string name = estr.substr(0, eqpos);
86
std::string content = estr.substr(eqpos + 1);
87
env.putVar(name, content);
83
std::string estr = std::string(*entry);
84
int eqpos = estr.find("=");
85
std::string name = estr.substr(0, eqpos);
86
std::string content = estr.substr(eqpos + 1);
87
env.putVar(name, content);
150
150
throw (SystemException) {
151
151
// Reset supplementary groups
152
152
if (::setgroups(0, NULL) == -1) {
153
throw SystemException(std::string("setgroups() failed: ")
154
+ ::strerror(errno), __FILE__, __LINE__);
153
throw SystemException(std::string("setgroups() failed: ")
154
+ ::strerror(errno), __FILE__, __LINE__);
158
if (::initgroups(user.getUsername().c_str(),
159
user.getGroupInfo().getGid())
161
throw SystemException(std::string("initgroups() failed: ")
162
+ ::strerror(errno), __FILE__, __LINE__);
158
if (::initgroups(user.getUsername().c_str(),
159
user.getGroupInfo().getGid())
161
throw SystemException(std::string("initgroups() failed: ")
162
+ ::strerror(errno), __FILE__, __LINE__);
164
164
} catch (LookupException &e) {
165
// Ignore this exception
166
// If we have a UID, which does not exist in /etc/passwd
167
// we simply cannot use supplementary groups
165
// Ignore this exception
166
// If we have a UID, which does not exist in /etc/passwd
167
// we simply cannot use supplementary groups
170
170
if (::setuid(user.getUid()) == -1) {
171
throw SystemException(std::string("setuid() failed: ")
172
+ ::strerror(errno), __FILE__, __LINE__);
171
throw SystemException(std::string("setuid() failed: ")
172
+ ::strerror(errno), __FILE__, __LINE__);
198
198
struct passwd *tmpuser = NULL;
199
199
tmpuser = getpwuid(uinfo.getUid());
200
200
if (tmpuser == NULL) {
201
throw LookupException(std::string("Could not lookup UID ")
202
+ Util::intToStr(uinfo.getUid()),
201
throw LookupException(std::string("Could not lookup UID ")
202
+ Util::intToStr(uinfo.getUid()),
205
205
return GroupInfo(tmpuser->pw_gid);
208
std::string suPHP::API_Linux::UserInfo_getHomeDirectory(const UserInfo& uinfo) const
209
throw (LookupException) {
210
struct passwd *tmpuser = NULL;
211
tmpuser = getpwuid(uinfo.getUid());
212
if (tmpuser == NULL) {
213
throw LookupException(std::string("Could not lookup UID ")
214
+ Util::intToStr(uinfo.getUid()),
217
return tmpuser->pw_dir;
208
220
bool suPHP::API_Linux::UserInfo_isSuperUser(const UserInfo& uinfo) const {
209
221
if (uinfo.getUid() == 0)
215
227
std::string suPHP::API_Linux::GroupInfo_getGroupname(const GroupInfo& ginfo)
216
228
const throw (LookupException) {
217
229
struct group *tmpgroup = ::getgrgid(ginfo.getGid());
218
230
if (tmpgroup == NULL) {
219
throw LookupException(std::string("Could not lookup GID ")
220
+ Util::intToStr(ginfo.getGid()),
231
throw LookupException(std::string("Could not lookup GID ")
232
+ Util::intToStr(ginfo.getGid()),
223
235
return std::string(tmpgroup->gr_name);
226
238
bool suPHP::API_Linux::File_exists(const File& file) const {
227
239
struct stat dummy;
228
if (::stat(file.getPath().c_str(), &dummy) == 0)
240
if (::lstat(file.getPath().c_str(), &dummy) == 0)
234
246
std::string suPHP::API_Linux::File_getRealPath(const File& file) const
238
250
bool failed = true;
240
252
if ((currentpath.size() == 0) || (currentpath.at(0) != '/')) {
241
currentpath = this->getCwd() + std::string("/") + currentpath;
253
currentpath = this->getCwd() + std::string("/") + currentpath;
244
256
// Limit iterations to avoid infinite symlink loops
245
257
for (int i=0; i<512; i++) {
246
// If nothing is left, we have finished
247
if (currentpath.size() == 0) {
248
resolvedpath = ("/" + resolvedpath);
253
if (this->isSymlink(currentpath)) {
254
currentpath = this->readSymlink(currentpath);
256
// We know last part is not a symlink, so it is resolved
258
currentpath.substr(0, currentpath.rfind('/'));
260
currentpath.substr(currentpath.rfind('/')+1);
262
if (resolvedpath.size() == 0)
263
resolvedpath = part2;
265
resolvedpath = part2 + "/" + resolvedpath;
258
// If nothing is left, we have finished
259
if (currentpath.size() == 0) {
260
resolvedpath = ("/" + resolvedpath);
265
if (this->isSymlink(currentpath)) {
266
currentpath = this->readSymlink(currentpath);
268
// We know last part is not a symlink, so it is resolved
270
currentpath.substr(0, currentpath.rfind('/'));
272
currentpath.substr(currentpath.rfind('/')+1);
274
if (resolvedpath.size() == 0)
275
resolvedpath = part2;
277
resolvedpath = part2 + "/" + resolvedpath;
270
throw SystemException("Could not resolve path \"" +
271
file.getPath() + "\"", __FILE__, __LINE__);
282
throw SystemException("Could not resolve path \"" +
283
file.getPath() + "\"", __FILE__, __LINE__);
274
286
while (resolvedpath.find("/./") != std::string::npos) {
275
int pos = resolvedpath.find("/./");
276
resolvedpath = resolvedpath.substr(0, pos)
277
+ resolvedpath.substr(pos + 2);
287
int pos = resolvedpath.find("/./");
288
resolvedpath = resolvedpath.substr(0, pos)
289
+ resolvedpath.substr(pos + 2);
280
292
while (resolvedpath.find("/../") != std::string::npos) {
281
int pos = resolvedpath.find("/../");
282
int pos2 = resolvedpath.rfind('/', pos-1);
283
resolvedpath = resolvedpath.substr(0, pos2)
284
+ resolvedpath.substr(pos + 3);
293
int pos = resolvedpath.find("/../");
294
int pos2 = resolvedpath.rfind('/', pos-1);
295
resolvedpath = resolvedpath.substr(0, pos2)
296
+ resolvedpath.substr(pos + 3);
287
299
if (resolvedpath.find("/..", resolvedpath.size() - 3)
288
!= std::string::npos) {
289
resolvedpath = resolvedpath.substr(0, resolvedpath.size() - 3);
290
resolvedpath = resolvedpath.substr(0, resolvedpath.rfind('/'));
300
!= std::string::npos) {
301
resolvedpath = resolvedpath.substr(0, resolvedpath.size() - 3);
302
resolvedpath = resolvedpath.substr(0, resolvedpath.rfind('/'));
293
305
if (resolvedpath.find("/.", resolvedpath.size() - 2)
294
!= std::string::npos) {
295
resolvedpath = resolvedpath.substr(0, resolvedpath.size() - 2);
306
!= std::string::npos) {
307
resolvedpath = resolvedpath.substr(0, resolvedpath.size() - 2);
298
310
if (resolvedpath.size() == 0)
301
313
return resolvedpath;
304
316
bool suPHP::API_Linux::File_hasPermissionBit(const File& file, FileMode perm)
305
317
const throw (SystemException) {
306
318
struct stat temp;
307
if (stat(file.getPath().c_str(), &temp) == -1) {
308
throw SystemException(std::string("Could not stat \"")
309
+ file.getPath() + "\": "
310
+ ::strerror(errno), __FILE__, __LINE__);
319
if (lstat(file.getPath().c_str(), &temp) == -1) {
320
throw SystemException(std::string("Could not stat \"")
321
+ file.getPath() + "\": "
322
+ ::strerror(errno), __FILE__, __LINE__);
313
325
case FILEMODE_USER_READ:
314
if ((temp.st_mode & S_IRUSR) == S_IRUSR)
326
if ((temp.st_mode & S_IRUSR) == S_IRUSR)
318
330
case FILEMODE_USER_WRITE:
319
if ((temp.st_mode & S_IWUSR) == S_IWUSR)
331
if ((temp.st_mode & S_IWUSR) == S_IWUSR)
323
335
case FILEMODE_USER_EXEC:
324
if ((temp.st_mode & S_IXUSR) == S_IXUSR)
336
if ((temp.st_mode & S_IXUSR) == S_IXUSR)
328
340
case FILEMODE_GROUP_READ:
329
if ((temp.st_mode & S_IRGRP) == S_IRGRP)
341
if ((temp.st_mode & S_IRGRP) == S_IRGRP)
333
345
case FILEMODE_GROUP_WRITE:
334
if ((temp.st_mode & S_IWGRP) == S_IWGRP)
346
if ((temp.st_mode & S_IWGRP) == S_IWGRP)
338
350
case FILEMODE_GROUP_EXEC:
339
if ((temp.st_mode & S_IXGRP) == S_IXGRP)
351
if ((temp.st_mode & S_IXGRP) == S_IXGRP)
343
355
case FILEMODE_OTHERS_READ:
344
if ((temp.st_mode & S_IROTH) == S_IROTH)
356
if ((temp.st_mode & S_IROTH) == S_IROTH)
348
360
case FILEMODE_OTHERS_WRITE:
349
if ((temp.st_mode & S_IWOTH) == S_IWOTH)
361
if ((temp.st_mode & S_IWOTH) == S_IWOTH)
353
365
case FILEMODE_OTHERS_EXEC:
354
if ((temp.st_mode & S_IXOTH) == S_IXOTH)
366
if ((temp.st_mode & S_IXOTH) == S_IXOTH)
362
374
UserInfo suPHP::API_Linux::File_getUser(const File& file) const
363
375
throw (SystemException) {
364
376
struct stat temp;
365
if (stat(file.getPath().c_str(), &temp) == -1) {
366
throw SystemException(std::string("Could not stat \"")
367
+ file.getPath() + "\": "
368
+ ::strerror(errno), __FILE__, __LINE__);
377
if (lstat(file.getPath().c_str(), &temp) == -1) {
378
throw SystemException(std::string("Could not stat \"")
379
+ file.getPath() + "\": "
380
+ ::strerror(errno), __FILE__, __LINE__);
370
382
return UserInfo(temp.st_uid);
373
385
GroupInfo suPHP::API_Linux::File_getGroup(const File& file) const
374
386
throw (SystemException) {
375
387
struct stat temp;
376
if (stat(file.getPath().c_str(), &temp) == -1) {
377
throw SystemException(std::string("Could not stat \"")
378
+ file.getPath() + "\": "
379
+ ::strerror(errno), __FILE__, __LINE__);
388
if (lstat(file.getPath().c_str(), &temp) == -1) {
389
throw SystemException(std::string("Could not stat \"")
390
+ file.getPath() + "\": "
391
+ ::strerror(errno), __FILE__, __LINE__);
381
393
return GroupInfo(temp.st_gid);
397
bool suPHP::API_Linux::File_isSymlink(const File& file) const throw (SystemException) {
398
return this->isSymlink(file.getPath());
385
402
void suPHP::API_Linux::execute(std::string program, const CommandLine& cline,
386
const Environment& env) const
403
const Environment& env) const
387
404
throw (SystemException) {
388
405
char **sysCline = NULL;
389
406
char **sysEnv = NULL;
397
414
// Construct commandline
398
415
sysCline = new char*[cline.size() + 1];
399
416
for (i=0; i<cline.size(); i++) {
400
std::string arg = cline.getArgument(i);
401
sysCline[i] = new char[arg.size()+1];
402
::strncpy(sysCline[i], arg.c_str(), arg.size()+1);
417
std::string arg = cline.getArgument(i);
418
sysCline[i] = new char[arg.size()+1];
419
::strncpy(sysCline[i], arg.c_str(), arg.size()+1);
404
421
sysCline[cline.size()] = NULL;
408
425
sysEnv = new char*[map.size() + 1];
410
427
for (std::map<std::string, std::string>::iterator pos = map.begin();
414
var = pos->first + "=" + pos->second;
415
*p = new char[var.size()+1];
416
::strncpy(*p, var.c_str(), var.size()+1);
431
var = pos->first + "=" + pos->second;
432
*p = new char[var.size()+1];
433
::strncpy(*p, var.c_str(), var.size()+1);
422
439
sysProgram = new char[program.size() + 1];
423
440
::strncpy(sysProgram, program.c_str(), program.size()+1);
424
441
if (execve(sysProgram, sysCline, sysEnv) == -1) {
425
throw SystemException("execve() for program \"" + program
426
+ "\" failed: " + ::strerror(errno),
442
throw SystemException("execve() for program \"" + program
443
+ "\" failed: " + ::strerror(errno),
430
447
// We are still here? This cannot be good..
431
448
throw SystemException("execve() for program \"" + program
432
+ "\" failed because of unknown reason",
449
+ "\" failed because of unknown reason",
436
453
std::string suPHP::API_Linux::getCwd() const throw (SystemException) {
437
454
char buf[4096] = {0};
438
455
if (::getcwd(buf, 4095) == NULL)
439
throw SystemException(std::string("getcwd() failed: ")
440
+ ::strerror(errno), __FILE__, __LINE__);
456
throw SystemException(std::string("getcwd() failed: ")
457
+ ::strerror(errno), __FILE__, __LINE__);
441
458
return std::string(buf);
444
461
void suPHP::API_Linux::setCwd(const std::string& dir) const
445
462
throw (SystemException) {
446
463
if(::chdir(dir.c_str())) {
447
throw SystemException(std::string("chdir() failed: ")
448
+ ::strerror(errno), __FILE__, __LINE__);
464
throw SystemException(std::string("chdir() failed: ")
465
+ ::strerror(errno), __FILE__, __LINE__);