1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 11:28:12 +00:00

LibCore+su+passwd: Don't keep /etc/passwd and /etc/shadow open

Now that we've moved to atomic replacement of these files when altering
them, we don't need to keep them open for the lifetime of Core::Account
so just simplify this and close them when they are not needed.
This commit is contained in:
Andreas Kling 2021-01-21 11:17:06 +01:00
parent 77e0598c6d
commit 439f447ba8
4 changed files with 22 additions and 71 deletions

View file

@ -65,36 +65,14 @@ static Vector<gid_t> get_gids(const StringView& username)
return extra_gids; return extra_gids;
} }
Result<Account, String> Account::from_passwd(const passwd& pwd, Core::Account::OpenPasswdFile open_passwd_file, Core::Account::OpenShadowFile open_shadow_file) Result<Account, String> Account::from_passwd(const passwd& pwd)
{ {
RefPtr<Core::File> passwd_file; Account account(pwd, get_gids(pwd.pw_name));
if (open_passwd_file != Core::Account::OpenPasswdFile::No) {
auto open_mode = open_passwd_file == Core::Account::OpenPasswdFile::ReadOnly
? Core::File::OpenMode::ReadOnly
: Core::File::OpenMode::ReadWrite;
auto file_or_error = Core::File::open("/etc/passwd", open_mode);
if (file_or_error.is_error())
return file_or_error.error();
passwd_file = file_or_error.value();
}
RefPtr<Core::File> shadow_file;
if (open_shadow_file != Core::Account::OpenShadowFile::No) {
auto open_mode = open_shadow_file == Core::Account::OpenShadowFile::ReadOnly
? Core::File::OpenMode::ReadOnly
: Core::File::OpenMode::ReadWrite;
auto file_or_error = Core::File::open("/etc/shadow", open_mode);
if (file_or_error.is_error())
return file_or_error.error();
shadow_file = file_or_error.value();
}
Account account(pwd, get_gids(pwd.pw_name), move(passwd_file), move(shadow_file));
endpwent(); endpwent();
return account; return account;
} }
Result<Account, String> Account::from_name(const char* username, Core::Account::OpenPasswdFile open_passwd_file, Core::Account::OpenShadowFile open_shadow_file) Result<Account, String> Account::from_name(const char* username)
{ {
struct passwd* pwd = nullptr; struct passwd* pwd = nullptr;
errno = 0; errno = 0;
@ -105,10 +83,10 @@ Result<Account, String> Account::from_name(const char* username, Core::Account::
return String(strerror(errno)); return String(strerror(errno));
} }
return from_passwd(*pwd, open_passwd_file, open_shadow_file); return from_passwd(*pwd);
} }
Result<Account, String> Account::from_uid(uid_t uid, Core::Account::OpenPasswdFile open_passwd_file, Core::Account::OpenShadowFile open_shadow_file) Result<Account, String> Account::from_uid(uid_t uid)
{ {
struct passwd* pwd = nullptr; struct passwd* pwd = nullptr;
errno = 0; errno = 0;
@ -119,7 +97,7 @@ Result<Account, String> Account::from_uid(uid_t uid, Core::Account::OpenPasswdFi
return String(strerror(errno)); return String(strerror(errno));
} }
return from_passwd(*pwd, open_passwd_file, open_shadow_file); return from_passwd(*pwd);
} }
bool Account::authenticate(const char* password) const bool Account::authenticate(const char* password) const
@ -169,10 +147,8 @@ void Account::delete_password()
m_password_hash = ""; m_password_hash = "";
} }
Account::Account(const passwd& pwd, Vector<gid_t> extra_gids, RefPtr<Core::File> passwd_file, RefPtr<Core::File> shadow_file) Account::Account(const passwd& pwd, Vector<gid_t> extra_gids)
: m_passwd_file(move(passwd_file)) : m_username(pwd.pw_name)
, m_shadow_file(move(shadow_file))
, m_username(pwd.pw_name)
, m_uid(pwd.pw_uid) , m_uid(pwd.pw_uid)
, m_gid(pwd.pw_gid) , m_gid(pwd.pw_gid)
, m_gecos(pwd.pw_gecos) , m_gecos(pwd.pw_gecos)
@ -180,9 +156,7 @@ Account::Account(const passwd& pwd, Vector<gid_t> extra_gids, RefPtr<Core::File>
, m_shell(pwd.pw_shell) , m_shell(pwd.pw_shell)
, m_extra_gids(extra_gids) , m_extra_gids(extra_gids)
{ {
if (m_shadow_file) { load_shadow_file();
load_shadow_file();
}
} }
String Account::generate_passwd_file() const String Account::generate_passwd_file() const
@ -221,17 +195,15 @@ String Account::generate_passwd_file() const
void Account::load_shadow_file() void Account::load_shadow_file()
{ {
ASSERT(m_shadow_file); auto file_or_error = Core::File::open("/etc/shadow", Core::File::ReadOnly);
ASSERT(m_shadow_file->is_open()); ASSERT(!file_or_error.is_error());
auto shadow_file = file_or_error.release_value();
if (!m_shadow_file->seek(0)) { ASSERT(shadow_file->is_open());
ASSERT_NOT_REACHED();
}
Vector<ShadowEntry> entries; Vector<ShadowEntry> entries;
for (;;) { for (;;) {
auto line = m_shadow_file->read_line(); auto line = shadow_file->read_line();
if (line.is_null()) if (line.is_null())
break; break;
auto parts = line.split(':'); auto parts = line.split(':');
@ -270,11 +242,6 @@ String Account::generate_shadow_file() const
bool Account::sync() bool Account::sync()
{ {
ASSERT(m_passwd_file);
ASSERT(m_passwd_file->mode() == Core::File::OpenMode::ReadWrite);
ASSERT(m_shadow_file);
ASSERT(m_shadow_file->mode() == Core::File::OpenMode::ReadWrite);
auto new_passwd_file_content = generate_passwd_file(); auto new_passwd_file_content = generate_passwd_file();
auto new_shadow_file_content = generate_shadow_file(); auto new_shadow_file_content = generate_shadow_file();

View file

@ -30,7 +30,6 @@
#include <AK/String.h> #include <AK/String.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibCore/File.h>
#include <pwd.h> #include <pwd.h>
#include <sys/types.h> #include <sys/types.h>
@ -38,20 +37,8 @@ namespace Core {
class Account { class Account {
public: public:
enum class OpenPasswdFile { static Result<Account, String> from_name(const char* username);
No, static Result<Account, String> from_uid(uid_t uid);
ReadOnly,
ReadWrite,
};
enum class OpenShadowFile {
No,
ReadOnly,
ReadWrite,
};
static Result<Account, String> from_name(const char* username, OpenPasswdFile = OpenPasswdFile::No, OpenShadowFile = OpenShadowFile::No);
static Result<Account, String> from_uid(uid_t uid, OpenPasswdFile = OpenPasswdFile::No, OpenShadowFile = OpenShadowFile::No);
bool authenticate(const char* password) const; bool authenticate(const char* password) const;
bool login() const; bool login() const;
@ -76,17 +63,14 @@ public:
bool sync(); bool sync();
private: private:
static Result<Account, String> from_passwd(const passwd&, OpenPasswdFile, OpenShadowFile); static Result<Account, String> from_passwd(const passwd&);
Account(const passwd& pwd, Vector<gid_t> extra_gids, RefPtr<Core::File> passwd_file, RefPtr<Core::File> shadow_file); Account(const passwd& pwd, Vector<gid_t> extra_gids);
void load_shadow_file(); void load_shadow_file();
String generate_passwd_file() const; String generate_passwd_file() const;
String generate_shadow_file() const; String generate_shadow_file() const;
RefPtr<Core::File> m_passwd_file;
RefPtr<Core::File> m_shadow_file;
String m_username; String m_username;
// Contents of passwd field in passwd entry. // Contents of passwd field in passwd entry.

View file

@ -74,8 +74,8 @@ int main(int argc, char** argv)
uid_t current_uid = getuid(); uid_t current_uid = getuid();
auto account_or_error = (username) auto account_or_error = (username)
? Core::Account::from_name(username, Core::Account::OpenPasswdFile::ReadWrite, Core::Account::OpenShadowFile::ReadWrite) ? Core::Account::from_name(username)
: Core::Account::from_uid(current_uid, Core::Account::OpenPasswdFile::ReadWrite, Core::Account::OpenShadowFile::ReadWrite); : Core::Account::from_uid(current_uid);
if (account_or_error.is_error()) { if (account_or_error.is_error()) {
warnln("Core::Account::{}: {}", (username) ? "from_name" : "from_uid", account_or_error.error()); warnln("Core::Account::{}: {}", (username) ? "from_name" : "from_uid", account_or_error.error());

View file

@ -58,8 +58,8 @@ int main(int argc, char** argv)
} }
auto account_or_error = (user) auto account_or_error = (user)
? Core::Account::from_name(user, Core::Account::OpenPasswdFile::No, Core::Account::OpenShadowFile::ReadOnly) ? Core::Account::from_name(user)
: Core::Account::from_uid(0, Core::Account::OpenPasswdFile::No, Core::Account::OpenShadowFile::ReadOnly); : Core::Account::from_uid(0);
if (account_or_error.is_error()) { if (account_or_error.is_error()) {
fprintf(stderr, "Core::Account::from_name: %s\n", account_or_error.error().characters()); fprintf(stderr, "Core::Account::from_name: %s\n", account_or_error.error().characters());
return 1; return 1;