Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit afd68bf

Browse files
Expose mechanisms in the high-level API
This creates a new class, Mechanism, for inquiring information about a mechanism. This includes support for RFCs 5587 and 5801. As Mechanism derives from OID, it is compatible with all places that accept a mech by OID. Signed-off-by: Alexander Scheel <ascheel@redhat.com>
1 parent b1cb22b commit afd68bf

File tree

4 files changed

+278
-0
lines changed

4 files changed

+278
-0
lines changed

‎gssapi/__init__.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@
3333
from gssapi.creds import Credentials # noqa
3434
from gssapi.names import Name # noqa
3535
from gssapi.sec_contexts import SecurityContext # noqa
36+
from gssapi.mechs import Mechanism # noqa
3637

3738
from gssapi._utils import set_encoding # noqa

‎gssapi/mechs.py‎

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import six
2+
3+
from gssapi.raw import oids as roids
4+
from gssapi._utils import import_gssapi_extension
5+
from gssapi.raw import misc as rmisc
6+
from gssapi import _utils
7+
8+
rfc5587 = import_gssapi_extension('rfc5587')
9+
rfc5801 = import_gssapi_extension('rfc5801')
10+
11+
12+
class Mechanism(roids.OID):
13+
"""
14+
A GSSAPI Mechanism
15+
16+
This class represents a mechanism and centralizes functions dealing with
17+
mechanisms and can be used with any calls.
18+
19+
It inherits from the low-level GSSAPI :class:`~gssapi.raw.oids.OID` class,
20+
and thus can be used with both low-level and high-level API calls.
21+
"""
22+
_sasl_name = None
23+
_mech_attrs = None
24+
25+
def __new__(cls, cpy=None, elements=None):
26+
return super(Mechanism, cls).__new__(cls, cpy, elements)
27+
28+
@property
29+
def names(self):
30+
"""
31+
Get the set of name types supported by the mechanism.
32+
"""
33+
return rmisc.inquire_names_for_mech(self)
34+
35+
@property
36+
def _query_saslname(self):
37+
if rfc5801 is None:
38+
raise NotImplementedError("Your GSSAPI implementation does not "
39+
"have support for RFC 5801")
40+
return rfc5801.inquire_saslname_for_mech(self)
41+
42+
@property
43+
def _query_attrs(self):
44+
if rfc5587 is None:
45+
raise NotImplementedError("Your GSSAPI implementation does not "
46+
"have support for RFC 5587")
47+
48+
return rfc5587.inquire_attrs_for_mech(self)
49+
50+
def __str__(self):
51+
if issubclass(str, six.text_type):
52+
# Python 3 -- we should return unicode
53+
return self.__bytes__().decode(_utils._get_encoding())
54+
else:
55+
return self.__bytes__()
56+
57+
def __unicode__(self):
58+
return self.__bytes__().decode(_utils._get_encoding())
59+
60+
def __bytes__(self):
61+
"""
62+
Get a name representing the mechanism; always safe to call
63+
"""
64+
base = self.dotted_form
65+
if rfc5801 is not None:
66+
base = self._query_saslname.mech_name
67+
68+
if issubclass(str, six.text_type):
69+
base = bytes(base, _utils._get_encoding())
70+
else:
71+
base = bytes(base)
72+
73+
return base
74+
75+
def __repr__(self):
76+
"""
77+
Get a name representing the mechanism; always safe to call
78+
"""
79+
base = self.dotted_form
80+
if rfc5801 is not None:
81+
base = "%s %s" % (self._query_saslname.mech_name.decode('UTF-8'),
82+
base)
83+
84+
return base
85+
86+
@property
87+
def sasl_name(self):
88+
"""
89+
Get the SASL name for the mechanism; depends on RFC 5801
90+
91+
:requires-ext:`rfc5801`
92+
"""
93+
return self._query_saslname.sasl_mech_name.decode('UTF-8')
94+
95+
@property
96+
def name(self):
97+
"""
98+
Get the name for the mechanism; depends on RFC 5801
99+
100+
:requires-ext:`rfc5801`
101+
"""
102+
self._query_saslname()
103+
return self._query_saslname.mech_name.decode('UTF-8')
104+
105+
@property
106+
def description(self):
107+
"""
108+
Get the description of the mechanism; depends on RFC 5801
109+
110+
:requires-ext:`rfc5801`
111+
"""
112+
self._query_saslname()
113+
return self._query_saslname.mech_description.decode('UTF-8')
114+
115+
@property
116+
def known_attrs(self):
117+
"""
118+
Get the known attributes of the mechanism; depends on RFC 5587
119+
120+
:requires-ext:`rfc5587`
121+
"""
122+
return self._query_attrs.known_mech_attrs
123+
124+
@property
125+
def attrs(self):
126+
"""
127+
Get the attributes of the mechanism; depends on RFC 5587
128+
129+
:requires-ext:`rfc5587`
130+
"""
131+
return self._query_attrs.mech_attrs
132+
133+
@classmethod
134+
def all_mechs(cls):
135+
"""
136+
all_mechs()
137+
Get a list of all mechanisms supported by GSSAPI
138+
"""
139+
mechs = rmisc.indicate_mechs()
140+
return [cls(mech) for mech in mechs]
141+
142+
@classmethod
143+
def from_name(cls, name=None):
144+
"""
145+
from_name(name)
146+
Get a set of mechanisms that may be able to process the name
147+
148+
Args:
149+
name (Name): a name to inquire about
150+
151+
Returns:
152+
[Mechanism]: a set of mechanisms which support this name
153+
154+
Raises:
155+
GSSError
156+
"""
157+
mechs = rmisc.inquire_mechs_for_name(name)
158+
return [cls(mech) for mech in mechs]
159+
160+
@classmethod
161+
def from_sasl_name(cls, name=None):
162+
"""
163+
from_sasl_name(name)
164+
Create a Mechanism from its SASL name
165+
166+
Args:
167+
name (str): SASL name of the desired mechanism
168+
169+
Returns:
170+
Mechanism: the desired mechanism
171+
172+
Raises:
173+
GSSError
174+
175+
:requires-ext:`rfc5801`
176+
"""
177+
if rfc5801 is None:
178+
raise NotImplementedError("Your GSSAPI implementation does not "
179+
"have support for RFC 5801")
180+
n = name
181+
if type(n) is not bytes:
182+
n = str(n).encode()
183+
184+
m = rfc5801.inquire_mech_for_saslname(n)
185+
186+
return cls(m)
187+
188+
@classmethod
189+
def from_attrs(cls, m_desired=None, m_except=None, m_critical=None):
190+
"""
191+
from_attrs
192+
Get the set of mechanisms supporting the specified attributes. See
193+
RFC 5587's indicate_mechs_by_attrs for more information.
194+
195+
Args:
196+
m_desired ([OID]): Desired attributes
197+
m_except ([OID]): Except attributes
198+
m_critical ([OID]): Critical attributes
199+
200+
Returns:
201+
[Mechanism]: A set of mechanisms having the desired features.
202+
203+
Raises:
204+
GSSError
205+
206+
:requires-ext:`rfc5587`
207+
"""
208+
if type(m_desired) == roids.OID:
209+
m_desired = set([m_desired])
210+
if type(m_except) == roids.OID:
211+
m_except = set([m_except])
212+
if type(m_critical) == roids.OID:
213+
m_critical = set([m_critical])
214+
215+
if rfc5587 is None:
216+
raise NotImplementedError("Your GSSAPI implementation does not "
217+
"have support for RFC 5587")
218+
219+
mechs = rfc5587.indicate_mechs_by_attrs(m_desired,
220+
m_except,
221+
m_critical)
222+
return [cls(mech) for mech in mechs]

