1
0
mirror of https://github.com/systemd/systemd synced 2026-04-04 06:04:51 +02:00

Compare commits

...

16 Commits

Author SHA1 Message Date
ml
84b10e536c man: remove unintentionally repetitive words 2021-11-11 14:36:50 +01:00
Lennart Poettering
371264b6c6
Merge pull request #21302 from yuwata/udev-drop-colon-from-ID_NET_NAME_MAC
udev: drop colon from ID_NET_NAME_MAC
2021-11-11 14:36:28 +01:00
Lennart Poettering
126c02a8fd
Merge pull request #21304 from poettering/chain-ssh-auth-keys
userdbctl: add support for chaining other ssh-authorized-keys commands from userdbctl
2021-11-11 14:35:48 +01:00
Luca Boccassi
bb23992740
Merge pull request #21301 from yuwata/network-neighbor-use-hw-addr-data
network: neighbor: use "struct hw_addr_data"
2021-11-11 10:32:11 +00:00
Yu Watanabe
a914901d38 test: use kbd-mode-map we ship in one more test case
Follow-up for be0cc2ce6c947aafadb3f42dba405269f670b31c.

Fixes https://github.com/systemd/systemd/pull/19670#issuecomment-965817823.
2021-11-11 09:54:01 +00:00
Yu Watanabe
dfa4876c41 udev: drop colon from ID_NET_NAME_MAC
Fixes a bug introduced by eaba9bb3e69635d2c490c5e1b0d262b763753e1d.
2021-11-11 18:29:55 +09:00
Yu Watanabe
e44cd43788 ether-addr-util: introduce hw_addr_to_string_full() 2021-11-11 18:29:52 +09:00
Lennart Poettering
01f6c450b6 man: document new --chain switch to userdbctl
And while we are at it, make 'ssh-authorized-keys' verb properly
documented. Given that OpenSSH documents the interface in its man page
it's fine to just document our implementation of it too.
2021-11-11 10:06:39 +01:00
Lennart Poettering
8072a7e6a9 userdbctl: add support for chaining command lines in "authorized-keys" verb 2021-11-11 10:06:35 +01:00
Lennart Poettering
7d0cede04f escape: return unused memory in quote_command_line() 2021-11-11 10:06:31 +01:00
Lennart Poettering
5e659ffcb0 process-util: use quote_command_line() at one more place 2021-11-11 10:06:26 +01:00
Lennart Poettering
4ef15008cc escape: add flags argument to quote_command_line()
That way, we can reuse the call at one more place (see later patch).
2021-11-11 10:05:46 +01:00
Yu Watanabe
13b7b8bd73 network: neighbor: accept an empty string assignment 2021-11-11 12:49:42 +09:00
Yu Watanabe
17193d767d network: neighbor: use "struct hw_addr_data" to store link layer address 2021-11-11 12:49:42 +09:00
Yu Watanabe
ca7d208367 ether-addr-util: expose hw_addr_hash_func() 2021-11-11 12:49:42 +09:00
Yu Watanabe
c990101f23 sd-netlink: fix type of NDA_LLADDR attribute 2021-11-11 12:49:42 +09:00
23 changed files with 180 additions and 147 deletions

View File

@ -2235,7 +2235,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<literal>needs-reload</literal>. Package scripts may use the first to mark units for later restart when
a new version of the package is installed. Configuration management scripts may use the second to mark
units for a later reload when the configuration is adjusted. Those flags are not set by the manager,
except to unset as appropriate when when the unit is stopped, restarted, or reloaded.</para>
except to unset as appropriate when the unit is stopped, restarted, or reloaded.</para>
<para><varname>JobTimeoutUSec</varname> maps directly to the corresponding configuration setting in the
unit file.</para>

View File

