Skip to content

Commit

Permalink
Untested code that hopefully works.
Browse files Browse the repository at this point in the history
Will eventually close pythongssapi#5.
  • Loading branch information
frozencemetery committed Jan 21, 2015
1 parent dec88d0 commit 35ffd22
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 0 deletions.
16 changes: 16 additions & 0 deletions docs/source/gssapi.raw.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ raw Package
:undoc-members:
:show-inheritance:

:mod:`ext_password` Module
---------------------

.. automodule:: gssapi.raw.ext_password
:members:
:undoc-members:
:show-inheritance:

:mod:`ext_password_add` Module
---------------------

.. automodule:: gssapi.raw.ext_password_add
:members:
:undoc-members:
:show-inheritance:

:mod:`mech_krb5` Module
-----------------------

Expand Down
7 changes: 7 additions & 0 deletions gssapi/raw/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,10 @@
import gssapi.raw.mech_krb5 # noqa
except ImportError:
pass

# optional password support
try:
from gssapi.raw.ext_password import * # noqa
from gssapi.raw.ext_password_add import * # noqa
except ImportError:
pass
96 changes: 96 additions & 0 deletions gssapi/raw/ext_password.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
GSSAPI="BASE" # This ensures that a full module is generated by Cythin

# Due to a bug in MIT Kerberos, add_cred_with_password was not properly
# exported for some time. In order to work around this,
# add_cred_with_password is in its own file. For more information, see:
# https://github.com/krb5/krb5/pull/244

from gssapi.raw.cython_types cimport *
from gssapi.raw.cython_converters cimport c_get_mech_oid_set
from gssapi.raw.cython_converters cimport c_create_oid_set
from gssapi.raw.cython_converters cimport c_py_ttl_to_c, c_c_ttl_to_py
from gssapi.raw.creds cimport Creds
from gssapi.raw.names cimport Name

from gssapi.raw.misc import GSSError
from gssapi.raw.named_tuples import AcquireCredResult

cdef extern from "gssapi/gssapi_ext.h":
OM_uint32 gss_acquire_cred_with_password(OM_uint32 *min_stat,
const gss_name_t desired_name,
const gss_buffer_t password,
OM_uint32 ttl,
const gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
gss_cred_id_t *output_creds,
gss_OID_set *actual_mechs,
OM_uint32 *actual_ttl) nogil

def acquire_cred_with_password(Name name not None, password not None,
lifetime=None, mechs=None, usage="initiate"):
"""
Acquire credentials through provided password.
This function is originally from Solaris and is not documented by either
MIT or Heimdal.
Args:
name (Name): the name to acquire credentials for
password (str): the password used to acquire credentialss with
lifetime (int): the lifetime for the credentials (or None for
indefinite)
mechs ([MechType]): the desired mechanisms for which the credentials
should work (or None for the default set)
usage (str): the usage type for the credentials: may be
'initiate', 'accept', or 'both'
Returns:
AcquireCredResult: the resulting credentials, the actual mechanisms
with which they may be used, and their actual lifetime (or None for
indefinite or not supported)
Raises:
GSSError
"""

cdef gss_buffer_desc password_buffer = gss_buffer_desc(len(password),
password)

cdef OM_uint32 input_ttl = c_py_ttl_to_c(lifetime)

cdef gss_OID_set desired_mechs
if mechs is not None:
desired_mechs = c_get_mech_oid_set(mechs)
else:
desired_mechs = GSS_C_NO_OID_SET

cdef gss_cred_usage_t c_usage
if usage == "initiate":
c_usage = GSS_C_INITIATE
elif usage == "accept":
c_usage = GSS_C_ACCEPT
else:
c_usage = GSS_C_BOTH

cdef gss_cred_id_t creds
cdef gss_OID_set actual_mechs
cdef OM_uint32 actual_ttl

cdef OM_uint32 maj_stat, min_stat

with nogil:
maj_stat = gss_acquire_cred_with_password(
&min_stat, name.raw_name, &password_buffer, input_ttl,
desired_mechs, c_usage, &creds, &actual_mechs, &actual_ttl)

cdef OM_uint32 tmp_min_stat
if mechs is not None:
gss_release_oid_set(&tmp_min_stat, &desired_mechs)

cdef Creds rc = Creds()
if maj_stat == GSS_S_COMPLETE:
rc.raw_creds = creds
return AcquireCredResult(rc, c_create_oid_set(actual_mechs),
c_c_ttl_to_py(actual_ttl))
else:
raise GSSError(maj_stat, min_stat)
103 changes: 103 additions & 0 deletions gssapi/raw/ext_password_add.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
GSSAPI="BASE" # This ensures that a full module is generated by Cythin

# Due to a bug in MIT Kerberos, add_cred_with_password was not properly
# exported for some time. In order to work around this,
# add_cred_with_password is in its own file. For more information, see:
# https://github.com/krb5/krb5/pull/244

from gssapi.raw.cython_types cimport *
from gssapi.raw.cython_converters cimport c_get_mech_oid_set
from gssapi.raw.cython_converters cimport c_create_oid_set
from gssapi.raw.cython_converters cimport c_py_ttl_to_c, c_c_ttl_to_py
from gssapi.raw.creds cimport Creds
from gssapi.raw.names cimport Name
from gssapi.raw.oids cimport OID

