summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2010-04-05 16:27:46 -0400
committerJason Gerard DeRose <jderose@redhat.com>2010-04-23 04:57:40 -0600
commit1d635090cbd68b6bec9ce57a2fbfd9ff1b91f908 (patch)
tree3816a3809f5274741850c89ea830c24859f05e64
parent7c61663def1b00ceb4daf22be7a8d1c7116b6433 (diff)
downloadfreeipa-1d635090cbd68b6bec9ce57a2fbfd9ff1b91f908.tar.gz
freeipa-1d635090cbd68b6bec9ce57a2fbfd9ff1b91f908.tar.xz
freeipa-1d635090cbd68b6bec9ce57a2fbfd9ff1b91f908.zip
Use the certificate subject base in IPA when requesting certs in certmonger.
When using the dogtag CA we can control what the subject of an issued certificate is regardless of what is in the CSR, we just use the CN value. The selfsign CA does not have this capability. The subject format must match the configured format or certificate requests are rejected. The default format is CN=%s,O=IPA. certmonger by default issues requests with just CN so all requests would fail if using the selfsign CA. This subject base is stored in cn=ipaconfig so we can just fetch that value in the enrollment process and pass it to certmonger to request the right thing. Note that this also fixes ipa-join to work with the new argument passing mechanism.
-rw-r--r--ipa-client/ipa-install/ipa-client-install17
-rw-r--r--ipa-client/ipa-join.c89
-rw-r--r--ipaserver/plugins/join.py3
-rw-r--r--ipaserver/rpcserver.py3
4 files changed, 103 insertions, 9 deletions
diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 9e66e786..7a5e0931 100644
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -301,7 +301,7 @@ def configure_krb5_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server, d
return 0
-def configure_certmonger(fstore, options):
+def configure_certmonger(fstore, subject_base, cli_realm, options):
started = True
try:
@@ -319,8 +319,10 @@ def configure_certmonger(fstore, options):
# Request our host cert
if started:
+ subject = 'CN=%s,%s' % (socket.getfqdn(), subject_base)
+ principal = 'host/%s@%s' % (socket.getfqdn(), cli_realm)
try:
- run(["ipa-getcert", "request", "-d", "/etc/pki/nssdb", "-n", "Server-Cert"])
+ run(["ipa-getcert", "request", "-d", "/etc/pki/nssdb", "-n", "Server-Cert", "-N", subject, "-K", principal])
except:
print "certmonger request for host certificate failed"
@@ -370,6 +372,8 @@ def main():
cli_realm = None
cli_basedn = None
+ subject_base = "O=IPA"
+
if options.unattended and (options.password is None and options.principal is None and options.prompt_password is False) and not options.on_master:
print "One of password and principal are required."
return 1
@@ -489,6 +493,13 @@ def main():
if not options.force:
return 1
print " Use ipa-getkeytab to obtain a host principal for this server."
+
+ start = stderr.find('Certificate subject base is: ')
+ if start >= 0:
+ start = start + 29
+ subject_base = stderr[start:]
+ subject_base = subject_base.strip()
+
finally:
if options.principal is not None:
(stderr, stdout, returncode) = run(["/usr/kerberos/bin/kdestroy"], raiseonerr=False)
@@ -511,7 +522,7 @@ def main():
print "Configured /etc/ldap.conf"
if not options.on_master:
- configure_certmonger(fstore, options)
+ configure_certmonger(fstore, subject_base, cli_realm, options)
# If on master assume kerberos is already configured properly.
if not options.on_master:
diff --git a/ipa-client/ipa-join.c b/ipa-client/ipa-join.c
index 5b1f0a60..094bc948 100644
--- a/ipa-client/ipa-join.c
+++ b/ipa-client/ipa-join.c
@@ -261,6 +261,57 @@ done:
return rval;
}
+static int
+get_subject(const char *ipaserver, char *ldap_base, char **subject)
+{
+ LDAP *ld = NULL;
+ char *attrs[] = {"ipaCertificateSubjectBase", NULL};
+ char base[LINE_MAX];
+ LDAPMessage *entry, *res = NULL;
+ struct berval **ncvals;
+ int ret, rval = 0;
+
+ ld = connect_ldap(ipaserver, NULL, NULL);
+ if (!ld) {
+ rval = 14;
+ goto done;
+ }
+
+ strcpy(base, "cn=ipaconfig,cn=etc,");
+ strcat(base, ldap_base);
+
+ 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",
+ attrs[0], 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:
+ if (res) ldap_msgfree(res);
+ if (ld != NULL) {
+ ldap_unbind_ext(ld, NULL, NULL);
+ }
+
+ return rval;
+}
+
/* Join a host to the current IPA realm.
*
* There are several scenarios for this:
@@ -280,7 +331,7 @@ done:
* the state of the entry.
*/
static int
-join_ldap(const char *ipaserver, const char *hostname, const char ** binddn, const char *bindpw, const char ** princ, int quiet)
+join_ldap(const char *ipaserver, const char *hostname, const char ** binddn, const char *bindpw, const char **princ, const char **subject, int quiet)
{
LDAP *ld;
char *filter = NULL;
@@ -304,6 +355,11 @@ join_ldap(const char *ipaserver, const char *hostname, const char ** binddn, con
goto done;
}
+ if (get_subject(ipaserver, ldap_base, &subject) != 0) {
+ fprintf(stderr, "Unable to determine certificate subject of %s\n", ipaserver);
+ /* Not a critical failure */
+ }
+
ld = connect_ldap(ipaserver, NULL, NULL);
if (!ld) {
fprintf(stderr, "Unable to make an LDAP connection to %s\n", ipaserver);
@@ -382,6 +438,7 @@ ldap_done:
free(filter);
free(search_base);
free(ldap_base);
+ free(subject);
if (ld != NULL) {
ldap_unbind_ext(ld, NULL, NULL);
}
@@ -392,8 +449,9 @@ done:
}
static int
-join_krb5(const char *ipaserver, const char *hostname, const char **hostdn, const char **princ, int quiet) {
+join_krb5(const char *ipaserver, const char *hostname, const char **hostdn, const char **princ, const char **subject, int quiet) {
xmlrpc_env env;
+ xmlrpc_value * argArrayP = NULL;
xmlrpc_value * paramArrayP = NULL;
xmlrpc_value * paramP = NULL;
xmlrpc_value * optionsP = NULL;
@@ -403,6 +461,7 @@ join_krb5(const char *ipaserver, const char *hostname, const char **hostdn, cons
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;
@@ -424,17 +483,19 @@ join_krb5(const char *ipaserver, const char *hostname, const char **hostdn, cons
#endif
serverInfoP = xmlrpc_server_info_new(&env, url);
+ argArrayP = xmlrpc_array_new(&env);
paramArrayP = xmlrpc_array_new(&env);
if (hostname == NULL)
paramP = xmlrpc_string_new(&env, uinfo.nodename);
else
paramP = xmlrpc_string_new(&env, hostname);
+ xmlrpc_array_append_item(&env, argArrayP, paramP);
#ifdef REALM
if (!quiet)
printf("Joining %s to IPA realm %s\n", uinfo.nodename, iparealm);
#endif
- xmlrpc_array_append_item(&env, paramArrayP, paramP);
+ xmlrpc_array_append_item(&env, paramArrayP, argArrayP);
xmlrpc_DECREF(paramP);
optionsP = xmlrpc_build_value(&env, "{s:s,s:s}",
@@ -488,7 +549,20 @@ join_krb5(const char *ipaserver, const char *hostname, const char **hostdn, cons
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);
if (resultP) xmlrpc_DECREF(resultP);
@@ -513,6 +587,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *k
char *iparealm = NULL;
char * conf_data = NULL;
const char * princ = NULL;
+ const char * subject = NULL;
const char * hostdn = NULL;
struct utsname uinfo;
@@ -548,7 +623,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *k
}
if (bindpw)
- rval = join_ldap(ipaserver, hostname, &hostdn, bindpw, &princ, quiet);
+ rval = join_ldap(ipaserver, hostname, &hostdn, bindpw, &princ, &subject, quiet);
else {
krberr = krb5_init_context(&krbctx);
if (krberr) {
@@ -569,7 +644,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *k
rval = 6;
goto cleanup;
}
- rval = join_krb5(ipaserver, hostname, &hostdn, &princ, quiet);
+ rval = join_krb5(ipaserver, hostname, &hostdn, &princ, &subject, quiet);
}
if (rval) goto cleanup;
@@ -629,7 +704,11 @@ join(const char *server, const char *hostname, const char *bindpw, const char *k
}
cleanup:
+ if (NULL != subject)
+ fprintf(stderr, "Certificate subject base is: %s\n", subject);
+
free((char *)princ);
+ free((char *)subject);
if (bindpw)
ldap_memfree((void *)hostdn);
else
diff --git a/ipaserver/plugins/join.py b/ipaserver/plugins/join.py
index e2f72bfa..74fa806f 100644
--- a/ipaserver/plugins/join.py
+++ b/ipaserver/plugins/join.py
@@ -113,6 +113,9 @@ class join(Command):
attrs_list = api.Command['host_add'](hostname)['result']
dn = attrs_list['dn']
+ config = api.Command['config_show']()['result']
+ attrs_list['ipacertificatesubjectbase'] = config['ipacertificatesubjectbase']
+
return (dn, attrs_list)
api.register(join)
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 795a240d..71d55445 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -295,7 +295,8 @@ class xmlserver(WSGIExecutioner):
self.info('response: %s: %s', error.__class__.__name__, str(error))
response = Fault(error.errno, error.strerror)
else:
- self.info('response: entries returned %d', result.get('count', 1))
+ if isinstance(result, dict):
+ self.info('response: entries returned %d', result.get('count', 1))
response = (result,)
return xml_dumps(response, methodresponse=True)