Skip to content

Commit

Permalink
Added support for GGF inquire cred and sec context
Browse files Browse the repository at this point in the history
  • Loading branch information
jborean93 committed Jan 11, 2018
1 parent beb69c9 commit 4b68958
Show file tree
Hide file tree
Showing 4 changed files with 208 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 @@ -119,3 +119,9 @@
from gssapi.raw.ext_rfc6680_comp_oid import * # noqa
except ImportError:
pass

# optional Global Grid Forum support
try:
from gssapi.raw.ext_ggf import * # noqa
except ImportError:
pass
114 changes: 114 additions & 0 deletions gssapi/raw/ext_ggf.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
GSSAPI="BASE" # This ensures that a full module is generated by Cython

from gssapi.raw.cython_types cimport *
from gssapi.raw.ext_buffer_sets cimport *
from gssapi.raw.cython_converters cimport c_get_mech_oid_set
from gssapi.raw.misc import GSSError
from gssapi.raw.oids cimport OID
from gssapi.raw.creds cimport Creds
from gssapi.raw.sec_contexts cimport SecurityContext

cdef extern from "python_gssapi_ext.h":

OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status,
const gss_cred_id_t cred_handle,
const gss_OID desired_object,
gss_buffer_set_t *data_set) nogil

OM_uint32 gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
const gss_ctx_id_t context_handle,
const gss_OID desired_object,
gss_buffer_set_t *data_set) nogil


def inquire_cred_by_oid(Creds cred_handle not None, OID mech not None):
"""
inquire_cred_by_oid(cred_handle, mech)
This method inspects a :class:`Creds` object for information
specific to a particular mechanism.
Args:
cred_handle (Creds): the security context to query
mech (OID): the desired mechanism
Returns:
list: A list of zero or more pieces of data corresponding to the
OID set
Raises:
GSS_ERROR
"""

cdef gss_buffer_set_t *data_set_ptr = NULL
cdef gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET
cdef OM_uint32 maj_stat, min_stat

data_set_ptr = &data_set

with nogil:
maj_stat = gss_inquire_cred_by_oid(&min_stat, cred_handle.raw_creds,
&mech.raw_oid, data_set_ptr)

if maj_stat == GSS_S_COMPLETE:
py_tokens = []

if data_set != GSS_C_NO_BUFFER_SET:
for i in range(data_set.count):
token = data_set.elements[i]
py_tokens.append(token.value[:token.length])

gss_release_buffer_set(&min_stat, &data_set)

return py_tokens
else:
raise GSSError(maj_stat, min_stat)


def inquire_sec_context_by_oid(SecurityContext context not None,
OID mech not None):
"""
inquire_sec_context_by_oid(context, mech)
This method inspects a :class:`SecurityContext` object for information
specific to a particular mechanism.
This method can be used with the GSS_KRB5_INQ_SSPI_SESSION_KEY_OID OID to
retrieve the required key that is used to derive the SMB/SAMBA signing and
encryption keys.
Args:
context (SecurityContext): the security context to query
mech (OID): the desired mechanism
Returns:
list: A list of zero or more pieces of data corresponding to the
OID set
Raises:
GSS_ERROR
"""

cdef gss_buffer_set_t *data_set_ptr = NULL
cdef gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET
cdef OM_uint32 maj_stat, min_stat

data_set_ptr = &data_set

with nogil:
maj_stat = gss_inquire_sec_context_by_oid(&min_stat, context.raw_ctx,
&mech.raw_oid, data_set_ptr)

if maj_stat == GSS_S_COMPLETE:
py_tokens = []

if data_set != GSS_C_NO_BUFFER_SET:
for i in range(data_set.count):
token = data_set.elements[i]
py_tokens.append(token.value[:token.length])

gss_release_buffer_set(&min_stat, &data_set)

return py_tokens
else:
raise GSSError(maj_stat, min_stat)
87 changes: 87 additions & 0 deletions gssapi/tests/test_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,93 @@ def test_sasl_names(self):
cmp_mech.shouldnt_be_none()
cmp_mech.should_be(mech)

