From b903df96fc5c6352da62bba3b08ce57268977478 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Apr 08 2019 17:10:51 +0000 Subject: Bypass D-BUS interface definition deficiences for trust-fetch-domains In oddjobd it is possible to pass arguments as command line or on the stdin. We use command line to pass them but the way oddjobd registers the D-BUS method signatures is by specifying all arguments as mandatory. Internally, oddjobd simply ignores if you passed less arguments than specified in the D-BUS defition. Unfortunately, it is not possible to specify less than maximum due to D-BUS seeing all arguments in the list (30 is defined for the trust-fetch-domains). To pass options, have to pad a list of arguments to maximum with empty strings and then filter out unneeded ones in the script. Option parser already removes all options from the list of arguments so all we need to do is to take our actual arguments. In case of trust-fetch-domains, it is the name of the domain so we can only care about args[0]. Fixes: https://pagure.io/freeipa/issue/7903 Signed-off-by: Alexander Bokovoy Reviewed-By: Florence Blanc-Renaud --- diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains.in b/install/oddjob/com.redhat.idm.trust-fetch-domains.in index fbb1ed9..58ec5fe 100644 --- a/install/oddjob/com.redhat.idm.trust-fetch-domains.in +++ b/install/oddjob/com.redhat.idm.trust-fetch-domains.in @@ -5,6 +5,7 @@ from ipaserver.install.installutils import is_ipa_configured, ScriptError from ipapython import config, ipautil from ipalib import api from ipapython.dn import DN +from ipapython.dnsutil import DNSName from ipaplatform.constants import constants from ipaplatform.paths import paths import sys @@ -37,7 +38,17 @@ def parse_options(): options, args = parser.parse_args() safe_options = parser.get_safe_opts(options) - return safe_options, options, args + # We only use first argument of the passed args but as D-BUS interface + # in oddjobd cannot expose optional, we fill in empty slots from IPA side + # and filter them here. + trusted_domain = ipautil.fsdecode(args[0]).lower() + + # Accept domain names that at least have two labels. We do not support + # single label Active Directory domains. This also catches empty args. + if len(DNSName(trusted_domain).labels) < 2: + # LSB status code 2: invalid or excess argument(s) + raise ScriptError("You must specify a valid trusted domain name", 2) + return safe_options, options, trusted_domain def retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal): getkeytab_args = ["/usr/sbin/ipa-getkeytab", @@ -87,13 +98,7 @@ if not os.getegid() == 0: # LSB status code 4: user had insufficient privilege raise ScriptError("You must be root to run ipactl.", 4) -safe_options, options, args = parse_options() - -if len(args) != 1: - # LSB status code 2: invalid or excess argument(s) - raise ScriptError("You must specify trusted domain name", 2) - -trusted_domain = ipautil.fsdecode(args[0]).lower() +safe_options, options, trusted_domain = parse_options() api.bootstrap(in_server=True, log=None, context='server', confdir=paths.ETC_IPA) diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py index 8eb9a34..b636eb3 100644 --- a/ipaserver/plugins/trust.py +++ b/ipaserver/plugins/trust.py @@ -446,8 +446,15 @@ def fetch_trusted_domains_over_dbus(myapi, *keys, **options): fetch_domains_method = intf.get_dbus_method( 'fetch_domains', dbus_interface=DBUS_IFACE_TRUST) - (_ret, _stdout, _stderr) = fetch_domains_method( - [forest_name] + method_options) + # Oddjobd D-BUS method definition only accepts fixed number + # of arguments on the command line. Thus, we need to pass + # remaining ones as ''. There are 30 slots to allow for extension + # and the number comes from the 'arguments' definition in + # install/oddjob/etc/oddjobd.conf.d/oddjobd-ipa-trust.conf + method_arguments = [forest_name] + method_arguments.extend(method_options) + method_arguments.extend([''] * (30 - len(method_arguments))) + (_ret, _stdout, _stderr) = fetch_domains_method(*method_arguments) except dbus.DBusException as e: logger.error('Failed to call %s.fetch_domains helper.' 'DBus exception is %s.', DBUS_IFACE_TRUST, str(e))