Skip to content

Commit 4af9011

Browse files
committed
Add credentials import-export to low-level API
Previously, there was support for credentials import-export in the high-level API, but no actuall corresponding support in the low-level API. This commit fixes that. Closes #25
1 parent 35f1050 commit 4af9011

File tree

5 files changed

+107
-4
lines changed

5 files changed

+107
-4
lines changed

gssapi/raw/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
except ImportError:
2727
pass
2828

29+
try:
30+
from gssapi.raw.ext_cred_imp_exp import * # noqa
31+
except ImportError:
32+
pass
33+
2934
# optional KRB5 mech support
3035
try:
3136
import gssapi.raw.mech_krb5 # noqa

gssapi/raw/ext_cred_imp_exp.pyx

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
GSSAPI="BASE" # This ensures that a full module is generated by Cython
2+
3+
from gssapi.raw.cython_types cimport *
4+
from gssapi.raw.cython_converters cimport c_create_oid_set
5+
from gssapi.raw.cython_converters cimport c_get_mech_oid_set
6+
from gssapi.raw.cython_converters cimport c_py_ttl_to_c, c_c_ttl_to_py
7+
from gssapi.raw.creds cimport Creds
8+
from gssapi.raw.names cimport Name
9+
from gssapi.raw.oids cimport OID
10+
11+
from gssapi.raw.misc import GSSError
12+
from gssapi.raw.named_tuples import AcquireCredResult, AddCredResult
13+
14+
15+
cdef extern from "gssapi/gssapi_ext.h":
16+
OM_uint32 gss_export_cred(OM_uint32 *min_stat, gss_cred_id_t cred_handle,
17+
gss_buffer_t token) nogil
18+
19+
OM_uint32 gss_import_cred(OM_uint32 *min_stat, gss_buffer_t token,
20+
gss_cred_id_t *cred_handle) nogil
21+
22+
23+
def export_cred(Creds creds not None):
24+
"""Export GSSAPI credentials object
25+
26+
This method exports a GSSSAPI credentials object into a token
27+
which may be transmitted between different processes.
28+
29+
Args:
30+
creds (Creds): the credentials object to be exported
31+
32+
Returns:
33+
bytes: the exported token representing the given credentials object
34+
35+
Raises:
36+
GSSError
37+
"""
38+
39+
# GSS_C_EMPTY_BUFFER
40+
cdef gss_buffer_desc exported_creds = gss_buffer_desc(0, NULL)
41+
42+
cdef OM_uint32 maj_stat, min_stat
43+
44+
with nogil:
45+
maj_stat = gss_export_cred(&min_stat, creds.raw_creds, &exported_creds)
46+
47+
if maj_stat == GSS_S_COMPLETE:
48+
res = exported_creds.value[:exported_creds.length]
49+
gss_release_buffer(&min_stat, &exported_creds)
50+
return res
51+
else:
52+
raise GSSError(maj_stat, min_stat)
53+
54+
55+
def import_cred(token not None):
56+
"""Import GSSAPI credentials from a token
57+
58+
This method imports a credentials object from a token
59+
previously exported by :func:`export_cred`.
60+
61+
Args:
62+
token (bytes): the token to import
63+
64+
Returns:
65+
Creds: the imported credentials object
66+
67+
Raises:
68+
GSSError
69+
"""
70+
71+
cdef gss_buffer_desc token_buffer = gss_buffer_desc(len(token), token)
72+
73+
cdef gss_cred_id_t creds
74+
75+
cdef OM_uint32 maj_stat, min_stat
76+
77+
with nogil:
78+
maj_stat = gss_import_cred(&min_stat, &token_buffer, &creds)
79+
80+
cdef Creds res
81+
if maj_stat == GSS_S_COMPLETE:
82+
res = Creds()
83+
res.raw_creds = creds
84+
return res
85+
else:
86+
raise GSSError(maj_stat, min_stat)

gssapi/tests/test_high_level.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,13 @@ def test_store_into_add_from(self):
300300
retrieved_creds.shouldnt_be_none()
301301
retrieved_creds.should_be_a(gsscreds.Credentials)
302302

303-
@_extension_test('cred_imp_ext', 'credentials import-export')
303+
@_extension_test('cred_imp_exp', 'credentials import-export')
304304
def test_export(self):
305305
creds = gsscreds.Credentials(name=self.name)
306306
token = creds.export()
307-
token.should_be(bytes)
307+
token.should_be_a(bytes)
308308

309-
@_extension_test('cred_imp_ext', 'credentials import-export')
309+
@_extension_test('cred_imp_exp', 'credentials import-export')
310310
def test_import_by_init(self):
311311
creds = gsscreds.Credentials(name=self.name)
312312
token = creds.export()
@@ -315,7 +315,7 @@ def test_import_by_init(self):
315315
imported_creds.lifetime.should_be(creds.lifetime)
316316
imported_creds.name.should_be(creds.name)
317317

318-
@_extension_test('cred_imp_ext', 'credentials import-export')
318+
@_extension_test('cred_imp_exp', 'credentials import-export')
319319
def test_pickle_unpickle(self):
320320
creds = gsscreds.Credentials(name=self.name)
321321
pickled_creds = pickle.dumps(creds)

gssapi/tests/test_raw.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ def test_acquire_creds(self):
157157
gb.release_name(name)
158158
gb.release_cred(creds)
159159

160+
@_extension_test('cred_imp_exp', 'credentials import-export')
161+
def test_cred_import_export(self):
162+
creds = gb.acquire_cred(None).creds
163+
token = gb.export_cred(creds)
164+
imported_creds = gb.import_cred(token)
165+
166+
inquire_orig = gb.inquire_cred(creds, name=True)
167+
inquire_imp = gb.inquire_cred(imported_creds, name=True)
168+
169+
gb.compare_name(inquire_orig.name, inquire_imp.name).should_be_true()
170+
160171
def test_context_time(self):
161172
target_name = gb.import_name(TARGET_SERVICE_NAME,
162173
gb.NameType.hostbased_service)

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ def gssapi_modules(lst):
190190
extension_file('s4u', 'gss_acquire_cred_impersonate_name'),
191191
extension_file('cred_store', 'gss_store_cred_into'),
192192
extension_file('rfc5588', 'gss_store_cred'),
193+
extension_file('cred_imp_exp', 'gss_import_cred'),
193194
]),
194195
keywords=['gssapi', 'security'],
195196
install_requires=[

0 commit comments

Comments
 (0)