ipautil: new functions kinit_keytab and kinit_password

kinit_keytab replaces kinit_hostprincipal and performs Kerberos auth using
keytab file. Function is also able to repeat authentication multiple times
before giving up and raising Krb5Error.

kinit_password wraps kinit auth using password and also supports FAST
authentication using httpd armor ccache.

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Reviewed-By: Simo Sorce <ssorce@redhat.com>
Reviewed-By: Petr Spacek <pspacek@redhat.com>
This commit is contained in:
Martin Babinsky
2015-03-16 16:28:54 +01:00
committed by Jan Cholasta
parent e4930b3235
commit 415a5ff372

View File

@@ -1185,27 +1185,64 @@ def wait_for_open_socket(socket_name, timeout=0):
else: else:
raise e raise e
def kinit_hostprincipal(keytab, ccachedir, principal):
"""
Given a ccache directory and a principal kinit as that user.
This blindly overwrites the current CCNAME so if you need to save def kinit_keytab(principal, keytab, ccache_name, attempts=1):
it do so before calling this function.
Thus far this is used to kinit as the local host.
""" """
try: Given a ccache_path, keytab file and a principal kinit as that user.
ccache_file = 'FILE:%s/ccache' % ccachedir
krbcontext = krbV.default_context() The optional parameter 'attempts' specifies how many times the credential
ktab = krbV.Keytab(name=keytab, context=krbcontext) initialization should be attempted in case of non-responsive KDC.
princ = krbV.Principal(name=principal, context=krbcontext) """
os.environ['KRB5CCNAME'] = ccache_file errors_to_retry = {krbV.KRB5KDC_ERR_SVC_UNAVAILABLE,
ccache = krbV.CCache(name=ccache_file, context=krbcontext, primary_principal=princ) krbV.KRB5_KDC_UNREACH}
ccache.init(princ) root_logger.debug("Initializing principal %s using keytab %s"
ccache.init_creds_keytab(keytab=ktab, principal=princ) % (principal, keytab))
return ccache_file root_logger.debug("using ccache %s" % ccache_name)
except krbV.Krb5Error, e: for attempt in range(1, attempts + 1):
raise StandardError('Error initializing principal %s in %s: %s' % (principal, keytab, str(e))) try:
krbcontext = krbV.default_context()
ktab = krbV.Keytab(name=keytab, context=krbcontext)
princ = krbV.Principal(name=principal, context=krbcontext)
ccache = krbV.CCache(name=ccache_name, context=krbcontext,
primary_principal=princ)
ccache.init(princ)
ccache.init_creds_keytab(keytab=ktab, principal=princ)
root_logger.debug("Attempt %d/%d: success"
% (attempt, attempts))
return
except krbV.Krb5Error as e:
if e.args[0] not in errors_to_retry:
raise
root_logger.debug("Attempt %d/%d: failed: %s"
% (attempt, attempts, e))
if attempt == attempts:
root_logger.debug("Maximum number of attempts (%d) reached"
% attempts)
raise
root_logger.debug("Waiting 5 seconds before next retry")
time.sleep(5)
def kinit_password(principal, password, ccache_name, armor_ccache_name=None):
"""
perform interactive kinit as principal using password. If using FAST for
web-based authentication, use armor_ccache_path to specify http service
ccache.
"""
root_logger.debug("Initializing principal %s using password" % principal)
args = [paths.KINIT, principal, '-c', ccache_name]
if armor_ccache_name is not None:
root_logger.debug("Using armor ccache %s for FAST webauth"
% armor_ccache_name)
args.extend(['-T', armor_ccache_name])
# this workaround enables us to capture stderr and put it
# into the raised exception in case of unsuccessful authentication
(stdout, stderr, retcode) = run(args, stdin=password, env={'LC_ALL': 'C'},
raiseonerr=False)
if retcode:
raise RuntimeError(stderr)
def dn_attribute_property(private_name): def dn_attribute_property(private_name):
''' '''