su.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibCore/Account.h>
  7. #include <LibCore/ArgsParser.h>
  8. #include <LibCore/GetPassword.h>
  9. #include <stdio.h>
  10. #include <unistd.h>
  11. extern "C" int main(int, char**);
  12. int main(int argc, char** argv)
  13. {
  14. if (pledge("stdio rpath tty exec id", nullptr) < 0) {
  15. perror("pledge");
  16. return 1;
  17. }
  18. if (!isatty(STDIN_FILENO)) {
  19. warnln("{}: standard in is not a terminal", argv[0]);
  20. return 1;
  21. }
  22. const char* user = nullptr;
  23. Core::ArgsParser args_parser;
  24. args_parser.add_positional_argument(user, "User to switch to (defaults to user with UID 0)", "user", Core::ArgsParser::Required::No);
  25. args_parser.parse(argc, argv);
  26. if (geteuid() != 0) {
  27. warnln("Not running as root :(");
  28. return 1;
  29. }
  30. auto account_or_error = (user)
  31. ? Core::Account::from_name(user)
  32. : Core::Account::from_uid(0);
  33. if (account_or_error.is_error()) {
  34. warnln("Core::Account::from_name: {}", account_or_error.error());
  35. return 1;
  36. }
  37. if (pledge("stdio tty exec id", nullptr) < 0) {
  38. perror("pledge");
  39. return 1;
  40. }
  41. const auto& account = account_or_error.value();
  42. if (getuid() != 0 && account.has_password()) {
  43. auto password = Core::get_password();
  44. if (password.is_error()) {
  45. warnln("{}", password.error());
  46. return 1;
  47. }
  48. if (!account.authenticate(password.value().characters())) {
  49. warnln("Incorrect or disabled password.");
  50. return 1;
  51. }
  52. }
  53. if (pledge("stdio exec id", nullptr) < 0) {
  54. perror("pledge");
  55. return 1;
  56. }
  57. if (!account.login()) {
  58. perror("Core::Account::login");
  59. return 1;
  60. }
  61. if (pledge("stdio exec", nullptr) < 0) {
  62. perror("pledge");
  63. return 1;
  64. }
  65. execl(account.shell().characters(), account.shell().characters(), nullptr);
  66. perror("execl");
  67. return 1;
  68. }