@ -416,7 +416,7 @@
… suffixes (to the base of 1024). If <varname>SizeMinBytes=</varname> is specified the partition is
created at or grown to at least the specified size. If <varname>SizeMaxBytes=</varname> is specified
the partition is created at or grown to at most the specified size. The precise size is determined
through the weight value value configured with <varname>Weight=</varname>, see above. When
through the weight value configured with <varname>Weight=</varname>, see above. When
<varname>SizeMinBytes=</varname> is set equal to <varname>SizeMaxBytes=</varname> the configured
weight has no effect as the partition is explicitly sized to the specified fixed value. Note that
partitions are never created smaller than 4096 bytes, and since partitions are never shrunk the

View File

@ -210,7 +210,7 @@
true all connections to the server will be encrypted. Note that this
mode requires a DNS server that supports DNS-over-TLS and has a valid
certificate. If the hostname was specified in <varname>DNS=</varname>
by using the format format <literal>address#server_name</literal> it
by using the format <literal>address#server_name</literal> it
is used to validate its certificate and also to enable Server Name
Indication (SNI) when opening a TLS connection. Otherwise
the certificate is checked against the server's IP.

View File

@ -3163,7 +3163,7 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
configuration, with just a few environment variables. The user manager inherits environment variables as
any other system service, but in addition may receive additional environment variables from PAM, and,
typically, additional imported variables when the user starts a graphical session. It is recommended to
keep the environment blocks in both the system and user managers managers lean. Importing all variables
keep the environment blocks in both the system and user managers lean. Importing all variables
inherited by the graphical session or by one of the user shells is strongly discouraged.</para>
<para>Hint: <command>systemd-run -P env</command> and <command>systemd-run --user -P env</command> print

View File