from gssapi.raw.misc import GSSError
from gssapi.raw.named_tuples import AddCredResult

cdef extern from "gssapi/gssapi_ext.h":
OM_uint32 gss_add_cred_with_password(OM_uint32 *min_stat,
const gss_cred_id_t input_cred_handle,
const gss_name_t desired_name,
const gss_OID desired_mech,
const gss_buffer_t password,
gss_cred_usage_t cred_usage,
OM_uint32 initiator_ttl,
OM_uint32 acceptor_ttl,
gss_cred_id_t *output_creds,
gss_OID_set *actual_mechs,
OM_uint32 *actual_init_ttl,
OM_uint32 *actual_accept_ttl) nogil
def add_cred_with_password(Creds input_cred not None, Name name not None,
OID mech not None, password not None,
usage="initiate", init_lifetime=None,
accept_lifetime=None):

"""
Add a credential-element to a credential using provided password.
This function is originally from Solaris and is not documented by either
MIT or Heimdal.
Args:
input_cred (Creds): the credentials to add to
name (Name): the name to acquire credentials for
mech (MechType): the desired mechanism. Note that this is both
singular and required
password (str): the password used to acquire credentialss with
usage (str): the usage type for the credentials: may be
'initiate', 'accept', or 'both'
init_lifetime (int): the lifetime for the credentials to remain valid
when using them to initiate security contexts (or None for
indefinite)
accept_lifetime (int): the lifetime for the credentials to remain
valid when using them to accept security contexts (or None for
indefinite)
Returns:
AddCredResult: the actual mechanisms with which the credentials may be
used, the actual initiator TTL, and the actual acceptor TTL (the TTLs
may be None for indefinite or not supported)
Raises:
GSSError
"""

cdef gss_buffer_desc password_buffer = gss_buffer_desc(len(password),
password)

cdef gss_cred_usage_t c_usage
if usage == "initiate":
c_usage = GSS_C_INITIATE
elif usage == "accept":
c_usage = GSS_C_ACCEPT
else:
c_usage = GSS_C_BOTH

cdef OM_uint32 input_initiator_ttl = c_py_ttl_to_c(init_lifetime)
cdef OM_uint32 input_acceptor_ttl = c_py_ttl_to_c(accept_lifetime)

cdef gss_cred_id_t creds
cdef gss_OID_set actual_mechs
cdef OM_uint32 actual_initiator_ttl
cdef OM_uint32 actual_acceptor_ttl

cdef OM_uint32 maj_stat, min_stat

with nogil:
maj_stat = gss_add_cred_with_password(
&min_stat, input_cred.raw_creds, name.raw_name, &mech.raw_oid,
&password_buffer, c_usage, input_initiator_ttl,
input_acceptor_ttl, &creds, &actual_mechs, &actual_initiator_ttl,
&actual_acceptor_ttl)

cdef Creds rc
if maj_stat == GSS_S_COMPLETE:
rc = Creds()
rc.raw_creds = creds
return AddCredResult(rc, c_create_oid_set(actual_mechs),
c_c_ttl_to_py(actual_initiator_ttl),
c_c_ttl_to_py(actual_acceptor_ttl))
else:
raise GSSError(maj_stat, min_stat)
29 changes: 29 additions & 0 deletions gssapi/tests/test_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ def tearDownClass(cls):


class TestBaseUtilities(_GSSAPIKerberosTestCase):
def setUp(self):
self.kinit(SERVICE_PRINCIPAL.decode("UTF-8"), flags=['-k'])

def test_indicate_mechs(self):
mechs = gb.indicate_mechs()

Expand Down Expand Up @@ -449,6 +452,32 @@ def test_inquire_mechs_for_name(self):
res.shouldnt_be_none()
res.should_include(gb.MechType.kerberos)

@_extension_test('password', 'Password')
def test_acquire_cred_with_password(self):
self.kinit('user')

name = gb.import_name(SERVICE_PRINCIPAL,
gb.NameType.kerberos_principal)
password = self.password('user')

imp_resp = gb.acquire_cred_with_password(name, password, usage='both')
imp_resp.shouldnt_be_none()

imp_creds, actual_mechs, output_ttl = imp_resp

imp_creds.shouldnt_be_none()
imp_creds.should_be_a(gb.Creds)

actual_mechs.shouldnt_be_empty()
actual_mechs.should_include(gb.MechType.kerberos)

output_ttl.should_be_a(int)
pass

@_extension_test('password_add', 'Password (add)')
def test_add_cred_with_password(self):
pass


class TestIntEnumFlagSet(unittest.TestCase):
def test_create_from_int(self):
Expand Down
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ def gssapi_modules(lst):
extension_file('cred_store', 'gss_store_cred_into'),
extension_file('rfc5588', 'gss_store_cred'),
extension_file('cred_imp_exp', 'gss_import_cred'),

# see ext_password{,_add}.pyx for more information on this split
extension_file('password', 'gss_acquire_cred_with_password'),
extension_file('password_add', 'gss_add_cred_with_password'),
]),
keywords=['gssapi', 'security'],
install_requires=[
Expand Down

0 comments on commit 35ffd22

Please sign in to comment.