Discussion:
[PATCH] network: allow domain names up to 255 characters
(too old to reply)
Nick Owens
2015-04-10 20:03:19 UTC
Permalink
From: mischief <***@offblast.org>

The maximum domain name size is larger than the maximum host name size.
The smaller limit causes valid domains provided by DHCP or .network
files to be silently ignored.
---
src/libsystemd-network/sd-dhcp-lease.c | 2 +-
src/network/networkd-network.c | 2 +-
src/shared/util.c | 21 ++++++++++++++-------
src/shared/util.h | 4 ++++
4 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 34aa36c..5ec0c20 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -511,7 +511,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
if (e)
*e = 0;

- if (!hostname_is_valid(domainname) || is_localhost(domainname))
+ if (!domainname_is_valid(domainname) || is_localhost(domainname))
break;

free(lease->domainname);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 0d1ec0b..3fe1600 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -456,7 +456,7 @@ int config_parse_domains(const char *unit,
STRV_FOREACH(domain, *domains) {
if (is_localhost(*domain))
log_syntax(unit, LOG_ERR, filename, line, EINVAL, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
- else if (!hostname_is_valid(*domain)) {
+ else if (!domainname_is_valid(*domain)) {
if (!streq(*domain, "*"))
log_syntax(unit, LOG_ERR, filename, line, EINVAL, "domain name is not valid, ignoring assignment: %s", *domain);
} else
diff --git a/src/shared/util.c b/src/shared/util.c
index ba035ca..705112b1 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -4245,18 +4245,16 @@ static bool hostname_valid_char(char c) {
c == '.';
}

-bool hostname_is_valid(const char *s) {
+/* Doesn't accept empty hostnames, hostnames with trailing or
+ * leading dots, and hostnames with multiple dots in a
+ * sequence. Also ensures that the length stays below n */
+static bool hostname_is_valid_len(const char *s, size_t n) {
const char *p;
bool dot;

if (isempty(s))
return false;

- /* Doesn't accept empty hostnames, hostnames with trailing or
- * leading dots, and hostnames with multiple dots in a
- * sequence. Also ensures that the length stays below
- * HOST_NAME_MAX. */
-
for (p = s, dot = true; *p; p++) {
if (*p == '.') {
if (dot)
@@ -4274,10 +4272,19 @@ bool hostname_is_valid(const char *s) {
if (dot)
return false;

- if (p-s > HOST_NAME_MAX)
+ if (p-s > n)
return false;

return true;
+
+}
+
+bool hostname_is_valid(const char *s) {
+ return hostname_is_valid_len(s, HOST_NAME_MAX);
+}
+
+bool domainname_is_valid(const char *s) {
+ return hostname_is_valid_len(s, DOMAIN_NAME_MAX);
}

char* hostname_cleanup(char *s, bool lowercase) {
diff --git a/src/shared/util.h b/src/shared/util.h
index a83b588..1c8691d 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -89,6 +89,9 @@
#include "missing.h"
#include "time-util.h"

+/* Maximum length of a domain name. See RFC 1035 */
+#define DOMAIN_NAME_MAX 255
+
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
#define NEWLINE "\n\r"
@@ -553,6 +556,7 @@ bool nulstr_contains(const char*nulstr, const char *needle);
bool plymouth_running(void);

bool hostname_is_valid(const char *s) _pure_;
+bool domainname_is_valid(const char *s) _pure_;
char* hostname_cleanup(char *s, bool lowercase);

bool machine_name_is_valid(const char *s) _pure_;
--
2.0.5
Lennart Poettering
2015-04-12 16:37:16 UTC
Permalink
On Sun, Apr 12, 2015 at 6:35 AM, Lennart Poettering
Post by Nick Owens
The maximum domain name size is larger than the maximum host name size.
The smaller limit causes valid domains provided by DHCP or .network
files to be silently ignored.
Hmm?
Can you give an example?
if you set the Domains key in the [Network] section of a
systemd.network file to a domain longer than a label, then it will be
ignored. the same is true if your DHCP server sends a domain in option
15 (domain name) that is longer than a label. it will be ignored too.
both of these code paths call 'hostname_is_valid', which will fail if
passed something larger than a label, which a domain name can be.
"longer than a label"? What do you mean by that? The function should
perfectly consider multi-label names valid? Are you saying you cannot
set the domain name "foo.bar."?

Hmm, so the DHCP spec explicitly declares that options 15 and 12 are
about the DNS hostname, where RFC 1035 is normative. Our function
hostname_is_valid() currently does not validate host names according
to RFC 1035, but is in some way stricter (by enforcing Linux' own semantics
on the length, and by limiting the charset drastically) and in other
ways less strict (by not enforce label length.)

I am pretty sure we should leave hostname_is_valid() the way it is, to
be used when setting local hostnames and things like that. However,
the DHCP code should really validate according to RFC 1035 instead,
since that's what the spec says...

Implementation-wise this probably means we should move
src/resolve/resolved-dns-domain.[ch] into src/shared/dns-domain.[ch]
and then add a call there that works similar to dns_name_normalize()
but doesn't actually normalize, but simply validates.

Hope that makes sense?

Lennart
--
Lennart Poettering, Red Hat
Nick Owens
2015-04-13 17:09:57 UTC
Permalink
sorry, "supercalifragilisticexpialidocioussupercalifragilisticexpialidocious"
was a bad example. it would not be valid since it is longer than a
label.

On Sun, Apr 12, 2015 at 9:37 AM, Lennart Poettering
Post by Lennart Poettering
On Sun, Apr 12, 2015 at 6:35 AM, Lennart Poettering
Post by Nick Owens
The maximum domain name size is larger than the maximum host name size.
The smaller limit causes valid domains provided by DHCP or .network
files to be silently ignored.
Hmm?
Can you give an example?
if you set the Domains key in the [Network] section of a
systemd.network file to a domain longer than a label, then it will be
ignored. the same is true if your DHCP server sends a domain in option
15 (domain name) that is longer than a label. it will be ignored too.
both of these code paths call 'hostname_is_valid', which will fail if
passed something larger than a label, which a domain name can be.
"longer than a label"? What do you mean by that? The function should
perfectly consider multi-label names valid? Are you saying you cannot
set the domain name "foo.bar."?
a multi-label name is valid. however, hostname_is_valid will reject
any domain name (multi-label or not) longer than HOST_NAME_MAX, the
size of a label.
Post by Lennart Poettering
Hmm, so the DHCP spec explicitly declares that options 15 and 12 are
about the DNS hostname, where RFC 1035 is normative. Our function
hostname_is_valid() currently does not validate host names according
to RFC 1035, but is in some way stricter (by enforcing Linux' own semantics
on the length, and by limiting the charset drastically) and in other
ways less strict (by not enforce label length.)
I am pretty sure we should leave hostname_is_valid() the way it is, to
be used when setting local hostnames and things like that. However,
the DHCP code should really validate according to RFC 1035 instead,
since that's what the spec says...
Implementation-wise this probably means we should move
src/resolve/resolved-dns-domain.[ch] into src/shared/dns-domain.[ch]
and then add a call there that works similar to dns_name_normalize()
but doesn't actually normalize, but simply validates.
the intention of the domainname_is_valid function in this patch is to
validate domain names, which can be up to 255 octets. there appears to
be no standardized macro for this size, so i added one.
Post by Lennart Poettering
Hope that makes sense?
Lennart
--
Lennart Poettering, Red Hat
Lennart Poettering
2015-04-14 12:07:45 UTC
Permalink
Post by Nick Owens
Post by Lennart Poettering
Hmm, so the DHCP spec explicitly declares that options 15 and 12 are
about the DNS hostname, where RFC 1035 is normative. Our function
hostname_is_valid() currently does not validate host names according
to RFC 1035, but is in some way stricter (by enforcing Linux' own semantics
on the length, and by limiting the charset drastically) and in other
ways less strict (by not enforce label length.)
I am pretty sure we should leave hostname_is_valid() the way it is, to
be used when setting local hostnames and things like that. However,
the DHCP code should really validate according to RFC 1035 instead,
since that's what the spec says...
Implementation-wise this probably means we should move
src/resolve/resolved-dns-domain.[ch] into src/shared/dns-domain.[ch]
and then add a call there that works similar to dns_name_normalize()
but doesn't actually normalize, but simply validates.
the intention of the domainname_is_valid function in this patch is to
validate domain names, which can be up to 255 octets. there appears to
be no standardized macro for this size, so i added one.
Well, I understand that. But I'd prefer if we could reuse the DNS
domain parsing code for this we already have instead of adding yet
another function for validating this.

I hope that makese sense,

Lennart
--
Lennart Poettering, Red Hat
Shawn Landden
2015-04-12 16:13:04 UTC
Permalink
On Sun, Apr 12, 2015 at 6:35 AM, Lennart Poettering
Post by Nick Owens
The maximum domain name size is larger than the maximum host name size.
The smaller limit causes valid domains provided by DHCP or .network
files to be silently ignored.
Hmm?
Can you give an example?
What is a domain name according to your definition? And what a
hostname?
So far, a hostname in my definition was either a single label, or an
fqdn, and a domain name the part of the fqdn with the first label
removed...
With such a definition I am not sure I understand the patch, hence
please explain, and give a valid example of where this turns out to be
an issue?
./x86_64-linux-gnu/bits/posix1_lim.h:#define _POSIX_HOST_NAME_MAX 255
./x86_64-linux-gnu/bits/local_lim.h:#define HOST_NAME_MAX 64
./x86_64-linux-musl/limits.h:#define HOST_NAME_MAX 255

Perhaps we need to use _POSIX_HOST_NAME_MAX ?, or redefine HOST_NAME_MAX to 255?
Lennart
--
Lennart Poettering, Red Hat
_______________________________________________
systemd-devel mailing list
http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
Liberty equality fraternity or death,

Shawn Landden
ChurchOfGit.com
Lennart Poettering
2015-04-12 16:17:47 UTC
Permalink
On Sun, Apr 12, 2015 at 6:35 AM, Lennart Poettering
Post by Nick Owens
The maximum domain name size is larger than the maximum host name size.
The smaller limit causes valid domains provided by DHCP or .network
files to be silently ignored.
Hmm?
Can you give an example?
What is a domain name according to your definition? And what a
hostname?
So far, a hostname in my definition was either a single label, or an
fqdn, and a domain name the part of the fqdn with the first label
removed...
With such a definition I am not sure I understand the patch, hence
please explain, and give a valid example of where this turns out to be
an issue?
./x86_64-linux-gnu/bits/posix1_lim.h:#define _POSIX_HOST_NAME_MAX 255
./x86_64-linux-gnu/bits/local_lim.h:#define HOST_NAME_MAX 64
./x86_64-linux-musl/limits.h:#define HOST_NAME_MAX 255
musl is irrelevant for systemd.

Also, musl is wrong. The Linux kernel maintains the system hostname as
64 char array, and sethostname() enforces that limit.
Perhaps we need to use _POSIX_HOST_NAME_MAX ?,
Not really, that' the "minimal accepted value" for
HOST_NAME_MAX and defined to 255. Linux ignores that, and sets
HOST_NAME_MAX to 64 anyway...
or redefine HOST_NAME_MAX to 255?
No, we will not redefine what the libc provides us with. This can only break.

Lennart
--
Lennart Poettering, Red Hat
Loading...