move nearly everything into /src to make git.io/gam cleaner w/o a readme tree

This commit is contained in:
Jay Lee
2015-09-30 09:14:32 -04:00
parent 8b19040e45
commit c1225178d6
225 changed files with 2015 additions and 2015 deletions

View File

View File

@ -1,21 +1,21 @@
rmdir /q /s gam
rmdir /q /s gam-64
rmdir /q /s build
rmdir /q /s dist
del /q /f gam-%1-windows.zip
del /q /f gam-%1-windows-x64.zip
c:\python27-32\scripts\pyinstaller -F --distpath=gam gam.spec
xcopy LICENSE gam\
xcopy whatsnew.txt gam\
xcopy admin-settings-v1.json gam\
xcopy cloudprint-v2.json gam\
del gam\w9xpopen.exe
"%ProgramFiles(x86)%\7-Zip\7z.exe" a -tzip gam-%1-windows.zip gam\ -xr!.svn
c:\python27\scripts\pyinstaller -F --distpath=gam-64 gam.spec
xcopy LICENSE gam-64\
xcopy whatsnew.txt gam-64\
xcopy admin-settings-v1.json gam-64\
xcopy cloudprint-v2.json gam-64\
"%ProgramFiles(x86)%\7-Zip\7z.exe" a -tzip gam-%1-windows-x64.zip gam-64\ -xr!.svn
rmdir /q /s gam
rmdir /q /s gam-64
rmdir /q /s build
rmdir /q /s dist
del /q /f gam-%1-windows.zip
del /q /f gam-%1-windows-x64.zip
c:\python27-32\scripts\pyinstaller -F --distpath=gam gam.spec
xcopy LICENSE gam\
xcopy whatsnew.txt gam\
xcopy admin-settings-v1.json gam\
xcopy cloudprint-v2.json gam\
del gam\w9xpopen.exe
"%ProgramFiles(x86)%\7-Zip\7z.exe" a -tzip gam-%1-windows.zip gam\ -xr!.svn
c:\python27\scripts\pyinstaller -F --distpath=gam-64 gam.spec
xcopy LICENSE gam-64\
xcopy whatsnew.txt gam-64\
xcopy admin-settings-v1.json gam-64\
xcopy cloudprint-v2.json gam-64\
"%ProgramFiles(x86)%\7-Zip\7z.exe" a -tzip gam-%1-windows-x64.zip gam-64\ -xr!.svn

0
gam.py → src/gam.py Executable file → Normal file
View File

View File

@ -1,17 +1,17 @@
1. Moved oauth.py to __init__.py
2. Refactored __init__.py for compatibility with python 2.2 (Issue 59)
3. Refactored rsa.py for compatibility with python 2.2 (Issue 59)
4. Refactored OAuthRequest.from_token_and_callback since the callback url was
getting double url-encoding the callback url in place of single. (Issue 43)
5. Added build_signature_base_string method to rsa.py since it used the
implementation of this method from oauth.OAuthSignatureMethod_HMAC_SHA1 which
was incorrect since it enforced the presence of a consumer secret and a token
secret. Also, changed its super class from oauth.OAuthSignatureMethod_HMAC_SHA1
to oauth.OAuthSignatureMethod (Issue 64)
6. Refactored <OAuthRequest>.to_header method since it returned non-oauth params
1. Moved oauth.py to __init__.py
2. Refactored __init__.py for compatibility with python 2.2 (Issue 59)
3. Refactored rsa.py for compatibility with python 2.2 (Issue 59)
4. Refactored OAuthRequest.from_token_and_callback since the callback url was
getting double url-encoding the callback url in place of single. (Issue 43)
5. Added build_signature_base_string method to rsa.py since it used the
implementation of this method from oauth.OAuthSignatureMethod_HMAC_SHA1 which
was incorrect since it enforced the presence of a consumer secret and a token
secret. Also, changed its super class from oauth.OAuthSignatureMethod_HMAC_SHA1
to oauth.OAuthSignatureMethod (Issue 64)
6. Refactored <OAuthRequest>.to_header method since it returned non-oauth params
as well which was incorrect. (Issue 31)

File diff suppressed because it is too large Load Diff

View File

@ -1,120 +1,120 @@
"""Base class for SharedKeyDB and VerifierDB."""
import anydbm
import thread
class BaseDB:
def __init__(self, filename, type):
self.type = type
self.filename = filename
if self.filename:
self.db = None
else:
self.db = {}
self.lock = thread.allocate_lock()
def create(self):
"""Create a new on-disk database.
@raise anydbm.error: If there's a problem creating the database.
"""
if self.filename:
self.db = anydbm.open(self.filename, "n") #raises anydbm.error
self.db["--Reserved--type"] = self.type
self.db.sync()
else:
self.db = {}
def open(self):
"""Open a pre-existing on-disk database.
@raise anydbm.error: If there's a problem opening the database.
@raise ValueError: If the database is not of the right type.
"""
if not self.filename:
raise ValueError("Can only open on-disk databases")
self.db = anydbm.open(self.filename, "w") #raises anydbm.error
try:
if self.db["--Reserved--type"] != self.type:
raise ValueError("Not a %s database" % self.type)
except KeyError:
raise ValueError("Not a recognized database")
def __getitem__(self, username):
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
valueStr = self.db[username]
finally:
self.lock.release()
return self._getItem(username, valueStr)
def __setitem__(self, username, value):
if self.db == None:
raise AssertionError("DB not open")
valueStr = self._setItem(username, value)
self.lock.acquire()
try:
self.db[username] = valueStr
if self.filename:
self.db.sync()
finally:
self.lock.release()
def __delitem__(self, username):
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
del(self.db[username])
if self.filename:
self.db.sync()
finally:
self.lock.release()
def __contains__(self, username):
"""Check if the database contains the specified username.
@type username: str
@param username: The username to check for.
@rtype: bool
@return: True if the database contains the username, False
otherwise.
"""
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
return self.db.has_key(username)
finally:
self.lock.release()
def check(self, username, param):
value = self.__getitem__(username)
return self._checkItem(value, username, param)
def keys(self):
"""Return a list of usernames in the database.
@rtype: list
@return: The usernames in the database.
"""
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
usernames = self.db.keys()
finally:
self.lock.release()
usernames = [u for u in usernames if not u.startswith("--Reserved--")]
"""Base class for SharedKeyDB and VerifierDB."""
import anydbm
import thread
class BaseDB:
def __init__(self, filename, type):
self.type = type
self.filename = filename
if self.filename:
self.db = None
else:
self.db = {}
self.lock = thread.allocate_lock()
def create(self):
"""Create a new on-disk database.
@raise anydbm.error: If there's a problem creating the database.
"""
if self.filename:
self.db = anydbm.open(self.filename, "n") #raises anydbm.error
self.db["--Reserved--type"] = self.type
self.db.sync()
else:
self.db = {}
def open(self):
"""Open a pre-existing on-disk database.
@raise anydbm.error: If there's a problem opening the database.
@raise ValueError: If the database is not of the right type.
"""
if not self.filename:
raise ValueError("Can only open on-disk databases")
self.db = anydbm.open(self.filename, "w") #raises anydbm.error
try:
if self.db["--Reserved--type"] != self.type:
raise ValueError("Not a %s database" % self.type)
except KeyError:
raise ValueError("Not a recognized database")
def __getitem__(self, username):
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
valueStr = self.db[username]
finally:
self.lock.release()
return self._getItem(username, valueStr)
def __setitem__(self, username, value):
if self.db == None:
raise AssertionError("DB not open")
valueStr = self._setItem(username, value)
self.lock.acquire()
try:
self.db[username] = valueStr
if self.filename:
self.db.sync()
finally:
self.lock.release()
def __delitem__(self, username):
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
del(self.db[username])
if self.filename:
self.db.sync()
finally:
self.lock.release()
def __contains__(self, username):
"""Check if the database contains the specified username.
@type username: str
@param username: The username to check for.
@rtype: bool
@return: True if the database contains the username, False
otherwise.
"""
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
return self.db.has_key(username)
finally:
self.lock.release()
def check(self, username, param):
value = self.__getitem__(username)
return self._checkItem(value, username, param)
def keys(self):
"""Return a list of usernames in the database.
@rtype: list
@return: The usernames in the database.
"""
if self.db == None:
raise AssertionError("DB not open")
self.lock.acquire()
try:
usernames = self.db.keys()
finally:
self.lock.release()
usernames = [u for u in usernames if not u.startswith("--Reserved--")]
return usernames

View File

@ -1,181 +1,181 @@
"""Class representing an X.509 certificate chain."""
from utils import cryptomath
class X509CertChain:
"""This class represents a chain of X.509 certificates.
@type x509List: list
@ivar x509List: A list of L{tlslite.X509.X509} instances,
starting with the end-entity certificate and with every
subsequent certificate certifying the previous.
"""
def __init__(self, x509List=None):
"""Create a new X509CertChain.
@type x509List: list
@param x509List: A list of L{tlslite.X509.X509} instances,
starting with the end-entity certificate and with every
subsequent certificate certifying the previous.
"""
if x509List:
self.x509List = x509List
else:
self.x509List = []
def getNumCerts(self):
"""Get the number of certificates in this chain.
@rtype: int
"""
return len(self.x509List)
def getEndEntityPublicKey(self):
"""Get the public key from the end-entity certificate.
@rtype: L{tlslite.utils.RSAKey.RSAKey}
"""
if self.getNumCerts() == 0:
raise AssertionError()
return self.x509List[0].publicKey
def getFingerprint(self):
"""Get the hex-encoded fingerprint of the end-entity certificate.
@rtype: str
@return: A hex-encoded fingerprint.
"""
if self.getNumCerts() == 0:
raise AssertionError()
return self.x509List[0].getFingerprint()
def getCommonName(self):
"""Get the Subject's Common Name from the end-entity certificate.
The cryptlib_py module must be installed in order to use this
function.
@rtype: str or None
@return: The CN component of the certificate's subject DN, if
present.
"""
if self.getNumCerts() == 0:
raise AssertionError()
return self.x509List[0].getCommonName()
def validate(self, x509TrustList):
"""Check the validity of the certificate chain.
This checks that every certificate in the chain validates with
the subsequent one, until some certificate validates with (or
is identical to) one of the passed-in root certificates.
The cryptlib_py module must be installed in order to use this
function.
@type x509TrustList: list of L{tlslite.X509.X509}
@param x509TrustList: A list of trusted root certificates. The
certificate chain must extend to one of these certificates to
be considered valid.
"""
import cryptlib_py
c1 = None
c2 = None
lastC = None
rootC = None
try:
rootFingerprints = [c.getFingerprint() for c in x509TrustList]
#Check that every certificate in the chain validates with the
#next one
for cert1, cert2 in zip(self.x509List, self.x509List[1:]):
#If we come upon a root certificate, we're done.
if cert1.getFingerprint() in rootFingerprints:
return True
c1 = cryptlib_py.cryptImportCert(cert1.writeBytes(),
cryptlib_py.CRYPT_UNUSED)
c2 = cryptlib_py.cryptImportCert(cert2.writeBytes(),
cryptlib_py.CRYPT_UNUSED)
try:
cryptlib_py.cryptCheckCert(c1, c2)
except:
return False
cryptlib_py.cryptDestroyCert(c1)
c1 = None
cryptlib_py.cryptDestroyCert(c2)
c2 = None
#If the last certificate is one of the root certificates, we're
#done.
if self.x509List[-1].getFingerprint() in rootFingerprints:
return True
#Otherwise, find a root certificate that the last certificate
#chains to, and validate them.
lastC = cryptlib_py.cryptImportCert(self.x509List[-1].writeBytes(),
cryptlib_py.CRYPT_UNUSED)
for rootCert in x509TrustList:
rootC = cryptlib_py.cryptImportCert(rootCert.writeBytes(),
cryptlib_py.CRYPT_UNUSED)
if self._checkChaining(lastC, rootC):
try:
cryptlib_py.cryptCheckCert(lastC, rootC)
return True
except:
return False
return False
finally:
if not (c1 is None):
cryptlib_py.cryptDestroyCert(c1)
if not (c2 is None):
cryptlib_py.cryptDestroyCert(c2)
if not (lastC is None):
cryptlib_py.cryptDestroyCert(lastC)
if not (rootC is None):
cryptlib_py.cryptDestroyCert(rootC)
def _checkChaining(self, lastC, rootC):
import cryptlib_py
import array
def compareNames(name):
try:
length = cryptlib_py.cryptGetAttributeString(lastC, name, None)
lastName = array.array('B', [0] * length)
cryptlib_py.cryptGetAttributeString(lastC, name, lastName)
lastName = lastName.tostring()
except cryptlib_py.CryptException, e:
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
lastName = None
try:
length = cryptlib_py.cryptGetAttributeString(rootC, name, None)
rootName = array.array('B', [0] * length)
cryptlib_py.cryptGetAttributeString(rootC, name, rootName)
rootName = rootName.tostring()
except cryptlib_py.CryptException, e:
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
rootName = None
return lastName == rootName
cryptlib_py.cryptSetAttribute(lastC,
cryptlib_py.CRYPT_CERTINFO_ISSUERNAME,
cryptlib_py.CRYPT_UNUSED)
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COUNTRYNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_LOCALITYNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONALUNITNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COMMONNAME):
return False
"""Class representing an X.509 certificate chain."""
from utils import cryptomath
class X509CertChain:
"""This class represents a chain of X.509 certificates.
@type x509List: list
@ivar x509List: A list of L{tlslite.X509.X509} instances,
starting with the end-entity certificate and with every
subsequent certificate certifying the previous.
"""
def __init__(self, x509List=None):
"""Create a new X509CertChain.
@type x509List: list
@param x509List: A list of L{tlslite.X509.X509} instances,
starting with the end-entity certificate and with every
subsequent certificate certifying the previous.
"""
if x509List:
self.x509List = x509List
else:
self.x509List = []
def getNumCerts(self):
"""Get the number of certificates in this chain.
@rtype: int
"""
return len(self.x509List)
def getEndEntityPublicKey(self):
"""Get the public key from the end-entity certificate.
@rtype: L{tlslite.utils.RSAKey.RSAKey}
"""
if self.getNumCerts() == 0:
raise AssertionError()
return self.x509List[0].publicKey
def getFingerprint(self):
"""Get the hex-encoded fingerprint of the end-entity certificate.
@rtype: str
@return: A hex-encoded fingerprint.
"""
if self.getNumCerts() == 0:
raise AssertionError()
return self.x509List[0].getFingerprint()
def getCommonName(self):
"""Get the Subject's Common Name from the end-entity certificate.
The cryptlib_py module must be installed in order to use this
function.
@rtype: str or None
@return: The CN component of the certificate's subject DN, if
present.
"""
if self.getNumCerts() == 0:
raise AssertionError()
return self.x509List[0].getCommonName()
def validate(self, x509TrustList):
"""Check the validity of the certificate chain.
This checks that every certificate in the chain validates with
the subsequent one, until some certificate validates with (or
is identical to) one of the passed-in root certificates.
The cryptlib_py module must be installed in order to use this
function.
@type x509TrustList: list of L{tlslite.X509.X509}
@param x509TrustList: A list of trusted root certificates. The
certificate chain must extend to one of these certificates to
be considered valid.
"""
import cryptlib_py
c1 = None
c2 = None
lastC = None
rootC = None
try:
rootFingerprints = [c.getFingerprint() for c in x509TrustList]
#Check that every certificate in the chain validates with the
#next one
for cert1, cert2 in zip(self.x509List, self.x509List[1:]):
#If we come upon a root certificate, we're done.
if cert1.getFingerprint() in rootFingerprints:
return True
c1 = cryptlib_py.cryptImportCert(cert1.writeBytes(),
cryptlib_py.CRYPT_UNUSED)
c2 = cryptlib_py.cryptImportCert(cert2.writeBytes(),
cryptlib_py.CRYPT_UNUSED)
try:
cryptlib_py.cryptCheckCert(c1, c2)
except:
return False
cryptlib_py.cryptDestroyCert(c1)
c1 = None
cryptlib_py.cryptDestroyCert(c2)
c2 = None
#If the last certificate is one of the root certificates, we're
#done.
if self.x509List[-1].getFingerprint() in rootFingerprints:
return True
#Otherwise, find a root certificate that the last certificate
#chains to, and validate them.
lastC = cryptlib_py.cryptImportCert(self.x509List[-1].writeBytes(),
cryptlib_py.CRYPT_UNUSED)
for rootCert in x509TrustList:
rootC = cryptlib_py.cryptImportCert(rootCert.writeBytes(),
cryptlib_py.CRYPT_UNUSED)
if self._checkChaining(lastC, rootC):
try:
cryptlib_py.cryptCheckCert(lastC, rootC)
return True
except:
return False
return False
finally:
if not (c1 is None):
cryptlib_py.cryptDestroyCert(c1)
if not (c2 is None):
cryptlib_py.cryptDestroyCert(c2)
if not (lastC is None):
cryptlib_py.cryptDestroyCert(lastC)
if not (rootC is None):
cryptlib_py.cryptDestroyCert(rootC)
def _checkChaining(self, lastC, rootC):
import cryptlib_py
import array
def compareNames(name):
try:
length = cryptlib_py.cryptGetAttributeString(lastC, name, None)
lastName = array.array('B', [0] * length)
cryptlib_py.cryptGetAttributeString(lastC, name, lastName)
lastName = lastName.tostring()
except cryptlib_py.CryptException, e:
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
lastName = None
try:
length = cryptlib_py.cryptGetAttributeString(rootC, name, None)
rootName = array.array('B', [0] * length)
cryptlib_py.cryptGetAttributeString(rootC, name, rootName)
rootName = rootName.tostring()
except cryptlib_py.CryptException, e:
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
rootName = None
return lastName == rootName
cryptlib_py.cryptSetAttribute(lastC,
cryptlib_py.CRYPT_CERTINFO_ISSUERNAME,
cryptlib_py.CRYPT_UNUSED)
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COUNTRYNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_LOCALITYNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONALUNITNAME):
return False
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COMMONNAME):
return False
return True

