Hello community,
here is the log from the commit of package python-ntlm-auth for
openSUSE:Factory checked in at 2020-07-16 12:15:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ntlm-auth (Old)
and /work/SRC/openSUSE:Factory/.python-ntlm-auth.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ntlm-auth"
Thu Jul 16 12:15:24 2020 rev:7 rq:821007 version:1.5.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ntlm-auth/python-ntlm-auth.changes
2019-08-27 10:27:54.179912117 +0200
+++
/work/SRC/openSUSE:Factory/.python-ntlm-auth.new.3592/python-ntlm-auth.changes
2020-07-16 12:16:40.494856867 +0200
@@ -1,0 +2,14 @@
+Wed Jul 15 05:51:54 UTC 2020 - Steve Kowalik <[email protected]>
+
+- Update to 1.5.0:
+ * Added the `mic_present` property to the `NtlmContext` class to determine
+ if a MIC has been added to the authentication message.
+ * Added the `sign` and `verify` function to the `NtlmContext` to sign data
+ and verify signatures.
+ * Added the `reset_rc4_state` function to the `NtlmContext` to allow a
+ caller to reset the incoming and outgoing RC4 cipher.
+ * Added the `NTLMSSP_NEGOTIATE_UNICODE` flag to the negotiate message to
+ ensure the challenge and authentication message's text fields can be
+ unicode encoded
+
+-------------------------------------------------------------------
Old:
----
python-ntlm-auth-1.4.0.tar.gz
New:
----
python-ntlm-auth-1.5.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-ntlm-auth.spec ++++++
--- /var/tmp/diff_new_pack.WB84Ot/_old 2020-07-16 12:16:41.718858105 +0200
+++ /var/tmp/diff_new_pack.WB84Ot/_new 2020-07-16 12:16:41.722858108 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-ntlm-auth
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,11 +18,10 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-ntlm-auth
-Version: 1.4.0
+Version: 1.5.0
Release: 0
Summary: NTLM low-level Python library
License: MIT
-Group: Development/Languages/Python
URL: https://github.com/jborean93/ntlm-auth
Source:
https://github.com/jborean93/ntlm-auth/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
BuildRequires: %{python_module cryptography}
++++++ python-ntlm-auth-1.4.0.tar.gz -> python-ntlm-auth-1.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/.travis.yml
new/ntlm-auth-1.5.0/.travis.yml
--- old/ntlm-auth-1.4.0/.travis.yml 2019-08-19 02:51:07.000000000 +0200
+++ new/ntlm-auth-1.5.0/.travis.yml 2020-06-16 08:07:58.000000000 +0200
@@ -1,6 +1,6 @@
language: python
-dist: xenial
+dist: bionic
matrix:
include:
@@ -13,12 +13,14 @@
dist: trusty
- python: 3.6
- python: 3.7
- - python: 3.8-dev
+ - python: 3.8
- # 3.8 is still an alpha and this is just running to make sure nothing major
+ - python: 3.9-dev
+
+ # 3.9 is still an alpha and this is just running to make sure nothing major
# breaks but we don't want it to stop the build
allow_failures:
- - python: 3.8-dev
+ - python: 3.9-dev
install:
- pip install --upgrade pip setuptools
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/CHANGES.md
new/ntlm-auth-1.5.0/CHANGES.md
--- old/ntlm-auth-1.4.0/CHANGES.md 2019-08-19 02:51:07.000000000 +0200
+++ new/ntlm-auth-1.5.0/CHANGES.md 2020-06-16 08:07:58.000000000 +0200
@@ -1,5 +1,12 @@
# Changes
+## 1.5.0 (Jun 16, 2020)
+
+* Added the `mic_present` property to the `NtlmContext` class to determine if
a MIC has been added to the authentication message.
+* Added the `sign` and `verify` function to the `NtlmContext` to sign data and
verify signatures.
+* Added the `reset_rc4_state` function to the `NtlmContext` to allow a caller
to reset the incoming and outgoing RC4 cipher.
+* Added the `NTLMSSP_NEGOTIATE_UNICODE` flag to the negotiate message to
ensure the challenge and authentication message's text fields can be unicode
encoded
+
## 1.4.0 (Aug 19, 2019)
* Added the `session_key` attribute to the `NtlmContext` class so the session
key can be accessed in downstream libraries
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/appveyor.yml
new/ntlm-auth-1.5.0/appveyor.yml
--- old/ntlm-auth-1.4.0/appveyor.yml 2019-08-19 02:51:07.000000000 +0200
+++ new/ntlm-auth-1.5.0/appveyor.yml 2020-06-16 08:07:58.000000000 +0200
@@ -13,14 +13,14 @@
# https://www.appveyor.com/docs/installed-software/#python
- PYTHON: Python27
- PYTHON: Python27-x64
- - PYTHON: Python34
- - PYTHON: Python34-x64
- PYTHON: Python35
- PYTHON: Python35-x64
- PYTHON: Python36
- PYTHON: Python36-x64
- PYTHON: Python37
- PYTHON: Python37-x64
+ - PYTHON: Python38
+ - PYTHON: Python38-x64
services:
- iis
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/ntlm_auth/messages.py
new/ntlm-auth-1.5.0/ntlm_auth/messages.py
--- old/ntlm-auth-1.4.0/ntlm_auth/messages.py 2019-08-19 02:51:07.000000000
+0200
+++ new/ntlm-auth-1.5.0/ntlm_auth/messages.py 2020-06-16 08:07:58.000000000
+0200
@@ -110,10 +110,11 @@
negotiate_flags |= \
NegotiateFlags.NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED
- # Set the encoding flag to use OEM, remove UNICODE if set as it isn't
- # support in this message
- negotiate_flags -= NegotiateFlags.NTLMSSP_NEGOTIATE_UNICODE
- negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_OEM
+ # Set the encoding flag to use UNICODE, remove OEM if set.
+ negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_UNICODE
+ negotiate_flags &= ~NegotiateFlags.NTLMSSP_NEGOTIATE_OEM
+
+ # The domain name and workstation are always OEM encoded.
self.domain_name = self.domain_name.encode('ascii')
self.workstation = self.workstation.encode('ascii')
@@ -330,7 +331,7 @@
self.workstation = workstation
if self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_UNICODE:
- self.negotiate_flags -= NegotiateFlags.NTLMSSP_NEGOTIATE_OEM
+ self.negotiate_flags &= ~NegotiateFlags.NTLMSSP_NEGOTIATE_OEM
encoding_value = 'utf-16-le'
else:
encoding_value = 'ascii'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/ntlm_auth/ntlm.py
new/ntlm-auth-1.5.0/ntlm_auth/ntlm.py
--- old/ntlm-auth-1.4.0/ntlm_auth/ntlm.py 2019-08-19 02:51:07.000000000
+0200
+++ new/ntlm-auth-1.5.0/ntlm_auth/ntlm.py 2020-06-16 08:07:58.000000000
+0200
@@ -49,7 +49,6 @@
self._server_certificate_hash = None # deprecated for backwards compat
self.ntlm_compatibility = ntlm_compatibility
self.complete = False
- self.session_key = None
# Setting up our flags so the challenge message returns the target info
# block if supported
@@ -71,6 +70,23 @@
self._authenticate_message = None
self._session_security = None
+ @property
+ def mic_present(self):
+ if self._authenticate_message:
+ return bool(self._authenticate_message.mic)
+
+ return False
+
+ @property
+ def session_key(self):
+ if self._authenticate_message:
+ return self._authenticate_message.exported_session_key
+
+ def reset_rc4_state(self, outgoing=True):
+ """ Resets the signing cipher for the incoming or outgoing cipher. For
SPNEGO for calculating mechListMIC. """
+ if self._session_security:
+ self._session_security.reset_rc4_state(outgoing=outgoing)
+
def step(self, input_token=None):
if self._negotiate_message is None:
self._negotiate_message = NegotiateMessage(self.negotiate_flags,
@@ -92,14 +108,19 @@
flags = struct.unpack("<I", flag_bytes)[0]
if flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL or \
flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN:
- self.session_key =
self._authenticate_message.exported_session_key
self._session_security = SessionSecurity(
- flags, self._authenticate_message.exported_session_key
+ flags, self.session_key
)
self.complete = True
return self._authenticate_message.get_data()
+ def sign(self, data):
+ return self._session_security.get_signature(data)
+
+ def verify(self, data, signature):
+ self._session_security.verify_signature(data, signature)
+
def wrap(self, data):
if self._session_security is None:
raise NoAuthContextError("Cannot wrap data as no security context "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/ntlm_auth/session_security.py
new/ntlm-auth-1.5.0/ntlm_auth/session_security.py
--- old/ntlm-auth-1.4.0/ntlm_auth/session_security.py 2019-08-19
02:51:07.000000000 +0200
+++ new/ntlm-auth-1.5.0/ntlm_auth/session_security.py 2020-06-16
08:07:58.000000000 +0200
@@ -102,36 +102,35 @@
self.exported_session_key = exported_session_key
self.outgoing_seq_num = 0
self.incoming_seq_num = 0
-
- client_sealing_key = \
- compkeys.get_seal_key(self.negotiate_flags, exported_session_key,
- SignSealConstants.CLIENT_SEALING)
- server_sealing_key = \
- compkeys.get_seal_key(self.negotiate_flags, exported_session_key,
- SignSealConstants.SERVER_SEALING)
+ self._source = source
+ self._client_sealing_key = compkeys.get_seal_key(self.negotiate_flags,
exported_session_key,
+
SignSealConstants.CLIENT_SEALING)
+ self._server_sealing_key = compkeys.get_seal_key(self.negotiate_flags,
exported_session_key,
+
SignSealConstants.SERVER_SEALING)
+
+ self.outgoing_handle = None
+ self.incoming_handle = None
+ self.reset_rc4_state(True)
+ self.reset_rc4_state(False)
if source == "client":
- self.outgoing_signing_key = \
- compkeys.get_sign_key(exported_session_key,
- SignSealConstants.CLIENT_SIGNING)
- self.incoming_signing_key = \
- compkeys.get_sign_key(exported_session_key,
- SignSealConstants.SERVER_SIGNING)
- self.outgoing_handle = ARC4(client_sealing_key)
- self.incoming_handle = ARC4(server_sealing_key)
+ self.outgoing_signing_key =
compkeys.get_sign_key(exported_session_key, SignSealConstants.CLIENT_SIGNING)
+ self.incoming_signing_key =
compkeys.get_sign_key(exported_session_key, SignSealConstants.SERVER_SIGNING)
elif source == "server":
- self.outgoing_signing_key = \
- compkeys.get_sign_key(exported_session_key,
- SignSealConstants.SERVER_SIGNING)
- self.incoming_signing_key = \
- compkeys.get_sign_key(exported_session_key,
- SignSealConstants.CLIENT_SIGNING)
- self.outgoing_handle = ARC4(server_sealing_key)
- self.incoming_handle = ARC4(client_sealing_key)
+ self.outgoing_signing_key =
compkeys.get_sign_key(exported_session_key, SignSealConstants.SERVER_SIGNING)
+ self.incoming_signing_key =
compkeys.get_sign_key(exported_session_key, SignSealConstants.CLIENT_SIGNING)
else:
raise ValueError("Invalid source parameter %s, must be client "
"or server" % source)
+ def reset_rc4_state(self, outgoing=True):
+ csk = self._client_sealing_key
+ ssk = self._server_sealing_key
+ if outgoing:
+ self.outgoing_handle = ARC4(csk if self._source == 'client' else
ssk)
+ else:
+ self.incoming_handle = ARC4(ssk if self._source == 'client' else
csk)
+
def wrap(self, message):
"""
[MS-NLMP] v28.0 2016-07-14
@@ -147,11 +146,11 @@
"""
if self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL:
encrypted_message = self._seal_message(message)
- signature = self._get_signature(message)
+ signature = self.get_signature(message)
message = encrypted_message
elif self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN:
- signature = self._get_signature(message)
+ signature = self.get_signature(message)
else:
signature = None
@@ -172,10 +171,10 @@
"""
if self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL:
message = self._unseal_message(message)
- self._verify_signature(message, signature)
+ self.verify_signature(message, signature)
elif self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN:
- self._verify_signature(message, signature)
+ self.verify_signature(message, signature)
return message
@@ -207,7 +206,7 @@
decrypted_message = self.incoming_handle.update(message)
return decrypted_message
- def _get_signature(self, message):
+ def get_signature(self, message):
"""
[MS-NLMP] v28.0 2016-07-14
@@ -227,7 +226,7 @@
return signature.get_data()
- def _verify_signature(self, message, signature):
+ def verify_signature(self, message, signature):
"""
Will verify that the signature received from the server matches up with
the expected signature computed locally. Will throw an exception if
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/setup.py new/ntlm-auth-1.5.0/setup.py
--- old/ntlm-auth-1.4.0/setup.py 2019-08-19 02:51:07.000000000 +0200
+++ new/ntlm-auth-1.5.0/setup.py 2020-06-16 08:07:58.000000000 +0200
@@ -13,7 +13,7 @@
setup(
name='ntlm-auth',
- version='1.4.0',
+ version='1.5.0',
packages=['ntlm_auth'],
install_requires=[],
extras_require={
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/tests/test_messages.py
new/ntlm-auth-1.5.0/tests/test_messages.py
--- old/ntlm-auth-1.4.0/tests/test_messages.py 2019-08-19 02:51:07.000000000
+0200
+++ new/ntlm-auth-1.5.0/tests/test_messages.py 2020-06-16 08:07:58.000000000
+0200
@@ -71,7 +71,7 @@
def test_negotiate_with_all(self):
expected = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
- b"\x01\x00\x00\x00\x32\xb2\x02\xe2" \
+ b"\x01\x00\x00\x00\x31\xb2\x02\xe2" \
b"\x06\x00\x06\x00\x28\x00\x00\x00" \
b"\x08\x00\x08\x00\x2e\x00\x00\x00" \
b"\x06\x01\xb1\x1d\x00\x00\x00\x0f" \
@@ -83,7 +83,7 @@
def test_negotiate_without_version(self):
test_flags = 3791815219 - NegotiateFlags.NTLMSSP_NEGOTIATE_VERSION
expected = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
- b"\x01\x00\x00\x00\x32\xb2\x02\xe0" \
+ b"\x01\x00\x00\x00\x31\xb2\x02\xe0" \
b"\x06\x00\x06\x00\x28\x00\x00\x00" \
b"\x08\x00\x08\x00\x2e\x00\x00\x00" \
b"\x00\x00\x00\x00\x00\x00\x00\x00" \
@@ -94,7 +94,7 @@
def test_negotiate_without_domain_workstation(self):
expected = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
- b"\x01\x00\x00\x00\x32\x82\x02\xe2" \
+ b"\x01\x00\x00\x00\x31\x82\x02\xe2" \
b"\x00\x00\x00\x00\x28\x00\x00\x00" \
b"\x00\x00\x00\x00\x28\x00\x00\x00" \
b"\x06\x01\xb1\x1d\x00\x00\x00\x0f"
@@ -580,42 +580,42 @@
"COMPUTER")
# Not a Microsoft example, using pre-computed value
- expected = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
+ expected = b"\x4E\x54\x4C\x4D\x53\x53\x50\x00" \
b"\x03\x00\x00\x00\x18\x00\x18\x00" \
- b"\x7c\x00\x00\x00\x7c\x00\x7c\x00" \
- b"\x94\x00\x00\x00\x0c\x00\x0c\x00" \
+ b"\x7C\x00\x00\x00\x7C\x00\x7C\x00" \
+ b"\x94\x00\x00\x00\x0C\x00\x0C\x00" \
b"\x58\x00\x00\x00\x08\x00\x08\x00" \
b"\x64\x00\x00\x00\x10\x00\x10\x00" \
- b"\x6c\x00\x00\x00\x10\x00\x10\x00" \
- b"\x10\x01\x00\x00\x31\x82\x8a\xe2" \
- b"\x06\x01\xb1\x1d\x00\x00\x00\x0f" \
- b"\x8b\x69\xf5\x92\xb2\xd7\x8f\xd7" \
- b"\x3a\x3a\x49\xdb\xfe\x19\x61\xbc" \
- b"\x44\x00\x6f\x00\x6d\x00\x61\x00" \
- b"\x69\x00\x6e\x00\x55\x00\x73\x00" \
- b"\x65\x00\x72\x00\x43\x00\x4f\x00" \
- b"\x4d\x00\x50\x00\x55\x00\x54\x00" \
+ b"\x6C\x00\x00\x00\x10\x00\x10\x00" \
+ b"\x10\x01\x00\x00\x31\x82\x8A\xE2" \
+ b"\x06\x01\xB1\x1D\x00\x00\x00\x0F" \
+ b"\xD2\xA1\x45\xDE\xA4\x25\x3E\x19" \
+ b"\x10\xFE\x0F\x5B\x7A\x0D\x2A\x90" \
+ b"\x44\x00\x6F\x00\x6D\x00\x61\x00" \
+ b"\x69\x00\x6E\x00\x55\x00\x73\x00" \
+ b"\x65\x00\x72\x00\x43\x00\x4F\x00" \
+ b"\x4D\x00\x50\x00\x55\x00\x54\x00" \
b"\x45\x00\x52\x00\x00\x00\x00\x00" \
b"\x00\x00\x00\x00\x00\x00\x00\x00" \
b"\x00\x00\x00\x00\x00\x00\x00\x00" \
- b"\x00\x00\x00\x00\xa1\x3d\x03\x8a" \
- b"\xd0\xca\x02\x64\x33\x89\x7c\x33" \
- b"\x5e\x0f\x56\xdf\x01\x01\x00\x00" \
+ b"\x00\x00\x00\x00\xA1\x3D\x03\x8A" \
+ b"\xD0\xCA\x02\x64\x33\x89\x7C\x33" \
+ b"\x5E\x0F\x56\xDF\x01\x01\x00\x00" \
b"\x00\x00\x00\x00\x00\x00\x00\x00" \
- b"\x00\x00\x00\x00\xaa\xaa\xaa\xaa" \
- b"\xaa\xaa\xaa\xaa\x00\x00\x00\x00" \
- b"\x02\x00\x0c\x00\x44\x00\x6f\x00" \
- b"\x6d\x00\x61\x00\x69\x00\x6e\x00" \
- b"\x01\x00\x0c\x00\x53\x00\x65\x00" \
+ b"\x00\x00\x00\x00\xAA\xAA\xAA\xAA" \
+ b"\xAA\xAA\xAA\xAA\x00\x00\x00\x00" \
+ b"\x02\x00\x0C\x00\x44\x00\x6F\x00" \
+ b"\x6D\x00\x61\x00\x69\x00\x6E\x00" \
+ b"\x01\x00\x0C\x00\x53\x00\x65\x00" \
b"\x72\x00\x76\x00\x65\x00\x72\x00" \
b"\x07\x00\x08\x00\x00\x00\x00\x00" \
b"\x00\x00\x00\x00\x06\x00\x04\x00" \
- b"\x02\x00\x00\x00\x0a\x00\x10\x00" \
- b"\x6e\xa1\x9d\xf0\x66\xda\x46\x22" \
- b"\x05\x1f\x9c\x4f\x92\xc6\xdf\x74" \
+ b"\x02\x00\x00\x00\x0A\x00\x10\x00" \
+ b"\x6E\xA1\x9D\xF0\x66\xDA\x46\x22" \
+ b"\x05\x1F\x9C\x4F\x92\xC6\xDF\x74" \
b"\x00\x00\x00\x00\x00\x00\x00\x00" \
- b"\x1d\x08\x89\xd1\xa5\xee\xed\x21" \
- b"\x91\x9e\x1a\xb8\x27\xc3\x0b\x17"
+ b"\x1D\x08\x89\xD1\xA5\xEE\xED\x21" \
+ b"\x91\x9E\x1A\xB8\x27\xC3\x0B\x17"
actual = AuthenticateMessage("User", "Password", "Domain", "COMPUTER",
test_challenge_message, 3,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ntlm-auth-1.4.0/tests/test_ntlm.py
new/ntlm-auth-1.5.0/tests/test_ntlm.py
--- old/ntlm-auth-1.4.0/tests/test_ntlm.py 2019-08-19 02:51:07.000000000
+0200
+++ new/ntlm-auth-1.5.0/tests/test_ntlm.py 2020-06-16 08:07:58.000000000
+0200
@@ -126,8 +126,7 @@
# permutations are in test_message.py
def test_create_negotiate_message(self):
ntlm_context = Ntlm()
- expected = b'TlRMTVNTUAABAAAAMrCI4gYABgAoAAAACAAIAC4AAAA' \
- b'GAbEdAAAAD0RvbWFpbkNPTVBVVEVS'
+ expected =
b'TlRMTVNTUAABAAAAMbCI4gYABgAoAAAACAAIAC4AAAAGAbEdAAAAD0RvbWFpbkNPTVBVVEVS'
actual = ntlm_context.create_negotiate_message("Domain", "COMPUTER")
assert actual == expected
@@ -312,8 +311,6 @@
monkeypatch.setattr('ntlm_auth.compute_response.get_windows_timestamp',
lambda: b"\x00" * 8)
- import binascii
-
ch = 'E3CA49271E5089CC48CE82109F1324F41DBEDDC29A777410C738F7868C4FF405'
cbt_data = GssChannelBindingsStruct()
cbt_data[cbt_data.APPLICATION_DATA] = b"tls-server-end-point:" + \
@@ -322,13 +319,14 @@
cbt_data=cbt_data)
actual_nego = ntlm_context.step()
expected_nego = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
- b"\x01\x00\x00\x00\x32\xb0\x88\xe2" \
+ b"\x01\x00\x00\x00\x31\xb0\x88\xe2" \
b"\x06\x00\x06\x00\x28\x00\x00\x00" \
b"\x08\x00\x08\x00\x2e\x00\x00\x00" \
b"\x05\x01\x28\x0a\x00\x00\x00\x0f" \
b"\x44\x6f\x6d\x61\x69\x6e\x43\x4f" \
b"\x4d\x50\x55\x54\x45\x52"
assert actual_nego == expected_nego
+ assert not ntlm_context.mic_present
assert not ntlm_context.complete
challenge_msg = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
@@ -380,6 +378,111 @@
assert actual_auth == expected_auth
assert ntlm_context.complete
+ assert not ntlm_context.mic_present
+
+ request_msg = b"test req"
+ response_msg = b"test res"
+ actual_wrapped = ntlm_context.wrap(request_msg)
+ expected_wrapped = b"\x01\x00\x00\x00\xbc\xe3\x23\xa1" \
+ b"\x72\x06\x23\x78\x00\x00\x00\x00" \
+ b"\x70\x80\x1e\x11\xfe\x6b\x3a\xad"
+ assert actual_wrapped == expected_wrapped
+
+ server_sec = SessionSecurity(
+ ntlm_context._session_security.negotiate_flags,
+ ntlm_context._session_security.exported_session_key, "server"
+ )
+ server_unwrap = server_sec.unwrap(actual_wrapped[16:],
+ actual_wrapped[0:16])
+ assert server_unwrap == request_msg
+
+ response_wrapped = server_sec.wrap(response_msg)
+
+ actual_unwrap = ntlm_context.unwrap(
+ response_wrapped[1] + response_wrapped[0]
+ )
+ assert actual_unwrap == response_msg
+
+ def test_ntlm_context_with_mic(self, monkeypatch):
+ monkeypatch.setattr('os.urandom', lambda s: b"\xaa" * 8)
+ monkeypatch.setattr('ntlm_auth.messages.get_version', lambda s:
b"\x05\x01\x28\x0A\x00\x00\x00\x0F")
+
monkeypatch.setattr('ntlm_auth.messages.get_random_export_session_key', lambda:
b"\x55" * 16)
+
monkeypatch.setattr('ntlm_auth.compute_response.get_windows_timestamp', lambda:
b"\x00" * 8)
+
+ ch = 'E3CA49271E5089CC48CE82109F1324F41DBEDDC29A777410C738F7868C4FF405'
+ cbt_data = GssChannelBindingsStruct()
+ cbt_data[cbt_data.APPLICATION_DATA] = b"tls-server-end-point:" + \
+ base64.b16decode(ch)
+ ntlm_context = NtlmContext("User", "Password", "Domain", "COMPUTER",
+ cbt_data=cbt_data)
+ ntlm_context.reset_rc4_state() # Verifies it won't fail when the
session security isn't set up.
+
+ actual_nego = ntlm_context.step()
+ expected_nego = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
+ b"\x01\x00\x00\x00\x31\xb0\x88\xe2" \
+ b"\x06\x00\x06\x00\x28\x00\x00\x00" \
+ b"\x08\x00\x08\x00\x2e\x00\x00\x00" \
+ b"\x05\x01\x28\x0a\x00\x00\x00\x0f" \
+ b"\x44\x6f\x6d\x61\x69\x6e\x43\x4f" \
+ b"\x4d\x50\x55\x54\x45\x52"
+ assert actual_nego == expected_nego
+ assert not ntlm_context.mic_present
+ assert not ntlm_context.complete
+
+ challenge_msg = b"\x4E\x54\x4C\x4D\x53\x53\x50\x00" \
+ b"\x02\x00\x00\x00\x00\x00\x00\x00" \
+ b"\x38\x00\x00\x00\x33\x82\x8A\xE2" \
+ b"\x01\x23\x45\x67\x89\xAB\xCD\xEF" \
+ b"\x00\x00\x00\x00\x00\x00\x00\x00" \
+ b"\x30\x00\x30\x00\x38\x00\x00\x00" \
+ b"\x06\x01\xB1\x1D\x00\x00\x00\x0F" \
+ b"\x02\x00\x0C\x00\x44\x00\x6F\x00" \
+ b"\x6D\x00\x61\x00\x69\x00\x6E\x00" \
+ b"\x01\x00\x0C\x00\x53\x00\x65\x00" \
+ b"\x72\x00\x76\x00\x65\x00\x72\x00" \
+ b"\x07\x00\x08\x00\x00\x00\x00\x00" \
+ b"\x00\x00\x00\x00\x00\x00\x00\x00"
+ actual_auth = ntlm_context.step(challenge_msg)
+ expected_auth = b'\x4E\x54\x4C\x4D\x53\x53\x50\x00' \
+ b'\x03\x00\x00\x00\x18\x00\x18\x00' \
+ b'\x7C\x00\x00\x00\x7C\x00\x7C\x00' \
+ b'\x94\x00\x00\x00\x0C\x00\x0C\x00' \
+ b'\x58\x00\x00\x00\x08\x00\x08\x00' \
+ b'\x64\x00\x00\x00\x10\x00\x10\x00' \
+ b'\x6C\x00\x00\x00\x10\x00\x10\x00' \
+ b'\x10\x01\x00\x00\x31\x82\x8A\xE2' \
+ b'\x05\x01\x28\x0A\x00\x00\x00\x0F' \
+ b'\xC4\x45\x2C\xF7\xA8\x1E\x4D\x11' \
+ b'\xD0\x78\x18\x94\x09\x57\x5D\x9E' \
+ b'\x44\x00\x6F\x00\x6D\x00\x61\x00' \
+ b'\x69\x00\x6E\x00\x55\x00\x73\x00' \
+ b'\x65\x00\x72\x00\x43\x00\x4F\x00' \
+ b'\x4D\x00\x50\x00\x55\x00\x54\x00' \
+ b'\x45\x00\x52\x00\x00\x00\x00\x00' \
+ b'\x00\x00\x00\x00\x00\x00\x00\x00' \
+ b'\x00\x00\x00\x00\x00\x00\x00\x00' \
+ b'\x00\x00\x00\x00\xA1\x3D\x03\x8A' \
+ b'\xD0\xCA\x02\x64\x33\x89\x7C\x33' \
+ b'\x5E\x0F\x56\xDF\x01\x01\x00\x00' \
+ b'\x00\x00\x00\x00\x00\x00\x00\x00' \
+ b'\x00\x00\x00\x00\xAA\xAA\xAA\xAA' \
+ b'\xAA\xAA\xAA\xAA\x00\x00\x00\x00' \
+ b'\x02\x00\x0C\x00\x44\x00\x6F\x00' \
+ b'\x6D\x00\x61\x00\x69\x00\x6E\x00' \
+ b'\x01\x00\x0C\x00\x53\x00\x65\x00' \
+ b'\x72\x00\x76\x00\x65\x00\x72\x00' \
+ b'\x07\x00\x08\x00\x00\x00\x00\x00' \
+ b'\x00\x00\x00\x00\x06\x00\x04\x00' \
+ b'\x02\x00\x00\x00\x0A\x00\x10\x00' \
+ b'\x6E\xA1\x9D\xF0\x66\xDA\x46\x22' \
+ b'\x05\x1F\x9C\x4F\x92\xC6\xDF\x74' \
+ b'\x00\x00\x00\x00\x00\x00\x00\x00' \
+ b'\x1D\x08\x89\xD1\xA5\xEE\xED\x21' \
+ b'\x91\x9E\x1A\xB8\x27\xC3\x0B\x17'
+
+ assert actual_auth == expected_auth
+ assert ntlm_context.complete
+ assert ntlm_context.mic_present
request_msg = b"test req"
response_msg = b"test res"
@@ -404,6 +507,28 @@
)
assert actual_unwrap == response_msg
+ msg = b"Hello"
+ actual_sig1 = ntlm_context.sign(msg)
+ expected_sig1 =
b"\x01\x00\x00\x00\x08\xF0\x0D\x86\x34\x05\x1A\x1D\x01\x00\x00\x00"
+ assert actual_sig1 == expected_sig1
+ server_sec.verify_signature(msg, actual_sig1)
+
+ actual_sig2 = ntlm_context.sign(msg)
+ expected_sig2 =
b"\x01\x00\x00\x00\x07\x64\x0C\x30\x1C\xD7\x76\xF0\x02\x00\x00\x00"
+ assert actual_sig2 == expected_sig2
+ server_sec.verify_signature(msg, actual_sig2)
+
+ ntlm_context.reset_rc4_state()
+ actual_sig3 = ntlm_context.sign(msg)
+ expected_sig3 =
b"\x01\x00\x00\x00\x1E\xD4\xA3\xE5\xE8\x05\x74\x01\x03\x00\x00\x00"
+ assert actual_sig3 == expected_sig3
+
+ server_sec.reset_rc4_state(outgoing=False)
+ server_sec.verify_signature(msg, actual_sig3)
+
+ server_sig = server_sec.get_signature(msg)
+ ntlm_context.verify(msg, server_sig)
+
def test_fail_wrap_no_context(self):
ntlm_context = NtlmContext("", "")
with pytest.raises(NoAuthContextError) as err: