From: Yu Watanabe Date: Sun, 16 Feb 2025 12:08:58 +0000 (+0900) Subject: resolve: unify two validate_and_mangle_flags() X-Git-Tag: v258-rc1~1289^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cf95470f3aaeb5091ebd493f9ba4427e421d5dd;p=thirdparty%2Fsystemd.git resolve: unify two validate_and_mangle_flags() The argument `Manager *manager`, is currently unused, but will be used later. --- diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index b81b9358d54..96cfd32257a 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -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) diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 78c57da1819..5698511b805 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -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; +} diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h index 1097e90dc09..3a93ff7f1ab 100644 --- a/src/resolve/resolved-dns-query.h +++ b/src/resolve/resolved-dns-query.h @@ -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); diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c index d04bcc332ee..c687dd694ff 100644 --- a/src/resolve/resolved-varlink.c +++ b/src/resolve/resolved-varlink.c @@ -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);