View File

@ -1,235 +1,235 @@
"""
A state machine for using TLS Lite with asynchronous I/O.
"""
class AsyncStateMachine:
"""
This is an abstract class that's used to integrate TLS Lite with
asyncore and Twisted.
This class signals wantsReadsEvent() and wantsWriteEvent(). When
the underlying socket has become readable or writeable, the event
should be passed to this class by calling inReadEvent() or
inWriteEvent(). This class will then try to read or write through
the socket, and will update its state appropriately.
This class will forward higher-level events to its subclass. For
example, when a complete TLS record has been received,
outReadEvent() will be called with the decrypted data.
"""
def __init__(self):
self._clear()
def _clear(self):
#These store the various asynchronous operations (i.e.
#generators). Only one of them, at most, is ever active at a
#time.
self.handshaker = None
self.closer = None
self.reader = None
self.writer = None
#This stores the result from the last call to the
#currently active operation. If 0 it indicates that the
#operation wants to read, if 1 it indicates that the
#operation wants to write. If None, there is no active
#operation.
self.result = None
def _checkAssert(self, maxActive=1):
#This checks that only one operation, at most, is
#active, and that self.result is set appropriately.
activeOps = 0
if self.handshaker:
activeOps += 1
if self.closer:
activeOps += 1
if self.reader:
activeOps += 1
if self.writer:
activeOps += 1
if self.result == None:
if activeOps != 0:
raise AssertionError()
elif self.result in (0,1):
if activeOps != 1:
raise AssertionError()
else:
raise AssertionError()
if activeOps > maxActive:
raise AssertionError()
def wantsReadEvent(self):
"""If the state machine wants to read.
If an operation is active, this returns whether or not the
operation wants to read from the socket. If an operation is
not active, this returns None.
@rtype: bool or None
@return: If the state machine wants to read.
"""
if self.result != None:
return self.result == 0
return None
def wantsWriteEvent(self):
"""If the state machine wants to write.
If an operation is active, this returns whether or not the
operation wants to write to the socket. If an operation is
not active, this returns None.
@rtype: bool or None
@return: If the state machine wants to write.
"""
if self.result != None:
return self.result == 1
return None
def outConnectEvent(self):
"""Called when a handshake operation completes.
May be overridden in subclass.
"""
pass
def outCloseEvent(self):
"""Called when a close operation completes.
May be overridden in subclass.
"""
pass
def outReadEvent(self, readBuffer):
"""Called when a read operation completes.
May be overridden in subclass."""
pass
def outWriteEvent(self):
"""Called when a write operation completes.
May be overridden in subclass."""
pass
def inReadEvent(self):
"""Tell the state machine it can read from the socket."""
try:
self._checkAssert()
if self.handshaker:
self._doHandshakeOp()
elif self.closer:
self._doCloseOp()
elif self.reader:
self._doReadOp()
elif self.writer:
self._doWriteOp()
else:
self.reader = self.tlsConnection.readAsync(16384)
self._doReadOp()
except:
self._clear()
raise
def inWriteEvent(self):
"""Tell the state machine it can write to the socket."""
try:
self._checkAssert()
if self.handshaker:
self._doHandshakeOp()
elif self.closer:
self._doCloseOp()
elif self.reader:
self._doReadOp()
elif self.writer:
self._doWriteOp()
else:
self.outWriteEvent()
except:
self._clear()
raise
def _doHandshakeOp(self):
try:
self.result = self.handshaker.next()
except StopIteration:
self.handshaker = None
self.result = None
self.outConnectEvent()
def _doCloseOp(self):
try:
self.result = self.closer.next()
except StopIteration:
self.closer = None
self.result = None
self.outCloseEvent()
def _doReadOp(self):
self.result = self.reader.next()
if not self.result in (0,1):
readBuffer = self.result
self.reader = None
self.result = None
self.outReadEvent(readBuffer)
def _doWriteOp(self):
try:
self.result = self.writer.next()
except StopIteration:
self.writer = None
self.result = None
def setHandshakeOp(self, handshaker):
"""Start a handshake operation.
@type handshaker: generator
@param handshaker: A generator created by using one of the
asynchronous handshake functions (i.e. handshakeServerAsync, or
handshakeClientxxx(..., async=True).
"""
try:
self._checkAssert(0)
self.handshaker = handshaker
self._doHandshakeOp()
except:
self._clear()
raise
def setServerHandshakeOp(self, **args):
"""Start a handshake operation.
The arguments passed to this function will be forwarded to
L{tlslite.TLSConnection.TLSConnection.handshakeServerAsync}.
"""
handshaker = self.tlsConnection.handshakeServerAsync(**args)
self.setHandshakeOp(handshaker)
def setCloseOp(self):
"""Start a close operation.
"""
try:
self._checkAssert(0)
self.closer = self.tlsConnection.closeAsync()
self._doCloseOp()
except:
self._clear()
raise
def setWriteOp(self, writeBuffer):
"""Start a write operation.
@type writeBuffer: str
@param writeBuffer: The string to transmit.
"""
try:
self._checkAssert(0)
self.writer = self.tlsConnection.writeAsync(writeBuffer)
self._doWriteOp()
except:
self._clear()
raise
"""
A state machine for using TLS Lite with asynchronous I/O.
"""
class AsyncStateMachine:
"""
This is an abstract class that's used to integrate TLS Lite with
asyncore and Twisted.
This class signals wantsReadsEvent() and wantsWriteEvent(). When
the underlying socket has become readable or writeable, the event
should be passed to this class by calling inReadEvent() or
inWriteEvent(). This class will then try to read or write through
the socket, and will update its state appropriately.
This class will forward higher-level events to its subclass. For
example, when a complete TLS record has been received,
outReadEvent() will be called with the decrypted data.
"""
def __init__(self):
self._clear()
def _clear(self):
#These store the various asynchronous operations (i.e.
#generators). Only one of them, at most, is ever active at a
#time.
self.handshaker = None
self.closer = None
self.reader = None
self.writer = None
#This stores the result from the last call to the
#currently active operation. If 0 it indicates that the
#operation wants to read, if 1 it indicates that the
#operation wants to write. If None, there is no active
#operation.
self.result = None
def _checkAssert(self, maxActive=1):
#This checks that only one operation, at most, is
#active, and that self.result is set appropriately.
activeOps = 0
if self.handshaker:
activeOps += 1
if self.closer:
activeOps += 1
if self.reader:
activeOps += 1
if self.writer:
activeOps += 1
if self.result == None:
if activeOps != 0:
raise AssertionError()
elif self.result in (0,1):
if activeOps != 1:
raise AssertionError()
else:
raise AssertionError()
if activeOps > maxActive:
raise AssertionError()
def wantsReadEvent(self):
"""If the state machine wants to read.
If an operation is active, this returns whether or not the
operation wants to read from the socket. If an operation is
not active, this returns None.
@rtype: bool or None
@return: If the state machine wants to read.
"""
if self.result != None:
return self.result == 0
return None
def wantsWriteEvent(self):
"""If the state machine wants to write.
If an operation is active, this returns whether or not the
operation wants to write to the socket. If an operation is
not active, this returns None.
@rtype: bool or None
@return: If the state machine wants to write.
"""
if self.result != None:
return self.result == 1
return None
def outConnectEvent(self):
"""Called when a handshake operation completes.
May be overridden in subclass.
"""
pass
def outCloseEvent(self):
"""Called when a close operation completes.
May be overridden in subclass.
"""
pass
def outReadEvent(self, readBuffer):
"""Called when a read operation completes.
May be overridden in subclass."""
pass
def outWriteEvent(self):
"""Called when a write operation completes.
May be overridden in subclass."""
pass
def inReadEvent(self):
"""Tell the state machine it can read from the socket."""
try:
self._checkAssert()
if self.handshaker:
self._doHandshakeOp()
elif self.closer:
self._doCloseOp()
elif self.reader:
self._doReadOp()
elif self.writer:
self._doWriteOp()
else:
self.reader = self.tlsConnection.readAsync(16384)
self._doReadOp()
except:
self._clear()
raise
def inWriteEvent(self):
"""Tell the state machine it can write to the socket."""
try:
self._checkAssert()
if self.handshaker:
self._doHandshakeOp()
elif self.closer:
self._doCloseOp()
elif self.reader:
self._doReadOp()
elif self.writer:
self._doWriteOp()
else:
self.outWriteEvent()
except:
self._clear()
raise
def _doHandshakeOp(self):
try:
self.result = self.handshaker.next()
except StopIteration:
self.handshaker = None
self.result = None
self.outConnectEvent()
def _doCloseOp(self):
try:
self.result = self.closer.next()
except StopIteration:
self.closer = None
self.result = None
self.outCloseEvent()
def _doReadOp(self):
self.result = self.reader.next()
if not self.result in (0,1):
readBuffer = self.result
self.reader = None
self.result = None
self.outReadEvent(readBuffer)
def _doWriteOp(self):
try:
self.result = self.writer.next()
except StopIteration:
self.writer = None
self.result = None
def setHandshakeOp(self, handshaker):
"""Start a handshake operation.
@type handshaker: generator
@param handshaker: A generator created by using one of the
asynchronous handshake functions (i.e. handshakeServerAsync, or
handshakeClientxxx(..., async=True).
"""
try:
self._checkAssert(0)
self.handshaker = handshaker
self._doHandshakeOp()
except:
self._clear()
raise
def setServerHandshakeOp(self, **args):
"""Start a handshake operation.
The arguments passed to this function will be forwarded to
L{tlslite.TLSConnection.TLSConnection.handshakeServerAsync}.
"""
handshaker = self.tlsConnection.handshakeServerAsync(**args)
self.setHandshakeOp(handshaker)
def setCloseOp(self):
"""Start a close operation.
"""
try:
self._checkAssert(0)
self.closer = self.tlsConnection.closeAsync()
self._doCloseOp()
except:
self._clear()
raise
def setWriteOp(self, writeBuffer):
"""Start a write operation.
@type writeBuffer: str
@param writeBuffer: The string to transmit.
"""
try:
self._checkAssert(0)
self.writer = self.tlsConnection.writeAsync(writeBuffer)
self._doWriteOp()
except:
self._clear()
raise

