Skip to content

Commit

Permalink
Implement support for GSSAPI extension RFC 5587
Browse files Browse the repository at this point in the history
RFC 5587 provides extended mech inquiry calls to GSSAPI.
This adds the ability to indicate mechs by their
mech attrs, along with determining the attrs supported
by a mech. These calls are provided as a part of
the raw interface and are not exposed in the high-level
interface due to not having objects for mechs or attrs.

Signed-off-by: Alexander Scheel <ascheel@redhat.com>
  • Loading branch information
cipherboy committed Jul 18, 2017
1 parent 0be0230 commit 345fb85
Show file tree
Hide file tree
Showing 5 changed files with 242 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 5587 support
try:
from gssapi.raw.ext_rfc5587 import * # noqa
except ImportError:
pass

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

from gssapi.raw.cython_converters cimport c_get_mech_oid_set

from gssapi.raw.named_tuples import InquireAttrsResult, DisplayAttrResult
from gssapi.raw.misc import GSSError

cdef extern from "python_gssapi_ext.h":
OM_uint32 gss_indicate_mechs_by_attrs(
OM_uint32 *minor_status,
const gss_OID_set desired_mech_attrs,
const gss_OID_set except_mech_attrs,
const gss_OID_set critical_mech_attrs,
gss_OID_set *mechs) nogil

OM_uint32 gss_inquire_attrs_for_mech(
OM_uint32 *minor_status,
const gss_OID mech,
gss_OID_set *mech_attrs,
gss_OID_set *known_mech_attrs) nogil

OM_uint32 gss_display_mech_attr(
OM_uint32 *minor_status,
const gss_OID mech_attr,
gss_buffer_t name,
gss_buffer_t short_desc,
gss_buffer_t long_desc) nogil


def indicate_mechs_by_attrs(desired_mech_attrs=None, except_mech_attrs=None,
critical_mech_attrs=None):
"""
indicate_mechs_by_attrs(desired_mech_attrs=None, except_mech_attrs=None,
critical_mech_attrs=None)
Get a set of mechanisms that have the specified attributes.
Args:
desired_mech_attrs ([OID]): Attributes that the output mechs MUST
offer
except_mech_attrs ([OID]): Attributes that the output mechs MUST NOT
offer
critical_mech_attrs ([OID]): Attributes that the output mechs MUST
understand and offer
Returns:
[MechType]: a set of mechs which satisfy the given criteria
Raises:
GSSError
"""
cdef OM_uint32 maj_stat, min_stat
cdef gss_OID_set desired_attrs = GSS_C_NO_OID_SET
cdef gss_OID_set except_attrs = GSS_C_NO_OID_SET
cdef gss_OID_set critical_attrs = GSS_C_NO_OID_SET
cdef gss_OID_set mechs

if desired_mech_attrs is not None:
desired_attrs = c_get_mech_oid_set(desired_mech_attrs)

if except_mech_attrs is not None:
except_attrs = c_get_mech_oid_set(except_mech_attrs)

if critical_mech_attrs is not None:
critical_attrs = c_get_mech_oid_set(critical_mech_attrs)

with nogil:
maj_stat = gss_indicate_mechs_by_attrs(&min_stat, desired_attrs,
except_attrs, critical_attrs,
&mechs)

if maj_stat == GSS_S_COMPLETE:
return c_create_oid_set(mechs)
else:
raise GSSError(maj_stat, min_stat)


def inquire_attrs_for_mech(OID mech):
"""
inquire_attrs_for_mech(mech)
Gets the set of attrs supported and known by a mechanism.
Args:
mech (MechType): Mechanism to inquire about
Returns:
InquireAttrsResult: the results of inquiry; a mech's attributes and
known attributes
Raises:
GSSError
"""
cdef OM_uint32 maj_stat, min_stat
cdef gss_OID m = GSS_C_NO_OID
cdef gss_OID_set mech_attrs = GSS_C_NO_OID_SET
cdef gss_OID_set known_mech_attrs = GSS_C_NO_OID_SET

if mech is not None:
m = &mech.raw_oid

with nogil:
maj_stat = gss_inquire_attrs_for_mech(&min_stat, m, &mech_attrs,
&known_mech_attrs)

if maj_stat == GSS_S_COMPLETE:
return InquireAttrsResult(c_create_oid_set(mech_attrs),
c_create_oid_set(known_mech_attrs))
else:
raise GSSError(maj_stat, min_stat)


