* Meson options '-Dintegration-tests=' and '-Dcryptolib=' (deprecated
in v258) have been removed.
+ * Support for libidn has been removed. IDN functionality now requires
+ libidn2. The corresponding meson option '-Dlibidn=' is deprecated
+ too and will be dropped in a future release.
+
CHANGES WITH 259:
Announcements of Future Feature Removals and Incompatible Changes:
libqrencode >= 3 (optional)
libmicrohttpd >= 0.9.33 (optional)
libcurl >= 7.32.0 (optional)
- libidn2 or libidn (optional)
+ libidn2 (optional)
gnutls >= 3.1.4 (optional)
openssl >= 3.0.0 (optional, required to support DNS-over-TLS)
p11-kit >= 0.23.3 (optional)
* port copy.c over to use LabelOps for all labelling.
-* get rid of compat with libidn.so.11 (retain only for libidn.so.12)
-
* get rid of compat with libbpf.so.0 (retainly only for libbpf.so.1)
* define a generic "report" varlink interface, which services can implement to
conf.set10('HAVE_LIBCURL', libcurl.found())
conf.set10('CURL_NO_OLDIES', conf.get('BUILD_MODE_DEVELOPER') == 1)
-feature = get_option('libidn2').disable_auto_if(get_option('libidn').enabled())
-libidn = dependency('libidn2',
- required : feature)
-have = libidn.found()
-if not have
- # libidn is used for both libidn and libidn2 objects
- libidn = dependency('libidn',
- required : get_option('libidn'))
-endif
-libidn_cflags = libidn.partial_dependency(includes: true, compile_args: true)
-conf.set10('HAVE_LIBIDN', not have and libidn.found())
-conf.set10('HAVE_LIBIDN2', have)
+libidn2 = dependency('libidn2',
+ required : get_option('libidn2'))
+libidn2_cflags = libidn2.partial_dependency(includes: true, compile_args: true)
+conf.set10('HAVE_LIBIDN2', libidn2.found())
libqrencode = dependency('libqrencode',
version : '>= 3',
['libcurl'],
['libfdisk'],
['libfido2'],
- ['libidn'],
['libidn2'],
['microhttpd'],
['openssl'],
description : 'use IDN when printing hostnames')
option('libidn2', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
description : 'libidn2 support')
-option('libidn', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
+option('libidn', type : 'feature', deprecated : true,
description : 'libidn support')
option('libiptc', type : 'feature', deprecated : true,
description : 'libiptc support')
" -IDN2"
#endif
-#if HAVE_LIBIDN
- " +IDN"
-#else
- " -IDN"
-#endif
-
#if HAVE_KMOD
" +KMOD"
#else
resolve_common_template = {
'dependencies' : [
+ libidn2_cflags,
libopenssl,
libm,
threads,
'resolvconf-compat.c',
'resolvectl.c',
),
- 'dependencies' : resolve_common_template['dependencies'] + [
- libidn,
- ],
'objects' : ['systemd-resolved'],
},
resolve_test_template + {
int resolve_system_hostname(char **full_hostname, char **first_label) {
_cleanup_free_ char *h = NULL, *n = NULL;
-#if HAVE_LIBIDN2
- _cleanup_free_ char *utf8 = NULL;
-#elif HAVE_LIBIDN
- int k;
-#endif
char label[DNS_LABEL_MAX+1];
const char *p, *decoded;
int r;
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Couldn't find a single label in hostname.");
-#if HAVE_LIBIDN || HAVE_LIBIDN2
- r = dlopen_idn();
- if (r < 0) {
- log_debug_errno(r, "Failed to initialize IDN support, ignoring: %m");
- decoded = label; /* no decoding */
- } else
-#endif
- {
#if HAVE_LIBIDN2
+ _cleanup_free_ char *utf8 = NULL;
+
+ if (dlopen_idn() >= 0) {
r = sym_idn2_to_unicode_8z8z(label, &utf8, 0);
if (r != IDN2_OK)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
r = strlen(utf8);
decoded = utf8;
-#elif HAVE_LIBIDN
- k = dns_label_undo_idna(label, r, label, sizeof label);
- if (k < 0)
- return log_debug_errno(k, "Failed to undo IDNA: %m");
- if (k > 0)
- r = k;
-
- if (!utf8_is_valid(label))
- return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
- "System hostname is not UTF-8 clean.");
- decoded = label;
-#else
- decoded = label; /* no decoding */
+ } else
#endif
- }
+ decoded = label; /* no decoding */
r = dns_label_escape_new(decoded, r, &n);
if (r < 0)
ASSERT_NULL(query);
}
-#if HAVE_LIBIDN || HAVE_LIBIDN2
+#if HAVE_LIBIDN2
TEST(dns_query_new_same_utf8_and_idna) {
Manager manager = {};
_cleanup_(dns_question_unrefp) DnsQuestion *q_utf8 = NULL, *q_idna = NULL;
dns_resource_key_unref(key);
}
-#if HAVE_LIBIDN || HAVE_LIBIDN2
+#if HAVE_LIBIDN2
TEST(dns_query_process_cname_one_success_match_dname_utf8_same) {
Manager manager = {};
_cleanup_(dns_question_unrefp) DnsQuestion *q_utf8 = NULL, *q_idna = NULL;
ASSERT_OK_POSITIVE(dns_question_contains_key(question, key6));
}
-#if HAVE_LIBIDN || HAVE_LIBIDN2
+#if HAVE_LIBIDN2
TEST(dns_question_new_address_convert_idna) {
_cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
question = dns_question_unref(question);
key = dns_resource_key_unref(key);
-#if HAVE_LIBIDN || HAVE_LIBIDN2
+#if HAVE_LIBIDN2
/* convert idna with type */
ASSERT_OK(dns_question_new_service(
&question,
test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
-#if HAVE_LIBIDN2 || HAVE_LIBIDN
+#if HAVE_LIBIDN2
/* Unsigned A with IDNA conversion necessary */
test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL);
test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL);
return dns_label_unescape(name, NULL, DNS_LABEL_MAX, 0);
}
-#if HAVE_LIBIDN
-int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
- _cleanup_free_ uint32_t *input = NULL;
- size_t input_size, l;
- bool contains_8_bit = false;
- char buffer[DNS_LABEL_MAX+1];
- int r;
-
- assert(encoded);
- assert(decoded);
-
- /* Converts a U-label into an A-label */
-
- r = dlopen_idn();
- if (r < 0)
- return r;
-
- if (encoded_size <= 0)
- return -EINVAL;
-
- for (const char *p = encoded; p < encoded + encoded_size; p++)
- if ((uint8_t) *p > 127)
- contains_8_bit = true;
-
- if (!contains_8_bit) {
- if (encoded_size > DNS_LABEL_MAX)
- return -EINVAL;
-
- return 0;
- }
-
- input = sym_stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
- if (!input)
- return -ENOMEM;
-
- if (sym_idna_to_ascii_4i(input, input_size, buffer, 0) != 0)
- return -EINVAL;
-
- l = strlen(buffer);
-
- /* Verify that the result is not longer than one DNS label. */
- if (l <= 0 || l > DNS_LABEL_MAX)
- return -EINVAL;
- if (l > decoded_max)
- return -ENOBUFS;
-
- memcpy(decoded, buffer, l);
-
- /* If there's room, append a trailing NUL byte, but only then */
- if (decoded_max > l)
- decoded[l] = 0;
-
- return (int) l;
-}
-
-int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
- size_t input_size, output_size;
- _cleanup_free_ uint32_t *input = NULL;
- _cleanup_free_ char *result = NULL;
- uint32_t *output = NULL;
- size_t w;
- int r;
-
- /* To be invoked after unescaping. Converts an A-label into a U-label. */
-
- assert(encoded);
- assert(decoded);
-
- r = dlopen_idn();
- if (r < 0)
- return r;
-
- if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX)
- return -EINVAL;
-
- if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX))
- return 0;
-
- input = sym_stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
- if (!input)
- return -ENOMEM;
-
- output_size = input_size;
- output = newa(uint32_t, output_size);
-
- sym_idna_to_unicode_44i(input, input_size, output, &output_size, 0);
-
- result = sym_stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
- if (!result)
- return -ENOMEM;
- if (w <= 0)
- return -EINVAL;
- if (w > decoded_max)
- return -ENOBUFS;
-
- memcpy(decoded, result, w);
-
- /* Append trailing NUL byte if there's space, but only then. */
- if (decoded_max > w)
- decoded[w] = 0;
-
- return w;
-}
-#endif
-
int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret) {
_cleanup_free_ char *result = NULL;
size_t n_result = 0, n_unescaped = 0;
/* Return negative on error, 0 if not implemented, positive on success. */
-#if HAVE_LIBIDN2 || HAVE_LIBIDN2
+#if HAVE_LIBIDN2
int r;
r = dlopen_idn();
}
if (r < 0)
return r;
-#endif
-#if HAVE_LIBIDN2
_cleanup_free_ char *t = NULL;
assert(name);
return -ENOSPC;
return -EINVAL;
-#elif HAVE_LIBIDN
- _cleanup_free_ char *buf = NULL;
- size_t n = 0;
- bool first = true;
- int r, q;
-
- assert(name);
- assert(ret);
-
- for (;;) {
- char label[DNS_LABEL_MAX+1];
-
- r = dns_label_unescape(&name, label, sizeof label, 0);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- q = dns_label_apply_idna(label, r, label, sizeof label);
- if (q < 0)
- return q;
- if (q > 0)
- r = q;
-
- if (!GREEDY_REALLOC(buf, n + !first + DNS_LABEL_ESCAPED_MAX))
- return -ENOMEM;
-
- r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX);
- if (r < 0)
- return r;
-
- if (first)
- first = false;
- else
- buf[n++] = '.';
-
- n += r;
- }
-
- if (n > DNS_HOSTNAME_MAX)
- return -EINVAL;
-
- if (!GREEDY_REALLOC(buf, n + 1))
- return -ENOMEM;
-
- buf[n] = 0;
- *ret = TAKE_PTR(buf);
-
- return 1;
#else
*ret = NULL;
return 0;
int dns_name_parent(const char **name);
-#if HAVE_LIBIDN
-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);
-#endif
-
int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret);
static inline int dns_name_normalize(const char *s, DNSLabelFlags flags, char **ret) {
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#if HAVE_LIBIDN2
-# include <idn2.h>
-#elif HAVE_LIBIDN
-# include <idna.h>
-# include <stringprep.h>
-#endif
-
-#include "dlfcn-util.h"
#include "idn-util.h"
#include "log.h" /* IWYU pragma: keep */
-#if HAVE_LIBIDN || HAVE_LIBIDN2
static void* idn_dl = NULL;
-#endif
-#if HAVE_LIBIDN2
DLSYM_PROTOTYPE(idn2_lookup_u8) = NULL;
const char *(*sym_idn2_strerror)(int rc) _const_ = NULL;
DLSYM_PROTOTYPE(idn2_to_unicode_8z8z) = NULL;
DLSYM_ARG(idn2_strerror),
DLSYM_ARG(idn2_to_unicode_8z8z));
}
-#endif
-
-#if HAVE_LIBIDN
-DLSYM_PROTOTYPE(idna_to_ascii_4i) = NULL;
-DLSYM_PROTOTYPE(idna_to_unicode_44i) = NULL;
-DLSYM_PROTOTYPE(stringprep_ucs4_to_utf8) = NULL;
-DLSYM_PROTOTYPE(stringprep_utf8_to_ucs4) = NULL;
-
-int dlopen_idn(void) {
- int r;
-
- ELF_NOTE_DLOPEN("idn",
- "Support for internationalized domain names",
- ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
- "libidn.so.12", "libidn.so.11");
-
- if (idn_dl)
- return 0; /* Already loaded */
-
- r = check_dlopen_blocked("libidn.so.12");
- if (r < 0)
- return r;
-
- _cleanup_(dlclosep) void *dl = NULL;
- r = dlopen_safe("libidn.so.12", &dl, /* reterr_dlerror= */ NULL);
- if (r < 0) {
- /* libidn broke ABI in 1.34, but not in a way we care about (a new field got added to an
- * open-coded struct we do not use), hence support both versions. */
- const char *dle = NULL;
- r = dlopen_safe("libidn.so.11", &dl, &dle);
- if (r < 0) {
- log_debug_errno(r, "libidn support is not available: %s", dle ?: STRERROR(r));
- return -EOPNOTSUPP; /* turn into recognizable error */
- }
- log_debug("Loaded 'libidn.so.11' via dlopen()");
- } else
- log_debug("Loaded 'libidn.so.12' via dlopen()");
-
- r = dlsym_many_or_warn(
- dl,
- LOG_DEBUG,
- DLSYM_ARG(idna_to_ascii_4i),
- DLSYM_ARG(idna_to_unicode_44i),
- DLSYM_ARG(stringprep_ucs4_to_utf8),
- DLSYM_ARG(stringprep_utf8_to_ucs4));
- if (r < 0)
- return r;
-
- idn_dl = TAKE_PTR(dl);
-
- return 1;
-}
-#endif
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#if HAVE_LIBIDN2
-# include <idn2.h>
-#elif HAVE_LIBIDN
-# include <idna.h>
-# include <stringprep.h>
-#endif
-
#include "shared-forward.h"
-#if HAVE_LIBIDN2 || HAVE_LIBIDN
+#if HAVE_LIBIDN2
+#include <idn2.h>
+
#include "dlfcn-util.h"
+extern DLSYM_PROTOTYPE(idn2_lookup_u8);
+extern const char *(*sym_idn2_strerror)(int rc) _const_;
+extern DLSYM_PROTOTYPE(idn2_to_unicode_8z8z);
+
int dlopen_idn(void);
#else
static inline int dlopen_idn(void) {
return -EOPNOTSUPP;
}
#endif
-
-#if HAVE_LIBIDN2
-extern DLSYM_PROTOTYPE(idn2_lookup_u8);
-extern const char *(*sym_idn2_strerror)(int rc) _const_;
-extern DLSYM_PROTOTYPE(idn2_to_unicode_8z8z);
-#endif
-
-#if HAVE_LIBIDN
-extern DLSYM_PROTOTYPE(idna_to_ascii_4i);
-extern DLSYM_PROTOTYPE(idna_to_unicode_44i);
-extern DLSYM_PROTOTYPE(stringprep_ucs4_to_utf8);
-extern DLSYM_PROTOTYPE(stringprep_utf8_to_ucs4);
-#endif
'hostname-setup.c',
'hwdb-util.c',
'id128-print.c',
- 'idn-util.c',
'ima-util.c',
'image-policy.c',
'import-util.c',
shared_sources += files('libmount-util.c')
endif
+if conf.get('HAVE_LIBIDN2') == 1
+ shared_sources += files('idn-util.c')
+endif
+
generate_ip_protocol_list = files('generate-ip-protocol-list.sh')
ip_protocol_list_txt = custom_target(
input : [generate_ip_protocol_list, ipproto_sources],
libelf_cflags,
libfido2_cflags,
libgcrypt_cflags,
- libidn_cflags,
+ libidn2_cflags,
libkmod_cflags,
libmount_cflags,
libopenssl,
ASSERT_DLOPEN(dlopen_dw, HAVE_ELFUTILS);
ASSERT_DLOPEN(dlopen_elf, HAVE_ELFUTILS);
ASSERT_DLOPEN(dlopen_gcrypt, HAVE_GCRYPT);
- ASSERT_DLOPEN(dlopen_idn, HAVE_LIBIDN2 || HAVE_LIBIDN);
+ ASSERT_DLOPEN(dlopen_idn, HAVE_LIBIDN2);
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR);
ASSERT_DLOPEN(dlopen_libarchive, HAVE_LIBARCHIVE);
}
TEST(dns_name_apply_idna) {
- const int ret = HAVE_LIBIDN2 | HAVE_LIBIDN;
+ const int ret = HAVE_LIBIDN2;
/* IDNA2008 forbids names with hyphens in third and fourth positions
* (https://tools.ietf.org/html/rfc5891#section-4.2.3.1).
* labels. If registrars follow IDNA2008 we'll just be performing a
* useless lookup.
*/
- const int ret2 = HAVE_LIBIDN;
test_dns_name_apply_idna_one("", ret, "");
test_dns_name_apply_idna_one("foo", ret, "foo");
test_dns_name_apply_idna_one("föö.bär.", ret, "xn--f-1gaa.xn--br-via");
test_dns_name_apply_idna_one("xn--f-1gaa.xn--br-via", ret, "xn--f-1gaa.xn--br-via");
- test_dns_name_apply_idna_one("_443._tcp.fedoraproject.org", ret2,
+ test_dns_name_apply_idna_one("_443._tcp.fedoraproject.org", 0,
"_443._tcp.fedoraproject.org");
- test_dns_name_apply_idna_one("_443", ret2, "_443");
- test_dns_name_apply_idna_one("gateway", ret, "gateway");
- test_dns_name_apply_idna_one("_gateway", ret2, "_gateway");
+ test_dns_name_apply_idna_one("_443", 0, "_443");
+ test_dns_name_apply_idna_one("gateway", 0, "gateway");
+ test_dns_name_apply_idna_one("_gateway", 0, "_gateway");
- test_dns_name_apply_idna_one("r3---sn-ab5l6ne7.googlevideo.com", ret2,
- ret2 ? "r3---sn-ab5l6ne7.googlevideo.com" : "");
+ test_dns_name_apply_idna_one("r3---sn-ab5l6ne7.googlevideo.com", 0, "");
}
TEST(dns_name_is_valid_or_address) {