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 fe6d5cc

Browse files
cipherboyDirectXMan12
authored andcommitted
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> Signed-off-by: Alexander Scheel <alexander.m.scheel@gmail.com>
1 parent 96fb80b commit fe6d5cc

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-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: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
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+
def __new__(cls, cpy=None, elements=None):
23+
return super(Mechanism, cls).__new__(cls, cpy, elements)
24+
25+
@property
26+
def name_types(self):
27+
"""
28+
Get the set of name types supported by this mechanism.
29+
"""
30+
return rmisc.inquire_names_for_mech(self)
31+
32+
@property
33+
def _saslname(self):
34+
if rfc5801 is None:
35+
raise NotImplementedError("Your GSSAPI implementation does not "
36+
"have support for RFC 5801")
37+
return rfc5801.inquire_saslname_for_mech(self)
38+
39+
@property
40+
def _attrs(self):
41+
if rfc5587 is None:
42+
raise NotImplementedError("Your GSSAPI implementation does not "
43+
"have support for RFC 5587")
44+
45+
return rfc5587.inquire_attrs_for_mech(self)
46+
47+
def __str__(self):
48+
if issubclass(str, six.text_type):
49+
# Python 3 -- we should return unicode
50+
return self._bytes_desc().decode(_utils._get_encoding())
51+
else:
52+
return self._bytes_desc()
53+
54+
def __unicode__(self):
55+
return self._bytes_desc().decode(_utils._get_encoding())
56+
57+
def _bytes_desc(self):
58+
base = self.dotted_form
59+
if rfc5801 is not None:
60+
base = self._saslname.mech_name
61+
62+
if isinstance(base, six.text_type):
63+
base = base.encode(_utils._get_encoding())
64+
65+
return base
66+
67+
def __repr__(self):
68+
"""
69+
Get a name representing the mechanism; always safe to call
70+
"""
71+
base = "<Mechanism (%s)>" % self.dotted_form
72+
if rfc5801 is not None:
73+
base = "<Mechanism %s (%s)>" % (
74+
self._saslname.mech_name.decode('UTF-8'),
75+
self.dotted_form
76+
)
77+
78+
return base
79+
80+
@property
81+
def sasl_name(self):
82+
"""
83+
Get the SASL name for the mechanism
84+
85+
:requires-ext:`rfc5801`
86+
"""
87+
return self._saslname.sasl_mech_name.decode('UTF-8')
88+
89+
@property
90+
def description(self):
91+
"""
92+
Get the description of the mechanism
93+
94+
:requires-ext:`rfc5801`
95+
"""
96+
return self._saslname.mech_description.decode('UTF-8')
97+
98+
@property
99+
def known_attrs(self):
100+
"""
101+
Get the known attributes of the mechanism; returns a set of OIDs
102+
([OID])
103+
104+
:requires-ext:`rfc5587`
105+
"""
106+
return self._attrs.known_mech_attrs
107+
108+
@property
109+
def attrs(self):
110+
"""
111+
Get the attributes of the mechanism; returns a set of OIDs ([OID])
112+
113+
:requires-ext:`rfc5587`
114+
"""
115+
return self._attrs.mech_attrs
116+
117+
@classmethod
118+
def all_mechs(cls):
119+
"""
120+
Get a generator of all mechanisms supported by GSSAPI
121+
"""
122+
return (cls(mech) for mech in rmisc.indicate_mechs())
123+
124+
@classmethod
125+
def from_name(cls, name=None):
126+
"""
127+
Get a generator of mechanisms that may be able to process the name
128+
129+
Args:
130+
name (Name): a name to inquire about
131+
132+
Returns:
133+
[Mechanism]: a set of mechanisms which support this name
134+
135+
Raises:
136+
GSSError
137+
"""
138+
return (cls(mech) for mech in rmisc.inquire_mechs_for_name(name))
139+
140+
@classmethod
141+
def from_sasl_name(cls, name=None):
142+
"""
143+
Create a Mechanism from its SASL name
144+
145+
Args:
146+
name (str): SASL name of the desired mechanism
147+
148+
Returns:
149+
Mechanism: the desired mechanism
150+
151+
Raises:
152+
GSSError
153+
154+
:requires-ext:`rfc5801`
155+
"""
156+
if rfc5801 is None:
157+
raise NotImplementedError("Your GSSAPI implementation does not "
158+
"have support for RFC 5801")
159+
if isinstance(name, six.text_type):
160+
name = name.encode(_utils._get_encoding())
161+
162+
m = rfc5801.inquire_mech_for_saslname(name)
163+
164+
return cls(m)
165+
166+
@classmethod
167+
def from_attrs(cls, m_desired=None, m_except=None, m_critical=None):
168+
"""
169+
Get a generator of mechanisms supporting the specified attributes. See
170+
RFC 5587's :func:`indicate_mechs_by_attrs` for more information.
171+
172+
Args:
173+
m_desired ([OID]): Desired attributes
174+
m_except ([OID]): Except attributes
175+
m_critical ([OID]): Critical attributes
176+
177+
Returns:
178+
[Mechanism]: A set of mechanisms having the desired features.
179+
180+
Raises:
181+
GSSError
182+
183+
:requires-ext:`rfc5587`
184+
"""
185+
if isinstance(m_desired, roids.OID):
186+
m_desired = set([m_desired])
187+
if isinstance(m_except, roids.OID):
188+
m_except = set([m_except])
189+
if isinstance(m_critical, roids.OID):
190+
m_critical = set([m_critical])
191+
192+
if rfc5587 is None:
193+
raise NotImplementedError("Your GSSAPI implementation does not "
194+
"have support for RFC 5587")
195+
196+
mechs = rfc5587.indicate_mechs_by_attrs(m_desired,
197+
m_except,
198+
m_critical)
199+
return (cls(mech) for mech in mechs)

‎gssapi/tests/test_high_level.py

Lines changed: 56 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,61 @@ 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+
encoding = gssutils._get_encoding()
384+
for mech in mechs:
385+
s = str(mech)
386+
s.shouldnt_be_empty()
387+
s.should_be_a(str)
388+
s.should_be(mech._saslname.mech_name.decode(encoding))
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 = list(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+
from_desired = gssmechs.Mechanism.from_attrs(m_desired=[attr])
409+
from_except = gssmechs.Mechanism.from_attrs(m_except=[attr])
410+
411+
from_desired = list(from_desired)
412+
from_except = list(from_except)
413+
414+
(len(from_desired) + len(from_except)).should_be(c)
415+
from_desired.should_include(mech)
416+
from_except.shouldnt_include(mech)
417+
418+
for attr in known_attrs:
419+
from_desired = gssmechs.Mechanism.from_attrs(m_desired=[attr])
420+
from_except = gssmechs.Mechanism.from_attrs(m_except=[attr])
421+
422+
from_desired = list(from_desired)
423+
from_except = list(from_except)
424+
425+
(len(from_desired) + len(from_except)).should_be(c)
426+
427+
372428
class NamesTestCase(_GSSAPIKerberosTestCase):
373429
def test_create_from_other(self):
374430
raw_name = gb.import_name(SERVICE_PRINCIPAL)

0 commit comments

Comments
(0)

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