On 2015-08-03 09:25, Jan Cholasta wrote:
Dne 31.7.2015 v 20:20 Simo Sorce napsal(a):
On Fri, 2015-07-31 at 16:41 +0200, Michael Šimáček wrote:
On 2015-07-31 07:52, Jan Cholasta wrote:
Hi Michael,

Dne 29.7.2015 v 10:09 Michael Šimáček napsal(a):
Hi,

this is the first attempt to port FreeIPA from deprecated
python3-incompatible python-krbV library to python-gssapi. The patch
depends on python-kerberos->python-gssapi patch [1] to apply cleanly,
but the overlap is small, so I think it can be at least partially
reviewed without it.

Comments:
I removed Backend.krb and KRB5_CCache classes as they were wrappers
around krbV classes. I added few utility functions to krb_utils module
that perform part of its functionality (no need for classes, because
gssapi acquire calls don't pass any context objects, they wouldn't
have
any state).

I merged the two different kinit_keytab functions.

GSSAPI doesn't provide any method (that I'm aware of) to get default
ccache name. In most cases this is not needed as we can simply not
pass
any name and it will use the default. The ldap plugin had to be
adjusted
for this - the connect method now takes new use_gssapi argument, which
can turn on gssapi support without the need to supply explicit ccache
name. The only place where the ccache name is really needed is the
test
server, where I use system klist command to obtain it.

I would prefer if the semantics were the same as in IPAdmin, i.e.
GSSAPI
is used by default if bind password is not specified, see
IPAdmin.do_bind() in ipapython.ipaldap.

Just to clarify, the current flow in ldap module is:
if ccache: # I added "or use_gssapi" here in this patch
      gssapi_bind
elif autobind:
      external_bind
else:
      simple_bind

I had to make this change as well for my replica promotion code, and
incidentally used the same indicator "use_gssapi".

and you would like it to be changed into:
if bind_pw:
      simple_bind
elif autobind:
      external_bind
else:
      gssapi_bind

Is that correct?

Actually this is what IPAdmin does:

     def do_bind(self, dm_password="", autobind=AUTOBIND_AUTO,
timeout=DEFAULT_TIMEOUT):
         if dm_password:
             self.do_simple_bind(bindpw=dm_password, timeout=timeout)
             return
         if autobind != AUTOBIND_DISABLED and os.getegid() == 0 and
self.ldapi:
             try:
                 # autobind
                 pw_name = pwd.getpwuid(os.geteuid()).pw_name
                 self.do_external_bind(pw_name, timeout=timeout)
                 return
             except errors.NotFound, e:
                 if autobind == AUTOBIND_ENABLED:
                     # autobind was required and failed, raise
                     # exception that it failed
                     raise

         #fall back
         self.do_sasl_gssapi_bind(timeout=timeout)


I think this is what Jan wanted, but I am wondering if it is the right
thing to do. In ipa we have basically 2 possible default approaches.
One is to use GSSAPI, and one is to use LDAPI with external bind.

The latter makes sense mostly only when running as root, so I am
wondering, should the default change depending on whether we are root
and we are connecting to the local LDAP server ?

If this is a sensible option it means we have to preserver use_gssapi as
we may need to force use of gssapi in some case even when we are root
and connectiong to the local server (for example to test that the local
ccache can successfully be used).

Jan,
what do you think ?

I think GSSAPI should be the default and EXTERNAL should be opt-in, like
in IPAdmin, see above.




It's also not possible to directly get default realm name, what I
do is
importing nonexistent name, cannonicalizing it and extracting the
realm
from it. Which should work but is ugly. It would be better if we could
modify the places that use it to not need it at all, but it's mostly
used in ldap code and I don't understand that part of FreeIPA.
Alternative would be parsing /etc/krb.conf.

You should use api.env.realm where possible. I think this should be
most
of the places where default realm is currently used, if not all of
them.

That would be great if all the usages could be replaced. How can I
determine where api.env.realm can be used? In particular, I'm unsure
about ipapython/config.py/__discover_config and
ipaserver/plugins/join.py.

I would just remove the code from __discover_config. It is used to get
realm name in case it is not configured in /etc/ipa/default.conf, but it
is called only from ipa-compat-manage and ipa-nis-manage, which can be
run only on IPA server, and IPA server won't work if realm is not
configured.

As for join.py, you can just return api.env.realm in get_realm().


try:
    realm = api.env.realm
except:
    realm = dirty gssapi trick ?

Please don't, you should always be able to choose the correct one
instead of guessing.


Attaching new revision of the patch. Changes from the previous:
- ldap2's connect now chooses the bind type same way as in ipaldap
- get_default_realm usages replaced by api.env.realm
- fixed missing third kinit attempt in trust-fetch-domains
- removed rewrapping gssapi errors to ccache errors in krb_utils
- updated some parts of exception handling

Michael
From a553ca5ffff96e0942acd3bd3220564d7a0a794c Mon Sep 17 00:00:00 2001
From: Michael Simacek <msima...@redhat.com>
Date: Mon, 20 Jul 2015 16:04:07 +0200
Subject: [PATCH] Port from python-krbV to python-gssapi

python-krbV library is deprecated and doesn't work with python 3. Replacing all
it's usages with python-gssapi.

- Removed Backend.krb and KRB5_CCache classes
  They were wrappers around krbV classes that cannot really work without them
- Added few utility functions for querying GSSAPI credentials
  in krb_utils module. They provide replacements for KRB5_CCache.
- Merged two kinit_keytab functions
- Changed ldap plugin connection defaults to match ipaldap
- Unified getting default realm
  Using api.env.realm instead of krbV call
---
 BUILD.txt                                         |   2 +-
 doc/examples/python-api.py                        |   4 +-
 freeipa.spec.in                                   |   7 +-
 install/oddjob/com.redhat.idm.trust-fetch-domains |  75 ++---
 install/tools/ipa-adtrust-install                 |  16 +-
 install/tools/ipa-csreplica-manage                |   5 +-
 install/tools/ipa-replica-manage                  |   9 +-
 ipa-client/ipa-client.spec.in                     |   2 +-
 ipa-client/ipa-install/ipa-client-automount       |   4 +-
 ipa-client/ipa-install/ipa-client-install         |   8 +-
 ipalib/krb_utils.py                               | 337 +++++-----------------
 ipalib/plugins/kerberos.py                        | 125 --------
 ipalib/plugins/passwd.py                          |   6 +-
 ipalib/plugins/vault.py                           |   7 +-
 ipalib/rpc.py                                     |   9 +-
 ipalib/util.py                                    |  12 -
 ipapython/config.py                               |  11 -
 ipapython/ipautil.py                              |  28 +-
 ipaserver/install/ipa_cacert_manage.py            |   7 +-
 ipaserver/install/ipa_ldap_updater.py             |   4 +-
 ipaserver/install/ipa_otptoken_import.py          |   7 +-
 ipaserver/install/ipa_winsync_migrate.py          |   8 +-
 ipaserver/install/ldapupdate.py                   |  10 +-
 ipaserver/install/schemaupdate.py                 |   4 +-
 ipaserver/install/server/upgrade.py               |   4 +-
 ipaserver/plugins/join.py                         |  13 +-
 ipaserver/plugins/ldap2.py                        |  60 ++--
 ipaserver/rpcserver.py                            |  25 +-
 ipatests/test_cmdline/cmdline.py                  |   5 +-
 ipatests/test_cmdline/test_ipagetkeytab.py        |  23 +-
 ipatests/test_xmlrpc/test_dns_plugin.py           |   3 +-
 ipatests/test_xmlrpc/test_netgroup_plugin.py      |   6 +-
 ipatests/test_xmlrpc/test_permission_plugin.py    |   3 +-
 lite-server.py                                    |  16 +-
 make-lint                                         |   4 +-
 35 files changed, 235 insertions(+), 634 deletions(-)
 delete mode 100644 ipalib/plugins/kerberos.py

diff --git a/BUILD.txt b/BUILD.txt
index 53012b14d05673d4fbc4d0567e877348d5e78444..4507fa357375edc09377368ab3d1eb1c48994a61 100644
--- a/BUILD.txt
+++ b/BUILD.txt
@@ -20,7 +20,7 @@ systemd-units samba-devel samba-python libwbclient-devel libtalloc-devel \
 libtevent-devel nspr-devel nss-devel openssl-devel openldap-devel krb5-devel \
 krb5-workstation libuuid-devel libcurl-devel xmlrpc-c-devel popt-devel \
 autoconf automake m4 libtool gettext python-devel python-ldap \
-python-setuptools python-krbV python-nss python-netaddr python-gssapi \
+python-setuptools python-nss python-netaddr python-gssapi \
 python-rhsm pyOpenSSL pylint python-polib libipa_hbac-python python-memcached \
 sssd python-lxml python-pyasn1 python-qrcode-core python-dns m2crypto \
 check libsss_idmap-devel libsss_nss_idmap-devel java-headless rhino \
