Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-requests_ntlm for
openSUSE:Factory checked in at 2023-03-01 16:14:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-requests_ntlm (Old)
and /work/SRC/openSUSE:Factory/.python-requests_ntlm.new.31432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-requests_ntlm"
Wed Mar 1 16:14:49 2023 rev:3 rq:1068435 version:1.2.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-requests_ntlm/python-requests_ntlm.changes
2018-12-24 11:46:33.169178036 +0100
+++
/work/SRC/openSUSE:Factory/.python-requests_ntlm.new.31432/python-requests_ntlm.changes
2023-03-01 16:15:13.270962544 +0100
@@ -1,0 +2,8 @@
+Wed Mar 1 11:53:47 UTC 2023 - Daniel Garcia <[email protected]>
+
+- Update to 1.2.0
+ * Migrate to GHA for CI by @jborean93 in #129
+ * Migrate to PySPNEGO by @clubby789 in #126
+ * Add pyproject.toml for PEP518 compliance by @jborean93 in #131
+
+-------------------------------------------------------------------
Old:
----
requests-ntlm-1.1.0.tar.gz
New:
----
requests-ntlm-1.2.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-requests_ntlm.spec ++++++
--- /var/tmp/diff_new_pack.MDpCtd/_old 2023-03-01 16:15:13.890965751 +0100
+++ /var/tmp/diff_new_pack.MDpCtd/_new 2023-03-01 16:15:13.898965791 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-requests_ntlm
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -16,25 +16,25 @@
#
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-requests_ntlm
-Version: 1.1.0
+Version: 1.2.0
Release: 0
Summary: NTLM authentication for the python-requests library
License: ISC
Group: Development/Languages/Python
-Url: https://github.com/requests/requests-ntlm
+URL: https://github.com/requests/requests-ntlm
Source:
https://github.com/requests/requests-ntlm/archive/v%{version}.tar.gz#/requests-ntlm-%{version}.tar.gz
BuildRequires: %{python_module Flask}
BuildRequires: %{python_module cryptography >= 1.3}
-BuildRequires: %{python_module ntlm-auth >= 1.0.2}
+BuildRequires: %{python_module pip}
+BuildRequires: %{python_module pyspnego}
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module requests >= 2.0.0}
-BuildRequires: %{python_module setuptools}
+BuildRequires: %{python_module wheel}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-cryptography >= 1.3
-Requires: python-ntlm-auth >= 1.0.2
+Requires: python-pyspnego
Requires: python-requests >= 2.0.0
BuildArch: noarch
%python_subpackages
@@ -49,19 +49,20 @@
%setup -q -n requests-ntlm-%{version}
%build
-%python_build
+%pyproject_wheel
%install
-%python_install
+%pyproject_install
%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
-#%%python_exec -m tests.test_server &
-#%%python_expand PYTHONPATH=%{buildroot}%{$python_sitelib}
py.test-%{$python_version}
+%python_exec -m tests.test_server &
+%pytest --ignore tests/functional/test_functional.py --ignore
tests/test_server.py
%files %{python_files}
%license LICENSE
%doc README.rst
-%{python_sitelib}/*
+%{python_sitelib}/requests_ntlm
+%{python_sitelib}/requests_ntlm-%{version}*-info
%changelog
++++++ requests-ntlm-1.1.0.tar.gz -> requests-ntlm-1.2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/.github/workflows/ci.yml
new/requests-ntlm-1.2.0/.github/workflows/ci.yml
--- old/requests-ntlm-1.1.0/.github/workflows/ci.yml 1970-01-01
01:00:00.000000000 +0100
+++ new/requests-ntlm-1.2.0/.github/workflows/ci.yml 2023-02-15
21:23:12.000000000 +0100
@@ -0,0 +1,86 @@
+name: Test requests-ntlm
+on:
+ push:
+ branches:
+ - master
+ paths-ignore:
+ - LICENSE
+ - README.rst
+
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - LICENSE
+ - README.rst
+
+ release:
+ types:
+ - published
+
+jobs:
+ test:
+ name: test
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - python-version: '3.7'
+ - python-version: '3.8'
+ - python-version: '3.9'
+ - python-version: '3.10'
+ - python-version: '3.11'
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Run tests
+ shell: bash
+ run: |
+ python -m pip install -U pip setuptools
+ python -m pip install .
+ python -m pip install -r requirements.txt
+
+ python -m tests.test_server &
+
+ python -m pytest \
+ --ignore=tests/functional/test_functional.py \
+ --ignore=tests/test_server.py \
+ --cov requests_ntlm \
+ --cov-report term-missing \
+ tests
+
+ publish:
+ name: publish
+ needs:
+ - test
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Installing baseline packages
+ run: |
+ echo "Installing baseline pip packages"
+ python -m pip install --upgrade pip setuptools wheel
+
+ - name: Build package
+ run: python setup.py sdist bdist_wheel
+
+ - name: Capture Wheel and SDist
+ uses: actions/upload-artifact@v3
+ with:
+ name: artifact
+ path: dist/*
+
+ - name: Publish
+ if: startsWith(github.ref, 'refs/tags/v')
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ user: __token__
+ password: ${{ secrets.PYPI_API_TOKEN }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/.travis.yml
new/requests-ntlm-1.2.0/.travis.yml
--- old/requests-ntlm-1.1.0/.travis.yml 2017-09-19 20:06:53.000000000 +0200
+++ new/requests-ntlm-1.2.0/.travis.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,26 +0,0 @@
-language: python
-
-python:
- - "2.6"
- - "2.7"
- - "3.3"
- - "3.4"
- - "3.5"
- - "3.6"
-
-install:
- - pip install -U pip setuptools
- - pip install .
- - pip install -r requirements.txt
- - pip install python-coveralls
-
-# start the Flask server for our tests
-before_script:
- - python -m tests.test_server &
-
-script:
- - py.test --ignore=tests/functional/test_functional.py
--ignore=tests/test_server.py --cov requests_ntlm --cov-report term-missing
tests
-
-after_success:
- - coveralls
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/README.rst
new/requests-ntlm-1.2.0/README.rst
--- old/requests-ntlm-1.1.0/README.rst 2017-09-19 20:06:53.000000000 +0200
+++ new/requests-ntlm-1.2.0/README.rst 2023-02-15 21:23:12.000000000 +0100
@@ -1,11 +1,8 @@
requests-ntlm
=============
-.. image:: https://travis-ci.org/requests/requests-ntlm.svg?branch=master
- :target: https://travis-ci.org/requests/requests-ntlm
-
-.. image::
https://coveralls.io/repos/github/requests/requests-ntlm/badge.svg?branch=master
- :target: https://coveralls.io/github/requests/requests-ntlm?branch=master
+.. image::
https://github.com/requests/requests-ntlm/actions/workflows/ci.yml/badge.svg
+ :target: https://github.com/requests/requests-ntlm/actions/workflows/ci.yml
This package allows for HTTP NTLM authentication using the requests library.
@@ -20,7 +17,7 @@
from requests_ntlm import HttpNtlmAuth
requests.get("http://ntlm_protected_site.com",auth=HttpNtlmAuth('domain\\username','password'))
-
+
``HttpNtlmAuth`` can be used in conjunction with a ``Session`` in order to
make use of connection pooling. Since NTLM authenticates connections,
this is more efficient. Otherwise, each request will go through a new
@@ -44,10 +41,10 @@
------------
- requests_
-- ntlm-auth_
+- pyspnego_
.. _requests: https://github.com/kennethreitz/requests/
-.. _ntlm-auth: https://github.com/jborean93/ntlm-auth
+.. _pyspnego: https://github.com/jborean93/pyspnego/
Authors
-------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/pyproject.toml
new/requests-ntlm-1.2.0/pyproject.toml
--- old/requests-ntlm-1.1.0/pyproject.toml 1970-01-01 01:00:00.000000000
+0100
+++ new/requests-ntlm-1.2.0/pyproject.toml 2023-02-15 21:23:12.000000000
+0100
@@ -0,0 +1,5 @@
+[build-system]
+requires = [
+ "setuptools >= 42.0.0", # Supports license_files
+]
+build-backend = "setuptools.build_meta"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/requests_ntlm/requests_ntlm.py
new/requests-ntlm-1.2.0/requests_ntlm/requests_ntlm.py
--- old/requests-ntlm-1.1.0/requests_ntlm/requests_ntlm.py 2017-09-19
20:06:53.000000000 +0200
+++ new/requests-ntlm-1.2.0/requests_ntlm/requests_ntlm.py 2023-02-15
21:23:12.000000000 +0100
@@ -1,14 +1,38 @@
-import binascii
-import sys
import warnings
+import base64
+import typing as t
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import UnsupportedAlgorithm
-from ntlm_auth import ntlm
from requests.auth import AuthBase
from requests.packages.urllib3.response import HTTPResponse
+import spnego
+
+
+class ShimSessionSecurity:
+ """Shim used for backwards compatibility with ntlm-auth."""
+
+ def __init__(self, context: spnego.ContextProxy) -> None:
+ self._context = context
+
+ def wrap(self, message) -> t.Tuple[bytes, bytes]:
+ wrap_res = self._context.wrap(message, encrypt=True)
+ signature = wrap_res.data[:16]
+ data = wrap_res.data[16:]
+
+ return data, signature
+
+ def unwrap(self, message: bytes, signature: bytes) -> bytes:
+ data = signature + message
+ return self._context.unwrap(data).data
+
+ def get_signature(self, message: bytes) -> bytes:
+ return self._context.sign(message)
+
+ def verify_signature(self, message: bytes, signature: bytes) -> None:
+ self._context.verify(message, signature)
class HttpNtlmAuth(AuthBase):
@@ -26,18 +50,7 @@
:param str session: Unused. Kept for backwards-compatibility.
:param bool send_cbt: Will send the channel bindings over a HTTPS
channel (Default: True)
"""
- if ntlm is None:
- raise Exception("NTLM libraries unavailable")
-
- # parse the username
- try:
- self.domain, self.username = username.split('\\', 1)
- except ValueError:
- self.username = username
- self.domain = ''
-
- if self.domain:
- self.domain = self.domain.upper()
+ self.username = username
self.password = password
self.send_cbt = send_cbt
@@ -46,18 +59,30 @@
# call requests_ntlm to encrypt and decrypt the messages sent after
authentication
self.session_security = None
- def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
- response, auth_type, args):
+ def retry_using_http_NTLM_auth(
+ self,
+ auth_header_field,
+ auth_header,
+ response,
+ auth_type,
+ args,
+ ):
# Get the certificate of the server if using HTTPS for CBT
server_certificate_hash = self._get_server_cert(response)
+ cbt = None
+ if server_certificate_hash:
+ cbt = spnego.channel_bindings.GssChannelBindings(
+ application_data=b"tls-server-end-point:" +
server_certificate_hash
+ )
"""Attempt to authenticate using HTTP NTLM challenge/response."""
if auth_header in response.request.headers:
return response
content_length = int(
- response.request.headers.get('Content-Length', '0'), base=10)
- if hasattr(response.request.body, 'seek'):
+ response.request.headers.get("Content-Length", "0"), base=10
+ )
+ if hasattr(response.request.body, "seek"):
if content_length > 0:
response.request.body.seek(-content_length, 1)
else:
@@ -69,11 +94,16 @@
response.raw.release_conn()
request = response.request.copy()
- # ntlm returns the headers as a base64 encoded bytestring. Convert to
- # a string.
- context = ntlm.Ntlm()
- negotiate_message =
context.create_negotiate_message(self.domain).decode('ascii')
- auth = u'%s %s' % (auth_type, negotiate_message)
+ client = spnego.client(
+ self.username,
+ self.password,
+ protocol="ntlm",
+ channel_bindings=cbt,
+ )
+ # Perform the first step of the NTLM authentication
+ negotiate_message = base64.b64encode(client.step()).decode()
+ auth = "%s %s" % (auth_type, negotiate_message)
+
request.headers[auth_header] = auth
# A streaming response breaks authentication.
@@ -96,42 +126,34 @@
# this is important for some web applications that store
# authentication-related info in cookies (it took a long time to
# figure out)
- if response2.headers.get('set-cookie'):
- request.headers['Cookie'] = response2.headers.get('set-cookie')
+ if response2.headers.get("set-cookie"):
+ request.headers["Cookie"] = response2.headers.get("set-cookie")
# get the challenge
auth_header_value = response2.headers[auth_header_field]
- auth_strip = auth_type + ' '
+ auth_strip = auth_type + " "
ntlm_header_value = next(
- s for s in (val.lstrip() for val in auth_header_value.split(','))
+ s
+ for s in (val.lstrip() for val in auth_header_value.split(","))
if s.startswith(auth_strip)
).strip()
- # Parse the challenge in the ntlm context
- context.parse_challenge_message(ntlm_header_value[len(auth_strip):])
+ # Parse the challenge in the ntlm context and perform
+ # the second step of authentication
+ val = base64.b64decode(ntlm_header_value[len(auth_strip) :].encode())
+ authenticate_message = base64.b64encode(client.step(val)).decode()
- # build response
- # Get the response based on the challenge message
- authenticate_message = context.create_authenticate_message(
- self.username,
- self.password,
- self.domain,
- server_certificate_hash=server_certificate_hash
- )
- authenticate_message = authenticate_message.decode('ascii')
- auth = u'%s %s' % (auth_type, authenticate_message)
+ auth = "%s %s" % (auth_type, authenticate_message)
request.headers[auth_header] = auth
response3 = response2.connection.send(request, **args)
-
# Update the history.
response3.history.append(response)
response3.history.append(response2)
- # Get the session_security object created by ntlm-auth for signing and
sealing of messages
- self.session_security = context.session_security
+ self.session_security = ShimSessionSecurity(client)
return response3
@@ -139,30 +161,28 @@
"""The actual hook handler."""
if r.status_code == 401:
# Handle server auth.
- www_authenticate = r.headers.get('www-authenticate', '').lower()
+ www_authenticate = r.headers.get("www-authenticate", "").lower()
auth_type = _auth_type_from_header(www_authenticate)
if auth_type is not None:
return self.retry_using_http_NTLM_auth(
- 'www-authenticate',
- 'Authorization',
+ "www-authenticate",
+ "Authorization",
r,
auth_type,
- kwargs
+ kwargs,
)
elif r.status_code == 407:
# If we didn't have server auth, do proxy auth.
- proxy_authenticate = r.headers.get(
- 'proxy-authenticate', ''
- ).lower()
+ proxy_authenticate = r.headers.get("proxy-authenticate",
"").lower()
auth_type = _auth_type_from_header(proxy_authenticate)
if auth_type is not None:
return self.retry_using_http_NTLM_auth(
- 'proxy-authenticate',
- 'Proxy-authorization',
+ "proxy-authenticate",
+ "Proxy-authorization",
r,
auth_type,
- kwargs
+ kwargs,
)
return r
@@ -179,36 +199,31 @@
:return: The hash of the DER encoded certificate at the request_url or
None if not a HTTPS endpoint
"""
if self.send_cbt:
- certificate_hash = None
raw_response = response.raw
if isinstance(raw_response, HTTPResponse):
- if sys.version_info > (3, 0):
- socket = raw_response._fp.fp.raw._sock
- else:
- socket = raw_response._fp.fp._sock
+ socket = raw_response._fp.fp.raw._sock
try:
server_certificate = socket.getpeercert(True)
except AttributeError:
pass
else:
- certificate_hash =
_get_certificate_hash(server_certificate)
+ return _get_certificate_hash(server_certificate)
else:
warnings.warn(
"Requests is running with a non urllib3 backend, cannot
retrieve server certificate for CBT",
- NoCertificateRetrievedWarning)
+ NoCertificateRetrievedWarning,
+ )
- return certificate_hash
- else:
- return None
+ return None
def __call__(self, r):
# we must keep the connection because NTLM authenticates the
# connection, not single requests
r.headers["Connection"] = "Keep-Alive"
- r.register_hook('response', self.response_hook)
+ r.register_hook("response", self.response_hook)
return r
@@ -218,10 +233,10 @@
authentication type to use. We prefer NTLM over Negotiate if the server
suppports it.
"""
- if 'ntlm' in header:
- return 'NTLM'
- elif 'negotiate' in header:
- return 'Negotiate'
+ if "ntlm" in header:
+ return "NTLM"
+ elif "negotiate" in header:
+ return "Negotiate"
return None
@@ -233,22 +248,24 @@
try:
hash_algorithm = cert.signature_hash_algorithm
except UnsupportedAlgorithm as ex:
- warnings.warn("Failed to get signature algorithm from certificate, "
- "unable to pass channel bindings: %s" % str(ex),
UnknownSignatureAlgorithmOID)
+ warnings.warn(
+ "Failed to get signature algorithm from certificate, "
+ "unable to pass channel bindings: %s" % str(ex),
+ UnknownSignatureAlgorithmOID,
+ )
return None
# if the cert signature algorithm is either md5 or sha1 then use sha256
# otherwise use the signature algorithm
- if hash_algorithm.name in ['md5', 'sha1']:
+ if hash_algorithm.name in ["md5", "sha1"]:
digest = hashes.Hash(hashes.SHA256(), default_backend())
else:
digest = hashes.Hash(hash_algorithm, default_backend())
digest.update(certificate_der)
certificate_hash_bytes = digest.finalize()
- certificate_hash =
binascii.hexlify(certificate_hash_bytes).decode().upper()
- return certificate_hash
+ return certificate_hash_bytes
class NoCertificateRetrievedWarning(Warning):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/requirements.txt
new/requests-ntlm-1.2.0/requirements.txt
--- old/requests-ntlm-1.1.0/requirements.txt 2017-09-19 20:06:53.000000000
+0200
+++ new/requests-ntlm-1.2.0/requirements.txt 2023-02-15 21:23:12.000000000
+0100
@@ -1,5 +1,5 @@
requests>=2.0.0
-ntlm-auth>=1.0.2
+pyspnego
cryptography>=1.3
flask
pytest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/setup.cfg
new/requests-ntlm-1.2.0/setup.cfg
--- old/requests-ntlm-1.1.0/setup.cfg 1970-01-01 01:00:00.000000000 +0100
+++ new/requests-ntlm-1.2.0/setup.cfg 2023-02-15 21:23:12.000000000 +0100
@@ -0,0 +1,29 @@
+[metadata]
+name = requests_ntlm
+version = 1.2.0
+url = https://github.com/requests/requests-ntlm
+author = Ben Toews
+author_email = [email protected]
+license = ISC
+license_files = LICENSE
+description = This package allows for HTTP NTLM authentication using the
requests library.
+long_description = file: README.rst
+long_description_content_type = text/x-rst
+classifiers =
+ Development Status :: 4 - Beta
+ Intended Audience :: Developers
+ Programming Language :: Python
+ Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.7
+ Programming Language :: Python :: 3.8
+ Programming Language :: Python :: 3.9
+ Programming Language :: Python :: 3.10
+ Programming Language :: Python :: 3.11
+ License :: OSI Approved :: ISC License (ISCL)
+
+[options]
+python_requires = >= 3.7
+install_requires =
+ cryptography >= 1.3
+ pyspnego >= 0.1.6
+ requests >= 2.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/setup.py
new/requests-ntlm-1.2.0/setup.py
--- old/requests-ntlm-1.1.0/setup.py 2017-09-19 20:06:53.000000000 +0200
+++ new/requests-ntlm-1.2.0/setup.py 2023-02-15 21:23:12.000000000 +0100
@@ -1,29 +1,6 @@
#!/usr/bin/env python
-# coding: utf-8
from setuptools import setup
-setup(
- name='requests_ntlm',
- version='1.1.0',
- packages=[ 'requests_ntlm' ],
- install_requires=[ 'requests>=2.0.0', 'ntlm-auth>=1.0.2',
'cryptography>=1.3' ],
- provides=[ 'requests_ntlm' ],
- author='Ben Toews',
- author_email='[email protected]',
- url='https://github.com/requests/requests-ntlm',
- description='This package allows for HTTP NTLM authentication using the
requests library.',
- license='ISC',
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Intended Audience :: Developers',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.3',
- 'Programming Language :: Python :: 3.4',
- 'License :: OSI Approved :: ISC License (ISCL)',
- ],
-)
+# Kept for editable install compatibility with older setuptools/pip versions
+setup()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/tests/test_utils.py
new/requests-ntlm-1.2.0/tests/test_utils.py
--- old/requests-ntlm-1.1.0/tests/test_utils.py 2017-09-19 20:06:53.000000000
+0200
+++ new/requests-ntlm-1.2.0/tests/test_utils.py 2023-02-15 21:23:12.000000000
+0100
@@ -2,3 +2,6 @@
username = 'username'
domain = 'domain'
password = 'password'
+
+# Genearated online as hashlib.md4 may not be available anymore
+password_md4 = '8a9d093f14f8701df17732b2bb182c74'
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-ntlm-1.1.0/tests/unit/test_requests_ntlm.py
new/requests-ntlm-1.2.0/tests/unit/test_requests_ntlm.py
--- old/requests-ntlm-1.1.0/tests/unit/test_requests_ntlm.py 2017-09-19
20:06:53.000000000 +0200
+++ new/requests-ntlm-1.2.0/tests/unit/test_requests_ntlm.py 2023-02-15
21:23:12.000000000 +0100
@@ -4,7 +4,7 @@
import requests_ntlm
import warnings
-from tests.test_utils import domain, username, password
+from tests.test_utils import domain, username, password, password_md4
class TestRequestsNtlm(unittest.TestCase):
@@ -13,7 +13,8 @@
self.test_server_url = 'http://localhost:5000/'
self.test_server_username = '%s\\%s' % (domain, username)
self.test_server_password = password
- self.auth_types = ['ntlm','negotiate','both']
+ self.auth_types = ['ntlm', 'negotiate', 'both']
+ self.hash = password_md4
def test_requests_ntlm(self):
for auth_type in self.auth_types:
@@ -25,6 +26,17 @@
self.assertEqual(res.status_code,200, msg='auth_type ' + auth_type)
+ def test_requests_ntlm_hash(self):
+ # Test authenticating using an NTLM hash
+ for auth_type in self.auth_types:
+ res = requests.get(\
+ url = self.test_server_url + auth_type,\
+ auth = requests_ntlm.HttpNtlmAuth(
+ self.test_server_username,\
+ "0" * 32 + ":" + self.hash))
+
+ self.assertEqual(res.status_code,200, msg='auth_type ' + auth_type)
+
def test_history_is_preserved(self):
for auth_type in self.auth_types:
res = requests.get(url=self.test_server_url + auth_type,
@@ -42,46 +54,6 @@
self.assertTrue(res.history[0].request is not
res.history[1].request)
self.assertTrue(res.history[0].request is not res.request)
- def test_username_parse_backslash(self):
- test_user = 'domain\\user'
- expected_domain = 'DOMAIN'
- expected_user = 'user'
-
- context = requests_ntlm.HttpNtlmAuth(test_user, 'pass')
-
- actual_domain = context.domain
- actual_user = context.username
-
- assert actual_domain == expected_domain
- assert actual_user == expected_user
-
- def test_username_parse_at(self):
- test_user = '[email protected]'
- # UPN format should not be split, since "stuff after @" not always ==
domain
- # (eg, email address with alt UPN suffix)
- expected_domain = ''
- expected_user = '[email protected]'
-
- context = requests_ntlm.HttpNtlmAuth(test_user, 'pass')
-
- actual_domain = context.domain
- actual_user = context.username
-
- assert actual_domain == expected_domain
- assert actual_user == expected_user
-
- def test_username_parse_no_domain(self):
- test_user = 'user'
- expected_domain = ''
- expected_user = 'user'
-
- context = requests_ntlm.HttpNtlmAuth(test_user, 'pass')
-
- actual_domain = context.domain
- actual_user = context.username
-
- assert actual_domain == expected_domain
- assert actual_user == expected_user
class TestCertificateHash(unittest.TestCase):
@@ -110,7 +82,7 @@
expected_hash = '2334B8476CBF4E6DFC766A5D5A30D6649C01BAE1662A5C3A130' \
'2A968D7C6B0F6'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_rsa_sha1(self):
cert_der = b'MIIDGzCCAgOgAwIBAgIQJg/Mf5sR55xApJRK+kabbTANBgkqhkiG9w0' \
@@ -137,7 +109,7 @@
expected_hash = '14CFE8E4B332B20A343FC840B18F9F6F78926AFE7EC3E7B8E28' \
'969619B1E8F3E'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_rsa_sha256(self):
cert_der = b'MIIDGzCCAgOgAwIBAgIQWkeAtqoFg6pNWF7xC4YXhTANBgkqhkiG9w0' \
@@ -164,7 +136,7 @@
expected_hash = '996F3EEA812C1870E30549FF9B86CD87A890B6D8DFDF4A81BEF' \
'9675970DADB26'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_rsa_sha384(self):
cert_der = b'MIIDGzCCAgOgAwIBAgIQEmj1prSSQYRL2zYBEjsm5jANBgkqhkiG9w0' \
@@ -191,7 +163,7 @@
expected_hash = '34F303C995286F4B214A9BA6435B69B51ECF3758EABC2A14D7A' \
'43FD237DC2B1A1AD9111C5C965E107507CB4198C09FEC'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_rsa_sha512(self):
cert_der = b'MIIDGzCCAgOgAwIBAgIQUDHcKGevZohJV+TkIIYC1DANBgkqhkiG9w0' \
@@ -219,7 +191,7 @@
'00544E1AD2B76FF25CFBE69B1C4E630C3BB0207DF11314C6738' \
'BCAED7E071D7BFBF2C9DFAB85D'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_ecdsa_sha1(self):
cert_der = b'MIIBjjCCATSgAwIBAgIQRCJw7nbtvJ5F8wikRmwgizAJBgcqhkjOPQQ' \
@@ -236,7 +208,7 @@
expected_hash = '1EC9AD46DEE9340E4503CFFDB5CD810CB26B778F46BE95D5EAF' \
'999DCB1C45EDA'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_ecdsa_sha256(self):
cert_der = b'MIIBjzCCATWgAwIBAgIQeNQTxkMgq4BF9tKogIGXUTAKBggqhkjOPQQ' \
@@ -253,7 +225,7 @@
expected_hash = 'FECF1B2585449990D9E3B2C92D3F597EC8354E124EDA751D948' \
'37C2C89A2C155'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_ecdsa_sha384(self):
cert_der = b'MIIBjzCCATWgAwIBAgIQcO3/jALdQ6BOAoaoseLSCjAKBggqhkjOPQQ' \
@@ -270,7 +242,7 @@
expected_hash = 'D2987AD8F20E8316A831261B74EF7B3E55155D0922E07FFE546' \
'20806982B68A73A5E3C478BAA5E7714135CB26D980749'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_ecdsa_sha512(self):
cert_der = b'MIIBjjCCATWgAwIBAgIQHVj2AGEwd6pOOSbcf0skQDAKBggqhkjOPQQ' \
@@ -288,7 +260,7 @@
'F19A5BD8F0B2FAAC861855FBB63A221CC46FC1E226A072411AF' \
'175DDE479281E006878B348059'
actual_hash =
requests_ntlm.requests_ntlm._get_certificate_hash(base64.b64decode(cert_der))
- assert actual_hash == expected_hash
+ assert actual_hash == base64.b16decode(expected_hash)
def test_invalid_signature_algorithm(self):
# Manually edited from test_ecdsa_sha512 to change the OID to
'1.2.840.10045.4.3.5'