From b5b8f38e4d01fe2fd55129f965aa9183d7c5c568 Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Wed, 18 Mar 2015 15:23:21 -0400 Subject: [PATCH 1/5] Structural Revamp This commit revamps the general structure of the documentation, focusing on more human-readable sections with actual descriptions, and class grouping. It also switches to the ReadTheDocs theme. --- .travis.before-deploy.sh | 3 + docs-requirements.txt | 3 + docs/source/conf.py | 7 +- docs/source/gssapi.raw.rst | 139 ++++++++++++++++++------------------- docs/source/gssapi.rst | 78 ++++++++++++++++----- docs/source/index.rst | 19 ++++- 6 files changed, 154 insertions(+), 95 deletions(-) create mode 100644 docs-requirements.txt diff --git a/.travis.before-deploy.sh b/.travis.before-deploy.sh index 45b8c1e5..f037868a 100755 --- a/.travis.before-deploy.sh +++ b/.travis.before-deploy.sh @@ -19,3 +19,6 @@ PKG_NAME_VER="python-gssapi-${PYTHON_GSSAPI_VERSION}" tar -czvf ./tag_build/${PKG_NAME_VER}.tar.gz --exclude='tag_build' --exclude='.git' --transform "s,^\.,${PKG_NAME_VER}," . sha512sum --binary ./tag_build/${PKG_NAME_VER}.tar.gz > ./tag_build/${PKG_NAME_VER}.sha512sum + +# for the docs deploy +pip install -r test-requirements.txt diff --git a/docs-requirements.txt b/docs-requirements.txt new file mode 100644 index 00000000..16f5fda7 --- /dev/null +++ b/docs-requirements.txt @@ -0,0 +1,3 @@ +Sphinx >= 1.3.1 +sphinx-rtd-theme >= 0.1.7 +sphinxcontrib-napoleon >= 0.2.8 diff --git a/docs/source/conf.py b/docs/source/conf.py index fdb10c49..370012f2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -50,9 +50,9 @@ # built documents. # # The short X.Y version. -version = '1.0.0' +version = '1.1.0' # The full version, including alpha/beta/rc tags. -release = '1.0.0' +release = '1.1.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -77,6 +77,7 @@ # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True +add_module_names = False # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. @@ -96,7 +97,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the diff --git a/docs/source/gssapi.raw.rst b/docs/source/gssapi.raw.rst index 6248c1c4..bf507ca7 100644 --- a/docs/source/gssapi.raw.rst +++ b/docs/source/gssapi.raw.rst @@ -1,138 +1,135 @@ -raw Package -=========== +Low-Level API +============= -:mod:`raw` Package ------------------- +The low-level API contains a variety of functions that map directly to the +corresponding C functions. Additionally, it contains several basic wrapper +classes that wrap underlying C structs and automatically deallocate them +when the Python object itself is deallocated. -.. automodule:: gssapi.raw +Core RFC 2744 +------------- + +Names +~~~~~ + +.. automodule:: gssapi.raw.names :members: :undoc-members: - :show-inheritance: -:mod:`creds` Module -------------------- +Credentials +~~~~~~~~~~~ .. automodule:: gssapi.raw.creds :members: :undoc-members: - :show-inheritance: -:mod:`cython_converters` Module -------------------------------- +Security Contexts +~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.cython_converters +.. automodule:: gssapi.raw.sec_contexts :members: :undoc-members: - :show-inheritance: - -:mod:`exceptions` Module ------------------------- -.. automodule:: gssapi.raw.exceptions +.. automodule:: gssapi.raw.message :members: :undoc-members: - :show-inheritance: -:mod:`ext_cred_store` Module ----------------------------- +Misc +~~~~ -.. automodule:: gssapi.raw.ext_cred_store +.. automodule:: gssapi.raw.oids :members: :undoc-members: - :show-inheritance: -:mod:`ext_rfc5588` Module -------------------------- - -.. automodule:: gssapi.raw.ext_rfc5588 +.. automodule:: gssapi.raw.misc :members: :undoc-members: - :show-inheritance: -:mod:`ext_s4u` Module ---------------------- +.. automodule:: gssapi.raw.types + :members: + :undoc-members: -.. automodule:: gssapi.raw.ext_s4u +.. automodule:: gssapi.raw.chan_bindings :members: :undoc-members: - :show-inheritance: -:mod:`ext_password` Module ---------------------- +Extensions +---------- -.. automodule:: gssapi.raw.ext_password +The following is a list of GSSAPI extensions supported by the low-level API. +Ones supported by the high-level API are marked as such. Note that while +all of these extensions have bindings, they may not be supported by your +particularly GSSAPI implementation, in which case they will simply not be +compiled. + +:rfc:`5588` (GSS-API Extension for Storing Delegated Credentials) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. automodule:: gssapi.raw.ext_rfc5588 :members: :undoc-members: - :show-inheritance: -:mod:`ext_password_add` Module ---------------------- +Credential Store Extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.ext_password_add +.. automodule:: gssapi.raw.ext_cred_store :members: :undoc-members: - :show-inheritance: -:mod:`mech_krb5` Module ------------------------ +:rfc:`6680` (GSS-API Naming Extensions) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.mech_krb5 +.. automodule:: gssapi.raw.ext_rfc6680 :members: :undoc-members: - :show-inheritance: - -:mod:`message` Module ---------------------- -.. automodule:: gssapi.raw.message +.. automodule:: gssapi.raw.ext_rfc6680_comp_oid :members: :undoc-members: - :show-inheritance: -:mod:`misc` Module ------------------- +Credentials Import-Export Extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.misc +.. automodule:: gssapi.raw.ext_cred_imp_exp :members: :undoc-members: - :show-inheritance: -:mod:`names` Module -------------------- +DCE (IOV/AEAD) Extensions +~~~~~~~~~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.names +.. automodule:: gssapi.raw.ext_dce :members: :undoc-members: - :show-inheritance: -:mod:`oids` Module ------------------- +IOV MIC Extensions +~~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.oids +.. automodule:: gssapi.raw.ext_iov_mic :members: :undoc-members: - :show-inheritance: -:mod:`sec_contexts` Module --------------------------- +Services4User Extensions +~~~~~~~~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.sec_contexts +.. automodule:: gssapi.raw.ext_s4u :members: :undoc-members: - :show-inheritance: -:mod:`types` Module -------------------- +Acquiring Credentials With a Password Extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. automodule:: gssapi.raw.types +.. automodule:: gssapi.raw.ext_password + :members: + :undoc-members: + +.. automodule:: gssapi.raw.ext_password_add :members: :undoc-members: - :show-inheritance: -:mod:`named_tuples` Module --------------------------- +Exceptions +---------- -.. automodule:: gssapi.raw.named_tuples +.. automodule:: gssapi.raw.exceptions :members: :undoc-members: :show-inheritance: diff --git a/docs/source/gssapi.rst b/docs/source/gssapi.rst index 20aa999f..d85785e3 100644 --- a/docs/source/gssapi.rst +++ b/docs/source/gssapi.rst @@ -1,42 +1,84 @@ -gssapi Package +High-Level API ============== -:mod:`creds` Module --------------------- +The high-level API contains three main classes for interacting with GSSAPI, +representing the primary abstractions that GSSAPI provides: +:class:`~gssapi.names.Name`, :class:`~gssapi.creds.Credentials`, and +:class:`~gssapi.sec_contexts.SecurityContext`. Note that classes in +the high-level API inherit from the corresponding classes in the +low-level API, and thus may be passed in to low-level API functions. + +Main Classes +------------ + +.. automodule:: gssapi.names + :members: + :undoc-members: + :inherited-members: .. automodule:: gssapi.creds :members: :undoc-members: - :show-inheritance: + :inherited-members: + +.. automodule:: gssapi.sec_contexts + :members: + :undoc-members: + :inherited-members: -:mod:`exceptions` Module +Enums and Helper Classes ------------------------ -.. automodule:: gssapi.exceptions +The following enumerations from the low-level API are also +used with the high-level API. For convienience, the are +imported in the high-level API :mod:`gssapi` module: + +.. autoclass:: gssapi.raw.types.NameType :members: :undoc-members: :show-inheritance: + :noindex: -:mod:`names` Module -------------------- - -.. automodule:: gssapi.names +.. autoclass:: gssapi.raw.types.MechType :members: :undoc-members: :show-inheritance: + :noindex: -:mod:`sec_contexts` Module --------------------------- +.. TODO(directxman12): Sphinx doesn't document enums properly yet, + so we need to figure out how to document them. -.. automodule:: gssapi.sec_contexts +.. autoclass:: gssapi.raw.types.RequirementFlag + :show-inheritance: + :noindex: + +.. autoclass:: gssapi.raw.types.AddressType + :show-inheritance: + :noindex: + +Similiarly, there are a couple classes from the low-level API +that are imported into the high-level API module. These classes +are less likely to be used directly by a user, but are returned +by several methods: + +.. autoclass:: gssapi.raw.oids.OID + :members: + :noindex: + +.. autoclass:: gssapi.raw.types.IntEnumFlagSet :members: :undoc-members: :show-inheritance: + :noindex: -Subpackages ------------ - -.. toctree:: +Exceptions +---------- - gssapi.raw +The high-level API can raise all of the exceptions that the low-level API +can raise in addition to several other high-level-specific exceptions: +.. automodule:: gssapi.exceptions + :members: + :undoc-members: + :show-inheritance: + :imported-members: diff --git a/docs/source/index.rst b/docs/source/index.rst index 1593e5db..4724fce5 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -3,14 +3,27 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to Python-GSSAPI's documentation! -==================================== +Python-GSSAPI: Python bindings for GSSAPI +========================================= + +Python-GSSAPI provides Python bindings for the GSSAPI C bindings as defined +by :rfc:`2744`, as well as several extensions. + +The package is organized into two parts: a high-level API and a low-level API. +The high-level API resides in :mod:`gssapi`, and presents an object-oriented +API around GSSAPI. + +The other part of Python-GSSAPI is the low-level API, which resides in +:mod:`gssapi.raw`. The low-level API provides thin wrappers around the +corresponding C functions. The high-level API makes use of the low-level API +to access underlying GSSAPI functionality. Additionally certain extensions +are currently only available from the low-level API. Contents: .. toctree:: :maxdepth: 2 - + gssapi.rst gssapi.raw.rst From 693c8f0f907c2de0c8fd49d4133991d3529fa557 Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Sat, 21 Mar 2015 00:00:03 -0400 Subject: [PATCH 2/5] Actually import set_encoding into the main module Previously, `set_encoding` was only available from `gssapi._utils`. However, `gssapi._utils` was not intended for external use, while `set_encoding` is intended for external use. Now, `set_encoding` is available from the main `gssapi` module. --- gssapi/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gssapi/__init__.py b/gssapi/__init__.py index 901448fb..b533cf4f 100644 --- a/gssapi/__init__.py +++ b/gssapi/__init__.py @@ -6,4 +6,6 @@ from gssapi.names import Name # noqa from gssapi.sec_contexts import SecurityContext # noqa +from gssapi._utils import set_encoding # noqa + """The High-Level GSSAPI Wrapper""" From c758fd4de98f47839dd32c48977d89a3ca7cc695 Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Sat, 21 Mar 2015 00:52:02 -0400 Subject: [PATCH 3/5] High-Level Documentation Updates This commit updates the high-level documentation. Typos were corrected, improvements were made for readability, and more links were inserted. Additionally, two custom Sphinx extensions were added to help with the process: The first extension catches unknown class references and attempts to track them down. The class is searched for as if it were an `:any:` reference. The results from this searched are used, prefering results in the current API level (high-level vs low-level). The second extension adds a convinience role, `:requires-ext`, which inserts a link and some text indicating that a particular extension is required. If the extension is an RFC, a link to the RFC is generated, otherwise, a link to the low-level API module is generated. In the latter case, the text of the link is generated using the first line of the docstring of the low-level module, if it is present. Otherwise, the partial name of the module is used (the '%s' part of 'ext_%s') Finally, as per above, the docstrings of several extensions were updated. --- docs/custom_extensions/gssapi_find_missing.py | 63 +++++++++++ docs/custom_extensions/requires_rfc.py | 60 +++++++++++ docs/source/conf.py | 3 +- docs/source/gssapi.raw.rst | 29 +++-- docs/source/gssapi.rst | 42 ++++---- gssapi/__init__.py | 30 +++++- gssapi/creds.py | 102 +++++++++--------- gssapi/names.py | 73 ++++++++++--- gssapi/raw/ext_cred_imp_exp.pyx | 1 + gssapi/raw/ext_cred_store.pyx | 1 + gssapi/raw/ext_s4u.pyx | 1 + gssapi/sec_contexts.py | 69 +++++++----- 12 files changed, 348 insertions(+), 126 deletions(-) create mode 100644 docs/custom_extensions/gssapi_find_missing.py create mode 100644 docs/custom_extensions/requires_rfc.py diff --git a/docs/custom_extensions/gssapi_find_missing.py b/docs/custom_extensions/gssapi_find_missing.py new file mode 100644 index 00000000..4e064f85 --- /dev/null +++ b/docs/custom_extensions/gssapi_find_missing.py @@ -0,0 +1,63 @@ +from docutils import nodes +from sphinx.util.nodes import make_refnode + +MATCH_RE_RAW = r'\b(([A-Z][A-Za-z0-9]+)+)\b' + + +def setup(app): + app.connect('missing-reference', _missing_ref) + + +def _missing_ref(app, env, node, contnode): + # skip non-elements + if not isinstance(contnode, nodes.Element): + return + + if node.get('refdomain') != 'py': + return + + options = env.domains['py'].find_obj( + env, None, None, node.get('reftarget'), node.get('reftype'), 1) + + if not options: + return + + is_raw = node.get('py:module').startswith('gssapi.raw') + + if len(options) > 1: + raw_opts = [] + non_raw_opts = [] + for opt in options: + full_name, type_info = opt + mod_name, _mod_type = type_info + if mod_name.startswith('gssapi.raw'): + raw_opts.append(opt) + else: + non_raw_opts.append(opt) + + if is_raw: + if raw_opts: + choice = raw_opts[0] + elif non_raw_opts: + choice = non_raw_opts[0] + else: + return + else: + if non_raw_opts: + choice = non_raw_opts[0] + elif raw_opts: + choice = raw_opts[0] + else: + return + else: + choice = options[0] + + choice_name, choice_info = choice + choice_mod, choice_type = choice_info + + if choice_type == 'module': + return env.domains['py']._make_module_refnode( + app.builder, node.get('refdoc'), choice_name, contnode) + else: + return make_refnode(app.builder, node.get('refdoc'), choice_mod, + choice_name, contnode, choice_name) diff --git a/docs/custom_extensions/requires_rfc.py b/docs/custom_extensions/requires_rfc.py new file mode 100644 index 00000000..b77ff4fa --- /dev/null +++ b/docs/custom_extensions/requires_rfc.py @@ -0,0 +1,60 @@ +import sys + +from docutils import nodes +from docutils.parsers.rst import roles + + +def setup(app): + app.add_role('requires-ext', RequiresExtRole(app)) + + +class RequiresExtRole(object): + def __init__(self, app): + self.app = app + + def __call__(self, name, rawtext, text, lineno, inliner, + options={}, content=[]): + if text.startswith('rfc'): + rfc_text = text[3:] + + rfc_node, rfc_msg = roles.rfc_reference_role( + 'rfc', ':rfc:`%s`' % rfc_text, rfc_text, lineno, + inliner, options, content) + + if rfc_msg: + # error + return (rfc_node, rfc_msg) + else: + middle_parts = rfc_node + [nodes.Text(" extension", + " extension")] + else: + ext_name = 'gssapi.raw.ext_%s' % text + # autodoc has already imported everything + try: + ext_module = sys.modules[ext_name] + except KeyError: + ext_title = text + " extension" + else: + if ext_module.__doc__: + ext_title = ext_module.__doc__.splitlines()[0] + else: + ext_title = text + " extension" + ref_nodes, ref_messages = self.app.env.domains['py'].role('mod')( + 'mod', rawtext, ext_name, lineno, inliner) + + if ref_messages: + # error + return (ref_nodes, ref_messages) + + title_node = nodes.Text(ext_title, ext_title) + + ref_nodes[0].children = [title_node] + + middle_parts = ref_nodes + + begin_text = nodes.Text("requires the ", "requires the ") + + main_nodes = [begin_text] + middle_parts + wrapper_node = nodes.emphasis('', '', *main_nodes) + + return ([nodes.Text('', ''), wrapper_node, nodes.Text('', '')], []) diff --git a/docs/source/conf.py b/docs/source/conf.py index 370012f2..a80db3b2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,6 +19,7 @@ #sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('../..')) +sys.path.insert(0, os.path.abspath('../custom_extensions')) # -- General configuration ----------------------------------------------------- @@ -27,7 +28,7 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', "sphinxcontrib.napoleon"] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', "sphinxcontrib.napoleon", 'gssapi_find_missing', 'requires_rfc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/docs/source/gssapi.raw.rst b/docs/source/gssapi.raw.rst index bf507ca7..332c8636 100644 --- a/docs/source/gssapi.raw.rst +++ b/docs/source/gssapi.raw.rst @@ -1,10 +1,17 @@ Low-Level API ============= -The low-level API contains a variety of functions that map directly to the -corresponding C functions. Additionally, it contains several basic wrapper -classes that wrap underlying C structs and automatically deallocate them -when the Python object itself is deallocated. +.. py:module:: gssapi.raw + +The low-level API contains a variety of Python functions that map directly +to the corresponding C functions. Additionally, it contains several basic +wrapper classes that wrap underlying C structs and automatically deallocate +them when the Python object itself is deallocated. + +.. warning:: + + All methods in both the high-level and low-level APIs may throw the generic + GSSError exception. Core RFC 2744 ------------- @@ -53,14 +60,16 @@ Misc :members: :undoc-members: -Extensions ----------- +Additional RFCs and Extensions +------------------------------ The following is a list of GSSAPI extensions supported by the low-level API. -Ones supported by the high-level API are marked as such. Note that while -all of these extensions have bindings, they may not be supported by your -particularly GSSAPI implementation, in which case they will simply not be -compiled. + +.. note:: + While all of these extensions have bindings, they may not be supported + by your particularly GSSAPI implementation. In this case, they will not + be compiled, and will simply not be available in the :mod:`gssapi.raw` + namespace. :rfc:`5588` (GSS-API Extension for Storing Delegated Credentials) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/gssapi.rst b/docs/source/gssapi.rst index d85785e3..e6790f29 100644 --- a/docs/source/gssapi.rst +++ b/docs/source/gssapi.rst @@ -1,12 +1,22 @@ High-Level API ============== +.. py:module:: gssapi + The high-level API contains three main classes for interacting with GSSAPI, representing the primary abstractions that GSSAPI provides: :class:`~gssapi.names.Name`, :class:`~gssapi.creds.Credentials`, and -:class:`~gssapi.sec_contexts.SecurityContext`. Note that classes in -the high-level API inherit from the corresponding classes in the -low-level API, and thus may be passed in to low-level API functions. +:class:`~gssapi.sec_contexts.SecurityContext`. + +.. note:: + + Classes in the high-level API inherit from the corresponding classes in the + low-level API, and thus may be passed in to low-level API functions. + +.. warning:: + + All methods in both the high-level and low-level APIs may throw the generic + :class:`GSSError` exception. Main Classes ------------ @@ -14,17 +24,14 @@ Main Classes .. automodule:: gssapi.names :members: :undoc-members: - :inherited-members: .. automodule:: gssapi.creds :members: :undoc-members: - :inherited-members: .. automodule:: gssapi.sec_contexts :members: :undoc-members: - :inherited-members: Enums and Helper Classes ------------------------ @@ -33,43 +40,37 @@ The following enumerations from the low-level API are also used with the high-level API. For convienience, the are imported in the high-level API :mod:`gssapi` module: -.. autoclass:: gssapi.raw.types.NameType +.. autoclass:: gssapi.NameType :members: :undoc-members: :show-inheritance: - :noindex: -.. autoclass:: gssapi.raw.types.MechType +.. autoclass:: gssapi.MechType :members: :undoc-members: :show-inheritance: - :noindex: .. TODO(directxman12): Sphinx doesn't document enums properly yet, so we need to figure out how to document them. -.. autoclass:: gssapi.raw.types.RequirementFlag +.. autoclass:: gssapi.RequirementFlag :show-inheritance: - :noindex: -.. autoclass:: gssapi.raw.types.AddressType +.. autoclass:: gssapi.AddressType :show-inheritance: - :noindex: Similiarly, there are a couple classes from the low-level API that are imported into the high-level API module. These classes are less likely to be used directly by a user, but are returned by several methods: -.. autoclass:: gssapi.raw.oids.OID +.. autoclass:: gssapi.OID :members: - :noindex: -.. autoclass:: gssapi.raw.types.IntEnumFlagSet +.. autoclass:: gssapi.IntEnumFlagSet :members: :undoc-members: :show-inheritance: - :noindex: Exceptions ---------- @@ -82,3 +83,8 @@ can raise in addition to several other high-level-specific exceptions: :undoc-members: :show-inheritance: :imported-members: + +Utilities +--------- + +.. autofunction:: gssapi.set_encoding diff --git a/gssapi/__init__.py b/gssapi/__init__.py index b533cf4f..9c894529 100644 --- a/gssapi/__init__.py +++ b/gssapi/__init__.py @@ -1,3 +1,31 @@ +"""High-Level GSSAPI Bindings + +The high-level API contains three main classes, which represent +the primary abstractions that GSSAPI provides: + + Name (see gssapi.names) + + Credentials (see gssapi.creds) + + SecurityContext (see gssapi.sec_contexts) + +Additionally, a number of helper classes shared with the low-level API +exist as well: + + Enums (see gssapi.raw.types) -- + NameType, RequirementFlag, AddressType, MechType + + IntEnumFlagSet (see gssapi.raw.types) + + OID (see gssapi.raw.oids) + +Note: + + Classes in the high-level API inherit from the corresponding + classes in the low-level API, and thus may be passed in to + low-level API functions. +""" + from gssapi.raw.types import NameType, RequirementFlag, AddressType # noqa from gssapi.raw.types import MechType, IntEnumFlagSet # noqa from gssapi.raw.oids import OID # noqa @@ -7,5 +35,3 @@ from gssapi.sec_contexts import SecurityContext # noqa from gssapi._utils import set_encoding # noqa - -"""The High-Level GSSAPI Wrapper""" diff --git a/gssapi/creds.py b/gssapi/creds.py index 59496104..df051fb8 100644 --- a/gssapi/creds.py +++ b/gssapi/creds.py @@ -21,36 +21,33 @@ class Credentials(rcreds.Creds): If your implementation of GSSAPI supports the credentials import-export extension, you may pickle and unpickle this object. - """ - - __slots__ = () - def __new__(cls, base=None, token=None, name=None, lifetime=None, - mechs=None, usage='both', store=None): - """Acquire or import a set of credentials. + The constructor either acquires or imports a set of GSSAPI + credentials. - The constructor either acquires or imports a set of GSSAPI - credentials. + If the `base` argument is used, an existing + :class:`~gssapi.raw.creds.Cred` object from the low-level API is + converted into a high-level object. - If the `base` argument is used, an existing - :class:`~gssapi.raw.creds.Cred` object from the low-level API is - converted into a high-level object. + If the `token` argument is used, the credentials + are imported using the token, if the credentials import-export + extension is supported (:requires-ext:`cred_imp_exp`). - If the :python:`token` argument is used, the credentials - are imported using the token, if the credentials import-export - extension is supported. + Otherwise, the credentials are acquired as per the + :meth:`acquire` method. - Otherwise, the credentials are acquired as per the - :meth:`acquire` method. + Raises: + BadMechanismError + BadNameTypeError + BadNameError + ExpiredCredentialsError + MissingCredentialsError + """ - Raises: - BadMechanismError - BadNameTypeError - BadNameError - ExpiredCredentialsError - MissingCredentialsError - """ + __slots__ = () + def __new__(cls, base=None, token=None, name=None, lifetime=None, + mechs=None, usage='both', store=None): # TODO(directxman12): this is missing support for password # (non-RFC method) if base is not None: @@ -71,25 +68,25 @@ def __new__(cls, base=None, token=None, name=None, lifetime=None, @property def name(self): - """Get the name associated with the credentials""" + """Get the name associated with these credentials""" return self.inquire(name=True, lifetime=False, usage=False, mechs=False).name @property def lifetime(self): - """Get the remaining lifetime of the credentials""" + """Get the remaining lifetime of these credentials""" return self.inquire(name=False, lifetime=True, usage=False, mechs=False).lifetime @property def mechs(self): - """Get the mechanisms for the current credentials""" + """Get the mechanisms for these credentials""" return self.inquire(name=False, lifetime=False, usage=False, mechs=True).mechs @property def usage(self): - """Get the usage (initiate, accept, or both) of the credentials""" + """Get the usage (initiate, accept, or both) of these credentials""" return self.inquire(name=False, lifetime=False, usage=True, mechs=False).usage @@ -115,13 +112,13 @@ def acquire(cls, name=None, lifetime=None, mechs=None, usage='both', or None for the default name lifetime (int): the desired lifetime of the credentials, or None for indefinite - mechs (list): the desired mechanisms to be used with these + mechs (list): the desired :class:`MechType`s to be used with the credentials, or None for the default set - usage (str): the usage for these credentials -- either 'both', + usage (str): the usage for the credentials -- either 'both', 'initiate', or 'accept' store (dict): the credential store information pointing to the credential store from which to acquire the credentials, - or None for the default store + or None for the default store (:requires-ext:`cred_store`) Returns: AcquireCredResult: the acquired credentials and information about @@ -155,19 +152,22 @@ def acquire(cls, name=None, lifetime=None, mechs=None, usage='both', def store(self, store=None, usage='both', mech=None, overwrite=False, set_default=False): - """Store credentials to the given store + """Store these credentials into the given store This method stores the current credentials into the specified credentials store. If the default store is used, support for - RFC 5588 is required. Otherwise, support for the credentials + :rfc:`5588` is required. Otherwise, support for the credentials store extension is required. + :requires-ext:`rfc5588` or :requires-ext:`cred_store` + Args: store (dict): the store into which to store the credentials, or None for the default store. usage (str): the usage to store the credentials with -- either 'both', 'initiate', or 'accept' - mech (OID): the mechansim to associate with the stored credentials + mech (OID): the :class:`MechType` to associate with the + stored credentials overwrite (bool): whether or not to overwrite existing credentials stored with the same name, etc set_default (bool): whether or not to set these credentials as @@ -207,14 +207,15 @@ def impersonate(self, name=None, lifetime=None, mechs=None, """Impersonate a name using the current credentials This method acquires credentials by impersonating another - name using the current credentials. This requires the - Services4User extension. + name using the current credentials. + + :requires-ext:`s4u` Args: name (Name): the name to impersonate lifetime (int): the desired lifetime of the new credentials, or None for indefinite - mechs (list): the desired mechanisms for the new + mechs (list): the desired :class:`MechType`s for the new credentials usage (str): the desired usage for the new credentials -- either 'both', 'initiate', or 'accept'. Note that some mechanisms @@ -235,9 +236,9 @@ def impersonate(self, name=None, lifetime=None, mechs=None, return type(self)(base=res.creds) def inquire(self, name=True, lifetime=True, usage=True, mechs=True): - """Inspect the credentials for information + """Inspect these credentials for information - This method inspects the credentials for information about them. + This method inspects these credentials for information about them. Args: name (bool): get the name associated with the credentials @@ -267,10 +268,10 @@ def inquire(self, name=True, lifetime=True, usage=True, mechs=True): def inquire_by_mech(self, mech, name=True, init_lifetime=True, accept_lifetime=True, usage=True): - """Inspect the credentials for per-mechanism information + """Inspect these credentials for per-mechanism information - This method inspects the credentials for per-mechanism information - about them + This method inspects these credentials for per-mechanism information + about them. Args: mech (OID): the mechanism for which to retrive the information @@ -311,12 +312,12 @@ def add(self, name, mech, usage='both', mechanism. If the `impersonator` argument is used, the credentials will - impersonate the given name using the impersonator credentials. - This requires the Services4User extension. + impersonate the given name using the impersonator credentials + (:requires-ext:`s4u`). If the `store` argument is used, the credentials will be acquired - from the given credential store (if supported). Otherwise, the - credentials are acquired from the default store. + from the given credential store (:requires-ext:`cred_store`). + Otherwise, the credentials are acquired from the default store. The credential store information is a dictionary containing mechanisms-specific keys and values pointing to a credential store @@ -328,9 +329,9 @@ def add(self, name, mech, usage='both', Args: name (Name): the name associated with the credentials - mech (OID): the desired mechanism to be used with these + mech (OID): the desired :class:`MechType` to be used with the credentials - usage (str): the usage for these credentials -- either 'both', + usage (str): the usage for the credentials -- either 'both', 'initiate', or 'accept' init_lifetime (int): the desired initiate lifetime of the credentials, or None for indefinite @@ -338,9 +339,10 @@ def add(self, name, mech, usage='both', credentials, or None for indefinite impersonator (Credentials): the credentials to use to impersonate the given name, or None to not acquire normally + (:requires-ext:`s4u`) store (dict): the credential store information pointing to the credential store from which to acquire the credentials, - or None for the default store + or None for the default store (:requires-ext:`cred_store`) Returns: Credentials: the credentials set containing the current credentials @@ -384,13 +386,15 @@ def add(self, name, mech, usage='both', return Credentials(res.creds) def export(self): - """Export the credentials to a token + """Export these credentials into a token This method exports the current credentials to a token that can then be imported by passing the `token` argument to the constructor. This is often used to pass credentials between processes. + :requires-ext:`cred_imp_exp` + Returns: bytes: the exported credentials in token form """ diff --git a/gssapi/names.py b/gssapi/names.py index b5cad0b9..afa02ba3 100644 --- a/gssapi/names.py +++ b/gssapi/names.py @@ -12,7 +12,7 @@ class Name(rname.Name): - """GSSAPI Name + """A GSSAPI Name This class represents a GSSAPI name which may be used with used with and/or returned by other GSSAPI methods. @@ -24,6 +24,14 @@ class Name(rname.Name): The :func:`str` and :func:`bytes` methods may be used to retrieve the text of the name. + + Note: + Name strings will be automatically converted to and from unicode + strings as appropriate. If a method is listed as returning a + :class:`str` object, it will return a unicode string. + + The encoding used will be python-gssapi's current encoding, which + defaults to UTF-8. """ __slots__ = ('_attr_obj') @@ -65,11 +73,13 @@ def __new__(cls, base=None, name_type=None, token=None, return super(Name, cls).__new__(cls, base_name) def __init__(self, base=None, name_type=None, token=None, composite=False): - """Create or import a GSSAPI name - - The constructor either creates or imports a GSSAPI name. + """ + The constructor can be used to "import" a name from a human readable + representation, or from a token, and can also be used to convert a + low-level :class:`gssapi.raw.names.Name` object into a high-level + object. - If a :python:`~gssapi.raw.names.Name` object from the low-level API + If a :class:`~gssapi.raw.names.Name` object from the low-level API is passed as the `base` argument, it will be converted into a high-level object. @@ -78,7 +88,8 @@ def __init__(self, base=None, name_type=None, token=None, composite=False): pass `composite=True`. Otherwise, a new name will be created, using the `base` argument as - the string and the `name_type` argument to denote the name type. + the human-readable string and the `name_type` argument to denote the + name type. Raises: BadNameTypeError @@ -109,13 +120,16 @@ def __bytes__(self): def display_as(self, name_type): """ - Display the current name as the given name type. + Display this name as the given name type. - This method attempts to display the current Name using - the syntax of the given NameType, if possible. + This method attempts to display the current :class:`Name` + using the syntax of the given :class:`NameType`, if possible. + + :requires-ext:`rfc6680` Args: - name_type (OID): the NameType to use to display the given name + name_type (OID): the :class:`NameType` to use to display the given + name Returns: str: the displayed name @@ -133,7 +147,7 @@ def display_as(self, name_type): @property def name_type(self): - """Get the name type of this name""" + """The :class:`NameType` of this name""" return rname.display_name(self, name_type=True).name_type def __eq__(self, other): @@ -153,11 +167,15 @@ def __repr__(self): name_type=disp_res.name_type) def export(self, composite=False): - """Export the name + """Export this name as a token. This method exports the name into a byte string which can then be imported by using the `token` argument of the constructor. + Args: + composite (bool): whether or not use to a composite token -- + :requires-ext:`rfc6680` + Returns: bytes: the exported name in token form @@ -178,13 +196,13 @@ def export(self, composite=False): return rname.export_name(self) def canonicalize(self, mech): - """Canonicalize a name with respect to a mechanism + """Canonicalize a name with respect to a mechanism. - This method returns a new Name that is canonicalized according to - the given mechanism. + This method returns a new :class:`Name` that is canonicalized according + to the given mechanism. Args: - mech (OID): the mechanism type to use + mech (OID): the :class:`MechType` to use Returns: Name: the canonicalized name @@ -204,7 +222,7 @@ def __deepcopy__(self, memo): return type(self)(rname.duplicate_name(self)) def _inquire(self, **kwargs): - """Inspect the name for information + """Inspect this name for information. This method inspects the name for information. @@ -243,14 +261,35 @@ def _inquire(self, **kwargs): @property def is_mech_name(self): + """Whether or not this name is a mechanism name + (:requires-ext:`rfc6680`) + """ return self._inquire(mech_name=True).is_mech_name @property def mech(self): + """The mechanism associated with this name (:requires-ext:`rfc6680`) + """ return self._inquire(mech_name=True).mech @property def attributes(self): + """The attributes of this name (:requires-ext:`rfc6680`) + + The attributes are presenting in the form of a + :class:`~collections.MutableMapping` (a dict-like object). + + Retrieved values will always be in the form of :class:`frozensets`. + + When assigning values, if iterables are used, they be considered to be + the set of values for the given attribute. If a non-iterable is used, + it will be considered a single value, and automatically wrapped in an + iterable. + + Note: + String types (includes :class:`bytes`) are not considered to + be iterables in this case. + """ if self._attr_obj is None: raise NotImplementedError("Your GSSAPI implementation does not " "support RFC 6680 (the GSSAPI naming " diff --git a/gssapi/raw/ext_cred_imp_exp.pyx b/gssapi/raw/ext_cred_imp_exp.pyx index ee145948..071b8947 100644 --- a/gssapi/raw/ext_cred_imp_exp.pyx +++ b/gssapi/raw/ext_cred_imp_exp.pyx @@ -1,3 +1,4 @@ +"""Credentials Import/Export Extension""" GSSAPI="BASE" # This ensures that a full module is generated by Cython from gssapi.raw.cython_types cimport * diff --git a/gssapi/raw/ext_cred_store.pyx b/gssapi/raw/ext_cred_store.pyx index 27f079c9..53c8ffd3 100644 --- a/gssapi/raw/ext_cred_store.pyx +++ b/gssapi/raw/ext_cred_store.pyx @@ -1,3 +1,4 @@ +"""Credential Store Extension""" GSSAPI="BASE" # This ensures that a full module is generated by Cython from libc.string cimport memcmp, memcpy, memset diff --git a/gssapi/raw/ext_s4u.pyx b/gssapi/raw/ext_s4u.pyx index 4b3297fd..61f89cb9 100644 --- a/gssapi/raw/ext_s4u.pyx +++ b/gssapi/raw/ext_s4u.pyx @@ -1,3 +1,4 @@ +"""Service4User Extension""" GSSAPI="BASE" # This ensures that a full module is generated by Cython from gssapi.raw.cython_types cimport * diff --git a/gssapi/sec_contexts.py b/gssapi/sec_contexts.py index 2f684c47..5e13c323 100644 --- a/gssapi/sec_contexts.py +++ b/gssapi/sec_contexts.py @@ -121,7 +121,7 @@ def __init__(self, base=None, token=None, # TODO(directxman12): implement flag properties def get_signature(self, message): - """Calculate the signature for a message + """Calculate the signature for a message. This method calculates the signature (called a MIC) for the given message, which may be then used with @@ -145,10 +145,10 @@ def get_signature(self, message): return rmessage.get_mic(self, message) def verify_signature(self, message, mic): - """Verify the signature for a message + """Verify the signature for a message. This method verifies that a signature (generated by - :meth:`get_signature` is valid for the given method. + :meth:`get_signature` is valid for the given message. If the signature is valid, the method will return. Otherwise, it will raise an error. @@ -159,10 +159,7 @@ def verify_signature(self, message, mic): Raises: BadMICError: the signature was not valid - - Raises: InvalidTokenError - BadMICError DuplicateTokenError ExpiredTokenError TokenTooLateError @@ -176,8 +173,8 @@ def verify_signature(self, message, mic): def wrap(self, message, encrypt): """Wrap a message, optionally with encryption - This method generates a signature and uses it to - wrap the message, optionally encrypting it. + This wraps a message, signing it and optionally + encrypting it. Args: message (bytes): the message to wrap @@ -196,7 +193,7 @@ def wrap(self, message, encrypt): return rmessage.wrap(self, message, encrypt) def unwrap(self, message): - """Unwrap a wrapped message + """Unwrap a wrapped message. This method unwraps/unencrypts a wrapped message, verifying the signature along the way. @@ -222,7 +219,7 @@ def unwrap(self, message): return rmessage.unwrap(self, message) def encrypt(self, message): - """Encrypt a message + """Encrypt a message. This method wraps and encrypts a message, similarly to :meth:`wrap`. The difference is that encryption is always @@ -251,12 +248,13 @@ def encrypt(self, message): return res.message def decrypt(self, message): - """Decrypt a message + """Decrypt a message. This method decrypts and unwraps a message, verifying the signature along the way, similarly to :meth:`unwrap`. The difference is that - this method will raise an exception if encryption was by the context - and not used, and simply returns the decrypted message directly. + this method will raise an exception if encryption was established + by the context and not used, and simply returns the decrypted + message directly. Args: message (bytes): the encrypted message @@ -289,10 +287,10 @@ def decrypt(self, message): def get_wrap_size_limit(self, desired_output_size, encrypted=True): - """Get the maximum message size for a given wrapped message size + """Calculate the maximum message size for a given wrapped message size. This method calculates the maximum input message size for a given - wrapped/encrypted message size. + maximum wrapped/encrypted message size. Args: desired_output_size (int): the maximum output message size @@ -312,11 +310,14 @@ def get_wrap_size_limit(self, desired_output_size, encrypted) def process_token(self, token): - """Process an output token asynchronously + """Process an output token asynchronously. This method processes an output token even when the security context was not expecting it. + Warning: + This method is deprecated. + Args: token (bytes): the token to process @@ -328,7 +329,7 @@ def process_token(self, token): rsec_contexts.process_context_token(self, token) def export(self): - """Export a security context + """Export a security context. This method exports a security context, allowing it to be passed between processes. @@ -361,7 +362,7 @@ def _inquire(self, **kwargs): initiator_name (bool): get the initiator name for this context target_name (bool): get the target name for this context lifetime (bool): get the remaining lifetime for this context - mech (bool): get the mechanism used by this context + mech (bool): get the :class:`MechType` used by this context flags (bool): get the flags set on this context locally_init (bool): get whether this context was locally initiated complete (bool): get whether negotiation on this context has @@ -403,24 +404,24 @@ def _inquire(self, **kwargs): @property def lifetime(self): - """Get the amount of time for which the context remains valid""" + """The amount of time for which this context remains valid""" return rsec_contexts.context_time(self) initiator_name = _utils.inquire_property( - 'initiator_name', 'Get the Name of the initiator of this context') + 'initiator_name', 'The :class:`Name` of the initiator of this context') target_name = _utils.inquire_property( - 'target_name', 'Get the Name of the target of this context') + 'target_name', 'The :class:`Name` of the target of this context') mech = _utils.inquire_property( - 'mech', 'Get the mechanism in use by this context') + 'mech', 'The mechanism (:class:`MechType`) in use by this context') actual_flags = _utils.inquire_property( - 'flags', 'Get the flags set on this context') + 'flags', 'The flags set on this context') locally_initiated = _utils.inquire_property( - 'locally_init', 'Get whether this context was locally intiated') + 'locally_init', 'Whether this context was locally intiated') @property @_utils.check_last_err def complete(self): - """Get whether negotiation for this context has been completed""" + """Whether negotiation for this context has been completed""" if self._started: return self._inquire(complete=True).complete else: @@ -428,13 +429,14 @@ def complete(self): @_utils.catch_and_return_token def step(self, token=None): - """Perform a negotation step + """Perform a negotation step. This method performs a negotiation step based on the usage type - of this context. If `__DEFER_STEP_ERRORS__` is set to true, - this method will return a token, even when exceptions would be - thrown. The generated exception will be thrown on the next + of this context. If `__DEFER_STEP_ERRORS__` is set to True on + the class, this method will return a token, even when exceptions + would be thrown. The generated exception will be thrown on the next method call or property lookup on the context. + **This is the default behavior.** This method should be used in a while loop, as such: @@ -448,6 +450,15 @@ def step(self, token=None): except GSSError as e: handle_the_issue() + .. tip:: + + Disabling `__DEFER_STEP_ERRORS__` is rarely necessary. + When this method is used in a loop (as above), + `__DEFER_STEP_ERRORS__` will ensure that you always + send an error token when it's available, + keeping the other end of the security context updated + with the status of the negotiation. + Args: token (bytes): the input token from the other participant's step From 2572d5dded411aac845e65f13abe216c0e2e151e Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Wed, 22 Apr 2015 21:02:54 -0400 Subject: [PATCH 4/5] Low-level Documentation Updates This commit updates the low-level documentation, introducing method signatures as well as fixing typos. --- docs/source/gssapi.raw.rst | 6 ++++ gssapi/raw/creds.pyx | 23 +++++++++++--- gssapi/raw/ext_cred_imp_exp.pyx | 10 ++++-- gssapi/raw/ext_cred_store.pyx | 17 ++++++++--- gssapi/raw/ext_dce.pyx | 54 +++++++++++++++++++++------------ gssapi/raw/ext_iov_mic.pyx | 21 +++++++++---- gssapi/raw/ext_password.pyx | 4 +++ gssapi/raw/ext_password_add.pyx | 4 +++ gssapi/raw/ext_rfc5588.pyx | 5 ++- gssapi/raw/ext_rfc6680.pyx | 30 ++++++++++++------ gssapi/raw/ext_s4u.pyx | 6 +++- gssapi/raw/message.pyx | 5 +++ gssapi/raw/misc.pyx | 11 +++++-- gssapi/raw/names.pyx | 46 +++++++++++++++++----------- gssapi/raw/oids.pyx | 7 +++-- gssapi/raw/sec_contexts.pyx | 45 +++++++++++++++++++-------- gssapi/raw/types.pyx | 30 ++++++++---------- 17 files changed, 225 insertions(+), 99 deletions(-) diff --git a/docs/source/gssapi.raw.rst b/docs/source/gssapi.raw.rst index 332c8636..bebdeebd 100644 --- a/docs/source/gssapi.raw.rst +++ b/docs/source/gssapi.raw.rst @@ -19,6 +19,12 @@ Core RFC 2744 Names ~~~~~ +.. note:: + Some functions in the following section will refer to + "mechanism names". These are not names of mechanisms. + Instead, they are a special form of name specific to + a given mechanism. + .. automodule:: gssapi.raw.names :members: :undoc-members: diff --git a/gssapi/raw/creds.pyx b/gssapi/raw/creds.pyx index f207d2cd..a4240751 100644 --- a/gssapi/raw/creds.pyx +++ b/gssapi/raw/creds.pyx @@ -82,6 +82,7 @@ cdef class Creds: def acquire_cred(Name name=None, lifetime=None, mechs=None, usage='both'): """ + acquire_cred(name=None, lifetime=None, mechs=None, usage='both') Get GSSAPI credentials for the given name and mechanisms. This method gets GSSAPI credentials corresponding to the given name @@ -159,10 +160,15 @@ def acquire_cred(Name name=None, lifetime=None, mechs=None, usage='both'): def release_cred(Creds creds not None): """ + release_cred(creds) Release GSSAPI Credentials. This method releases GSSAPI credentials. + Warning: + This method is deprecated. Credentials are + automatically freed by Python. + Args: creds (Creds): the credentials in question @@ -180,7 +186,10 @@ def release_cred(Creds creds not None): def add_cred(Creds input_cred, Name name not None, OID mech not None, usage='initiate', init_lifetime=None, accept_lifetime=None, mutate_input=False): - """Add a credential element to a credential. + """ + add_cred(input_cred, name, mech, usage='initiate', init_lifetime=None, \ +accept_lifetime=None, mutate_input=False) + Add a credential element to a credential. This method can be used to either compose two credentials (i.e., original and new credential), or to add a new element to an existing credential. @@ -264,7 +273,9 @@ def add_cred(Creds input_cred, Name name not None, OID mech not None, def inquire_cred(Creds creds not None, name=True, lifetime=True, usage=True, mechs=True): - """Inspect credentials for information + """ + inquire_cred(creds, name=True, lifetime=True, usage=True, mechs=True) + Inspect credentials for information. This method inspects a :class:`Creds` object for information. @@ -343,10 +354,14 @@ def inquire_cred(Creds creds not None, name=True, lifetime=True, usage=True, def inquire_cred_by_mech(Creds creds not None, OID mech not None, name=True, init_lifetime=True, accept_lifetime=True, usage=True): - """Inspect credentials for mechanism-specific + """ + inquire_cred_by_mech(creds, mech, name=True, init_lifetime=True, \ +accept_lifetime=True, usage=True) + Inspect credentials for mechanism-specific information. This method inspects a :class:`Creds` object for information - specific to a particular mechanism. + specific to a particular mechanism. It functions similarly + to :func:`inquire_cred`. Args: creds (Creds): the credentials to inspect diff --git a/gssapi/raw/ext_cred_imp_exp.pyx b/gssapi/raw/ext_cred_imp_exp.pyx index 071b8947..2f980603 100644 --- a/gssapi/raw/ext_cred_imp_exp.pyx +++ b/gssapi/raw/ext_cred_imp_exp.pyx @@ -22,9 +22,11 @@ cdef extern from "python_gssapi_ext.h": def export_cred(Creds creds not None): - """Export GSSAPI credentials object + """ + export_cred(creds) + Export GSSAPI credentials. - This method exports a GSSSAPI credentials object into a token + This method exports GSSSAPI credentials into a token which may be transmitted between different processes. Args: @@ -54,7 +56,9 @@ def export_cred(Creds creds not None): def import_cred(token not None): - """Import GSSAPI credentials from a token + """ + import_cred(token) + Import GSSAPI credentials from a token. This method imports a credentials object from a token previously exported by :func:`export_cred`. diff --git a/gssapi/raw/ext_cred_store.pyx b/gssapi/raw/ext_cred_store.pyx index 53c8ffd3..be26a142 100644 --- a/gssapi/raw/ext_cred_store.pyx +++ b/gssapi/raw/ext_cred_store.pyx @@ -95,7 +95,10 @@ cdef void c_free_key_value_set(gss_key_value_set_desc *kvset): def acquire_cred_from(dict store=None, Name name=None, lifetime=None, mechs=None, usage='both'): - """Acquire credentials from the given store + """ + acquire_cred_from(store=None, name=None, lifetime=None, mechs=None, \ +usage='both') + Acquire credentials from the given store. This method acquires credentials from the store specified by the given credential store information. @@ -183,12 +186,15 @@ def add_cred_from(dict store, Creds input_creds, Name name not None, OID mech not None, usage='both', init_lifetime=None, accept_lifetime=None): - """Acquire credentials to add to the current set from the given store + """ + add_cred_from(store, input_creds, name, mech, usage='both', \ +init_lifetime=None, accept_lifetime=None) + Acquire credentials to add to the current set from the given store. This method works like :func:`acquire_cred_from`, except that it adds the acquired credentials for a single mechanism to a copy of the current set, instead of creating a new set for multiple mechanisms. - Unlike :meth:`acquire`, you cannot pass None desired name or + Unlike :func:`acquire_cred`, you cannot pass None for the desired name or mechanism. The credential store information is a dictionary containing @@ -273,7 +279,10 @@ def add_cred_from(dict store, Creds input_creds, def store_cred_into(dict store, Creds creds not None, usage='both', OID mech=None, bint overwrite=False, bint set_default=False): - """Store credentials to the given store + """ + store_cred_into(store, creds, usage='both', mech=None, overwrite=False, \ +set_default=False) + Store credentials into the given store. This method stores the given credentials into the store specified by the given store information. They may then be retrieved later using diff --git a/gssapi/raw/ext_dce.pyx b/gssapi/raw/ext_dce.pyx index a005ef1b..e23bb899 100644 --- a/gssapi/raw/ext_dce.pyx +++ b/gssapi/raw/ext_dce.pyx @@ -91,6 +91,7 @@ IOVBuffer = namedtuple('IOVBuffer', ['type', 'allocate', 'value']) cdef class IOV: + """A GSSAPI IOV""" # defined in ext_dce.pxd # cdef int iov_len @@ -304,24 +305,28 @@ cdef class IOV: def wrap_iov(SecurityContext context not None, IOV message not None, confidential=True, qop=None): """ - Wrap/Encrypt an IOV message + wrap_iov(context, message, confidential=True, qop=None) + Wrap/Encrypt an IOV message. This method wraps or encrypts an IOV message. The allocate - parameter of the :class:`IOVBuffer` indicates whether or - not that particular buffer should be automatically allocated - (for use with padding, header, and trailer buffers). + parameter of the :class:`IOVBuffer` objects in the :class:`IOV` + indicates whether or not that particular buffer should be + automatically allocated (for use with padding, header, and + trailer buffers). + + Warning: + This modifies the input :class:`IOV`. Args: context (SecurityContext): the current security context - message (list): a list of :class:`IOVBuffer` objects + message (IOV): an :class:`IOV` containing the message confidential (bool): whether or not to encrypt the message (True), or just wrap it with a MIC (False) qop (int): the desired Quality of Protection (or None for the default QoP) Returns: - WrapResult: the wrapped/encrypted message (IOV list), and - whether or not encryption was actually used + bool: whether or not confidentiality was actually used Raises: GSSError @@ -348,12 +353,14 @@ def wrap_iov(SecurityContext context not None, IOV message not None, def unwrap_iov(SecurityContext context not None, IOV message not None): """ - Unwrap/Decrypt an IOV message + unwrap_iov(context, message) + Unwrap/Decrypt an IOV message. - This method unwraps or decrypts an IOV message. The allocate - parameter of the :class:`IOVBuffer` indicates whether or - not that particular buffer should be automatically allocated - (for use with padding, header, and trailer buffers). + This method uwraps or decrypts an IOV message. The allocate + parameter of the :class:`IOVBuffer` objects in the :class:`IOV` + indicates whether or not that particular buffer should be + automatically allocated (for use with padding, header, and + trailer buffers). As a special case, you may pass an entire IOV message as a single 'stream'. In this case, pass a buffer type @@ -361,13 +368,16 @@ def unwrap_iov(SecurityContext context not None, IOV message not None): :attr:`IOVBufferType.data`. The former should contain the entire IOV message, while the latter should be empty. + Warning: + This modifies the input :class:`IOV`. + Args: context (SecurityContext): the current security context - message (list): a list of :class:`IOVBuffer` objects + message (IOV): an :class:`IOV` containing the message Returns: - UnwrapResult: the unwrapped/decrypted message, whether or not - encryption was used, and the QoP used + IOVUnwrapResult: whether or not confidentiality was used, + and the QoP used. Raises: GSSError @@ -393,7 +403,8 @@ def unwrap_iov(SecurityContext context not None, IOV message not None): def wrap_iov_length(SecurityContext context not None, IOV message not None, confidential=True, qop=None): """ - Appropriately size padding, trailer, and header IOV buffers + wrap_iov_length(context, message, confidential=True, qop=None) + Appropriately size padding, trailer, and header IOV buffers. This method sets the length values on the IOV buffers. You should already have data provided for the data (and sign-only) @@ -402,9 +413,12 @@ def wrap_iov_length(SecurityContext context not None, IOV message not None, In Python terms, this will result in an appropriately sized `bytes` object consisting of all zeros. + Warning: + This modifies the input :class:`IOV`. + Args: context (SecurityContext): the current security context - message (list): a list of :class:`IOVBuffer` objects + message (IOV): an :class:`IOV` containing the message Returns: WrapResult: a list of :class:IOVBuffer` objects, and whether or not @@ -437,7 +451,8 @@ def wrap_iov_length(SecurityContext context not None, IOV message not None, def wrap_aead(SecurityContext context not None, bytes message not None, bytes associated=None, confidential=True, qop=None): """ - Wrap/Encrypt an AEAD Message + wrap_aead(context, message, associated=None, confidential=True, qop=None) + Wrap/Encrypt an AEAD message. This method takes an input message and associated data, and outputs and AEAD message. @@ -492,7 +507,8 @@ def wrap_aead(SecurityContext context not None, bytes message not None, def unwrap_aead(SecurityContext context not None, bytes message not None, bytes associated=None): """ - Unwrap/Decrypt an AEAD Message + unwrap_aead(context, message, associated=None) + Unwrap/Decrypt an AEAD message. This method takes an encrpyted/wrapped AEAD message and some associated data, and returns an unwrapped/decrypted message. diff --git a/gssapi/raw/ext_iov_mic.pyx b/gssapi/raw/ext_iov_mic.pyx index a41e6c38..d18576f5 100644 --- a/gssapi/raw/ext_iov_mic.pyx +++ b/gssapi/raw/ext_iov_mic.pyx @@ -34,15 +34,19 @@ IOV.AUTO_ALLOC_BUFFERS.add(IOVBufferType.mic_token) def get_mic_iov(SecurityContext context not None, IOV message not None, qop=None): """ - Generate MIC tokens for the given IOV message + get_mic_iov(context, message, qop=None) + Generate MIC tokens for the given IOV message. This method generates a MIC token for the given IOV message, and places it in the :attr:`IOVBufferType.mic_token` buffer in the IOV. This method operates entirely in-place, and returns nothing. + Warning: + This modifies the input :class:`IOV`. + Args: context (SecurityContext): the current security context - message (list): a list of :class:`IOVBuffer` objects + message (IOV): the :class:`IOV` containing the message qop (int): the desired Quality of Protection (or None for the default QoP) @@ -70,14 +74,18 @@ def get_mic_iov(SecurityContext context not None, IOV message not None, def get_mic_iov_length(SecurityContext context not None, IOV message not None, qop=None): """ - Allocate space for the MIC buffer in the given IOV message + get_mic_iov_length(context, message, qop=None) + Allocate space for the MIC buffer in the given IOV message. This method allocates space for the MIC token buffer (:attr:`IOVBufferType.mic_token`) in the given IOV message. + Warning: + This modifies the input :class:`IOV`. + Args: context (SecurityContext): the current security context - message (list): a list of :class:`IOVBuffer` objects + message (IOV): the :class:`IOV` containing the message qop (int): the desired Quality of Protection (or None for the default QoP) @@ -105,7 +113,8 @@ def get_mic_iov_length(SecurityContext context not None, IOV message not None, def verify_mic_iov(SecurityContext context not None, IOV message not None, qop=None): """ - Verify that the MIC matches the data in the given IOV message + verify_mic_iov(context, message, qop=None) + Verify that the MIC matches the data in the given IOV message. This method verifies that the MIC token in the MIC buffer (:attr:`IOVBufferType.mic_token`) match the data buffer(s) @@ -113,7 +122,7 @@ def verify_mic_iov(SecurityContext context not None, IOV message not None, Args: context (SecurityContext): the current security context - message (list): a list of :class:`IOVBuffer` objects + message (IOV): the :class:`IOV` containing the message Returns: int: the QoP used to generate the MIC token diff --git a/gssapi/raw/ext_password.pyx b/gssapi/raw/ext_password.pyx index 9ad8a5c4..be960f97 100644 --- a/gssapi/raw/ext_password.pyx +++ b/gssapi/raw/ext_password.pyx @@ -30,11 +30,15 @@ cdef extern from "python_gssapi_ext.h": def acquire_cred_with_password(Name name not None, password not None, lifetime=None, mechs=None, usage="initiate"): """ + acquire_cred_with_password(name, password, 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. + In general, it functions similarly to :func:`acquire_cred`. + Args: name (Name): the name to acquire credentials for password (bytes): the password used to acquire credentialss with diff --git a/gssapi/raw/ext_password_add.pyx b/gssapi/raw/ext_password_add.pyx index 968f1c0d..aed3cd05 100644 --- a/gssapi/raw/ext_password_add.pyx +++ b/gssapi/raw/ext_password_add.pyx @@ -37,11 +37,15 @@ def add_cred_with_password(Creds input_cred not None, Name name not None, accept_lifetime=None): """ + add_cred_with_password(input_cred, name, mech, password, \ +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. + In general, it functions similarly to :func:`add_cred`. + Args: input_cred (Creds): the credentials to add to name (Name): the name to acquire credentials for diff --git a/gssapi/raw/ext_rfc5588.pyx b/gssapi/raw/ext_rfc5588.pyx index f552ee72..d87e6183 100644 --- a/gssapi/raw/ext_rfc5588.pyx +++ b/gssapi/raw/ext_rfc5588.pyx @@ -24,7 +24,10 @@ cdef extern from "python_gssapi.h": def store_cred(Creds creds not None, usage='both', OID mech=None, bint overwrite=False, bint set_default=False): - """Store credentials to the default store + """ + store_cred(creds, usage='both', mech=None, overwrite=False, \ +set_default=False) + Store credentials into the default store. This method stores the given credentials into the default store. They may then be retrieved later using :func:`acquire_cred`. diff --git a/gssapi/raw/ext_rfc6680.pyx b/gssapi/raw/ext_rfc6680.pyx index 3b9e0b89..1d8a0a2a 100644 --- a/gssapi/raw/ext_rfc6680.pyx +++ b/gssapi/raw/ext_rfc6680.pyx @@ -38,7 +38,8 @@ cdef extern from "python_gssapi_ext.h": def display_name_ext(Name name not None, OID name_type not None): """ - Display the given Name using the given name type OID + display_name_ext(name, name_type) + Display the given Name using the given name type. This method attempts to display the given Name using the syntax of the given name type. If this is not possible, an appropriate error @@ -75,12 +76,13 @@ def display_name_ext(Name name not None, OID name_type not None): def inquire_name(Name name not None, mech_name=True, attrs=True): """ - Get information about a Name + inquire_name(name, mech_name=True, attrs=True) + Get information about a Name. This method retrives information about the given name, including the set of attribute names for the given name, as well as whether or - not the name is a Mechanism Name. Additionally, if the given name is - a Mechanism Name, the associated mechansim is returned as well. + not the name is a mechanism name. Additionally, if the given name is + a mechanism name, the associated mechansim is returned as well. Args: name (Name): the name about which to inquire @@ -140,7 +142,8 @@ def inquire_name(Name name not None, mech_name=True, attrs=True): def set_name_attribute(Name name not None, attr not None, value not None, bint complete=False): """ - Set the value(s) of a Name attribute + set_name_attribute(name, attr, value, complete=False) + Set the value(s) of a name attribute. This method sets the value(s) of the given attribute on the given name. @@ -185,7 +188,8 @@ def set_name_attribute(Name name not None, attr not None, value not None, def get_name_attribute(Name name not None, attr not None, more=None): """ - Get the value(s) of a Name attribute + get_name_attribute(name, attr, more=None) + Get the value(s) of a name attribute. This method retrieves the value(s) of the given attribute for the given Name. @@ -244,7 +248,8 @@ def get_name_attribute(Name name not None, attr not None, more=None): def delete_name_attribute(Name name not None, attr not None): """ - Remove an attribute from a Name + delete_name_attribute(name, attr) + Remove an attribute from a name. This method removes an attribute from a Name. This method may be used before :func:`set_name_attribute` clear the values of an attribute @@ -275,11 +280,18 @@ def delete_name_attribute(Name name not None, attr not None): def export_name_composite(Name name not None): """ - Export a name, preserving attribute information + export_name_composite(name) + Export a name, preserving attribute information. This method functions similarly to :func:`export_name`, except that it preserves attribute information. The resulting bytes may be imported - using :func:`import_name` with the `NameType.composite_export` name type. + using :func:`import_name` with the :attr:`NameType.composite_export` + name type. + + Note: + Some versions of MIT Kerberos require you to either canonicalize a name + once it has been imported with composite-export name type, or to import + using the normal export name type. Args: name (Name): the name to export diff --git a/gssapi/raw/ext_s4u.pyx b/gssapi/raw/ext_s4u.pyx index 61f89cb9..a1269b35 100644 --- a/gssapi/raw/ext_s4u.pyx +++ b/gssapi/raw/ext_s4u.pyx @@ -42,6 +42,8 @@ def acquire_cred_impersonate_name(Creds impersonator_cred not None, Name name not None, lifetime=None, mechs=None, usage='initiate'): """ + acquire_cred_impersonate_name(impersonator_cred, name, lifetime=None, \ +mechs=None, usage='initiate') Acquire credentials by impersonating another name. This method is one of the ways to use S4U2Self. It acquires credentials @@ -116,7 +118,9 @@ def add_cred_impersonate_name(Creds input_cred, usage='initiate', init_lifetime=None, accept_lifetime=None): """ - Add a credential-element to a credential by impersonating another name. + add_cred_impersonate_name(input_cred, impersonator_cred, name, mech, \ +usage='initiate', init_lifetime=None, accept_lifetime=None) + Add a credentials element to a credential by impersonating another name. This method is one of the ways to use S4U2Self. It adds credentials to the input credentials by impersonating another name using a set of diff --git a/gssapi/raw/message.pyx b/gssapi/raw/message.pyx index 58a5aca2..97972082 100644 --- a/gssapi/raw/message.pyx +++ b/gssapi/raw/message.pyx @@ -45,6 +45,7 @@ cdef extern from "python_gssapi.h": def get_mic(SecurityContext context not None, message, qop=None): """ + get_mic(context, message, qop=None) Generate a MIC for a message. This method generates a Message Integrity Check token for the @@ -90,6 +91,7 @@ def get_mic(SecurityContext context not None, message, qop=None): def verify_mic(SecurityContext context not None, message, token): """ + verify_mic(context, message, token) Verify that a MIC matches a message. This method verifies that the given MIC matches the given message. @@ -136,6 +138,7 @@ def verify_mic(SecurityContext context not None, message, token): def wrap_size_limit(SecurityContext context not None, OM_uint32 output_size, confidential=True, qop=None): """ + wrap_size_limit(context, output_size, confidential=True, qop=None) Calculate the max message size. This method calculates the unwrapped/unencrypted message size for @@ -177,6 +180,7 @@ def wrap_size_limit(SecurityContext context not None, OM_uint32 output_size, def wrap(SecurityContext context not None, message, confidential=True, qop=None): """ + wrap(context, message, confidential=True, qop=None) Wrap/Encrypt a message. This method wraps or encrypts a message (depending on the value @@ -225,6 +229,7 @@ def wrap(SecurityContext context not None, message, confidential=True, def unwrap(SecurityContext context not None, message): """ + unwrap(context, message) Unwrap/Decrypt a message. This method unwraps or decrypts a message, depending diff --git a/gssapi/raw/misc.pyx b/gssapi/raw/misc.pyx index f101c89e..34d9e102 100644 --- a/gssapi/raw/misc.pyx +++ b/gssapi/raw/misc.pyx @@ -32,6 +32,7 @@ cdef extern from "python_gssapi.h": def indicate_mechs(): """ + indicate_mechs() Get the currently supported mechanisms. This method retrieves the currently supported GSSAPI mechanisms. @@ -51,7 +52,9 @@ def indicate_mechs(): def inquire_names_for_mech(OID mech not None): - """Get the name types supported by a mechanism. + """ + inquire_names_for_mech(mech) + Get the name types supported by a mechanism. This method retrives the different name types supported by the given mechanism. @@ -80,7 +83,9 @@ def inquire_names_for_mech(OID mech not None): def inquire_mechs_for_name(Name name not None): - """List the mechanisms which can process a name. + """ + inquire_mechs_for_name(name) + List the mechanisms which can process a name. This method lists the mechanisms which may be able to process the given name. @@ -216,7 +221,7 @@ class GSSErrorRegistry(type): # so that display_status can use it class GSSError(Exception, metaclass=GSSErrorRegistry): """ - GSSAPI Error + A GSSAPI Error This Exception represents an error returned from the GSSAPI C bindings. It contains the major and minor status codes diff --git a/gssapi/raw/names.pyx b/gssapi/raw/names.pyx index d1cbbe53..8c63eb51 100644 --- a/gssapi/raw/names.pyx +++ b/gssapi/raw/names.pyx @@ -42,7 +42,7 @@ cdef extern from "python_gssapi.h": cdef class Name: """ - A GSS API Name + A GSSAPI Name """ # defined in pxd # cdef gss_name_t raw_name @@ -67,10 +67,11 @@ cdef class Name: def import_name(name not None, OID name_type=None): """ - Convert a string and a NameType into a GSSAPI name. + import_name(name, name_type=None) + Convert a string and a name type into a GSSAPI name. This method takes a string name and a name type and converts - it into a GSSAPI Name. + them into a GSSAPI :class:`Name`. Args: name (bytes): the string version of the name @@ -114,11 +115,13 @@ def import_name(name not None, OID name_type=None): def display_name(Name name not None, name_type=True): """ + display_name(name, name_type=True) Convert a GSSAPI name into its components. - This method converts a GSSAPI name back into its text and - NameType parts. If name_type is True, it also attempts - to retrieve the name type of the name. + This method converts a GSSAPI :class:`Name` back into its + text form. If ``name_type`` is True, it also attempts to + retrieve the :class:`NameType` of the name (otherwise the + returned name type will be ``None``). Args: name (Name): the name in question @@ -167,6 +170,7 @@ def display_name(Name name not None, name_type=True): def compare_name(Name name1=None, Name name2=None): """ + compare_name(name1, name2) Check two GSSAPI names to see if they are the same. This method compares two GSSAPI names, checking to @@ -205,17 +209,14 @@ def compare_name(Name name1=None, Name name2=None): def export_name(Name name not None): """ - Export a GSSAPI Mechanim Name. + Export a GSSAPI name. This method "produces a canonical contigous string representation of a mechanism name, suitable for direct comparison for use in - authorization functions". The input name must be a valid GSSAPI - mechanism name, as generated by canonicalizeName or acceptSecContext. + authorization functions". - Note: - A mechanism name does not, in fact, refer to the name of a - mechanism. Instead, it refers to a canonicalized name, - such as the initiator name return by acceptSecContext + The input name must be a valid GSSAPI mechanism name, as generated + by :func:`canonicalize_name` or :func:`accept_sec_context`. Args: name (Name): the name to export @@ -248,11 +249,11 @@ def export_name(Name name not None): def canonicalize_name(Name name not None, OID mech not None): """ + canonicalize_name(name, mech) Canonicalize an arbitrary GSSAPI Name into a Mechanism Name - This method turns any GSSAPI name into a "mechanism name", - i.e. a name that would be returned as an initiator princiapl - from acceptSecContext. + This method turns any GSSAPI name into a "mechanism name" -- + a full form name specific to a mechanism. Args: name (Name): the name to canonicalize @@ -287,7 +288,8 @@ def canonicalize_name(Name name not None, OID mech not None): def duplicate_name(Name name not None): """ - Duplicate a GSSAPI Name + duplicate_name(name) + Duplicate a GSSAPI name. Args: name (Name): the name to duplicate @@ -315,7 +317,15 @@ def duplicate_name(Name name not None): def release_name(Name name not None): """ - Release a GSSAPI Name. + release_name(name) + Release a GSSAPI name. + + This method frees a GSSAPI :class:`Name`. + You probably won't have to do this. + + Warning: + This method is deprecated. Names are + automatically freed by Python. Args: name (Name): the name in question diff --git a/gssapi/raw/oids.pyx b/gssapi/raw/oids.pyx index cd54d90f..d40157c0 100644 --- a/gssapi/raw/oids.pyx +++ b/gssapi/raw/oids.pyx @@ -13,7 +13,8 @@ cdef inline bint c_compare_oids(gss_OID a, gss_OID b): cdef class OID: - """GSSAPI OID + """ + A GSSAPI OID A new OID may be created by passing the `elements` argument to the constructor. The `elements` argument should be a @@ -65,7 +66,9 @@ cdef class OID: @classmethod def from_int_seq(cls, integer_sequence): - """Create a OID from a sequence of integers + """ + from_int_seq(integer_sequence) + Create a OID from a sequence of integers. This method creates an OID from a sequence of integers. The sequence can either be in dotted form as a string, diff --git a/gssapi/raw/sec_contexts.pyx b/gssapi/raw/sec_contexts.pyx index 4dd72343..b3e766c7 100644 --- a/gssapi/raw/sec_contexts.pyx +++ b/gssapi/raw/sec_contexts.pyx @@ -76,7 +76,7 @@ cdef extern from "python_gssapi.h": cdef class SecurityContext: """ - A GSSAPI Context + A GSSAPI Security Context """ # defined in pxd # cdef gss_ctx_id_t raw_ctx @@ -116,7 +116,9 @@ def init_sec_context(Name target_name not None, Creds creds=None, ChannelBindings channel_bindings=None, input_token=None): """ - Initiate a GSSAPI Security Context. + init_sec_context(target_name, creds=None, context=None, mech=None, \ +flags=None, lifetime=None, channel_bindings=None, input_token=None) + Initiate a GSSAPI security context. This method initiates a GSSAPI security context, targeting the given target name. To create a basic context, just provide the target name. @@ -134,9 +136,10 @@ def init_sec_context(Name target_name not None, Creds creds=None, None to create a new context mech (MechType): the mechanism type for this security context, or None for the default mechanism type - flags ([RequirementFlag]): the flags to request for the security - context, or None to use the default set: mutual_authentication and - out_of_sequence_detection + flags (list): the flags to request for the security context, or + None to use the default set: mutual_authentication and + out_of_sequence_detection. This may also be an + :class:`IntEnumFlagSet` lifetime (int): the request lifetime of the security context (a value of 0 or None means indefinite) channel_bindings (ChannelBindings): The channel bindings (or None for @@ -243,6 +246,8 @@ def accept_sec_context(input_token not None, Creds acceptor_creds=None, SecurityContext context=None, ChannelBindings channel_bindings=None): """ + accept_sec_context(input_token, acceptor_creds=None, context=None, \ +channel_bindings=None) Accept a GSSAPI security context. This method accepts a GSSAPI security context using a token sent by the @@ -366,13 +371,16 @@ def inquire_context(SecurityContext context not None, initiator_name=True, target_name=True, lifetime=True, mech=True, flags=True, locally_init=True, complete=True): """ + inquire_context(context, initiator_name=True, target_name=True, \ +lifetime=True, mech=True, flags=True, locally_init=True, complete=True) Get information about a security context. This method obtains information about a security context, including the initiator and target names, as well as the TTL, mech, flags, and its current state (open vs closed). - Note: the target name may be None if it would have been GSS_C_NO_NAME + Note: + the target name may be ``None`` if it would have been ``GSS_C_NO_NAME`` Args: context (SecurityContext): the context in question @@ -479,6 +487,7 @@ def inquire_context(SecurityContext context not None, initiator_name=True, def context_time(SecurityContext context not None): """ + context_time(context) Get the amount of time for which the given context will remain valid. This method determines the amount of time for which the given @@ -510,7 +519,8 @@ def context_time(SecurityContext context not None): def process_context_token(SecurityContext context not None, token): """ - Process a token asynchronously + process_context_token(context, token) + Process a token asynchronously. This method provides a way to process a token, even if the given security context is not expecting one. For example, @@ -519,6 +529,9 @@ def process_context_token(SecurityContext context not None, token): and wishes to send a token to the initiator, letting the initiator know of the error. + Warning: + This method has been essentially deprecated by :rfc:`2744`. + Args: context (SecurityContext): the security context against which to process the token @@ -543,10 +556,12 @@ def process_context_token(SecurityContext context not None, token): def import_sec_context(token not None): """ - Import a context from another process + import_sec_context(token) + Import a context from another process. This method imports a security context established in another process - by reading the specified token which was output by exportSecContext. + by reading the specified token which was output by + :func:`export_sec_context`. Raises: MissingContextError @@ -574,11 +589,12 @@ def import_sec_context(token not None): def export_sec_context(SecurityContext context not None): """ - Export a context for use in another process + export_sec_context(context) + Export a context for use in another process. This method exports a security context, deactivating in the current process and creating a token which can then be imported into another process - with importSecContext. + with :func:`import_sec_context`. Warning: this modifies the input context @@ -612,13 +628,18 @@ def export_sec_context(SecurityContext context not None): def delete_sec_context(SecurityContext context not None, local_only=True): """ - Delete a GSSAPI Security Context. + delete_sec_context(context, local_only=True) + Delete a GSSAPI security context. This method deletes a GSSAPI security context, returning an output token to send to the other holder of the security context to notify them of the deletion. + Note: + This method generally should not be used. :class:`SecurityContext` + objects will automatically be freed by Python. + Args: context (SecurityContext): the security context in question local_only (bool): should we request local deletion (True), or also diff --git a/gssapi/raw/types.pyx b/gssapi/raw/types.pyx index f7018c4f..5a389549 100644 --- a/gssapi/raw/types.pyx +++ b/gssapi/raw/types.pyx @@ -18,13 +18,8 @@ class NameType(object): """ GSSAPI Name Types - This IntEnum represents GSSAPI name types - (to be used with importName, etc) - - Note that the integers behind these - enum members do not correspond to any numbers - in the GSSAPI C bindings, and are subject - to change at any point. + This enum-like object represents GSSAPI name + types (to be used with :func:`import_name`, etc) """ # mech-agnostic name types @@ -43,8 +38,9 @@ class RequirementFlag(IntEnum, metaclass=ExtendableEnum): """ GSSAPI Requirement Flags - This IntEnum represents flags to be used in the - service flags parameter of initSecContext. + This :class:`~enum.IntEnum` represents flags used with the + :class:`SecurityContext`-related methods (e.g. + :func:`init_sec_context`) The numbers behind the values correspond directly to their C counterparts. @@ -65,11 +61,13 @@ class AddressType(IntEnum, metaclass=ExtendableEnum): """ GSSAPI Channel Bindings Address Types - This IntEnum represents the various address - types used with the channel bindings structure. + This :class:`~enum.IntEnum` represents the various address + types used with the :class:`ChannelBindings` structure. The numbers behind the values correspond directly - to their C counterparts. + to their C counterparts. There is no value for + ``GSS_C_AF_UNSPEC``, since this is represented + by ``None``. """ # unspecified = GSS_C_AF_UNSPEC # None --> GSS_C_AF_UNSPEC @@ -100,10 +98,8 @@ class MechType(object): """ GSSAPI Mechanism Types - This class acts like an Enum, but is not - - The elements of this pseudo-Enum are OID objects. - + This enum-like object contains any mechanism :class:`OID` + values registered by imported mechanisms. """ pass @@ -218,7 +214,7 @@ class IntEnumFlagSet(GenericFlagSet): """A set backed by a 32-bit integer with enum members This class is a :class:`GenericFlagSet` where the returned - members are values in an :class:`IntEnum`. + members are values in an :class:`~enum.IntEnum`. It functions exactly like a `GenericFlagSet`, except that it also supports bitwise operations with the enum values. From 4052a46b331bc68029fce034f4d5a65fc940d28f Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Wed, 22 Apr 2015 21:24:31 -0400 Subject: [PATCH 5/5] Add inline documentation for low-level module This commit adds a docstring to `gssapi.raw` so that `help(gssapi.raw)` returns useful information. --- gssapi/raw/__init__.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/gssapi/raw/__init__.py b/gssapi/raw/__init__.py index ee27a5f4..eb1d290b 100644 --- a/gssapi/raw/__init__.py +++ b/gssapi/raw/__init__.py @@ -1,3 +1,39 @@ +"""Low-Level GSSAPI Bindings + +The low-level API presents a series of methods designed +to closely mimic the C API presented in RFC 2744 and +associated RFCs. + +In this API, classes are simply thin wrappers around C +constructs, and generally lack instance methods. However, +classes will automatically free associated memory (so the +release_xyz methods are not necessary to call). + +The core RFC 2744 components are organized into the following +submodules: + + gssapi.raw.names -- Names + + gssapi.raw.creds -- Credentials + + gssapi.raw.sec_contexts -- Security Contexts + + gssapi.raw.message -- Message encryption, decryption, etc + + gssapi.raw.misc -- Miscellaneous functions + + gssapi.raw.types -- Miscellaneous types (enums, etc) + + gssapi.raw.exceptions -- Exceptions + +Additionally, a number of extensions may be present. All extensions +are in modules of the form `gssapi.raw.ext_xyz`. + +All available functions and classes can be accessed directly from this +module (`gssapi.raw`) -- it is unneccessary to directly import submodules. +""" + + import pkgutil import importlib