-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
set_password extended server response processing (#53)
* set_password bytes result_string * CI bump version * CI revert version * set_password response ADPolicyInfo and MIT chpw_message * isort * result structures, docs and code enums * black format * remove nesting from named tuples * chpw_message locale encoding * revert over-decoding and fixed enum * removed ADPolicyInfo.to_bytes() etc --------- Co-authored-by: zarganum <[email protected]>
- Loading branch information
Showing
8 changed files
with
386 additions
and
73 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
# Copyright: (c) 2021 Jordan Borean (@jborean93) <[email protected]> | ||
# MIT License (see LICENSE or https://opensource.org/licenses/MIT) | ||
|
||
from krb5._adpi import ADPolicyInfo, ADPolicyInfoProp | ||
from krb5._ccache import ( | ||
CCache, | ||
CredentialsRetrieveFlags, | ||
|
@@ -85,12 +86,15 @@ | |
) | ||
from krb5._set_password import ( | ||
SetPasswordResult, | ||
SetPasswordResultCode, | ||
set_password, | ||
set_password_using_ccache, | ||
) | ||
from krb5._string import enctype_to_string, string_to_enctype | ||
|
||
__all__ = [ | ||
"ADPolicyInfo", | ||
"ADPolicyInfoProp", | ||
"CCache", | ||
"Context", | ||
"CredentialsRetrieveFlags", | ||
|
@@ -107,6 +111,7 @@ | |
"PrincipalParseFlags", | ||
"PrincipalUnparseFlags", | ||
"SetPasswordResult", | ||
"SetPasswordResultCode", | ||
"TicketFlags", | ||
"TicketTimes", | ||
"build_principal", | ||
|
@@ -195,6 +200,13 @@ | |
__all__.append("marshal_credentials") | ||
__all__.append("unmarshal_credentials") | ||
|
||
try: | ||
from krb5._chpw_message_mit import chpw_message | ||
except ImportError: | ||
pass | ||
else: | ||
__all__.append("chpw_message") | ||
|
||
|
||
try: | ||
from krb5._ccache_match import cc_cache_match | ||
|
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,71 @@ | ||
import enum | ||
import struct | ||
import typing | ||
|
||
FORMAT = "!HIIIQQ" | ||
|
||
|
||
class ADPolicyInfoProp(enum.IntFlag): | ||
COMPLEX = 0x00000001 | ||
NO_ANON_CHANGEv = 0x00000002 | ||
NO_CLEAR_CHANGE = 0x00000004 | ||
LOCKOUT_ADMINS = 0x00000008 | ||
STORE_CLEARTEXT = 0x00000010 | ||
REFUSE_CHANGE = 0x00000020 | ||
|
||
|
||
class ADPolicyInfo(typing.NamedTuple): | ||
"""The structure containing the reasons for failed password change attempt. | ||
Should be used to inform the end user how to meet the policy requirements. | ||
This is specific to Active Directory and is returned as the | ||
`server_response` by :meth:`set_password()` and | ||
:meth:`set_password_using_ccache()`. | ||
When using MIT library, this structure may be encoded back to bytes and | ||
passed to :meth:`chpw_message()` to obtain a human readable response. | ||
With Heimdal, it is required to provide a custom implementation based | ||
on the known fields below. | ||
The structure contains the following fields:\n | ||
- `properties` - Password policy bit flags (see below) | ||
- `min_length` - Minimal password length | ||
- `history` - Number of passwords that this system remembers | ||
- `max_age` - Maximum password age in 100 nanosecond units | ||
- `min_age` - Minimum password age in 100 nanosecond units | ||
The only known property flag is `COMPLEX` which means that the password must | ||
meet certain character variety and not contain the user's name. | ||
To convert `max_age` and `min_age` to seconds, divide them by 10,000,000. | ||
""" | ||
|
||
properties: ADPolicyInfoProp | ||
min_length: int | ||
history: int | ||
max_age: int | ||
min_age: int | ||
|
||
@classmethod | ||
def from_bytes(cls, data: bytes) -> "ADPolicyInfo": | ||
"""Decode AD policy result from byte string | ||
Args: | ||
data: Serialized AD policy `server_response` | ||
Returns: | ||
ADPolicyInfo: Decoded AD policy result strcture | ||
Raises: | ||
ValueError: Invalid data length or wrong signature | ||
""" | ||
if len(data) != struct.calcsize(FORMAT): | ||
raise ValueError("Invalid data length") | ||
signature, min_length, history, flags, max_age, min_age = struct.unpack(FORMAT, data) | ||
if signature != 0x0000: | ||
raise ValueError("Invalid signature") | ||
return cls( | ||
min_length=min_length, | ||
history=history, | ||
max_age=max_age, | ||
min_age=min_age, | ||
properties=ADPolicyInfoProp(flags), | ||
) |
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,21 @@ | ||
from krb5._context import Context | ||
|
||
def chpw_message(context: Context, server_response: bytes) -> bytes: | ||
"""This function processes the byte sequence returned as the | ||
`server_response` by :meth:`set_password()` and | ||
:meth:`set_password_using_ccache()` functions, and returns a human readable | ||
byte string. | ||
Note that `gettext` library is used to translate the strings according | ||
to locale settings. For the list of existing translations, pls. refer | ||
to MIT krb5 source code. Not all translations may be available on your | ||
system. Caller is responsible for decoding the string according to | ||
locale settings. | ||
Args: | ||
context: Krb5 context. | ||
server_response: The `server_response` bytes received from the KDC. | ||
Returns: | ||
bytes: The human readable bytes string. | ||
""" |
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,49 @@ | ||
import typing | ||
|
||
from krb5._exceptions import Krb5Error | ||
|
||
from libc.string cimport strlen | ||
|
||
from krb5._context cimport Context | ||
from krb5._krb5_types cimport * | ||
|
||
|
||
cdef extern from "python_krb5.h": | ||
krb5_error_code krb5_chpw_message( | ||
krb5_context context, | ||
const krb5_data *server_string, | ||
char **message_out | ||
) nogil | ||
|
||
void krb5_free_string( | ||
krb5_context context, | ||
char *string | ||
) nogil | ||
|
||
def chpw_message( | ||
Context context not None, | ||
const unsigned char[:] server_string not None, | ||
) -> bytes: | ||
cdef krb5_error_code err = 0 | ||
cdef krb5_data server_string_raw | ||
cdef char *message_out = NULL | ||
|
||
try: | ||
if len(server_string) == 0: | ||
pykrb5_set_krb5_data(&server_string_raw, 0, "") | ||
else: | ||
pykrb5_set_krb5_data(&server_string_raw, len(server_string), <char *>&server_string[0]) | ||
|
||
err = krb5_chpw_message(context.raw, &server_string_raw, &message_out) | ||
|
||
if err: | ||
raise Krb5Error(context, err) | ||
|
||
if message_out is NULL: | ||
return b"" | ||
else: | ||
message_len = strlen(message_out) | ||
return <bytes>message_out[:message_len] | ||
|
||
finally: | ||
krb5_free_string(context.raw, message_out) |
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.