summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am18
-rw-r--r--hwdb/60-evdev.hwdb11
-rw-r--r--man/resolved.conf.xml8
-rw-r--r--man/systemd-resolve.xml19
-rw-r--r--man/systemd.resource-control.xml6
-rw-r--r--man/systemd.service.xml10
-rw-r--r--man/timesyncd.conf.xml2
-rw-r--r--src/basic/fs-util.c3
-rw-r--r--src/basic/hexdecoct.c61
-rw-r--r--src/basic/hexdecoct.h5
-rw-r--r--src/basic/verbs.c6
-rw-r--r--src/basic/verbs.h3
-rw-r--r--src/boot/bootctl.c16
-rw-r--r--src/core/dbus-unit.c18
-rw-r--r--src/core/job.c12
-rw-r--r--src/core/job.h2
-rw-r--r--src/resolve/dns-type.c46
-rw-r--r--src/resolve/dns-type.h11
-rw-r--r--src/resolve/resolve-tool.c43
-rw-r--r--src/resolve/resolved-dns-dnssec.c201
-rw-r--r--src/resolve/resolved-dns-dnssec.h1
-rw-r--r--src/resolve/resolved-dns-packet.c49
-rw-r--r--src/resolve/resolved-dns-rr.c184
-rw-r--r--src/resolve/resolved-dns-rr.h11
-rw-r--r--src/resolve/resolved-dns-server.c13
-rw-r--r--src/resolve/resolved-dns-server.h4
-rw-r--r--src/resolve/resolved-manager.c2
-rw-r--r--src/resolve/resolved-resolv-conf.c2
-rw-r--r--src/resolve/resolved-resolv-conf.h2
-rw-r--r--src/resolve/resolved.c2
-rw-r--r--src/resolve/test-resolve-tables.c27
-rw-r--r--src/shared/test-tables.h15
-rw-r--r--src/systemctl/systemctl.c133
-rw-r--r--src/test/test-util.c21
-rw-r--r--test/TEST-06-SELINUX/Makefile10
-rw-r--r--test/TEST-06-SELINUX/systemd_test.if8
-rw-r--r--test/TEST-06-SELINUX/systemd_test.te50
-rwxr-xr-xtest/TEST-06-SELINUX/test-selinux-checks.sh13
-rwxr-xr-xtest/TEST-06-SELINUX/test.sh135
40 files changed, 927 insertions, 257 deletions
diff --git a/.gitignore b/.gitignore
index b9db9784ad..586b3796b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -251,6 +251,7 @@
/test-rbtree
/test-replace-var
/test-resolve
+/test-resolve-tables
/test-ring
/test-rlimit-util
/test-sched-prio
diff --git a/Makefile.am b/Makefile.am
index 90bc5d7ddc..0b4a6b9e2e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1499,6 +1499,7 @@ tests += \
test-af-list \
test-arphrd-list \
test-dns-domain \
+ test-resolve-tables \
test-install-root \
test-rlimit-util \
test-signal-util
@@ -1663,6 +1664,17 @@ test_dns_domain_LDADD = \
libsystemd-network.la \
libshared.la
+test_resolve_tables_SOURCES = \
+ src/resolve/test-resolve-tables.c \
+ src/shared/test-tables.h \
+ src/resolve/dns-type.c \
+ src/resolve/dns-type.h \
+ src/resolve/dns_type-from-name.h \
+ src/resolve/dns_type-to-name.h
+
+test_resolve_tables_LDADD = \
+ libshared.la
+
if ENABLE_EFI
manual_tests += \
test-boot-timestamp
@@ -5172,7 +5184,6 @@ EXTRA_DIST += \
# ------------------------------------------------------------------------------
if ENABLE_RESOLVED
-if HAVE_GCRYPT
systemd_resolved_SOURCES = \
src/resolve/resolved.c \
@@ -5286,6 +5297,8 @@ lib_LTLIBRARIES += \
systemd_resolve_SOURCES = \
src/resolve/resolve-tool.c \
+ src/resolve/resolved-dns-dnssec.c \
+ src/resolve/resolved-dns-dnssec.h \
src/resolve/resolved-dns-packet.c \
src/resolve/resolved-dns-packet.h \
src/resolve/resolved-dns-rr.c \
@@ -5304,7 +5317,7 @@ nodist_systemd_resolve_SOURCES = \
systemd_resolve_LDADD = \
libshared.la
-rootlibexec_PROGRAMS += \
+bin_PROGRAMS += \
systemd-resolve
tests += \
@@ -5341,7 +5354,6 @@ test_dnssec_complex_LDADD = \
libshared.la
endif
-endif
gperf_txt_sources += \
src/resolve/dns_type-list.txt
diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
index 577800e075..218d1c963d 100644
--- a/hwdb/60-evdev.hwdb
+++ b/hwdb/60-evdev.hwdb
@@ -147,3 +147,14 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T510*
EVDEV_ABS_01=841:5330:100
EVDEV_ABS_35=778:6239:72
EVDEV_ABS_36=841:5330:100
+
+#########################################
+# Samsung
+#########################################
+
+# Samsung 305V4
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/305V5A*
+ EVDEV_ABS_00=0:2480:28
+ EVDEV_ABS_01=0:1116:24
+ EVDEV_ABS_35=0:2480:28
+ EVDEV_ABS_36=0:1116:24
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index 3aa9c3acb1..920ce9e89b 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -68,6 +68,8 @@
<refsect1>
<title>Options</title>
+ <para>The following options are available in the <literal>[Resolve]</literal> section:</para>
+
<variablelist class='network-directives'>
<varlistentry>
@@ -129,8 +131,8 @@
<listitem><para>Takes a boolean argument or
<literal>allow-downgrade</literal>. If true all DNS lookups are
DNSSEC-validated locally (excluding LLMNR and Multicast
- DNS). If a response for a lookup request is detected invalid
- this is returned as lookup failure to applications. Note that
+ DNS). If the response to a lookup request is detected to be invalid
+ a lookup failure is returned to applications. Note that
this mode requires a DNS server that supports DNSSEC. If the
DNS server does not properly support DNSSEC all validations
will fail. If set to <literal>allow-downgrade</literal> DNSSEC
@@ -151,7 +153,7 @@
is built into the resolver, additional trust anchors may be
defined with
<citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- Trust anchors may change in regular intervals, and old trust
+ Trust anchors may change at regular intervals, and old trust
anchors may be revoked. In such a case DNSSEC validation is
not possible until new trust anchors are configured locally or
the resolver software package is updated with the new root
diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml
index c5ad6a0e3e..546054a403 100644
--- a/man/systemd-resolve.xml
+++ b/man/systemd-resolve.xml
@@ -64,14 +64,14 @@
<cmdsynopsis>
<command>systemd-resolve</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
- <command>--type=<replaceable>TYPE</replaceable></command>
+ <command> --type=<replaceable>TYPE</replaceable></command>
<arg choice="plain" rep="repeat"><replaceable>RRDOMAIN</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>systemd-resolve</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
- <command>--service</command>
+ <command> --service</command>
<arg choice="plain"><arg choice="opt"><arg choice="opt"><replaceable>NAME</replaceable></arg>
<replaceable>TYPE</replaceable></arg> <replaceable>DOMAIN</replaceable></arg>
</cmdsynopsis>
@@ -79,13 +79,13 @@
<cmdsynopsis>
<command>systemd-resolve</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
- <command>--statistics</command>
+ <command> --statistics</command>
</cmdsynopsis>
<cmdsynopsis>
<command>systemd-resolve</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
- <command>--reset-statistics</command>
+ <command> --reset-statistics</command>
</cmdsynopsis>
</refsynopsisdiv>
@@ -101,7 +101,8 @@
done, and a hostname is retrieved for the specified addresses.</para>
<para>The <option>--type=</option> switch may be used to specify a DNS resource record type (A, AAAA, SOA, MX, ...) in
- order to request a specific DNS resource record, instead of the address or reverse address lookups.</para>
+ order to request a specific DNS resource record, instead of the address or reverse address lookups.
+ The special value <literal>help</literal> may be used to list known values.</para>
<para>The <option>--service</option> switch may be used to resolve <ulink
url="https://tools.ietf.org/html/rfc2782">SRV</ulink> and <ulink
@@ -157,7 +158,9 @@
same time. The setting <literal>llmnr</literal> is identical to specifying this switch once with
<literal>llmnr-ipv4</literal> and once via <literal>llmnr-ipv6</literal>. Note that this option does not force
the service to resolve the operation with the specified protocol, as that might require a suitable network
- interface and configuration.</para></listitem>
+ interface and configuration.
+ The special value <literal>help</literal> may be used to list known values.
+ </para></listitem>
</varlistentry>
<varlistentry>
@@ -168,7 +171,9 @@
<listitem><para>Specifies the DNS resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to
look up. If these options are used a DNS resource record set matching the specified class and type is
- requested. The class defaults to IN if only a type is specified.</para></listitem>
+ requested. The class defaults to IN if only a type is specified.
+ The special value <literal>help</literal> may be used to list known values.
+ </para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index b1106c759d..b6b38fde58 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -459,6 +459,12 @@
this setting is the parent slice. Since the name of a slice
unit implies the parent slice, it is hence redundant to ever
set this parameter directly for slice units.</para>
+
+ <para>Special care should be taken when relying on the default slice assignment in templated service units
+ that have <varname>DefaultDependencies=no</varname> set, see
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>, section
+ "Automatic Dependencies" for details.</para>
+
</listitem>
</varlistentry>
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index b998a1f81f..d7b19ee27f 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -113,6 +113,16 @@
involved with early boot or late system shutdown should disable
this option.</para>
+ <para>Instanced service units (i.e. service units with an <literal>@</literal> in their name) are assigned by
+ default a per-template slice unit (see
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>), named after the
+ template unit, containing all instances of the specific template. This slice is normally stopped at shutdown,
+ together with all template instances. If that is not desired, set <varname>DefaultDependencies=no</varname> in the
+ template unit, and either define your own per-template slice unit file that also sets
+ <varname>DefaultDependencies=no</varname>, or set <varname>Slice=system.slice</varname> (or another suitable slice)
+ in the template unit. Also see
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
<para>Additional implicit dependencies may be added as result of
execution and resource control parameters as documented in
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
diff --git a/man/timesyncd.conf.xml b/man/timesyncd.conf.xml
index 10c2de89f6..8c86fd0074 100644
--- a/man/timesyncd.conf.xml
+++ b/man/timesyncd.conf.xml
@@ -68,6 +68,8 @@
<refsect1>
<title>Options</title>
+ <para>The following settings are configured in the <literal>[Time]</literal> section:</para>
+
<variablelist class='network-directives'>
<varlistentry>
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index d31bd6e273..61b651b573 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -341,7 +341,8 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
if (parents)
mkdir_parents(path, 0755);
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
+ fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
+ (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
if (fd < 0)
return -errno;
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
index 1e907de228..f30e028f45 100644
--- a/src/basic/hexdecoct.c
+++ b/src/basic/hexdecoct.c
@@ -514,14 +514,14 @@ int unbase64char(char c) {
return -EINVAL;
}
-char *base64mem(const void *p, size_t l) {
+ssize_t base64mem(const void *p, size_t l, char **out) {
char *r, *z;
const uint8_t *x;
/* three input bytes makes four output bytes, padding is added so we must round up */
z = r = malloc(4 * (l + 2) / 3 + 1);
if (!r)
- return NULL;
+ return -ENOMEM;
for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
@@ -549,9 +549,64 @@ char *base64mem(const void *p, size_t l) {
}
*z = 0;
- return r;
+ *out = r;
+ return z - r;
+}
+
+static int base64_append_width(char **prefix, int plen,
+ const char *sep, int indent,
+ const void *p, size_t l,
+ int width) {
+
+ _cleanup_free_ char *x = NULL;
+ char *t, *s;
+ ssize_t slen, len, avail;
+ int line, lines;
+
+ len = base64mem(p, l, &x);
+ if (len <= 0)
+ return len;
+
+ lines = (len + width - 1) / width;
+
+ slen = sep ? strlen(sep) : 0;
+ t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
+ if (!t)
+ return -ENOMEM;
+
+ memcpy(t + plen, sep, slen);
+
+ for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
+ int act = MIN(width, avail);
+
+ if (line > 0 || sep) {
+ memset(s, ' ', indent);
+ s += indent;
+ }
+
+ memcpy(s, x + width * line, act);
+ s += act;
+ *(s++) = line < lines - 1 ? '\n' : '\0';
+ avail -= act;
+ }
+ assert(avail == 0);
+
+ *prefix = t;
+ return 0;
}
+int base64_append(char **prefix, int plen,
+ const void *p, size_t l,
+ int indent, int width) {
+ if (plen > width / 2 || plen + indent > width)
+ /* leave indent on the left, keep last column free */
+ return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
+ else
+ /* leave plen on the left, keep last column free */
+ return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
+};
+
+
int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
_cleanup_free_ uint8_t *r = NULL;
int a, b, c, d;
diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h
index d9eb54a8a1..243c5e921e 100644
--- a/src/basic/hexdecoct.h
+++ b/src/basic/hexdecoct.h
@@ -49,7 +49,10 @@ int unbase64char(char c) _const_;
char *base32hexmem(const void *p, size_t l, bool padding);
int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
-char *base64mem(const void *p, size_t l);
+ssize_t base64mem(const void *p, size_t l, char **out);
+int base64_append(char **prefix, int plen,
+ const void *p, size_t l,
+ int margin, int width);
int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
void hexdump(FILE *f, const void *p, size_t s);
diff --git a/src/basic/verbs.c b/src/basic/verbs.c
index 7feb47c48e..6dded9fb77 100644
--- a/src/basic/verbs.c
+++ b/src/basic/verbs.c
@@ -28,6 +28,7 @@
#include "macro.h"
#include "string-util.h"
#include "verbs.h"
+#include "virt.h"
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
const Verb *verb;
@@ -84,6 +85,11 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
return -EINVAL;
}
+ if ((verb->flags & VERB_NOCHROOT) && running_in_chroot() > 0) {
+ log_info("Running in chroot, ignoring request.");
+ return 0;
+ }
+
if (name)
return verb->dispatch(left, argv + optind, userdata);
else {
diff --git a/src/basic/verbs.h b/src/basic/verbs.h
index d59e4d59b8..4132cad773 100644
--- a/src/basic/verbs.h
+++ b/src/basic/verbs.h
@@ -22,7 +22,8 @@
***/
#define VERB_ANY ((unsigned) -1)
-#define VERB_DEFAULT 1
+#define VERB_DEFAULT 1U
+#define VERB_NOCHROOT 2U
typedef struct {
const char *verb;
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 77eea6aada..13cf323bb7 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -39,6 +39,7 @@
#include "alloc-util.h"
#include "blkid-util.h"
+#include "dirent-util.h"
#include "efivars.h"
#include "fd-util.h"
#include "fileio.h"
@@ -249,13 +250,10 @@ static int enumerate_binaries(const char *esp_path, const char *path, const char
return log_error_errno(errno, "Failed to read \"%s\": %m", p);
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, break) {
_cleanup_close_ int fd = -1;
_cleanup_free_ char *v = NULL;
- if (de->d_name[0] == '.')
- continue;
-
if (!endswith_no_case(de->d_name, ".efi"))
continue;
@@ -614,12 +612,9 @@ static int install_binaries(const char *esp_path, bool force) {
if (!d)
return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, break) {
int k;
- if (de->d_name[0] == '.')
- continue;
-
if (!endswith_no_case(de->d_name, ".efi"))
continue;
@@ -797,13 +792,10 @@ static int remove_boot_efi(const char *esp_path) {
return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, break) {
_cleanup_close_ int fd = -1;
_cleanup_free_ char *v = NULL;
- if (de->d_name[0] == '.')
- continue;
-
if (!endswith_no_case(de->d_name, ".efi"))
continue;
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 386ea96d1b..dca9f77528 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -458,7 +458,10 @@ int bus_unit_method_start_generic(
assert(u);
assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
- r = mac_selinux_unit_access_check(u, message, job_type == JOB_STOP ? "stop" : "start", error);
+ r = mac_selinux_unit_access_check(
+ u, message,
+ job_type_to_access_method(job_type),
+ error);
if (r < 0)
return r;
@@ -983,6 +986,13 @@ int bus_unit_queue_job(
assert(type >= 0 && type < _JOB_TYPE_MAX);
assert(mode >= 0 && mode < _JOB_MODE_MAX);
+ r = mac_selinux_unit_access_check(
+ u, message,
+ job_type_to_access_method(type),
+ error);
+ if (r < 0)
+ return r;
+
if (reload_if_possible && unit_can_reload(u)) {
if (type == JOB_RESTART)
type = JOB_RELOAD_OR_START;
@@ -990,12 +1000,6 @@ int bus_unit_queue_job(
type = JOB_TRY_RELOAD;
}
- r = mac_selinux_unit_access_check(
- u, message,
- (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
- type == JOB_STOP ? "stop" : "reload", error);
- if (r < 0)
- return r;
if (type == JOB_STOP &&
(u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
diff --git a/src/core/job.c b/src/core/job.c
index 4e111ffb46..d8fdf1b53f 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -1240,3 +1240,15 @@ static const char* const job_result_table[_JOB_RESULT_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);
+
+const char* job_type_to_access_method(JobType t) {
+ assert(t >= 0);
+ assert(t < _JOB_TYPE_MAX);
+
+ if (IN_SET(t, JOB_START, JOB_RESTART, JOB_TRY_RESTART))
+ return "start";
+ else if (t == JOB_STOP)
+ return "stop";
+ else
+ return "reload";
+}
diff --git a/src/core/job.h b/src/core/job.h
index 52866fdc48..bbf5471e8b 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -240,3 +240,5 @@ const char* job_result_to_string(JobResult t) _const_;
JobResult job_result_from_string(const char *s) _pure_;
int job_get_timeout(Job *j, uint64_t *timeout) _pure_;
+
+const char* job_type_to_access_method(JobType t);
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c
index 56720646ca..fc2f1826fd 100644
--- a/src/resolve/dns-type.c
+++ b/src/resolve/dns-type.c
@@ -22,6 +22,7 @@
#include <sys/socket.h>
#include "dns-type.h"
+#include "parse-util.h"
#include "string-util.h"
typedef const struct {
@@ -41,10 +42,19 @@ int dns_type_from_string(const char *s) {
assert(s);
sc = lookup_dns_type(s, strlen(s));
- if (!sc)
- return _DNS_TYPE_INVALID;
+ if (sc)
+ return sc->id;
- return sc->id;
+ s = startswith_no_case(s, "TYPE");
+ if (s) {
+ unsigned x;
+
+ if (safe_atou(s, &x) >= 0 &&
+ x <= UINT16_MAX)
+ return (int) x;
+ }
+
+ return _DNS_TYPE_INVALID;
}
bool dns_type_is_pseudo(uint16_t type) {
@@ -228,3 +238,33 @@ int dns_class_from_string(const char *s) {
return _DNS_CLASS_INVALID;
}
+
+const char* tlsa_cert_usage_to_string(uint8_t cert_usage) {
+ switch(cert_usage) {
+ case 0: return "CA constraint";
+ case 1: return "Service certificate constraint";
+ case 2: return "Trust anchor assertion";
+ case 3: return "Domain-issued certificate";
+ case 4 ... 254: return "Unassigned";
+ case 255: return "Private use";
+ }
+}
+
+const char* tlsa_selector_to_string(uint8_t selector) {
+ switch(selector) {
+ case 0: return "Full Certificate";
+ case 1: return "SubjectPublicKeyInfo";
+ case 2 ... 254: return "Unassigned";
+ case 255: return "Private use";
+ }
+}
+
+const char* tlsa_matching_type_to_string(uint8_t selector) {
+ switch(selector) {
+ case 0: return "No hash used";
+ case 1: return "SHA-256";
+ case 2: return "SHA-512";
+ case 3 ... 254: return "Unassigned";
+ case 255: return "Private use";
+ }
+}
diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h
index 60ff160383..d025544bab 100644
--- a/src/resolve/dns-type.h
+++ b/src/resolve/dns-type.h
@@ -87,6 +87,7 @@ enum {
DNS_TYPE_TALINK,
DNS_TYPE_CDS,
DNS_TYPE_CDNSKEY,
+ DNS_TYPE_OPENPGPKEY,
DNS_TYPE_SPF = 0x63,
DNS_TYPE_NID,
@@ -138,8 +139,18 @@ int dns_type_to_af(uint16_t t);
bool dns_class_is_pseudo(uint16_t class);
bool dns_class_is_valid_rr(uint16_t class);
+/* TYPE?? follows http://tools.ietf.org/html/rfc3597#section-5 */
const char *dns_type_to_string(int type);
int dns_type_from_string(const char *s);
const char *dns_class_to_string(uint16_t type);
int dns_class_from_string(const char *name);
+
+/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.2 */
+const char *tlsa_cert_usage_to_string(uint8_t cert_usage);
+
+/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.3 */
+const char *tlsa_selector_to_string(uint8_t selector);
+
+/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.4 */
+const char *tlsa_matching_type_to_string(uint8_t selector);
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index fdaeb8d926..9bee953839 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolve-tool.c
@@ -900,6 +900,12 @@ static int reset_statistics(sd_bus *bus) {
return 0;
}
+static void help_protocol_types(void) {
+ if (arg_legend)
+ puts("Known protocol types:");
+ puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6");
+}
+
static void help_dns_types(void) {
int i;
const char *t;
@@ -930,22 +936,22 @@ static void help(void) {
printf("%s [OPTIONS...] NAME...\n"
"%s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n\n"
"Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -4 Resolve IPv4 addresses\n"
- " -6 Resolve IPv6 addresses\n"
- " -i --interface=INTERFACE Look on interface\n"
- " -p --protocol=PROTOCOL Look via protocol\n"
- " -t --type=TYPE Query RR with DNS type\n"
- " -c --class=CLASS Query RR with DNS class\n"
- " --service Resolve service (SRV)\n"
- " --service-address=BOOL Do [not] resolve address for services\n"
- " --service-txt=BOOL Do [not] resolve TXT records for services\n"
- " --cname=BOOL Do [not] follow CNAME redirects\n"
- " --search=BOOL Do [not] use search domains\n"
- " --legend=BOOL Do [not] print column headers and meta information\n"
- " --statistics Show resolver statistics\n"
- " --reset-statistics Reset resolver statistics\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " -4 Resolve IPv4 addresses\n"
+ " -6 Resolve IPv6 addresses\n"
+ " -i --interface=INTERFACE Look on interface\n"
+ " -p --protocol=PROTOCOL|help Look via protocol\n"
+ " -t --type=TYPE|help Query RR with DNS type\n"
+ " -c --class=CLASS|help Query RR with DNS class\n"
+ " --service Resolve service (SRV)\n"
+ " --service-address=BOOL Do [not] resolve address for services\n"
+ " --service-txt=BOOL Do [not] resolve TXT records for services\n"
+ " --cname=BOOL Do [not] follow CNAME redirects\n"
+ " --search=BOOL Do [not] use search domains\n"
+ " --legend=BOOL Do [not] print column headers and meta information\n"
+ " --statistics Show resolver statistics\n"
+ " --reset-statistics Reset resolver statistics\n"
, program_invocation_short_name, program_invocation_short_name);
}
@@ -1061,7 +1067,10 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'p':
- if (streq(optarg, "dns"))
+ if (streq(optarg, "help")) {
+ help_protocol_types();
+ return 0;
+ } else if (streq(optarg, "dns"))
arg_flags |= SD_RESOLVED_DNS;
else if (streq(optarg, "llmnr"))
arg_flags |= SD_RESOLVED_LLMNR;
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c
index 76c801cce8..21cf161494 100644
--- a/src/resolve/resolved-dns-dnssec.c
+++ b/src/resolve/resolved-dns-dnssec.c
@@ -19,7 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#ifdef HAVE_GCRYPT
#include <gcrypt.h>
+#endif
#include "alloc-util.h"
#include "dns-domain.h"
@@ -48,19 +50,6 @@
* Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
*/
-static void initialize_libgcrypt(void) {
- const char *p;
-
- if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
- return;
-
- p = gcry_check_version("1.4.5");
- assert(p);
-
- gcry_control(GCRYCTL_DISABLE_SECMEM);
- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
-}
-
uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
const uint8_t *p;
uint32_t sum, f;
@@ -88,6 +77,70 @@ uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
return sum & UINT32_C(0xFFFF);
}
+int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) {
+ size_t c = 0;
+ int r;
+
+ /* Converts the specified hostname into DNSSEC canonicalized
+ * form. */
+
+ if (buffer_max < 2)
+ return -ENOBUFS;
+
+ for (;;) {
+ r = dns_label_unescape(&n, buffer, buffer_max);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ if (buffer_max < (size_t) r + 2)
+ return -ENOBUFS;
+
+ /* The DNSSEC canonical form is not clear on what to
+ * do with dots appearing in labels, the way DNS-SD
+ * does it. Refuse it for now. */
+
+ if (memchr(buffer, '.', r))
+ return -EINVAL;
+
+ ascii_strlower_n(buffer, (size_t) r);
+ buffer[r] = '.';
+
+ buffer += r + 1;
+ c += r + 1;
+
+ buffer_max -= r + 1;
+ }
+
+ if (c <= 0) {
+ /* Not even a single label: this is the root domain name */
+
+ assert(buffer_max > 2);
+ buffer[0] = '.';
+ buffer[1] = 0;
+
+ return 1;
+ }
+
+ return (int) c;
+}
+
+#ifdef HAVE_GCRYPT
+
+static void initialize_libgcrypt(void) {
+ const char *p;
+
+ if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
+ return;
+
+ p = gcry_check_version("1.4.5");
+ assert(p);
+
+ gcry_control(GCRYCTL_DISABLE_SECMEM);
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+}
+
static int rr_compare(const void *a, const void *b) {
DnsResourceRecord **x = (DnsResourceRecord**) a, **y = (DnsResourceRecord**) b;
size_t m;
@@ -971,55 +1024,6 @@ int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
return 0;
}
-int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) {
- size_t c = 0;
- int r;
-
- /* Converts the specified hostname into DNSSEC canonicalized
- * form. */
-
- if (buffer_max < 2)
- return -ENOBUFS;
-
- for (;;) {
- r = dns_label_unescape(&n, buffer, buffer_max);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- if (buffer_max < (size_t) r + 2)
- return -ENOBUFS;
-
- /* The DNSSEC canonical form is not clear on what to
- * do with dots appearing in labels, the way DNS-SD
- * does it. Refuse it for now. */
-
- if (memchr(buffer, '.', r))
- return -EINVAL;
-
- ascii_strlower_n(buffer, (size_t) r);
- buffer[r] = '.';
-
- buffer += r + 1;
- c += r + 1;
-
- buffer_max -= r + 1;
- }
-
- if (c <= 0) {
- /* Not even a single label: this is the root domain name */
-
- assert(buffer_max > 2);
- buffer[0] = '.';
- buffer[1] = 0;
-
- return 1;
- }
-
- return (int) c;
-}
-
static int digest_to_gcrypt_md(uint8_t algorithm) {
/* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */
@@ -1882,7 +1886,7 @@ int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
return 0;
}
-int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) {
+static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) {
DnsResourceRecord *rr;
DnsAnswerFlags flags;
int r;
@@ -2114,6 +2118,77 @@ int dnssec_test_positive_wildcard(
return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated);
}
+#else
+
+int dnssec_verify_rrset(
+ DnsAnswer *a,
+ const DnsResourceKey *key,
+ DnsResourceRecord *rrsig,
+ DnsResourceRecord *dnskey,
+ usec_t realtime,
+ DnssecResult *result) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_verify_rrset_search(
+ DnsAnswer *a,
+ const DnsResourceKey *key,
+ DnsAnswer *validated_dnskeys,
+ usec_t realtime,
+ DnssecResult *result,
+ DnsResourceRecord **ret_rrsig) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
+
+ return -EOPNOTSUPP;
+}
+
+int dnssec_test_positive_wildcard(
+ DnsAnswer *answer,
+ const char *name,
+ const char *source,
+ const char *zone,
+ bool *authenticated) {
+
+ return -EOPNOTSUPP;
+}
+
+#endif
+
static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
[DNSSEC_VALIDATED] = "validated",
[DNSSEC_VALIDATED_WILDCARD] = "validated-wildcard",
diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h
index c99861b8e5..4542f0aa89 100644
--- a/src/resolve/resolved-dns-dnssec.h
+++ b/src/resolve/resolved-dns-dnssec.h
@@ -94,7 +94,6 @@ typedef enum DnssecNsecResult {
int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl);
-int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated);
int dnssec_test_positive_wildcard(DnsAnswer *a, const char *name, const char *source, const char *zone, bool *authenticated);
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 032e719595..5cbe20832f 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -1058,11 +1058,28 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
break;
+ case DNS_TYPE_TLSA:
+ r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
+ break;
+
case DNS_TYPE_OPT:
+ case DNS_TYPE_OPENPGPKEY:
case _DNS_TYPE_INVALID: /* unparseable */
default:
- r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
+ r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
break;
}
if (r < 0)
@@ -1976,10 +1993,36 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_fl
break;
}
+ case DNS_TYPE_TLSA:
+ r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_memdup(p, rdlength - 3,
+ &rr->tlsa.data, &rr->tlsa.data_size,
+ NULL);
+ if (rr->tlsa.data_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ break;
+
case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
+ case DNS_TYPE_OPENPGPKEY:
default:
unparseable:
- r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
+ r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
if (r < 0)
goto fail;
break;
@@ -2021,7 +2064,7 @@ static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) {
return false;
p = rr->opt.data;
- l = rr->opt.size;
+ l = rr->opt.data_size;
while (l > 0) {
uint16_t option_code, option_length;
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 7273ef3825..783ec7516c 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -25,11 +25,13 @@
#include "dns-domain.h"
#include "dns-type.h"
#include "hexdecoct.h"
+#include "resolved-dns-dnssec.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-rr.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
DnsResourceKey *k;
@@ -486,6 +488,11 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
case DNS_TYPE_AAAA:
break;
+ case DNS_TYPE_TLSA:
+ free(rr->tlsa.data);
+ break;
+
+ case DNS_TYPE_OPENPGPKEY:
default:
free(rr->generic.data);
}
@@ -564,6 +571,10 @@ int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const u
return 0;
}
+#define FIELD_EQUAL(a, b, field) \
+ ((a).field ## _size == (b).field ## _size && \
+ memcmp((a).field, (b).field, (a).field ## _size) == 0)
+
int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
int r;
@@ -645,36 +656,30 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
return a->ds.key_tag == b->ds.key_tag &&
a->ds.algorithm == b->ds.algorithm &&
a->ds.digest_type == b->ds.digest_type &&
- a->ds.digest_size == b->ds.digest_size &&
- memcmp(a->ds.digest, b->ds.digest, a->ds.digest_size) == 0;
+ FIELD_EQUAL(a->ds, b->ds, digest);
case DNS_TYPE_SSHFP:
return a->sshfp.algorithm == b->sshfp.algorithm &&
a->sshfp.fptype == b->sshfp.fptype &&
- a->sshfp.fingerprint_size == b->sshfp.fingerprint_size &&
- memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
+ FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
case DNS_TYPE_DNSKEY:
return a->dnskey.flags == b->dnskey.flags &&
a->dnskey.protocol == b->dnskey.protocol &&
a->dnskey.algorithm == b->dnskey.algorithm &&
- a->dnskey.key_size == b->dnskey.key_size &&
- memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
+ FIELD_EQUAL(a->dnskey, b->dnskey, key);
case DNS_TYPE_RRSIG:
/* do the fast comparisons first */
- if (a->rrsig.type_covered != b->rrsig.type_covered ||
- a->rrsig.algorithm != b->rrsig.algorithm ||
- a->rrsig.labels != b->rrsig.labels ||
- a->rrsig.original_ttl != b->rrsig.original_ttl ||
- a->rrsig.expiration != b->rrsig.expiration ||
- a->rrsig.inception != b->rrsig.inception ||
- a->rrsig.key_tag != b->rrsig.key_tag ||
- a->rrsig.signature_size != b->rrsig.signature_size ||
- memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
- return false;
-
- return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
+ return a->rrsig.type_covered == b->rrsig.type_covered &&
+ a->rrsig.algorithm == b->rrsig.algorithm &&
+ a->rrsig.labels == b->rrsig.labels &&
+ a->rrsig.original_ttl == b->rrsig.original_ttl &&
+ a->rrsig.expiration == b->rrsig.expiration &&
+ a->rrsig.inception == b->rrsig.inception &&
+ a->rrsig.key_tag == b->rrsig.key_tag &&
+ FIELD_EQUAL(a->rrsig, b->rrsig, signature) &&
+ dns_name_equal(a->rrsig.signer, b->rrsig.signer);
case DNS_TYPE_NSEC:
return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
@@ -682,16 +687,20 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
case DNS_TYPE_NSEC3:
return a->nsec3.algorithm == b->nsec3.algorithm &&
- a->nsec3.flags == b->nsec3.flags &&
- a->nsec3.iterations == b->nsec3.iterations &&
- a->nsec3.salt_size == b->nsec3.salt_size &&
- memcmp(a->nsec3.salt, b->nsec3.salt, a->nsec3.salt_size) == 0 &&
- memcmp(a->nsec3.next_hashed_name, b->nsec3.next_hashed_name, a->nsec3.next_hashed_name_size) == 0 &&
- bitmap_equal(a->nsec3.types, b->nsec3.types);
+ a->nsec3.flags == b->nsec3.flags &&
+ a->nsec3.iterations == b->nsec3.iterations &&
+ FIELD_EQUAL(a->nsec3, b->nsec3, salt) &&
+ FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) &&
+ bitmap_equal(a->nsec3.types, b->nsec3.types);
+
+ case DNS_TYPE_TLSA:
+ return a->tlsa.cert_usage == b->tlsa.cert_usage &&
+ a->tlsa.selector == b->tlsa.selector &&
+ a->tlsa.matching_type == b->tlsa.matching_type &&
+ FIELD_EQUAL(a->tlsa, b->tlsa, data);
default:
- return a->generic.size == b->generic.size &&
- memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
+ return FIELD_EQUAL(a->generic, b->generic, data);
}
}
@@ -958,23 +967,47 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
case DNS_TYPE_DNSKEY: {
_cleanup_free_ char *alg = NULL;
+ char *ss;
+ int n, n1;
+ uint16_t key_tag;
+
+ key_tag = dnssec_keytag(rr, true);
r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
if (r < 0)
return NULL;
- t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
- if (!t)
- return NULL;
-
- r = asprintf(&s, "%s %u %u %s %s",
+ r = asprintf(&s, "%s %n%u %u %s %n",
k,
+ &n1,
rr->dnskey.flags,
rr->dnskey.protocol,
alg,
- t);
+ &n);
+ if (r < 0)
+ return NULL;
+
+ r = base64_append(&s, n,
+ rr->dnskey.key, rr->dnskey.key_size,
+ 8, columns());
if (r < 0)
return NULL;
+
+ r = asprintf(&ss, "%s\n"
+ "%*s-- Flags:%s%s%s\n"
+ "%*s-- Key tag: %u",
+ s,
+ n1, "",
+ rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "",
+ rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "",
+ rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "",
+ n1, "",
+ key_tag);
+ if (r < 0)
+ return NULL;
+ free(s);
+ s = ss;
+
break;
}
@@ -982,6 +1015,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
_cleanup_free_ char *alg = NULL;
char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
const char *type;
+ int n;
type = dns_type_to_string(rr->rrsig.type_covered);
@@ -989,10 +1023,6 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
if (r < 0)
return NULL;
- t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
- if (!t)
- return NULL;
-
r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
if (r < 0)
return NULL;
@@ -1004,7 +1034,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
/* TYPE?? follows
* http://tools.ietf.org/html/rfc3597#section-5 */
- r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %s",
+ r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n",
k,
type ?: "TYPE",
type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
@@ -1015,9 +1045,16 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
inception,
rr->rrsig.key_tag,
rr->rrsig.signer,
- t);
+ &n);
if (r < 0)
return NULL;
+
+ r = base64_append(&s, n,
+ rr->rrsig.signature, rr->rrsig.signature_size,
+ 8, columns());
+ if (r < 0)
+ return NULL;
+
break;
}
@@ -1065,13 +1102,70 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
break;
}
+ case DNS_TYPE_TLSA: {
+ const char *cert_usage, *selector, *matching_type;
+ char *ss;
+ int n;
+
+ cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage);
+ selector = tlsa_selector_to_string(rr->tlsa.selector);
+ matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type);
+
+ r = asprintf(&s, "%s %u %u %u %n",
+ k,
+ rr->tlsa.cert_usage,
+ rr->tlsa.selector,
+ rr->tlsa.matching_type,
+ &n);
+ if (r < 0)
+ return NULL;
+
+ r = base64_append(&s, n,
+ rr->tlsa.data, rr->tlsa.data_size,
+ 8, columns());
+ if (r < 0)
+ return NULL;
+
+ r = asprintf(&ss, "%s\n"
+ "%*s-- Cert. usage: %s\n"
+ "%*s-- Selector: %s\n"
+ "%*s-- Matching type: %s",
+ s,
+ n - 6, "", cert_usage,
+ n - 6, "", selector,
+ n - 6, "", matching_type);
+ if (r < 0)
+ return NULL;
+ free(s);
+ s = ss;
+
+ break;
+ }
+
+ case DNS_TYPE_OPENPGPKEY: {
+ int n;
+
+ r = asprintf(&s, "%s %n",
+ k,
+ &n);
+ if (r < 0)
+ return NULL;
+
+ r = base64_append(&s, n,
+ rr->generic.data, rr->generic.data_size,
+ 8, columns());
+ if (r < 0)
+ return NULL;
+ break;
+ }
+
default:
- t = hexmem(rr->generic.data, rr->generic.size);
+ t = hexmem(rr->generic.data, rr->generic.data_size);
if (!t)
return NULL;
/* Format as documented in RFC 3597, Section 5 */
- r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t);
+ r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
if (r < 0)
return NULL;
break;
@@ -1331,8 +1425,16 @@ static void dns_resource_record_hash_func(const void *i, struct siphash *state)
/* FIXME: We leave the bitmaps out */
break;
+ case DNS_TYPE_TLSA:
+ siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
+ siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
+ siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
+ siphash24_compress(&rr->tlsa.data, rr->tlsa.data_size, state);
+ break;
+
+ case DNS_TYPE_OPENPGPKEY:
default:
- siphash24_compress(rr->generic.data, rr->generic.size, state);
+ siphash24_compress(rr->generic.data, rr->generic.data_size, state);
break;
}
}
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index d9c31e81c5..37c4487332 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -129,7 +129,7 @@ struct DnsResourceRecord {
union {
struct {
void *data;
- size_t size;
+ size_t data_size;
} generic, opt;
struct {
@@ -242,6 +242,15 @@ struct DnsResourceRecord {
size_t next_hashed_name_size;
Bitmap *types;
} nsec3;
+
+ /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */
+ struct {
+ uint8_t cert_usage;
+ uint8_t selector;
+ uint8_t matching_type;
+ void *data;
+ size_t data_size;
+ } tlsa;
};
};
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index e1d2025863..43ec92f4f0 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -657,7 +657,9 @@ DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
return s;
if (s)
- log_info("Switching to system DNS server %s.", dns_server_string(s));
+ log_info("Switching to %s DNS server %s.",
+ dns_server_type_to_string(s->type),
+ dns_server_string(s));
dns_server_unref(m->current_dns_server);
m->current_dns_server = dns_server_ref(s);
@@ -675,7 +677,7 @@ DnsServer *manager_get_dns_server(Manager *m) {
/* Try to read updates resolv.conf */
manager_read_resolv_conf(m);
- /* If no DNS server was chose so far, pick the first one */
+ /* If no DNS server was chosen so far, pick the first one */
if (!m->current_dns_server)
manager_set_dns_server(m, m->dns_servers);
@@ -723,6 +725,13 @@ void manager_next_dns_server(Manager *m) {
manager_set_dns_server(m, m->dns_servers);
}
+static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
+ [DNS_SERVER_SYSTEM] = "system",
+ [DNS_SERVER_FALLBACK] = "fallback",
+ [DNS_SERVER_LINK] = "link",
+};
+DEFINE_STRING_TABLE_LOOKUP(dns_server_type, DnsServerType);
+
static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = {
[DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP",
[DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP",
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index 2a3c921678..7a885655a4 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -30,6 +30,10 @@ typedef enum DnsServerType {
DNS_SERVER_FALLBACK,
DNS_SERVER_LINK,
} DnsServerType;
+#define _DNS_SERVER_TYPE_MAX (DNS_SERVER_LINK + 1)
+
+const char* dns_server_type_to_string(DnsServerType i) _const_;
+DnsServerType dns_server_type_from_string(const char *s) _pure_;
typedef enum DnsServerFeatureLevel {
DNS_SERVER_FEATURE_LEVEL_TCP,
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 4306403834..fbd188c2ac 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -288,7 +288,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
r = manager_write_resolv_conf(m);
if (r < 0)
- log_warning_errno(r, "Could not update resolv.conf: %m");
+ log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m");
return 0;
}
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c
index 7567f4c369..c5ce9c4f01 100644
--- a/src/resolve/resolved-resolv-conf.c
+++ b/src/resolve/resolved-resolv-conf.c
@@ -226,8 +226,6 @@ static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *doma
int manager_write_resolv_conf(Manager *m) {
- #define PRIVATE_RESOLV_CONF "/run/systemd/resolve/resolv.conf"
-
_cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
diff --git a/src/resolve/resolved-resolv-conf.h b/src/resolve/resolved-resolv-conf.h
index a3355e994b..7081563965 100644
--- a/src/resolve/resolved-resolv-conf.h
+++ b/src/resolve/resolved-resolv-conf.h
@@ -23,5 +23,7 @@
#include "resolved-manager.h"
+#define PRIVATE_RESOLV_CONF "/run/systemd/resolve/resolv.conf"
+
int manager_read_resolv_conf(Manager *m);
int manager_write_resolv_conf(Manager *m);
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index 472bb32764..eee52da882 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -91,7 +91,7 @@ int main(int argc, char *argv[]) {
* symlink */
r = manager_write_resolv_conf(m);
if (r < 0)
- log_warning_errno(r, "Could not create resolv.conf: %m");
+ log_warning_errno(r, "Could not create "PRIVATE_RESOLV_CONF": %m");
sd_notify(false,
"READY=1\n"
diff --git a/src/resolve/test-resolve-tables.c b/src/resolve/test-resolve-tables.c
new file mode 100644
index 0000000000..63660afc87
--- /dev/null
+++ b/src/resolve/test-resolve-tables.c
@@ -0,0 +1,27 @@
+/***
+ This file is part of systemd
+
+ Copyright 2013 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "dns-type.h"
+#include "test-tables.h"
+
+int main(int argc, char **argv) {
+ test_table_sparse(dns_type, DNS_TYPE);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/shared/test-tables.h b/src/shared/test-tables.h
index 74f1716fe0..228e510104 100644
--- a/src/shared/test-tables.h
+++ b/src/shared/test-tables.h
@@ -28,18 +28,25 @@ static inline void _test_table(const char *name,
reverse_t reverse,
int size,
bool sparse) {
- int i;
+ int i, boring = 0;
for (i = -1; i < size + 1; i++) {
const char* val = lookup(i);
int rev;
- if (val)
+ if (val) {
rev = reverse(val);
- else
+ boring = 0;
+ } else {
rev = reverse("--no-such--value----");
+ boring += i >= 0;
+ }
+
+ if (boring < 1 || i == size)
+ printf("%s: %d → %s → %d\n", name, i, val, rev);
+ else if (boring == 1)
+ printf("%*s ...\n", (int) strlen(name), "");
- printf("%s: %d → %s → %d\n", name, i, val, rev);
assert_se(!(i >= 0 && i < size ?
sparse ? rev != i && rev != -1 : val == NULL || rev != i :
val != NULL || rev != -1));
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index f5703af241..078c1b5ea4 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5792,7 +5792,7 @@ static int is_system_running(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r;
- if (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted()) {
+ if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
if (!arg_quiet)
puts("offline");
return EXIT_FAILURE;
@@ -7325,70 +7325,71 @@ static int talk_initctl(void) {
static int systemctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
- { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_units },
- { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
- { "list-sockets", VERB_ANY, VERB_ANY, 0, list_sockets },
- { "list-timers", VERB_ANY, VERB_ANY, 0, list_timers },
- { "list-jobs", VERB_ANY, VERB_ANY, 0, list_jobs },
- { "list-machines", VERB_ANY, VERB_ANY, 0, list_machines },
- { "clear-jobs", VERB_ANY, 1, 0, daemon_reload },
- { "cancel", VERB_ANY, VERB_ANY, 0, cancel_job },
- { "start", 2, VERB_ANY, 0, start_unit },
- { "stop", 2, VERB_ANY, 0, start_unit },
- { "condstop", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */
- { "reload", 2, VERB_ANY, 0, start_unit },
- { "restart", 2, VERB_ANY, 0, start_unit },
- { "try-restart", 2, VERB_ANY, 0, start_unit },
- { "reload-or-restart", 2, VERB_ANY, 0, start_unit },
- { "reload-or-try-restart", 2, VERB_ANY, 0, start_unit },
- { "force-reload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with SysV */
- { "condreload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */
- { "condrestart", 2, VERB_ANY, 0, start_unit }, /* For compatibility with RH */
- { "isolate", 2, 2, 0, start_unit },
- { "kill", 2, VERB_ANY, 0, kill_unit },
- { "is-active", 2, VERB_ANY, 0, check_unit_active },
- { "check", 2, VERB_ANY, 0, check_unit_active },
- { "is-failed", 2, VERB_ANY, 0, check_unit_failed },
- { "show", VERB_ANY, VERB_ANY, 0, show },
- { "cat", 2, VERB_ANY, 0, cat },
- { "status", VERB_ANY, VERB_ANY, 0, show },
- { "help", VERB_ANY, VERB_ANY, 0, show },
- { "daemon-reload", VERB_ANY, 1, 0, daemon_reload },
- { "daemon-reexec", VERB_ANY, 1, 0, daemon_reload },
- { "show-environment", VERB_ANY, 1, 0, show_environment },
- { "set-environment", 2, VERB_ANY, 0, set_environment },
- { "unset-environment", 2, VERB_ANY, 0, set_environment },
- { "import-environment", VERB_ANY, VERB_ANY, 0, import_environment},
- { "halt", VERB_ANY, 1, 0, start_special },
- { "poweroff", VERB_ANY, 1, 0, start_special },
- { "reboot", VERB_ANY, 2, 0, start_special },
- { "kexec", VERB_ANY, 1, 0, start_special },
- { "suspend", VERB_ANY, 1, 0, start_special },
- { "hibernate", VERB_ANY, 1, 0, start_special },
- { "hybrid-sleep", VERB_ANY, 1, 0, start_special },
- { "default", VERB_ANY, 1, 0, start_special },
- { "rescue", VERB_ANY, 1, 0, start_special },
- { "emergency", VERB_ANY, 1, 0, start_special },
- { "exit", VERB_ANY, 2, 0, start_special },
- { "reset-failed", VERB_ANY, VERB_ANY, 0, reset_failed },
- { "enable", 2, VERB_ANY, 0, enable_unit },
- { "disable", 2, VERB_ANY, 0, enable_unit },
- { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
- { "reenable", 2, VERB_ANY, 0, enable_unit },
- { "preset", 2, VERB_ANY, 0, enable_unit },
- { "preset-all", VERB_ANY, 1, 0, preset_all },
- { "mask", 2, VERB_ANY, 0, enable_unit },
- { "unmask", 2, VERB_ANY, 0, enable_unit },
- { "link", 2, VERB_ANY, 0, enable_unit },
- { "switch-root", 2, VERB_ANY, 0, switch_root },
- { "list-dependencies", VERB_ANY, 2, 0, list_dependencies },
- { "set-default", 2, 2, 0, set_default },
- { "get-default", VERB_ANY, 1, 0, get_default, },
- { "set-property", 3, VERB_ANY, 0, set_property },
- { "is-system-running", VERB_ANY, 1, 0, is_system_running },
- { "add-wants", 3, VERB_ANY, 0, add_dependency },
- { "add-requires", 3, VERB_ANY, 0, add_dependency },
- { "edit", 2, VERB_ANY, 0, edit },
+ { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_NOCHROOT, list_units },
+ { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
+ { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets },
+ { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers },
+ { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs },
+ { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines },
+ { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
+ { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job },
+ { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
+ { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */
+ { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
+ { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */
+ { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
+ { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */
+ { "isolate", 2, 2, VERB_NOCHROOT, start_unit },
+ { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit },
+ { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
+ { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
+ { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed },
+ { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
+ { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat },
+ { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
+ { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
+ { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
+ { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
+ { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment },
+ { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
+ { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
+ { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment},
+ { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_special },
+ { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_special },
+ { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special },
+ { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed },
+ { "enable", 2, VERB_ANY, 0, enable_unit },
+ { "disable", 2, VERB_ANY, 0, enable_unit },
+ { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
+ { "reenable", 2, VERB_ANY, 0, enable_unit },
+ { "preset", 2, VERB_ANY, 0, enable_unit },
+ { "preset-all", VERB_ANY, 1, 0, preset_all },
+ { "mask", 2, VERB_ANY, 0, enable_unit },
+ { "unmask", 2, VERB_ANY, 0, enable_unit },
+ { "link", 2, VERB_ANY, 0, enable_unit },
+ { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root },
+ { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies },
+ { "set-default", 2, 2, 0, set_default },
+ { "get-default", VERB_ANY, 1, 0, get_default, },
+ { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property },
+ { "is-system-running", VERB_ANY, 1, 0, is_system_running },
+ { "add-wants", 3, VERB_ANY, 0, add_dependency },
+ { "add-requires", 3, VERB_ANY, 0, add_dependency },
+ { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit },
{}
};
@@ -7642,7 +7643,7 @@ int main(int argc, char*argv[]) {
if (r <= 0)
goto finish;
- if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
+ if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
log_info("Running in chroot, ignoring request.");
r = 0;
goto finish;
diff --git a/src/test/test-util.c b/src/test/test-util.c
index f6ed55878c..e199497818 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -545,38 +545,31 @@ static void test_unbase32hexmem(void) {
static void test_base64mem(void) {
char *b64;
- b64 = base64mem("", strlen(""));
- assert_se(b64);
+ assert_se(base64mem("", strlen(""), &b64) == 0);
assert_se(streq(b64, ""));
free(b64);
- b64 = base64mem("f", strlen("f"));
- assert_se(b64);
+ assert_se(base64mem("f", strlen("f"), &b64) == 4);
assert_se(streq(b64, "Zg=="));
free(b64);
- b64 = base64mem("fo", strlen("fo"));
- assert_se(b64);
+ assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
assert_se(streq(b64, "Zm8="));
free(b64);
- b64 = base64mem("foo", strlen("foo"));
- assert_se(b64);
+ assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
assert_se(streq(b64, "Zm9v"));
free(b64);
- b64 = base64mem("foob", strlen("foob"));
- assert_se(b64);
+ assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
assert_se(streq(b64, "Zm9vYg=="));
free(b64);
- b64 = base64mem("fooba", strlen("fooba"));
- assert_se(b64);
+ assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmE="));
free(b64);
- b64 = base64mem("foobar", strlen("foobar"));
- assert_se(b64);
+ assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmFy"));
free(b64);
}
diff --git a/test/TEST-06-SELINUX/Makefile b/test/TEST-06-SELINUX/Makefile
new file mode 100644
index 0000000000..5e89a29eff
--- /dev/null
+++ b/test/TEST-06-SELINUX/Makefile
@@ -0,0 +1,10 @@
+all:
+ @make -s --no-print-directory -C ../.. all
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all
+setup:
+ @make --no-print-directory -C ../.. all
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup
+clean:
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean
+run:
+ @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run
diff --git a/test/TEST-06-SELINUX/systemd_test.if b/test/TEST-06-SELINUX/systemd_test.if
new file mode 100644
index 0000000000..25c91adce9
--- /dev/null
+++ b/test/TEST-06-SELINUX/systemd_test.if
@@ -0,0 +1,8 @@
+template(`systemd_test_base_template', `
+ gen_require(`
+ attribute systemd_test_domain_type;
+ ')
+
+ type $1_t, systemd_test_domain_type;
+ domain_type($1_t)
+')
diff --git a/test/TEST-06-SELINUX/systemd_test.te b/test/TEST-06-SELINUX/systemd_test.te
new file mode 100644
index 0000000000..ff01c09b5e
--- /dev/null
+++ b/test/TEST-06-SELINUX/systemd_test.te
@@ -0,0 +1,50 @@
+policy_module(systemd_test, 0.0.1)
+
+# declarations
+attribute systemd_test_domain_type;
+
+systemd_test_base_template(systemd_test)
+systemd_test_base_template(systemd_test_status)
+systemd_test_base_template(systemd_test_start)
+systemd_test_base_template(systemd_test_stop)
+systemd_test_base_template(systemd_test_reload)
+
+# systemd_test_domain_type
+
+require {
+ role system_r;
+ role unconfined_r;
+ type bin_t;
+ type initrc_t;
+ type systemd_systemctl_exec_t;
+ type unconfined_service_t;
+}
+
+role system_r types systemd_test_domain_type;
+role unconfined_r types systemd_test_domain_type;
+
+allow systemd_test_domain_type bin_t: file entrypoint;
+allow systemd_test_domain_type systemd_systemctl_exec_t: file entrypoint;
+allow initrc_t systemd_test_domain_type: process transition;
+allow unconfined_service_t systemd_test_domain_type: process transition;
+corecmd_exec_bin(systemd_test_domain_type)
+init_signal_script(systemd_test_domain_type)
+init_sigchld_script(systemd_test_domain_type)
+systemd_exec_systemctl(systemd_test_domain_type)
+userdom_use_user_ttys(systemd_test_domain_type)
+userdom_use_user_ptys(systemd_test_domain_type)
+
+optional_policy(`
+ dbus_system_bus_client(systemd_test_domain_type)
+ init_dbus_chat(systemd_test_domain_type)
+')
+
+# systemd_test_*_t
+require {
+ type systemd_unit_file_t;
+}
+
+allow systemd_test_status_t systemd_unit_file_t: service { status };
+allow systemd_test_start_t systemd_unit_file_t: service { start };
+allow systemd_test_stop_t systemd_unit_file_t: service { stop };
+allow systemd_test_reload_t systemd_unit_file_t: service { reload };
diff --git a/test/TEST-06-SELINUX/test-selinux-checks.sh b/test/TEST-06-SELINUX/test-selinux-checks.sh
new file mode 100755
index 0000000000..08d2ddf4f0
--- /dev/null
+++ b/test/TEST-06-SELINUX/test-selinux-checks.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -x
+set -e
+set -o pipefail
+
+echo 1 >/sys/fs/selinux/enforce
+runcon -t systemd_test_start_t systemctl start hola
+runcon -t systemd_test_reload_t systemctl reload hola
+runcon -t systemd_test_stop_t systemctl stop hola
+
+touch /testok
+exit 0
diff --git a/test/TEST-06-SELINUX/test.sh b/test/TEST-06-SELINUX/test.sh
new file mode 100755
index 0000000000..4f5895be66
--- /dev/null
+++ b/test/TEST-06-SELINUX/test.sh
@@ -0,0 +1,135 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+TEST_DESCRIPTION="SELinux tests"
+
+# Requirements:
+# Fedora 23
+# selinux-policy-targeted
+# selinux-policy-devel
+
+. $TEST_BASE_DIR/test-functions
+SETUP_SELINUX=yes
+KERNEL_APPEND="$KERNEL_APPEND selinux=1"
+
+check_result_qemu() {
+ ret=1
+ mkdir -p $TESTDIR/root
+ mount ${LOOPDEV}p1 $TESTDIR/root
+ [[ -e $TESTDIR/root/testok ]] && ret=0
+ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
+ cp -a $TESTDIR/root/var/log/journal $TESTDIR
+ umount $TESTDIR/root
+ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
+ ls -l $TESTDIR/journal/*/*.journal
+ test -s $TESTDIR/failed && ret=$(($ret+1))
+ return $ret
+}
+
+test_run() {
+ if run_qemu; then
+ check_result_qemu || return 1
+ else
+ dwarn "can't run QEMU, skipping"
+ fi
+ return 0
+}
+
+test_setup() {
+ create_empty_image
+ mkdir -p $TESTDIR/root
+ mount ${LOOPDEV}p1 $TESTDIR/root
+
+ # Create what will eventually be our root filesystem onto an overlay
+ (
+ LOG_LEVEL=5
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+ setup_basic_environment
+
+ # setup the testsuite service
+ cat <<EOF >$initdir/etc/systemd/system/testsuite.service
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-selinux-checks.sh
+Type=oneshot
+EOF
+
+ cat <<EOF >$initdir/etc/systemd/system/hola.service
+[Service]
+Type=oneshot
+ExecStart=/bin/echo Start Hola
+ExecReload=/bin/echo Reload Hola
+ExecStop=/bin/echo Stop Hola
+RemainAfterExit=yes
+EOF
+
+ setup_testsuite
+
+ cat <<EOF >$initdir/etc/systemd/system/load-systemd-test-module.service
+[Unit]
+Description=Load systemd-test module
+DefaultDependencies=no
+Requires=local-fs.target
+Conflicts=shutdown.target
+After=local-fs.target
+Before=sysinit.target shutdown.target autorelabel.service
+ConditionSecurity=selinux
+ConditionPathExists=|/.load-systemd-test-module
+
+[Service]
+ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && cd /systemd-test-module && make -f /usr/share/selinux/devel/Makefile load && rm /.load-systemd-test-module'
+Type=oneshot
+TimeoutSec=0
+RemainAfterExit=yes
+EOF
+
+ touch $initdir/.load-systemd-test-module
+ mkdir -p $initdir/etc/systemd/system/basic.target.wants
+ ln -fs load-systemd-test-module.service $initdir/etc/systemd/system/basic.target.wants/load-systemd-test-module.service
+
+ local _modules_dir=/var/lib/selinux
+ rm -rf $initdir/$_modules_dir
+ if ! cp -ar $_modules_dir $initdir/$_modules_dir; then
+ dfatal "Failed to copy $_modules_dir"
+ exit 1
+ fi
+
+ local _policy_headers_dir=/usr/share/selinux/devel
+ rm -rf $initdir/$_policy_headers_dir
+ inst_dir /usr/share/selinux
+ if ! cp -ar $_policy_headers_dir $initdir/$_policy_headers_dir; then
+ dfatal "Failed to copy $_policy_headers_dir"
+ exit 1
+ fi
+
+ mkdir $initdir/systemd-test-module
+ cp systemd_test.te $initdir/systemd-test-module
+ cp systemd_test.if $initdir/systemd-test-module
+ cp test-selinux-checks.sh $initdir
+ dracut_install -o sesearch
+ dracut_install runcon
+ dracut_install checkmodule semodule semodule_package m4 make /usr/libexec/selinux/hll/pp load_policy sefcontext_compile
+ ) || return 1
+
+ # mask some services that we do not want to run in these tests
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+test_cleanup() {
+ umount $TESTDIR/root 2>/dev/null
+ [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+ return 0
+}
+
+do_test "$@"