From 1c7771f2e64fcbba2548bd86a7d9ca11e212cd50 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Aug 29 2018 11:53:03 +0000 Subject: Retrieve certificate subject base directly instead of ipa-join The subject base is used as a fallback to find the available CA certificates during client enrollment if the LDAP connection fails (e.g. due to new client connecting to very old server) and for constructing the subject if a certificate is requested. raw=True is passed to config-show in order to avoid parsing the server roles which will fail because the services aren't marked as enabled until after the client installation is successful on a master. ipa-join providing the subject base via stderr was fragile and would cause client enrollment to fail if any other output was included in stderr. https://pagure.io/freeipa/issue/7674 Signed-off-by: Rob Crittenden Reviewed-By: Christian Heimes --- diff --git a/client/ipa-join.c b/client/ipa-join.c index 7f406b4..7f454f7 100644 --- a/client/ipa-join.c +++ b/client/ipa-join.c @@ -371,62 +371,6 @@ done: return rval; } -/* - * Get the certificate subject base from the IPA configuration. - * - * Not considered a show-stopper if this fails for some reason. - * - * The caller is responsible for binding/unbinding to LDAP. - */ -static int -get_subject(LDAP *ld, char *ldap_base, const char **subject, int quiet) -{ - char *attrs[] = {"ipaCertificateSubjectBase", NULL}; - char *base = NULL; - LDAPMessage *entry, *res = NULL; - struct berval **ncvals; - int ret, rval = 0; - - ret = asprintf(&base, "cn=ipaconfig,cn=etc,%s", ldap_base); - if (ret == -1) - { - if (!quiet) - fprintf(stderr, _("Out of memory!\n")); - rval = 3; - goto done; - } - - ret = ldap_search_ext_s(ld, base, LDAP_SCOPE_BASE, - "objectclass=*", attrs, 0, - NULL, NULL, NULL, 0, &res); - - if (ret != LDAP_SUCCESS) { - fprintf(stderr, - _("Search for ipaCertificateSubjectBase failed with error %d"), - ret); - rval = 14; - goto done; - } - - entry = ldap_first_entry(ld, res); - ncvals = ldap_get_values_len(ld, entry, attrs[0]); - if (!ncvals) { - fprintf(stderr, _("No values for %s"), attrs[0]); - rval = 14; - goto done; - } - - *subject = strdup(ncvals[0]->bv_val); - - ldap_value_free_len(ncvals); - -done: - free(base); - if (res) ldap_msgfree(res); - - return rval; -} - /* Join a host to the current IPA realm. * * There are several scenarios for this: @@ -446,7 +390,7 @@ done: * the state of the entry. */ static int -join_ldap(const char *ipaserver, char *hostname, char ** binddn, const char *bindpw, const char *basedn, const char **princ, const char **subject, int quiet) +join_ldap(const char *ipaserver, char *hostname, char ** binddn, const char *bindpw, const char *basedn, const char **princ, int quiet) { LDAP *ld; int rval = 0; @@ -458,7 +402,6 @@ join_ldap(const char *ipaserver, char *hostname, char ** binddn, const char *bin *binddn = NULL; *princ = NULL; - *subject = NULL; if (NULL != basedn) { ldap_base = strdup(basedn); @@ -494,14 +437,6 @@ join_ldap(const char *ipaserver, char *hostname, char ** binddn, const char *bin goto done; } - if (get_subject(ld, ldap_base, subject, quiet) != 0) { - if (!quiet) - fprintf(stderr, - _("Unable to determine certificate subject of %s\n"), - ipaserver); - /* Not a critical failure */ - } - valrequest.bv_val = (char *)hostname; valrequest.bv_len = strlen(hostname); @@ -538,7 +473,7 @@ done: } static int -join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **princ, const char **subject, int force, int quiet) { +join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **princ, int force, int quiet) { xmlrpc_env env; xmlrpc_value * argArrayP = NULL; xmlrpc_value * paramArrayP = NULL; @@ -550,7 +485,6 @@ join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **pri struct utsname uinfo; xmlrpc_value *princP = NULL; xmlrpc_value *krblastpwdchangeP = NULL; - xmlrpc_value *subjectP = NULL; xmlrpc_value *hostdnP = NULL; const char *krblastpwdchange = NULL; char * url = NULL; @@ -559,7 +493,6 @@ join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **pri int ret; *hostdn = NULL; - *subject = NULL; *princ = NULL; /* Start up our XML-RPC client library. */ @@ -658,18 +591,6 @@ join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **pri goto cleanup; } - xmlrpc_struct_find_value(&env, structP, "ipacertificatesubjectbase", &subjectP); - if (subjectP) { - xmlrpc_value * singleprincP = NULL; - - /* FIXME: all values are returned as lists currently. Once this is - * fixed we can read the string directly. - */ - xmlrpc_array_read_item(&env, subjectP, 0, &singleprincP); - xmlrpc_read_string(&env, singleprincP, *&subject); - xmlrpc_DECREF(subjectP); - } - cleanup: if (argArrayP) xmlrpc_DECREF(argArrayP); if (paramArrayP) xmlrpc_DECREF(paramArrayP); @@ -922,7 +843,6 @@ join(const char *server, const char *hostname, const char *bindpw, const char *b char *iparealm = NULL; char * host = NULL; const char * princ = NULL; - const char * subject = NULL; char * hostdn = NULL; struct utsname uinfo; @@ -963,7 +883,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *b } if (bindpw) - rval = join_ldap(ipaserver, host, &hostdn, bindpw, basedn, &princ, &subject, quiet); + rval = join_ldap(ipaserver, host, &hostdn, bindpw, basedn, &princ, quiet); else { krberr = krb5_init_context(&krbctx); if (krberr) { @@ -987,7 +907,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *b rval = 6; goto cleanup; } - rval = join_krb5(ipaserver, host, &hostdn, &princ, &subject, force, + rval = join_krb5(ipaserver, host, &hostdn, &princ, force, quiet); } @@ -1049,11 +969,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *b } cleanup: - if (NULL != subject && !quiet && rval == 0) - fprintf(stderr, _("Certificate subject base is: %s\n"), subject); - free((char *)princ); - free((char *)subject); free(host); if (bindpw) diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py index 627351a..e02c497 100644 --- a/ipaclient/install/client.py +++ b/ipaclient/install/client.py @@ -2684,13 +2684,6 @@ def _install(options): else: logger.info("Enrolled in IPA realm %s", cli_realm) - start = stderr.find('Certificate subject base is: ') - if start >= 0: - start = start + 29 - subject_base = stderr[start:] - subject_base = subject_base.strip() - subject_base = DN(subject_base) - if options.principal is not None: run([paths.KDESTROY], raiseonerr=False, env=env) @@ -2856,6 +2849,20 @@ def _install(options): if not ca_enabled: disable_ra() + try: + result = api.Backend.rpcclient.forward( + 'config_show', + raw=True, # so that servroles are not queried + version=u'2.0' + ) + except Exception as e: + logger.debug("config_show failed %s", e, exc_info=True) + raise ScriptError( + "Failed to retrieve CA certificate subject base: {}".format(e), + rval=CLIENT_INSTALL_ERROR) + else: + subject_base = DN(result['result']['ipacertificatesubjectbase'][0]) + # Create IPA NSS database try: create_ipa_nssdb()