Handle GSSAPI exceptions more gracefully

This commit is contained in:
Rob Crittenden 2009-04-13 18:01:58 -04:00
parent e6171404bf
commit a9387b48e6
3 changed files with 116 additions and 13 deletions

View File

@ -458,6 +458,85 @@ class ServiceError(KerberosError):
format = _('Service %(service)r not found in Kerberos database') format = _('Service %(service)r not found in Kerberos database')
class NoCCacheError(KerberosError):
"""
**1103** Raised when a client attempts to use Kerberos without a ccache.
For example:
>>> raise NoCCacheError()
Traceback (most recent call last):
...
NoCCacheError: No credentials cache found
"""
errno = 1103
format = _('No credentials cache found')
class TicketExpired(KerberosError):
"""
**1104** Raised when a client attempts to use an expired ticket
For example:
>>> raise TicketExpired()
Traceback (most recent call last):
...
TicketExpired: Ticket expired
"""
errno = 1104
format = _('Ticket expired')
class BadCCachePerms(KerberosError):
"""
**1105** Raised when a client has bad permissions on their ccache
For example:
>>> raise BadCCachePerms()
Traceback (most recent call last):
...
BadCCachePerms: Credentials cache permissions incorrect
"""
errno = 1105
format = _('Credentials cache permissions incorrect')
class BadCCacheFormat(KerberosError):
"""
**1106** Raised when a client has a misformated ccache
For example:
>>> raise BadCCacheFormat()
Traceback (most recent call last):
...
BadCCacheFormat: Bad format in credentials cache
"""
errno = 1106
format = _('Bad format in credentials cache')
class CannotResolveKDC(KerberosError):
"""
**1107** Raised when the KDC can't be resolved
For example:
>>> raise CannotResolveKDC()
Traceback (most recent call last):
...
CannotResolveKDC: Cannot resolve KDC for requested realm
"""
errno = 1107
format = _('Cannot resolve KDC for requested realm')
############################################################################## ##############################################################################
# 2000 - 2999: Authorization errors # 2000 - 2999: Authorization errors

View File

@ -34,15 +34,24 @@ from types import NoneType
import threading import threading
import socket import socket
import os import os
import errno
from xmlrpclib import Binary, Fault, dumps, loads, ServerProxy, Transport from xmlrpclib import Binary, Fault, dumps, loads, ServerProxy, Transport
import kerberos import kerberos
from ipalib.backend import Connectible from ipalib.backend import Connectible
from ipalib.errors2 import public_errors, PublicError, UnknownError, NetworkError from ipalib.errors2 import public_errors, PublicError, UnknownError, NetworkError
from ipalib import errors2 from ipalib import errors2
from ipalib.request import context from ipalib.request import context
from ipapython import ipautil
from OpenSSL import SSL from OpenSSL import SSL
import httplib import httplib
# Some Kerberos error definitions from krb5.h
KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN = (-1765328377L)
KRB5KRB_AP_ERR_TKT_EXPIRED = (-1765328352L)
KRB5_FCC_PERM = (-1765328190L)
KRB5_FCC_NOFILE = (-1765328189L)
KRB5_CC_FORMAT = (-1765328185L)
KRB5_REALM_CANT_RESOLVE = (-1765328164L)
def xml_wrap(value): def xml_wrap(value):
""" """
@ -304,6 +313,23 @@ class KerbTransport(SSLTransport):
Handles Kerberos Negotiation authentication to an XML-RPC server. Handles Kerberos Negotiation authentication to an XML-RPC server.
""" """
def _handle_exception(self, e, service=None):
(major, minor) = ipautil.get_gsserror(e)
if minor[1] == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
raise errors2.ServiceError(service=service)
elif minor[1] == KRB5_FCC_NOFILE:
raise errors2.NoCCacheError()
elif minor[1] == KRB5KRB_AP_ERR_TKT_EXPIRED:
raise errors2.TicketExpired()
elif minor[1] == KRB5_FCC_PERM:
raise errors2.BadCCachePerms()
elif minor[1] == KRB5_CC_FORMAT:
raise errors2.BadCCacheFormat()
elif minor[1] == KRB5_REALM_CANT_RESOLVE:
raise errors2.CannotResolveKDC()
else:
raise errors2.KerberosError(major=major, minor=minor)
def get_host_info(self, host): def get_host_info(self, host):
(host, extra_headers, x509) = SSLTransport.get_host_info(self, host) (host, extra_headers, x509) = SSLTransport.get_host_info(self, host)
@ -316,16 +342,12 @@ class KerbTransport(SSLTransport):
kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_MUTUAL_FLAG |
kerberos.GSS_C_SEQUENCE_FLAG) kerberos.GSS_C_SEQUENCE_FLAG)
except kerberos.GSSError, e: except kerberos.GSSError, e:
raise e # FIXME: raise a PublicError self._handle_exception(e)
try: try:
kerberos.authGSSClientStep(vc, "") kerberos.authGSSClientStep(vc, "")
except kerberos.GSSError, e: except kerberos.GSSError, e:
(major, minor) = e.args self._handle_exception(e, service=service)
if minor[1] == -1765328377:
raise errors2.ServiceError(service=service)
else:
raise e
extra_headers = [ extra_headers = [
('Authorization', 'negotiate %s' % kerberos.authGSSClientResponse(vc)) ('Authorization', 'negotiate %s' % kerberos.authGSSClientResponse(vc))

View File

@ -956,14 +956,16 @@ class ItemCompleter:
return items return items
def get_gsserror(e): def get_gsserror(e):
"""A GSSError exception looks differently in python 2.4 than it does """
in python 2.5, deal with it.""" A GSSError exception looks differently in python 2.4 than it does
in python 2.5. Deal with it.
"""
try: try:
primary = e[0] major = e[0]
secondary = e[1] minor = e[1]
except: except:
primary = e[0][0] major = e[0][0]
secondary = e[0][1] minor = e[0][1]
return (primary[0], secondary[0]) return (major, minor)