def display_mech_attr(OID attr):
"""
display_mech_attrs(attr)
Returns information about attributes in human readable form.
Args:
attr (OID): Mechanism attribute to retrive names and descriptions of
Returns:
DisplayAttrResult: the results of displaying the attribute; mech name,
short description, and long description.
Raises:
GSSError
"""
cdef OM_uint32 maj_stat, min_stat
cdef gss_OID a = GSS_C_NO_OID
cdef gss_buffer_desc name
cdef gss_buffer_desc short_desc
cdef gss_buffer_desc long_desc

if attr is not None:
a = &attr.raw_oid

with nogil:
maj_stat = gss_display_mech_attr(&min_stat, a, &name, &short_desc,
&long_desc)

if maj_stat == GSS_S_COMPLETE:
out_name = name.value[:name.length]
out_short = short_desc.value[:short_desc.length]
out_long = long_desc.value[:long_desc.length]

gss_release_buffer(&min_stat, &name)
gss_release_buffer(&min_stat, &short_desc)
gss_release_buffer(&min_stat, &long_desc)

return DisplayAttrResult(out_name, out_short, out_long)
else:
raise GSSError(maj_stat, min_stat)
6 changes: 6 additions & 0 deletions gssapi/raw/named_tuples.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,9 @@
GetNameAttributeResult = namedtuple('GetNamedAttributeResult',
['values', 'display_values',
'authenticated', 'complete'])

InquireAttrsResult = namedtuple('InquireAttrsResult',
['mech_attrs', 'known_mech_attrs'])

DisplayAttrResult = namedtuple('DisplayAttrResult', ['name', 'short_desc',
'long_desc'])
76 changes: 76 additions & 0 deletions gssapi/tests/test_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,82 @@ def test_add_cred_with_password(self):

new_creds.should_be_a(gb.Creds)

@ktu.gssapi_extension_test('rfc5587', 'RFC 5587')
def test_rfc5587(self):
mechs = gb.indicate_mechs_by_attrs(None, None, None)

mechs.should_be_a(set)
mechs.shouldnt_be_empty()

last_attr = None
last_mech = None

for mech in mechs:
mech.shouldnt_be_none()
mech.should_be_a(gb.OID)
last_mech = mech

inquire_out = gb.inquire_attrs_for_mech(mech)
mech_attrs = inquire_out.mech_attrs
known_mech_attrs = inquire_out.known_mech_attrs

mech_attrs.should_be_a(set)
mech_attrs.shouldnt_be_empty()

known_mech_attrs.should_be_a(set)
known_mech_attrs.shouldnt_be_empty()

for mech_attr in mech_attrs:
mech_attr.shouldnt_be_none()
mech_attr.should_be_a(gb.OID)

display_out = gb.display_mech_attr(mech_attr)
display_out.name.shouldnt_be_none()
display_out.long_desc.shouldnt_be_none()
display_out.short_desc.shouldnt_be_none()

last_attr = mech_attr

for mech_attr in known_mech_attrs:
mech_attr.shouldnt_be_none()
mech_attr.should_be_a(gb.OID)

display_out = gb.display_mech_attr(mech_attr)
display_out.name.shouldnt_be_none()
display_out.long_desc.shouldnt_be_none()
display_out.short_desc.shouldnt_be_none()

attrs = set([last_attr])

mechs = gb.indicate_mechs_by_attrs(attrs, None, None)
mechs.shouldnt_be_empty()
mechs.should_include(last_mech)

mechs = gb.indicate_mechs_by_attrs(None, attrs, None)
mechs.shouldnt_include(last_mech)

mechs = gb.indicate_mechs_by_attrs(None, None, attrs)
mechs.shouldnt_be_empty()
mechs.should_include(last_mech)

@ktu.gssapi_extension_test('rfc5587', 'RFC 5587')
def test_display_mech_attr(self):
test_attrs = [
# oid, name, short_desc, long_desc
[gb.OID.from_int_seq("1.3.6.1.5.5.13.24"), b"GSS_C_MA_CBINDINGS",
b"channel-bindings", b"Mechanism supports channel bindings."],
[gb.OID.from_int_seq("1.3.6.1.5.5.13.1"),
b"GSS_C_MA_MECH_CONCRETE", b"concrete-mech",
b"Mechanism is neither a pseudo-mechanism nor a composite "
b"mechanism."]
]

for attr in test_attrs:
display_out = gb.display_mech_attr(attr[0])
display_out.name.should_be(attr[1])
display_out.short_desc.should_be(attr[2])
display_out.long_desc.should_be(attr[3])


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 @@ -258,6 +258,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('rfc5587', 'gss_indicate_mechs_by_attrs'),
extension_file('rfc5588', 'gss_store_cred'),
extension_file('cred_imp_exp', 'gss_import_cred'),
extension_file('dce', 'gss_wrap_iov'),
Expand Down

0 comments on commit 345fb85

Please sign in to comment.