diff --git a/doc/examples/python-api.py b/doc/examples/python-api.py
index 805925f262774edca20fd0f31eda214b83a24fc9..215bb915370ffaac9fb64747a42bb2422b69a6e0 100755
--- a/doc/examples/python-api.py
+++ b/doc/examples/python-api.py
@@ -37,9 +37,7 @@ api.finalize()
 # Backend.ldap.connect(), otherwise Backend.rpcclient.connect().
 
 if api.env.in_server:
-    api.Backend.ldap2.connect(
-        ccache=api.Backend.krb.default_ccname()
-     )
+    api.Backend.ldap2.connect()
 else:
     api.Backend.rpcclient.connect()
 
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 57d3d26e94aab6267143793943268175ed440586..8e6b5b8f90d8c8250f6bf07f0b49f2f319fc4e25 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -68,7 +68,6 @@ BuildRequires:  gettext
 BuildRequires:  python-devel
 BuildRequires:  python-ldap
 BuildRequires:  python-setuptools
-BuildRequires:  python-krbV
 BuildRequires:  python-nss
 BuildRequires:  python-cryptography
 BuildRequires:  python-netaddr
@@ -128,7 +127,7 @@ Requires: mod_wsgi
 Requires: mod_auth_gssapi >= 1.1.0-2
 Requires: mod_nss >= 1.0.8-26
 Requires: python-ldap >= 2.4.15
-Requires: python-krbV
+Requires: python-gssapi >= 1.1.1
 Requires: python-sssdconfig
 Requires: acl
 Requires: python-pyasn1
@@ -263,7 +262,7 @@ Requires: certmonger >= 0.78
 Requires: nss-tools
 Requires: bind-utils
 Requires: oddjob-mkhomedir
-Requires: python-krbV
+Requires: python-gssapi >= 1.1.1
 Requires: python-dns >= 1.11.1
 Requires: libsss_autofs
 Requires: autofs
@@ -287,7 +286,7 @@ Summary: IPA administrative tools
 Group: System Environment/Base
 Requires: %{name}-python = %{version}-%{release}
 Requires: %{name}-client = %{version}-%{release}
-Requires: python-krbV
+Requires: python-gssapi >= 1.1.1
 Requires: python-ldap
 
 Conflicts: %{alt_name}-admintools
diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains b/install/oddjob/com.redhat.idm.trust-fetch-domains
index e50c81e50e73b258bf08737c2d9a13a8832eb69f..cfc9a589ca8d1d6b77350dd4640d4dcd08c0f197 100755
--- a/install/oddjob/com.redhat.idm.trust-fetch-domains
+++ b/install/oddjob/com.redhat.idm.trust-fetch-domains
@@ -7,33 +7,10 @@ from ipalib import api, errors
 from ipapython.dn import DN
 from ipalib.config import Env
 from ipalib.constants import DEFAULT_CONFIG
-from ipalib.krb_utils import KRB5_CCache
+from ipapython.ipautil import kinit_keytab
 import sys
 import os, pwd
-import krbV
-import time
-
-# This version is different from the original in ipapyton.ipautil
-# in the fact that it returns a krbV.CCache object.
-def kinit_keytab(principal, keytab, ccache_name, attempts=1):
-    errors_to_retry = {krbV.KRB5KDC_ERR_SVC_UNAVAILABLE,
-                       krbV.KRB5_KDC_UNREACH}
-    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)
-            return ccache
-        except krbV.Krb5Error as e:
-            if e.args[0] not in errors_to_retry:
-                raise
-            if attempt == attempts:
-                raise
-            time.sleep(5)
+import gssapi
 
 def retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal):
     getkeytab_args = ["/usr/sbin/ipa-getkeytab",
@@ -125,17 +102,18 @@ ccache_name = '/var/run/ipa/krb5cc_oddjob_trusts'
 #   - if not, initialize it from Samba's keytab
 # - refer the correct ccache object for further use
 #
-if not os.path.isfile(ccache_name):
-    ccache = kinit_keytab(principal, keytab_name, ccache_name)
-
-ccache_check = KRB5_CCache(ccache_name)
-if not ccache_check.credential_is_valid(principal):
-    ccache = kinit_keytab(principal, keytab_name, ccache_name)
-else:
-    ccache = ccache_check.ccache
+try:
+    cred = kinit_keytab(principal, keytab_name, ccache_name)
+    # would raise exception if expired
+    cred.lifetime
+except gssapi.exceptions.ExpiredCredentialsError:
+    # delete stale ccache and try again
+    if os.path.exists(oneway_ccache_name):
+        os.unlink(ccache_name)
+    cred = kinit_keytab(principal, keytab_name, ccache_name)
 
 old_ccache = os.environ.get('KRB5CCNAME')
-api.Backend.ldap2.connect(ccache)
+api.Backend.ldap2.connect(ccache_name)
 
 own_trust_dn = DN(('cn', api.env.domain),('cn','ad'), ('cn', 'etc'), api.env.basedn)
 own_trust_entry = api.Backend.ldap2.get_entry(own_trust_dn, ['ipantflatname'])
@@ -147,25 +125,22 @@ oneway_principal = str('%s$@%s' % (own_trust_flatname, trusted_domain.upper()))
 if not os.path.isfile(oneway_keytab_name):
     retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal)
 
-oneway_ccache = None
 try:
-    # The keytab may have stale key material (from older trust-add run)
-    if not os.path.isfile(oneway_ccache_name):
-        oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
-except krbV.Krb5Error as e:
+    try:
+        # The keytab may have stale key material (from older trust-add run)
+        cred = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
+        # would raise exception if expired
+        cred.lifetime
+    except gssapi.exceptions.ExpiredCredentialsError:
+        if os.path.exists(oneway_ccache_name):
+            os.unlink(oneway_ccache_name)
+        kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
+except gssapi.exceptions.GSSError:
     # If there was failure on using keytab, assume it is stale and retrieve again
     retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal)
-
-if oneway_ccache:
-    # There wasn existing ccache, validate its content
-    oneway_ccache_check = KRB5_CCache(oneway_ccache_name)
-    if not oneway_ccache_check.credential_is_valid(oneway_principal):
-        # If credentials were invalid, obtain them again
-        oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
-    else:
-        oneway_ccache = oneway_ccache_check.ccache
-else:
-    oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
+    if os.path.exists(oneway_ccache_name):
+        os.unlink(oneway_ccache_name)
+    kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
 
 # We are done: we have ccache with TDO credentials and can fetch domains
 ipa_domain = api.env.domain
diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
index 21e58dd9f25e82429ce8d0c776d1b512c2661809..4a5a478b94937e30d04269bd7031bff48ced62e9 100755
--- a/install/tools/ipa-adtrust-install
+++ b/install/tools/ipa-adtrust-install
@@ -21,14 +21,14 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+import gssapi
 from ipaserver.install import adtrustinstance
 from ipaserver.install.installutils import *
 from ipaserver.install import service
 from ipapython import version
 from ipapython import ipautil, sysrestore, ipaldap
-from ipalib import api, errors, util
+from ipalib import api, errors, krb_utils
 from ipapython.config import IPAOptionParser
-import krbV
 from ipaplatform.paths import paths
 from ipapython.ipa_log_manager import *
 from ipapython.dn import DN
@@ -302,21 +302,19 @@ def main():
             print "Proceeding with credentials that existed before"
 
     try:
-        ctx = krbV.default_context()
-        ccache = ctx.default_ccache()
-        principal = ccache.principal()
-    except krbV.Krb5Error, e:
-        sys.exit("Must have Kerberos credentials to setup AD trusts on server")
+        principal = krb_utils.get_principal()
+    except gssapi.exceptions.GSSError as e:
+        sys.exit("Must have Kerberos credentials to setup AD trusts on server: %s" % e.message)
 
     try:
-        api.Backend.ldap2.connect(ccache)
+        api.Backend.ldap2.connect()
     except errors.ACIError, e:
         sys.exit("Outdated Kerberos credentials. Use kdestroy and kinit to update your ticket")
     except errors.DatabaseError, e:
         sys.exit("Cannot connect to the LDAP database. Please check if IPA is running")
 
     try:
-        user = api.Command.user_show(unicode(principal[0]))['result']
+        user = api.Command.user_show(principal)['result']
         group = api.Command.group_show(u'admins')['result']
         if not (user['uid'][0] in group['member_user'] and
                 group['cn'][0] in user['memberof_group']):
diff --git a/install/tools/ipa-csreplica-manage b/install/tools/ipa-csreplica-manage
index 6f6c6c75a122274eeb221f6e0eb15959dec56786..7ae16cb8b98c2dba46508015dc9f2610995fd636 100755
--- a/install/tools/ipa-csreplica-manage
+++ b/install/tools/ipa-csreplica-manage
@@ -22,12 +22,11 @@
 import sys
 import os
 
-import krbV
 from ipapython.ipa_log_manager import *
 
 from ipaserver.install import (replication, installutils, bindinstance,
     cainstance, certs)
-from ipalib import api, errors, util
+from ipalib import api, errors
 from ipalib.constants import CACERT
 from ipapython import ipautil, ipaldap, version, dogtag
 from ipapython.dn import DN
@@ -407,7 +406,7 @@ def main():
     api.finalize()
 
     dirman_passwd = None
-    realm = krbV.default_context().default_realm
+    realm = api.env.realm
 
     if options.host:
         host = options.host
diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index 50a57f70ec452c0df5bf2ea55d2a136e8149aa41..97a1a5701e630d6260d77d37b7eaf45b9a811480 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -20,7 +20,7 @@
 import sys
 import os
 
-import re, krbV
+import re
 import traceback
 from urllib2 import urlparse
 import ldap
@@ -32,7 +32,7 @@ from ipaserver.install import replication, dsinstance, installutils
 from ipaserver.install import bindinstance, cainstance, certs
 from ipaserver.install import opendnssecinstance, dnskeysyncinstance
 from ipapython import version, ipaldap
-from ipalib import api, errors, util
+from ipalib import api, errors
 from ipalib.constants import CACERT
 from ipalib.util import create_topology_graph, get_topology_connection_errors
 from ipapython.ipa_log_manager import *
@@ -1379,7 +1379,7 @@ def main():
     api.finalize()
 
     dirman_passwd = None
-    realm = krbV.default_context().default_realm
+    realm = api.env.realm
 
     if options.host:
         host = options.host
@@ -1404,8 +1404,7 @@ def main():
         api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
                                   bind_pw=options.dirman_passwd)
     else:
-        ccache = krbV.default_context().default_ccache()
-        api.Backend.ldap2.connect(ccache=ccache)
+        api.Backend.ldap2.connect()
 
     if args[0] == "list":
         replica = None
diff --git a/ipa-client/ipa-client.spec.in b/ipa-client/ipa-client.spec.in
index 686259ad24b241c232dce83b695a05f6fd6c3849..4413937bb6c98ef4ad8e87f1b94246b98d82755c 100644
--- a/ipa-client/ipa-client.spec.in
+++ b/ipa-client/ipa-client.spec.in
@@ -9,7 +9,7 @@ URL:            http://www.freeipa.org
 Source0:        %{name}-%{version}.tgz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
-Requires: python python-ldap python-krbV ipa-python cyrus-sasl-gssapi
+Requires: python python-ldap python-gssapi ipa-python cyrus-sasl-gssapi
 
 %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
 
diff --git a/ipa-client/ipa-install/ipa-client-automount b/ipa-client/ipa-install/ipa-client-automount
index eee141812cace38ed795c3f3b4120bded2257d1b..0128e7c3d899be5610cb49f23f18760c6c8786e5 100755
--- a/ipa-client/ipa-install/ipa-client-automount
+++ b/ipa-client/ipa-install/ipa-client-automount
@@ -26,7 +26,7 @@ import os
 import urlparse
 import time
 import tempfile
-from krbV import Krb5Error
+import gssapi
 
 import SSSDConfig
 
@@ -435,7 +435,7 @@ def main():
             host_princ = str('host/%s@%s' % (api.env.host, api.env.realm))
             ipautil.kinit_keytab(host_princ, paths.KRB5_KEYTAB, ccache_name)
             os.environ['KRB5CCNAME'] = ccache_name
-        except Krb5Error as e:
+        except gssapi.exceptions.GSSError as e:
             sys.exit("Failed to obtain host TGT: %s" % e)
         # Now we have a TGT, connect to IPA
         try:
diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 17cd2b6879aeb0c4b80dae9fe4218c0a741c0990..5b38ac310b868560bcbeb973fc120a9e770f5d80 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -31,7 +31,7 @@ try:
     from ConfigParser import RawConfigParser
     from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError
     import shutil
-    from krbV import Krb5Error
+    import gssapi
 
     import nss.nss as nss
     import SSSDConfig
@@ -2442,7 +2442,7 @@ def install(options, env, fstore, statestore):
                                              ccache_name,
                                              config=krb_name,
                                              attempts=options.kinit_attempts)
-                    except Krb5Error as e:
+                    except gssapi.exceptions.GSSError as e:
                         print_port_conf_info()
                         root_logger.error("Kerberos authentication failed: %s"
                                           % e)
@@ -2522,7 +2522,7 @@ def install(options, env, fstore, statestore):
                                      config=krb_name,
                                      attempts=options.kinit_attempts)
                 env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = CCACHE_FILE
-            except Krb5Error as e:
+            except gssapi.exceptions.GSSError 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
@@ -2569,7 +2569,7 @@ def install(options, env, fstore, statestore):
                                  CCACHE_FILE,
                                  attempts=options.kinit_attempts)
             os.environ['KRB5CCNAME'] = CCACHE_FILE
-        except Krb5Error as e:
+        except gssapi.exceptions.GSSError as e:
             root_logger.error("Failed to obtain host TGT: %s" % e)
             return CLIENT_INSTALL_ERROR
     else:
diff --git a/ipalib/krb_utils.py b/ipalib/krb_utils.py
index 9a557ce5cf1b4c3ef7587d3fb545827c1ade1f1d..7b2263f324f9527e298f04a2b67d3be95ff44bee 100644
--- a/ipalib/krb_utils.py
+++ b/ipalib/krb_utils.py
@@ -16,25 +16,22 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-import krbV
 import time
 import re
-from ipapython.ipa_log_manager import *
+import gssapi
+
+from ipalib import errors
 
 #-------------------------------------------------------------------------------
 
-# Kerberos constants, should be defined in krbV, but aren't
-KRB5_GC_CACHED = 0x2
-
-# Kerberos error codes, should be defined in krbV, but aren't
-KRB5_CC_NOTFOUND                = -1765328243 # Matching credential not found
-KRB5_FCC_NOFILE                 = -1765328189 # No credentials cache found
-KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN = -1765328377 # Server not found in Kerberos database
-KRB5KRB_AP_ERR_TKT_EXPIRED      = -1765328352 # Ticket expired
-KRB5_FCC_PERM                   = -1765328190 # Credentials cache permissions incorrect
-KRB5_CC_FORMAT                  = -1765328185 # Bad format in credentials cache
-KRB5_REALM_CANT_RESOLVE         = -1765328164 # Cannot resolve network address for KDC in requested realm
-
+# Kerberos error codes
+KRB5_CC_NOTFOUND                = 2529639053 # Matching credential not found
+KRB5_FCC_NOFILE                 = 2529639107 # No credentials cache found
+KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN = 2529638919 # Server not found in Kerberos database
+KRB5KRB_AP_ERR_TKT_EXPIRED      = 2529638944 # Ticket expired
+KRB5_FCC_PERM                   = 2529639106 # Credentials cache permissions incorrect
+KRB5_CC_FORMAT                  = 2529639111 # Bad format in credentials cache
+KRB5_REALM_CANT_RESOLVE         = 2529639132 # Cannot resolve network address for KDC in requested realm
 
 krb_ticket_expiration_threshold = 60*5 # number of seconds to accmodate clock skew
 krb5_time_fmt = '%m/%d/%y %H:%M:%S'
@@ -136,260 +133,66 @@ def krb5_format_time(timestamp):
     '''
     return time.strftime(krb5_time_fmt, time.localtime(timestamp))
 
-class KRB5_CCache(object):
+def get_credentials(name=None, ccache_name=None):
     '''
