[Freeipa-devel] [PATCHES 0015-0017] consolidation of various Kerberos auth methods in FreeIPA code
Martin Babinsky
mbabinsk at redhat.com
Wed Mar 11 12:38:38 UTC 2015
On 03/11/2015 12:42 PM, Petr Spacek wrote:
> Hello Martin^3,
>
> good work, we are almost there! Please see my nitpicks in-line.
>
> On 9.3.2015 13:06, Martin Babinsky wrote:
>> On 03/06/2015 01:05 PM, Martin Babinsky wrote:
>>> This series of patches for the master/4.1 branch attempts to implement
>>> some of the Rob's and Petr Vobornik's ideas which originated from a
>>> discussion on this list regarding my original patch fixing
>>> https://fedorahosted.org/freeipa/ticket/4808.
>>>
>>> I suppose that these patches are just a first iteration, we may further
>>> discuss if this is the right thing to do.
>>>
>>> Below is a quote from the original discussion just to get the context:
>>>
>>>
>>>
>>
>> The next iteration of patches is attached below. Thanks to jcholast and
>> pvoborni for the comments and insights.
>>
>> --
>> Martin^3 Babinsky
>>
>> freeipa-mbabinsk-0015-2-ipautil-new-functions-kinit_keytab-and-kinit_passwor.patch
>>
>>
>> From 97e4eed332391bab7a12dc593152e369f347fd3c Mon Sep 17 00:00:00 2001
>> From: Martin Babinsky <mbabinsk at redhat.com>
>> Date: Mon, 9 Mar 2015 12:53:10 +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 StandardError.
>>
>> kinit_password wraps kinit auth using password and also supports FAST
>> authentication using httpd armor ccache.
>> ---
>> ipapython/ipautil.py | 60 ++++++++++++++++++++++++++++++++++++++++------------
>> 1 file changed, 46 insertions(+), 14 deletions(-)
>>
>> diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
>> index 4116d974e620341119b56fad3cff1bda48af3bab..4547165ccf24ff6edf5c65e756aa321aa34b9e61 100644
>> --- a/ipapython/ipautil.py
>> +++ b/ipapython/ipautil.py
>> @@ -1175,27 +1175,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
>> + StandardError.
>>
>> 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.
>> """
>> - 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))
>> + for attempt in xrange(attempts):
> I would like to see new code compatible with Python 3. Here I'm not sure what
> is the generic solution for xrange but in this particular case I would
> recommend you to use just range. Attempts variable should have small values so
> the x/range differences do not matter here.
>
>> + try:
>> + krbcontext = krbV.default_context()
>> + ktab = krbV.Keytab(name=keytab, context=krbcontext)
>> + princ = krbV.Principal(name=principal, context=krbcontext)
>> + os.environ['KRB5CCNAME'] = ccache_path
> This is a bit scary, especially when it comes to multi-threaded execution. If
> it is really necessary please add comment that this method is not thread-safe.
>
>> + 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 + 1, attempts))
> What about adding + 1 to range boundaries instead of + 1 here and there?
>
>> + return
>> + except krbV.Krb5Error, e:
> except ... , ... syntax is not going to work in Python 3. Maybe 'as' would be
> better?
>
>> + root_logger.debug("Attempt %d/%d: failed"
>> + % (attempt + 1, attempts))
>> + time.sleep(1)
>> +
>> + root_logger.debug("Maximum number of attempts (%d) reached"
>> + % attempts)
>> + raise StandardError("Error initializing principal %s: %s"
>> + % (principal, str(e)))
>> +
>> +
>> +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
>>
>>
>> freeipa-mbabinsk-0016-2-ipa-client-install-try-to-get-host-TGT-several-times.patch
>>
>>
>> From e438d8a0711b4271d24d7d24e98395503912a1c4 Mon Sep 17 00:00:00 2001
>> From: Martin Babinsky <mbabinsk at redhat.com>
>> Date: Mon, 9 Mar 2015 12:53:57 +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 TGT from KDC 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 | 65 +++++++++++++++++--------------
>> ipa-client/man/ipa-client-install.1 | 5 +++
>> 2 files changed, 41 insertions(+), 29 deletions(-)
>>
>> diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
>> index ccaab5536e83b4b6ac60b81132c3455c0af19ae1..c817f9e86dbaa6a2cca7d1a463f53d491fa7badb 100755
>> --- a/ipa-client/ipa-install/ipa-client-install
>> +++ b/ipa-client/ipa-install/ipa-client-install
>> @@ -91,6 +91,13 @@ 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(
>> + "%s option has invalid value %d" % (opt, value))
> It would be nice if the error message said what is the expected value.
> ("Expected integer in range <1,%s>" % sys.maxint)
>
> BTW is it possible to do this using existing option parser? I would expect
> some generic support for type=uint or something similar.
>
>> +
>> + parser.values.kinit_attempts = value
>> +
>> parser = IPAOptionParser(version=version.VERSION)
>>
>> basic_group = OptionGroup(parser, "basic options")
>> @@ -144,6 +151,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,
>
> It would be good to check lockout numbers in default configuration to make
> sure that replication delay will not lock the principal.
>
>> + 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 +2363,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 +2384,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 +2421,24 @@ 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, e:
>> print_port_conf_info()
>> - root_logger.error("Kerberos authentication failed")
>> - root_logger.info("%s", stdout)
>> + root_logger.error("Kerberos authentication failed: %s"
>> + % str(e))
> Isn't str() redundant? IMHO %s calls str() implicitly.
>
>> 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 StandardError, 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"
>> + % str(e))
> Again str().
>
>> return CLIENT_INSTALL_ERROR
>> else:
>> root_logger.error("Keytab file could not be found: %s"
>> @@ -2501,12 +2508,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 StandardError, e:
>> + print_port_conf_info()
>> + root_logger.error("Failed to obtain host TGT: %s" % str(e))
> str()?
>
>> # 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 +2551,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 StandardError, e:
>> + root_logger.error("Failed to obtain host TGT: %s" % str(e))
> str()? I will not mention it again but please look for it.
>
>> 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..56ed899a25e626b8ae61714f77f3588059fa86f9 100644
>> --- a/ipa-client/man/ipa-client-install.1
>> +++ b/ipa-client/man/ipa-client-install.1
>> @@ -152,6 +152,11 @@ 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
>> +Number of unsuccessful attempts to obtain host TGT that will be performed
>> +before aborting client installation. \fIKINIT_ATTEMPTS\fR should be a number
>> +greater than zero. By default 5 attempts to get TGT are performed.
> It would be nice to add a rationale to the text. Current text is somehow
> confusing for users not familiar with replication and related problems.
>
> My hope is descriptive manual will prevent users from creating cargo-cults
> based on copy&pastings texts they do not understand.
>
>> +.TP
>> \fB\-d\fR, \fB\-\-debug\fR
>> Print debugging information to stdout
>> .TP
>> -- 2.1.0
>>
>>
>> freeipa-mbabinsk-0017-2-Adopted-kinit_keytab-and-kinit_password-for-kerberos.patch
>>
>>
>> From 912113529138e5b1bd8357ae6a17376cb5d32759 Mon Sep 17 00:00:00 2001
>> From: Martin Babinsky <mbabinsk at redhat.com>
>> Date: Mon, 9 Mar 2015 12:54:36 +0100
>> Subject: [PATCH 3/3] Adopted kinit_keytab and kinit_password for kerberos auth
>>
>> ---
>> daemons/dnssec/ipa-dnskeysync-replica | 6 ++-
>> daemons/dnssec/ipa-dnskeysyncd | 2 +-
>> 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 | 9 ++--
>> ipa-client/ipaclient/ipa_certupdate.py | 3 +-
>> ipaserver/rpcserver.py | 49 +++++++++++-----------
>> 9 files changed, 47 insertions(+), 41 deletions(-)
>>
>> diff --git a/daemons/dnssec/ipa-dnskeysync-replica b/daemons/dnssec/ipa-dnskeysync-replica
>> index d04f360e04ee018dcdd1ba9b2ca42b1844617af9..e9cae519202203a10678b7384e5acf748f256427 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, 'ccache')
> BTW I really appreciate this patch set! We finally can use more descriptive
> names like 'ipa-dnskeysync-replica.ccache' which sometimes make debugging easier.
>
>> +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..4e64596c7f8ccd6cff47df4772c875917c71606a 100755
>> --- a/daemons/dnssec/ipa-dnskeysyncd
>> +++ b/daemons/dnssec/ipa-dnskeysyncd
>> @@ -65,7 +65,7 @@ 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)
>> +ipautil.kinit_keytab(KEYTAB_FB, os.path.join(WORKDIR, 'ccache'), PRINCIPAL)
> 'ipa-dnskeysyncd.ccache'?
>
>> # 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..0cf825950338cdce330a15b3ea22150f6e02588a 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, 'ccache')
> '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'),
> 'dogtag-ipa-ca-renew-agent-submit.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
> 'renew_ca_cert.ccache'?
>
>> + 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,
> 'renew_ra_cert.ccache'?
>
>> + 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 7b9e701dead5f50a033a455eb62e30df78cc0249..19197d34ca580062742b3d7363e5dfb2dad0e4de 100755
>> --- a/ipa-client/ipa-install/ipa-client-automount
>> +++ b/ipa-client/ipa-install/ipa-client-automount
>> @@ -425,10 +425,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,
> I'm not sure what is ccache_name here but it should be something descriptive.
>
>> + host_princ)
>> + except StandardError, 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)
> 'ipa_certupdate.ccache'?
>
>>
>> api.Backend.rpcclient.connect()
>> try:
>> diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
>> index d6bc955b9d9910a24eec5df1def579310eb54786..36f16908ac8477d9982bfee613b77576853054eb 100644
>> --- a/ipaserver/rpcserver.py
>> +++ b/ipaserver/rpcserver.py
>> @@ -958,8 +958,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 +967,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 StandardError, 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:
> I know it is not your code but please make sure it will work with non-English
> LANG or LC_MESSAGE.
>
>> + raise PasswordExpired(principal=principal,
>> + message=unicode(e.output))
>> + raise InvalidSessionPassword(principal=principal,
>> + message=unicode(e.output))
>>
>> class change_password(Backend, HTTP_Status):
>
> Hopefully this review is not too annoying :-)
>
Thank you for plenty of suggestions Petr. I will try to update the
patches accordingly.
--
Martin^3 Babinsky
More information about the Freeipa-devel
mailing list