On 03/17/2015 12:09 PM, Petr Spacek wrote:
On 16.3.2015 17:20, Martin Babinsky wrote:
On 03/16/2015 01:35 PM, Jan Cholasta wrote:
Dne 16.3.2015 v 13:30 Martin Babinsky napsal(a):
On 03/16/2015 12:15 PM, Martin Kosek wrote:
On 03/13/2015 05:37 PM, Martin Babinsky wrote:
Attaching the next iteration of patches.

Very good! I hopefully have last two nitpicks :-) See below.

diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 
4116d974e620341119b56fad3cff1bda48af3bab..cd03e9fd17b60b8b7324d0ccd436a10f7556baf0
 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -1175,27 +1175,61 @@ def wait_for_open_socket(socket_name, timeout=0):
              else:
                  raise e

-def kinit_hostprincipal(keytab, ccachedir, principal):
+
+def kinit_keytab(keytab, ccache_path, principal, attempts=1):
      """
-    Given a ccache directory and a principal kinit as that user.
+    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 before giving up and raising
+    StandardError.

      This blindly overwrites the current CCNAME so if you need to save
      it do so before calling this function.

+    This function is also not thread-safe since it modifies environment
+    variables.
+
      Thus far this is used to kinit as the local host.

This note can be deleted because it is used elsewhere too.

      """
-    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)))
+    root_logger.debug("Initializing principal %s using keytab %s"
+                      % (principal, keytab))

I'm sorry for nitpicking but it would be nice to log ccache_file too. Krb5
libs return quite weird errors when CC cache is not accessible so it helps to
have the path at hand.


Attaching updated patches.

--
Martin^3 Babinsky
From 5888e5924c8b6aac30a8a893b9d0045545773ceb Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Mon, 16 Mar 2015 16:28:54 +0100
Subject: [PATCH 1/3] 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.

---
 ipapython/ipautil.py | 62 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 47 insertions(+), 15 deletions(-)

diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 6a06a8e956552597dfd48128b60a1dd6a4cc92f6..212f39d7e77eaa1c9655e06b2758e173e0bd9a42 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -1185,27 +1185,59 @@ def wait_for_open_socket(socket_name, timeout=0):
             else:
                 raise e
 
-def kinit_hostprincipal(keytab, ccachedir, principal):
+
+def kinit_keytab(keytab, ccache_path, principal, attempts=1):
     """
-    Given a ccache directory and a principal kinit as that user.
+    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 before giving up and raising Krb5Error.
 
     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.
+    This function is also not thread-safe since it modifies environment
+    variables.
     """
