resolve: unify two validate_and_mangle_flags()

The argument `Manager *manager`, is currently unused, but will be used
later.
This commit is contained in:
Yu Watanabe
2025-02-16 22:39:52 +09:00
parent 5f494e8fa6
commit 7cf95470f3
4 changed files with 60 additions and 107 deletions
+8 -57
View File
@@ -361,51 +361,6 @@ finish:
}
}
static int validate_and_mangle_flags(
const char *name,
uint64_t *flags,
uint64_t ok,
sd_bus_error *error) {
assert(flags);
/* Checks that the client supplied interface index and flags parameter actually are valid and make
* sense in our method call context. Specifically:
*
* 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive
*
* 2. Only the protocols flags and a bunch of NO_XYZ flags are set, at most. Plus additional flags
* specific to our method, passed in the "ok" parameter.
*
* 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way
* clients can simply pass 0 as flags and all will work as it should. They can also use this so
* that clients don't have to know all the protocols resolved implements, but can just specify 0
* to mean "all supported protocols".
*/
if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|
SD_RESOLVED_NO_CNAME|
SD_RESOLVED_NO_VALIDATE|
SD_RESOLVED_NO_SYNTHESIZE|
SD_RESOLVED_NO_CACHE|
SD_RESOLVED_NO_ZONE|
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
SD_RESOLVED_NO_STALE|
SD_RESOLVED_RELAX_SINGLE_LABEL|
ok))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
*flags |= SD_RESOLVED_PROTOCOLS_ALL;
/* Imply SD_RESOLVED_NO_SEARCH if permitted and name is dot suffixed. */
if (name && FLAGS_SET(ok, SD_RESOLVED_NO_SEARCH) && dns_name_dot_suffixed(name) > 0)
*flags |= SD_RESOLVED_NO_SEARCH;
return 0;
}
static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname, int family, uint64_t flags) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *canonical = NULL;
@@ -519,9 +474,8 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
r = validate_and_mangle_flags(hostname, &flags, SD_RESOLVED_NO_SEARCH, error);
if (r < 0)
return r;
if (validate_and_mangle_query_flags(m, &flags, hostname, SD_RESOLVED_NO_SEARCH) < 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
r = parse_as_address(message, ifindex, hostname, family, flags);
if (r != 0)
@@ -674,9 +628,8 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
if (ifindex < 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
r = validate_and_mangle_flags(NULL, &flags, 0, error);
if (r < 0)
return r;
if (validate_and_mangle_query_flags(m, &flags, /* name = */ NULL, /* ok = */ 0) < 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
r = dns_question_new_reverse(&question, family, &a);
if (r < 0)
@@ -843,9 +796,8 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
if (dns_type_is_obsolete(type))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
r = validate_and_mangle_flags(name, &flags, 0, error);
if (r < 0)
return r;
if (validate_and_mangle_query_flags(m, &flags, name, /* ok = */ 0) < 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
question = dns_question_new(1);
if (!question)
@@ -1378,9 +1330,8 @@ static int bus_method_resolve_service(sd_bus_message *message, void *userdata, s
if (name && !type)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
r = validate_and_mangle_flags(name, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
if (r < 0)
return r;
if (validate_and_mangle_query_flags(m, &flags, name, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS) < 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false);
if (r < 0)
+46
View File
@@ -1440,3 +1440,49 @@ bool dns_query_fully_authoritative(DnsQuery *q) {
* explicitly check previous redirects here.) */
return (q->answer_query_flags & SD_RESOLVED_FROM_MASK & ~(SD_RESOLVED_FROM_TRUST_ANCHOR | SD_RESOLVED_FROM_ZONE)) == 0;
}
int validate_and_mangle_query_flags(
Manager *manager,
uint64_t *flags,
const char *name,
uint64_t ok) {
assert(manager);
assert(flags);
/* Checks that the client supplied interface index and flags parameter actually are valid and make
* sense in our method call context. Specifically:
*
* 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive
*
* 2. Only the protocols flags and a bunch of NO_XYZ flags are set, at most. Plus additional flags
* specific to our method, passed in the "ok" parameter.
*
* 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way
* clients can simply pass 0 as flags and all will work as it should. They can also use this so
* that clients don't have to know all the protocols resolved implements, but can just specify 0
* to mean "all supported protocols".
*/
if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|
SD_RESOLVED_NO_CNAME|
SD_RESOLVED_NO_VALIDATE|
SD_RESOLVED_NO_SYNTHESIZE|
SD_RESOLVED_NO_CACHE|
SD_RESOLVED_NO_ZONE|
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
SD_RESOLVED_NO_STALE|
SD_RESOLVED_RELAX_SINGLE_LABEL|
ok))
return -EINVAL;
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
*flags |= SD_RESOLVED_PROTOCOLS_ALL;
/* Imply SD_RESOLVED_NO_SEARCH if permitted and name is dot suffixed. */
if (name && FLAGS_SET(ok, SD_RESOLVED_NO_SEARCH) && dns_name_dot_suffixed(name) > 0)
*flags |= SD_RESOLVED_NO_SEARCH;
return 0;
}
+2
View File
@@ -158,6 +158,8 @@ bool dns_query_fully_authenticated(DnsQuery *q);
bool dns_query_fully_confidential(DnsQuery *q);
bool dns_query_fully_authoritative(DnsQuery *q);
int validate_and_mangle_query_flags(Manager *manager, uint64_t *flags, const char *name, uint64_t ok);
static inline uint64_t dns_query_reply_flags_make(DnsQuery *q) {
assert(q);
+4 -50
View File
@@ -166,52 +166,6 @@ static void vl_on_notification_disconnect(sd_varlink_server *s, sd_varlink *link
}
}
static bool validate_and_mangle_flags(
const char *name,
uint64_t *flags,
uint64_t ok) {
assert(flags);
/* This checks that the specified client-provided flags parameter actually makes sense, and mangles
* it slightly. Specifically:
*
* 1. We check that only the protocol flags and a bunch of NO_XYZ flags are on at most, plus the
* method-specific flags specified in 'ok'.
*
* 2. If no protocols are enabled we automatically convert that to "all protocols are enabled".
*
* The second rule means that clients can just pass 0 as flags for the common case, and all supported
* protocols are enabled. Moreover it's useful so that client's do not have to be aware of all
* protocols implemented in resolved, but can use 0 as protocols flags set as indicator for
* "everything".
*/
if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|
SD_RESOLVED_NO_CNAME|
SD_RESOLVED_NO_VALIDATE|
SD_RESOLVED_NO_SYNTHESIZE|
SD_RESOLVED_NO_CACHE|
SD_RESOLVED_NO_ZONE|
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
SD_RESOLVED_NO_STALE|
SD_RESOLVED_RELAX_SINGLE_LABEL|
ok))
return false;
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
*flags |= SD_RESOLVED_PROTOCOLS_ALL;
/* If the SD_RESOLVED_NO_SEARCH flag is acceptable, and the query name is dot-suffixed, turn off
* search domains. Note that DNS name normalization drops the dot suffix, hence we propagate this
* into the flags field as early as we can. */
if (name && FLAGS_SET(ok, SD_RESOLVED_NO_SEARCH) && dns_name_dot_suffixed(name) > 0)
*flags |= SD_RESOLVED_NO_SEARCH;
return true;
}
static int find_addr_records(
sd_json_variant **array,
DnsQuestion *question,
@@ -387,7 +341,7 @@ static int vl_method_resolve_hostname(sd_varlink *link, sd_json_variant *paramet
if (!IN_SET(p.family, AF_UNSPEC, AF_INET, AF_INET6))
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family"));
if (!validate_and_mangle_flags(p.name, &p.flags, SD_RESOLVED_NO_SEARCH))
if (validate_and_mangle_query_flags(m, &p.flags, p.name, SD_RESOLVED_NO_SEARCH) < 0)
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
r = parse_as_address(link, &p);
@@ -550,7 +504,7 @@ static int vl_method_resolve_address(sd_varlink *link, sd_json_variant *paramete
if (FAMILY_ADDRESS_SIZE(p.family) != p.address_size)
return sd_varlink_error(link, "io.systemd.Resolve.BadAddressSize", NULL);
if (!validate_and_mangle_flags(NULL, &p.flags, 0))
if (validate_and_mangle_query_flags(m, &p.flags, /* name = */ NULL, /* ok = */ 0) < 0)
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
r = dns_question_new_reverse(&question, p.family, &p.address);
@@ -1044,7 +998,7 @@ static int vl_method_resolve_service(sd_varlink* link, sd_json_variant* paramete
if (p.name && !p.type) /* Service name cannot be specified without service type. */
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("type"));
if (!validate_and_mangle_flags(p.name, &p.flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS))
if (validate_and_mangle_query_flags(m, &p.flags, p.name, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS) < 0)
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
r = dns_question_new_service(&question_utf8, p.name, p.type, p.domain, !(p.flags & SD_RESOLVED_NO_TXT), false);
@@ -1184,7 +1138,7 @@ static int vl_method_resolve_record(sd_varlink *link, sd_json_variant *parameter
if (dns_type_is_obsolete(p.type))
return sd_varlink_error(link, "io.systemd.Resolve.ResourceRecordTypeObsolete", NULL);
if (!validate_and_mangle_flags(p.name, &p.flags, SD_RESOLVED_NO_SEARCH))
if (validate_and_mangle_query_flags(m, &p.flags, p.name, SD_RESOLVED_NO_SEARCH) < 0)
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
_cleanup_(dns_question_unrefp) DnsQuestion *question = dns_question_new(1);