Commit 62741002 authored by Jelmer Vernooij's avatar Jelmer Vernooij Committed by Philipp Hörist
Browse files

Fix GSSAPI support and switch to GSSAPI Python module

parent bd7195cb
Pipeline #6606 passed with stages
in 33 seconds
......@@ -11,6 +11,10 @@
- precis-i18n
- idna
## Optional Runtime Requirements
- python-gssapi (for GSSAPI authentication)
## Features
* List of [supported XEPs](https://dev.gajim.org/gajim/python-nbxmpp/-/wikis/Supported-XEPs-in-python-nbxmpp/)
......
......@@ -29,17 +29,16 @@ from nbxmpp.protocol import SASL_AUTH_MECHS
from nbxmpp.util import b64decode
from nbxmpp.util import b64encode
from nbxmpp.util import LogAdapter
from nbxmpp.const import GSSAPIState
from nbxmpp.const import StreamState
log = logging.getLogger('nbxmpp.auth')
try:
kerberos = __import__('kerberos')
KERBEROS_AVAILABLE = True
gssapi = __import__('gssapi')
GSSAPI_AVAILABLE = True
except ImportError:
KERBEROS_AVAILABLE = False
GSSAPI_AVAILABLE = False
class SASL:
......@@ -91,7 +90,7 @@ class SASL:
self._enabled_mechs.discard('SCRAM-SHA-256-PLUS')
# channel_binding_data = None
if not KERBEROS_AVAILABLE:
if not GSSAPI_AVAILABLE:
self._enabled_mechs.discard('GSSAPI')
available_mechs = features.get_mechs() & self._enabled_mechs
......@@ -156,9 +155,16 @@ class SASL:
elif chosen_mechanism == 'GSSAPI':
self._method = GSSAPI(self._client)
self._method.initiate(domain_based_name or
self._client.domain)
if domain_based_name:
hostname = domain_based_name
else:
hostname = self._client.domain
try:
self._method.initiate(hostname)
except AuthFail as error:
self._log.error(error)
self._abort_auth()
return
else:
self._log.error('Unknown auth mech')
......@@ -258,39 +264,41 @@ class ANONYMOUS:
class GSSAPI:
# See https://tools.ietf.org/html/rfc4752#section-3.1
_mechanism = 'GSSAPI'
def __init__(self, client):
self._client = client
self._gss_vc = None
self._state = GSSAPIState.STEP
def initiate(self, hostname):
self._gss_vc = kerberos.authGSSClientInit('xmpp@%s' % hostname)[1]
kerberos.authGSSClientStep(self._gss_vc, '')
response = kerberos.authGSSClientResponse(self._gss_vc)
service = gssapi.Name(
'xmpp@%s' % hostname, name_type=gssapi.NameType.hostbased_service)
try:
self.ctx = gssapi.SecurityContext(
name=service, usage="initiate",
flags=gssapi.RequirementFlag.integrity)
token = self.ctx.step()
except (gssapi.exceptions.GeneralError, gssapi.raw.misc.GSSError) as e:
raise AuthFail(e)
node = Node('auth',
attrs={'xmlns': Namespace.SASL, 'mechanism': 'GSSAPI'},
payload=(response or ''))
payload=b64encode(token))
self._client.send_nonza(node)
def response(self, server_message, *args, **kwargs):
server_message = b64decode(server_message, bytes)
if self._state == GSSAPIState.STEP:
rc = kerberos.authGSSClientStep(self._gss_vc, server_message)
if rc != kerberos.AUTH_GSS_CONTINUE:
self._state = GSSAPIState.WRAP
elif self._state == GSSAPIState.WRAP:
rc = kerberos.authGSSClientUnwrap(self._gss_vc, server_message)
response = kerberos.authGSSClientResponse(self._gss_vc)
rc = kerberos.authGSSClientWrap(
self._gss_vc,
response,
kerberos.authGSSClientUserName(self._gss_vc))
response = kerberos.authGSSClientResponse(self._gss_vc)
if not response:
response = ''
try:
if not self.ctx.complete:
output_token = self.ctx.step(server_message)
else:
result = self.ctx.unwrap(server_message)
# TODO(jelmer): Log result.message
data = b'\x00\x00\x00\x00' + bytes(self.ctx.initiator_name)
output_token = self.ctx.wrap(data, False).message
except (gssapi.exceptions.GeneralError, gssapi.raw.misc.GSSError) as e:
raise AuthFail(e)
response = b64encode(output_token)
node = Node('response',
attrs={'xmlns': Namespace.SASL},
payload=response)
......
......@@ -279,6 +279,7 @@ class Client(Observable):
def mechs(self):
return set(self._allowed_mechs or set(['SCRAM-SHA-256',
'SCRAM-SHA-1',
'GSSAPI',
# 'SCRAM-SHA-256-PLUS',
# 'SCRAM-SHA-1-PLUS',
'PLAIN']))
......
......@@ -21,10 +21,6 @@ from functools import total_ordering
from gi.repository import Gio
class GSSAPIState(IntEnum):
STEP = 0
WRAP = 1
class IqType(Enum):
GET = 'get'
......
......@@ -40,8 +40,8 @@ SASL_AUTH_MECHS = [
'SCRAM-SHA-256',
'SCRAM-SHA-1-PLUS',
'SCRAM-SHA-1',
'PLAIN',
'GSSAPI',
'PLAIN',
'EXTERNAL',
'ANONYMOUS',
]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment