diff --git a/HISTORY.rst b/HISTORY.rst index 0182670..57d8d38 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,6 +4,7 @@ History FUTURE: TBD ----------- - Drop flag for out of sequence detection +- Use SPNEGO mechanism by default 1.2.3: 2021-02-08 ----------------- diff --git a/README.rst b/README.rst index 6e3456e..6c787ca 100644 --- a/README.rst +++ b/README.rst @@ -194,10 +194,10 @@ applicable). However, an explicit credential can be in instead, if desired. Explicit Mechanism ------------------ -``HTTPSPNEGOAuth`` normally lets the underlying ``gssapi`` library decide which -negotiation mechanism to use. However, an explicit mechanism can be used instead -if desired. The ``mech`` parameter will be passed straight through to ``gssapi`` -without interference. It is expected to be an instance of ``gssapi.mechs.Mechanism``. +``HTTPSPNEGOAuth`` normally lets SPNEGO decide which negotiation mechanism to use. +However, an explicit mechanism can be used instead if desired. The ``mech`` +parameter will be passed straight through to ``gssapi`` without interference. +It is expected to be an instance of ``gssapi.mechs.Mechanism``. .. code-block:: python @@ -205,10 +205,10 @@ without interference. It is expected to be an instance of ``gssapi.mechs.Mechani >>> import requests >>> from requests_gssapi import HTTPSPNEGOAuth >>> try: - ... spnego = gssapi.mechs.Mechanism.from_sasl_name("SPNEGO") + ... krb5 = gssapi.mechs.Mechanism.from_sasl_name("GS2-KRB5") ... except AttributeError: - ... spnego = gssapi.OID.from_int_seq("1.3.6.1.5.5.2") - >>> gssapi_auth = HTTPSPNEGOAuth(mech=spnego) + ... krb5 = gssapi.OID.from_int_seq("1.2.840.113554.1.2.2") + >>> gssapi_auth = HTTPSPNEGOAuth(mech=krb5) >>> r = requests.get("http://example.org", auth=gssapi_auth) ... diff --git a/requests_gssapi/__init__.py b/requests_gssapi/__init__.py index 92bd9ed..65e6d4e 100644 --- a/requests_gssapi/__init__.py +++ b/requests_gssapi/__init__.py @@ -14,12 +14,12 @@ """ import logging -from .gssapi_ import HTTPSPNEGOAuth, REQUIRED, OPTIONAL, DISABLED # noqa +from .gssapi_ import HTTPSPNEGOAuth, SPNEGO, REQUIRED, OPTIONAL, DISABLED # noqa from .exceptions import MutualAuthenticationError from .compat import NullHandler, HTTPKerberosAuth logging.getLogger(__name__).addHandler(NullHandler()) __all__ = ('HTTPSPNEGOAuth', 'HTTPKerberosAuth', 'MutualAuthenticationError', - 'REQUIRED', 'OPTIONAL', 'DISABLED') + 'SPNEGO', 'REQUIRED', 'OPTIONAL', 'DISABLED') __version__ = '1.2.3' diff --git a/requests_gssapi/gssapi_.py b/requests_gssapi/gssapi_.py index aa7a87b..bdbb578 100644 --- a/requests_gssapi/gssapi_.py +++ b/requests_gssapi/gssapi_.py @@ -30,6 +30,9 @@ OPTIONAL = 2 DISABLED = 3 +# OID for the SPNEGO mechanism +SPNEGO = gssapi.OID.from_int_seq("1.3.6.1.5.5.2") + class SanitizedResponse(Response): """The :class:`Response ` object, which contains a server's @@ -101,7 +104,7 @@ class HTTPSPNEGOAuth(AuthBase): Default is `None`. `mech` is GSSAPI Mechanism (gssapi.Mechanism) to use for negotiation. - Default is `None` + Default is `SPNEGO` `sanitize_mutual_error_response` controls whether we should clean up server responses. See the `SanitizedResponse` class. @@ -109,7 +112,7 @@ class HTTPSPNEGOAuth(AuthBase): """ def __init__(self, mutual_authentication=DISABLED, target_name="HTTP", delegate=False, opportunistic_auth=False, creds=None, - mech=None, sanitize_mutual_error_response=True): + mech=SPNEGO, sanitize_mutual_error_response=True): self.context = {} self.pos = None self.mutual_authentication = mutual_authentication @@ -117,7 +120,7 @@ def __init__(self, mutual_authentication=DISABLED, target_name="HTTP", self.delegate = delegate self.opportunistic_auth = opportunistic_auth self.creds = creds - self.mech = mech + self.mech = mech if mech else SPNEGO self.sanitize_mutual_error_response = sanitize_mutual_error_response def generate_request_header(self, response, host, is_preemptive=False): diff --git a/test_requests_gssapi.py b/test_requests_gssapi.py index bf15a9c..f2a600d 100644 --- a/test_requests_gssapi.py +++ b/test_requests_gssapi.py @@ -14,6 +14,7 @@ import unittest from requests_gssapi import REQUIRED +from requests_gssapi import SPNEGO # Note: we're not using the @mock.patch decorator: # > My only word of warning is that in the past, the patch decorator hides @@ -110,7 +111,7 @@ def test_generate_request_header(self): b64_negotiate_response) fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - creds=None, mech=None, flags=gssflags, usage="initiate") + creds=None, mech=SPNEGO, flags=gssflags, usage="initiate") fake_resp.assert_called_with(b"token") def test_generate_request_header_init_error(self): @@ -125,7 +126,7 @@ def test_generate_request_header_init_error(self): auth.generate_request_header, response, host) fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - usage="initiate", flags=gssflags, creds=None, mech=None) + usage="initiate", flags=gssflags, creds=None, mech=SPNEGO) def test_generate_request_header_step_error(self): with patch.multiple("gssapi.SecurityContext", __init__=fake_init, @@ -139,7 +140,7 @@ def test_generate_request_header_step_error(self): auth.generate_request_header, response, host) fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - usage="initiate", flags=gssflags, creds=None, mech=None) + usage="initiate", flags=gssflags, creds=None, mech=SPNEGO) fail_resp.assert_called_with(b"token") def test_authenticate_user(self): @@ -176,7 +177,7 @@ def test_authenticate_user(self): raw.release_conn.assert_called_with() fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - flags=gssflags, usage="initiate", creds=None, mech=None) + flags=gssflags, usage="initiate", creds=None, mech=SPNEGO) fake_resp.assert_called_with(b"token") def test_handle_401(self): @@ -213,7 +214,7 @@ def test_handle_401(self): raw.release_conn.assert_called_with() fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - creds=None, mech=None, flags=gssflags, usage="initiate") + creds=None, mech=SPNEGO, flags=gssflags, usage="initiate") fake_resp.assert_called_with(b"token") def test_authenticate_server(self): @@ -452,7 +453,7 @@ def test_handle_response_401(self): raw.release_conn.assert_called_with() fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - usage="initiate", flags=gssflags, creds=None, mech=None) + usage="initiate", flags=gssflags, creds=None, mech=SPNEGO) fake_resp.assert_called_with(b"token") def test_handle_response_401_rejected(self): @@ -495,7 +496,7 @@ def connection_send(self, *args, **kwargs): raw.release_conn.assert_called_with() fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - usage="initiate", flags=gssflags, creds=None, mech=None) + usage="initiate", flags=gssflags, creds=None, mech=SPNEGO) fake_resp.assert_called_with(b"token") def test_generate_request_header_custom_service(self): @@ -509,7 +510,7 @@ def test_generate_request_header_custom_service(self): auth.generate_request_header(response, host), fake_init.assert_called_with( name=gssapi_sname("barfoo@www.example.org"), - usage="initiate", flags=gssflags, creds=None, mech=None) + usage="initiate", flags=gssflags, creds=None, mech=SPNEGO) fake_resp.assert_called_with(b"token") def test_delegation(self): @@ -547,7 +548,7 @@ def test_delegation(self): raw.release_conn.assert_called_with() fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), - usage="initiate", flags=gssdelegflags, creds=None, mech=None) + usage="initiate", flags=gssdelegflags, creds=None, mech=SPNEGO) fake_resp.assert_called_with(b"token") def test_principal_override(self): @@ -566,7 +567,7 @@ def test_principal_override(self): fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), usage="initiate", flags=gssflags, - creds=b"fake creds", mech=None) + creds=b"fake creds", mech=SPNEGO) def test_realm_override(self): with patch.multiple("gssapi.SecurityContext", __init__=fake_init, @@ -580,7 +581,7 @@ def test_realm_override(self): auth.generate_request_header(response, host) fake_init.assert_called_with( name=gssapi_sname("HTTP@otherhost.otherdomain.org"), - usage="initiate", flags=gssflags, creds=None, mech=None) + usage="initiate", flags=gssflags, creds=None, mech=SPNEGO) fake_resp.assert_called_with(b"token") def test_opportunistic_auth(self): @@ -610,7 +611,7 @@ def test_explicit_creds(self): fake_init.assert_called_with( name=gssapi_sname("HTTP@www.example.org"), usage="initiate", flags=gssflags, - creds=b"fake creds", mech=None) + creds=b"fake creds", mech=SPNEGO) fake_resp.assert_called_with(b"token") def test_explicit_mech(self): @@ -642,7 +643,7 @@ def test_target_name(self): auth.generate_request_header(response, host) fake_init.assert_called_with( name=gssapi_sname("HTTP@otherhost.otherdomain.org"), - usage="initiate", flags=gssflags, creds=None, mech=None) + usage="initiate", flags=gssflags, creds=None, mech=SPNEGO) fake_resp.assert_called_with(b"token")