URL: https://github.com/freeipa/freeipa/pull/2299
Author: rcritten
 Title: #2299: Retrieve certificate subject base directly instead of ipa-join
Action: opened

PR body:
"""
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

Testing is handled by existing integration tests, both in plain installations 
and --request-cert to ensure there is a subject base.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/2299/head:pr2299
git checkout pr2299
From e3d199cd4ecb57fec0dc048a17b6399d89f8318e Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcrit...@redhat.com>
Date: Mon, 20 Aug 2018 15:10:34 -0400
Subject: [PATCH] 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 <rcrit...@redhat.com>
---
 client/ipa-join.c           | 92 ++-----------------------------------
 ipaclient/install/client.py | 20 +++++---
 2 files changed, 17 insertions(+), 95 deletions(-)

diff --git a/client/ipa-join.c b/client/ipa-join.c
index 7f406b440a..7f454f723d 100644
--- a/client/ipa-join.c
+++ b/client/ipa-join.c
@@ -371,62 +371,6 @@ get_root_dn(const char *ipaserver, char **ldap_base)
     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 @@ get_subject(LDAP *ld, char *ldap_base, const char **subject, int quiet)
  * 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 @@ join_ldap(const char *ipaserver, char *hostname, char ** binddn, const char *bin
 }
 
 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 800a467340..045b4ba482 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,19 @@ 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:
+        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()
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org

Reply via email to