summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorPeter Elliott <pelliott@ualberta.ca>2020-09-04 12:01:48 -0700
committerAndreas Kling <kling@serenityos.org>2020-09-21 20:18:05 +0200
commit7ba7b72736ecece784b87c51dae6405501071031 (patch)
tree3e9c89e65f289c3a1ec9424b93497cbf979a166f /Userland
parent4a834f969faf997fc40623d6daaf7b98f9453616 (diff)
downloadserenity-7ba7b72736ecece784b87c51dae6405501071031.zip
Userland: Convert passwd(1) to use Core::Account
this fixes the passwd issues discovered in #3296
Diffstat (limited to 'Userland')
-rw-r--r--Userland/passwd.cpp89
1 files changed, 27 insertions, 62 deletions
diff --git a/Userland/passwd.cpp b/Userland/passwd.cpp
index a848caebee..61cd1e6094 100644
--- a/Userland/passwd.cpp
+++ b/Userland/passwd.cpp
@@ -24,53 +24,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <AK/Base64.h>
-#include <AK/StringBuilder.h>
#include <AK/Types.h>
+#include <LibCore/Account.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/File.h>
#include <LibCore/GetPassword.h>
-#include <pwd.h>
#include <string.h>
#include <unistd.h>
-static String get_salt()
-{
- char random_data[12];
- arc4random_buf(random_data, sizeof(random_data));
-
- StringBuilder builder;
- builder.append("$5$");
- builder.append(encode_base64(ReadonlyBytes(random_data, sizeof(random_data))));
-
- return builder.build();
-}
-
-static void write_passwd_file(struct passwd* pwd)
-{
- StringBuilder new_passwd_file;
-
- setpwent();
-
- struct passwd* p;
- while ((p = getpwent())) {
- if (p->pw_uid == pwd->pw_uid) {
- p = pwd;
- }
-
- new_passwd_file.appendf("%s:%s:%u:%u:%s:%s:%s\n",
- p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);
- }
- endpwent();
-
- auto file = Core::File::open("/etc/passwd", Core::IODevice::OpenMode::WriteOnly);
- if (file.is_error()) {
- fprintf(stderr, "Core::File::open: %s\n", file.error().characters());
- exit(1);
- }
- file.value()->write(new_passwd_file.build());
-}
-
int main(int argc, char** argv)
{
if (geteuid() != 0) {
@@ -88,6 +49,11 @@ int main(int argc, char** argv)
return 1;
}
+ if (unveil("/etc/group", "rwc") < 0) {
+ perror("unveil");
+ return 1;
+ }
+
unveil(nullptr, nullptr);
bool del = false;
@@ -103,32 +69,29 @@ int main(int argc, char** argv)
args_parser.parse(argc, argv);
- uid_t current_user = getuid();
+ uid_t current_uid = getuid();
- struct passwd pwd;
- if (username) {
- pwd = *getpwnam(username);
- if (current_user != 0 && current_user != pwd.pw_uid) {
- fprintf(stderr, "You can't modify passwd for %s.\n", username);
- return 1;
- }
- } else {
- pwd = *getpwuid(current_user);
+ auto account_or_error = (username) ? Core::Account::from_name(username) : Core::Account::from_uid(current_uid);
+
+ if (account_or_error.is_error()) {
+ fprintf(stderr, "Core::Account::%s: %s\n", (username) ? "from_name" : "from_uid", account_or_error.error().characters());
+ return 1;
+ }
+
+ // target_account is the account we are changing the password of.
+ auto target_account = account_or_error.value();
+
+ if (current_uid != 0 && current_uid != target_account.uid()) {
+ fprintf(stderr, "You can't modify passwd for %s\n", username);
+ return 1;
}
- String pw_string;
if (del) {
- pwd.pw_passwd = const_cast<char*>("");
+ target_account.delete_password();
} else if (lock) {
- StringBuilder builder;
- builder.append('!');
- builder.append(pwd.pw_passwd);
- pw_string = builder.build();
- pwd.pw_passwd = const_cast<char*>(pw_string.characters());
+ target_account.set_password_enabled(false);
} else if (unlock) {
- if (pwd.pw_passwd[0] == '!') {
- pwd.pw_passwd += 1;
- }
+ target_account.set_password_enabled(true);
} else {
auto new_password = Core::get_password("New password: ");
if (new_password.is_error()) {
@@ -136,10 +99,12 @@ int main(int argc, char** argv)
return 1;
}
- pwd.pw_passwd = crypt(new_password.value().characters(), get_salt().characters());
+ target_account.set_password(new_password.value().characters());
}
- write_passwd_file(&pwd);
+ if (!target_account.sync()) {
+ perror("Core::Account::Sync");
+ }
return 0;
}