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

Simo Sorce ssorce at redhat.com
Wed Jul 22 13:47:34 UTC 2015


Comments inline.

----- Original Message -----
> From: "Michael Simacek" <msimacek at redhat.com>
> To: freeipa-devel at redhat.com
> Sent: Tuesday, July 21, 2015 8:02:26 AM
> Subject: [Freeipa-devel] [PATCH] Port from python-kerberos library to	python-gssapi
> 
> 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

Please do not use the raw api unless you have no other option.
Use the high level api, also do not refernce a member while instantiating a class.
Instantiate, then reference please, we want readable code.

> +        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

Same as above.
Create a credential and inquire it with the high level api

>          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
> 
> --
> 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
> 

-- 
Simo Sorce * Red Hat, Inc. * New York




More information about the Freeipa-devel mailing list