‎gssapi/raw/oids.pyx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ cdef class OID:
6161
self._free_on_dealloc = True
6262
return 0
6363

64+
def _copy_oid(self, OID other):
65+
self._copy_from(other.raw_oid)
66+
6467
cdef int _from_bytes(OID self, object base) except -1:
6568
base_bytes = bytes(base)
6669
cdef char* byte_str = base_bytes

‎gssapi/tests/test_high_level.py‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from nose_parameterized import parameterized
1010

1111
from gssapi import creds as gsscreds
12+
from gssapi import mechs as gssmechs
1213
from gssapi import names as gssnames
1314
from gssapi import sec_contexts as gssctx
1415
from gssapi import raw as gb
@@ -369,6 +370,57 @@ def test_add_with_impersonate(self):
369370
new_creds.should_be_a(gsscreds.Credentials)
370371

371372

373+
class MechsTestCase(_GSSAPIKerberosTestCase):
374+
def test_indicate_mechs(self):
375+
mechs = gssmechs.Mechanism.all_mechs()
376+
for mech in mechs:
377+
s = str(mech)
378+
s.shouldnt_be_empty()
379+
380+
@ktu.gssapi_extension_test('rfc5801', 'RFC 5801: SASL Names')
381+
def test_sasl_properties(self):
382+
mechs = gssmechs.Mechanism.all_mechs()
383+
for mech in mechs:
384+
s = str(mech)
385+
s.shouldnt_be_empty()
386+
s.should_be_a(str)
387+
s[0].shouldnt_be('<')
388+
s.should_be(mech.name)
389+
390+
mech.sasl_name.shouldnt_be_empty()
391+
mech.sasl_name.should_be_a(six.text_type)
392+
393+
mech.description.shouldnt_be_empty()
394+
mech.description.should_be_a(six.text_type)
395+
396+
cmp_mech = gssmechs.Mechanism.from_sasl_name(mech.sasl_name)
397+
str(cmp_mech).should_be(str(mech))
398+
399+
@ktu.gssapi_extension_test('rfc5587', 'RFC 5587: Mech Inquiry')
400+
def test_mech_inquiry(self):
401+
mechs = gssmechs.Mechanism.all_mechs()
402+
c = len(mechs)
403+
for mech in mechs:
404+
attrs = mech.attrs
405+
known_attrs = mech.known_attrs
406+
407+
for attr in attrs:
408+
i = gssmechs.Mechanism.from_attrs(m_desired=[attr])
409+
e = gssmechs.Mechanism.from_attrs(m_except=[attr])
410+
411+
count = len(i) + len(e)
412+
count.should_be(c)
413+
i.should_include(mech)
414+
e.shouldnt_include(mech)
415+
416+
for attr in known_attrs:
417+
i = gssmechs.Mechanism.from_attrs(m_desired=[attr])
418+
e = gssmechs.Mechanism.from_attrs(m_except=[attr])
419+
420+
count = len(i) + len(e)
421+
count.should_be(c)
422+
423+
372424
class NamesTestCase(_GSSAPIKerberosTestCase):
373425
def test_create_from_other(self):
374426
raw_name = gb.import_name(SERVICE_PRINCIPAL)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /