Make ipa-client-install error messages more understandable and relevant.

* Check remote LDAP server to see if it is a V2 server
* Replace numeric return values with alphanumeric constants
* Display the error message from the ipa-enrollment extended op
* Remove generic join failed error message when XML-RPC fails
* Don't display Certificate subject base when enrollment fails
* Return proper error message when LDAP bind fails

https://fedorahosted.org/freeipa/ticket/1417
This commit is contained in:
Rob Crittenden 2011-07-06 10:30:24 -04:00
parent e8c7eaf260
commit 02df85bb2e
3 changed files with 53 additions and 36 deletions

View File

@ -28,7 +28,7 @@ try:
import logging
import tempfile
import getpass
import ipaclient.ipadiscovery
from ipaclient import ipadiscovery
import ipaclient.ipachangeconf
import ipaclient.ntpconf
from ipapython.ipautil import run, user_input, CalledProcessError, file_exists
@ -703,15 +703,18 @@ def main():
sys.exit('Invalid hostname \'%s\', must be lower-case.' % hostname)
# Create the discovery instance
ds = ipaclient.ipadiscovery.IPADiscovery()
ds = ipadiscovery.IPADiscovery()
ret = ds.search(domain=options.domain, server=options.server)
ret = ds.search(domain=options.domain, server=options.server, hostname=hostname)
if ret == -10:
if ret == ipadiscovery.BAD_HOST_CONFIG:
print >>sys.stderr, "Can't get the fully qualified name of this host"
print >>sys.stderr, "Please check that the client is properly configured"
return ret
if ret == -1 or not ds.getDomainName():
if ret == ipadiscovery.NOT_FQDN:
print >>sys.stderr, "%s is not a fully-qualified hostname" % hostname
return ret
if ret == ipadiscovery.NO_LDAP_SERVER or not ds.getDomainName():
logging.debug("Domain not found")
if options.domain:
cli_domain = options.domain
@ -722,14 +725,14 @@ def main():
print "DNS discovery failed to determine your DNS domain"
cli_domain = user_input("Please provide the domain name of your IPA server (ex: example.com)", allow_empty = False)
logging.debug("will use domain: %s\n", cli_domain)
ret = ds.search(domain=cli_domain, server=options.server)
ret = ds.search(domain=cli_domain, server=options.server, hostname=hostname)
if not cli_domain:
if ds.getDomainName():
cli_domain = ds.getDomainName()
logging.debug("will use domain: %s\n", cli_domain)
if ret == -2 or not ds.getServerName():
if ret == ipadiscovery.NO_LDAP_SERVER or not ds.getServerName():
logging.debug("IPA Server not found")
if options.server:
cli_server = options.server
@ -740,7 +743,7 @@ def main():
print "DNS discovery failed to find the IPA Server"
cli_server = user_input("Please provide your IPA server name (ex: ipa.example.com)", allow_empty = False)
logging.debug("will use server: %s\n", cli_server)
ret = ds.search(domain=cli_domain, server=cli_server)
ret = ds.search(domain=cli_domain, server=cli_server, hostname=hostname)
else:
dnsok = True
if not cli_server:
@ -748,6 +751,9 @@ def main():
cli_server = ds.getServerName()
logging.debug("will use server: %s\n", cli_server)
if ret == ipadiscovery.NOT_IPA_SERVER:
print >>sys.stderr, "%s is not an IPA v2 Server." % cli_server
return ret
if ret != 0:
print >>sys.stderr, "Failed to verify that "+cli_server+" is an IPA Server."
print >>sys.stderr, "This may mean that the remote server is not up or is not reachable"
@ -861,11 +867,7 @@ def main():
(stdout, stderr, returncode) = run(join_args, raiseonerr=False, env=env)
if returncode != 0:
if returncode == 17: # XML-RPC fault - possible IPA v1/v2 incompatibility
print "Joining realm failed because of failing XML-RPC request."
print " This error may be caused by incompatible server/client major versions."
else:
print >>sys.stderr, "Joining realm failed: %s" % stderr,
print >>sys.stderr, "Joining realm failed: %s" % stderr,
if not options.force:
return 1
print " Use ipa-getkeytab to obtain a host principal for this server."

View File

