Lines 52-57
Link Here
|
52 |
#include <deque> |
52 |
#include <deque> |
53 |
#include <list> |
53 |
#include <list> |
54 |
#include <cstdlib> |
54 |
#include <cstdlib> |
|
|
55 |
#include <sys/stat.h> |
56 |
#include <pwd.h> |
57 |
#include <grp.h> |
58 |
#include <netdb.h> |
55 |
|
59 |
|
56 |
namespace po = boost::program_options; |
60 |
namespace po = boost::program_options; |
57 |
using namespace std; |
61 |
using namespace std; |
Lines 340-345
Link Here
|
340 |
} |
344 |
} |
341 |
|
345 |
|
342 |
bool |
346 |
bool |
|
|
347 |
Daemon::droppriv(std::string const& chrootdir, std::string const& user, std::string const& group) |
348 |
{ |
349 |
uid_t uid = 0; |
350 |
uid_t gid = 0; |
351 |
|
352 |
if (!chrootdir.empty() || !user.empty() || !group.empty()) { |
353 |
struct stat stat_r; |
354 |
struct passwd *user_r; |
355 |
struct group *group_r; |
356 |
|
357 |
if (getuid()) { |
358 |
std::cerr << "Cannot lower privileges, not running as root" << std::endl; |
359 |
return false; |
360 |
} |
361 |
if (!chrootdir.empty() && stat(chrootdir.c_str(), &stat_r)) { |
362 |
if (!S_ISDIR(stat_r.st_mode)) { |
363 |
std::cerr << "Cannot lower privileges, chroot directory does not exist" << std::endl; |
364 |
return false; |
365 |
} |
366 |
} |
367 |
if (!user.empty()) { |
368 |
user_r = getpwnam(user.c_str()); |
369 |
if (user_r) { |
370 |
uid = user_r->pw_uid; |
371 |
} else { |
372 |
std::cerr << "Cannot lower privileges, unknown user" << std::endl; |
373 |
return false; |
374 |
} |
375 |
} |
376 |
if (!group.empty()) { |
377 |
group_r = getgrnam(group.c_str()); |
378 |
if (group_r) { |
379 |
gid = group_r->gr_gid; |
380 |
} else { |
381 |
std::cerr << "Cannot lower privileges, unknown group" << std::endl; |
382 |
return false; |
383 |
} |
384 |
} |
385 |
} |
386 |
|
387 |
if (!chrootdir.empty()) { |
388 |
// Using gethostbyname before chrooting means that the chroot |
389 |
// directory can be empty (no etc/resolv.conf or dynamically |
390 |
// loaded lib/libnss* libraries). Using localhost here to |
391 |
// prevent remote name resolution does not work. |
392 |
gethostbyname("slashdot.org"); |
393 |
if (chroot(chrootdir.c_str())) { |
394 |
std::cerr << "Cannot lower privileges, chroot directory no longer exists" << std::endl; |
395 |
return false; |
396 |
} |
397 |
chdir("/"); |
398 |
} |
399 |
if (gid) { |
400 |
setgroups(0, NULL); |
401 |
setgid(gid); |
402 |
} |
403 |
if (uid) { |
404 |
setuid(uid); |
405 |
} |
406 |
return true; |
407 |
} |
408 |
|
409 |
bool |
343 |
Daemon::run(bool nodaemon) |
410 |
Daemon::run(bool nodaemon) |
344 |
{ |
411 |
{ |
345 |
if (!nodaemon) { |
412 |
if (!nodaemon) { |
Lines 447-459
Link Here
|
447 |
{ |
514 |
{ |
448 |
bool nodaemon = false; |
515 |
bool nodaemon = false; |
449 |
std::string confdir = string(SYSCONFDIR) + "/bfilter"; |
516 |
std::string confdir = string(SYSCONFDIR) + "/bfilter"; |
450 |
|
517 |
std::string chrootdir; |
|
|
518 |
std::string user; |
519 |
std::string group; |
520 |
|
451 |
try { |
521 |
try { |
452 |
po::options_description desc("Allowed options"); |
522 |
po::options_description desc("Allowed options"); |
453 |
desc.add_options() |
523 |
desc.add_options() |
454 |
("help,h", "Print help message") |
524 |
("help,h", "Print help message") |
455 |
("version,v", "Print version") |
525 |
("version,v", "Print version") |
456 |
("confdir,c", po::value<string>(&confdir), "Set custom config directory") |
526 |
("confdir,c", po::value<string>(&confdir), "Set custom config directory") |
|
|
527 |
("chroot,r", po::value<string>(&chrootdir), "Set chroot directory") |
528 |
("user,u", po::value<string>(&user), "Set unprivileged user") |
529 |
("group,g", po::value<string>(&group), "Set unprivileged group") |
457 |
("nodaemon,n", po::bool_switch(&nodaemon), "Disable background daemon mode") |
530 |
("nodaemon,n", po::bool_switch(&nodaemon), "Disable background daemon mode") |
458 |
; |
531 |
; |
459 |
po::variables_map vm; |
532 |
po::variables_map vm; |
Lines 476-481
Link Here
|
476 |
if (!daemon.init(confdir)) { |
549 |
if (!daemon.init(confdir)) { |
477 |
exit(EXIT_FAILURE); |
550 |
exit(EXIT_FAILURE); |
478 |
} |
551 |
} |
|
|
552 |
if (!daemon.droppriv(chrootdir, user, group)) { |
553 |
exit(EXIT_FAILURE); |
554 |
} |
479 |
if (!daemon.run(nodaemon)) { |
555 |
if (!daemon.run(nodaemon)) { |
480 |
exit(EXIT_FAILURE); |
556 |
exit(EXIT_FAILURE); |
481 |
} |
557 |
} |