@ -128,7 +128,7 @@
datagram. This field is only included if the <varname>MESSAGE=</varname>
field was modified compared to the original payload or the timestamp could
not be located properly and is not included in
<varname>SYSLOG_TIMESTAMP=</varname>. Message truncation occurs when when
<varname>SYSLOG_TIMESTAMP=</varname>. Message truncation occurs when
the message contains leading or trailing whitespace (trailing and leading
whitespace is stripped), or it contains an embedded
<constant>NUL</constant> byte (the <constant>NUL</constant> byte and

View File

@ -2558,7 +2558,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<para>Takes a boolean value. When <literal>yes</literal>, DHCP server socket will be bound
to its network interface and all socket communication will be restricted to this interface.
Defaults to <literal>yes</literal>, except if <varname>RelayTarget=</varname> is used (see below),
in which case it defaults defaults to <literal>no</literal>.</para>
in which case it defaults to <literal>no</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -33,7 +33,7 @@
<title>Description</title>
<para>An nspawn container settings file (suffix <filename>.nspawn</filename>) contains runtime
configuration for a local container, and is used used by
configuration for a local container, and is used by
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
Files of this type are named after the containers they define settings for. They are optional, and only
required for containers whose execution environment shall differ from the defaults. Files of this type

View File

@ -146,6 +146,14 @@
typically preferable, since it runs in a locked down sandbox.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--chain</option></term>
<listitem><para>When used with the <command>ssh-authorized-keys</command> command, this will allow
passing an additional command line after the user name that is chain executed after the lookup
completed. This allows chaining multiple tools that show SSH authorized keys.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="no-legend" />
<xi:include href="standard-options.xml" xpointer="help" />
@ -201,8 +209,8 @@
<varlistentry>
<term><command>ssh-authorized-keys</command></term>
<listitem><para>This operation is not a public, user-facing interface. It is used to allow the SSH daemon to pick
up authorized keys from user records, see below.</para></listitem>
<listitem><para>Show SSH authorized keys for this account. This command is intended to be used to
allow the SSH daemon to pick up authorized keys from user records, see below.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
@ -301,6 +309,19 @@
AuthorizedKeysCommand /usr/bin/userdbctl ssh-authorized-keys %u
AuthorizedKeysCommandUser root
</programlisting>
<para>Sometimes it's useful to allow chain invocation of another program to list SSH authorized keys. By
using the <option>--chain</option> such a tool may be chain executed by <command>userdbctl
ssh-authorized-keys</command> once a lookup completes (regardless if an SSH key was found or
not). Example:</para>
<programlisting>
AuthorizedKeysCommand /usr/bin/userdbctl ssh-authorized-keys %u --chain /usr/bin/othertool %u
AuthorizedKeysCommandUser root
</programlisting>
<para>The above will first query the userdb database for SSH keys, and then chain execute
<command>/usr/bin/othertool</command> to also be queried.</para>
</refsect1>
<refsect1>

View File

@ -544,7 +544,7 @@ char* shell_maybe_quote(const char *s, ShellEscapeFlags flags) {
return str_realloc(buf);
}
char* quote_command_line(char **argv) {
char* quote_command_line(char **argv, ShellEscapeFlags flags) {
_cleanup_free_ char *result = NULL;
assert(argv);
@ -553,7 +553,7 @@ char* quote_command_line(char **argv) {
STRV_FOREACH(a, argv) {
_cleanup_free_ char *t = NULL;
t = shell_maybe_quote(*a, SHELL_ESCAPE_EMPTY);
t = shell_maybe_quote(*a, flags);
if (!t)
return NULL;
@ -561,5 +561,5 @@ char* quote_command_line(char **argv) {
return NULL;
}
return TAKE_PTR(result);
return str_realloc(TAKE_PTR(result));
}

View File

@ -69,4 +69,4 @@ char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFl
char* shell_escape(const char *s, const char *bad);
char* shell_maybe_quote(const char *s, ShellEscapeFlags flags);
char* quote_command_line(char **argv);
char* quote_command_line(char **argv, ShellEscapeFlags flags);

View File

@ -11,7 +11,11 @@
#include "macro.h"
#include "string-util.h"
char* hw_addr_to_string(const struct hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]) {
char *hw_addr_to_string_full(
const struct hw_addr_data *addr,
HardwareAddressToStringFlags flags,
char buffer[static HW_ADDR_TO_STRING_MAX]) {
assert(addr);
assert(buffer);
assert(addr->length <= HW_ADDR_MAX_SIZE);
@ -19,10 +23,13 @@ char* hw_addr_to_string(const struct hw_addr_data *addr, char buffer[HW_ADDR_TO_
for (size_t i = 0, j = 0; i < addr->length; i++) {
buffer[j++] = hexchar(addr->bytes[i] >> 4);
buffer[j++] = hexchar(addr->bytes[i] & 0x0f);
buffer[j++] = ':';
if (!FLAGS_SET(flags, HW_ADDR_TO_STRING_NO_COLON))
buffer[j++] = ':';
}
buffer[addr->length > 0 ? addr->length * 3 - 1 : 0] = '\0';
buffer[addr->length == 0 || FLAGS_SET(flags, HW_ADDR_TO_STRING_NO_COLON) ?
addr->length * 2 :
addr->length * 3 - 1] = '\0';
return buffer;
}
@ -39,7 +46,7 @@ int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b)
return memcmp(a->bytes, b->bytes, a->length);
}
static void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state) {
void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state) {
assert(p);
assert(state);

View File

@ -31,16 +31,28 @@ static inline int parse_hw_addr(const char *s, struct hw_addr_data *ret) {
}
int parse_ether_addr(const char *s, struct ether_addr *ret);
typedef enum HardwareAddressToStringFlags {
HW_ADDR_TO_STRING_NO_COLON = 1 << 0,
} HardwareAddressToStringFlags;
#define HW_ADDR_TO_STRING_MAX (3*HW_ADDR_MAX_SIZE)
char* hw_addr_to_string(const struct hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]);
char *hw_addr_to_string_full(
const struct hw_addr_data *addr,
HardwareAddressToStringFlags flags,
char buffer[static HW_ADDR_TO_STRING_MAX]);
static inline char *hw_addr_to_string(const struct hw_addr_data *addr, char buffer[static HW_ADDR_TO_STRING_MAX]) {
return hw_addr_to_string_full(addr, 0, buffer);
}
/* Note: the lifetime of the compound literal is the immediately surrounding block,
* see C11 §6.5.2.5, and
* https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */
#define HW_ADDR_TO_STR(hw_addr) hw_addr_to_string((hw_addr), (char[HW_ADDR_TO_STRING_MAX]){})
#define HW_ADDR_TO_STR_FULL(hw_addr, flags) hw_addr_to_string_full((hw_addr), flags, (char[HW_ADDR_TO_STRING_MAX]){})
#define HW_ADDR_TO_STR(hw_addr) HW_ADDR_TO_STR_FULL(hw_addr, 0)
#define HW_ADDR_NULL ((const struct hw_addr_data){})
void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state);
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b);
static inline bool hw_addr_equal(const struct hw_addr_data *a, const struct hw_addr_data *b) {
return hw_addr_compare(a, b) == 0;

View File

@ -219,20 +219,9 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
if (!args)
return -ENOMEM;
for (size_t i = 0; args[i]; i++) {
char *e;
e = shell_maybe_quote(args[i], shflags);
if (!e)
return -ENOMEM;
free_and_replace(args[i], e);
}
ans = strv_join(args, " ");
ans = quote_command_line(args, shflags);
if (!ans)
return -ENOMEM;
} else {
/* Arguments are separated by NULs. Let's replace those with spaces. */
for (size_t i = 0; i < k - 1; i++)

View File

@ -3999,16 +3999,15 @@ static int exec_child(
exec_context_tty_reset(context, params);
if (unit_shall_confirm_spawn(unit)) {
const char *vc = params->confirm_spawn;
_cleanup_free_ char *cmdline = NULL;
cmdline = quote_command_line(command->argv);
cmdline = quote_command_line(command->argv, SHELL_ESCAPE_EMPTY);
if (!cmdline) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
r = ask_for_confirmation(context, vc, unit, cmdline);
r = ask_for_confirmation(context, params->confirm_spawn, unit, cmdline);
if (r != CONFIRM_EXECUTE) {
if (r == CONFIRM_PRETEND_SUCCESS) {
*exit_status = EXIT_SUCCESS;
@ -4884,7 +4883,7 @@ static int exec_child(
if (DEBUG_LOGGING) {
_cleanup_free_ char *line = NULL;
line = quote_command_line(final_argv);
line = quote_command_line(final_argv, SHELL_ESCAPE_EMPTY);
if (!line) {
*exit_status = EXIT_MEMORY;
return log_oom();
@ -4976,7 +4975,7 @@ int exec_spawn(Unit *unit,
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
line = quote_command_line(command->argv);
line = quote_command_line(command->argv, SHELL_ESCAPE_EMPTY);
if (!line)
return log_oom();
@ -6230,7 +6229,7 @@ static void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
prefix = strempty(prefix);
prefix2 = strjoina(prefix, "\t");
cmd = quote_command_line(c->argv);
cmd = quote_command_line(c->argv, SHELL_ESCAPE_EMPTY);
fprintf(f,
"%sCommand Line: %s\n",
prefix, cmd ? cmd : strerror_safe(ENOMEM));

View File

@ -968,7 +968,7 @@ int bus_socket_exec(sd_bus *b) {
_cleanup_free_ char *line = NULL;
if (b->exec_argv)
line = quote_command_line(b->exec_argv);
line = quote_command_line(b->exec_argv, SHELL_ESCAPE_EMPTY);
log_debug("sd-bus: starting bus%s%s with %s%s",
b->description ? " " : "", strempty(b->description),

View File

@ -968,7 +968,7 @@ DEFINE_TYPE_SYSTEM(rtnl_route);
static const NLType rtnl_neigh_types[] = {
[NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
[NDA_LLADDR] = { /* struct ether_addr, struct in_addr, or struct in6_addr */ },
[NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
[NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
[NDA_PROBES] = { .type = NETLINK_TYPE_U32 },
[NDA_VLAN] = { .type = NETLINK_TYPE_U16 },

View File

@ -196,11 +196,11 @@ int main(int argc, char **argv) {
test_find_language_fallback();
test_find_converted_keymap();
test_find_legacy_keymap();
assert_se(get_testdata_dir("test-keymap-util/kbd-model-map", &map) >= 0);
assert_se(setenv("SYSTEMD_KBD_MODEL_MAP", map, 1) == 0);
test_find_legacy_keymap();
test_vconsole_convert_to_x11();
test_x11_convert_to_vconsole();

View File

@ -91,7 +91,6 @@ void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
assert(neighbor);
siphash24_compress(&neighbor->family, sizeof(neighbor->family), state);
siphash24_compress(&neighbor->lladdr_size, sizeof(neighbor->lladdr_size), state);
switch (neighbor->family) {
case AF_INET:
@ -104,7 +103,7 @@ void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
break;
}
siphash24_compress(&neighbor->lladdr, neighbor->lladdr_size, state);
hw_addr_hash_func(&neighbor->ll_addr, state);
}
int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
@ -114,10 +113,6 @@ int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
if (r != 0)
return r;
r = CMP(a->lladdr_size, b->lladdr_size);
if (r != 0)
return r;
switch (a->family) {
case AF_INET:
case AF_INET6:
@ -126,7 +121,7 @@ int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
return r;
}
return memcmp(&a->lladdr, &b->lladdr, a->lladdr_size);
return hw_addr_compare(&a->ll_addr, &b->ll_addr);
}
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func, neighbor_free);
@ -163,7 +158,7 @@ static int neighbor_add(Link *link, Neighbor *neighbor) {
}
static void log_neighbor_debug(const Neighbor *neighbor, const char *str, const Link *link) {
_cleanup_free_ char *state = NULL, *lladdr = NULL, *dst = NULL;
_cleanup_free_ char *state = NULL, *dst = NULL;
assert(neighbor);
assert(str);
@ -172,19 +167,12 @@ static void log_neighbor_debug(const Neighbor *neighbor, const char *str, const
return;
(void) network_config_state_to_string_alloc(neighbor->state, &state);
if (neighbor->lladdr_size == sizeof(struct ether_addr))
(void) ether_addr_to_string_alloc(&neighbor->lladdr.mac, &lladdr);
else if (neighbor->lladdr_size == sizeof(struct in_addr))
(void) in_addr_to_string(AF_INET, &neighbor->lladdr.ip, &lladdr);
else if (neighbor->lladdr_size == sizeof(struct in6_addr))
(void) in_addr_to_string(AF_INET6, &neighbor->lladdr.ip, &lladdr);
(void) in_addr_to_string(neighbor->family, &neighbor->in_addr, &dst);
log_link_debug(link,
"%s %s neighbor (%s): lladdr: %s, dst: %s",
str, strna(network_config_source_to_string(neighbor->source)), strna(state),
strna(lladdr), strna(dst));
HW_ADDR_TO_STR(&neighbor->ll_addr), strna(dst));
}
static int neighbor_configure(
@ -213,7 +201,7 @@ static int neighbor_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not set state: %m");
r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr, neighbor->lladdr_size);
r = netlink_message_append_hw_addr(req, NDA_LLADDR, &neighbor->ll_addr);
if (r < 0)
return log_link_error_errno(link, r, "Could not append NDA_LLADDR attribute: %m");
@ -466,7 +454,6 @@ int request_process_neighbor(Request *req) {
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(neighbor_freep) Neighbor *tmp = NULL;
_cleanup_free_ void *lladdr = NULL;
Neighbor *neighbor = NULL;
uint16_t type, state;
int ifindex, r;
@ -536,15 +523,11 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
return 0;
}
r = sd_netlink_message_read_data(message, NDA_LLADDR, &tmp->lladdr_size, &lladdr);
r = netlink_message_read_hw_addr(message, NDA_LLADDR, &tmp->ll_addr);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid lladdr, ignoring: %m");
return 0;
} else if (!IN_SET(tmp->lladdr_size, sizeof(struct ether_addr), sizeof(struct in_addr), sizeof(struct in6_addr))) {
log_link_warning(link, "rtnl: received neighbor message with invalid lladdr size (%zu), ignoring: %m", tmp->lladdr_size);
log_link_warning_errno(link, r, "rtnl: received neighbor message without valid link layer address, ignoring: %m");
return 0;
}
memcpy(&tmp->lladdr, lladdr, tmp->lladdr_size);
(void) neighbor_get(link, tmp, &neighbor);
@ -596,7 +579,7 @@ static int neighbor_section_verify(Neighbor *neighbor) {
"Ignoring [Neighbor] section from line %u.",
neighbor->section->filename, neighbor->section->line);
if (neighbor->lladdr_size == 0)
if (neighbor->ll_addr.length == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Neighbor section without LinkLayerAddress= configured. "
"Ignoring [Neighbor] section from line %u.",
@ -628,20 +611,27 @@ int config_parse_neighbor_address(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
Network *network = userdata;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = neighbor_new_static(network, filename, section_line, &n);
if (r < 0)
return log_oom();
if (isempty(rvalue)) {
n->family = AF_UNSPEC;
n->in_addr = IN_ADDR_NULL;
TAKE_PTR(n);
return 0;
}
r = in_addr_from_string_auto(rvalue, &n->family, &n->in_addr);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
@ -650,7 +640,6 @@ int config_parse_neighbor_address(
}
TAKE_PTR(n);
return 0;
}
@ -666,74 +655,34 @@ int config_parse_neighbor_lladdr(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
int family, r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = neighbor_new_static(network, filename, section_line, &n);
if (r < 0)
return log_oom();
r = parse_ether_addr(rvalue, &n->lladdr.mac);
if (r >= 0)
n->lladdr_size = sizeof(n->lladdr.mac);
else {
r = in_addr_from_string_auto(rvalue, &family, &n->lladdr.ip);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Neighbor LinkLayerAddress= is invalid, ignoring assignment: %s",
rvalue);
return 0;
}
n->lladdr_size = family == AF_INET ? sizeof(n->lladdr.ip.in) : sizeof(n->lladdr.ip.in6);
}
TAKE_PTR(n);
return 0;
}
int config_parse_neighbor_hwaddr(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = neighbor_new_static(network, filename, section_line, &n);
if (r < 0)
return log_oom();
r = parse_ether_addr(rvalue, &n->lladdr.mac);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Neighbor MACAddress= is invalid, ignoring assignment: %s", rvalue);
if (isempty(rvalue)) {
n->ll_addr = HW_ADDR_NULL;
TAKE_PTR(n);
return 0;
}
n->lladdr_size = sizeof(n->lladdr.mac);
TAKE_PTR(n);
r = parse_hw_addr(rvalue, &n->ll_addr);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Neighbor %s= is invalid, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
TAKE_PTR(n);
return 0;
}

View File

@ -15,11 +15,6 @@ typedef struct Manager Manager;
typedef struct Network Network;
typedef struct Request Request;
union lladdr_union {
struct ether_addr mac;
union in_addr_union ip;
};
typedef struct Neighbor {
Network *network;
Link *link;
@ -29,8 +24,7 @@ typedef struct Neighbor {
int family;
union in_addr_union in_addr;
union lladdr_union lladdr;
size_t lladdr_size;
struct hw_addr_data ll_addr;
} Neighbor;
Neighbor *neighbor_free(Neighbor *neighbor);
@ -52,5 +46,4 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Neighbor, neighbor);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr);

View File

@ -156,7 +156,7 @@ IPv6AddressLabel.Prefix, config_parse_address_label_prefix,
IPv6AddressLabel.Label, config_parse_address_label, 0, 0
Neighbor.Address, config_parse_neighbor_address, 0, 0
Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0
Neighbor.MACAddress, config_parse_neighbor_hwaddr, 0, 0 /* deprecated */
Neighbor.MACAddress, config_parse_neighbor_lladdr, 0, 0 /* deprecated */
RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule_tos, 0, 0
RoutingPolicyRule.Priority, config_parse_routing_policy_rule_priority, 0, 0
RoutingPolicyRule.Table, config_parse_routing_policy_rule_table, 0, 0

View File

@ -206,7 +206,7 @@ static void test_shell_maybe_quote(void) {
static void test_quote_command_line_one(char **argv, const char *expected) {
_cleanup_free_ char *s;
assert_se(s = quote_command_line(argv));
assert_se(s = quote_command_line(argv, SHELL_ESCAPE_EMPTY));
log_info("%s", s);
assert_se(streq(s, expected));
}

View File

@ -957,7 +957,7 @@ static int builtin_net_id(sd_device *dev, sd_netlink **rtnl, int argc, char *arg
if (names_mac(dev, &info) >= 0) {
char str[ALTIFNAMSIZ];
xsprintf(str, "%s%s", prefix, HW_ADDR_TO_STR(&info.hw_addr));
xsprintf(str, "%s%s", prefix, HW_ADDR_TO_STR_FULL(&info.hw_addr, HW_ADDR_TO_STRING_NO_COLON));
udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
ieee_oui(dev, &info, test);

View File

@ -5,6 +5,7 @@
#include "dirent-util.h"
#include "errno-list.h"
#include "escape.h"
#include "fd-util.h"
#include "format-table.h"
#include "format-util.h"
@ -34,6 +35,7 @@ static bool arg_legend = true;
static char** arg_services = NULL;
static UserDBFlags arg_userdb_flags = 0;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static bool arg_chain = false;
STATIC_DESTRUCTOR_REGISTER(arg_services, strv_freep);
@ -586,33 +588,84 @@ static int display_services(int argc, char *argv[], void *userdata) {
static int ssh_authorized_keys(int argc, char *argv[], void *userdata) {
_cleanup_(user_record_unrefp) UserRecord *ur = NULL;
char **chain_invocation;
int r;
assert(argc >= 2);
if (arg_chain) {
/* If --chain is specified, the rest of the command line is the chain command */
if (argc < 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"No chain command line specified, refusing.");
/* Make similar restrictions on the chain command as OpenSSH itself makes on the primary command. */
if (!path_is_absolute(argv[2]))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Chain invocation of ssh-authorized-keys commands requires an absolute binary path argument.");
if (!path_is_normalized(argv[2]))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Chain invocation of ssh-authorized-keys commands requires an normalized binary path argument.");
chain_invocation = argv + 2;
} else {
/* If --chain is not specified, then refuse any further arguments */
if (argc > 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many arguments.");
chain_invocation = NULL;
}
r = userdb_by_name(argv[1], arg_userdb_flags, &ur);
if (r == -ESRCH)
return log_error_errno(r, "User %s does not exist.", argv[1]);
log_error_errno(r, "User %s does not exist.", argv[1]);
else if (r == -EHOSTDOWN)
return log_error_errno(r, "Selected user database service is not available for this request.");
log_error_errno(r, "Selected user database service is not available for this request.");
else if (r == -EINVAL)
return log_error_errno(r, "Failed to find user %s: %m (Invalid user name?)", argv[1]);
log_error_errno(r, "Failed to find user %s: %m (Invalid user name?)", argv[1]);
else if (r < 0)
return log_error_errno(r, "Failed to find user %s: %m", argv[1]);
if (strv_isempty(ur->ssh_authorized_keys))
log_debug("User record for %s has no public SSH keys.", argv[1]);
log_error_errno(r, "Failed to find user %s: %m", argv[1]);
else {
char **i;
if (strv_isempty(ur->ssh_authorized_keys))
log_debug("User record for %s has no public SSH keys.", argv[1]);
else {
char **i;
STRV_FOREACH(i, ur->ssh_authorized_keys)
printf("%s\n", *i);
STRV_FOREACH(i, ur->ssh_authorized_keys)
printf("%s\n", *i);
}
if (ur->incomplete) {
fflush(stdout);
log_warning("Warning: lacking rights to acquire privileged fields of user record of '%s', output incomplete.", ur->user_name);
}
}
if (ur->incomplete) {
fflush(stdout);
log_warning("Warning: lacking rights to acquire privileged fields of user record of '%s', output incomplete.", ur->user_name);
if (chain_invocation) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *s = NULL;
s = quote_command_line(chain_invocation, SHELL_ESCAPE_EMPTY);
if (!s)
return log_oom();
log_debug("Chain invoking: %s", s);
}
execv(chain_invocation[0], chain_invocation);
if (errno == ENOENT) /* Let's handle ENOENT gracefully */
log_warning_errno(errno, "Chain executable '%s' does not exist, ignoring chain invocation.", chain_invocation[0]);
else {
log_error_errno(errno, "Failed to invoke chain executable '%s': %m", chain_invocation[0]);
if (r >= 0)
r = -errno;
}
}
return EXIT_SUCCESS;
return r;
}
static int help(int argc, char *argv[], void *userdata) {
@ -633,6 +686,7 @@ static int help(int argc, char *argv[], void *userdata) {
" users-in-group [GROUP…] Show users that are members of specified group(s)\n"
" groups-of-user [USER…] Show groups the specified user(s) is a member of\n"
" services Show enabled database services\n"
" ssh-authorized-keys USER Show SSH authorized keys for user\n"
"\nOptions:\n"
" -h --help Show this help\n"
" --version Show package version\n"
@ -650,6 +704,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --with-varlink=BOOL Control whether to talk to services at all\n"
" --multiplexer=BOOL Control whether to use the multiplexer\n"
" --json=pretty|short JSON output mode\n"
" --chain Chain another command\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@ -672,6 +727,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SYNTHESIZE,
ARG_MULTIPLEXER,
ARG_JSON,
ARG_CHAIN,
};
static const struct option options[] = {
@ -687,6 +743,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "synthesize", required_argument, NULL, ARG_SYNTHESIZE },
{ "multiplexer", required_argument, NULL, ARG_MULTIPLEXER },
{ "json", required_argument, NULL, ARG_JSON },
{ "chain", no_argument, NULL, ARG_CHAIN },
{}
};
@ -712,7 +769,9 @@ static int parse_argv(int argc, char *argv[]) {
for (;;) {
int c;
c = getopt_long(argc, argv, "hjs:N", options, NULL);
c = getopt_long(argc, argv,
arg_chain ? "+hjs:N" : "hjs:N", /* When --chain was used disable parsing of further switches */
options, NULL);
if (c < 0)
break;
@ -829,6 +888,10 @@ static int parse_argv(int argc, char *argv[]) {
SET_FLAG(arg_userdb_flags, USERDB_AVOID_MULTIPLEXER, !r);
break;
case ARG_CHAIN:
arg_chain = true;
break;
case '?':
return -EINVAL;
@ -851,7 +914,7 @@ static int run(int argc, char *argv[]) {
/* This one is a helper for sshd_config's AuthorizedKeysCommand= setting, it's not a
* user-facing verb and thus should not appear in man pages or --help texts. */
{ "ssh-authorized-keys", 2, 2, 0, ssh_authorized_keys },
{ "ssh-authorized-keys", 2, VERB_ANY, 0, ssh_authorized_keys },
{}
};