-    Kerberos stores a TGT (Ticket Granting Ticket) and the service
-    tickets bound to it in a ccache (credentials cache). ccaches are
-    bound to a Kerberos user principal. This class opens a Kerberos
-    ccache and allows one to manipulate it. Most useful is the
-    extraction of ticket entries (cred's) in the ccache and the
-    ability to examine their attributes.
+    Obtains GSSAPI credentials with given principal name from ccache. When no
+    principal name specified, it retrieves the default one for given
+    credentials cache.
+
+    :parameters:
+      name
+        gssapi.Name object specifying principal or None for the default
+      ccache_name
+        string specifying Kerberos credentials cache name or None for the
+        default
+    :returns:
+      gssapi.Credentials object
     '''
+    store = None
+    if ccache_name:
+        store = {'ccache': ccache_name}
+    try:
+        return gssapi.Credentials(usage='initiate', name=name, store=store)
+    except gssapi.exceptions.GSSError as e:
+        if e.min_code == KRB5_FCC_NOFILE:
+            raise ValueError('"%s", ccache="%s"' % (e.message, ccache_name))
+        raise
+
+def get_principal(ccache_name=None):
+    '''
+    Gets default principal name from given credentials cache.
+
+    :parameters:
+      ccache_name
+        string specifying Kerberos credentials cache name or None for the
+        default
+    :returns:
+      Default principal name as string
+    '''
+    creds = get_credentials(ccache_name=ccache_name)
+    return unicode(creds.name)
 
-    def __init__(self, ccache):
-        '''
-        :parameters:
-          ccache
-            The name of a Kerberos ccache used to hold Kerberos tickets.
-        :returns:
-          `KRB5_CCache` object encapsulting the ccache.
-        '''
-        log_mgr.get_logger(self, True)
-        self.context = None
-        self.scheme = None
-        self.name = None
-        self.ccache = None
-        self.principal = None
-
-        try:
-            self.context = krbV.default_context()
-            self.scheme, self.name = krb5_parse_ccache(ccache)
-            self.ccache = krbV.CCache(name=str(ccache), context=self.context)
-            self.principal = self.ccache.principal()
-        except krbV.Krb5Error, e:
-            error_code = e.args[0]
-            message = e.args[1]
-            if error_code == KRB5_FCC_NOFILE:
-                raise ValueError('"%s", ccache="%s"' % (message, ccache))
-            else:
-                raise e
-
-    def ccache_str(self):
-        '''
-        A Kerberos ccache is identified by a name comprised of a
-        scheme and location component. This function returns that
-        canonical name. See `krb5_parse_ccache()`
-
-        :returns:
-          The name of ccache with it's scheme and location components.
-        '''
-
-        return '%s:%s' % (self.scheme, self.name)
-
-    def __str__(self):
-        return 'cache="%s" principal="%s"' % (self.ccache_str(), self.principal.name)
-
-    def get_credentials(self, principal):
-        '''
-        Given a Kerberos principal return the krbV credentials
-        tuple describing the credential. If the principal does
-        not exist in the ccache a KeyError is raised.
-
-        :parameters:
-          principal
-            The Kerberos principal whose ticket is being retrieved.
-            The principal may be either a string formatted as a
-            Kerberos V5 principal or it may be a `krbV.Principal`
-            object.
-        :returns:
-          A krbV credentials tuple. If the principal is not in the
-          ccache a KeyError is raised.
-
-        '''
-
-        if isinstance(principal, krbV.Principal):
-            krbV_principal = principal
-        else:
-            try:
-                krbV_principal = krbV.Principal(str(principal), self.context)
-            except Exception, e:
-                self.error('could not create krbV principal from "%s", %s', principal, e)
-                raise e
-
-        creds_tuple = (self.principal,
-                       krbV_principal,
-                       (0, None),    # keyblock: (enctype, contents)
-                       (0, 0, 0, 0), # times: (authtime, starttime, endtime, renew_till)
-                       0,0,          # is_skey, ticket_flags
-                       None,         # addrlist
-                       None,         # ticket_data
-                       None,         # second_ticket_data
-                       None)         # adlist
-        try:
-            cred = self.ccache.get_credentials(creds_tuple, KRB5_GC_CACHED)
-        except krbV.Krb5Error, e:
-            error_code = e.args[0]
-            if error_code == KRB5_CC_NOTFOUND:
-                raise KeyError('"%s" credential not found in "%s" ccache' % \
-                               (krbV_principal.name, self.ccache_str()))
-            raise e
-        except Exception, e:
-            raise e
-
-        return cred
-
-    def get_credential_times(self, principal):
-        '''
-        Given a Kerberos principal return the ticket timestamps if the
-        principal's ticket in the ccache is valid.  If the principal
-        does not exist in the ccache a KeyError is raised.
-
-        The return credential time values are Unix timestamps in
-        localtime.
-
-        The returned timestamps are:
-
-        authtime
-          The time when the ticket was issued.
-        starttime
-          The time when the ticket becomes valid.
-        endtime
-          The time when the ticket expires.
-        renew_till
-          The time when the ticket becomes no longer renewable (if renewable).
-
-        :parameters:
-          principal
-            The Kerberos principal whose ticket is being validated.
-            The principal may be either a string formatted as a
-            Kerberos V5 principal or it may be a `krbV.Principal`
-            object.
-        :returns:
-            return authtime, starttime, endtime, renew_till
-        '''
-
-        if isinstance(principal, krbV.Principal):
-            krbV_principal = principal
-        else:
-            try:
-                krbV_principal = krbV.Principal(str(principal), self.context)
-            except Exception, e:
-                self.error('could not create krbV principal from "%s", %s', principal, e)
-                raise e
-
-        try:
-            cred = self.get_credentials(krbV_principal)
-            authtime, starttime, endtime, renew_till = cred[3]
-
-            self.debug('get_credential_times: principal=%s, authtime=%s, starttime=%s, endtime=%s, renew_till=%s',
-                       krbV_principal.name,
-                       krb5_format_time(authtime), krb5_format_time(starttime),
-                       krb5_format_time(endtime), krb5_format_time(renew_till))
-
-            return authtime, starttime, endtime, renew_till
-
-        except KeyError, e:
-            raise e
-        except Exception, e:
-            self.error('get_credential_times failed, principal="%s" error="%s"', krbV_principal.name, e)
-            raise e
-
-    def credential_is_valid(self, principal):
-        '''
-        Given a Kerberos principal return a boolean indicating if the
-        principal's ticket in the ccache is valid. If the ticket is
-        not in the ccache False is returned. If the ticket
-        exists in the ccache it's validity is checked and returned.
-
-        :parameters:
-          principal
-            The Kerberos principal whose ticket is being validated.
-            The principal may be either a string formatted as a
-            Kerberos V5 principal or it may be a `krbV.Principal`
-            object.
-        :returns:
-          True if the principal's ticket exists and is valid. False if
-          the ticket does not exist or if the ticket is not valid.
-        '''
-
-        try:
-            authtime, starttime, endtime, renew_till = self.get_credential_times(principal)
-        except KeyError, e:
-            return False
-        except Exception, e:
-            self.error('credential_is_valid failed, principal="%s" error="%s"', principal, e)
-            raise e
-
-
-        now = time.time()
-        if starttime > now:
-            return False
-        if endtime < now:
-            return False
-        return True
-
-    def valid(self, host, realm):
-        '''
-        Test to see if ldap service ticket or the TGT is valid.
-
-        :parameters:
-          host
-            ldap server
-          realm
-            kerberos realm
-        :returns:
-          True if either the ldap service ticket or the TGT is valid,
-          False otherwise.
-        '''
-
-        try:
-            principal = krb5_format_service_principal_name('HTTP', host, realm)
-            valid = self.credential_is_valid(principal)
-            if valid:
-                return True
-        except KeyError:
-            pass
-
-        try:
-            principal = krb5_format_tgt_principal_name(realm)
-            valid = self.credential_is_valid(principal)
-            return valid
-        except KeyError:
-            return False
-
-    def endtime(self, host, realm):
-        '''
-        Returns the minimum endtime for tickets of interest (ldap service or TGT).
-
-        :parameters:
-          host
-            ldap server
-          realm
-            kerberos realm
-        :returns:
-          UNIX timestamp value.
-        '''
-
-        result = 0
-        try:
-            principal = krb5_format_service_principal_name('HTTP', host, realm)
-            authtime, starttime, endtime, renew_till = self.get_credential_times(principal)
-            if result:
-                result = min(result, endtime)
-            else:
-                result = endtime
-        except KeyError:
-            pass
-
-        try:
-            principal = krb5_format_tgt_principal_name(realm)
-            authtime, starttime, endtime, renew_till = self.get_credential_times(principal)
-            if result:
-                result = min(result, endtime)
-            else:
-                result = endtime
-        except KeyError:
-            pass
+def get_credentials_if_valid(name=None, ccache_name=None):
+    '''
+    Obtains GSSAPI credentials with principal name from ccache. When no
+    principal name specified, it retrieves the default one for given
+    credentials cache. When the credentials cannot be retrieved or aren't valid
+    it returns None.
+
+    :parameters:
+      name
+        gssapi.Name object specifying principal or None for the default
+      ccache_name
+        string specifying Kerberos credentials cache name or None for the
+        default
+    :returns:
+      gssapi.Credentials object or None if valid credentials weren't found
+    '''
 
-        self.debug('KRB5_CCache %s endtime=%s (%s)', self.ccache_str(), result, krb5_format_time(result))
-        return result
+    try:
+        creds = get_credentials(name=name, ccache_name=ccache_name)
+        # property access would raise exception if expired
+        if creds.lifetime > 0:
+            return creds
+    except gssapi.exceptions.ExpiredCredentialsError:
+        return None
diff --git a/ipalib/plugins/kerberos.py b/ipalib/plugins/kerberos.py
deleted file mode 100644
index 3ed6d76719af46689cc3a0f6890ec243f9c685d3..0000000000000000000000000000000000000000
--- a/ipalib/plugins/kerberos.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# Authors:
-#   Jason Gerard DeRose <jder...@redhat.com>
-#
-# Copyright (C) 2008  Red Hat
-# see file 'COPYING' for use and warranty information
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""
-Backend plugin for Kerberos.
-
-This wraps the python-kerberos and python-krbV bindings.
-"""
-
-import sys
-from ipalib import api
-from ipalib.backend import Backend
-from ipalib.plugable import Registry
-import krbV
-
-register = Registry()
-
-ENCODING = 'UTF-8'
-
-
-@register()
-class krb(Backend):
-    """
-    Kerberos backend plugin.
-
-    This wraps the `krbV` bindings (and will eventually wrap the `kerberos`
-    bindings also).  Importantly, this plugin does correct Unicode
-    encoding/decoding of values going-to/coming-from the bindings.
-    """
-
-    def __default_ccache(self):
-        """
-        Return the ``krbV.CCache`` for the default credential cache.
-        """
-        return krbV.default_context().default_ccache()
-
-    def __default_principal(self):
-        """
-        Return the ``krb5.Principal`` for the default credential cache.
-        """
-        return self.__default_ccache().principal()
-
-    def __get_ccache(self, ccname):
-        """
-        Return the ``krbV.CCache`` for the ``ccname`` credential ccache.
-        """
-        return krbV.CCache(ccname)
-
-    def __get_principal(self, ccname):
-        """
-        Return the ``krb5.Principal`` for the ``ccname`` credential ccache.
-        """
-        return self.__get_ccache(ccname).principal()
-
-    def default_ccname(self):
-        """
-        Return the default ccache file name (schema+name).
-
-        This will return something like 'FILE:/tmp/krb5cc_500'.
-
-        This cannot return anything meaningful if used in the server as a
-        request is processed.
-        """
-        default_ccache = self.__default_ccache()
-        ccname = "%(type)s:%(name)s" % dict(type=default_ccache.type,
-                                            name=default_ccache.name)
-        return ccname
-
-    def default_principal(self):
-        """
-        Return the principal name in default credential cache.
-
-        This will return something like 'ad...@example.com'.  If no credential
-        cache exists for the invoking user, None is returned.
-
-        This cannot return anything meaningful if used in the server as a
-        request is processed.
-        """
-        return self.__default_principal().name.decode(ENCODING)
-
-    def default_realm(self):
-        """
-        Return the realm from the default credential cache.
-
-        This will return something like 'EXAMPLE.COM'.  If no credential cache
-        exists for the invoking user, None is returned.
-
-        This cannot return anything meaningful if used in the server as a
-        request is processed.
-        """
-        return krbV.default_context().default_realm.decode(ENCODING)
-
-    def get_principal(self, ccname):
-        """
-        Return the principal from credential cache file at ``ccname``.
-
-        This will return something like 'ad...@example.com'.
-        """
-        return self.__get_principal(ccname).name.decode(ENCODING)
-
-    def get_realm(self, ccname):
-        """
-        Return the realm from credential cache file at ``ccname``.
-
-        This will return something like 'EXAMPLE.COM'.
-        """
-        return self.__get_principal(ccname).realm.decode(ENCODING)
-
-
diff --git a/ipalib/plugins/passwd.py b/ipalib/plugins/passwd.py
index f5fc14d510ea7eea1e16435fe11d982d4ca49d79..a4f791c1bdf4b6f695b3a79f00a54c084f423229 100644
--- a/ipalib/plugins/passwd.py
+++ b/ipalib/plugins/passwd.py
@@ -17,7 +17,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ipalib import api, errors, util
+from ipalib import api, errors, krb_utils
 from ipalib import Command
 from ipalib import Str, Password
 from ipalib import _
@@ -58,7 +58,7 @@ def get_current_password(principal):
     current password is prompted for, otherwise return a fixed value to
     be ignored later.
     """
-    current_principal = util.get_current_principal()
+    current_principal = krb_utils.get_principal()
     if current_principal == normalize_principal(principal):
         return None
     else:
@@ -74,7 +74,7 @@ class passwd(Command):
             label=_('User name'),
             primary_key=True,
             autofill=True,
-            default_from=lambda: util.get_current_principal(),
+            default_from=lambda: krb_utils.get_principal(),
             normalizer=lambda value: normalize_principal(value),
         ),
         Password('password',
diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py
index 423df6b7c0e39c46b20561133be8cd54560bf8b9..72d0ce62c3f94c329cfb316c8c3c5b7b3621576c 100644
--- a/ipalib/plugins/vault.py
+++ b/ipalib/plugins/vault.py
@@ -34,7 +34,6 @@ from cryptography.hazmat.primitives.serialization import load_pem_public_key,\
     load_pem_private_key
 
 import nss.nss as nss
-import krbV
 
 from ipalib.frontend import Command, Object, Local
 from ipalib import api, errors
@@ -602,7 +601,7 @@ class vault_add(PKQuery, Local):
         else:
             backend = self.api.Backend.rpcclient
         if not backend.isconnected():
-            backend.connect(ccache=krbV.default_context().default_ccache())
+            backend.connect()
 
         if vault_type == u'standard':
 
@@ -945,7 +944,7 @@ class vault_archive(PKQuery, Local):
         else:
             backend = self.api.Backend.rpcclient
         if not backend.isconnected():
-            backend.connect(ccache=krbV.default_context().default_ccache())
+            backend.connect()
 
         # retrieve vault info
         vault = self.api.Command.vault_show(*args, **options)['result']
@@ -1210,7 +1209,7 @@ class vault_retrieve(PKQuery, Local):
         else:
             backend = self.api.Backend.rpcclient
         if not backend.isconnected():
-            backend.connect(ccache=krbV.default_context().default_ccache())
+            backend.connect()
 
         # retrieve vault info
         vault = self.api.Command.vault_show(*args, **options)['result']
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index 4176bbd283da709b60844bdb38651af97ea8f48f..7b2385e0d3e731573338e5b8e6e04f9579ee13d9 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -55,7 +55,6 @@ from ipalib.errors import (public_errors, UnknownError, NetworkError,
     KerberosError, XMLRPCMarshallError, JSONError, ConversionError)
 from ipalib import errors, capabilities
 from ipalib.request import context, Connection
-from ipalib.util import get_current_principal
 from ipapython.ipa_log_manager import root_logger
 from ipapython import ipautil
 from ipapython import kernel_keyring
@@ -66,7 +65,8 @@ from ipalib.text import _
 import ipapython.nsslib
 from ipapython.nsslib import NSSHTTPS, NSSConnection
 from ipalib.krb_utils import KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, KRB5KRB_AP_ERR_TKT_EXPIRED, \
-                             KRB5_FCC_PERM, KRB5_FCC_NOFILE, KRB5_CC_FORMAT, KRB5_REALM_CANT_RESOLVE
+                             KRB5_FCC_PERM, KRB5_FCC_NOFILE, KRB5_CC_FORMAT, \
+                             KRB5_REALM_CANT_RESOLVE, get_principal
 from ipapython.dn import DN
 from ipalib.capabilities import VERSION_WITHOUT_CAPABILITIES
 from ipalib import api
@@ -518,10 +518,7 @@ class KerbTransport(SSLTransport):
         self._sec_context = None
 
     def _handle_exception(self, e, service=None):
-        # kerberos library coerced error codes to signed, gssapi uses unsigned
         minor = e.min_code
-        if minor & (1 << 31):
-            minor -= 1 << 32
         if minor == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
             raise errors.ServiceError(service=service)
         elif minor == KRB5_FCC_NOFILE:
@@ -835,7 +832,7 @@ class RPCClient(Connectible):
                           delegate=False, nss_dir=None):
         try:
             rpc_uri = self.env[self.env_rpc_uri_key]
-            principal = get_current_principal()
+            principal = get_principal()
             setattr(context, 'principal', principal)
             # We have a session cookie, try using the session URI to see if it
             # is still valid
diff --git a/ipalib/util.py b/ipalib/util.py
index 5a670146e0ea569458bf0086b075df3d4b7b4b5b..c90b9c9ca68b2e22f7356354866b0dded26b62d6 100644
--- a/ipalib/util.py
+++ b/ipalib/util.py
@@ -61,18 +61,6 @@ def json_serialize(obj):
         return ''
     return json_serialize(obj.__json__())
 
-def get_current_principal():
-    try:
-        import gssapi
-        cred = gssapi.Credentials(usage='initiate')
-        return unicode(cred.name)
-    except ImportError:
-        raise RuntimeError('python-gssapi is not available.')
-    except gssapi.exceptions.GSSError:
-        #TODO: do a kinit?
-        raise errors.CCacheError()
-
-
 def validate_host_dns(log, fqdn):
     """
     See if the hostname has a DNS A/AAAA record.
diff --git a/ipapython/config.py b/ipapython/config.py
index 60f556dc946651903652aa284ce75bd1e8f13d6c..1a227f8afb9a6d3fe68a90b4915760fdab8f447a 100644
--- a/ipapython/config.py
+++ b/ipapython/config.py
@@ -176,17 +176,6 @@ def __parse_config(discover_server = True):
 def __discover_config(discover_server = True):
     servers = []
     try:
-        if not config.default_realm:
-            try:
-                # only import krbV when we need it
-                import krbV
-                krbctx = krbV.default_context()
-                config.default_realm = krbctx.default_realm
-            except ImportError:
-                pass
-            if not config.default_realm:
-                return False
-
         if not config.default_domain:
             # try once with REALM -> domain
             domain = str(config.default_realm).lower()
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 05a7eebf012b27e3e34cb74778c2724e9deaf616..f02a7e007f68c5f8eecd788df28656af7065a0c3 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -34,7 +34,7 @@ import xmlrpclib
 import datetime
 import netaddr
 import time
-import krbV
+import gssapi
 import pwd
 import grp
 from dns import resolver, rdatatype
@@ -54,6 +54,11 @@ GEN_PWD_LEN = 12
 
 IPA_BASEDN_INFO = 'ipa v2.0'
 
+# Having this in krb_utils would cause circular import
+KRB5_KDC_UNREACH = 2529639068 # Cannot contact any KDC for requested realm
+KRB5KDC_ERR_SVC_UNAVAILABLE = 2529638941 # A service is not available that is
+                                         # required to process the request
+
 try:
     from subprocess import CalledProcessError
 except ImportError:
@@ -1193,8 +1198,8 @@ def kinit_keytab(principal, keytab, ccache_name, config=None, attempts=1):
     The optional parameter 'attempts' specifies how many times the credential
     initialization should be attempted in case of non-responsive KDC.
     """
-    errors_to_retry = {krbV.KRB5KDC_ERR_SVC_UNAVAILABLE,
-                       krbV.KRB5_KDC_UNREACH}
+    errors_to_retry = {KRB5KDC_ERR_SVC_UNAVAILABLE,
+                       KRB5_KDC_UNREACH}
     root_logger.debug("Initializing principal %s using keytab %s"
                       % (principal, keytab))
     root_logger.debug("using ccache %s" % ccache_name)
@@ -1205,18 +1210,15 @@ def kinit_keytab(principal, keytab, ccache_name, config=None, attempts=1):
         else:
             os.environ.pop('KRB5_CONFIG', None)
         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)
+            name = gssapi.Name(principal, gssapi.NameType.kerberos_principal)
+            store = {'ccache': ccache_name,
+                     'client_keytab': keytab}
+            cred = gssapi.Credentials(name=name, store=store, usage='initiate')
             root_logger.debug("Attempt %d/%d: success"
                               % (attempt, attempts))
-            return
-        except krbV.Krb5Error as e:
-            if e.args[0] not in errors_to_retry:
+            return cred
+        except gssapi.exceptions.GSSError as e:
+            if e.min_code not in errors_to_retry:
                 raise
             root_logger.debug("Attempt %d/%d: failed: %s"
                               % (attempt, attempts, e))
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
index 01ec805fc2094326d119827b4358c143f45f3ec4..9f5976ec3afde9b60b794cc3724470eaa8837a6b 100644
--- a/ipaserver/install/ipa_cacert_manage.py
+++ b/ipaserver/install/ipa_cacert_manage.py
@@ -23,7 +23,7 @@ from optparse import OptionGroup
 import base64
 from nss import nss
 from nss.error import NSPRError
-import krbV
+import gssapi
 
 from ipapython import admintool, certmonger, ipautil
 from ipapython.dn import DN
@@ -126,9 +126,8 @@ class CACertManage(admintool.AdminTool):
         password = self.options.password
         if not password:
             try:
-                ccache = krbV.default_context().default_ccache()
-                conn.connect(ccache=ccache)
-            except (krbV.Krb5Error, errors.ACIError):
+                conn.connect()
+            except (gssapi.exceptions.GSSError, errors.ACIError):
                 pass
             else:
                 return conn
diff --git a/ipaserver/install/ipa_ldap_updater.py b/ipaserver/install/ipa_ldap_updater.py
index f07eecf232916e979f7f92f0fe15e4976ad48ec6..f610748e32ac8a2ed8a5ee1f32c2810f67452e3d 100644
--- a/ipaserver/install/ipa_ldap_updater.py
+++ b/ipaserver/install/ipa_ldap_updater.py
@@ -26,8 +26,6 @@
 import os
 import sys
 
-import krbV
-
 from ipalib import api
 from ipapython import ipautil, admintool
 from ipaplatform.paths import paths
@@ -100,7 +98,7 @@ class LDAPUpdater_Upgrade(LDAPUpdater):
         super(LDAPUpdater_Upgrade, self).run()
         options = self.options
 
-        realm = krbV.default_context().default_realm
+        realm = api.env.realm
         upgrade = IPAUpgrade(realm, self.files,
                              schema_files=options.schema_files)
 
diff --git a/ipaserver/install/ipa_otptoken_import.py b/ipaserver/install/ipa_otptoken_import.py
index 386ca4273c413d9f6a121956d0db3f0c44fe5c24..ae89f7e07fc823005b4970ae20314a8259939b8e 100644
--- a/ipaserver/install/ipa_otptoken_import.py
+++ b/ipaserver/install/ipa_otptoken_import.py
@@ -30,7 +30,7 @@ from lxml import etree
 import dateutil.parser
 import dateutil.tz
 import nss.nss as nss
-import krbV
+import gssapi
 
 from ipapython import admintool
 from ipalib import api, errors
@@ -509,9 +509,8 @@ class OTPTokenImport(admintool.AdminTool):
 
         conn = ldap2(api)
         try:
-            ccache = krbV.default_context().default_ccache()
-            conn.connect(ccache=ccache)
-        except (krbV.Krb5Error, errors.ACIError):
+            conn.connect()
+        except (gssapi.exceptions.GSSError, errors.ACIError):
             raise admintool.ScriptError("Unable to connect to LDAP! Did you kinit?")
 
         try:
diff --git a/ipaserver/install/ipa_winsync_migrate.py b/ipaserver/install/ipa_winsync_migrate.py
index cbe068458cc0b6853573c9d23d4cb6386a816bb3..671e6f436756b0faed6f0e408df8b5f5b5177e77 100644
--- a/ipaserver/install/ipa_winsync_migrate.py
+++ b/ipaserver/install/ipa_winsync_migrate.py
@@ -17,7 +17,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-import krbV
+import gssapi
 import sys
 
 from ipalib import api
@@ -315,11 +315,9 @@ class WinsyncMigrate(admintool.AdminTool):
 
         # Setup LDAP connection
         try:
-            ctx = krbV.default_context()
-            ccache = ctx.default_ccache()
-            api.Backend.ldap2.connect(ccache)
+            api.Backend.ldap2.connect()
             cls.ldap = api.Backend.ldap2
-        except krbV.Krb5Error, e:
+        except gssapi.exceptions.GSSError:
             sys.exit("Must have Kerberos credentials to migrate Winsync users.")
         except errors.ACIError, e:
             sys.exit("Outdated Kerberos credentials. Use kdestroy and kinit to update your ticket.")
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 6f796dfdc8bbac1bb99a8b5a1bd5a6aaa778db16..daf2221a93052f072c001baf9ec971bcaa5cae17 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -32,7 +32,6 @@ import pwd
 import fnmatch
 import re
 
-import krbV
 import ldap
 
 from ipaserver.install import installutils
@@ -272,13 +271,8 @@ class LDAPUpdate:
         if sub_dict.get("REALM"):
             self.realm = sub_dict["REALM"]
         else:
-            krbctx = krbV.default_context()
-            try:
-                self.realm = krbctx.default_realm
-                suffix = ipautil.realm_to_suffix(self.realm)
-            except krbV.Krb5Error:
-                self.realm = None
-                suffix = None
+            self.realm = api.env.realm
+            suffix = ipautil.realm_to_suffix(self.realm) if self.realm else None
 
         if suffix is not None:
             assert isinstance(suffix, DN)
diff --git a/ipaserver/install/schemaupdate.py b/ipaserver/install/schemaupdate.py
index 03edb63075e893ca9887559de6470b9f94c40cf9..f98d0e949f59f19e0b51deeac0717e5c87ff92cf 100644
--- a/ipaserver/install/schemaupdate.py
+++ b/ipaserver/install/schemaupdate.py
@@ -20,9 +20,9 @@
 import pprint
 
 import ldap.schema
-import krbV
 
 import ipapython.version
+from ipalib import api
 from ipapython.ipa_log_manager import log_mgr
 from ipapython.dn import DN
 from ipaserver.install.ldapupdate import connect
@@ -106,7 +106,7 @@ def update_schema(schema_files, ldapi=False, dm_password=None,):
     SCHEMA_ELEMENT_CLASSES_KEYS = [x[0] for x in SCHEMA_ELEMENT_CLASSES]
 
     conn = connect(ldapi=ldapi, dm_password=dm_password,
-                   realm=krbV.default_context().default_realm,
+                   realm=api.env.realm,
                    fqdn=installutils.get_fqdn())
 
     old_schema = conn.schema
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index f9f2d75f952f3b28fbd1a66256e186e17b4a5c09..76aa47e4db61a0b1db0487db1586665ca527fa2c 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -9,11 +9,9 @@ import pwd
 import fileinput
 import ConfigParser
 import sys
-import krbV
 
 from ipalib import api
 import SSSDConfig
-import ipalib.util
 import ipalib.errors
 from ipaplatform import services
 from ipaplatform.tasks import tasks
@@ -1557,7 +1555,7 @@ def upgrade_check(options):
 
 
 def upgrade():
-    realm = krbV.default_context().default_realm
+    realm = api.env.realm
     schema_files = [os.path.join(ipautil.SHARE_DIR, f) for f
                     in dsinstance.ALL_SCHEMA_FILES]
     data_upgrade = IPAUpgrade(realm, schema_files=schema_files)
diff --git a/ipaserver/plugins/join.py b/ipaserver/plugins/join.py
index 3b668053c5d275c53da0c897fb4f82442a725564..7342117e78e3f82c78e0ef0aac8eea6a0b20fde9 100644
--- a/ipaserver/plugins/join.py
+++ b/ipaserver/plugins/join.py
@@ -21,8 +21,6 @@
 Joining an IPA domain
 """
 
-import krbV
-
 from ipalib import api
 from ipalib import Command, Str
 from ipalib import errors
@@ -30,15 +28,6 @@ from ipalib import _
 from ipaserver.install import installutils
 
 
-def get_realm():
-    """
-    Returns the default kerberos realm configured for this server.
-    """
-    krbctx = krbV.default_context()
-
-    return unicode(krbctx.default_realm)
-
-
 def validate_host(ugettext, cn):
     """
     Require at least one dot in the hostname (to support localhost.localdomain)
@@ -66,7 +55,7 @@ class join(Command):
     takes_options = (
         Str('realm',
             doc=_("The IPA realm"),
-            default_from=lambda: get_realm(),
+            default_from=lambda: api.env.realm,
             autofill=True,
         ),
         Str('nshardwareplatform?',
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index 68feee4f09eb12e50867dfbe3c482a359838aa82..acaf45fddb7ba54a42af15270534e1cde81fc2bd 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -30,11 +30,12 @@ Backend plugin for LDAP.
 import os
 import pwd
 
-import krbV
 import ldap as _ldap
 
+from ipalib import krb_utils
 from ipapython.dn import DN
-from ipapython.ipaldap import SASL_GSSAPI, LDAPClient
+from ipapython.ipaldap import (LDAPClient, AUTOBIND_AUTO, AUTOBIND_ENABLED,
+                               AUTOBIND_DISABLED)
 
 
 try:
@@ -88,13 +89,14 @@ class ldap2(CrudBackend, LDAPClient):
 
     def create_connection(self, ccache=None, bind_dn=None, bind_pw='',
             tls_cacertfile=None, tls_certfile=None, tls_keyfile=None,
-            debug_level=0, autobind=False, serverctrls=None, clientctrls=None):
+            debug_level=0, autobind=AUTOBIND_AUTO, serverctrls=None,
+            clientctrls=None):
         """
         Connect to LDAP server.
 
         Keyword arguments:
         ldapuri -- the LDAP server to connect to
-        ccache -- Kerberos V5 ccache object or name
+        ccache -- Kerberos ccache name
         bind_dn -- dn used to bind to the server
         bind_pw -- password used to bind to the server
         debug_level -- LDAP debug level option
@@ -122,8 +124,6 @@ class ldap2(CrudBackend, LDAPClient):
         conn = self._conn
 
         with self.error_handler():
-            if self.ldap_uri.startswith('ldapi://') and ccache:
-                conn.set_option(_ldap.OPT_HOST_NAME, self.api.env.host)
             minssf = conn.get_option(_ldap.OPT_X_SASL_SSF_MIN)
             maxssf = conn.get_option(_ldap.OPT_X_SASL_SSF_MAX)
             # Always connect with at least an SSF of 56, confidentiality
@@ -134,33 +134,37 @@ class ldap2(CrudBackend, LDAPClient):
                 if maxssf < minssf:
                     conn.set_option(_ldap.OPT_X_SASL_SSF_MAX, minssf)
 
-        if ccache is not None:
-            if isinstance(ccache, krbV.CCache):
-                principal = ccache.principal().name
-                # Get a fully qualified CCACHE name (schema+name)
-                # As we do not use the krbV.CCache object later,
-                # we can safely overwrite it
-                ccache = "%(type)s:%(name)s" % dict(type=ccache.type,
-                                                    name=ccache.name)
-            else:
-                principal = krbV.CCache(name=ccache,
-                    context=krbV.default_context()).principal().name
+        ldapi = self.ldap_uri.startswith('ldapi://')
 
-            os.environ['KRB5CCNAME'] = ccache
-            self.gssapi_bind(server_controls=serverctrls,
+        if bind_pw:
+            self.simple_bind(bind_dn, bind_pw,
+                             server_controls=serverctrls,
                              client_controls=clientctrls)
-            setattr(context, 'principal', principal)
-        else:
-            # no kerberos ccache, use simple bind or external sasl
-            if autobind:
-                pent = pwd.getpwuid(os.geteuid())
-                self.external_bind(pent.pw_name,
+        elif autobind != AUTOBIND_DISABLED and os.getegid() == 0 and ldapi:
+            try:
+                pw_name = pwd.getpwuid(os.geteuid()).pw_name
+                self.external_bind(pw_name,
                                    server_controls=serverctrls,
                                    client_controls=clientctrls)
+            except errors.NotFound:
+                if autobind == AUTOBIND_ENABLED:
+                    # autobind was required and failed, raise
+                    # exception that it failed
+                    raise
+        else:
+            if ldapi:
+                with self.error_handler():
+                    conn.set_option(_ldap.OPT_HOST_NAME, self.api.env.host)
+            if ccache is None:
+                os.environ.pop('KRB5CCNAME', None)
             else:
-                self.simple_bind(bind_dn, bind_pw,
-                                 server_controls=serverctrls,
-                                 client_controls=clientctrls)
+                os.environ['KRB5CCNAME'] = ccache
+
+            principal = krb_utils.get_principal(ccache_name=ccache)
+
+            self.gssapi_bind(server_controls=serverctrls,
+                             client_controls=clientctrls)
+            setattr(context, 'principal', principal)
 
         return conn
 
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index ead830def127492cecda09cb1dc7964c314f2912..a232b4d11f1f55f10d38a6af4521d3c5fdeb5ab8 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -30,7 +30,8 @@ import datetime
 import urlparse
 import json
 import traceback
-from krbV import Krb5Error
+import gssapi
+import time
 
 import ldap.controls
 from pyasn1.type import univ, namedtype
@@ -54,8 +55,8 @@ from ipalib.session import (
     default_max_session_duration, krbccache_dir, krbccache_prefix)
 from ipalib.backend import Backend
 from ipalib.krb_utils import (
-    KRB5_CCache, krb_ticket_expiration_threshold, krb5_format_principal_name,
-    krb5_format_service_principal_name)
+    krb_ticket_expiration_threshold, krb5_format_principal_name,
+    krb5_format_service_principal_name, get_credentials, get_credentials_if_valid)
 from ipapython import ipautil
 from ipaplatform.paths import paths
 from ipapython.version import VERSION
@@ -593,8 +594,8 @@ class KerberosSession(object):
         session_data['ccache_data'] = load_ccache_data(ccache_name)
 
         # Set when the session will expire
-        cc = KRB5_CCache(ccache_name)
-        endtime = cc.endtime(self.api.env.host, self.api.env.realm)
+        creds = get_credentials(ccache_name=ccache_name)
+        endtime = creds.lifetime + time.time()
         self.update_session_expiration(session_data, endtime)
 
         # Store the session data now that it's been updated with the ccache
@@ -789,15 +790,15 @@ class jsonserver_session(jsonserver, KerberosSession):
         ipa_ccache_name = bind_ipa_ccache(ccache_data)
 
         # Redirect to login if Kerberos credentials are expired
-        cc = KRB5_CCache(ipa_ccache_name)
-        if not cc.valid(self.api.env.host, self.api.env.realm):
+        creds = get_credentials_if_valid(ccache_name=ipa_ccache_name)
+        if not creds:
             self.debug('ccache expired, deleting session, need login')
             # The request is finished with the ccache, destroy it.
             release_ipa_ccache(ipa_ccache_name)
             return self.need_login(start_response)
 
         # Update the session expiration based on the Kerberos expiration
-        endtime = cc.endtime(self.api.env.host, self.api.env.realm)
+        endtime = creds.lifetime + time.time()
         self.update_session_expiration(session_data, endtime)
 
         # Store the session data in the per-thread context
@@ -962,7 +963,7 @@ class login_password(Backend, KerberosSession, HTTP_Status):
 
         try:
             ipautil.kinit_keytab(armor_principal, paths.IPA_KEYTAB, armor_path)
-        except Krb5Error as e:
+        except gssapi.exceptions.GSSError as e:
             raise CCacheError(str(e))
 
         # Format the user as a kerberos principal
@@ -1229,15 +1230,15 @@ class xmlserver_session(xmlserver, KerberosSession):
         ipa_ccache_name = bind_ipa_ccache(ccache_data)
 
         # Redirect to /ipa/xml if Kerberos credentials are expired
-        cc = KRB5_CCache(ipa_ccache_name)
-        if not cc.valid(self.api.env.host, self.api.env.realm):
+        creds = get_credentials_if_valid(ccache_name=ipa_ccache_name)
+        if not creds:
             self.debug('xmlserver_session.__call_: ccache expired, deleting session, need login')
             # The request is finished with the ccache, destroy it.
             release_ipa_ccache(ipa_ccache_name)
             return self.need_login(start_response)
 
         # Update the session expiration based on the Kerberos expiration
-        endtime = cc.endtime(self.api.env.host, self.api.env.realm)
+        endtime = creds.lifetime + time.time()
         self.update_session_expiration(session_data, endtime)
 
         # Store the session data in the per-thread context
diff --git a/ipatests/test_cmdline/cmdline.py b/ipatests/test_cmdline/cmdline.py
index a7ed677937cbd3b14c365d045306b2fdb2f30e8b..2f51248a1a099a605f74ad7b4e2206cb2bff4636 100644
--- a/ipatests/test_cmdline/cmdline.py
+++ b/ipatests/test_cmdline/cmdline.py
@@ -22,7 +22,6 @@ Base class for all cmdline tests
 """
 
 import nose
-import krbV
 import distutils.spawn
 import os
 
@@ -33,11 +32,9 @@ from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
 from ipaserver.plugins.ldap2 import ldap2
 
 # See if our LDAP server is up and we can talk to it over GSSAPI
-ccache = krbV.default_context().default_ccache()
-
 try:
     conn = ldap2(api)
-    conn.connect(ccache=ccache)
+    conn.connect()
     conn.disconnect()
     server_available = True
 except errors.DatabaseError:
diff --git a/ipatests/test_cmdline/test_ipagetkeytab.py b/ipatests/test_cmdline/test_ipagetkeytab.py
index bc948bf09a68b9017a4101fba6603e68c096571c..2fd628df27206d5790e86f76d10aea97aef4f82f 100644
--- a/ipatests/test_cmdline/test_ipagetkeytab.py
+++ b/ipatests/test_cmdline/test_ipagetkeytab.py
@@ -26,10 +26,10 @@ from cmdline import cmdline_test
 from ipalib import api
 from ipalib import errors
 import tempfile
-from ipapython import ipautil
+from ipapython import ipautil, ipaldap
 import nose
 import tempfile
-import krbV
+import gssapi
 from ipaserver.plugins.ldap2 import ldap2
 from ipapython.dn import DN
 
@@ -37,21 +37,18 @@ def use_keytab(principal, keytab):
     try:
         tmpdir = tempfile.mkdtemp(prefix = "tmp-")
         ccache_file = 'FILE:%s/ccache' % tmpdir
-        krbcontext = krbV.default_context()
-        principal = str(principal)
-        keytab = krbV.Keytab(name=keytab, context=krbcontext)
-        principal = krbV.Principal(name=principal, context=krbcontext)
+        name = gssapi.Name(principal, gssapi.NameType.kerberos_principal)
+        store = {'ccache': ccache_file,
+                 'client_keytab': keytab}
         os.environ['KRB5CCNAME'] = ccache_file
-        ccache = krbV.CCache(name=ccache_file, context=krbcontext, primary_principal=principal)
-        ccache.init(principal)
-        ccache.init_creds_keytab(keytab=keytab, principal=principal)
+        gssapi.Credentials(name=name, usage='initiate', store=store)
         conn = ldap2(api)
-        conn.connect(ccache=ccache)
+        conn.connect(autobind=ipaldap.AUTOBIND_DISABLED)
         conn.disconnect()
-    except krbV.Krb5Error, e:
-        raise StandardError('Unable to bind to LDAP. Error initializing principal %s in %s: %s' % (principal.name, keytab, str(e)))
+    except gssapi.exceptions.GSSError as e:
+        raise StandardError('Unable to bind to LDAP. Error initializing principal %s in %s: %s' % (principal, keytab, str(e)))
     finally:
-        del os.environ['KRB5CCNAME']
+        os.environ.pop('KRB5CCNAME', None)
         if tmpdir:
             shutil.rmtree(tmpdir)
 
diff --git a/ipatests/test_xmlrpc/test_dns_plugin.py b/ipatests/test_xmlrpc/test_dns_plugin.py
index 7e5058b0957b56b501a8d6ea9216ab4478a17ab4..2883c97b4074ce99878c03db40a0a15807f06d38 100644
--- a/ipatests/test_xmlrpc/test_dns_plugin.py
+++ b/ipatests/test_xmlrpc/test_dns_plugin.py
@@ -33,7 +33,6 @@ try:
 except ImportError:
     have_ldap2 = False
 else:
-    import krbV
     have_ldap2 = True
 
 _dns_zone_record = DNSName(u'@')
@@ -401,7 +400,7 @@ def _get_nameservers_ldap(conn):
 
 def get_nameservers():
         ldap = ldap2(api)
-        ldap.connect(ccache=krbV.default_context().default_ccache())
+        ldap.connect()
         nameservers = [normalize_zone(x) for x in _get_nameservers_ldap(ldap)]
         return nameservers
 
diff --git a/ipatests/test_xmlrpc/test_netgroup_plugin.py b/ipatests/test_xmlrpc/test_netgroup_plugin.py
index 64cc422102d581728567d4fc35fc0cee96487718..d5ba5181ed55f2d57da1e525793064cfdc9143ce 100644
--- a/ipatests/test_xmlrpc/test_netgroup_plugin.py
+++ b/ipatests/test_xmlrpc/test_netgroup_plugin.py
@@ -22,7 +22,6 @@ Test the `ipalib/plugins/netgroup.py` module.
 """
 
 import nose
-import krbV
 
 from ipalib import api
 from ipalib import errors
@@ -36,9 +35,6 @@ from ipatests.test_xmlrpc.test_user_plugin import get_user_result
 # Global so we can save the value between tests
 netgroup_dn = None
 
-# See if our LDAP server is up and we can talk to it over GSSAPI
-ccache = krbV.default_context().default_ccache().name
-
 netgroup1 = u'netgroup1'
 netgroup2 = u'netgroup2'
 netgroup_single = u'a'
@@ -1298,7 +1294,7 @@ class test_netgroup(Declarative):
 #        # Do an LDAP query to the compat area and verify that the entry
 #        # is correct
 #        conn = ldap2(api)
-#        conn.connect(ccache=ccache)
+#        conn.connect()
 #        try:
 #            entries = conn.find_entries('cn=%s' % self.ng_cn,
 #                      base_dn='cn=ng,cn=compat,%s' % api.env.basedn)
diff --git a/ipatests/test_xmlrpc/test_permission_plugin.py b/ipatests/test_xmlrpc/test_permission_plugin.py
index c899c428edfcd19c2e7f538cdc38b693e11c8715..65977c1bb29c5f740a91f06229cea9b307c4dc10 100644
--- a/ipatests/test_xmlrpc/test_permission_plugin.py
+++ b/ipatests/test_xmlrpc/test_permission_plugin.py
@@ -37,7 +37,6 @@ try:
 except ImportError:
     have_ldap2 = False
 else:
-    import krbV
     have_ldap2 = True
 
 permission1 = u'testperm'
@@ -3175,7 +3174,7 @@ class test_managed_permissions(Declarative):
     def add_managed_permission(self):
         """Add a managed permission and the corresponding ACI"""
         ldap = ldap2(api)
-        ldap.connect(ccache=krbV.default_context().default_ccache())
+        ldap.connect()
 
         result = api.Command.permission_add(permission1, type=u'user',
                                             ipapermright=u'write',
diff --git a/lite-server.py b/lite-server.py
index 99089b00f9a9cc4c54a227c3aff55c7357ba2428..0e867915f19e16801556b4362e53f330da365f4e 100755
--- a/lite-server.py
+++ b/lite-server.py
@@ -37,13 +37,27 @@ from paste import httpserver
 import paste.gzipper
 from paste.urlmap import URLMap
 from ipalib import api
+from subprocess import check_output, CalledProcessError
+import re
+
+# Ugly hack for test purposes only. GSSAPI has no way to get default ccache
+# name, but we don't need it outside test server
+def get_default_ccache_name():
+    try:
+        out = check_output(['klist'])
+    except CalledProcessError:
+        raise RuntimeError("Default ccache not found. Did you kinit?")
+    match = re.match(r'^Ticket cache:\s*(\S+)', out)
+    if not match:
+        raise RuntimeError("Cannot obtain ccache name")
+    return match.group(1)
 
 
 class KRBCheater(object):
     def __init__(self, app):
         self.app = app
         self.url = app.url
-        self.ccname = api.Backend.krb.default_ccname()
+        self.ccname = get_default_ccache_name()
 
     def __call__(self, environ, start_response):
         environ['KRB5CCNAME'] = self.ccname
diff --git a/make-lint b/make-lint
index 0447985303f485a014fecf7d17d0b1c7eb6137bd..380e8c86d039be0351e2fefa3758194aa2397e12 100755
--- a/make-lint
+++ b/make-lint
@@ -50,7 +50,6 @@ class IPATypeChecker(TypeChecker):
     # 'class or module': ['generated', 'properties']
     ignore = {
         # Python standard library & 3rd party classes
-        'krbV.Principal': ['name'],
         'socket._socketobject': ['sendall'],
         # should be 'subprocess.Popen'
         '.Popen': ['stdin', 'stdout', 'stderr', 'pid', 'returncode', 'poll',
@@ -68,7 +67,6 @@ class IPATypeChecker(TypeChecker):
         'ipalib.base.NameSpace': ['add', 'mod', 'del', 'show', 'find'],
         'ipalib.cli.Collector': ['__options'],
         'ipalib.config.Env': ['*'],
-        'ipalib.krb_utils.KRB5_CCache': LOGGING_ATTRS,
         'ipalib.parameters.Param': ['cli_name', 'cli_short_name', 'label',
             'default', 'doc', 'required', 'multivalue', 'primary_key',
             'normalizer', 'default_from', 'autofill', 'query', 'attribute',
@@ -261,7 +259,7 @@ Errors were found during the static code check.
             for mod in sorted(linter.missing):
                 print >> sys.stderr, "    " + mod
             print >> sys.stderr, """
-Please make sure all of the required and optional (python-krbV, python-rhsm)
+Please make sure all of the required and optional (python-gssapi, python-rhsm)
 python packages are installed.
 """
 
-- 
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