Serenity Operating System
at master 99 lines 3.2 kB view raw
1/* 2 * Copyright (c) 2020, Peter Elliott <pelliott@serenityos.org> 3 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <AK/ScopeGuard.h> 9#include <LibCore/Account.h> 10#include <LibCore/ArgsParser.h> 11#include <LibCore/GetPassword.h> 12#include <LibCore/System.h> 13#include <LibMain/Main.h> 14#include <string.h> 15#include <unistd.h> 16 17ErrorOr<int> serenity_main(Main::Arguments arguments) 18{ 19 if (geteuid() != 0) { 20 warnln("Not running as root :^("); 21 return 1; 22 } 23 24 TRY(Core::System::setegid(0)); 25 26 TRY(Core::System::pledge("stdio wpath rpath cpath fattr tty")); 27 TRY(Core::System::unveil("/etc", "rwc")); 28 TRY(Core::System::unveil(nullptr, nullptr)); 29 30 bool del = false; 31 bool lock = false; 32 bool unlock = false; 33 StringView username {}; 34 35 auto args_parser = Core::ArgsParser(); 36 args_parser.set_general_help("Modify an account password."); 37 args_parser.add_option(del, "Delete password", "delete", 'd'); 38 args_parser.add_option(lock, "Lock password", "lock", 'l'); 39 args_parser.add_option(unlock, "Unlock password", "unlock", 'u'); 40 args_parser.add_positional_argument(username, "Username", "username", Core::ArgsParser::Required::No); 41 42 args_parser.parse(arguments); 43 44 uid_t current_uid = getuid(); 45 46 // target_account is the account we are changing the password of. 47 auto target_account = TRY(!username.is_empty() 48 ? Core::Account::from_name(username) 49 : Core::Account::from_uid(current_uid)); 50 51 setpwent(); 52 53 if (current_uid != 0 && current_uid != target_account.uid()) { 54 warnln("You can't modify passwd for {}", username); 55 return 1; 56 } 57 58 if (del) { 59 target_account.delete_password(); 60 } else if (lock) { 61 target_account.set_password_enabled(false); 62 } else if (unlock) { 63 target_account.set_password_enabled(true); 64 } else { 65 if (current_uid != 0) { 66 auto current_password = TRY(Core::get_password("Current password: "sv)); 67 68 if (!target_account.authenticate(current_password)) { 69 warnln("Incorrect or disabled password."); 70 warnln("Password for user {} unchanged.", target_account.username()); 71 return 1; 72 } 73 } 74 75 auto new_password = TRY(Core::get_password("New password: "sv)); 76 auto new_password_retype = TRY(Core::get_password("Retype new password: "sv)); 77 78 if (new_password.is_empty() && new_password_retype.is_empty()) { 79 warnln("No password supplied."); 80 warnln("Password for user {} unchanged.", target_account.username()); 81 return 1; 82 } 83 84 if (new_password.view() != new_password_retype.view()) { 85 warnln("Sorry, passwords don't match."); 86 warnln("Password for user {} unchanged.", target_account.username()); 87 return 1; 88 } 89 90 target_account.set_password(new_password); 91 } 92 93 TRY(Core::System::pledge("stdio wpath rpath cpath fattr")); 94 95 TRY(target_account.sync()); 96 97 outln("Password for user {} successfully updated.", target_account.username()); 98 return 0; 99}