mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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:
parent
e8c7eaf260
commit
02df85bb2e
@ -28,7 +28,7 @@ try:
|
|||||||
import logging
|
import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
import getpass
|
import getpass
|
||||||
import ipaclient.ipadiscovery
|
from ipaclient import ipadiscovery
|
||||||
import ipaclient.ipachangeconf
|
import ipaclient.ipachangeconf
|
||||||
import ipaclient.ntpconf
|
import ipaclient.ntpconf
|
||||||
from ipapython.ipautil import run, user_input, CalledProcessError, file_exists
|
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)
|
sys.exit('Invalid hostname \'%s\', must be lower-case.' % hostname)
|
||||||
|
|
||||||
# Create the discovery instance
|
# 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, "Can't get the fully qualified name of this host"
|
||||||
print >>sys.stderr, "Please check that the client is properly configured"
|
print >>sys.stderr, "Please check that the client is properly configured"
|
||||||
return ret
|
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")
|
logging.debug("Domain not found")
|
||||||
if options.domain:
|
if options.domain:
|
||||||
cli_domain = options.domain
|
cli_domain = options.domain
|
||||||
@ -722,14 +725,14 @@ def main():
|
|||||||
print "DNS discovery failed to determine your DNS domain"
|
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)
|
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)
|
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 not cli_domain:
|
||||||
if ds.getDomainName():
|
if ds.getDomainName():
|
||||||
cli_domain = ds.getDomainName()
|
cli_domain = ds.getDomainName()
|
||||||
logging.debug("will use domain: %s\n", cli_domain)
|
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")
|
logging.debug("IPA Server not found")
|
||||||
if options.server:
|
if options.server:
|
||||||
cli_server = options.server
|
cli_server = options.server
|
||||||
@ -740,7 +743,7 @@ def main():
|
|||||||
print "DNS discovery failed to find the IPA Server"
|
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)
|
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)
|
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:
|
else:
|
||||||
dnsok = True
|
dnsok = True
|
||||||
if not cli_server:
|
if not cli_server:
|
||||||
@ -748,6 +751,9 @@ def main():
|
|||||||
cli_server = ds.getServerName()
|
cli_server = ds.getServerName()
|
||||||
logging.debug("will use server: %s\n", cli_server)
|
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:
|
if ret != 0:
|
||||||
print >>sys.stderr, "Failed to verify that "+cli_server+" is an IPA Server."
|
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"
|
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)
|
(stdout, stderr, returncode) = run(join_args, raiseonerr=False, env=env)
|
||||||
|
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
if returncode == 17: # XML-RPC fault - possible IPA v1/v2 incompatibility
|
print >>sys.stderr, "Joining realm failed: %s" % stderr,
|
||||||
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,
|
|
||||||
if not options.force:
|
if not options.force:
|
||||||
return 1
|
return 1
|
||||||
print " Use ipa-getkeytab to obtain a host principal for this server."
|
print " Use ipa-getkeytab to obtain a host principal for this server."
|
||||||
|
@ -475,15 +475,9 @@ join_ldap(const char *ipaserver, char *hostname, const char ** binddn, const cha
|
|||||||
/* Now rebind as the host */
|
/* Now rebind as the host */
|
||||||
ld = connect_ldap(ipaserver, *binddn, bindpw);
|
ld = connect_ldap(ipaserver, *binddn, bindpw);
|
||||||
if (!ld) {
|
if (!ld) {
|
||||||
if (has_principal) {
|
if (!quiet)
|
||||||
if (!quiet)
|
fprintf(stderr, _("Incorrect password.\n"));
|
||||||
fprintf(stderr, _("Host is already joined.\n"));
|
rval = 15;
|
||||||
rval = 13;
|
|
||||||
} else {
|
|
||||||
if (!quiet)
|
|
||||||
fprintf(stderr, _("Incorrect password.\n"));
|
|
||||||
rval = 15;
|
|
||||||
}
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,13 +485,19 @@ join_ldap(const char *ipaserver, char *hostname, const char ** binddn, const cha
|
|||||||
valrequest.bv_len = strlen(hostname);
|
valrequest.bv_len = strlen(hostname);
|
||||||
|
|
||||||
if ((rc = ldap_extended_operation_s(ld, JOIN_OID, &valrequest, NULL, NULL, &oidresult, &valresult)) != LDAP_SUCCESS) {
|
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)
|
if (!quiet)
|
||||||
fprintf(stderr, _("principal not found in host entry\n"));
|
fprintf(stderr, _("Enrollment failed. %s\n"), s);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
fprintf(stderr, "ldap_extended_operation_s failed: %s",
|
fprintf(stderr, "ldap_extended_operation_s failed: %s",
|
||||||
ldap_err2string(rc));
|
ldap_err2string(rc));
|
||||||
}
|
}
|
||||||
rval = 18;
|
rval = 13;
|
||||||
goto ldap_done;
|
goto ldap_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,7 +1003,7 @@ join(const char *server, const char *hostname, const char *bindpw, const char *k
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (NULL != subject && !quiet)
|
if (NULL != subject && !quiet && rval == 0)
|
||||||
fprintf(stderr, _("Certificate subject base is: %s\n"), subject);
|
fprintf(stderr, _("Certificate subject base is: %s\n"), subject);
|
||||||
|
|
||||||
free((char *)princ);
|
free((char *)princ);
|
||||||
|
@ -26,6 +26,13 @@ import ldap
|
|||||||
from ldap import LDAPError
|
from ldap import LDAPError
|
||||||
from ipapython.ipautil import run, CalledProcessError
|
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:
|
class IPADiscovery:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -95,8 +102,7 @@ class IPADiscovery:
|
|||||||
domain = domain[p+1:]
|
domain = domain[p+1:]
|
||||||
return (None, None)
|
return (None, None)
|
||||||
|
|
||||||
def search(self, domain = "", server = ""):
|
def search(self, domain = "", server = "", hostname=None):
|
||||||
hostname = ""
|
|
||||||
qname = ""
|
qname = ""
|
||||||
results = []
|
results = []
|
||||||
result = []
|
result = []
|
||||||
@ -108,14 +114,15 @@ class IPADiscovery:
|
|||||||
if not domain: #domain not provided do full DNS discovery
|
if not domain: #domain not provided do full DNS discovery
|
||||||
|
|
||||||
# get the local host name
|
# get the local host name
|
||||||
hostname = socket.getfqdn()
|
|
||||||
if not hostname:
|
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
|
# first, check for an LDAP server for the local domain
|
||||||
p = hostname.find(".")
|
p = hostname.find(".")
|
||||||
if p == -1: #no domain name
|
if p == -1: #no domain name
|
||||||
return -1
|
return NOT_FQDN
|
||||||
domain = hostname[p+1:]
|
domain = hostname[p+1:]
|
||||||
|
|
||||||
# Get the list of domains from /etc/resolv.conf, we'll search
|
# Get the list of domains from /etc/resolv.conf, we'll search
|
||||||
@ -133,14 +140,14 @@ class IPADiscovery:
|
|||||||
self.domain = domain
|
self.domain = domain
|
||||||
break
|
break
|
||||||
if not self.domain: #no ldap server found
|
if not self.domain: #no ldap server found
|
||||||
return -1
|
return NO_LDAP_SERVER
|
||||||
else:
|
else:
|
||||||
logging.debug("[ipadnssearchldap]")
|
logging.debug("[ipadnssearchldap]")
|
||||||
self.server = self.ipadnssearchldap(domain)
|
self.server = self.ipadnssearchldap(domain)
|
||||||
if self.server:
|
if self.server:
|
||||||
self.domain = domain
|
self.domain = domain
|
||||||
else:
|
else:
|
||||||
return -2 #no ldap server found
|
return NO_LDAP_SERVER
|
||||||
|
|
||||||
else: #server forced on us, this means DNS doesn't work :/
|
else: #server forced on us, this means DNS doesn't work :/
|
||||||
|
|
||||||
@ -151,7 +158,7 @@ class IPADiscovery:
|
|||||||
logging.debug("[ipadnssearchkrb]")
|
logging.debug("[ipadnssearchkrb]")
|
||||||
krbret = self.ipadnssearchkrb(self.domain)
|
krbret = self.ipadnssearchkrb(self.domain)
|
||||||
if not server and not krbret[0]:
|
if not server and not krbret[0]:
|
||||||
return -3 # realm for autodiscovery not found
|
return REALM_NOT_FOUND
|
||||||
|
|
||||||
self.realm = krbret[0]
|
self.realm = krbret[0]
|
||||||
self.kdc = krbret[1]
|
self.kdc = krbret[1]
|
||||||
@ -161,7 +168,7 @@ class IPADiscovery:
|
|||||||
ldapret = self.ipacheckldap(self.server, self.realm)
|
ldapret = self.ipacheckldap(self.server, self.realm)
|
||||||
|
|
||||||
if not ldapret:
|
if not ldapret:
|
||||||
return -4 # not an IPA server (or broken config)
|
return NOT_IPA_SERVER
|
||||||
|
|
||||||
self.server = ldapret[0]
|
self.server = ldapret[0]
|
||||||
self.realm = ldapret[1]
|
self.realm = ldapret[1]
|
||||||
@ -169,6 +176,14 @@ class IPADiscovery:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def ipacheckldap(self, thost, trealm):
|
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 = []
|
lret = []
|
||||||
lres = []
|
lres = []
|
||||||
@ -219,7 +234,7 @@ class IPADiscovery:
|
|||||||
linfo = lret[0][1][lattr][0].lower()
|
linfo = lret[0][1][lattr][0].lower()
|
||||||
break
|
break
|
||||||
|
|
||||||
if not linfo:
|
if not linfo or linfo.lower() != 'ipa v2.0':
|
||||||
return []
|
return []
|
||||||
|
|
||||||
#search and return known realms
|
#search and return known realms
|
||||||
@ -323,5 +338,5 @@ class IPADiscovery:
|
|||||||
|
|
||||||
if not kdc:
|
if not kdc:
|
||||||
logging.debug("SRV record for KDC not found! Realm: %s, SRV record: %s" % (realm, qname))
|
logging.debug("SRV record for KDC not found! Realm: %s, SRV record: %s" % (realm, qname))
|
||||||
|
|
||||||
return [realm, kdc]
|
return [realm, kdc]
|
||||||
|
Loading…
Reference in New Issue
Block a user