@ktu.gssapi_extension_test('ggf', 'Global Grid Forum')
@ktu.gssapi_extension_test('s4u', 'S4U')
@ktu.krb_minversion_test('1.16',
'querying impersonator name of krb5 GSS '
'Credential using the '
'GSS_KRB5_GET_CRED_IMPERSONATOR OID')
def test_inquire_cred_by_oid_impersonator(self):
svc_princ = SERVICE_PRINCIPAL.decode("UTF-8")
self.realm.kinit(svc_princ, flags=['-k', '-f'])

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

client_token = gb.init_sec_context(target_name).token

# if our acceptor creds have a usage of both, we get
# s4u2proxy delegated credentials
server_creds = gb.acquire_cred(None, usage='both').creds
server_ctx_resp = gb.accept_sec_context(client_token,
acceptor_creds=server_creds)

server_ctx_resp.shouldnt_be_none()
server_ctx_resp.delegated_creds.shouldnt_be_none()
server_ctx_resp.delegated_creds.should_be_a(gb.Creds)

# GSS_KRB5_GET_CRED_IMPERSONATOR
oid = gb.OID.from_int_seq("1.2.840.113554.1.2.2.5.14")
info = gb.inquire_cred_by_oid(server_ctx_resp.delegated_creds, oid)

info.should_be_a(list)
info.shouldnt_be_empty()
info[0].should_be_a(bytes)
info[0].should_be(b"%s@%s" % (SERVICE_PRINCIPAL,
self.realm.realm.encode('utf-8')))

@ktu.gssapi_extension_test('ggf', 'Global Grid Forum')
def test_inquire_sec_context_by_oid(self):
target_name = gb.import_name(TARGET_SERVICE_NAME,
gb.NameType.hostbased_service)
ctx_resp1 = gb.init_sec_context(target_name)

server_name = gb.import_name(SERVICE_PRINCIPAL,
gb.NameType.kerberos_principal)
server_creds = gb.acquire_cred(server_name)[0]
server_resp = gb.accept_sec_context(ctx_resp1[3],
acceptor_creds=server_creds)
server_ctx = server_resp[0]
server_tok = server_resp[3]

client_resp2 = gb.init_sec_context(target_name,
context=ctx_resp1[0],
input_token=server_tok)
client_ctx = client_resp2[0]

# GSS_C_INQ_SSPI_SESSION_KEY
session_key_oid = gb.OID.from_int_seq("1.2.840.113554.1.2.2.5.5")

client_key = gb.inquire_sec_context_by_oid(client_ctx, session_key_oid)
server_key = gb.inquire_sec_context_by_oid(server_ctx, session_key_oid)

client_key.should_be_a(list)
client_key.shouldnt_be_empty()
server_key.should_be_a(list)
server_key.shouldnt_be_empty()
client_key.should_have_same_items_as(server_key)

@ktu.gssapi_extension_test('ggf', 'Global Grid Forum')
def test_inquire_sec_context_by_oid_should_raise_error(self):
target_name = gb.import_name(TARGET_SERVICE_NAME,
gb.NameType.hostbased_service)
ctx_resp1 = gb.init_sec_context(target_name)

server_name = gb.import_name(SERVICE_PRINCIPAL,
gb.NameType.kerberos_principal)
server_creds = gb.acquire_cred(server_name)[0]
server_resp = gb.accept_sec_context(ctx_resp1[3],
acceptor_creds=server_creds)

client_resp2 = gb.init_sec_context(target_name,
context=ctx_resp1[0],
input_token=server_resp[3])
client_ctx = client_resp2[0]

invalid_oid = gb.OID.from_int_seq("1.2.3.4.5.6.7.8.9")
gb.inquire_sec_context_by_oid.should_raise(gb.GSSError, client_ctx,
invalid_oid)


class TestIntEnumFlagSet(unittest.TestCase):
def test_create_from_int(self):
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ def gssapi_modules(lst):
extension_file('cred_imp_exp', 'gss_import_cred'),
extension_file('dce', 'gss_wrap_iov'),
extension_file('iov_mic', 'gss_get_mic_iov'),
extension_file('ggf', 'gss_inquire_sec_context_by_oid'),

# see ext_rfc6680_comp_oid for more information on this split
extension_file('rfc6680', 'gss_display_name_ext'),
Expand Down

0 comments on commit 4b68958

Please sign in to comment.