Skip to content

Commit

Permalink
Fix invalid regex escape sequences, update ntlm context class (#15)
Browse files Browse the repository at this point in the history
* Fix invalid regex escape sequences, update ntlm context class

* remove test that is no longer needed
  • Loading branch information
jborean93 authored Aug 18, 2019
1 parent 62635c5 commit 5dd03d8
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 45 deletions.
9 changes: 9 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
# Changes

## 1.1.0 (Aug 19, 2019)

* Bumped `ntlm-auth` minimum version to `v1.2.0`
* Use new NTLM context object to avoid having to base64 encode/decode the messages
* Fix invalid regex escape sequences that have been deprecated in Python 3.8
* Include `LICENSE` and `CHANGES.md` in the Python package manifest


## 1.0.2 (Nov 14, 2018)

* Changed some log messages to a debug level instead of info


## 1.0.1 (Sep 25, 2018)

* Added support for Python 3.7
Expand Down
2 changes: 1 addition & 1 deletion requests_credssp/credssp.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ def handle_401(self, response, **kwargs):
self.contexts[host] = context

credssp_gen = context.credssp_generator()
credssp_regex = re.compile("CredSSP ([^,\s]*)$", re.I)
credssp_regex = re.compile(r"CredSSP ([^,\s]*)$", re.I)

# loop through the CredSSP generator to exchange the tokens between the
# client and the server until either an error occurs or we reached the
Expand Down
35 changes: 12 additions & 23 deletions requests_credssp/spnego.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)

import base64
import binascii
import logging

from abc import ABCMeta, abstractmethod
from ntlm_auth.ntlm import Ntlm
from ntlm_auth.ntlm import NtlmContext
from six import with_metaclass

from requests_credssp.exceptions import AuthenticationException, \
Expand Down Expand Up @@ -496,7 +495,6 @@ class NTLMContext(AuthContext):
def __init__(self, username, password):
super(NTLMContext, self).__init__(password, "ntlm")
self._domain, self._username = self._get_domain_username(username)
self._complete = False

@property
def domain(self):
Expand All @@ -508,34 +506,25 @@ def username(self):

@property
def complete(self):
return self._complete
return self._context.complete

def init_context(self):
self._context = Ntlm()
self._context = NtlmContext(self.username, self.password, self.domain)

def step(self):
msg1 = self._context.create_negotiate_message(self.domain)
msg1 = base64.b64decode(msg1)
msg1 = self._context.step()
log.debug("NTLM Negotiate message: %s" % binascii.hexlify(msg1))

msg2 = yield msg1
log.debug("NTLM: Parsing Challenge message: %s"
% binascii.hexlify(msg2))
msg2 = base64.b64encode(msg2)
self._context.parse_challenge_message(msg2)

log.debug("NTLM: Generating Authenticate message")
msg3 = self._context.create_authenticate_message(
user_name=self.username,
password=self.password,
domain_name=self.domain
)
self._complete = True
yield base64.b64decode(msg3)
log.debug("NTLM: Parsing Challenge message and generating Authenticate"
" message: %s" % binascii.hexlify(msg2))
msg3 = self._context.step(msg2)

yield msg3

def wrap(self, data):
enc_data, enc_signature = self._context.session_security.wrap(data)
return enc_signature + enc_data
wrapped_data = self._context.wrap(data)
return wrapped_data[:16] + wrapped_data[16:]

def unwrap(self, data):
return self._context.session_security.unwrap(data[16:], data[:16])
return self._context.unwrap(data)
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@

setup(
name='requests-credssp',
version='1.0.2',
version='1.1.0',
packages=['requests_credssp'],
install_requires=[
"cryptography",
"ntlm-auth",
"ntlm-auth>=1.2.0",
"six",
"pyasn1>=0.3.1",
"pyOpenSSL>=16.0.0",
Expand Down
8 changes: 4 additions & 4 deletions tests/test_credssp.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ def test_set_credssp_token(self):
assert actual == expected

def test_get_credssp_token(self):
pattern = re.compile("CredSSP ([^,\s]*)$", re.I)
pattern = re.compile(r"CredSSP ([^,\s]*)$", re.I)
response = requests.Response()
response.headers['www-authenticate'] = "CredSSP YWJj"
expected = b"abc"
Expand All @@ -706,15 +706,15 @@ def test_get_credssp_token(self):
assert actual == expected

def test_get_credssp_token_fail_no_header(self):
pattern = re.compile("CredSSP ([^,\s]*)$", re.I)
pattern = re.compile(r"CredSSP ([^,\s]*)$", re.I)
response = requests.Response()
with pytest.raises(AuthenticationException) as exc:
HttpCredSSPAuth._get_credssp_token(response, pattern, "step 1")
assert str(exc.value) == "Server did not response with a CredSSP " \
"token after step step 1 - actual ''"

def test_get_credssp_token_fail_no_credssp_token(self):
pattern = re.compile("CredSSP ([^,\s]*)$", re.I)
pattern = re.compile(r"CredSSP ([^,\s]*)$", re.I)
response = requests.Response()
response.headers['www-authenticate'] = "NTLM YWJj"
with pytest.raises(AuthenticationException) as exc:
Expand Down Expand Up @@ -967,7 +967,7 @@ def _get_trailer_length(self, message_length, cipher_suite):
# SecPkgContext_StreamSizes but there is no GSSAPI/OpenSSL equivalent
# so we need to calculate it ourselves

if re.match('^.*-GCM-[\w\d]*$', cipher_suite):
if re.match(r'^.*-GCM-[\w\d]*$', cipher_suite):
# We are using GCM for the cipher suite, GCM has a fixed length of
# 16 bytes for the TLS trailer making it easy for us
trailer_length = 16
Expand Down
15 changes: 0 additions & 15 deletions tests/test_spnego.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,3 @@ def test_ntlm_step(self):
# 0-4 is NTLM sig == 01 00 00 00 , 12:16 is the sequence number
assert enc_msg[:4] == b"\x01\x00\x00\x00"
assert enc_msg[12:16] == b"\x00\x00\x00\x00"

def test_ntlm_unwrap(self):
class SessionSecurityMock(object):
def unwrap(self, data1, data2):
# asserts NTLMContext actually splits the sig and data and
# sends them to ntlm-auth correctly
assert data1 == b"\xbb" * 16
assert data2 == b"\xaa" * 16

ntlm = NTLMContext("", "")
ntlm.init_context()
ntlm._context.session_security = SessionSecurityMock()

data = (b"\xaa" * 16) + (b"\xbb" * 16)
ntlm.unwrap(data)

0 comments on commit 5dd03d8

Please sign in to comment.