Skip to content

Commit

Permalink
Add optional crypto dependency and removed dep warning
Browse files Browse the repository at this point in the history
  • Loading branch information
jborean93 committed Apr 8, 2019
1 parent 25c6a00 commit 4d23143
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 44 deletions.
31 changes: 22 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
language: python

python:
- "2.6"
- "2.7"
- "3.4"
- "3.5"
- "3.6"
dist: xenial

matrix:
include:
- python: 2.6
dist: trusty
- python: 2.7
- python: 3.4
dist: trusty
- python: 3.5
dist: trusty
- python: 3.6
- python: 3.7
- python: 3.8-dev

# 3.8 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

install:
- pip install -U pip setuptools
- pip install .
- pip install --upgrade pip setuptools
- pip install -r requirements-test.txt
- pip install python-coveralls
- pip install .
- pip install coveralls

script:
- py.test -v --pep8 --cov ntlm_auth --cov-report term-missing
Expand Down
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changes

## 1.3.0 (Apr 9, 2019)

* Added optional dependency for `cryptography` for faster RC4 cipher calls
* Removed the deprecation warning for Ntlm, this is still advised not to use but there's no major harm keep it in place for older hosts
* Add CI test for Python 3.7 and 3.8

## 1.2.0 (Jun 7, 2018)

* Deprecated ntlm_auth.ntlm.Ntlm in favour of ntlm_auth.ntlm.NtlmContext
Expand Down
10 changes: 6 additions & 4 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ environment:
- PYTHON: Python35-x64
- PYTHON: Python36
- PYTHON: Python36-x64
- PYTHON: Python37
- PYTHON: Python37-x64

services:
- iis
Expand All @@ -33,10 +35,10 @@ init:
$env:NTLM_PASSWORD = [Microsoft.Win32.Registry]::GetValue("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon", "DefaultPassword", '')
install:
- ps: |
pip install -U pip setuptools
pip install .
pip install -r requirements-test.txt
- cmd: python -m pip install --upgrade pip
- cmd: pip install --upgrade setuptools
- cmd: pip install -r requirements-test.txt
- cmd: pip install .[cryptography]
- cmd: PowerShell.exe -File appveyor\setup_iis.ps1

build: off
Expand Down
8 changes: 3 additions & 5 deletions ntlm_auth/compute_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import os
import struct
import time
import warnings