@ -475,15 +475,9 @@ join_ldap(const char *ipaserver, char *hostname, const char ** binddn, const cha
/* Now rebind as the host */
ld = connect_ldap(ipaserver, *binddn, bindpw);
if (!ld) {
if (has_principal) {
if (!quiet)
fprintf(stderr, _("Host is already joined.\n"));
rval = 13;
} else {
if (!quiet)
fprintf(stderr, _("Incorrect password.\n"));
rval = 15;
}
if (!quiet)
fprintf(stderr, _("Incorrect password.\n"));
rval = 15;
goto done;
}
@ -491,13 +485,19 @@ join_ldap(const char *ipaserver, char *hostname, const char ** binddn, const cha
valrequest.bv_len = strlen(hostname);
if ((rc = ldap_extended_operation_s(ld, JOIN_OID, &valrequest, NULL, NULL, &oidresult, &valresult)) != LDAP_SUCCESS) {
char *s = NULL;
#ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &s);
#else
ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &s);
#endif
if (!quiet)
fprintf(stderr, _("principal not found in host entry\n"));
fprintf(stderr, _("Enrollment failed. %s\n"), s);
if (debug) {
fprintf(stderr, "ldap_extended_operation_s failed: %s",
ldap_err2string(rc));
}
rval = 18;
rval = 13;
goto ldap_done;
}
@ -1003,7 +1003,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *k
}
cleanup:
if (NULL != subject && !quiet)
if (NULL != subject && !quiet && rval == 0)
fprintf(stderr, _("Certificate subject base is: %s\n"), subject);
free((char *)princ);

View File

@ -26,6 +26,13 @@ import ldap
from ldap import LDAPError
from ipapython.ipautil import run, CalledProcessError
NOT_FQDN = -1
NO_LDAP_SERVER = -2
REALM_NOT_FOUND = -3
NOT_IPA_SERVER = -4
BAD_HOST_CONFIG = -10
class IPADiscovery:
def __init__(self):
@ -95,8 +102,7 @@ class IPADiscovery:
domain = domain[p+1:]
return (None, None)
def search(self, domain = "", server = ""):
hostname = ""
def search(self, domain = "", server = "", hostname=None):
qname = ""
results = []
result = []
@ -108,14 +114,15 @@ class IPADiscovery:
if not domain: #domain not provided do full DNS discovery
# get the local host name
hostname = socket.getfqdn()
if not hostname:
return -10 #bad host configuration
hostname = socket.getfqdn()
if not hostname:
return BAD_HOST_CONFIG
# first, check for an LDAP server for the local domain
p = hostname.find(".")
if p == -1: #no domain name
return -1
return NOT_FQDN
domain = hostname[p+1:]
# Get the list of domains from /etc/resolv.conf, we'll search
@ -133,14 +140,14 @@ class IPADiscovery:
self.domain = domain
break
if not self.domain: #no ldap server found
return -1
return NO_LDAP_SERVER
else:
logging.debug("[ipadnssearchldap]")
self.server = self.ipadnssearchldap(domain)
if self.server:
self.domain = domain
else:
return -2 #no ldap server found
return NO_LDAP_SERVER
else: #server forced on us, this means DNS doesn't work :/
@ -151,7 +158,7 @@ class IPADiscovery:
logging.debug("[ipadnssearchkrb]")
krbret = self.ipadnssearchkrb(self.domain)
if not server and not krbret[0]:
return -3 # realm for autodiscovery not found
return REALM_NOT_FOUND
self.realm = krbret[0]
self.kdc = krbret[1]
@ -161,7 +168,7 @@ class IPADiscovery:
ldapret = self.ipacheckldap(self.server, self.realm)
if not ldapret:
return -4 # not an IPA server (or broken config)
return NOT_IPA_SERVER
self.server = ldapret[0]
self.realm = ldapret[1]
@ -169,6 +176,14 @@ class IPADiscovery:
return 0
def ipacheckldap(self, thost, trealm):
"""
Given a host and kerberos realm verify that it is an IPA LDAP
server hosting the realm. The connection is an SSL connection
so the remote IPA CA cert must be available at
http://HOST/ipa/config/ca.crt
Returns a list [host, realm] or an empty list on error.
"""
lret = []
lres = []
@ -219,7 +234,7 @@ class IPADiscovery:
linfo = lret[0][1][lattr][0].lower()
break
if not linfo:
if not linfo or linfo.lower() != 'ipa v2.0':
return []
#search and return known realms
@ -323,5 +338,5 @@ class IPADiscovery:
if not kdc:
logging.debug("SRV record for KDC not found! Realm: %s, SRV record: %s" % (realm, qname))
return [realm, kdc]