Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
226
venv/Lib/site-packages/win32/lib/sspi.py
Normal file
226
venv/Lib/site-packages/win32/lib/sspi.py
Normal file
|
@ -0,0 +1,226 @@
|
|||
"""
|
||||
Helper classes for SSPI authentication via the win32security module.
|
||||
|
||||
SSPI authentication involves a token-exchange "dance", the exact details
|
||||
of which depends on the authentication provider used. There are also
|
||||
a number of complex flags and constants that need to be used - in most
|
||||
cases, there are reasonable defaults.
|
||||
|
||||
These classes attempt to hide these details from you until you really need
|
||||
to know. They are not designed to handle all cases, just the common ones.
|
||||
If you need finer control than offered here, just use the win32security
|
||||
functions directly.
|
||||
"""
|
||||
# Based on Roger Upole's sspi demos.
|
||||
# $Id$
|
||||
import win32security, sspicon
|
||||
|
||||
error = win32security.error
|
||||
|
||||
class _BaseAuth(object):
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
"""Reset everything to an unauthorized state"""
|
||||
self.ctxt = None
|
||||
self.authenticated = False
|
||||
# The next seq_num for an encrypt/sign operation
|
||||
self.next_seq_num = 0
|
||||
|
||||
def _get_next_seq_num(self):
|
||||
"""Get the next sequence number for a transmission. Default
|
||||
implementation is to increment a counter
|
||||
"""
|
||||
ret = self.next_seq_num
|
||||
self.next_seq_num = self.next_seq_num + 1
|
||||
return ret
|
||||
|
||||
def encrypt(self, data):
|
||||
"""Encrypt a string, returning a tuple of (encrypted_data, encryption_data).
|
||||
These can be passed to decrypt to get back the original string.
|
||||
"""
|
||||
pkg_size_info=self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES)
|
||||
trailersize=pkg_size_info['SecurityTrailer']
|
||||
|
||||
encbuf=win32security.PySecBufferDescType()
|
||||
encbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA))
|
||||
encbuf.append(win32security.PySecBufferType(trailersize, sspicon.SECBUFFER_TOKEN))
|
||||
encbuf[0].Buffer=data
|
||||
self.ctxt.EncryptMessage(0,encbuf,self._get_next_seq_num())
|
||||
return encbuf[0].Buffer, encbuf[1].Buffer
|
||||
|
||||
def decrypt(self, data, trailer):
|
||||
"""Decrypt a previously encrypted string, returning the orignal data"""
|
||||
encbuf=win32security.PySecBufferDescType()
|
||||
encbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA))
|
||||
encbuf.append(win32security.PySecBufferType(len(trailer), sspicon.SECBUFFER_TOKEN))
|
||||
encbuf[0].Buffer=data
|
||||
encbuf[1].Buffer=trailer
|
||||
self.ctxt.DecryptMessage(encbuf,self._get_next_seq_num())
|
||||
return encbuf[0].Buffer
|
||||
|
||||
def sign(self, data):
|
||||
"""sign a string suitable for transmission, returning the signature.
|
||||
Passing the data and signature to verify will determine if the data
|
||||
is unchanged.
|
||||
"""
|
||||
pkg_size_info=self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES)
|
||||
sigsize=pkg_size_info['MaxSignature']
|
||||
sigbuf=win32security.PySecBufferDescType()
|
||||
sigbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA))
|
||||
sigbuf.append(win32security.PySecBufferType(sigsize, sspicon.SECBUFFER_TOKEN))
|
||||
sigbuf[0].Buffer=data
|
||||
|
||||
self.ctxt.MakeSignature(0,sigbuf,self._get_next_seq_num())
|
||||
return sigbuf[1].Buffer
|
||||
|
||||
def verify(self, data, sig):
|
||||
"""Verifies data and its signature. If verification fails, an sspi.error
|
||||
will be raised.
|
||||
"""
|
||||
sigbuf=win32security.PySecBufferDescType()
|
||||
sigbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA))
|
||||
sigbuf.append(win32security.PySecBufferType(len(sig), sspicon.SECBUFFER_TOKEN))
|
||||
|
||||
sigbuf[0].Buffer=data
|
||||
sigbuf[1].Buffer=sig
|
||||
self.ctxt.VerifySignature(sigbuf,self._get_next_seq_num())
|
||||
|
||||
class ClientAuth(_BaseAuth):
|
||||
"""Manages the client side of an SSPI authentication handshake
|
||||
"""
|
||||
def __init__(self,
|
||||
pkg_name, # Name of the package to used.
|
||||
client_name = None, # User for whom credentials are used.
|
||||
auth_info = None, # or a tuple of (username, domain, password)
|
||||
targetspn = None, # Target security context provider name.
|
||||
scflags=None, # security context flags
|
||||
datarep=sspicon.SECURITY_NETWORK_DREP):
|
||||
if scflags is None:
|
||||
scflags = sspicon.ISC_REQ_INTEGRITY|sspicon.ISC_REQ_SEQUENCE_DETECT|\
|
||||
sspicon.ISC_REQ_REPLAY_DETECT|sspicon.ISC_REQ_CONFIDENTIALITY
|
||||
self.scflags=scflags
|
||||
self.datarep=datarep
|
||||
self.targetspn=targetspn
|
||||
self.pkg_info=win32security.QuerySecurityPackageInfo(pkg_name)
|
||||
self.credentials, \
|
||||
self.credentials_expiry=win32security.AcquireCredentialsHandle(
|
||||
client_name, self.pkg_info['Name'],
|
||||
sspicon.SECPKG_CRED_OUTBOUND,
|
||||
None, auth_info)
|
||||
_BaseAuth.__init__(self)
|
||||
|
||||
# Perform *one* step of the client authentication process.
|
||||
def authorize(self, sec_buffer_in):
|
||||
if sec_buffer_in is not None and type(sec_buffer_in) != win32security.PySecBufferDescType:
|
||||
# User passed us the raw data - wrap it into a SecBufferDesc
|
||||
sec_buffer_new=win32security.PySecBufferDescType()
|
||||
tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'],
|
||||
sspicon.SECBUFFER_TOKEN)
|
||||
tokenbuf.Buffer=sec_buffer_in
|
||||
sec_buffer_new.append(tokenbuf)
|
||||
sec_buffer_in = sec_buffer_new
|
||||
sec_buffer_out=win32security.PySecBufferDescType()
|
||||
tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'], sspicon.SECBUFFER_TOKEN)
|
||||
sec_buffer_out.append(tokenbuf)
|
||||
## input context handle should be NULL on first call
|
||||
ctxtin=self.ctxt
|
||||
if self.ctxt is None:
|
||||
self.ctxt=win32security.PyCtxtHandleType()
|
||||
err, attr, exp=win32security.InitializeSecurityContext(
|
||||
self.credentials,
|
||||
ctxtin,
|
||||
self.targetspn,
|
||||
self.scflags,
|
||||
self.datarep,
|
||||
sec_buffer_in,
|
||||
self.ctxt,
|
||||
sec_buffer_out)
|
||||
# Stash these away incase someone needs to know the state from the
|
||||
# final call.
|
||||
self.ctxt_attr = attr
|
||||
self.ctxt_expiry = exp
|
||||
|
||||
if err in (sspicon.SEC_I_COMPLETE_NEEDED,sspicon.SEC_I_COMPLETE_AND_CONTINUE):
|
||||
self.ctxt.CompleteAuthToken(sec_buffer_out)
|
||||
self.authenticated = err == 0
|
||||
return err, sec_buffer_out
|
||||
|
||||
class ServerAuth(_BaseAuth):
|
||||
"""Manages the server side of an SSPI authentication handshake
|
||||
"""
|
||||
def __init__(self,
|
||||
pkg_name,
|
||||
spn = None,
|
||||
scflags=None,
|
||||
datarep=sspicon.SECURITY_NETWORK_DREP):
|
||||
self.spn=spn
|
||||
self.datarep=datarep
|
||||
|
||||
if scflags is None:
|
||||
scflags = sspicon.ASC_REQ_INTEGRITY|sspicon.ASC_REQ_SEQUENCE_DETECT|\
|
||||
sspicon.ASC_REQ_REPLAY_DETECT|sspicon.ASC_REQ_CONFIDENTIALITY
|
||||
# Should we default to sspicon.KerbAddExtraCredentialsMessage
|
||||
# if pkg_name=='Kerberos'?
|
||||
self.scflags=scflags
|
||||
|
||||
self.pkg_info=win32security.QuerySecurityPackageInfo(pkg_name)
|
||||
|
||||
self.credentials, \
|
||||
self.credentials_expiry=win32security.AcquireCredentialsHandle(spn,
|
||||
self.pkg_info['Name'], sspicon.SECPKG_CRED_INBOUND, None, None)
|
||||
_BaseAuth.__init__(self)
|
||||
|
||||
# Perform *one* step of the server authentication process.
|
||||
def authorize(self, sec_buffer_in):
|
||||
if sec_buffer_in is not None and type(sec_buffer_in) != win32security.PySecBufferDescType:
|
||||
# User passed us the raw data - wrap it into a SecBufferDesc
|
||||
sec_buffer_new=win32security.PySecBufferDescType()
|
||||
tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'],
|
||||
sspicon.SECBUFFER_TOKEN)
|
||||
tokenbuf.Buffer=sec_buffer_in
|
||||
sec_buffer_new.append(tokenbuf)
|
||||
sec_buffer_in = sec_buffer_new
|
||||
|
||||
sec_buffer_out=win32security.PySecBufferDescType()
|
||||
tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'], sspicon.SECBUFFER_TOKEN)
|
||||
sec_buffer_out.append(tokenbuf)
|
||||
## input context handle is None initially, then handle returned from last call thereafter
|
||||
ctxtin=self.ctxt
|
||||
if self.ctxt is None:
|
||||
self.ctxt=win32security.PyCtxtHandleType()
|
||||
err, attr, exp = win32security.AcceptSecurityContext(self.credentials, ctxtin,
|
||||
sec_buffer_in, self.scflags,
|
||||
self.datarep, self.ctxt, sec_buffer_out)
|
||||
|
||||
# Stash these away incase someone needs to know the state from the
|
||||
# final call.
|
||||
self.ctxt_attr = attr
|
||||
self.ctxt_expiry = exp
|
||||
|
||||
if err in (sspicon.SEC_I_COMPLETE_NEEDED,sspicon.SEC_I_COMPLETE_AND_CONTINUE):
|
||||
self.ctxt.CompleteAuthToken(sec_buffer_out)
|
||||
self.authenticated = err == 0
|
||||
return err, sec_buffer_out
|
||||
|
||||
if __name__=='__main__':
|
||||
# Setup the 2 contexts.
|
||||
sspiclient=ClientAuth("NTLM")
|
||||
sspiserver=ServerAuth("NTLM")
|
||||
|
||||
# Perform the authentication dance, each loop exchanging more information
|
||||
# on the way to completing authentication.
|
||||
sec_buffer=None
|
||||
while 1:
|
||||
err, sec_buffer = sspiclient.authorize(sec_buffer)
|
||||
err, sec_buffer = sspiserver.authorize(sec_buffer)
|
||||
if err==0:
|
||||
break
|
||||
data = "hello".encode("ascii") # py3k-friendly
|
||||
sig = sspiclient.sign(data)
|
||||
sspiserver.verify(data, sig)
|
||||
|
||||
data, key = sspiclient.encrypt(data)
|
||||
assert sspiserver.decrypt(data, key) == data
|
||||
print("cool!")
|
Loading…
Add table
Add a link
Reference in a new issue