|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- # Some tests of the win32security sspi functions.
- # Stolen from Roger's original test_sspi.c, a version of which is in "Demos"
- # See also the other SSPI demos.
- import re
- import unittest
-
- import sspi
- import sspicon
- import win32api
- import win32security
- from pywin32_testutil import TestSkipped, str2bytes, testmain
-
-
- # It is quite likely that the Kerberos tests will fail due to not being
- # installed. The NTLM tests do *not* get the same behaviour as they should
- # always be there.
- def applyHandlingSkips(func, *args):
- try:
- return func(*args)
- except win32api.error as exc:
- if exc.winerror in [
- sspicon.SEC_E_NO_CREDENTIALS,
- sspicon.SEC_E_NO_AUTHENTICATING_AUTHORITY,
- ]:
- raise TestSkipped(exc)
- raise
-
-
- class TestSSPI(unittest.TestCase):
- def assertRaisesHRESULT(self, hr, func, *args):
- try:
- return func(*args)
- raise RuntimeError("expecting %s failure" % (hr,))
- except win32security.error as exc:
- self.assertEqual(exc.winerror, hr)
-
- def _doAuth(self, pkg_name):
- sspiclient = sspi.ClientAuth(pkg_name, targetspn=win32api.GetUserName())
- sspiserver = sspi.ServerAuth(pkg_name)
-
- sec_buffer = None
- err = 1
- while err != 0:
- err, sec_buffer = sspiclient.authorize(sec_buffer)
- err, sec_buffer = sspiserver.authorize(sec_buffer)
- return sspiclient, sspiserver
-
- def _doTestImpersonate(self, pkg_name):
- # Just for the sake of code exercising!
- sspiclient, sspiserver = self._doAuth(pkg_name)
- sspiserver.ctxt.ImpersonateSecurityContext()
- sspiserver.ctxt.RevertSecurityContext()
-
- def testImpersonateKerberos(self):
- applyHandlingSkips(self._doTestImpersonate, "Kerberos")
-
- def testImpersonateNTLM(self):
- self._doTestImpersonate("NTLM")
-
- def _doTestEncrypt(self, pkg_name):
- sspiclient, sspiserver = self._doAuth(pkg_name)
-
- pkg_size_info = sspiclient.ctxt.QueryContextAttributes(
- sspicon.SECPKG_ATTR_SIZES
- )
- msg = str2bytes("some data to be encrypted ......")
-
- trailersize = pkg_size_info["SecurityTrailer"]
- encbuf = win32security.PySecBufferDescType()
- encbuf.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA))
- encbuf.append(
- win32security.PySecBufferType(trailersize, sspicon.SECBUFFER_TOKEN)
- )
- encbuf[0].Buffer = msg
- sspiclient.ctxt.EncryptMessage(0, encbuf, 1)
- sspiserver.ctxt.DecryptMessage(encbuf, 1)
- self.assertEqual(msg, encbuf[0].Buffer)
- # and test the higher-level functions
- data_in = str2bytes("hello")
- data, sig = sspiclient.encrypt(data_in)
- self.assertEqual(sspiserver.decrypt(data, sig), data_in)
-
- data, sig = sspiserver.encrypt(data_in)
- self.assertEqual(sspiclient.decrypt(data, sig), data_in)
-
- def _doTestEncryptStream(self, pkg_name):
- # Test out the SSPI/GSSAPI interop wrapping examples at
- # https://docs.microsoft.com/en-us/windows/win32/secauthn/sspi-kerberos-interoperability-with-gssapi
-
- sspiclient, sspiserver = self._doAuth(pkg_name)
-
- pkg_size_info = sspiclient.ctxt.QueryContextAttributes(
- sspicon.SECPKG_ATTR_SIZES
- )
- msg = str2bytes("some data to be encrypted ......")
-
- trailersize = pkg_size_info["SecurityTrailer"]
- blocksize = pkg_size_info["BlockSize"]
- encbuf = win32security.PySecBufferDescType()
- encbuf.append(
- win32security.PySecBufferType(trailersize, sspicon.SECBUFFER_TOKEN)
- )
- encbuf.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA))
- encbuf.append(
- win32security.PySecBufferType(blocksize, sspicon.SECBUFFER_PADDING)
- )
- encbuf[1].Buffer = msg
- sspiclient.ctxt.EncryptMessage(0, encbuf, 1)
-
- encmsg = encbuf[0].Buffer + encbuf[1].Buffer + encbuf[2].Buffer
- decbuf = win32security.PySecBufferDescType()
- decbuf.append(
- win32security.PySecBufferType(len(encmsg), sspicon.SECBUFFER_STREAM)
- )
- decbuf.append(win32security.PySecBufferType(0, sspicon.SECBUFFER_DATA))
- decbuf[0].Buffer = encmsg
-
- sspiserver.ctxt.DecryptMessage(decbuf, 1)
- self.assertEqual(msg, decbuf[1].Buffer)
-
- def testEncryptNTLM(self):
- self._doTestEncrypt("NTLM")
-
- def testEncryptStreamNTLM(self):
- self._doTestEncryptStream("NTLM")
-
- def testEncryptKerberos(self):
- applyHandlingSkips(self._doTestEncrypt, "Kerberos")
-
- def testEncryptStreamKerberos(self):
- applyHandlingSkips(self._doTestEncryptStream, "Kerberos")
-
- def _doTestSign(self, pkg_name):
- sspiclient, sspiserver = self._doAuth(pkg_name)
-
- pkg_size_info = sspiclient.ctxt.QueryContextAttributes(
- sspicon.SECPKG_ATTR_SIZES
- )
- msg = str2bytes("some data to be encrypted ......")
-
- sigsize = pkg_size_info["MaxSignature"]
- sigbuf = win32security.PySecBufferDescType()
- sigbuf.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA))
- sigbuf.append(win32security.PySecBufferType(sigsize, sspicon.SECBUFFER_TOKEN))
- sigbuf[0].Buffer = msg
- sspiclient.ctxt.MakeSignature(0, sigbuf, 0)
- sspiserver.ctxt.VerifySignature(sigbuf, 0)
- # and test the higher-level functions
- sspiclient.next_seq_num = 1
- sspiserver.next_seq_num = 1
- data = str2bytes("hello")
- key = sspiclient.sign(data)
- sspiserver.verify(data, key)
- key = sspiclient.sign(data)
- self.assertRaisesHRESULT(
- sspicon.SEC_E_MESSAGE_ALTERED, sspiserver.verify, data + data, key
- )
-
- # and the other way
- key = sspiserver.sign(data)
- sspiclient.verify(data, key)
- key = sspiserver.sign(data)
- self.assertRaisesHRESULT(
- sspicon.SEC_E_MESSAGE_ALTERED, sspiclient.verify, data + data, key
- )
-
- def testSignNTLM(self):
- self._doTestSign("NTLM")
-
- def testSignKerberos(self):
- applyHandlingSkips(self._doTestSign, "Kerberos")
-
- def _testSequenceSign(self):
- # Only Kerberos supports sequence detection.
- sspiclient, sspiserver = self._doAuth("Kerberos")
- key = sspiclient.sign(b"hello")
- sspiclient.sign(b"hello")
- self.assertRaisesHRESULT(
- sspicon.SEC_E_OUT_OF_SEQUENCE, sspiserver.verify, b"hello", key
- )
-
- def testSequenceSign(self):
- applyHandlingSkips(self._testSequenceSign)
-
- def _testSequenceEncrypt(self):
- # Only Kerberos supports sequence detection.
- sspiclient, sspiserver = self._doAuth("Kerberos")
- blob, key = sspiclient.encrypt(b"hello")
- blob, key = sspiclient.encrypt(b"hello")
- self.assertRaisesHRESULT(
- sspicon.SEC_E_OUT_OF_SEQUENCE, sspiserver.decrypt, blob, key
- )
-
- def testSequenceEncrypt(self):
- applyHandlingSkips(self._testSequenceEncrypt)
-
- def testSecBufferRepr(self):
- desc = win32security.PySecBufferDescType()
- assert re.match(
- "PySecBufferDesc\(ulVersion: 0 \| cBuffers: 0 \| pBuffers: 0x[\da-fA-F]{8,16}\)",
- repr(desc),
- )
-
- buffer1 = win32security.PySecBufferType(0, sspicon.SECBUFFER_TOKEN)
- assert re.match(
- "PySecBuffer\(cbBuffer: 0 \| BufferType: 2 \| pvBuffer: 0x[\da-fA-F]{8,16}\)",
- repr(buffer1),
- )
- "PySecBuffer(cbBuffer: 0 | BufferType: 2 | pvBuffer: 0x000001B8CC6D8020)"
- desc.append(buffer1)
-
- assert re.match(
- "PySecBufferDesc\(ulVersion: 0 \| cBuffers: 1 \| pBuffers: 0x[\da-fA-F]{8,16}\)",
- repr(desc),
- )
-
- buffer2 = win32security.PySecBufferType(4, sspicon.SECBUFFER_DATA)
- assert re.match(
- "PySecBuffer\(cbBuffer: 4 \| BufferType: 1 \| pvBuffer: 0x[\da-fA-F]{8,16}\)",
- repr(buffer2),
- )
- desc.append(buffer2)
-
- assert re.match(
- "PySecBufferDesc\(ulVersion: 0 \| cBuffers: 2 \| pBuffers: 0x[\da-fA-F]{8,16}\)",
- repr(desc),
- )
-
-
- if __name__ == "__main__":
- testmain()
|