-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
555 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Copyright: (c) 2023 Jordan Borean (@jborean93) <jborean93@gmail.com> | ||
# MIT License (see LICENSE or https://opensource.org/licenses/MIT) | ||
|
||
from __future__ import annotations | ||
|
||
import typing as t | ||
|
||
from ._security_context import SecurityContext | ||
|
||
T = t.TypeVar("T", bound=SecPkgBuffer) | ||
|
||
class SecPkgBuffer: | ||
"""Base class for context attribute types.""" | ||
|
||
class SecPkgContextNames(SecPkgBuffer): | ||
"""Security Package Names | ||
The structure indicates the name of the user associated with a security | ||
context. | ||
This wraps the `SecPkgContext_NamesW`_ Win32 structure. | ||
.. _SecPkgContext_NamesW: | ||
https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkgcontext_namesw | ||
""" | ||
|
||
@property | ||
def username(self) -> str: | ||
"""The user represented by the context.""" | ||
|
||
class SecPkgContextSessionKey(SecPkgBuffer): | ||
"""Security Package session key. | ||
The structure contains information about the session key used for the | ||
security context. | ||
This wraps the `SecPkgContext_SessionKey`_ Win32 structure. | ||
.. _SecPkgContext_SessionKey: | ||
https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkgcontext_sessionkey | ||
""" | ||
|
||
@property | ||
def session_key(self) -> bytes: | ||
"""The session key for the security context.""" | ||
|
||
class SecPkgContextSizes(SecPkgBuffer): | ||
"""Security Package sizes. | ||
The structure indicates the sizes of important structures used in the | ||
message support functions. Use :meth:`query_context_attributes` to generate | ||
this instance. | ||
This wraps the `SecPkgContext_Sizes`_ Win32 structure. | ||
.. _SecPkgContextSizes: | ||
https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkgcontext_sizes | ||
""" | ||
|
||
@property | ||
def max_token(self) -> int: | ||
"""Maximum security token sizes.""" | ||
@property | ||
def max_signature(self) -> int: | ||
"""Maximum signature size.""" | ||
@property | ||
def block_size(self) -> int: | ||
"""Preferred integral size of messages.""" | ||
@property | ||
def security_trailer(self) -> int: | ||
"""Size of the security trailer appended to messages.""" | ||
|
||
def query_context_attributes( | ||
context: SecurityContext, | ||
attribute: type[T], | ||
) -> T: | ||
"""Queries an attribute of a security context. | ||
Enables a transport application to query a security package for certain | ||
attributes of a security context. | ||
The attribute must be a type that is a subclass of :class:`SecPkgBuffer`. | ||
The instance is created, populated, and returned by this function. | ||
This wraps the `QueryContextAttributes`_ Win32 function. | ||
Args: | ||
context: The security context to query. | ||
attribute: The attribute type to query and return. | ||
Returns: | ||
The instance of the attribute type provided. | ||
.. _QueryContextAttributes: | ||
https://learn.microsoft.com/en-us/windows/win32/secauthn/querycontextattributes--general | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
# Copyright: (c) 2023 Jordan Borean (@jborean93) <jborean93@gmail.com> | ||
# MIT License (see LICENSE or https://opensource.org/licenses/MIT) | ||
|
||
from __future__ import annotations | ||
|
||
import collections | ||
import enum | ||
|
||
from cpython.exc cimport PyErr_SetFromWindowsErr | ||
|
||
from sspi._security_buffer cimport FreeContextBuffer | ||
from sspi._security_context cimport PCtxtHandle, SecurityContext | ||
from sspi._text cimport wide_char_to_str | ||
from sspi._win32_types cimport * | ||
|
||
from sspi._ntstatus import NtStatus | ||
|
||
|
||
cdef extern from "Security.h": | ||
unsigned long SECPKG_ATTR_SIZES | ||
unsigned long SECPKG_ATTR_NAMES | ||
unsigned long SECPKG_ATTR_LIFESPAN | ||
unsigned long SECPKG_ATTR_DCE_INFO | ||
unsigned long SECPKG_ATTR_STREAM_SIZES | ||
unsigned long SECPKG_ATTR_KEY_INFO | ||
unsigned long SECPKG_ATTR_AUTHORITY | ||
unsigned long SECPKG_ATTR_PROTO_INFO | ||
unsigned long SECPKG_ATTR_PASSWORD_EXPIRY | ||
unsigned long SECPKG_ATTR_SESSION_KEY | ||
unsigned long SECPKG_ATTR_PACKAGE_INFO | ||
unsigned long SECPKG_ATTR_USER_FLAGS | ||
unsigned long SECPKG_ATTR_NEGOTIATION_INFO | ||
unsigned long SECPKG_ATTR_NATIVE_NAMES | ||
unsigned long SECPKG_ATTR_FLAGS | ||
unsigned long SECPKG_ATTR_USE_VALIDATED | ||
unsigned long SECPKG_ATTR_CREDENTIAL_NAME | ||
unsigned long SECPKG_ATTR_TARGET_INFORMATION | ||
unsigned long SECPKG_ATTR_ACCESS_TOKEN | ||
unsigned long SECPKG_ATTR_TARGET | ||
unsigned long SECPKG_ATTR_AUTHENTICATION_ID | ||
unsigned long SECPKG_ATTR_LOGOFF_TIME | ||
unsigned long SECPKG_ATTR_NEGO_KEYS | ||
unsigned long SECPKG_ATTR_PROMPTING_NEEDED | ||
unsigned long SECPKG_ATTR_UNIQUE_BINDINGS | ||
unsigned long SECPKG_ATTR_ENDPOINT_BINDINGS | ||
unsigned long SECPKG_ATTR_CLIENT_SPECIFIED_TARGET | ||
unsigned long SECPKG_ATTR_LAST_CLIENT_TOKEN_STATUS | ||
unsigned long SECPKG_ATTR_NEGO_PKG_INFO | ||
unsigned long SECPKG_ATTR_NEGO_STATUS | ||
unsigned long SECPKG_ATTR_CONTEXT_DELETED | ||
unsigned long SECPKG_ATTR_DTLS_MTU | ||
unsigned long SECPKG_ATTR_DATAGRAM_SIZES | ||
unsigned long SECPKG_ATTR_SUBJECT_SECURITY_ATTRIBUTES | ||
unsigned long SECPKG_ATTR_APPLICATION_PROTOCOL | ||
unsigned long SECPKG_ATTR_NEGOTIATED_TLS_EXTENSIONS | ||
unsigned long SECPKG_ATTR_IS_LOOPBACK | ||
|
||
cdef struct _SecPkgContext_NamesW: | ||
LPWSTR sUserName | ||
ctypedef _SecPkgContext_NamesW SecPkgContext_NamesW | ||
ctypedef SecPkgContext_NamesW *PSecPkgContext_NamesW | ||
|
||
cdef struct _SecPkgContext_Sizes: | ||
unsigned long cbMaxToken | ||
unsigned long cbMaxSignature | ||
unsigned long cbBlockSize | ||
unsigned long cbSecurityTrailer | ||
ctypedef _SecPkgContext_Sizes SecPkgContext_Sizes | ||
ctypedef SecPkgContext_Sizes *PSecPkgContext_Sizes | ||
|
||
cdef struct _SecPkgContext_SessionKey: | ||
unsigned long SessionKeyLength | ||
unsigned char *SessionKey | ||
ctypedef _SecPkgContext_SessionKey SecPkgContext_SessionKey | ||
ctypedef SecPkgContext_SessionKey *PSecPkgContext_SessionKey | ||
|
||
# https://learn.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-querycontextattributesw | ||
SECURITY_STATUS QueryContextAttributesW( | ||
PCtxtHandle phContext, | ||
unsigned long ulAttribute, | ||
void *pBuffer | ||
) nogil | ||
|
||
cdef class SecPkgBuffer: | ||
|
||
cdef (unsigned long, void *) __c_value__(SecPkgBuffer self): | ||
return (0, NULL) | ||
|
||
cdef class SecPkgContextNames(SecPkgBuffer): | ||
cdef SecPkgContext_NamesW raw | ||
|
||
def __dealloc__(SecPkgContextNames self): | ||
if self.raw.sUserName: | ||
FreeContextBuffer(self.raw.sUserName) | ||
self.raw.sUserName = NULL | ||
|
||
cdef (unsigned long, void *) __c_value__(SecPkgContextNames self): | ||
return (SECPKG_ATTR_NAMES, &self.raw) | ||
|
||
def __repr__(SecPkgContextNames self): | ||
return f"SecPkgContextNames(username={self.username!r})" | ||
|
||
@property | ||
def username(SecPkgContextNames self) -> str: | ||
if self.raw.sUserName == NULL: | ||
return "" | ||
else: | ||
return wide_char_to_str(self.raw.sUserName) | ||
|
||
cdef class SecPkgContextSessionKey(SecPkgBuffer): | ||
cdef SecPkgContext_SessionKey raw | ||
|
||
def __dealloc__(SecPkgContextSessionKey self): | ||
if self.raw.SessionKey: | ||
FreeContextBuffer(self.raw.SessionKey) | ||
self.raw.SessionKeyLength = 0 | ||
self.raw.SessionKey = NULL | ||
|
||
cdef (unsigned long, void *) __c_value__(SecPkgContextSessionKey self): | ||
return (SECPKG_ATTR_SESSION_KEY, &self.raw) | ||
|
||
def __repr__(SecPkgContextSessionKey self): | ||
return f"SecPkgContextSessionKey(session_key={self.session_key!r})" | ||
|
||
@property | ||
def session_key(SecPkgContextSessionKey self) -> bytes: | ||
if self.raw.SessionKeyLength and self.raw.SessionKey != NULL: | ||
return (<char *>self.raw.SessionKey)[:self.raw.SessionKeyLength] | ||
else: | ||
return b"" | ||
|
||
cdef class SecPkgContextSizes(SecPkgBuffer): | ||
cdef SecPkgContext_Sizes raw | ||
|
||
cdef (unsigned long, void *) __c_value__(SecPkgContextSizes self): | ||
return (SECPKG_ATTR_SIZES, &self.raw) | ||
|
||
def __repr__(SecPkgContextSizes self) -> str: | ||
kwargs = [f"{k}={v}" for k, v in { | ||
'max_token': self.max_token, | ||
'max_signature': self.max_signature, | ||
'block_size': self.block_size, | ||
'security_trailer': self.security_trailer, | ||
}.items()] | ||
|
||
return f"SecPkgContextSizes({', '.join(kwargs)})" | ||
|
||
@property | ||
def max_token(SecPkgContextSizes self) -> int: | ||
return self.raw.cbMaxToken | ||
|
||
@property | ||
def max_signature(SecPkgContextSizes self) -> int: | ||
return self.raw.cbMaxSignature | ||
|
||
@property | ||
def block_size(SecPkgContextSizes self) -> int: | ||
return self.raw.cbBlockSize | ||
|
||
@property | ||
def security_trailer(SecPkgContextSizes self) -> int: | ||
return self.raw.cbSecurityTrailer | ||
|
||
def query_context_attributes( | ||
SecurityContext context not None, | ||
type attribute not None, | ||
) -> SecPkgBuffer: | ||
if not issubclass(attribute, SecPkgBuffer): | ||
raise TypeError("attribute must be a type of SecPkgBuffer") | ||
|
||
cdef SecPkgBuffer value = attribute() | ||
cdef (unsigned long, void*) raw = value.__c_value__() | ||
|
||
with nogil: | ||
res = QueryContextAttributesW( | ||
&context.raw, | ||
raw[0], | ||
raw[1], | ||
) | ||
|
||
if res: | ||
PyErr_SetFromWindowsErr(res) | ||
|
||
return value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.