Skip to content

Commit 4b68958

Browse files
committed
Added support for GGF inquire cred and sec context
1 parent beb69c9 commit 4b68958

File tree

4 files changed

+208
-0
lines changed

4 files changed

+208
-0
lines changed

Diff for: gssapi/raw/__init__.py

+6
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,9 @@
119119
from gssapi.raw.ext_rfc6680_comp_oid import * # noqa
120120
except ImportError:
121121
pass
122+
123+
# optional Global Grid Forum support
124+
try:
125+
from gssapi.raw.ext_ggf import * # noqa
126+
except ImportError:
127+
pass

Diff for: gssapi/raw/ext_ggf.pyx

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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.ext_buffer_sets cimport *
5+
from gssapi.raw.cython_converters cimport c_get_mech_oid_set
6+
from gssapi.raw.misc import GSSError
7+
from gssapi.raw.oids cimport OID
8+
from gssapi.raw.creds cimport Creds
9+
from gssapi.raw.sec_contexts cimport SecurityContext
10+
11+
cdef extern from "python_gssapi_ext.h":
12+
13+
OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status,
14+
const gss_cred_id_t cred_handle,
15+
const gss_OID desired_object,
16+
gss_buffer_set_t *data_set) nogil
17+
18+
OM_uint32 gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
19+
const gss_ctx_id_t context_handle,
20+
const gss_OID desired_object,
21+
gss_buffer_set_t *data_set) nogil
22+
23+
24+
def inquire_cred_by_oid(Creds cred_handle not None, OID mech not None):
25+
"""
26+
inquire_cred_by_oid(cred_handle, mech)
27+
28+
This method inspects a :class:`Creds` object for information
29+
specific to a particular mechanism.
30+
31+
Args:
32+
cred_handle (Creds): the security context to query
33+
mech (OID): the desired mechanism
34+
35+
Returns:
36+
list: A list of zero or more pieces of data corresponding to the
37+
OID set
38+
39+
Raises:
40+
GSS_ERROR
41+
"""
42+
43+
cdef gss_buffer_set_t *data_set_ptr = NULL
44+
cdef gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET
45+
cdef OM_uint32 maj_stat, min_stat
46+
47+
data_set_ptr = &data_set
48+
49+
with nogil:
50+
maj_stat = gss_inquire_cred_by_oid(&min_stat, cred_handle.raw_creds,
51+
&mech.raw_oid, data_set_ptr)
52+
53+
if maj_stat == GSS_S_COMPLETE:
54+
py_tokens = []
55+
56+
if data_set != GSS_C_NO_BUFFER_SET:
57+
for i in range(data_set.count):
58+
token = data_set.elements[i]
59+
py_tokens.append(token.value[:token.length])
60+
61+
gss_release_buffer_set(&min_stat, &data_set)
62+
63+
return py_tokens
64+
else:
65+
raise GSSError(maj_stat, min_stat)
66+
67+
68+
def inquire_sec_context_by_oid(SecurityContext context not None,
69+
OID mech not None):
70+
"""
71+
inquire_sec_context_by_oid(context, mech)
72+
73+
This method inspects a :class:`SecurityContext` object for information
74+
specific to a particular mechanism.
75+
76+
This method can be used with the GSS_KRB5_INQ_SSPI_SESSION_KEY_OID OID to
77+
retrieve the required key that is used to derive the SMB/SAMBA signing and
78+
encryption keys.
79+
80+
Args:
81+
context (SecurityContext): the security context to query
82+
mech (OID): the desired mechanism
83+
84+
Returns:
85+
list: A list of zero or more pieces of data corresponding to the
86+
OID set
87+
88+
Raises:
89+
GSS_ERROR
90+
"""
91+
92+
cdef gss_buffer_set_t *data_set_ptr = NULL
93+
cdef gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET
94+
cdef OM_uint32 maj_stat, min_stat
95+
96+
data_set_ptr = &data_set
97+
98+
with nogil:
99+
maj_stat = gss_inquire_sec_context_by_oid(&min_stat, context.raw_ctx,
100+
&mech.raw_oid, data_set_ptr)
101+
102+
if maj_stat == GSS_S_COMPLETE:
103+
py_tokens = []
104+
105+
if data_set != GSS_C_NO_BUFFER_SET:
106+
for i in range(data_set.count):
107+
token = data_set.elements[i]
108+
py_tokens.append(token.value[:token.length])
109+
110+
gss_release_buffer_set(&min_stat, &data_set)
111+
112+
return py_tokens
113+
else:
114+
raise GSSError(maj_stat, min_stat)

Diff for: gssapi/tests/test_raw.py

+87
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,93 @@ def test_sasl_names(self):
760760
cmp_mech.shouldnt_be_none()
761761
cmp_mech.should_be(mech)
762762

