1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
# -*- coding: utf-8 -*-
# Copyright: (c) 2020, Jordan Borean (@jborean93) <jborean93@gmail.com>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
import re
import pytest
import spnego.exceptions as exceptions
GSSError = exceptions.GSSError
WinError = exceptions.WinError
@pytest.mark.parametrize(
"option, expected",
[
(
exceptions.NegotiateOptions.negotiate_kerberos,
"The Python gssapi library is not installed so Kerberos cannot be negotiated.",
),
(
exceptions.NegotiateOptions.wrapping_iov,
"The system is missing the GSSAPI IOV extension headers or CredSSP is being requested, "
"cannot utilize wrap_iov and unwrap_iov",
),
(
exceptions.NegotiateOptions.wrapping_winrm,
"The system is missing the GSSAPI IOV extension headers required for WinRM encryption with Kerberos.",
),
(exceptions.NegotiateOptions.session_key, "The protocol selected does not support getting the session key."),
],
)
def test_feature_missing_error(option, expected):
err = exceptions.FeatureMissingError(option)
assert str(err) == expected
assert err.message == expected
def test_spnego_error_no_code_fail():
expected = "SpnegoError requires either an error_code or base_error"
with pytest.raises(ValueError, match=re.escape(expected)):
exceptions.SpnegoError()
def test_spnego_error_invalid_base_error_fail():
expected = "base_error of type 'Exception' is not supported, must be a gssapi.exceptions.GSSError or WindowsError"
with pytest.raises(ValueError, match=re.escape(expected)):
exceptions.SpnegoError(base_error=Exception())
def test_spnego_error_unknown_error():
actual = exceptions.SpnegoError(1024)
assert isinstance(actual, exceptions.SpnegoError)
assert actual.message == "SpnegoError (1024): Unknown error code"
def test_invalid_token_error():
actual = exceptions.SpnegoError(exceptions.ErrorCode.invalid_token)
assert isinstance(actual, exceptions.InvalidTokenError)
assert actual.ERROR_CODE == exceptions.ErrorCode.invalid_token
assert actual.base_error is None
assert actual.message == "SpnegoError (9): A token was invalid, or the logon was denied"
def test_invalid_token_error_with_context():
actual = exceptions.InvalidTokenError(context_msg="Context")
assert isinstance(actual, exceptions.InvalidTokenError)
assert actual.ERROR_CODE == exceptions.ErrorCode.invalid_token
assert actual.base_error is None
assert actual.message == "SpnegoError (9): A token was invalid, or the logon was denied, Context: Context"
@pytest.mark.skipif(GSSError == Exception, reason="Need a GSSError to test this out")
def test_invalid_token_from_gssapi():
base_error = GSSError(589824, 0)
actual = exceptions.SpnegoError(base_error=base_error)
assert isinstance(actual, exceptions.InvalidTokenError)
assert actual.ERROR_CODE == exceptions.ErrorCode.invalid_token
assert actual.base_error == base_error
assert actual.message.startswith("SpnegoError (9): Major (589824)")
@pytest.mark.skipif(WinError == Exception, reason="Need a WindowsError to test this out")
def test_invalid_token_from_sspi():
base_error = WinError("Error")
setattr(base_error, "winerror", -2146893048)
actual = exceptions.SpnegoError(base_error=base_error)
assert isinstance(actual, exceptions.InvalidTokenError)
assert actual.ERROR_CODE == exceptions.ErrorCode.invalid_token
assert actual.base_error == base_error
assert actual.message.startswith("SpnegoError (9): ")
@pytest.mark.skipif(WinError == Exception, reason="Need a WindowsError to test this out")
def test_invalid_token_from_sspi_logon_denied():
base_error = WinError("Error")
setattr(base_error, "winerror", -2146893044)
actual = exceptions.SpnegoError(base_error=base_error)
assert isinstance(actual, exceptions.InvalidTokenError)
assert actual.ERROR_CODE == exceptions.ErrorCode.invalid_token
assert actual.base_error == base_error
assert actual.message.startswith("SpnegoError (9): ")
def test_operation_not_available_error():
actual = exceptions.SpnegoError(exceptions.ErrorCode.unavailable)
assert isinstance(actual, exceptions.OperationNotAvailableError)
assert actual.ERROR_CODE == exceptions.ErrorCode.unavailable
assert actual.base_error is None
assert actual.message == "SpnegoError (16): Operation not supported or available"
def test_operation_not_available_error_with_context():
actual = exceptions.OperationNotAvailableError(context_msg="Context")
assert isinstance(actual, exceptions.OperationNotAvailableError)
assert actual.ERROR_CODE == exceptions.ErrorCode.unavailable
assert actual.base_error is None
assert actual.message == "SpnegoError (16): Operation not supported or available, Context: Context"
@pytest.mark.skipif(GSSError == Exception, reason="Need a GSSError to test this out")
def test_operation_not_available_from_gssapi():
base_error = GSSError(1048576, 0)
actual = exceptions.SpnegoError(base_error=base_error)
assert isinstance(actual, exceptions.OperationNotAvailableError)
assert actual.ERROR_CODE == exceptions.ErrorCode.unavailable
assert actual.base_error == base_error
assert actual.message.startswith("SpnegoError (16): Major (1048576): ")
@pytest.mark.skipif(WinError == Exception, reason="Need a WindowsError to test this out")
def test_operation_not_available_from_sspi():
base_error = WinError("Error")
setattr(base_error, "winerror", -2146893054)
actual = exceptions.SpnegoError(base_error=base_error)
assert isinstance(actual, exceptions.OperationNotAvailableError)
assert actual.ERROR_CODE == exceptions.ErrorCode.unavailable
assert actual.base_error == base_error
assert actual.message.startswith("SpnegoError (16): ")
|