summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--BUILD.txt2
-rwxr-xr-xdaemons/dnssec/ipa-dnskeysync-replica4
-rwxr-xr-xdaemons/dnssec/ipa-ods-exporter4
-rwxr-xr-xdoc/examples/python-api.py4
-rw-r--r--freeipa.spec.in6
-rwxr-xr-xinstall/oddjob/com.redhat.idm.trust-fetch-domains88
-rwxr-xr-xinstall/tools/ipa-adtrust-install16
-rwxr-xr-xinstall/tools/ipa-csreplica-manage5
-rwxr-xr-xinstall/tools/ipa-replica-manage7
-rw-r--r--ipa-client/ipa-client.spec.in2
-rwxr-xr-xipa-client/ipa-install/ipa-client-automount10
-rwxr-xr-xipa-client/ipa-install/ipa-client-install8
-rw-r--r--ipalib/krb_utils.py333
-rw-r--r--ipalib/plugins/kerberos.py125
-rw-r--r--ipalib/plugins/passwd.py6
-rw-r--r--ipalib/plugins/vault.py7
-rw-r--r--ipalib/rpc.py9
-rw-r--r--ipalib/util.py12
-rw-r--r--ipapython/config.py11
-rw-r--r--ipapython/ipautil.py28
-rw-r--r--ipaserver/install/ipa_cacert_manage.py7
-rw-r--r--ipaserver/install/ipa_ldap_updater.py4
-rw-r--r--ipaserver/install/ipa_otptoken_import.py7
-rw-r--r--ipaserver/install/ipa_winsync_migrate.py10
-rw-r--r--ipaserver/install/ldapupdate.py10
-rw-r--r--ipaserver/install/schemaupdate.py4
-rw-r--r--ipaserver/install/server/upgrade.py3
-rw-r--r--ipaserver/plugins/join.py13
-rw-r--r--ipaserver/plugins/ldap2.py60
-rw-r--r--ipaserver/rpcserver.py25
-rw-r--r--ipatests/test_cmdline/cmdline.py5
-rw-r--r--ipatests/test_cmdline/test_ipagetkeytab.py23
-rw-r--r--ipatests/test_xmlrpc/test_dns_plugin.py3
-rw-r--r--ipatests/test_xmlrpc/test_netgroup_plugin.py6
-rw-r--r--ipatests/test_xmlrpc/test_permission_plugin.py3
-rwxr-xr-xlite-server.py16
-rwxr-xr-xmake-lint4
37 files changed, 245 insertions, 645 deletions
diff --git a/BUILD.txt b/BUILD.txt
index 53012b14d..4507fa357 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/daemons/dnssec/ipa-dnskeysync-replica b/daemons/dnssec/ipa-dnskeysync-replica
index b80b38962..d21626808 100755
--- a/daemons/dnssec/ipa-dnskeysync-replica
+++ b/daemons/dnssec/ipa-dnskeysync-replica
@@ -12,7 +12,7 @@ from binascii import hexlify
from datetime import datetime
import dns.dnssec
import fcntl
-from krbV import Krb5Error
+from gssapi.exceptions import GSSError
import logging
import os
from pprint import pprint
@@ -146,7 +146,7 @@ ccache_filename = os.path.join(WORKDIR, 'ipa-dnskeysync-replica.ccache')
try:
ipautil.kinit_keytab(PRINCIPAL, paths.IPA_DNSKEYSYNCD_KEYTAB,
ccache_filename, attempts=5)
-except Krb5Error as e:
+except GSSError as e:
log.critical('Kerberos authentication failed: %s', e)
sys.exit(1)
diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter
index 4d5423797..e7d30014e 100755
--- a/daemons/dnssec/ipa-ods-exporter
+++ b/daemons/dnssec/ipa-ods-exporter
@@ -20,7 +20,7 @@ from datetime import datetime
import dateutil.tz
import dns.dnssec
import fcntl
-from krbV import Krb5Error
+from gssapi.exceptions import GSSError
import logging
import os
import subprocess
@@ -487,7 +487,7 @@ ccache_name = os.path.join(WORKDIR, 'ipa-ods-exporter.ccache')
try:
ipautil.kinit_keytab(PRINCIPAL, paths.IPA_ODS_EXPORTER_KEYTAB, ccache_name,
attempts=5)
-except Krb5Error as e:
+except GSSError as e:
log.critical('Kerberos authentication failed: %s', e)
sys.exit(1)
diff --git a/doc/examples/python-api.py b/doc/examples/python-api.py
index 805925f26..215bb9153 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 46f348e2a..4f902bbea 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.2
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.2
Requires: python-dns >= 1.11.1
Requires: libsss_autofs
Requires: autofs
@@ -287,7 +286,6 @@ Summary: IPA administrative tools
Group: System Environment/Base
Requires: %{name}-python = %{version}-%{release}
Requires: %{name}-client = %{version}-%{release}
-Requires: python-krbV
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 6a2171d5f..d19e06f12 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",
@@ -127,17 +104,21 @@ 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
+have_ccache = False
+try:
+ cred = kinit_keytab(principal, keytab_name, ccache_name)
+ if cred.lifetime > 0:
+ have_ccache = True
+except gssapi.exceptions.ExpiredCredentialsError:
+ pass
+if not have_ccache:
+ # 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)
# Retrieve own NetBIOS name and trusted forest's name.
# We use script's input to retrieve the trusted forest's name to sanitize input
@@ -159,32 +140,25 @@ 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)
- else:
- 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
-except krbV.Krb5Error as e:
+ have_ccache = False
+ try:
+ # The keytab may have stale key material (from older trust-add run)
+ cred = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
+ if cred.lifetime > 0:
+ have_ccache = True
+ except gssapi.exceptions.ExpiredCredentialsError:
+ pass
+ if not have_ccache:
+ 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)
-
-try:
- # 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
-except krbV.Krb5Error as e:
- 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 a3037440c..4d0e5707e 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 as 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 as e:
sys.exit("Outdated Kerberos credentials. Use kdestroy and kinit to update your ticket")
except errors.DatabaseError as 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.partition('@')[0].partition('/')[0])['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 3a5c78aa4..eec8bb2c8 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 1c9c7d32c..f26c6ab60 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
@@ -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 686259ad2..4413937bb 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 0739a2e6b..4abc853dc 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
@@ -427,15 +427,14 @@ def main():
print "Location: %s" % options.location
root_logger.debug('Using automount location %s' % options.location)
- # Verify that the location is valid
- (ccache_fd, ccache_name) = tempfile.mkstemp()
- os.close(ccache_fd)
+ ccache_dir = tempfile.mkdtemp()
+ ccache_name = os.path.join(ccache_dir, 'ccache')
try:
try:
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:
@@ -457,6 +456,7 @@ def main():
sys.exit("Cannot connect to the server due to generic error: %s" % str(e))
finally:
os.remove(ccache_name)
+ os.rmdir(ccache_dir)
if not options.unattended and not ipautil.user_input("Continue to configure the system with these values?", False):
sys.exit("Installation aborted")
diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index c2131ffb6..9352b0049 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -31,8 +31,8 @@ try:
from ConfigParser import RawConfigParser
from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError
import shutil
- from krbV import Krb5Error
import dns
+ import gssapi
import nss.nss as nss
import SSSDConfig
@@ -2618,7 +2618,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)
@@ -2698,7 +2698,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
@@ -2745,7 +2745,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 19cd0ad79..db1cffc1e 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
-#-------------------------------------------------------------------------------
-
-# Kerberos constants, should be defined in krbV, but aren't
-KRB5_GC_CACHED = 0x2
+from ipalib import errors
-# 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):
- '''
- 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.
+def get_credentials(name=None, ccache_name=None):
'''
+ Obtains GSSAPI credentials with given principal name from ccache. When no
+ principal name specified, it retrieves the default one for given
+ credentials cache.
- 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 as 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 as 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 as 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 as 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 as 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 as e:
- raise e
- except Exception as 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 as e:
- return False
- except Exception as 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:
+ 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:
- host
- ldap server
- realm
- kerberos realm
- :returns:
- UNIX timestamp value.
- '''
+ :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)
- 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
+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.
- 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
+ :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)
+ if creds.lifetime > 0:
+ return creds
+ return None
+ except gssapi.exceptions.ExpiredCredentialsError:
+ return None
diff --git a/ipalib/plugins/kerberos.py b/ipalib/plugins/kerberos.py
deleted file mode 100644
index 3ed6d7671..000000000
--- a/ipalib/plugins/kerberos.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# Authors:
-# Jason Gerard DeRose <jderose@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 'admin@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 'admin@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 f5fc14d51..a4f791c1b 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 6a07a76b5..18436e399 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
@@ -640,7 +639,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':
@@ -1239,7 +1238,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']
@@ -1508,7 +1507,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 04b8d01d9..9d0fc8f7b 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 0d5f85040..4a75b820a 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 8b6b5ac93..d586d66d6 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 c3ffb1d5c..d959bb369 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:
@@ -1206,8 +1211,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)
@@ -1218,18 +1223,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 34a931d1a..c991cafa1 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 2c4f28af4..8321c20a3 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 386ca4273..ae89f7e07 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 097b8c806..75d1dbe31 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
@@ -321,12 +321,10 @@ 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 as e:
- sys.exit("Must have Kerberos credentials to migrate Winsync users.")
+ except gssapi.exceptions.GSSError as e:
+ sys.exit("Must have Kerberos credentials to migrate Winsync users. Error: %s" % e)
except errors.ACIError as e:
sys.exit("Outdated Kerberos credentials. Use kdestroy and kinit to update your ticket.")
except errors.DatabaseError as e:
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 1f3aca542..0444327aa 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 03edb6307..f98d0e949 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 f8a4ff282..cb92250e4 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -9,7 +9,6 @@ import pwd
import fileinput
import ConfigParser
import sys
-import krbV
from ipalib import api
import SSSDConfig
@@ -1567,7 +1566,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 3b668053c..7342117e7 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 68feee4f0..acaf45fdd 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 8fa097344..df75d98bb 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 0ae8cc079..e41b027a3 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 2b99c268e..d9ab0daaa 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 as 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 caad00de3..f0b8edaa1 100644
--- a/ipatests/test_xmlrpc/test_dns_plugin.py
+++ b/ipatests/test_xmlrpc/test_dns_plugin.py
@@ -34,7 +34,6 @@ try:
except ImportError:
have_ldap2 = False
else:
- import krbV
have_ldap2 = True
_dns_zone_record = DNSName(u'@')
@@ -402,7 +401,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 afe0c617d..10553c21f 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 2d1a7d5e7..971d0e6cb 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 99089b00f..0e867915f 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 044798530..380e8c86d 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.
"""