Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SPNEGO mechanism by default (#41) #46

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----------------
Expand Down
14 changes: 7 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -194,21 +194,21 @@ 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

>>> import gssapi
>>> 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)
...

Expand Down
4 changes: 2 additions & 2 deletions requests_gssapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
9 changes: 6 additions & 3 deletions requests_gssapi/gssapi_.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Response>` object, which contains a server's
Expand Down Expand Up @@ -101,23 +104,23 @@ 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.

"""
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
self.target_name = target_name
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):
Expand Down
27 changes: 14 additions & 13 deletions test_requests_gssapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -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,
Expand All @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand Down Expand Up @@ -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):
Expand All @@ -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,
Expand All @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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")


Expand Down