Skip to content

Commit

Permalink
Update credential requirements
Browse files Browse the repository at this point in the history
Update the documentation that specifies a credential MUST be specified
when creating a security context. This is technically a breaking change
but it should be a minimal one.
  • Loading branch information
jborean93 committed Mar 6, 2024
1 parent cfb31bd commit d2dceb9
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 27 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.2.0 - TBD

+ **Breaking Change** - The constructor arguments for `sspi.ClientSecurityContext` and `sspi.SeverSecurityContext` have made the `credential` argument non-optional and moved to the first positional argument
+ This is in reflection of the `credential` actually being mandatory
+ Update documentation for `accept_security_context` and `initialize_security_context` to properly reflect that the credential must be specified on the first call to those functions

## 0.1.0 - 2024-10-04

First official release of the `sspilib` Python module.
Expand Down
2 changes: 1 addition & 1 deletion build_helpers/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ lib::setup::python_requirements() {
SSPI_VERSION="$( grep -m 1 version pyproject.toml | tr -s ' ' | tr -d '"' | tr -d "'" | cut -d' ' -f3 )"

python -m pip install sspilib=="${SSPI_VERSION}" \
--find-links "file:///${DIST_LINK_PATH}" \
--find-links "file://${DIST_LINK_PATH}" \
--verbose

echo "Installing dev dependencies"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "sspilib"
version = "0.1.0"
version = "0.2.0"
description = "SSPI API bindings for Python"
readme = "README.md"
requires-python = ">=3.8"
Expand Down
30 changes: 14 additions & 16 deletions src/sspilib/_sec_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class SecurityContext(raw.CtxtHandle, metaclass=abc.ABCMeta):

def __init__(
self,
credential: raw.CredHandle | None = None,
credential: raw.CredHandle,
channel_bindings: raw.SecChannelBindings | None = None,
) -> None:
self._complete = False
Expand Down Expand Up @@ -293,8 +293,7 @@ def _step_internal(
self,
input_buffers: raw.SecBufferDesc | None,
output_buffers: raw.SecBufferDesc | None,
) -> tuple[int, int]:
...
) -> tuple[int, int]: ...

def _get_secbuffer_data(
self,
Expand All @@ -320,6 +319,10 @@ class ClientSecurityContext(SecurityContext):
handle instance in case the low level interface doesn't expose the methods
needed.
The client must specify a credential which stores the credential to use for
authentication as well as extra information that controls how the
security protocol will perform the authentication steps.
The client must specify a target_name which is typically the Service
Principal Name (SPN) of the service. It might be a different value
depending on the security protocol used.
Expand All @@ -329,29 +332,24 @@ class ClientSecurityContext(SecurityContext):
specified. Custom flags can be requested but it will overwrite the default
set.
The credential stores the credential to use for authentication as well as
extra information that controls how the security protocol will perform
the authentication steps.
Optional channel bindings can be specified which is used to tie the
security context with an outer channel.
Properties like ``expiry`` and ``attributes`` won't be populated until the
context has been negotiated and is complete.
Args:
credential: A credential to use for authentication.
target_name: The target service's name, typically the SPN.
flags: Custom ISC REQ flags to use.
credential: A credential to use for authentication, defaults to the
current user context if not set.
channel_bindings: Optional channel bindings to tie the context to.
"""

def __init__(
self,
credential: raw.CredHandle,
target_name: str,
flags: raw.IscReq | int | None = None,
credential: raw.CredHandle | None = None,
*,
channel_bindings: raw.SecChannelBindings | None = None,
) -> None:
Expand Down Expand Up @@ -404,31 +402,31 @@ class ServerSecurityContext(SecurityContext):
handle instance in case the low level interface doesn't expose the methods
needed.
The credential stores the credential to use for authentication as well as
extra information that controls how the security protocol will perform
the authentication steps.
By default the flags are set to request mutual auth, replay detection,
sequence detection, confidentiality, and integrity if no flags are
specified. Custom flags can be requested but it will overwrite the default
set.
The credential stores the credential to use for authentication as well as
extra information that controls how the security protocol will perform
the authentication steps.
Optional channel bindings can be specified which is used to tie the
security context with an outer channel.
Properties like ``expiry`` and ``attributes`` won't be populated until the
context has been negotiated and is complete.
Args:
flags: Custom ASC REQ flags to use.
credential: A credential to use for authentication
flags: Custom ASC REQ flags to use.
channel_bindings: Optional channel bindings to tie the context to.
"""

def __init__(
self,
credential: raw.CredHandle,
flags: raw.AscReq | int | None = None,
credential: raw.CredHandle | None = None,
*,
channel_bindings: raw.SecChannelBindings | None = None,
) -> None:
Expand Down
24 changes: 16 additions & 8 deletions src/sspilib/raw/_security_context.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,11 @@ def accept_security_context(
only the Digest security provider is known to require completion.
The credential can be a credential generated by
:meth:`acquire_credentials_handle` or ``None``. If ``None``, the current
user context will be used. A credential can control what security provider
is used for authentication so should be set in most circumstances.
:meth:`acquire_credentials_handle`. The credential must be supplied on the
first call of this method but can be set to ``None`` on subsequent calls
when the context is supplied. A credential controls what security provider
is used for authentication and can be configured to control specific
options for that security provider.
The context should be set to ``None`` on the first call and the returned
context result on subsequent calls.
Expand All @@ -349,7 +351,9 @@ def accept_security_context(
This function wraps the `AcceptSecurityContext`_ Win32 function.
Args:
credential: Optional credential to use for this security exchange.
credential: Credential to use for this security exchange. This must
be set on the first call and can be omitted when context is
supplied on subsequent calls.
context: Must be None on the first call and the returned security
context on the next call(s)
input_buffers: The buffers supplied as input to the package.
Expand Down Expand Up @@ -426,9 +430,11 @@ def initialize_security_context(
only the Digest security provider is known to require completion.
The credential can be a credential generated by
:meth:`acquire_credentials_handle` or ``None``. If ``None``, the current
user context will be used. A credential can control what security provider
is used for authentication so should be set in most circumstances.
:meth:`acquire_credentials_handle`. The credential must be supplied on the
first call of this method but can be set to ``None`` on subsequent calls
when the context is supplied. A credential controls what security provider
is used for authentication and can be configured to control specific
options for that security provider.
The context should be set to ``None`` on the first call and the returned
context result on subsequent calls.
Expand Down Expand Up @@ -459,7 +465,9 @@ def initialize_security_context(
This function wraps the `InitializeSecurityContext`_ Win32 function.
Args:
credential: Optional credential to use for this security exchange.
credential: Credential to use for this security exchange. This must
be set on the first call and can be omitted when context is
supplied on subsequent calls.
context: Must be None on the first call and the returned security
context on the next call(s)
target_name: The target of the context.
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def initial_contexts() -> tuple[sspilib.ClientSecurityContext, sspilib.ServerSec
c_cred = sspilib.UserCredential("user", "pass", protocol="NTLM")
s_cred = sspilib.UserCredential("user", "pass", protocol="NTLM", usage="accept")

c_ctx = sspilib.ClientSecurityContext(target_name=spn, credential=c_cred)
c_ctx = sspilib.ClientSecurityContext(credential=c_cred, target_name=spn)
s_ctx = sspilib.ServerSecurityContext(credential=s_cred)

return c_ctx, s_ctx
Expand Down

0 comments on commit d2dceb9

Please sign in to comment.