summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibCore
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-05-01 11:43:38 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-01 12:40:12 +0200
commit302f9798eebc3b0b80ea08aa3506959b249e4155 (patch)
tree46f2cae69da5485b70cf52c280333f848cadcf19 /Userland/Libraries/LibCore
parentce77caf479a8f7003d3789737a888cec628efae3 (diff)
downloadserenity-302f9798eebc3b0b80ea08aa3506959b249e4155.zip
LibC: Implement support for getspnam() and friends
Diffstat (limited to 'Userland/Libraries/LibCore')
-rw-r--r--Userland/Libraries/LibCore/Account.cpp97
-rw-r--r--Userland/Libraries/LibCore/Account.h12
2 files changed, 53 insertions, 56 deletions
diff --git a/Userland/Libraries/LibCore/Account.cpp b/Userland/Libraries/LibCore/Account.cpp
index 869958c604..c86fb1d6f0 100644
--- a/Userland/Libraries/LibCore/Account.cpp
+++ b/Userland/Libraries/LibCore/Account.cpp
@@ -13,6 +13,7 @@
#include <errno.h>
#include <grp.h>
#include <pwd.h>
+#include <shadow.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
@@ -47,39 +48,52 @@ static Vector<gid_t> get_gids(const StringView& username)
return extra_gids;
}
-Result<Account, String> Account::from_passwd(const passwd& pwd)
+Result<Account, String> Account::from_passwd(const passwd& pwd, const spwd& spwd)
{
- Account account(pwd, get_gids(pwd.pw_name));
+ Account account(pwd, spwd, get_gids(pwd.pw_name));
endpwent();
+ endspent();
return account;
}
Result<Account, String> Account::from_name(const char* username)
{
- struct passwd* pwd = nullptr;
errno = 0;
- pwd = getpwnam(username);
+ auto* pwd = getpwnam(username);
if (!pwd) {
if (errno == 0)
return String("No such user");
return String(strerror(errno));
}
- return from_passwd(*pwd);
+ auto* spwd = getspnam(username);
+ if (!spwd) {
+ if (errno == 0)
+ return String("No such user");
+
+ return String(strerror(errno));
+ }
+ return from_passwd(*pwd, *spwd);
}
Result<Account, String> Account::from_uid(uid_t uid)
{
- struct passwd* pwd = nullptr;
errno = 0;
- pwd = getpwuid(uid);
+ auto* pwd = getpwuid(uid);
if (!pwd) {
if (errno == 0)
return String("No such user");
return String(strerror(errno));
}
- return from_passwd(*pwd);
+ auto* spwd = getspnam(pwd->pw_name);
+ if (!spwd) {
+ if (errno == 0)
+ return String("No such user");
+
+ return String(strerror(errno));
+ }
+ return from_passwd(*pwd, *spwd);
}
bool Account::authenticate(const char* password) const
@@ -133,8 +147,9 @@ void Account::delete_password()
m_password_hash = "";
}
-Account::Account(const passwd& pwd, Vector<gid_t> extra_gids)
+Account::Account(const passwd& pwd, const spwd& spwd, Vector<gid_t> extra_gids)
: m_username(pwd.pw_name)
+ , m_password_hash(spwd.sp_pwdp)
, m_uid(pwd.pw_uid)
, m_gid(pwd.pw_gid)
, m_gecos(pwd.pw_gecos)
@@ -142,7 +157,6 @@ Account::Account(const passwd& pwd, Vector<gid_t> extra_gids)
, m_shell(pwd.pw_shell)
, m_extra_gids(extra_gids)
{
- load_shadow_file();
}
String Account::generate_passwd_file() const
@@ -179,50 +193,39 @@ String Account::generate_passwd_file() const
return builder.to_string();
}
-void Account::load_shadow_file()
+String Account::generate_shadow_file() const
{
- auto file_or_error = Core::File::open("/etc/shadow", Core::File::ReadOnly);
- VERIFY(!file_or_error.is_error());
- auto shadow_file = file_or_error.release_value();
- VERIFY(shadow_file->is_open());
-
- Vector<ShadowEntry> entries;
-
- for (;;) {
- auto line = shadow_file->read_line();
- if (line.is_null())
- break;
- auto parts = line.split(':', true);
- if (parts.size() != 2) {
- dbgln("Malformed shadow entry, ignoring.");
- continue;
- }
- const auto& username = parts[0];
- const auto& password_hash = parts[1];
- entries.append({ username, password_hash });
+ StringBuilder builder;
- if (username == m_username) {
- m_password_hash = password_hash;
- }
- }
+ setspent();
- m_shadow_entries = move(entries);
-}
+ struct spwd* p;
+ errno = 0;
+ while ((p = getspent())) {
+ if (p->sp_namp == m_username) {
+ builder.appendff("{}:{}:{}:{}:{}:{}:{}:{}:{}\n",
+ m_username, m_password_hash,
+ p->sp_lstchg, p->sp_min,
+ p->sp_max, p->sp_warn,
+ p->sp_inact, p->sp_expire,
+ p->sp_flag);
-String Account::generate_shadow_file() const
-{
- StringBuilder builder;
- bool updated_entry_in_place = false;
- for (auto& entry : m_shadow_entries) {
- if (entry.username == m_username) {
- updated_entry_in_place = true;
- builder.appendff("{}:{}\n", m_username, m_password_hash);
} else {
- builder.appendff("{}:{}\n", entry.username, entry.password_hash);
+ builder.appendff("{}:{}:{}:{}:{}:{}:{}:{}:{}\n",
+ p->sp_namp, p->sp_pwdp,
+ p->sp_lstchg, p->sp_min,
+ p->sp_max, p->sp_warn,
+ p->sp_inact, p->sp_expire,
+ p->sp_flag);
}
}
- if (!updated_entry_in_place)
- builder.appendff("{}:{}\n", m_username, m_password_hash);
+ endspent();
+
+ if (errno) {
+ dbgln("errno was non-zero after generating new passwd file.");
+ return {};
+ }
+
return builder.to_string();
}
diff --git a/Userland/Libraries/LibCore/Account.h b/Userland/Libraries/LibCore/Account.h
index b9231f10e9..c97dae424b 100644
--- a/Userland/Libraries/LibCore/Account.h
+++ b/Userland/Libraries/LibCore/Account.h
@@ -11,6 +11,7 @@
#include <AK/Types.h>
#include <AK/Vector.h>
#include <pwd.h>
+#include <shadow.h>
#include <sys/types.h>
namespace Core {
@@ -46,10 +47,9 @@ public:
bool sync();
private:
- static Result<Account, String> from_passwd(const passwd&);
+ static Result<Account, String> from_passwd(const passwd&, const spwd&);
- Account(const passwd& pwd, Vector<gid_t> extra_gids);
- void load_shadow_file();
+ Account(const passwd& pwd, const spwd& spwd, Vector<gid_t> extra_gids);
String generate_passwd_file() const;
String generate_shadow_file() const;
@@ -63,12 +63,6 @@ private:
String m_home_directory;
String m_shell;
Vector<gid_t> m_extra_gids;
-
- struct ShadowEntry {
- String username;
- String password_hash;
- };
- Vector<ShadowEntry> m_shadow_entries;
};
}