[Freeipa-devel] [PATCH] Port from python-kerberos library to python-gssapi

Michael Simacek msimacek at redhat.com
Tue Jul 21 12:02:26 UTC 2015


Hi,

This is a first part of my effort to port FreeIPA from Python3-incompatible
Kerberos libraries to python-gssapi. This patch should replace python-kerberos
with python-gssapi (both use C GSSAPI behind the scenes).

--
Michael Simacek


>From bca55a6bd9cdb9cdea9d81b55cfdbc2c1279f031 Mon Sep 17 00:00:00 2001
From: Michael Simacek <msimacek at redhat.com>
Date: Thu, 16 Jul 2015 18:22:00 +0200
Subject: [PATCH] Port from python-kerberos library to python-gssapi

kerberos library doesn't support Python 3 and probably never will.
python-gssapi library is Python 3 compatible.
---
 BUILD.txt            |  2 +-
 freeipa.spec.in      |  2 +-
 ipalib/rpc.py        | 42 +++++++++++++++++++++---------------------
 ipalib/util.py       | 14 +++++++-------
 ipapython/ipautil.py | 17 -----------------
 5 files changed, 30 insertions(+), 47 deletions(-)

diff --git a/BUILD.txt b/BUILD.txt
index 6a28beb..53012b1 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-kerberos \
+python-setuptools python-krbV 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/freeipa.spec.in b/freeipa.spec.in
index fef20e1..5e10022 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -72,7 +72,7 @@ BuildRequires:  python-krbV
 BuildRequires:  python-nss
 BuildRequires:  python-cryptography
 BuildRequires:  python-netaddr
-BuildRequires:  python-kerberos >= 1.1-14
+BuildRequires:  python-gssapi >= 1.1.1
 BuildRequires:  python-rhsm
 BuildRequires:  pyOpenSSL
 BuildRequires:  pylint >= 1.0
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index 466b49a..bbedcc9 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -44,7 +44,7 @@ from urllib2 import urlparse
 
 from xmlrpclib import (Binary, Fault, DateTime, dumps, loads, ServerProxy,
         Transport, ProtocolError, MININT, MAXINT)
-import kerberos
+import gssapi
 from dns import resolver, rdatatype
 from dns.exception import DNSException
 from nss.error import NSPRError
@@ -510,24 +510,27 @@ class KerbTransport(SSLTransport):
     """
     Handles Kerberos Negotiation authentication to an XML-RPC server.
     """
-    flags = kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG
+    flags = gssapi.IntEnumFlagSet(gssapi.RequirementFlag,
+                                  [gssapi.RequirementFlag.mutual_authentication,
+                                   gssapi.RequirementFlag.out_of_sequence_detection])
 
     def _handle_exception(self, e, service=None):
-        (major, minor) = ipautil.get_gsserror(e)
-        if minor[1] == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
+        # kerberos library coerced error codes to signed, gssapi uses unsigned
+        minor = e.min_code - (1 << 32)
+        if minor == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
             raise errors.ServiceError(service=service)
-        elif minor[1] == KRB5_FCC_NOFILE:
+        elif minor == KRB5_FCC_NOFILE:
             raise errors.NoCCacheError()
-        elif minor[1] == KRB5KRB_AP_ERR_TKT_EXPIRED:
+        elif minor == KRB5KRB_AP_ERR_TKT_EXPIRED:
             raise errors.TicketExpired()
-        elif minor[1] == KRB5_FCC_PERM:
+        elif minor == KRB5_FCC_PERM:
             raise errors.BadCCachePerms()
-        elif minor[1] == KRB5_CC_FORMAT:
+        elif minor == KRB5_CC_FORMAT:
             raise errors.BadCCacheFormat()
-        elif minor[1] == KRB5_REALM_CANT_RESOLVE:
+        elif minor == KRB5_REALM_CANT_RESOLVE:
             raise errors.CannotResolveKDC()
         else:
