Skip to content

Commit

Permalink
Implement support for GSSAPI extension RFC 4178
Browse files Browse the repository at this point in the history
RFC 4178 provides two support API calls that enable the caller to
manipulate the set of acceptable security mechanisms used in SPNEGO
protocol; for the given credentials, the gss_get_neg_mechs call is
used to indicate the current set of security mechanisms available
for negotiation, and the gss_set_neg_mechs call is used to specify
the set of security mechanisms avaiable for negotiation. Since
gss_get_neg_mechs is not implemented by MIT krb5, we are only
implementing the raw interface for the latter call. Note that
although RFC 4178 did not specify that the mech_set argument cannot
be an empty set, we are forcing it to be non empty in the low-level
API here since passing an empty set will always trigger an error in
MIT krb5 implementation.
  • Loading branch information
tengcm2015 committed Jun 6, 2019
1 parent b6efe72 commit 8f77bf7
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
6 changes: 6 additions & 0 deletions gssapi/raw/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@
except ImportError:
pass

# optional RFC 4178 support
try:
from gssapi.raw.ext_rfc4178 import * # noqa
except ImportError:
pass

# optional RFC 5587 support
try:
from gssapi.raw.ext_rfc5587 import * # noqa
Expand Down
48 changes: 48 additions & 0 deletions gssapi/raw/ext_rfc4178.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
GSSAPI="BASE" # This ensures that a full module is generated by Cython

from gssapi.raw.cython_types cimport *
from gssapi.raw.cython_converters cimport c_get_mech_oid_set
from gssapi.raw.creds cimport Creds

from gssapi.raw.misc import GSSError

cdef extern from "python_gssapi_ext.h":
OM_uint32 gss_set_neg_mechs(
OM_uint32 *minor_status,
gss_cred_id_t cred_handle,
const gss_OID_set mech_set) nogil


def set_neg_mechs(Creds cred_handle not None, mech_set not None):
"""
set_neg_mechs(cred_handle not None, mech_set not None)
Specify the set of security mechanisms that may be negotiated with
the credential identified by cred_handle.
If more than one mechanism is specified in mech_set, the order in
which those mechanisms are specified implies a relative preference.
Args:
cred_handle (Creds): credentials to set negotiable mechanisms for
mech_set ([MechType]): negotiable mechanisms to be set
Returns:
None
Raises:
GSSError
"""

cdef gss_OID_set negotiable_mechs = c_get_mech_oid_set(mech_set)

cdef OM_uint32 maj_stat, min_stat

with nogil:
maj_stat = gss_set_neg_mechs(&min_stat, cred_handle.raw_creds,
negotiable_mechs)

cdef OM_uint32 tmp_min_stat
gss_release_oid_set(&tmp_min_stat, &negotiable_mechs)

if maj_stat == GSS_S_COMPLETE:
return None
else:
raise GSSError(maj_stat, min_stat)
61 changes: 61 additions & 0 deletions gssapi/tests/test_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,67 @@ def test_sasl_names(self):
cmp_mech.shouldnt_be_none()
cmp_mech.should_be(mech)

@ktu.gssapi_extension_test('rfc4178', 'Negotiation Mechanism')
def test_set_neg_mechs(self):
all_mechs = gb.indicate_mechs()
spnego_mech = gb.OID.from_int_seq("1.3.6.1.5.5.2")
krb5_mech = gb.OID.from_int_seq("1.2.840.113554.1.2.2")
ntlm_mech = gb.OID.from_int_seq("1.3.6.1.4.1.311.2.2.10")

server_name = gb.import_name(TARGET_SERVICE_NAME,
gb.NameType.hostbased_service)

username = gb.import_name(name=b"user",
name_type=gb.NameType.user)
krb5_client_creds = gb.acquire_cred(None, usage='initiate',
mechs=all_mechs).creds
ntlm_client_creds = gb.acquire_cred_with_password(
name=username,
password=b'password',
mechs=all_mechs).creds
server_creds = gb.acquire_cred(server_name, usage='accept',
mechs=all_mechs).creds

neg_resp = gb.set_neg_mechs(server_creds, [ntlm_mech])
neg_resp.should_be_none()

client_ctx_resp = gb.init_sec_context(server_name,
creds=ntlm_client_creds,
mech=spnego_mech)
client_token = client_ctx_resp.token

server_ctx_resp = gb.accept_sec_context(client_token,
acceptor_creds=server_creds)
server_ctx_resp.shouldnt_be_none()

client_ctx_resp = gb.init_sec_context(server_name,
creds=krb5_client_creds,
mech=spnego_mech)
client_token = client_ctx_resp.token

gb.accept_sec_context.should_raise(gb.GSSError, client_token,
acceptor_creds=server_creds)

neg_resp = gb.set_neg_mechs(server_creds, [krb5_mech])
neg_resp.should_be_none()

client_ctx_resp = gb.init_sec_context(server_name,
creds=krb5_client_creds,
mech=spnego_mech)
client_token = client_ctx_resp.token

server_ctx_resp = gb.accept_sec_context(client_token,
acceptor_creds=server_creds)
server_ctx_resp.shouldnt_be_none()

client_ctx_resp = gb.init_sec_context(server_name,
creds=ntlm_client_creds,
mech=spnego_mech)
client_token = client_ctx_resp.token

gb.accept_sec_context.should_raise(gb.GSSError, client_token,
acceptor_creds=server_creds)

@ktu.gssapi_extension_test('ggf', 'Global Grid Forum')
@ktu.gssapi_extension_test('s4u', 'S4U')
@ktu.krb_minversion_test('1.16',
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ def gssapi_modules(lst):
main_file('chan_bindings'),
extension_file('s4u', 'gss_acquire_cred_impersonate_name'),
extension_file('cred_store', 'gss_store_cred_into'),
extension_file('rfc4178', 'gss_set_neg_mechs'),
extension_file('rfc5587', 'gss_indicate_mechs_by_attrs'),
extension_file('rfc5588', 'gss_store_cred'),
extension_file('rfc5801', 'gss_inquire_saslname_for_mech'),
Expand Down

0 comments on commit 8f77bf7

Please sign in to comment.