View File

@ -1,163 +1,163 @@
"""
A helper class for using TLS Lite with stdlib clients
(httplib, xmlrpclib, imaplib, poplib).
"""
from gdata.tlslite.Checker import Checker
class ClientHelper:
"""This is a helper class used to integrate TLS Lite with various
TLS clients (e.g. poplib, smtplib, httplib, etc.)"""
def __init__(self,
username=None, password=None, sharedKey=None,
certChain=None, privateKey=None,
cryptoID=None, protocol=None,
x509Fingerprint=None,
x509TrustList=None, x509CommonName=None,
settings = None):
"""
For client authentication, use one of these argument
combinations:
- username, password (SRP)
- username, sharedKey (shared-key)
- certChain, privateKey (certificate)
For server authentication, you can either rely on the
implicit mutual authentication performed by SRP or
shared-keys, or you can do certificate-based server
authentication with one of these argument combinations:
- cryptoID[, protocol] (requires cryptoIDlib)
- x509Fingerprint
- x509TrustList[, x509CommonName] (requires cryptlib_py)
Certificate-based server authentication is compatible with
SRP or certificate-based client authentication. It is
not compatible with shared-keys.
The constructor does not perform the TLS handshake itself, but
simply stores these arguments for later. The handshake is
performed only when this class needs to connect with the
server. Then you should be prepared to handle TLS-specific
exceptions. See the client handshake functions in
L{tlslite.TLSConnection.TLSConnection} for details on which
exceptions might be raised.
@type username: str
@param username: SRP or shared-key username. Requires the
'password' or 'sharedKey' argument.
@type password: str
@param password: SRP password for mutual authentication.
Requires the 'username' argument.
@type sharedKey: str
@param sharedKey: Shared key for mutual authentication.
Requires the 'username' argument.
@type certChain: L{tlslite.X509CertChain.X509CertChain} or
L{cryptoIDlib.CertChain.CertChain}
@param certChain: Certificate chain for client authentication.
Requires the 'privateKey' argument. Excludes the SRP or
shared-key related arguments.
@type privateKey: L{tlslite.utils.RSAKey.RSAKey}
@param privateKey: Private key for client authentication.
Requires the 'certChain' argument. Excludes the SRP or
shared-key related arguments.
@type cryptoID: str
@param cryptoID: cryptoID for server authentication. Mutually
exclusive with the 'x509...' arguments.
@type protocol: str
@param protocol: cryptoID protocol URI for server
authentication. Requires the 'cryptoID' argument.
@type x509Fingerprint: str
@param x509Fingerprint: Hex-encoded X.509 fingerprint for
server authentication. Mutually exclusive with the 'cryptoID'
and 'x509TrustList' arguments.
@type x509TrustList: list of L{tlslite.X509.X509}
@param x509TrustList: A list of trusted root certificates. The
other party must present a certificate chain which extends to
one of these root certificates. The cryptlib_py module must be
installed to use this parameter. Mutually exclusive with the
'cryptoID' and 'x509Fingerprint' arguments.
@type x509CommonName: str
@param x509CommonName: The end-entity certificate's 'CN' field
must match this value. For a web server, this is typically a
server name such as 'www.amazon.com'. Mutually exclusive with
the 'cryptoID' and 'x509Fingerprint' arguments. Requires the
'x509TrustList' argument.
@type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
@param settings: Various settings which can be used to control
the ciphersuites, certificate types, and SSL/TLS versions
offered by the client.
"""
self.username = None
self.password = None
self.sharedKey = None
self.certChain = None
self.privateKey = None
self.checker = None
#SRP Authentication
if username and password and not \
(sharedKey or certChain or privateKey):
self.username = username
self.password = password
#Shared Key Authentication
elif username and sharedKey and not \
(password or certChain or privateKey):
self.username = username
self.sharedKey = sharedKey
#Certificate Chain Authentication
elif certChain and privateKey and not \
(username or password or sharedKey):
self.certChain = certChain
self.privateKey = privateKey
#No Authentication
elif not password and not username and not \
sharedKey and not certChain and not privateKey:
pass
else:
raise ValueError("Bad parameters")
#Authenticate the server based on its cryptoID or fingerprint
if sharedKey and (cryptoID or protocol or x509Fingerprint):
raise ValueError("Can't use shared keys with other forms of"\
"authentication")
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
x509TrustList, x509CommonName)
self.settings = settings
self.tlsSession = None
def _handshake(self, tlsConnection):
if self.username and self.password:
tlsConnection.handshakeClientSRP(username=self.username,
password=self.password,
checker=self.checker,
settings=self.settings,
session=self.tlsSession)
elif self.username and self.sharedKey:
tlsConnection.handshakeClientSharedKey(username=self.username,
sharedKey=self.sharedKey,
settings=self.settings)
else:
tlsConnection.handshakeClientCert(certChain=self.certChain,
privateKey=self.privateKey,
checker=self.checker,
settings=self.settings,
session=self.tlsSession)
self.tlsSession = tlsConnection.session
"""
A helper class for using TLS Lite with stdlib clients
(httplib, xmlrpclib, imaplib, poplib).
"""
from gdata.tlslite.Checker import Checker
class ClientHelper:
"""This is a helper class used to integrate TLS Lite with various
TLS clients (e.g. poplib, smtplib, httplib, etc.)"""
def __init__(self,
username=None, password=None, sharedKey=None,
certChain=None, privateKey=None,
cryptoID=None, protocol=None,
x509Fingerprint=None,
x509TrustList=None, x509CommonName=None,
settings = None):
"""
For client authentication, use one of these argument
combinations:
- username, password (SRP)
- username, sharedKey (shared-key)
- certChain, privateKey (certificate)
For server authentication, you can either rely on the
implicit mutual authentication performed by SRP or
shared-keys, or you can do certificate-based server
authentication with one of these argument combinations:
- cryptoID[, protocol] (requires cryptoIDlib)
- x509Fingerprint
- x509TrustList[, x509CommonName] (requires cryptlib_py)
Certificate-based server authentication is compatible with
SRP or certificate-based client authentication. It is
not compatible with shared-keys.
The constructor does not perform the TLS handshake itself, but
simply stores these arguments for later. The handshake is
performed only when this class needs to connect with the
server. Then you should be prepared to handle TLS-specific
exceptions. See the client handshake functions in
L{tlslite.TLSConnection.TLSConnection} for details on which
exceptions might be raised.
@type username: str
@param username: SRP or shared-key username. Requires the
'password' or 'sharedKey' argument.
@type password: str
@param password: SRP password for mutual authentication.
Requires the 'username' argument.
@type sharedKey: str
@param sharedKey: Shared key for mutual authentication.
Requires the 'username' argument.
@type certChain: L{tlslite.X509CertChain.X509CertChain} or
L{cryptoIDlib.CertChain.CertChain}
@param certChain: Certificate chain for client authentication.
Requires the 'privateKey' argument. Excludes the SRP or
shared-key related arguments.
@type privateKey: L{tlslite.utils.RSAKey.RSAKey}
@param privateKey: Private key for client authentication.
Requires the 'certChain' argument. Excludes the SRP or
shared-key related arguments.
@type cryptoID: str
@param cryptoID: cryptoID for server authentication. Mutually
exclusive with the 'x509...' arguments.
@type protocol: str
@param protocol: cryptoID protocol URI for server
authentication. Requires the 'cryptoID' argument.
@type x509Fingerprint: str
@param x509Fingerprint: Hex-encoded X.509 fingerprint for
server authentication. Mutually exclusive with the 'cryptoID'
and 'x509TrustList' arguments.
@type x509TrustList: list of L{tlslite.X509.X509}
@param x509TrustList: A list of trusted root certificates. The
other party must present a certificate chain which extends to
one of these root certificates. The cryptlib_py module must be
installed to use this parameter. Mutually exclusive with the
'cryptoID' and 'x509Fingerprint' arguments.
@type x509CommonName: str
@param x509CommonName: The end-entity certificate's 'CN' field
must match this value. For a web server, this is typically a
server name such as 'www.amazon.com'. Mutually exclusive with
the 'cryptoID' and 'x509Fingerprint' arguments. Requires the
'x509TrustList' argument.
@type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
@param settings: Various settings which can be used to control
the ciphersuites, certificate types, and SSL/TLS versions
offered by the client.
"""
self.username = None
self.password = None
self.sharedKey = None
self.certChain = None
self.privateKey = None
self.checker = None
#SRP Authentication
if username and password and not \
(sharedKey or certChain or privateKey):
self.username = username
self.password = password
#Shared Key Authentication
elif username and sharedKey and not \
(password or certChain or privateKey):
self.username = username
self.sharedKey = sharedKey
#Certificate Chain Authentication
elif certChain and privateKey and not \
(username or password or sharedKey):
self.certChain = certChain
self.privateKey = privateKey
#No Authentication
elif not password and not username and not \
sharedKey and not certChain and not privateKey:
pass
else:
raise ValueError("Bad parameters")
#Authenticate the server based on its cryptoID or fingerprint
if sharedKey and (cryptoID or protocol or x509Fingerprint):
raise ValueError("Can't use shared keys with other forms of"\
"authentication")
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
x509TrustList, x509CommonName)
self.settings = settings
self.tlsSession = None
def _handshake(self, tlsConnection):
if self.username and self.password:
tlsConnection.handshakeClientSRP(username=self.username,
password=self.password,
checker=self.checker,
settings=self.settings,
session=self.tlsSession)
elif self.username and self.sharedKey:
tlsConnection.handshakeClientSharedKey(username=self.username,
sharedKey=self.sharedKey,
settings=self.settings)
else:
tlsConnection.handshakeClientCert(certChain=self.certChain,
privateKey=self.privateKey,
checker=self.checker,
settings=self.settings,
session=self.tlsSession)
self.tlsSession = tlsConnection.session

