mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
homectl: expose "register" verb to register a user record locally
This commit is contained in:
@@ -1197,6 +1197,55 @@
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>register</command> <replaceable>FILE</replaceable> [<replaceable>FILE</replaceable>…]</term>
|
||||
|
||||
<listitem><para>Registers one or more users, without creating their home directories. Takes one or
|
||||
more paths to JSON user record files. If the path is specified as <literal>-</literal> reads the
|
||||
JSON user record from standard input.</para>
|
||||
|
||||
<para>Registering a user makes it accessible on the local system without creating a new home
|
||||
directory. This is particularly useful for making a user accessible on a system it was not originally
|
||||
created on.</para>
|
||||
|
||||
<para>Here's an example how to make a local user account with its home directory accessible on a
|
||||
remote system, using SMB/CIFS file sharing. With Samba installed in its default configuration invoke
|
||||
as <literal>root</literal>:</para>
|
||||
|
||||
<programlisting># smbpasswd -a lennart</programlisting>
|
||||
|
||||
<para>Continue as regular user <literal>lennart</literal>:</para>
|
||||
|
||||
<programlisting>$ homectl update lennart --ssh-authorized-keys=… -N --storage=cifs --cifs-service="//$HOSTNAME/lennart"
|
||||
$ homectl get-signing-key | ssh targetsystem homectl add-signing-key --key-name="$HOSTNAME".public
|
||||
$ homectl inspect -E lennart | ssh targetsystem homectl register -
|
||||
$ ssh lennart@targetsystem</programlisting>
|
||||
|
||||
<para>This first ensures the user account <literal>lennart</literal> is known to and accessible by
|
||||
Samba. It then registers a local SSH access that shall be used for accessing this user, and
|
||||
configures CIFS as default storage for non-local systems on the account. It then adds the local
|
||||
system's account signing key to the target system. Then it registers the local user account with the
|
||||
target system. Finally it logs into the account on the target system. The target system will then
|
||||
connect back via SMB/CIFS to access the home directory.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>unregister</command> <replaceable>USER</replaceable>…</term>
|
||||
|
||||
<listitem><para>Unregisters one or more user accounts. This only removes the user record from the
|
||||
local system, it does not delete the home directory. The home directory can be readded via the
|
||||
<command>register</command> or <command>adopt</command> command later, on this or another
|
||||
system. Note that unregistering a user whose home directory is placed in <filename>/home/</filename>
|
||||
will not make the user disappear from the local user database, as all supported home directories
|
||||
placed there will show up in the user database. However, the user record will become "unfixated",
|
||||
i.e. lose its binding to the local system. When logged into it will automatically regain the binding,
|
||||
and acquire a local UID/GID pair.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>remove</command> <replaceable>USER</replaceable></term>
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ _homectl() {
|
||||
fi
|
||||
|
||||
local -A VERBS=(
|
||||
[STANDALONE]='list lock-all adopt'
|
||||
[STANDALONE]='list lock-all register unregister adopt'
|
||||
[CREATE]='create'
|
||||
[NAMES]='activate deactivate inspect authenticate remove lock unlock'
|
||||
[NAME]='update passwd'
|
||||
|
||||
@@ -1596,6 +1596,101 @@ static int verb_adopt_home(int argc, char *argv[], void *userdata) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int register_home_one(sd_bus *bus, FILE *f, const char *path) {
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(path);
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file(f, path, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "[%s:%u:%u] Failed to parse user record: %m", path, line, column);
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
r = bus_message_new_method_call(bus, &m, bus_mgr, "RegisterHome");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
_cleanup_free_ char *formatted = NULL;
|
||||
r = sd_json_variant_format(v, /* flags= */ 0, &formatted);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to format JSON record: %m");
|
||||
|
||||
r = sd_bus_message_append(m, "s", formatted);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register home: %s", bus_error_message(&error, r));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_register_home(int argc, char *argv[], void *userdata) {
|
||||
int r;
|
||||
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
r = acquire_bus(&bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
|
||||
if (arg_identity) {
|
||||
if (argc > 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not accepting an arguments if --identity= is specified, refusing.");
|
||||
|
||||
return register_home_one(bus, /* f= */ NULL, arg_identity);
|
||||
}
|
||||
|
||||
if (argc == 1 || (argc == 2 && streq(argv[1], "-")))
|
||||
return register_home_one(bus, /* f= */ stdin, "<stdio>");
|
||||
|
||||
r = 0;
|
||||
STRV_FOREACH(i, strv_skip(argv, 1)) {
|
||||
if (streq(*i, "-"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Refusing reading from standard input if multiple user records are specified.");
|
||||
|
||||
RET_GATHER(r, register_home_one(bus, /* f= */ NULL, *i));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int verb_unregister_home(int argc, char *argv[], void *userdata) {
|
||||
int r;
|
||||
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
r = acquire_bus(&bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
|
||||
int ret = 0;
|
||||
STRV_FOREACH(i, strv_skip(argv, 1)) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
r = bus_message_new_method_call(bus, &m, bus_mgr, "UnregisterHome");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "s", *i);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, /* ret_reply= */ NULL);
|
||||
if (r < 0)
|
||||
RET_GATHER(ret, log_error_errno(r, "Failed to unregister home: %s", bus_error_message(&error, r)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int remove_home(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int r, ret = 0;
|
||||
@@ -2841,6 +2936,8 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" authenticate USER… Authenticate a home area\n"
|
||||
" create USER Create a home area\n"
|
||||
" adopt PATH… Add an existing home area on this system\n"
|
||||
" register PATH… Register a user record locally\n"
|
||||
" unregister USER… Unregister a user record locally\n"
|
||||
" remove USER… Remove a home area\n"
|
||||
" update USER Update a home area\n"
|
||||
" passwd USER Change password of a home area\n"
|
||||
@@ -5276,6 +5373,8 @@ static int run(int argc, char *argv[]) {
|
||||
{ "authenticate", VERB_ANY, VERB_ANY, 0, authenticate_home },
|
||||
{ "create", VERB_ANY, 2, 0, create_home },
|
||||
{ "adopt", VERB_ANY, VERB_ANY, 0, verb_adopt_home },
|
||||
{ "register", VERB_ANY, VERB_ANY, 0, verb_register_home },
|
||||
{ "unregister", 2, VERB_ANY, 0, verb_unregister_home },
|
||||
{ "remove", 2, VERB_ANY, 0, remove_home },
|
||||
{ "update", VERB_ANY, 2, 0, update_home },
|
||||
{ "passwd", VERB_ANY, 2, 0, passwd_home },
|
||||
|
||||
Reference in New Issue
Block a user