2018-07-16 16:58:23 +02:00
|
|
|
/*
|
|
|
|
* \brief Password database operations
|
2019-09-20 16:26:52 +02:00
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2019-09-20
|
2018-07-16 16:58:23 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2019-09-20 16:26:52 +02:00
|
|
|
* Copyright (C) 2019 Genode Labs GmbH
|
2018-07-16 16:58:23 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <util/string.h>
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
#include <util/xml_node.h>
|
2018-07-16 16:58:23 +02:00
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
/* libc includes */
|
2018-07-16 16:58:23 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
/* libc-local includes */
|
|
|
|
#include <internal/legacy.h>
|
|
|
|
#include <internal/errno.h>
|
2019-09-20 16:26:52 +02:00
|
|
|
#include <internal/init.h>
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
namespace Libc {
|
2019-09-19 20:37:17 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
struct Passwd_fields;
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
typedef String<128> Passwd_string;
|
|
|
|
}
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This struct must not contain any pointer because it is copied as
|
|
|
|
* plain old data.
|
|
|
|
*/
|
|
|
|
struct Libc::Passwd_fields
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
struct Buffer
|
|
|
|
{
|
|
|
|
char buf[Passwd_string::capacity()] { };
|
|
|
|
|
|
|
|
Buffer(Passwd_string const &string)
|
|
|
|
{
|
|
|
|
Genode::strncpy(buf, string.string(), sizeof(buf));
|
|
|
|
}
|
|
|
|
};
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
Buffer name;
|
|
|
|
Buffer passwd;
|
|
|
|
uid_t uid;
|
|
|
|
gid_t gid;
|
|
|
|
time_t change;
|
|
|
|
Buffer clas;
|
|
|
|
Buffer gecos;
|
|
|
|
Buffer home;
|
|
|
|
Buffer shell;
|
|
|
|
time_t expire;
|
|
|
|
int fields;
|
|
|
|
};
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
using namespace Libc;
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
static Passwd_fields *_fields_ptr = nullptr;
|
|
|
|
static passwd *_passwd_ptr = nullptr;
|
|
|
|
static int _passwd_index = 0;
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
|
|
|
|
static passwd passwd_from_fields(Passwd_fields &fields)
|
|
|
|
{
|
|
|
|
return passwd {
|
|
|
|
.pw_name = fields.name.buf,
|
|
|
|
.pw_passwd = fields.passwd.buf,
|
|
|
|
.pw_uid = fields.uid,
|
|
|
|
.pw_gid = fields.gid,
|
|
|
|
.pw_change = fields.change,
|
|
|
|
.pw_class = fields.clas.buf,
|
|
|
|
.pw_gecos = fields.gecos.buf,
|
|
|
|
.pw_dir = fields.home.buf,
|
|
|
|
.pw_shell = fields.shell.buf,
|
|
|
|
.pw_expire = fields.expire,
|
|
|
|
.pw_fields = fields.fields
|
|
|
|
};
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
void Libc::init_passwd(Xml_node config)
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
static Passwd_fields fields {
|
|
|
|
.name = config.attribute_value("name", Passwd_string("root")),
|
|
|
|
.passwd = config.attribute_value("passwd", Passwd_string("")),
|
|
|
|
.uid = config.attribute_value("uid", 0U),
|
|
|
|
.gid = config.attribute_value("gid", 0U),
|
|
|
|
.change = (time_t)config.attribute_value("change", 0U),
|
|
|
|
.clas = config.attribute_value("class", Passwd_string("")),
|
|
|
|
.gecos = config.attribute_value("gecos", Passwd_string("")),
|
|
|
|
.home = config.attribute_value("home", Passwd_string("/")),
|
|
|
|
.shell = config.attribute_value("shell", Passwd_string("")),
|
|
|
|
.expire = (time_t)config.attribute_value("expire", 0U),
|
|
|
|
.fields = (int)config.attribute_value("fields", 0U)
|
2018-07-16 16:58:23 +02:00
|
|
|
};
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
static passwd passwd = passwd_from_fields(fields);
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
_fields_ptr = &fields;
|
|
|
|
_passwd_ptr = &passwd;
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" passwd *getpwent()
|
|
|
|
{
|
|
|
|
struct Missing_call_of_init_passwd : Exception { };
|
|
|
|
if (!_passwd_ptr)
|
|
|
|
throw Missing_call_of_init_passwd();
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
return (_passwd_index++ == 0) ? _passwd_ptr : nullptr;
|
|
|
|
}
|
2018-07-16 16:58:23 +02:00
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
template <typename COND_FN>
|
|
|
|
static int copy_out_pwent(passwd *in, char *buffer, size_t bufsize, passwd **out,
|
|
|
|
COND_FN const &cond_fn)
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
*out = nullptr;
|
|
|
|
|
|
|
|
struct Missing_call_of_init_passwd : Exception { };
|
|
|
|
if (!_fields_ptr || !_passwd_ptr)
|
|
|
|
throw Missing_call_of_init_passwd();
|
|
|
|
|
|
|
|
if (bufsize < sizeof(Passwd_fields))
|
|
|
|
return Errno(ERANGE);
|
|
|
|
|
|
|
|
if (!cond_fn(*_passwd_ptr))
|
|
|
|
return Errno(ENOENT);
|
|
|
|
|
|
|
|
Passwd_fields &dst = *(Passwd_fields *)buffer;
|
|
|
|
|
|
|
|
dst = *_fields_ptr;
|
|
|
|
*in = passwd_from_fields(dst);
|
|
|
|
*out = in;
|
|
|
|
|
|
|
|
return 0;
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" int getpwent_r(passwd *in, char *buffer, size_t bufsize, passwd **out)
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
auto match = [&] (passwd const &) { return _passwd_index++ == 0; };
|
|
|
|
|
|
|
|
return copy_out_pwent(in, buffer, bufsize, out, match);
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" struct passwd *getpwnam(const char *login)
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
return (_passwd_ptr && Genode::strcmp(login, _passwd_ptr->pw_name) == 0)
|
|
|
|
? _passwd_ptr : nullptr;
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" int getpwnam_r(char const *login, passwd *in,
|
|
|
|
char *buffer, size_t bufsize, passwd **out)
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
auto match = [&] (passwd const &passwd) {
|
|
|
|
return !Genode::strcmp(passwd.pw_name, login); };
|
|
|
|
|
|
|
|
return copy_out_pwent(in, buffer, bufsize, out, match);
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" passwd *getpwuid(uid_t uid)
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
return (_passwd_ptr && uid == _passwd_ptr->pw_uid)
|
|
|
|
? _passwd_ptr : NULL;
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" int getpwuid_r(uid_t uid, passwd *in,
|
|
|
|
char *buffer, size_t bufsize, passwd **out)
|
2018-07-16 16:58:23 +02:00
|
|
|
{
|
2019-09-20 16:26:52 +02:00
|
|
|
auto match = [&] (passwd const &passwd) { return passwd.pw_uid == uid; };
|
|
|
|
|
|
|
|
return copy_out_pwent(in, buffer, bufsize, out, match);
|
2018-07-16 16:58:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" int setpassent(int)
|
|
|
|
{
|
|
|
|
_passwd_index = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-07-16 16:58:23 +02:00
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" void setpwent()
|
|
|
|
{
|
|
|
|
_passwd_index = 0;
|
|
|
|
}
|
2018-07-16 16:58:23 +02:00
|
|
|
|
|
|
|
|
2019-09-20 16:26:52 +02:00
|
|
|
extern "C" void endpwent() { }
|