View File

@ -1,52 +1,52 @@
class IntegrationHelper:
def __init__(self,
username=None, password=None, sharedKey=None,
certChain=None, privateKey=None,
cryptoID=None, protocol=None,
x509Fingerprint=None,
x509TrustList=None, x509CommonName=None,
settings = None):
self.username = None
self.password = None
self.sharedKey = None
self.certChain = None
self.privateKey = None
self.checker = None
#SRP Authentication
if username and password and not \
(sharedKey or certChain or privateKey):
self.username = username
self.password = password
#Shared Key Authentication
elif username and sharedKey and not \
(password or certChain or privateKey):
self.username = username
self.sharedKey = sharedKey
#Certificate Chain Authentication
elif certChain and privateKey and not \
(username or password or sharedKey):
self.certChain = certChain
self.privateKey = privateKey
#No Authentication
elif not password and not username and not \
sharedKey and not certChain and not privateKey:
pass
else:
raise ValueError("Bad parameters")
#Authenticate the server based on its cryptoID or fingerprint
if sharedKey and (cryptoID or protocol or x509Fingerprint):
raise ValueError("Can't use shared keys with other forms of"\
"authentication")
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
x509TrustList, x509CommonName)
class IntegrationHelper:
def __init__(self,
username=None, password=None, sharedKey=None,
certChain=None, privateKey=None,
cryptoID=None, protocol=None,
x509Fingerprint=None,
x509TrustList=None, x509CommonName=None,
settings = None):
self.username = None
self.password = None
self.sharedKey = None
self.certChain = None
self.privateKey = None
self.checker = None
#SRP Authentication
if username and password and not \
(sharedKey or certChain or privateKey):
self.username = username
self.password = password
#Shared Key Authentication
elif username and sharedKey and not \
(password or certChain or privateKey):
self.username = username
self.sharedKey = sharedKey
#Certificate Chain Authentication
elif certChain and privateKey and not \
(username or password or sharedKey):
self.certChain = certChain
self.privateKey = privateKey
#No Authentication
elif not password and not username and not \
sharedKey and not certChain and not privateKey:
pass
else:
raise ValueError("Bad parameters")
#Authenticate the server based on its cryptoID or fingerprint
if sharedKey and (cryptoID or protocol or x509Fingerprint):
raise ValueError("Can't use shared keys with other forms of"\
"authentication")
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
x509TrustList, x509CommonName)
self.settings = settings

View File

@ -1,139 +1,139 @@
"""TLS Lite + asyncore."""
import asyncore
from gdata.tlslite.TLSConnection import TLSConnection
from AsyncStateMachine import AsyncStateMachine
class TLSAsyncDispatcherMixIn(AsyncStateMachine):
"""This class can be "mixed in" with an
L{asyncore.dispatcher} to add TLS support.
This class essentially sits between the dispatcher and the select
loop, intercepting events and only calling the dispatcher when
applicable.
In the case of handle_read(), a read operation will be activated,
and when it completes, the bytes will be placed in a buffer where
the dispatcher can retrieve them by calling recv(), and the
dispatcher's handle_read() will be called.
In the case of handle_write(), the dispatcher's handle_write() will
be called, and when it calls send(), a write operation will be
activated.
To use this class, you must combine it with an asyncore.dispatcher,
and pass in a handshake operation with setServerHandshakeOp().
Below is an example of using this class with medusa. This class is
mixed in with http_channel to create http_tls_channel. Note:
1. the mix-in is listed first in the inheritance list
2. the input buffer size must be at least 16K, otherwise the
dispatcher might not read all the bytes from the TLS layer,
leaving some bytes in limbo.
3. IE seems to have a problem receiving a whole HTTP response in a
single TLS record, so HTML pages containing '\\r\\n\\r\\n' won't
be displayed on IE.
Add the following text into 'start_medusa.py', in the 'HTTP Server'
section::
from tlslite.api import *
s = open("./serverX509Cert.pem").read()
x509 = X509()
x509.parse(s)
certChain = X509CertChain([x509])
s = open("./serverX509Key.pem").read()
privateKey = parsePEMKey(s, private=True)
class http_tls_channel(TLSAsyncDispatcherMixIn,
http_server.http_channel):
ac_in_buffer_size = 16384
def __init__ (self, server, conn, addr):
http_server.http_channel.__init__(self, server, conn, addr)
TLSAsyncDispatcherMixIn.__init__(self, conn)
self.tlsConnection.ignoreAbruptClose = True
self.setServerHandshakeOp(certChain=certChain,
privateKey=privateKey)
hs.channel_class = http_tls_channel
If the TLS layer raises an exception, the exception will be caught
in asyncore.dispatcher, which will call close() on this class. The
TLS layer always closes the TLS connection before raising an
exception, so the close operation will complete right away, causing
asyncore.dispatcher.close() to be called, which closes the socket
and removes this instance from the asyncore loop.
"""
def __init__(self, sock=None):
AsyncStateMachine.__init__(self)
if sock:
self.tlsConnection = TLSConnection(sock)
#Calculate the sibling I'm being mixed in with.
#This is necessary since we override functions
#like readable(), handle_read(), etc., but we
#also want to call the sibling's versions.
for cl in self.__class__.__bases__:
if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine:
self.siblingClass = cl
break
else:
raise AssertionError()
def readable(self):
result = self.wantsReadEvent()
if result != None:
return result
return self.siblingClass.readable(self)
def writable(self):
result = self.wantsWriteEvent()
if result != None:
return result
return self.siblingClass.writable(self)
def handle_read(self):
self.inReadEvent()
def handle_write(self):
self.inWriteEvent()
def outConnectEvent(self):
self.siblingClass.handle_connect(self)
def outCloseEvent(self):
asyncore.dispatcher.close(self)
def outReadEvent(self, readBuffer):
self.readBuffer = readBuffer
self.siblingClass.handle_read(self)
def outWriteEvent(self):
self.siblingClass.handle_write(self)
def recv(self, bufferSize=16384):
if bufferSize < 16384 or self.readBuffer == None:
raise AssertionError()
returnValue = self.readBuffer
self.readBuffer = None
return returnValue
def send(self, writeBuffer):
self.setWriteOp(writeBuffer)
return len(writeBuffer)
def close(self):
if hasattr(self, "tlsConnection"):
self.setCloseOp()
else:
asyncore.dispatcher.close(self)
"""TLS Lite + asyncore."""
import asyncore
from gdata.tlslite.TLSConnection import TLSConnection
from AsyncStateMachine import AsyncStateMachine
class TLSAsyncDispatcherMixIn(AsyncStateMachine):
"""This class can be "mixed in" with an
L{asyncore.dispatcher} to add TLS support.
This class essentially sits between the dispatcher and the select
loop, intercepting events and only calling the dispatcher when
applicable.
In the case of handle_read(), a read operation will be activated,
and when it completes, the bytes will be placed in a buffer where
the dispatcher can retrieve them by calling recv(), and the
dispatcher's handle_read() will be called.
In the case of handle_write(), the dispatcher's handle_write() will
be called, and when it calls send(), a write operation will be
activated.
To use this class, you must combine it with an asyncore.dispatcher,
and pass in a handshake operation with setServerHandshakeOp().
Below is an example of using this class with medusa. This class is
mixed in with http_channel to create http_tls_channel. Note:
1. the mix-in is listed first in the inheritance list
2. the input buffer size must be at least 16K, otherwise the
dispatcher might not read all the bytes from the TLS layer,
leaving some bytes in limbo.
3. IE seems to have a problem receiving a whole HTTP response in a
single TLS record, so HTML pages containing '\\r\\n\\r\\n' won't
be displayed on IE.
Add the following text into 'start_medusa.py', in the 'HTTP Server'
section::
from tlslite.api import *
s = open("./serverX509Cert.pem").read()
x509 = X509()
x509.parse(s)
certChain = X509CertChain([x509])
s = open("./serverX509Key.pem").read()
privateKey = parsePEMKey(s, private=True)
class http_tls_channel(TLSAsyncDispatcherMixIn,
http_server.http_channel):
ac_in_buffer_size = 16384
def __init__ (self, server, conn, addr):
http_server.http_channel.__init__(self, server, conn, addr)
TLSAsyncDispatcherMixIn.__init__(self, conn)
self.tlsConnection.ignoreAbruptClose = True
self.setServerHandshakeOp(certChain=certChain,
privateKey=privateKey)
hs.channel_class = http_tls_channel
If the TLS layer raises an exception, the exception will be caught
in asyncore.dispatcher, which will call close() on this class. The
TLS layer always closes the TLS connection before raising an
exception, so the close operation will complete right away, causing
asyncore.dispatcher.close() to be called, which closes the socket
and removes this instance from the asyncore loop.
"""
def __init__(self, sock=None):
AsyncStateMachine.__init__(self)
if sock:
self.tlsConnection = TLSConnection(sock)
#Calculate the sibling I'm being mixed in with.
#This is necessary since we override functions
#like readable(), handle_read(), etc., but we
#also want to call the sibling's versions.
for cl in self.__class__.__bases__:
if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine:
self.siblingClass = cl
break
else:
raise AssertionError()
def readable(self):
result = self.wantsReadEvent()
if result != None:
return result
return self.siblingClass.readable(self)
def writable(self):
result = self.wantsWriteEvent()
if result != None:
return result
return self.siblingClass.writable(self)
def handle_read(self):
self.inReadEvent()
def handle_write(self):
self.inWriteEvent()
def outConnectEvent(self):
self.siblingClass.handle_connect(self)
def outCloseEvent(self):
asyncore.dispatcher.close(self)
def outReadEvent(self, readBuffer):
self.readBuffer = readBuffer
self.siblingClass.handle_read(self)
def outWriteEvent(self):
self.siblingClass.handle_write(self)
def recv(self, bufferSize=16384):
if bufferSize < 16384 or self.readBuffer == None:
raise AssertionError()
returnValue = self.readBuffer
self.readBuffer = None
return returnValue
def send(self, writeBuffer):
self.setWriteOp(writeBuffer)
return len(writeBuffer)
def close(self):
if hasattr(self, "tlsConnection"):
self.setCloseOp()
else:
asyncore.dispatcher.close(self)

View File

