Projects/Host-realm pluggable interface
This project adds a pluggable interface for host-to-realm mapping.
The krb5_get_host_realm() function attempts to map a hostname to one or more realm names. We never return more than one answer, and all existing in-tree consumers of this function use only the first answer. One of the possible answers is an empty realm, which means referrals should be used if the consumer is making a TGS request. krb5_get_host_realm() is used by krb5_sname_to_principal(), and also by the KDC in order to produce host referrals.
The krb5_get_fallback_realm() function attempts to map a hostname to one or more realms as well, using more heuristic or insecure approaches than krb5_get_host_realm(). We never return or consume more than one answer. krb5_get_fallback_realm() is used by the libkrb5 TGS request code path if we get an error from trying referrals.
The krb5_get_default_realm() function returns a default realm for the local host (although it may be overridden for a particular context using krb5_set_default_realm()). It is used chiefly by krb5_parse_name() when the string form of the principal contains no realm, but is also used in many other ways.
The currently supported mechanisms for these functions are:
- krb5_get_host_realm() only uses the profile [domain_realm] section. If it cannot get a mapping that way, it returns the referral realm.
- krb5_get_fallback_realm() has several heuristics:
- With explicit configuration, we can use a TXT record lookup of the hostname.
- With explicit configuration, we can try to resolve the uppercased parent domains as realms, to a specified depth.
- We can use the uppercased parent domain.
- We can use the default realm.
- krb5_get_default_realm() uses the profile default_realm value. If this value is not set, it can use a TXT record lookup of the local hostname with explicit configuration.
krb5_get_host_realm() and krb5_get_fallback_realm() "clean" their input hostname by converting it to lower-case and removing any trailing period.
krb5_sname_to_principal() canonicalizes its input hostname using a forward getaddrinfo() lookup and usually a reverse getnameinfo() lookup, before calling krb5_get_host_realm().
The behavior of these functions has changed over time. Prior to the introduction of TGS referral support in 1.6, we did not have krb5_get_fallback_host_realm(), and krb5_get_host_realm() applied most of the heuristics currently applied by that function.
The following functionality is in scope for the pluggable interface:
- Determining the behavior of krb5_get_host_realm()
- Determining the behavior of krb5_get_fallback_host_realm()
- Determining the behavior of krb5_get_default_realm()
- The ability to return multiple answers
The following functionality is not in scope:
- Hostname canonicalization
- Hostname "cleaning" (converting to lowercase and removing trailing periods)
The new pluggable interface will be named "hostrealm" and will have the following methods (plus initialization and finalization methods):
krb5_error_code (*host_realm)(krb5_context context, krb5_hostrealm_moddata data, const char *host, char ***realms_out); krb5_error_code (*fallback_realm)(krb5_context context, krb5_hostrealm_moddata data, const char *host, char ***realms_out); krb5_error_code (*default_realm)(krb5_context context, krb5_hostrealm_moddata data, char ***realms_out); void (*free_list_fn)(krb5_context context, krb5_hostrealm_moddata data, char **list);
Each of the three query functions may:
- Place a list of realms in *realms_out and return 0. Only the first answer will be consumed by current code, but subsequent answers may be used in the future.
- Return KRB5_PLUGIN_NO_HANDLE to defer to later modules.
- Return any other error code to terminate processing.
The following built-in modules will be provided to implement the current built-in behavior:
- The "profile" module will provide a host_realm method using the [domain_realm] section of the profile and a default_realm method using the default_realm profile variable.
- The "dns" module will provide fallback_realm and default_realm methods using DNS TXT records, if the dns_realm profile variable is set.
- The "domain" module will provide a fallback_realm method using the domain heuristics.
The final fallback heuristic (using the default realm) will a hardcoded behavior, used if no module returns a result for fallback_realm.
Plugin module ordering
This is the fourth pluggable interface (after locate, ccselect, and localauth) which have no natural way to order modules, and whose accumulator behavior is order-dependent for some operations. We can improve the predictability of these interfaces by providing a well-defined order for plugin modules. This project proposes the following ordering constraints, which do not require the addition of any new user-visible options or internal APIs:
- The default order is the dynamic modules in the order they were registered in the profile, followed by the built-in modules in the order they were registered by the code.
- If any modules are disabled, they are removed without affecting the order of the remaining modules.
- If modules are explicitly enabled with enable_only, the order of the enable_only list determines the order of the modules.
A test module will be added to plugins/hostrealm, to be built by default but not installed. A test harness and script will use the module to exercise the pluggable interface.
A new page under doc/plugindev will document the pluggable interface. krb5_conf.rst will be amended to briefly describe the interface.
Mailing list discussions
2721a662a3d88601bff991599928c1566be7485a Document hostrealm interface 7ad5f3bfd8b57d2f4c001182792e25968309ca8a Add hostrealm interface tests 4f7f1fce6edca17db625d76c1f81ea098f29c313 Move utility functions to hostrealm.c db21244a069e581a392dff5b320e758e06a28e4d Use hostrealm interface for realm mapping d61fbd85467c71c9bfb185e0e675e1619972bd0b Add hostrealm pluggable interface definition
- Add a plugin interface to control hostname-to-realm mappings and the default realm.