summaryrefslogtreecommitdiffstats
path: root/ipapython
diff options
context:
space:
mode:
authorMartin Babinsky <mbabinsk@redhat.com>2015-03-16 16:28:54 +0100
committerJan Cholasta <jcholast@redhat.com>2015-04-20 08:27:35 +0000
commit415a5ff372fccee38a799cae37fb170145222107 (patch)
tree661ee7494d1c766ef641b2bb60fd1ef86484eae7 /ipapython
parente4930b3235e5d61d227a7e43d30a8feb7f35664d (diff)
downloadfreeipa-415a5ff372fccee38a799cae37fb170145222107.tar.gz
freeipa-415a5ff372fccee38a799cae37fb170145222107.tar.xz
freeipa-415a5ff372fccee38a799cae37fb170145222107.zip
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>
Diffstat (limited to 'ipapython')
-rw-r--r--ipapython/ipautil.py71
1 files changed, 54 insertions, 17 deletions
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 6a06a8e95..bdbf8da49 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -1185,27 +1185,64 @@ def wait_for_open_socket(socket_name, timeout=0):
else:
raise e
-def kinit_hostprincipal(keytab, ccachedir, principal):
+
+def kinit_keytab(principal, keytab, ccache_name, attempts=1):
+ """
+ Given a ccache_path, keytab file and a principal kinit as that user.
+
+ The optional parameter 'attempts' specifies how many times the credential
+ initialization should be attempted in case of non-responsive KDC.
"""
- Given a ccache directory and a principal kinit as that user.
+ errors_to_retry = {krbV.KRB5KDC_ERR_SVC_UNAVAILABLE,
+ krbV.KRB5_KDC_UNREACH}
+ root_logger.debug("Initializing principal %s using keytab %s"
+ % (principal, keytab))
+ root_logger.debug("using ccache %s" % ccache_name)
+ for attempt in range(1, attempts + 1):
+ 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)
- This blindly overwrites the current CCNAME so if you need to save
- it do so before calling this function.
- Thus far this is used to kinit as the local host.
+def kinit_password(principal, password, ccache_name, armor_ccache_name=None):
"""
- try:
- ccache_file = 'FILE:%s/ccache' % ccachedir
- krbcontext = krbV.default_context()
- ktab = krbV.Keytab(name=keytab, context=krbcontext)
- princ = krbV.Principal(name=principal, context=krbcontext)
- os.environ['KRB5CCNAME'] = ccache_file
- ccache = krbV.CCache(name=ccache_file, context=krbcontext, primary_principal=princ)
- ccache.init(princ)
- ccache.init_creds_keytab(keytab=ktab, principal=princ)
- return ccache_file
- except krbV.Krb5Error, e:
- raise StandardError('Error initializing principal %s in %s: %s' % (principal, keytab, str(e)))
+ 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):
'''