@ -1,196 +1,196 @@
"""TLS Lite + Twisted."""
from twisted.protocols.policies import ProtocolWrapper, WrappingFactory
from twisted.python.failure import Failure
from AsyncStateMachine import AsyncStateMachine
from gdata.tlslite.TLSConnection import TLSConnection
from gdata.tlslite.errors import *
import socket
import errno
#The TLSConnection is created around a "fake socket" that
#plugs it into the underlying Twisted transport
class _FakeSocket:
def __init__(self, wrapper):
self.wrapper = wrapper
self.data = ""
def send(self, data):
ProtocolWrapper.write(self.wrapper, data)
return len(data)
def recv(self, numBytes):
if self.data == "":
raise socket.error, (errno.EWOULDBLOCK, "")
returnData = self.data[:numBytes]
self.data = self.data[numBytes:]
return returnData
class TLSTwistedProtocolWrapper(ProtocolWrapper, AsyncStateMachine):
"""This class can wrap Twisted protocols to add TLS support.
Below is a complete example of using TLS Lite with a Twisted echo
server.
There are two server implementations below. Echo is the original
protocol, which is oblivious to TLS. Echo1 subclasses Echo and
negotiates TLS when the client connects. Echo2 subclasses Echo and
negotiates TLS when the client sends "STARTTLS"::
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
from twisted.protocols.policies import WrappingFactory
from twisted.protocols.basic import LineReceiver
from twisted.python import log
from twisted.python.failure import Failure
import sys
from tlslite.api import *
s = open("./serverX509Cert.pem").read()
x509 = X509()
x509.parse(s)
certChain = X509CertChain([x509])
s = open("./serverX509Key.pem").read()
privateKey = parsePEMKey(s, private=True)
verifierDB = VerifierDB("verifierDB")
verifierDB.open()
class Echo(LineReceiver):
def connectionMade(self):
self.transport.write("Welcome to the echo server!\\r\\n")
def lineReceived(self, line):
self.transport.write(line + "\\r\\n")
class Echo1(Echo):
def connectionMade(self):
if not self.transport.tlsStarted:
self.transport.setServerHandshakeOp(certChain=certChain,
privateKey=privateKey,
verifierDB=verifierDB)
else:
Echo.connectionMade(self)
def connectionLost(self, reason):
pass #Handle any TLS exceptions here
class Echo2(Echo):
def lineReceived(self, data):
if data == "STARTTLS":
self.transport.setServerHandshakeOp(certChain=certChain,
privateKey=privateKey,
verifierDB=verifierDB)
else:
Echo.lineReceived(self, data)
def connectionLost(self, reason):
pass #Handle any TLS exceptions here
factory = Factory()
factory.protocol = Echo1
#factory.protocol = Echo2
wrappingFactory = WrappingFactory(factory)
wrappingFactory.protocol = TLSTwistedProtocolWrapper
log.startLogging(sys.stdout)
reactor.listenTCP(1079, wrappingFactory)
reactor.run()
This class works as follows:
Data comes in and is given to the AsyncStateMachine for handling.
AsyncStateMachine will forward events to this class, and we'll
pass them on to the ProtocolHandler, which will proxy them to the
wrapped protocol. The wrapped protocol may then call back into
this class, and these calls will be proxied into the
AsyncStateMachine.
The call graph looks like this:
- self.dataReceived
- AsyncStateMachine.inReadEvent
- self.out(Connect|Close|Read)Event
- ProtocolWrapper.(connectionMade|loseConnection|dataReceived)
- self.(loseConnection|write|writeSequence)
- AsyncStateMachine.(setCloseOp|setWriteOp)
"""
#WARNING: IF YOU COPY-AND-PASTE THE ABOVE CODE, BE SURE TO REMOVE
#THE EXTRA ESCAPING AROUND "\\r\\n"
def __init__(self, factory, wrappedProtocol):
ProtocolWrapper.__init__(self, factory, wrappedProtocol)
AsyncStateMachine.__init__(self)
self.fakeSocket = _FakeSocket(self)
self.tlsConnection = TLSConnection(self.fakeSocket)
self.tlsStarted = False
self.connectionLostCalled = False
def connectionMade(self):
try:
ProtocolWrapper.connectionMade(self)
except TLSError, e:
self.connectionLost(Failure(e))
ProtocolWrapper.loseConnection(self)
def dataReceived(self, data):
try:
if not self.tlsStarted:
ProtocolWrapper.dataReceived(self, data)
else:
self.fakeSocket.data += data
while self.fakeSocket.data:
AsyncStateMachine.inReadEvent(self)
except TLSError, e:
self.connectionLost(Failure(e))
ProtocolWrapper.loseConnection(self)
def connectionLost(self, reason):
if not self.connectionLostCalled:
ProtocolWrapper.connectionLost(self, reason)
self.connectionLostCalled = True
def outConnectEvent(self):
ProtocolWrapper.connectionMade(self)
def outCloseEvent(self):
ProtocolWrapper.loseConnection(self)
def outReadEvent(self, data):
if data == "":
ProtocolWrapper.loseConnection(self)
else:
ProtocolWrapper.dataReceived(self, data)
def setServerHandshakeOp(self, **args):
self.tlsStarted = True
AsyncStateMachine.setServerHandshakeOp(self, **args)
def loseConnection(self):
if not self.tlsStarted:
ProtocolWrapper.loseConnection(self)
else:
AsyncStateMachine.setCloseOp(self)
def write(self, data):
if not self.tlsStarted:
ProtocolWrapper.write(self, data)
else:
#Because of the FakeSocket, write operations are guaranteed to
#terminate immediately.
AsyncStateMachine.setWriteOp(self, data)
def writeSequence(self, seq):
if not self.tlsStarted:
ProtocolWrapper.writeSequence(self, seq)
else:
#Because of the FakeSocket, write operations are guaranteed to
#terminate immediately.
AsyncStateMachine.setWriteOp(self, "".join(seq))
"""TLS Lite + Twisted."""
from twisted.protocols.policies import ProtocolWrapper, WrappingFactory
from twisted.python.failure import Failure
from AsyncStateMachine import AsyncStateMachine
from gdata.tlslite.TLSConnection import TLSConnection
from gdata.tlslite.errors import *
import socket
import errno
#The TLSConnection is created around a "fake socket" that
#plugs it into the underlying Twisted transport
class _FakeSocket:
def __init__(self, wrapper):
self.wrapper = wrapper
self.data = ""
def send(self, data):
ProtocolWrapper.write(self.wrapper, data)
return len(data)
def recv(self, numBytes):
if self.data == "":
raise socket.error, (errno.EWOULDBLOCK, "")
returnData = self.data[:numBytes]
self.data = self.data[numBytes:]
return returnData
class TLSTwistedProtocolWrapper(ProtocolWrapper, AsyncStateMachine):
"""This class can wrap Twisted protocols to add TLS support.
Below is a complete example of using TLS Lite with a Twisted echo
server.
There are two server implementations below. Echo is the original
protocol, which is oblivious to TLS. Echo1 subclasses Echo and
negotiates TLS when the client connects. Echo2 subclasses Echo and
negotiates TLS when the client sends "STARTTLS"::
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
from twisted.protocols.policies import WrappingFactory
from twisted.protocols.basic import LineReceiver
from twisted.python import log
from twisted.python.failure import Failure
import sys
from tlslite.api import *
s = open("./serverX509Cert.pem").read()
x509 = X509()
x509.parse(s)
certChain = X509CertChain([x509])
s = open("./serverX509Key.pem").read()
privateKey = parsePEMKey(s, private=True)
verifierDB = VerifierDB("verifierDB")
verifierDB.open()
class Echo(LineReceiver):
def connectionMade(self):
self.transport.write("Welcome to the echo server!\\r\\n")
def lineReceived(self, line):
self.transport.write(line + "\\r\\n")
class Echo1(Echo):
def connectionMade(self):
if not self.transport.tlsStarted:
self.transport.setServerHandshakeOp(certChain=certChain,
privateKey=privateKey,
verifierDB=verifierDB)
else:
Echo.connectionMade(self)
def connectionLost(self, reason):
pass #Handle any TLS exceptions here
class Echo2(Echo):
def lineReceived(self, data):
if data == "STARTTLS":
self.transport.setServerHandshakeOp(certChain=certChain,
privateKey=privateKey,
verifierDB=verifierDB)
else:
Echo.lineReceived(self, data)
def connectionLost(self, reason):
pass #Handle any TLS exceptions here
factory = Factory()
factory.protocol = Echo1
#factory.protocol = Echo2
wrappingFactory = WrappingFactory(factory)
wrappingFactory.protocol = TLSTwistedProtocolWrapper
log.startLogging(sys.stdout)
reactor.listenTCP(1079, wrappingFactory)
reactor.run()
This class works as follows:
Data comes in and is given to the AsyncStateMachine for handling.
AsyncStateMachine will forward events to this class, and we'll
pass them on to the ProtocolHandler, which will proxy them to the
wrapped protocol. The wrapped protocol may then call back into
this class, and these calls will be proxied into the
AsyncStateMachine.
The call graph looks like this:
- self.dataReceived
- AsyncStateMachine.inReadEvent
- self.out(Connect|Close|Read)Event
- ProtocolWrapper.(connectionMade|loseConnection|dataReceived)
- self.(loseConnection|write|writeSequence)
- AsyncStateMachine.(setCloseOp|setWriteOp)
"""
#WARNING: IF YOU COPY-AND-PASTE THE ABOVE CODE, BE SURE TO REMOVE
#THE EXTRA ESCAPING AROUND "\\r\\n"
def __init__(self, factory, wrappedProtocol):
ProtocolWrapper.__init__(self, factory, wrappedProtocol)
AsyncStateMachine.__init__(self)
self.fakeSocket = _FakeSocket(self)
self.tlsConnection = TLSConnection(self.fakeSocket)
self.tlsStarted = False
self.connectionLostCalled = False
def connectionMade(self):
try:
ProtocolWrapper.connectionMade(self)
except TLSError, e:
self.connectionLost(Failure(e))
ProtocolWrapper.loseConnection(self)
def dataReceived(self, data):
try:
if not self.tlsStarted:
ProtocolWrapper.dataReceived(self, data)
else:
self.fakeSocket.data += data
while self.fakeSocket.data:
AsyncStateMachine.inReadEvent(self)
except TLSError, e:
self.connectionLost(Failure(e))
ProtocolWrapper.loseConnection(self)
def connectionLost(self, reason):
if not self.connectionLostCalled:
ProtocolWrapper.connectionLost(self, reason)
self.connectionLostCalled = True
def outConnectEvent(self):
ProtocolWrapper.connectionMade(self)
def outCloseEvent(self):
ProtocolWrapper.loseConnection(self)
def outReadEvent(self, data):
if data == "":
ProtocolWrapper.loseConnection(self)
else:
ProtocolWrapper.dataReceived(self, data)
def setServerHandshakeOp(self, **args):
self.tlsStarted = True
AsyncStateMachine.setServerHandshakeOp(self, **args)
def loseConnection(self):
if not self.tlsStarted:
ProtocolWrapper.loseConnection(self)
else:
AsyncStateMachine.setCloseOp(self)
def write(self, data):
if not self.tlsStarted:
ProtocolWrapper.write(self, data)
else:
#Because of the FakeSocket, write operations are guaranteed to
#terminate immediately.
AsyncStateMachine.setWriteOp(self, data)
def writeSequence(self, seq):
if not self.tlsStarted:
ProtocolWrapper.writeSequence(self, seq)
else:
#Because of the FakeSocket, write operations are guaranteed to
#terminate immediately.
AsyncStateMachine.setWriteOp(self, "".join(seq))

