diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/bus-util.c | 11 | ||||
-rw-r--r-- | src/shared/dns-domain.c | 156 | ||||
-rw-r--r-- | src/shared/dns-domain.h | 12 | ||||
-rw-r--r-- | src/shared/generator.c | 5 | ||||
-rw-r--r-- | src/shared/gpt.h | 7 | ||||
-rw-r--r-- | src/shared/import-util.c | 52 | ||||
-rw-r--r-- | src/shared/import-util.h | 6 | ||||
-rw-r--r-- | src/shared/logs-show.c | 3 | ||||
-rw-r--r-- | src/shared/resolve-util.c | 41 | ||||
-rw-r--r-- | src/shared/resolve-util.h | 62 | ||||
-rw-r--r-- | src/shared/switch-root.c | 3 |
11 files changed, 252 insertions, 106 deletions
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index e427cc1470..5c6dc34700 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -2381,23 +2381,28 @@ int bus_property_get_rlimit( struct rlimit *rl; uint64_t u; rlim_t x; + const char *is_soft; assert(bus); assert(reply); assert(userdata); + is_soft = endswith(property, "Soft"); rl = *(struct rlimit**) userdata; if (rl) - x = rl->rlim_max; + x = is_soft ? rl->rlim_cur : rl->rlim_max; else { struct rlimit buf = {}; int z; + const char *s; + + s = is_soft ? strndupa(property, is_soft - property) : property; - z = rlimit_from_string(strstr(property, "Limit")); + z = rlimit_from_string(strstr(s, "Limit")); assert(z >= 0); getrlimit(z, &buf); - x = buf.rlim_max; + x = is_soft ? buf.rlim_cur : buf.rlim_max; } /* rlim_t might have different sizes, let's map diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index 0466857042..59475115ba 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -48,7 +48,6 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) { assert(name); assert(*name); - assert(dest); n = *name; d = dest; @@ -79,9 +78,12 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) { else if (*n == '\\' || *n == '.') { /* Escaped backslash or dot */ - *(d++) = *(n++); + + if (d) + *(d++) = *n; sz--; r++; + n++; } else if (n[0] >= '0' && n[0] <= '9') { unsigned k; @@ -96,11 +98,17 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) { ((unsigned) (n[1] - '0') * 10) + ((unsigned) (n[2] - '0')); - /* Don't allow CC characters or anything that doesn't fit in 8bit */ - if (k < ' ' || k > 255 || k == 127) + /* Don't allow anything that doesn't + * fit in 8bit. Note that we do allow + * control characters, as some servers + * (e.g. cloudflare) are happy to + * generate labels with them + * inside. */ + if (k > 255) return -EINVAL; - *(d++) = (char) k; + if (d) + *(d++) = (char) k; sz--; r++; @@ -111,9 +119,12 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) { } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) { /* Normal character */ - *(d++) = *(n++); + + if (d) + *(d++) = *n; sz--; r++; + n++; } else return -EINVAL; } @@ -122,7 +133,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) { if (r == 0 && *n) return -EINVAL; - if (sz >= 1) + if (sz >= 1 && d) *d = 0; *name = n; @@ -148,20 +159,24 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha return 0; } - assert(**label_terminal == '.' || **label_terminal == 0); + terminal = *label_terminal; + assert(*terminal == '.' || *terminal == 0); - /* skip current terminal character */ - terminal = *label_terminal - 1; + /* Skip current terminal character (and accept domain names ending it ".") */ + if (*terminal == 0) + terminal--; + if (terminal >= name && *terminal == '.') + terminal--; - /* point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */ + /* Point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */ for (;;) { if (terminal < name) { - /* reached the first label, so indicate that there are no more */ + /* Reached the first label, so indicate that there are no more */ terminal = NULL; break; } - /* find the start of the last label */ + /* Find the start of the last label */ if (*terminal == '.') { const char *y; unsigned slashes = 0; @@ -170,7 +185,7 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha slashes ++; if (slashes % 2 == 0) { - /* the '.' was not escaped */ + /* The '.' was not escaped */ name = terminal + 1; break; } else { @@ -235,7 +250,7 @@ int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) { *(q++) = *p; sz -= 1; - } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) { + } else { /* Everything else */ @@ -249,8 +264,7 @@ int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) { sz -= 4; - } else - return -EINVAL; + } p++; l--; @@ -472,13 +486,15 @@ void dns_name_hash_func(const void *s, struct siphash *state) { assert(p); - while (*p) { + for (;;) { char label[DNS_LABEL_MAX+1]; int k; r = dns_label_unescape(&p, label, sizeof(label)); if (r < 0) break; + if (r == 0) + break; k = dns_label_undo_idna(label, r, label, sizeof(label)); if (k < 0) @@ -486,13 +502,9 @@ void dns_name_hash_func(const void *s, struct siphash *state) { if (k > 0) r = k; - if (r == 0) - break; - - label[r] = 0; - ascii_strlower(label); - - string_hash_func(label, state); + ascii_strlower_n(label, r); + siphash24_compress(label, r, state); + siphash24_compress_byte(0, state); /* make sure foobar and foo.bar result in different hashes */ } /* enforce that all names are terminated by the empty label */ @@ -527,7 +539,7 @@ int dns_name_compare_func(const void *a, const void *b) { if (k > 0) r = k; if (w > 0) - r = w; + q = w; la[r] = lb[q] = 0; r = strcasecmp(la, lb); @@ -899,19 +911,11 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, boo if (r < 0) return r; - if (canonical) { - size_t i; - - /* Optionally, output the name in DNSSEC - * canonical format, as described in RFC 4034, - * section 6.2. Or in other words: in - * lower-case. */ - - for (i = 0; i < (size_t) r; i++) { - if (out[i] >= 'A' && out[i] <= 'Z') - out[i] = out[i] - 'A' + 'a'; - } - } + /* Optionally, output the name in DNSSEC canonical + * format, as described in RFC 4034, section 6.2. Or + * in other words: in lower-case. */ + if (canonical) + ascii_strlower_n((char*) out, (size_t) r); /* Fill label length, move forward */ *label_length = r; @@ -1153,3 +1157,77 @@ finish: return 0; } + +int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) { + const char* labels[DNS_N_LABELS_MAX+1]; + unsigned n = 0; + const char *p; + int r; + + assert(name); + assert(ret); + + p = name; + for (;;) { + if (n > DNS_N_LABELS_MAX) + return -EINVAL; + + labels[n] = p; + + r = dns_name_parent(&p); + if (r < 0) + return r; + if (r == 0) + break; + + n++; + } + + if (n < n_labels) + return -EINVAL; + + *ret = labels[n - n_labels]; + return (int) (n - n_labels); +} + +int dns_name_count_labels(const char *name) { + unsigned n = 0; + const char *p; + int r; + + assert(name); + + p = name; + for (;;) { + r = dns_name_parent(&p); + if (r < 0) + return r; + if (r == 0) + break; + + if (n >= DNS_N_LABELS_MAX) + return -EINVAL; + + n++; + } + + return (int) n; +} + +int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) { + int r; + + assert(a); + assert(b); + + while (n_labels > 0) { + + r = dns_name_parent(&a); + if (r <= 0) + return r; + + n_labels --; + } + + return dns_name_equal(a, b); +} diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h index 3f8f621802..dd8ae3ac98 100644 --- a/src/shared/dns-domain.h +++ b/src/shared/dns-domain.h @@ -42,11 +42,18 @@ /* Maximum length of a full hostname, on the wire, including the final NUL byte */ #define DNS_WIRE_FOMAT_HOSTNAME_MAX 255 +/* Maximum number of labels per valid hostname */ +#define DNS_N_LABELS_MAX 127 + int dns_label_unescape(const char **name, char *dest, size_t sz); int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz); int dns_label_escape(const char *p, size_t l, char *dest, size_t sz); int dns_label_escape_new(const char *p, size_t l, char **ret); +static inline int dns_name_parent(const char **name) { + return dns_label_unescape(name, NULL, DNS_LABEL_MAX); +} + int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); @@ -92,3 +99,8 @@ bool dns_service_name_is_valid(const char *name); int dns_service_join(const char *name, const char *type, const char *domain, char **ret); int dns_service_split(const char *joined, char **name, char **type, char **domain); + +int dns_name_suffix(const char *name, unsigned n_labels, const char **ret); +int dns_name_count_labels(const char *name); + +int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b); diff --git a/src/shared/generator.c b/src/shared/generator.c index 37de3f7cb1..76808cbdd5 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -190,7 +190,6 @@ int generator_write_timeouts( return write_drop_in_format(dir, unit, 50, "device-timeout", "# Automatically generated by %s\n\n" - "[Unit]\nJobTimeoutSec=" USEC_FMT, - program_invocation_short_name, - u / USEC_PER_SEC); + "[Unit]\nJobTimeoutSec=%s", + program_invocation_short_name, timeout); } diff --git a/src/shared/gpt.h b/src/shared/gpt.h index add1df420f..5f4c00ba83 100644 --- a/src/shared/gpt.h +++ b/src/shared/gpt.h @@ -25,7 +25,7 @@ #include "sd-id128.h" -/* We only support root disk discovery for x86, x86-64 and ARM for +/* We only support root disk discovery for x86, x86-64, Itanium and ARM for * now, since EFI for anything else doesn't really exist, and we only * care for root partitions on the same disk as the EFI ESP. */ @@ -33,6 +33,7 @@ #define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09) #define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3) #define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae) +#define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97) #define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b) #define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f) @@ -46,6 +47,10 @@ # define GPT_ROOT_NATIVE GPT_ROOT_X86 #endif +#if defined(__ia64__) +# define GPT_ROOT_NATIVE GPT_ROOT_IA64 +#endif + #if defined(__aarch64__) && (__BYTE_ORDER != __BIG_ENDIAN) # define GPT_ROOT_NATIVE GPT_ROOT_ARM_64 # define GPT_ROOT_SECONDARY GPT_ROOT_ARM diff --git a/src/shared/import-util.c b/src/shared/import-util.c index 29ce732b56..ad400e8693 100644 --- a/src/shared/import-util.c +++ b/src/shared/import-util.c @@ -160,58 +160,6 @@ int raw_strip_suffixes(const char *p, char **ret) { return 0; } -bool dkr_digest_is_valid(const char *digest) { - /* 7 chars for prefix, 64 chars for the digest itself */ - if (strlen(digest) != 71) - return false; - - return startswith(digest, "sha256:") && in_charset(digest + 7, "0123456789abcdef"); -} - -bool dkr_ref_is_valid(const char *ref) { - const char *colon; - - if (isempty(ref)) - return false; - - colon = strchr(ref, ':'); - if (!colon) - return filename_is_valid(ref); - - return dkr_digest_is_valid(ref); -} - -bool dkr_name_is_valid(const char *name) { - const char *slash, *p; - - if (isempty(name)) - return false; - - slash = strchr(name, '/'); - if (!slash) - return false; - - if (!filename_is_valid(slash + 1)) - return false; - - p = strndupa(name, slash - name); - if (!filename_is_valid(p)) - return false; - - return true; -} - -bool dkr_id_is_valid(const char *id) { - - if (!filename_is_valid(id)) - return false; - - if (!in_charset(id, "0123456789abcdef")) - return false; - - return true; -} - int import_assign_pool_quota_and_warn(const char *path) { int r; diff --git a/src/shared/import-util.h b/src/shared/import-util.h index 9120a5119f..4bfa2d9aae 100644 --- a/src/shared/import-util.h +++ b/src/shared/import-util.h @@ -42,10 +42,4 @@ ImportVerify import_verify_from_string(const char *s) _pure_; int tar_strip_suffixes(const char *name, char **ret); int raw_strip_suffixes(const char *name, char **ret); -bool dkr_name_is_valid(const char *name); -bool dkr_id_is_valid(const char *id); -bool dkr_ref_is_valid(const char *ref); -bool dkr_digest_is_valid(const char *digest); -#define dkr_tag_is_valid(tag) filename_is_valid(tag) - int import_assign_pool_quota_and_warn(const char *path); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 193dad1943..a1f65d1a88 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -435,8 +435,9 @@ static int output_verbose( r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size); if (r < 0) - log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m"); + return r; else { + assert(r > 0); r = safe_atou64(value, &realtime); if (r < 0) log_debug_errno(r, "Failed to parse realtime timestamp: %m"); diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c new file mode 100644 index 0000000000..bf6fc26841 --- /dev/null +++ b/src/shared/resolve-util.c @@ -0,0 +1,41 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + 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 "conf-parser.h" +#include "resolve-util.h" +#include "string-table.h" + +DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting"); + +static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = { + [RESOLVE_SUPPORT_NO] = "no", + [RESOLVE_SUPPORT_YES] = "yes", + [RESOLVE_SUPPORT_RESOLVE] = "resolve", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolve_support, ResolveSupport, RESOLVE_SUPPORT_YES); + +static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = { + [DNSSEC_NO] = "no", + [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade", + [DNSSEC_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES); diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h new file mode 100644 index 0000000000..fd93a13f73 --- /dev/null +++ b/src/shared/resolve-util.h @@ -0,0 +1,62 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + 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 "macro.h" + +typedef enum ResolveSupport ResolveSupport; +typedef enum DnssecMode DnssecMode; + +enum ResolveSupport { + RESOLVE_SUPPORT_NO, + RESOLVE_SUPPORT_YES, + RESOLVE_SUPPORT_RESOLVE, + _RESOLVE_SUPPORT_MAX, + _RESOLVE_SUPPORT_INVALID = -1 +}; + +enum DnssecMode { + /* No DNSSEC validation is done */ + DNSSEC_NO, + + /* Validate locally, if the server knows DO, but if not, + * don't. Don't trust the AD bit. If the server doesn't do + * DNSSEC properly, downgrade to non-DNSSEC operation. Of + * course, we then are vulnerable to a downgrade attack, but + * that's life and what is configured. */ + DNSSEC_ALLOW_DOWNGRADE, + + /* Insist on DNSSEC server support, and rather fail than downgrading. */ + DNSSEC_YES, + + _DNSSEC_MODE_MAX, + _DNSSEC_MODE_INVALID = -1 +}; + +int config_parse_resolve_support(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); +int config_parse_dnssec_mode(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); + +const char* resolve_support_to_string(ResolveSupport p) _const_; +ResolveSupport resolve_support_from_string(const char *s) _pure_; + +const char* dnssec_mode_to_string(DnssecMode p) _const_; +DnssecMode dnssec_mode_from_string(const char *s) _pure_; diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index b1bbbdaadd..bf0739e5fa 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -35,6 +35,7 @@ #include "mkdir.h" #include "path-util.h" #include "rm-rf.h" +#include "stdio-util.h" #include "string-util.h" #include "switch-root.h" #include "user-util.h" @@ -77,7 +78,7 @@ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, char new_mount[PATH_MAX]; struct stat sb; - snprintf(new_mount, sizeof(new_mount), "%s%s", new_root, i); + xsprintf(new_mount, "%s%s", new_root, i); mkdir_p_label(new_mount, 0755); |