import ntlm_auth.compute_hash as comphash
import ntlm_auth.compute_keys as compkeys
Expand Down Expand Up @@ -180,10 +179,9 @@ def get_nt_challenge_response(self, lm_challenge_response,
struct.pack("<L", AvFlags.MIC_PROVIDED)

if server_certificate_hash is not None and cbt_data is None:
warnings.warn("Manually creating the cbt stuct from the cert "
"hash will be removed in a newer version of "
"ntlm-auth. Send the actual CBT struct using "
"cbt_data instead", DeprecationWarning)
# Older method of creating CBT struct based on the cert hash.
# This should be avoided in favour of an explicit
# GssChannelBindingStruct being passed in.
certificate_digest = base64.b16decode(server_certificate_hash)

cbt_data = GssChannelBindingsStruct()
Expand Down
6 changes: 1 addition & 5 deletions ntlm_auth/ntlm.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import base64
import struct
import warnings

from ntlm_auth.constants import NegotiateFlags
from ntlm_auth.exceptions import NoAuthContextError
Expand All @@ -16,7 +15,7 @@ class NtlmContext(object):

def __init__(self, username, password, domain=None, workstation=None,
cbt_data=None, ntlm_compatibility=3):
"""
r"""
Initialises a NTLM context to use when authenticating using the NTLM
protocol.
Initialises the NTLM context to use when sending and receiving messages
Expand Down Expand Up @@ -144,9 +143,6 @@ def __init__(self, ntlm_compatibility=3):
self._context = NtlmContext(None, None,
ntlm_compatibility=ntlm_compatibility)
self._challenge_token = None
warnings.warn("Using Ntlm() is deprecated and will be removed in a "
"future version. Use NtlmContext() instead",
DeprecationWarning)

@property
def negotiate_flags(self):
Expand Down
27 changes: 26 additions & 1 deletion ntlm_auth/rc4.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,27 @@

import struct

# Favour cryptography over our Python implementation as it is a lot faster
try:
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
HAS_CRYPTOGRAPHY = True
except ImportError: # pragma: no cover
HAS_CRYPTOGRAPHY = False

class ARC4(object):

class _CryptographyARC4(object):

def __init__(self, key):
algo = algorithms.ARC4(key)
cipher = Cipher(algo, mode=None, backend=default_backend())
self._encryptor = cipher.encryptor()

def update(self, value):
return self._encryptor.update(value)


class _PythonARC4(object):
state = None
i = 0
j = 0
Expand Down Expand Up @@ -40,3 +59,9 @@ def _random_generator(self):
self.state[self.i], self.state[self.j] = \
self.state[self.j], self.state[self.i]
yield self.state[(self.state[self.i] + self.state[self.j]) % 256]


if HAS_CRYPTOGRAPHY:
ARC4 = _CryptographyARC4
else: # pragma: no cover
ARC4 = _PythonARC4
5 changes: 4 additions & 1 deletion requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
pytest<=3.2.5
pytest==3.2.5; python_version<"2.7"
pytest>=3.6; python_version>="2.7"
pytest-cov
pytest-pep8
requests
cryptography<2.2; python_version<"2.7"
cryptography; python_version>="2.7"
5 changes: 4 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
universal = 1

[metadata]
license_file = LICENSE
license_file = LICENSE

[tool:pytest]
pep8maxlinelength = 119
14 changes: 12 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@

setup(
name='ntlm-auth',
version='1.2.0',
version='1.3.0',
packages=['ntlm_auth'],
install_requires=[],
extras_require={
':python_version<"2.7"': [
'ordereddict'
],
# Adds faster RC4 message encryption, optional as we can fallback
# to the slower Python imp.
'cryptography:python_version<"2.7"': [
'cryptography<2.2' # 2.2+ droppped Python 2.6 support
],
'cryptography:python_version>="2.7"': [
'cryptography'
]
},
author='Jordan Borean',
Expand All @@ -28,6 +36,7 @@
long_description=long_description,
keywords='authentication auth microsoft ntlm lm',
license='MIT',
python_requires='>=2.6,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
classifiers=[
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: MIT License',
Expand All @@ -37,6 +46,7 @@
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6'
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
)
38 changes: 23 additions & 15 deletions tests/test_rc4.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
from ntlm_auth.rc4 import ARC4
import pytest

from ntlm_auth.rc4 import _CryptographyARC4, _PythonARC4


@pytest.fixture(autouse=True)
def rc4(has_crypto):
return _CryptographyARC4 if has_crypto else _PythonARC4


@pytest.mark.parametrize('has_crypto', [True, False])
class TestARC4(object):

def test_encrypt_40bit_key(self):
test_handle = ARC4(b"\x01\x02\x03\x04\x05")
def test_encrypt_40bit_key(self, rc4):
test_handle = rc4(b"\x01\x02\x03\x04\x05")
expected1 = b"\xb2\x39\x63\x05\xf0\x3d\xc0\x27" \
b"\xcc\xc3\x52\x4a\x0a\x11\x18\xa8"
expected2 = b"\x69\x82\x94\x4f\x18\xfc\x82\xd5" \
Expand All @@ -14,8 +22,8 @@ def test_encrypt_40bit_key(self):
assert actual1 == expected1
assert actual2 == expected2

def test_decrypt_40bit_key(self):
test_handle = ARC4(b"\x01\x02\x03\x04\x05")
def test_decrypt_40bit_key(self, rc4):
test_handle = rc4(b"\x01\x02\x03\x04\x05")
test1 = b"\xb2\x39\x63\x05\xf0\x3d\xc0\x27" \
b"\xcc\xc3\x52\x4a\x0a\x11\x18\xa8"
test2 = b"\x69\x82\x94\x4f\x18\xfc\x82\xd5" \
Expand All @@ -26,8 +34,8 @@ def test_decrypt_40bit_key(self):
assert actual1 == expected
assert actual2 == expected

def test_encrypt_56bit_key(self):
test_handle = ARC4(b"\x01\x02\x03\x04\x05\x06\x07")
def test_encrypt_56bit_key(self, rc4):
test_handle = rc4(b"\x01\x02\x03\x04\x05\x06\x07")
expected1 = b"\x29\x3f\x02\xd4\x7f\x37\xc9\xb6" \
b"\x33\xf2\xaf\x52\x85\xfe\xb4\x6b"
expected2 = b"\xe6\x20\xf1\x39\x0d\x19\xbd\x84" \
Expand All @@ -37,8 +45,8 @@ def test_encrypt_56bit_key(self):
assert actual1 == expected1
assert actual2 == expected2

def test_decrypt_56bit_key(self):
test_handle = ARC4(b"\x01\x02\x03\x04\x05\x06\x07")
def test_decrypt_56bit_key(self, rc4):
test_handle = rc4(b"\x01\x02\x03\x04\x05\x06\x07")
test1 = b"\x29\x3f\x02\xd4\x7f\x37\xc9\xb6" \
b"\x33\xf2\xaf\x52\x85\xfe\xb4\x6b"
test2 = b"\xe6\x20\xf1\x39\x0d\x19\xbd\x84" \
Expand All @@ -49,9 +57,9 @@ def test_decrypt_56bit_key(self):
assert actual1 == expected
assert actual2 == expected

def test_encrypt_128bit_key(self):
test_handle = ARC4(b"\x01\x02\x03\x04\x05\x06\x07\x08"
b"\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10")
def test_encrypt_128bit_key(self, rc4):
test_handle = rc4(b"\x01\x02\x03\x04\x05\x06\x07\x08"
b"\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10")
expected1 = b"\x9a\xc7\xcc\x9a\x60\x9d\x1e\xf7" \
b"\xb2\x93\x28\x99\xcd\xe4\x1b\x97"
expected2 = b"\x52\x48\xc4\x95\x90\x14\x12\x6a" \
Expand All @@ -61,9 +69,9 @@ def test_encrypt_128bit_key(self):
assert actual1 == expected1
assert actual2 == expected2

def test_decrypt_128bit_key(self):
test_handle = ARC4(b"\x01\x02\x03\x04\x05\x06\x07\x08"
b"\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10")
def test_decrypt_128bit_key(self, rc4):
test_handle = rc4(b"\x01\x02\x03\x04\x05\x06\x07\x08"
b"\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10")
test1 = b"\x9a\xc7\xcc\x9a\x60\x9d\x1e\xf7" \
b"\xb2\x93\x28\x99\xcd\xe4\x1b\x97"
test2 = b"\x52\x48\xc4\x95\x90\x14\x12\x6a" \
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py26,py27,py33,py34,py35,py36
envlist = py27,py34,py35,py36,py37,py38

[testenv]
deps= -rrequirements-test.txt
Expand Down

0 comments on commit 4d23143

Please sign in to comment.