1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 17:47:44 +00:00

LibCore: Enable modification of a user's supplementary groups

This commit is contained in:
Tim Ledbetter 2023-06-26 17:48:11 +01:00 committed by Andreas Kling
parent ba34931620
commit 089ff7b94e
2 changed files with 50 additions and 1 deletions

View file

@ -251,6 +251,42 @@ ErrorOr<DeprecatedString> Account::generate_passwd_file() const
return builder.to_deprecated_string();
}
ErrorOr<DeprecatedString> Account::generate_group_file() const
{
StringBuilder builder;
char buffer[1024] = { 0 };
ScopeGuard pwent_guard([] { endgrent(); });
setgrent();
while (true) {
auto group = TRY(Core::System::getgrent(buffer));
if (!group.has_value())
break;
auto should_be_present = !m_deleted && m_extra_gids.contains_slow(group->gr_gid);
auto already_present = false;
Vector<char const*> members;
for (size_t i = 0; group->gr_mem[i]; ++i) {
auto const* member = group->gr_mem[i];
if (member == m_username) {
already_present = true;
if (!should_be_present)
continue;
}
members.append(member);
}
if (should_be_present && !already_present)
members.append(m_username.characters());
builder.appendff("{}:{}:{}:{}\n", group->gr_name, group->gr_passwd, group->gr_gid, DeprecatedString::join(","sv, members));
}
return builder.to_deprecated_string();
}
#ifndef AK_OS_BSD_GENERIC
ErrorOr<DeprecatedString> Account::generate_shadow_file() const
{
@ -291,11 +327,13 @@ ErrorOr<void> Account::sync()
Core::UmaskScope umask_scope(0777);
auto new_passwd_file_content = TRY(generate_passwd_file());
auto new_group_file_content = TRY(generate_group_file());
#ifndef AK_OS_BSD_GENERIC
auto new_shadow_file_content = TRY(generate_shadow_file());
#endif
char new_passwd_file[] = "/etc/passwd.XXXXXX";
char new_group_file[] = "/etc/group.XXXXXX";
#ifndef AK_OS_BSD_GENERIC
char new_shadow_file[] = "/etc/shadow.XXXXXX";
#endif
@ -305,6 +343,10 @@ ErrorOr<void> Account::sync()
ScopeGuard new_passwd_fd_guard = [new_passwd_fd] { close(new_passwd_fd); };
TRY(Core::System::fchmod(new_passwd_fd, 0644));
auto new_group_fd = TRY(Core::System::mkstemp(new_group_file));
ScopeGuard new_group_fd_guard = [new_group_fd] { close(new_group_fd); };
TRY(Core::System::fchmod(new_group_fd, 0644));
#ifndef AK_OS_BSD_GENERIC
auto new_shadow_fd = TRY(Core::System::mkstemp(new_shadow_file));
ScopeGuard new_shadow_fd_guard = [new_shadow_fd] { close(new_shadow_fd); };
@ -314,6 +356,9 @@ ErrorOr<void> Account::sync()
auto nwritten = TRY(Core::System::write(new_passwd_fd, new_passwd_file_content.bytes()));
VERIFY(static_cast<size_t>(nwritten) == new_passwd_file_content.length());
nwritten = TRY(Core::System::write(new_group_fd, new_group_file_content.bytes()));
VERIFY(static_cast<size_t>(nwritten) == new_group_file_content.length());
#ifndef AK_OS_BSD_GENERIC
nwritten = TRY(Core::System::write(new_shadow_fd, new_shadow_file_content.bytes()));
VERIFY(static_cast<size_t>(nwritten) == new_shadow_file_content.length());
@ -322,13 +367,15 @@ ErrorOr<void> Account::sync()
auto new_passwd_file_view = StringView { new_passwd_file, sizeof(new_passwd_file) };
TRY(Core::System::rename(new_passwd_file_view, "/etc/passwd"sv));
auto new_group_file_view = StringView { new_group_file, sizeof(new_group_file) };
TRY(Core::System::rename(new_group_file_view, "/etc/group"sv));
#ifndef AK_OS_BSD_GENERIC
auto new_shadow_file_view = StringView { new_shadow_file, sizeof(new_shadow_file) };
TRY(Core::System::rename(new_shadow_file_view, "/etc/shadow"sv));
#endif
return {};
// FIXME: Sync extra groups.
}
}

View file

@ -53,6 +53,7 @@ public:
void set_shell(StringView shell) { m_shell = shell; }
void set_gecos(StringView gecos) { m_gecos = gecos; }
void set_deleted() { m_deleted = true; };
void set_extra_gids(Vector<gid_t> extra_gids) { m_extra_gids = move(extra_gids); }
void delete_password();
// A null password means that this account was missing from /etc/shadow.
@ -74,6 +75,7 @@ private:
Account(passwd const& pwd, spwd const& spwd, Vector<gid_t> extra_gids);
ErrorOr<DeprecatedString> generate_passwd_file() const;
ErrorOr<DeprecatedString> generate_group_file() const;
#ifndef AK_OS_BSD_GENERIC
ErrorOr<DeprecatedString> generate_shadow_file() const;
#endif