-    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)))
+    root_logger.debug("Initializing principal %s using keytab %s"
+                      % (principal, keytab))
+    root_logger.debug("using ccache path %s" % ccache_path)
+    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)
+            os.environ['KRB5CCNAME'] = ccache_path
+            ccache = krbV.CCache(name=ccache_path, 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:
+            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
+            time.sleep(1)
+
+
+def kinit_password(principal, password, env={}, armor_ccache=""):
+    """perform interactive kinit as principal using password. Additional
+    enviroment variables can be specified using env. If using FAST for
+    web-based authentication, use armor_ccache to specify http service ccache.
+    """
+    root_logger.debug("Initializing principal %s using password" % principal)
+    args = [paths.KINIT, principal]
+    if armor_ccache:
+        root_logger.debug("Using armor ccache %s for FAST webauth"
+                          % armor_ccache)
+        args.extend(['-T', armor_ccache])
+    run(args, env=env, stdin=password)
+
 
 def dn_attribute_property(private_name):
     '''
-- 
2.1.0

From 8e9f72498fabde79bd9ab236b09d1c226ff363ab Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Mon, 16 Mar 2015 16:30:55 +0100
Subject: [PATCH 2/3] ipa-client-install: try to get host TGT several times
 before giving up

New option '--kinit-attempts' enables the host to make multiple attempts to
obtain host TGT from master before giving up and aborting client installation.

In addition, all kinit attempts were replaced by calls to
'ipautil.kinit_keytab' and 'ipautil.kinit_password'.

https://fedorahosted.org/freeipa/ticket/4808
---
 ipa-client/ipa-install/ipa-client-install | 66 +++++++++++++++++--------------
 ipa-client/man/ipa-client-install.1       |  9 +++++
 2 files changed, 46 insertions(+), 29 deletions(-)

diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index ccaab5536e83b4b6ac60b81132c3455c0af19ae1..5ff668c2bad882fcb38fa3c9a96b3583548a751d 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -31,6 +31,7 @@ try:
     from ConfigParser import RawConfigParser
     from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError
     import shutil
+    from krbV import Krb5Error
 
     import nss.nss as nss
     import SSSDConfig
@@ -91,6 +92,14 @@ def parse_options():
 
         parser.values.ca_cert_file = value
 
+    def validate_kinit_attempts_option(option, opt, value, parser):
+        if value < 1 or value > sys.maxint:
+            raise OptionValueError(
+                "Option %s expects an integer in range <1,%d>"
+                % (opt, sys.maxint))
+
+        parser.values.kinit_attempts = value
+
     parser = IPAOptionParser(version=version.VERSION)
 
     basic_group = OptionGroup(parser, "basic options")
@@ -144,6 +153,11 @@ def parse_options():
                       help="do not modify the nsswitch.conf and PAM configuration")
     basic_group.add_option("-f", "--force", dest="force", action="store_true",
                       default=False, help="force setting of LDAP/Kerberos conf")
+    basic_group.add_option('--kinit-attempts', dest='kinit_attempts',
+                           action='callback', type='int', default=5,
+                           callback=validate_kinit_attempts_option,
+                           help=("number of attempts to obtain host TGT"
+                                 " (defaults to %default)."))
     basic_group.add_option("-d", "--debug", dest="debug", action="store_true",
                       default=False, help="print debugging information")
     basic_group.add_option("-U", "--unattended", dest="unattended",
@@ -2351,6 +2365,7 @@ def install(options, env, fstore, statestore):
             root_logger.debug(
                 "will use principal provided as option: %s", options.principal)
 
+    host_principal = 'host/%s@%s' % (hostname, cli_realm)
     if not options.on_master:
         nolog = tuple()
         # First test out the kerberos configuration
@@ -2371,7 +2386,6 @@ def install(options, env, fstore, statestore):
             env['KRB5_CONFIG'] = krb_name
             (ccache_fd, ccache_name) = tempfile.mkstemp()
             os.close(ccache_fd)
-            env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name
             join_args = [paths.SBIN_IPA_JOIN,
                          "-s", cli_server[0],
                          "-b", str(realm_to_suffix(cli_realm)),
@@ -2409,29 +2423,23 @@ def install(options, env, fstore, statestore):
                         else:
                             stdin = sys.stdin.readline()
 
-                (stderr, stdout, returncode) = run(["kinit", principal],
-                                                    raiseonerr=False,
-                                                    stdin=stdin,
-                                                    env=env)
-                if returncode != 0:
+                try:
+                    ipautil.kinit_password(principal, stdin, env)
+                except CalledProcessError as e:
                     print_port_conf_info()
-                    root_logger.error("Kerberos authentication failed")
-                    root_logger.info("%s", stdout)
+                    root_logger.error("Kerberos authentication failed: %s" % e)
                     return CLIENT_INSTALL_ERROR
             elif options.keytab:
                 join_args.append("-f")
                 if os.path.exists(options.keytab):
-                    (stderr, stdout, returncode) = run(
-                        [paths.KINIT,'-k', '-t', options.keytab,
-                            'host/%s@%s' % (hostname, cli_realm)],
-                        env=env,
-                        raiseonerr=False)
-
-                    if returncode != 0:
+                    try:
+                        ipautil.kinit_keytab(options.keytab, ccache_name,
+                                             host_principal,
+                                             attempts=options.kinit_attempts)
+                    except Krb5Error as e:
                         print_port_conf_info()
-                        root_logger.error("Kerberos authentication failed "
-                                          "using keytab: %s", options.keytab)
-                        root_logger.info("%s", stdout)
+                        root_logger.error("Kerberos authentication failed: %s"
+                                          % e)
                         return CLIENT_INSTALL_ERROR
                 else:
                     root_logger.error("Keytab file could not be found: %s"
@@ -2501,12 +2509,13 @@ def install(options, env, fstore, statestore):
             # only the KDC we're installing under is contacted.
             # Other KDCs might not have replicated the principal yet.
             # Once we have the TGT, it's usable on any server.
-            env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = CCACHE_FILE
             try:
-                run([paths.KINIT, '-k', '-t', paths.KRB5_KEYTAB,
-                        'host/%s@%s' % (hostname, cli_realm)], env=env)
-            except CalledProcessError, e:
-                root_logger.error("Failed to obtain host TGT.")
+                ipautil.kinit_keytab(paths.KRB5_KEYTAB, CCACHE_FILE,
+                                     host_principal,
+                                     attempts=options.kinit_attempts)
+            except Krb5Error as e:
+                print_port_conf_info()
+                root_logger.error("Failed to obtain host TGT: %s" % e)
                 # failure to get ticket makes it impossible to login and bind
                 # from sssd to LDAP, abort installation and rollback changes
                 return CLIENT_INSTALL_ERROR
@@ -2543,16 +2552,15 @@ def install(options, env, fstore, statestore):
             return CLIENT_INSTALL_ERROR
         root_logger.info("Configured /etc/sssd/sssd.conf")
 
-    host_principal = 'host/%s@%s' % (hostname, cli_realm)
     if options.on_master:
         # If on master assume kerberos is already configured properly.
         # Get the host TGT.
-        os.environ['KRB5CCNAME'] = CCACHE_FILE
         try:
-            run([paths.KINIT, '-k', '-t', paths.KRB5_KEYTAB,
-                    host_principal])
-        except CalledProcessError, e:
-            root_logger.error("Failed to obtain host TGT.")
+            ipautil.kinit_keytab(paths.KRB5_KEYTAB, CCACHE_FILE,
+                                 host_principal,
+                                 attempts=options.kinit_attempts)
+        except Krb5Error as e:
+            root_logger.error("Failed to obtain host TGT: %s" % e)
             return CLIENT_INSTALL_ERROR
     else:
         # Configure krb5.conf
diff --git a/ipa-client/man/ipa-client-install.1 b/ipa-client/man/ipa-client-install.1
index 726a6c133132dd2e3ba2fde43d8a2ec0549bfcef..050a46905d67df98f7fad5bda1a689095eb543fa 100644
--- a/ipa-client/man/ipa-client-install.1
+++ b/ipa-client/man/ipa-client-install.1
@@ -152,6 +152,15 @@ Do not use Authconfig to modify the nsswitch.conf and PAM configuration.
 \fB\-f\fR, \fB\-\-force\fR
 Force the settings even if errors occur
 .TP
+\fB\-\-kinit\-attempts\fR=\fIKINIT_ATTEMPTS\fR
+Attempt to get Kerberos ticket for the host principal \fIKINIT_ATTEMPTS\fR
+times before giving up and aborting client installation. Useful when enrolling
+clients in heavy-load environments where KDCs may fail to respond to all
+requests at once. Default value is 5, which is less that the maximum number of
+failed auth attempts (6) before locking out principal in default FreeIPA group
+password policy. Make sure to update the policy accordingly when using higher
+values of fIKINIT_ATTEMPTS\fR.
+.TP
 \fB\-d\fR, \fB\-\-debug\fR
 Print debugging information to stdout
 .TP
-- 
2.1.0

From 2d7c04afd5c611c0d8a1ecabe1ec7f248cdb93b8 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Mon, 16 Mar 2015 16:43:10 +0100
Subject: [PATCH 3/3] Adopted kinit_keytab and kinit_password for kerberos auth

Calls to ipautil.run using kinit were replaced with calls
kinit_keytab/kinit_password functions implemented in the PATCH 0015.
---
 daemons/dnssec/ipa-dnskeysync-replica              |  6 ++-
 daemons/dnssec/ipa-dnskeysyncd                     |  3 +-
 daemons/dnssec/ipa-ods-exporter                    |  5 ++-
 .../certmonger/dogtag-ipa-ca-renew-agent-submit    |  3 +-
 install/restart_scripts/renew_ca_cert              |  7 +--
 install/restart_scripts/renew_ra_cert              |  4 +-
 ipa-client/ipa-install/ipa-client-automount        | 10 +++--
 ipa-client/ipaclient/ipa_certupdate.py             |  3 +-
 ipaserver/rpcserver.py                             | 50 +++++++++++-----------
 9 files changed, 50 insertions(+), 41 deletions(-)

diff --git a/daemons/dnssec/ipa-dnskeysync-replica b/daemons/dnssec/ipa-dnskeysync-replica
index d04f360e04ee018dcdd1ba9b2ca42b1844617af9..f22be9b09978ac292ea584d4c7081020b2097dda 100755
--- a/daemons/dnssec/ipa-dnskeysync-replica
+++ b/daemons/dnssec/ipa-dnskeysync-replica
@@ -139,14 +139,16 @@ log.setLevel(level=logging.DEBUG)
 # Kerberos initialization
 PRINCIPAL = str('%s/%s' % (DAEMONNAME, ipalib.api.env.host))
 log.debug('Kerberos principal: %s', PRINCIPAL)
-ipautil.kinit_hostprincipal(paths.IPA_DNSKEYSYNCD_KEYTAB, WORKDIR, PRINCIPAL)
+ccache_filename = os.path.join(WORKDIR, 'ipa-dnskeysync-replica.ccache')
+ipautil.kinit_keytab(paths.IPA_DNSKEYSYNCD_KEYTAB, ccache_filename,
+                     PRINCIPAL)
 log.debug('Got TGT')
 
 # LDAP initialization
 ldap = ipalib.api.Backend[ldap2]
 # fixme
 log.debug('Connecting to LDAP')
-ldap.connect(ccache="%s/ccache" % WORKDIR)
+ldap.connect(ccache=ccache_filename)
 log.debug('Connected')
 
 
diff --git a/daemons/dnssec/ipa-dnskeysyncd b/daemons/dnssec/ipa-dnskeysyncd
index 54a08a1e6307e89b3f52e78bddbe28cda8ac1345..cf3ecc5a5f7ac40b7f52e1dfc42367130dac926e 100755
--- a/daemons/dnssec/ipa-dnskeysyncd
+++ b/daemons/dnssec/ipa-dnskeysyncd
@@ -65,7 +65,8 @@ log = root_logger
 # Kerberos initialization
 PRINCIPAL = str('%s/%s' % (DAEMONNAME, api.env.host))
 log.debug('Kerberos principal: %s', PRINCIPAL)
-ipautil.kinit_hostprincipal(KEYTAB_FB, WORKDIR, PRINCIPAL)
+ccache_name = os.path.join(WORKDIR, 'ipa-dnskeysyncd.ccache')
+ipautil.kinit_keytab(KEYTAB_FB, ccache_name, PRINCIPAL)
 
 # LDAP initialization
 basedn = DN(api.env.container_dns, api.env.basedn)
diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter
index dc1851d3a34bb09c1a87c86d101b11afe35e49fe..4a6d387392146ea2cb48e6582bac513a36965d77 100755
--- a/daemons/dnssec/ipa-ods-exporter
+++ b/daemons/dnssec/ipa-ods-exporter
@@ -399,7 +399,8 @@ ipalib.api.finalize()
 # Kerberos initialization
 PRINCIPAL = str('%s/%s' % (DAEMONNAME, ipalib.api.env.host))
 log.debug('Kerberos principal: %s', PRINCIPAL)
-ipautil.kinit_hostprincipal(paths.IPA_ODS_EXPORTER_KEYTAB, WORKDIR, PRINCIPAL)
+ccache_name = os.path.join(WORKDIR, 'ipa-ods-exporter.ccache')
+ipautil.kinit_keytab(paths.IPA_ODS_EXPORTER_KEYTAB, ccache_name, PRINCIPAL)
 log.debug('Got TGT')
 
 # LDAP initialization
@@ -407,7 +408,7 @@ dns_dn = DN(ipalib.api.env.container_dns, ipalib.api.env.basedn)
 ldap = ipalib.api.Backend[ldap2]
 # fixme
 log.debug('Connecting to LDAP')
-ldap.connect(ccache="%s/ccache" % WORKDIR)
+ldap.connect(ccache=ccache_name)
 log.debug('Connected')
 
 
diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
index 7b91fc61148912c77d0ae962b3847d73e8d0720e..13d2c2a912d2fcf84053d36da5e07fc834f9cf25 100755
--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
@@ -440,7 +440,8 @@ def main():
     certs.renewal_lock.acquire()
     try:
         principal = str('host/%s@%s' % (api.env.host, api.env.realm))
-        ipautil.kinit_hostprincipal(paths.KRB5_KEYTAB, tmpdir, principal)
+        ipautil.kinit_keytab(paths.KRB5_KEYTAB, os.path.join(tmpdir, 'ccache'),
+                             principal)
 
         profile = os.environ.get('CERTMONGER_CA_PROFILE')
         if profile:
diff --git a/install/restart_scripts/renew_ca_cert b/install/restart_scripts/renew_ca_cert
index c7bd5d74c5b4659b3ad66d630653ff6419868d99..67156122bb75f00a4c3f612697092e5bab3723fb 100644
--- a/install/restart_scripts/renew_ca_cert
+++ b/install/restart_scripts/renew_ca_cert
@@ -73,8 +73,9 @@ def _main():
     tmpdir = tempfile.mkdtemp(prefix="tmp-")
     try:
         principal = str('host/%s@%s' % (api.env.host, api.env.realm))
-        ccache = ipautil.kinit_hostprincipal(paths.KRB5_KEYTAB, tmpdir,
-                                             principal)
+        ccache_filename = '%s/ccache' % tmpdir
+        ipautil.kinit_keytab(paths.KRB5_KEYTAB, ccache_filename,
+                             principal)
 
         ca = cainstance.CAInstance(host_name=api.env.host, ldapi=False)
         ca.update_cert_config(nickname, cert, configured_constants)
@@ -139,7 +140,7 @@ def _main():
             conn = None
             try:
                 conn = ldap2(shared_instance=False, ldap_uri=api.env.ldap_uri)
-                conn.connect(ccache=ccache)
+                conn.connect(ccache=ccache_filename)
             except Exception, e:
                 syslog.syslog(
                     syslog.LOG_ERR, "Failed to connect to LDAP: %s" % e)
diff --git a/install/restart_scripts/renew_ra_cert b/install/restart_scripts/renew_ra_cert
index 7dae3562380e919b2cc5f53825820291fc93fdc5..6276de78e4528dc1caa39be6628094a9d00e5988 100644
--- a/install/restart_scripts/renew_ra_cert
+++ b/install/restart_scripts/renew_ra_cert
@@ -42,8 +42,8 @@ def _main():
     tmpdir = tempfile.mkdtemp(prefix="tmp-")
     try:
         principal = str('host/%s@%s' % (api.env.host, api.env.realm))
-        ccache = ipautil.kinit_hostprincipal(paths.KRB5_KEYTAB, tmpdir,
-                                             principal)
+        ipautil.kinit_keytab(paths.KRB5_KEYTAB, '%s/ccache' % tmpdir,
+                             principal)
 
         ca = cainstance.CAInstance(host_name=api.env.host, ldapi=False)
         if ca.is_renewal_master():
diff --git a/ipa-client/ipa-install/ipa-client-automount b/ipa-client/ipa-install/ipa-client-automount
index ca56f97832159c55cb7010db1b406b52c206462f..0edd768f437c709a553094a361c79b5c317ef8b6 100755
--- a/ipa-client/ipa-install/ipa-client-automount
+++ b/ipa-client/ipa-install/ipa-client-automount
@@ -26,6 +26,7 @@ import os
 import urlparse
 import time
 import tempfile
+from krbV import Krb5Error
 
 import SSSDConfig
 
@@ -431,10 +432,11 @@ def main():
     os.close(ccache_fd)
     try:
         try:
-            os.environ['KRB5CCNAME'] = ccache_name
-            ipautil.run([paths.KINIT, '-k', '-t', paths.KRB5_KEYTAB, 'host/%s@%s' % (api.env.host, api.env.realm)])
-        except ipautil.CalledProcessError, e:
-            sys.exit("Failed to obtain host TGT.")
+            host_princ = str('host/%s@%s' % (api.env.host, api.env.realm))
+            ipautil.kinit_keytab(paths.KRB5_KEYTAB, ccache_name,
+                                 host_princ)
+        except Krb5Error as e:
+            sys.exit("Failed to obtain host TGT: %s" % e)
         # Now we have a TGT, connect to IPA
         try:
             api.Backend.rpcclient.connect()
diff --git a/ipa-client/ipaclient/ipa_certupdate.py b/ipa-client/ipaclient/ipa_certupdate.py
index 031a34c3a54a02d43978eedcb794678a1550702b..d6f7bbb3daff3ae4dced5d69f83a0516003235ab 100644
--- a/ipa-client/ipaclient/ipa_certupdate.py
+++ b/ipa-client/ipaclient/ipa_certupdate.py
@@ -57,7 +57,8 @@ class CertUpdate(admintool.AdminTool):
         tmpdir = tempfile.mkdtemp(prefix="tmp-")
         try:
             principal = str('host/%s@%s' % (api.env.host, api.env.realm))
-            ipautil.kinit_hostprincipal(paths.KRB5_KEYTAB, tmpdir, principal)
+            ipautil.kinit_keytab(paths.KRB5_KEYTAB,
+                                 os.path.join(tmpdir, 'ccache'), principal)
 
             api.Backend.rpcclient.connect()
             try:
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index d6bc955b9d9910a24eec5df1def579310eb54786..6505d8a2fef133dfdb4e8a69d9a2d1f18445151e 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -30,6 +30,7 @@ import datetime
 import urlparse
 import json
 import traceback
+from krbV import Krb5Error
 
 import ldap.controls
 from pyasn1.type import univ, namedtype
@@ -958,8 +959,8 @@ class login_password(Backend, KerberosSession, HTTP_Status):
 
     def kinit(self, user, realm, password, ccache_name):
         # get http service ccache as an armor for FAST to enable OTP authentication
-        armor_principal = krb5_format_service_principal_name(
-            'HTTP', self.api.env.host, realm)
+        armor_principal = str(krb5_format_service_principal_name(
+            'HTTP', self.api.env.host, realm))
         keytab = paths.IPA_KEYTAB
         armor_name = "%sA_%s" % (krbccache_prefix, user)
         armor_path = os.path.join(krbccache_dir, armor_name)
@@ -967,34 +968,33 @@ class login_password(Backend, KerberosSession, HTTP_Status):
         self.debug('Obtaining armor ccache: principal=%s keytab=%s ccache=%s',
                    armor_principal, keytab, armor_path)
 
-        (stdout, stderr, returncode) = ipautil.run(
-            [paths.KINIT, '-kt', keytab, armor_principal],
-            env={'KRB5CCNAME': armor_path}, raiseonerr=False)
-
-        if returncode != 0:
-            raise CCacheError()
+        try:
+            ipautil.kinit_keytab(paths.IPA_KEYTAB, armor_path,
+                                 armor_principal)
+        except Krb5Error as e:
+            raise CCacheError(str(e))
 
         # Format the user as a kerberos principal
         principal = krb5_format_principal_name(user, realm)
 
-        (stdout, stderr, returncode) = ipautil.run(
-            [paths.KINIT, principal, '-T', armor_path],
-            env={'KRB5CCNAME': ccache_name, 'LC_ALL': 'C'},
-            stdin=password, raiseonerr=False)
+        try:
+            ipautil.kinit_password(principal, password,
+                                   env={'KRB5CCNAME': ccache_name,
+                                        'LC_ALL': 'C'},
+                                   armor_ccache=armor_path)
 
-        self.debug('kinit: principal=%s returncode=%s, stderr="%s"',
-                   principal, returncode, stderr)
-
-        self.debug('Cleanup the armor ccache')
-        ipautil.run(
-            [paths.KDESTROY, '-A', '-c', armor_path],
-            env={'KRB5CCNAME': armor_path},
-            raiseonerr=False)
-
-        if returncode != 0:
-            if stderr.strip() == 'kinit: Cannot read password while getting initial credentials':
-                raise PasswordExpired(principal=principal, message=unicode(stderr))
-            raise InvalidSessionPassword(principal=principal, message=unicode(stderr))
+            self.debug('Cleanup the armor ccache')
+            ipautil.run(
+                [paths.KDESTROY, '-A', '-c', armor_path],
+                env={'KRB5CCNAME': armor_path},
+                raiseonerr=False)
+        except ipautil.CalledProcessError, e:
+            if ('kinit: Cannot read password while '
+                    'getting initial credentials') in e.output:
+                raise PasswordExpired(principal=principal,
+                                      message=unicode(e.output))
+            raise InvalidSessionPassword(principal=principal,
+                                         message=unicode(e.output))
 
 class change_password(Backend, HTTP_Status):
 
-- 
2.1.0

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to