763+
@ktu.gssapi_extension_test('ggf', 'Global Grid Forum')
764+
@ktu.gssapi_extension_test('s4u', 'S4U')
765+
@ktu.krb_minversion_test('1.16',
766+
'querying impersonator name of krb5 GSS '
767+
'Credential using the '
768+
'GSS_KRB5_GET_CRED_IMPERSONATOR OID')
769+
def test_inquire_cred_by_oid_impersonator(self):
770+
svc_princ = SERVICE_PRINCIPAL.decode("UTF-8")
771+
self.realm.kinit(svc_princ, flags=['-k', '-f'])
772+
773+
target_name = gb.import_name(TARGET_SERVICE_NAME,
774+
gb.NameType.hostbased_service)
775+
776+
client_token = gb.init_sec_context(target_name).token
777+
778+
# if our acceptor creds have a usage of both, we get
779+
# s4u2proxy delegated credentials
780+
server_creds = gb.acquire_cred(None, usage='both').creds
781+
server_ctx_resp = gb.accept_sec_context(client_token,
782+
acceptor_creds=server_creds)
783+
784+
server_ctx_resp.shouldnt_be_none()
785+
server_ctx_resp.delegated_creds.shouldnt_be_none()
786+
server_ctx_resp.delegated_creds.should_be_a(gb.Creds)
787+
788+
# GSS_KRB5_GET_CRED_IMPERSONATOR
789+
oid = gb.OID.from_int_seq("1.2.840.113554.1.2.2.5.14")
790+
info = gb.inquire_cred_by_oid(server_ctx_resp.delegated_creds, oid)
791+
792+
info.should_be_a(list)
793+
info.shouldnt_be_empty()
794+
info[0].should_be_a(bytes)
795+
info[0].should_be(b"%s@%s" % (SERVICE_PRINCIPAL,
796+
self.realm.realm.encode('utf-8')))
797+
798+
@ktu.gssapi_extension_test('ggf', 'Global Grid Forum')
799+
def test_inquire_sec_context_by_oid(self):
800+
target_name = gb.import_name(TARGET_SERVICE_NAME,
801+
gb.NameType.hostbased_service)
802+
ctx_resp1 = gb.init_sec_context(target_name)
803+
804+
server_name = gb.import_name(SERVICE_PRINCIPAL,
805+
gb.NameType.kerberos_principal)
806+
server_creds = gb.acquire_cred(server_name)[0]
807+
server_resp = gb.accept_sec_context(ctx_resp1[3],
808+
acceptor_creds=server_creds)
809+
server_ctx = server_resp[0]
810+
server_tok = server_resp[3]
811+
812+
client_resp2 = gb.init_sec_context(target_name,
813+
context=ctx_resp1[0],
814+
input_token=server_tok)
815+
client_ctx = client_resp2[0]
816+
817+
# GSS_C_INQ_SSPI_SESSION_KEY
818+
session_key_oid = gb.OID.from_int_seq("1.2.840.113554.1.2.2.5.5")
819+
820+
client_key = gb.inquire_sec_context_by_oid(client_ctx, session_key_oid)
821+
server_key = gb.inquire_sec_context_by_oid(server_ctx, session_key_oid)
822+
823+
client_key.should_be_a(list)
824+
client_key.shouldnt_be_empty()
825+
server_key.should_be_a(list)
826+
server_key.shouldnt_be_empty()
827+
client_key.should_have_same_items_as(server_key)
828+
829+
@ktu.gssapi_extension_test('ggf', 'Global Grid Forum')
830+
def test_inquire_sec_context_by_oid_should_raise_error(self):
831+
target_name = gb.import_name(TARGET_SERVICE_NAME,
832+
gb.NameType.hostbased_service)
833+
ctx_resp1 = gb.init_sec_context(target_name)
834+
835+
server_name = gb.import_name(SERVICE_PRINCIPAL,
836+
gb.NameType.kerberos_principal)
837+
server_creds = gb.acquire_cred(server_name)[0]
838+
server_resp = gb.accept_sec_context(ctx_resp1[3],
839+
acceptor_creds=server_creds)
840+
841+
client_resp2 = gb.init_sec_context(target_name,
842+
context=ctx_resp1[0],
843+
input_token=server_resp[3])
844+
client_ctx = client_resp2[0]
845+
846+
invalid_oid = gb.OID.from_int_seq("1.2.3.4.5.6.7.8.9")
847+
gb.inquire_sec_context_by_oid.should_raise(gb.GSSError, client_ctx,
848+
invalid_oid)
849+
763850

764851
class TestIntEnumFlagSet(unittest.TestCase):
765852
def test_create_from_int(self):

Diff for: setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ def gssapi_modules(lst):
264264
extension_file('cred_imp_exp', 'gss_import_cred'),
265265
extension_file('dce', 'gss_wrap_iov'),
266266
extension_file('iov_mic', 'gss_get_mic_iov'),
267+
extension_file('ggf', 'gss_inquire_sec_context_by_oid'),
267268

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

0 commit comments

Comments
 (0)