View File

@ -1,5 +1,5 @@
"""Pure-Python RSA implementation."""
"""Pure-Python RSA implementation."""
from cryptomath import *
import xmltools
from ASN1Parser import ASN1Parser
@ -8,7 +8,7 @@ from RSAKey import *
class Python_RSAKey(RSAKey):
def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0):
if (n and not e) or (e and not n):
raise AssertionError()
raise AssertionError()
self.n = n
self.e = e
self.d = d
@ -122,61 +122,61 @@ class Python_RSAKey(RSAKey):
bytes = base64ToBytes(s)
return Python_RSAKey._parsePKCS8(bytes)
else:
start = s.find("-----BEGIN RSA PRIVATE KEY-----")
if start != -1:
end = s.find("-----END RSA PRIVATE KEY-----")
if end == -1:
raise SyntaxError("Missing PEM Postfix")
s = s[start+len("-----BEGIN RSA PRIVATE KEY -----") : end]
bytes = base64ToBytes(s)
return Python_RSAKey._parseSSLeay(bytes)
raise SyntaxError("Missing PEM Prefix")
parsePEM = staticmethod(parsePEM)
def parseXML(s):
start = s.find("-----BEGIN RSA PRIVATE KEY-----")
if start != -1:
end = s.find("-----END RSA PRIVATE KEY-----")
if end == -1:
raise SyntaxError("Missing PEM Postfix")
s = s[start+len("-----BEGIN RSA PRIVATE KEY -----") : end]
bytes = base64ToBytes(s)
return Python_RSAKey._parseSSLeay(bytes)
raise SyntaxError("Missing PEM Prefix")
parsePEM = staticmethod(parsePEM)
def parseXML(s):
element = xmltools.parseAndStripWhitespace(s)
return Python_RSAKey._parseXML(element)
return Python_RSAKey._parseXML(element)
parseXML = staticmethod(parseXML)
def _parsePKCS8(bytes):
p = ASN1Parser(bytes)
version = p.getChild(0).value[0]
if version != 0:
raise SyntaxError("Unrecognized PKCS8 version")
rsaOID = p.getChild(1).value
if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
raise SyntaxError("Unrecognized AlgorithmIdentifier")
#Get the privateKey
privateKeyP = p.getChild(2)
#Adjust for OCTET STRING encapsulation
privateKeyP = ASN1Parser(privateKeyP.value)
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
_parsePKCS8 = staticmethod(_parsePKCS8)
def _parseSSLeay(bytes):
privateKeyP = ASN1Parser(bytes)
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
def _parsePKCS8(bytes):
p = ASN1Parser(bytes)
version = p.getChild(0).value[0]
if version != 0:
raise SyntaxError("Unrecognized PKCS8 version")
rsaOID = p.getChild(1).value
if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
raise SyntaxError("Unrecognized AlgorithmIdentifier")
#Get the privateKey
privateKeyP = p.getChild(2)
#Adjust for OCTET STRING encapsulation
privateKeyP = ASN1Parser(privateKeyP.value)
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
_parsePKCS8 = staticmethod(_parsePKCS8)
def _parseSSLeay(bytes):
privateKeyP = ASN1Parser(bytes)
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
_parseSSLeay = staticmethod(_parseSSLeay)
def _parseASN1PrivateKey(privateKeyP):
version = privateKeyP.getChild(0).value[0]
if version != 0:
raise SyntaxError("Unrecognized RSAPrivateKey version")
n = bytesToNumber(privateKeyP.getChild(1).value)
e = bytesToNumber(privateKeyP.getChild(2).value)
d = bytesToNumber(privateKeyP.getChild(3).value)
p = bytesToNumber(privateKeyP.getChild(4).value)
q = bytesToNumber(privateKeyP.getChild(5).value)
dP = bytesToNumber(privateKeyP.getChild(6).value)
dQ = bytesToNumber(privateKeyP.getChild(7).value)
qInv = bytesToNumber(privateKeyP.getChild(8).value)
return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
_parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey)
def _parseASN1PrivateKey(privateKeyP):
version = privateKeyP.getChild(0).value[0]
if version != 0:
raise SyntaxError("Unrecognized RSAPrivateKey version")
n = bytesToNumber(privateKeyP.getChild(1).value)
e = bytesToNumber(privateKeyP.getChild(2).value)
d = bytesToNumber(privateKeyP.getChild(3).value)
p = bytesToNumber(privateKeyP.getChild(4).value)
q = bytesToNumber(privateKeyP.getChild(5).value)
dP = bytesToNumber(privateKeyP.getChild(6).value)
dQ = bytesToNumber(privateKeyP.getChild(7).value)
qInv = bytesToNumber(privateKeyP.getChild(8).value)
return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
_parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey)
def _parseXML(element):
try:

Some files were not shown because too many files have changed in this diff Show More