-            raise errors.KerberosError(major=major, minor=minor)
+            raise errors.KerberosError(major=e.maj_code, minor=minor)
 
     def get_host_info(self, host):
         """
@@ -548,14 +551,9 @@ class KerbTransport(SSLTransport):
         service = "HTTP@" + host.split(':')[0]
 
         try:
-            (rc, vc) = kerberos.authGSSClientInit(service=service,
-                                                  gssflags=self.flags)
-        except kerberos.GSSError, e:
-            self._handle_exception(e)
-
-        try:
-            kerberos.authGSSClientStep(vc, "")
-        except kerberos.GSSError, e:
+            name = gssapi.Name(service, gssapi.NameType.hostbased_service)
+            response = gssapi.raw.init_sec_context(name, flags=self.flags).token
+        except gssapi.exceptions.GSSError as e:
             self._handle_exception(e, service=service)
 
         for (h, v) in extra_headers:
@@ -564,7 +562,7 @@ class KerbTransport(SSLTransport):
                 break
 
         extra_headers.append(
-            ('Authorization', 'negotiate %s' % kerberos.authGSSClientResponse(vc))
+            ('Authorization', 'negotiate %s' % base64.b64encode(response))
         )
 
         return (host, extra_headers, x509)
@@ -632,8 +630,10 @@ class DelegatedKerbTransport(KerbTransport):
     Handles Kerberos Negotiation authentication and TGT delegation to an
     XML-RPC server.
     """
-    flags = kerberos.GSS_C_DELEG_FLAG |  kerberos.GSS_C_MUTUAL_FLAG | \
-            kerberos.GSS_C_SEQUENCE_FLAG
+    flags = gssapi.IntEnumFlagSet(gssapi.RequirementFlag,
+                                  [gssapi.RequirementFlag.delegate_to_peer,
+                                   gssapi.RequirementFlag.mutual_authentication,
+                                   gssapi.RequirementFlag.out_of_sequence_detection])
 
 
 class RPCClient(Connectible):
diff --git a/ipalib/util.py b/ipalib/util.py
index 649a487..aea3ba9 100644
--- a/ipalib/util.py
+++ b/ipalib/util.py
@@ -63,15 +63,15 @@ def json_serialize(obj):
 
 def get_current_principal():
     try:
-        import kerberos
-        rc, vc = kerberos.authGSSClientInit("notempty")
-        rc = kerberos.authGSSClientInquireCred(vc)
-        username = kerberos.authGSSClientUserName(vc)
-        kerberos.authGSSClientClean(vc)
+        import gssapi
+        cred = gssapi.raw.acquire_cred(usage='initiate').creds
+        name = gssapi.raw.inquire_cred(cred, lifetime=False, usage=False,
+                                       mechs=False).name
+        username = gssapi.raw.display_name(name, name_type=False).name
         return unicode(username)
     except ImportError:
-        raise RuntimeError('python-kerberos is not available.')
-    except kerberos.GSSError, e:
+        raise RuntimeError('python-gssapi is not available.')
+    except gssapi.exceptions.GSSError:
         #TODO: do a kinit?
         raise errors.CCacheError()
 
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 88e8970..05a7eeb 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -783,23 +783,6 @@ def user_input(prompt, default = None, allow_empty = True):
                 return ret
 
 
-def get_gsserror(e):
-    """
-    A GSSError exception looks differently in python 2.4 than it does
-    in python 2.5. Deal with it.
-    """
-
-    try:
-       major = e[0]
-       minor = e[1]
-    except:
-       major = e[0][0]
-       minor = e[0][1]
-
-    return (major, minor)
-
-
-
 def host_port_open(host, port, socket_type=socket.SOCK_STREAM, socket_timeout=None):
     for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket_type):
         af, socktype, proto, canonname, sa = res
-- 
2.1.0




More information about the Freeipa-devel mailing list