mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-04 11:43:45 +00:00
move nearly everything into /src to make git.io/gam cleaner w/o a readme tree
This commit is contained in:
0
.gitignore → src/.gitignore
vendored
0
.gitignore → src/.gitignore
vendored
@ -1,21 +1,21 @@
|
|||||||
rmdir /q /s gam
|
rmdir /q /s gam
|
||||||
rmdir /q /s gam-64
|
rmdir /q /s gam-64
|
||||||
rmdir /q /s build
|
rmdir /q /s build
|
||||||
rmdir /q /s dist
|
rmdir /q /s dist
|
||||||
del /q /f gam-%1-windows.zip
|
del /q /f gam-%1-windows.zip
|
||||||
del /q /f gam-%1-windows-x64.zip
|
del /q /f gam-%1-windows-x64.zip
|
||||||
|
|
||||||
c:\python27-32\scripts\pyinstaller -F --distpath=gam gam.spec
|
c:\python27-32\scripts\pyinstaller -F --distpath=gam gam.spec
|
||||||
xcopy LICENSE gam\
|
xcopy LICENSE gam\
|
||||||
xcopy whatsnew.txt gam\
|
xcopy whatsnew.txt gam\
|
||||||
xcopy admin-settings-v1.json gam\
|
xcopy admin-settings-v1.json gam\
|
||||||
xcopy cloudprint-v2.json gam\
|
xcopy cloudprint-v2.json gam\
|
||||||
del gam\w9xpopen.exe
|
del gam\w9xpopen.exe
|
||||||
"%ProgramFiles(x86)%\7-Zip\7z.exe" a -tzip gam-%1-windows.zip gam\ -xr!.svn
|
"%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
|
c:\python27\scripts\pyinstaller -F --distpath=gam-64 gam.spec
|
||||||
xcopy LICENSE gam-64\
|
xcopy LICENSE gam-64\
|
||||||
xcopy whatsnew.txt gam-64\
|
xcopy whatsnew.txt gam-64\
|
||||||
xcopy admin-settings-v1.json gam-64\
|
xcopy admin-settings-v1.json gam-64\
|
||||||
xcopy cloudprint-v2.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
|
"%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
0
gam.py → src/gam.py
Executable file → Normal file
@ -1,17 +1,17 @@
|
|||||||
1. Moved oauth.py to __init__.py
|
1. Moved oauth.py to __init__.py
|
||||||
|
|
||||||
2. Refactored __init__.py for compatibility with python 2.2 (Issue 59)
|
2. Refactored __init__.py for compatibility with python 2.2 (Issue 59)
|
||||||
|
|
||||||
3. Refactored rsa.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
|
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)
|
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
|
5. Added build_signature_base_string method to rsa.py since it used the
|
||||||
implementation of this method from oauth.OAuthSignatureMethod_HMAC_SHA1 which
|
implementation of this method from oauth.OAuthSignatureMethod_HMAC_SHA1 which
|
||||||
was incorrect since it enforced the presence of a consumer secret and a token
|
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
|
secret. Also, changed its super class from oauth.OAuthSignatureMethod_HMAC_SHA1
|
||||||
to oauth.OAuthSignatureMethod (Issue 64)
|
to oauth.OAuthSignatureMethod (Issue 64)
|
||||||
|
|
||||||
6. Refactored <OAuthRequest>.to_header method since it returned non-oauth params
|
6. Refactored <OAuthRequest>.to_header method since it returned non-oauth params
|
||||||
as well which was incorrect. (Issue 31)
|
as well which was incorrect. (Issue 31)
|
File diff suppressed because it is too large
Load Diff
@ -1,120 +1,120 @@
|
|||||||
"""Base class for SharedKeyDB and VerifierDB."""
|
"""Base class for SharedKeyDB and VerifierDB."""
|
||||||
|
|
||||||
import anydbm
|
import anydbm
|
||||||
import thread
|
import thread
|
||||||
|
|
||||||
class BaseDB:
|
class BaseDB:
|
||||||
def __init__(self, filename, type):
|
def __init__(self, filename, type):
|
||||||
self.type = type
|
self.type = type
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
if self.filename:
|
if self.filename:
|
||||||
self.db = None
|
self.db = None
|
||||||
else:
|
else:
|
||||||
self.db = {}
|
self.db = {}
|
||||||
self.lock = thread.allocate_lock()
|
self.lock = thread.allocate_lock()
|
||||||
|
|
||||||
def create(self):
|
def create(self):
|
||||||
"""Create a new on-disk database.
|
"""Create a new on-disk database.
|
||||||
|
|
||||||
@raise anydbm.error: If there's a problem creating the database.
|
@raise anydbm.error: If there's a problem creating the database.
|
||||||
"""
|
"""
|
||||||
if self.filename:
|
if self.filename:
|
||||||
self.db = anydbm.open(self.filename, "n") #raises anydbm.error
|
self.db = anydbm.open(self.filename, "n") #raises anydbm.error
|
||||||
self.db["--Reserved--type"] = self.type
|
self.db["--Reserved--type"] = self.type
|
||||||
self.db.sync()
|
self.db.sync()
|
||||||
else:
|
else:
|
||||||
self.db = {}
|
self.db = {}
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
"""Open a pre-existing on-disk database.
|
"""Open a pre-existing on-disk database.
|
||||||
|
|
||||||
@raise anydbm.error: If there's a problem opening the database.
|
@raise anydbm.error: If there's a problem opening the database.
|
||||||
@raise ValueError: If the database is not of the right type.
|
@raise ValueError: If the database is not of the right type.
|
||||||
"""
|
"""
|
||||||
if not self.filename:
|
if not self.filename:
|
||||||
raise ValueError("Can only open on-disk databases")
|
raise ValueError("Can only open on-disk databases")
|
||||||
self.db = anydbm.open(self.filename, "w") #raises anydbm.error
|
self.db = anydbm.open(self.filename, "w") #raises anydbm.error
|
||||||
try:
|
try:
|
||||||
if self.db["--Reserved--type"] != self.type:
|
if self.db["--Reserved--type"] != self.type:
|
||||||
raise ValueError("Not a %s database" % self.type)
|
raise ValueError("Not a %s database" % self.type)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError("Not a recognized database")
|
raise ValueError("Not a recognized database")
|
||||||
|
|
||||||
def __getitem__(self, username):
|
def __getitem__(self, username):
|
||||||
if self.db == None:
|
if self.db == None:
|
||||||
raise AssertionError("DB not open")
|
raise AssertionError("DB not open")
|
||||||
|
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
valueStr = self.db[username]
|
valueStr = self.db[username]
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
return self._getItem(username, valueStr)
|
return self._getItem(username, valueStr)
|
||||||
|
|
||||||
def __setitem__(self, username, value):
|
def __setitem__(self, username, value):
|
||||||
if self.db == None:
|
if self.db == None:
|
||||||
raise AssertionError("DB not open")
|
raise AssertionError("DB not open")
|
||||||
|
|
||||||
valueStr = self._setItem(username, value)
|
valueStr = self._setItem(username, value)
|
||||||
|
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
self.db[username] = valueStr
|
self.db[username] = valueStr
|
||||||
if self.filename:
|
if self.filename:
|
||||||
self.db.sync()
|
self.db.sync()
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def __delitem__(self, username):
|
def __delitem__(self, username):
|
||||||
if self.db == None:
|
if self.db == None:
|
||||||
raise AssertionError("DB not open")
|
raise AssertionError("DB not open")
|
||||||
|
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
del(self.db[username])
|
del(self.db[username])
|
||||||
if self.filename:
|
if self.filename:
|
||||||
self.db.sync()
|
self.db.sync()
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def __contains__(self, username):
|
def __contains__(self, username):
|
||||||
"""Check if the database contains the specified username.
|
"""Check if the database contains the specified username.
|
||||||
|
|
||||||
@type username: str
|
@type username: str
|
||||||
@param username: The username to check for.
|
@param username: The username to check for.
|
||||||
|
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
@return: True if the database contains the username, False
|
@return: True if the database contains the username, False
|
||||||
otherwise.
|
otherwise.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self.db == None:
|
if self.db == None:
|
||||||
raise AssertionError("DB not open")
|
raise AssertionError("DB not open")
|
||||||
|
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
return self.db.has_key(username)
|
return self.db.has_key(username)
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def check(self, username, param):
|
def check(self, username, param):
|
||||||
value = self.__getitem__(username)
|
value = self.__getitem__(username)
|
||||||
return self._checkItem(value, username, param)
|
return self._checkItem(value, username, param)
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
"""Return a list of usernames in the database.
|
"""Return a list of usernames in the database.
|
||||||
|
|
||||||
@rtype: list
|
@rtype: list
|
||||||
@return: The usernames in the database.
|
@return: The usernames in the database.
|
||||||
"""
|
"""
|
||||||
if self.db == None:
|
if self.db == None:
|
||||||
raise AssertionError("DB not open")
|
raise AssertionError("DB not open")
|
||||||
|
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
usernames = self.db.keys()
|
usernames = self.db.keys()
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
usernames = [u for u in usernames if not u.startswith("--Reserved--")]
|
usernames = [u for u in usernames if not u.startswith("--Reserved--")]
|
||||||
return usernames
|
return usernames
|
@ -1,181 +1,181 @@
|
|||||||
"""Class representing an X.509 certificate chain."""
|
"""Class representing an X.509 certificate chain."""
|
||||||
|
|
||||||
from utils import cryptomath
|
from utils import cryptomath
|
||||||
|
|
||||||
class X509CertChain:
|
class X509CertChain:
|
||||||
"""This class represents a chain of X.509 certificates.
|
"""This class represents a chain of X.509 certificates.
|
||||||
|
|
||||||
@type x509List: list
|
@type x509List: list
|
||||||
@ivar x509List: A list of L{tlslite.X509.X509} instances,
|
@ivar x509List: A list of L{tlslite.X509.X509} instances,
|
||||||
starting with the end-entity certificate and with every
|
starting with the end-entity certificate and with every
|
||||||
subsequent certificate certifying the previous.
|
subsequent certificate certifying the previous.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, x509List=None):
|
def __init__(self, x509List=None):
|
||||||
"""Create a new X509CertChain.
|
"""Create a new X509CertChain.
|
||||||
|
|
||||||
@type x509List: list
|
@type x509List: list
|
||||||
@param x509List: A list of L{tlslite.X509.X509} instances,
|
@param x509List: A list of L{tlslite.X509.X509} instances,
|
||||||
starting with the end-entity certificate and with every
|
starting with the end-entity certificate and with every
|
||||||
subsequent certificate certifying the previous.
|
subsequent certificate certifying the previous.
|
||||||
"""
|
"""
|
||||||
if x509List:
|
if x509List:
|
||||||
self.x509List = x509List
|
self.x509List = x509List
|
||||||
else:
|
else:
|
||||||
self.x509List = []
|
self.x509List = []
|
||||||
|
|
||||||
def getNumCerts(self):
|
def getNumCerts(self):
|
||||||
"""Get the number of certificates in this chain.
|
"""Get the number of certificates in this chain.
|
||||||
|
|
||||||
@rtype: int
|
@rtype: int
|
||||||
"""
|
"""
|
||||||
return len(self.x509List)
|
return len(self.x509List)
|
||||||
|
|
||||||
def getEndEntityPublicKey(self):
|
def getEndEntityPublicKey(self):
|
||||||
"""Get the public key from the end-entity certificate.
|
"""Get the public key from the end-entity certificate.
|
||||||
|
|
||||||
@rtype: L{tlslite.utils.RSAKey.RSAKey}
|
@rtype: L{tlslite.utils.RSAKey.RSAKey}
|
||||||
"""
|
"""
|
||||||
if self.getNumCerts() == 0:
|
if self.getNumCerts() == 0:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
return self.x509List[0].publicKey
|
return self.x509List[0].publicKey
|
||||||
|
|
||||||
def getFingerprint(self):
|
def getFingerprint(self):
|
||||||
"""Get the hex-encoded fingerprint of the end-entity certificate.
|
"""Get the hex-encoded fingerprint of the end-entity certificate.
|
||||||
|
|
||||||
@rtype: str
|
@rtype: str
|
||||||
@return: A hex-encoded fingerprint.
|
@return: A hex-encoded fingerprint.
|
||||||
"""
|
"""
|
||||||
if self.getNumCerts() == 0:
|
if self.getNumCerts() == 0:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
return self.x509List[0].getFingerprint()
|
return self.x509List[0].getFingerprint()
|
||||||
|
|
||||||
def getCommonName(self):
|
def getCommonName(self):
|
||||||
"""Get the Subject's Common Name from the end-entity certificate.
|
"""Get the Subject's Common Name from the end-entity certificate.
|
||||||
|
|
||||||
The cryptlib_py module must be installed in order to use this
|
The cryptlib_py module must be installed in order to use this
|
||||||
function.
|
function.
|
||||||
|
|
||||||
@rtype: str or None
|
@rtype: str or None
|
||||||
@return: The CN component of the certificate's subject DN, if
|
@return: The CN component of the certificate's subject DN, if
|
||||||
present.
|
present.
|
||||||
"""
|
"""
|
||||||
if self.getNumCerts() == 0:
|
if self.getNumCerts() == 0:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
return self.x509List[0].getCommonName()
|
return self.x509List[0].getCommonName()
|
||||||
|
|
||||||
def validate(self, x509TrustList):
|
def validate(self, x509TrustList):
|
||||||
"""Check the validity of the certificate chain.
|
"""Check the validity of the certificate chain.
|
||||||
|
|
||||||
This checks that every certificate in the chain validates with
|
This checks that every certificate in the chain validates with
|
||||||
the subsequent one, until some certificate validates with (or
|
the subsequent one, until some certificate validates with (or
|
||||||
is identical to) one of the passed-in root certificates.
|
is identical to) one of the passed-in root certificates.
|
||||||
|
|
||||||
The cryptlib_py module must be installed in order to use this
|
The cryptlib_py module must be installed in order to use this
|
||||||
function.
|
function.
|
||||||
|
|
||||||
@type x509TrustList: list of L{tlslite.X509.X509}
|
@type x509TrustList: list of L{tlslite.X509.X509}
|
||||||
@param x509TrustList: A list of trusted root certificates. The
|
@param x509TrustList: A list of trusted root certificates. The
|
||||||
certificate chain must extend to one of these certificates to
|
certificate chain must extend to one of these certificates to
|
||||||
be considered valid.
|
be considered valid.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import cryptlib_py
|
import cryptlib_py
|
||||||
c1 = None
|
c1 = None
|
||||||
c2 = None
|
c2 = None
|
||||||
lastC = None
|
lastC = None
|
||||||
rootC = None
|
rootC = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
rootFingerprints = [c.getFingerprint() for c in x509TrustList]
|
rootFingerprints = [c.getFingerprint() for c in x509TrustList]
|
||||||
|
|
||||||
#Check that every certificate in the chain validates with the
|
#Check that every certificate in the chain validates with the
|
||||||
#next one
|
#next one
|
||||||
for cert1, cert2 in zip(self.x509List, self.x509List[1:]):
|
for cert1, cert2 in zip(self.x509List, self.x509List[1:]):
|
||||||
|
|
||||||
#If we come upon a root certificate, we're done.
|
#If we come upon a root certificate, we're done.
|
||||||
if cert1.getFingerprint() in rootFingerprints:
|
if cert1.getFingerprint() in rootFingerprints:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
c1 = cryptlib_py.cryptImportCert(cert1.writeBytes(),
|
c1 = cryptlib_py.cryptImportCert(cert1.writeBytes(),
|
||||||
cryptlib_py.CRYPT_UNUSED)
|
cryptlib_py.CRYPT_UNUSED)
|
||||||
c2 = cryptlib_py.cryptImportCert(cert2.writeBytes(),
|
c2 = cryptlib_py.cryptImportCert(cert2.writeBytes(),
|
||||||
cryptlib_py.CRYPT_UNUSED)
|
cryptlib_py.CRYPT_UNUSED)
|
||||||
try:
|
try:
|
||||||
cryptlib_py.cryptCheckCert(c1, c2)
|
cryptlib_py.cryptCheckCert(c1, c2)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
cryptlib_py.cryptDestroyCert(c1)
|
cryptlib_py.cryptDestroyCert(c1)
|
||||||
c1 = None
|
c1 = None
|
||||||
cryptlib_py.cryptDestroyCert(c2)
|
cryptlib_py.cryptDestroyCert(c2)
|
||||||
c2 = None
|
c2 = None
|
||||||
|
|
||||||
#If the last certificate is one of the root certificates, we're
|
#If the last certificate is one of the root certificates, we're
|
||||||
#done.
|
#done.
|
||||||
if self.x509List[-1].getFingerprint() in rootFingerprints:
|
if self.x509List[-1].getFingerprint() in rootFingerprints:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
#Otherwise, find a root certificate that the last certificate
|
#Otherwise, find a root certificate that the last certificate
|
||||||
#chains to, and validate them.
|
#chains to, and validate them.
|
||||||
lastC = cryptlib_py.cryptImportCert(self.x509List[-1].writeBytes(),
|
lastC = cryptlib_py.cryptImportCert(self.x509List[-1].writeBytes(),
|
||||||
cryptlib_py.CRYPT_UNUSED)
|
cryptlib_py.CRYPT_UNUSED)
|
||||||
for rootCert in x509TrustList:
|
for rootCert in x509TrustList:
|
||||||
rootC = cryptlib_py.cryptImportCert(rootCert.writeBytes(),
|
rootC = cryptlib_py.cryptImportCert(rootCert.writeBytes(),
|
||||||
cryptlib_py.CRYPT_UNUSED)
|
cryptlib_py.CRYPT_UNUSED)
|
||||||
if self._checkChaining(lastC, rootC):
|
if self._checkChaining(lastC, rootC):
|
||||||
try:
|
try:
|
||||||
cryptlib_py.cryptCheckCert(lastC, rootC)
|
cryptlib_py.cryptCheckCert(lastC, rootC)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
if not (c1 is None):
|
if not (c1 is None):
|
||||||
cryptlib_py.cryptDestroyCert(c1)
|
cryptlib_py.cryptDestroyCert(c1)
|
||||||
if not (c2 is None):
|
if not (c2 is None):
|
||||||
cryptlib_py.cryptDestroyCert(c2)
|
cryptlib_py.cryptDestroyCert(c2)
|
||||||
if not (lastC is None):
|
if not (lastC is None):
|
||||||
cryptlib_py.cryptDestroyCert(lastC)
|
cryptlib_py.cryptDestroyCert(lastC)
|
||||||
if not (rootC is None):
|
if not (rootC is None):
|
||||||
cryptlib_py.cryptDestroyCert(rootC)
|
cryptlib_py.cryptDestroyCert(rootC)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _checkChaining(self, lastC, rootC):
|
def _checkChaining(self, lastC, rootC):
|
||||||
import cryptlib_py
|
import cryptlib_py
|
||||||
import array
|
import array
|
||||||
def compareNames(name):
|
def compareNames(name):
|
||||||
try:
|
try:
|
||||||
length = cryptlib_py.cryptGetAttributeString(lastC, name, None)
|
length = cryptlib_py.cryptGetAttributeString(lastC, name, None)
|
||||||
lastName = array.array('B', [0] * length)
|
lastName = array.array('B', [0] * length)
|
||||||
cryptlib_py.cryptGetAttributeString(lastC, name, lastName)
|
cryptlib_py.cryptGetAttributeString(lastC, name, lastName)
|
||||||
lastName = lastName.tostring()
|
lastName = lastName.tostring()
|
||||||
except cryptlib_py.CryptException, e:
|
except cryptlib_py.CryptException, e:
|
||||||
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
|
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
|
||||||
lastName = None
|
lastName = None
|
||||||
try:
|
try:
|
||||||
length = cryptlib_py.cryptGetAttributeString(rootC, name, None)
|
length = cryptlib_py.cryptGetAttributeString(rootC, name, None)
|
||||||
rootName = array.array('B', [0] * length)
|
rootName = array.array('B', [0] * length)
|
||||||
cryptlib_py.cryptGetAttributeString(rootC, name, rootName)
|
cryptlib_py.cryptGetAttributeString(rootC, name, rootName)
|
||||||
rootName = rootName.tostring()
|
rootName = rootName.tostring()
|
||||||
except cryptlib_py.CryptException, e:
|
except cryptlib_py.CryptException, e:
|
||||||
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
|
if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
|
||||||
rootName = None
|
rootName = None
|
||||||
|
|
||||||
return lastName == rootName
|
return lastName == rootName
|
||||||
|
|
||||||
cryptlib_py.cryptSetAttribute(lastC,
|
cryptlib_py.cryptSetAttribute(lastC,
|
||||||
cryptlib_py.CRYPT_CERTINFO_ISSUERNAME,
|
cryptlib_py.CRYPT_CERTINFO_ISSUERNAME,
|
||||||
cryptlib_py.CRYPT_UNUSED)
|
cryptlib_py.CRYPT_UNUSED)
|
||||||
|
|
||||||
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COUNTRYNAME):
|
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COUNTRYNAME):
|
||||||
return False
|
return False
|
||||||
if not compareNames(cryptlib_py.CRYPT_CERTINFO_LOCALITYNAME):
|
if not compareNames(cryptlib_py.CRYPT_CERTINFO_LOCALITYNAME):
|
||||||
return False
|
return False
|
||||||
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONNAME):
|
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONNAME):
|
||||||
return False
|
return False
|
||||||
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONALUNITNAME):
|
if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONALUNITNAME):
|
||||||
return False
|
return False
|
||||||
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COMMONNAME):
|
if not compareNames(cryptlib_py.CRYPT_CERTINFO_COMMONNAME):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
@ -1,235 +1,235 @@
|
|||||||
"""
|
"""
|
||||||
A state machine for using TLS Lite with asynchronous I/O.
|
A state machine for using TLS Lite with asynchronous I/O.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class AsyncStateMachine:
|
class AsyncStateMachine:
|
||||||
"""
|
"""
|
||||||
This is an abstract class that's used to integrate TLS Lite with
|
This is an abstract class that's used to integrate TLS Lite with
|
||||||
asyncore and Twisted.
|
asyncore and Twisted.
|
||||||
|
|
||||||
This class signals wantsReadsEvent() and wantsWriteEvent(). When
|
This class signals wantsReadsEvent() and wantsWriteEvent(). When
|
||||||
the underlying socket has become readable or writeable, the event
|
the underlying socket has become readable or writeable, the event
|
||||||
should be passed to this class by calling inReadEvent() or
|
should be passed to this class by calling inReadEvent() or
|
||||||
inWriteEvent(). This class will then try to read or write through
|
inWriteEvent(). This class will then try to read or write through
|
||||||
the socket, and will update its state appropriately.
|
the socket, and will update its state appropriately.
|
||||||
|
|
||||||
This class will forward higher-level events to its subclass. For
|
This class will forward higher-level events to its subclass. For
|
||||||
example, when a complete TLS record has been received,
|
example, when a complete TLS record has been received,
|
||||||
outReadEvent() will be called with the decrypted data.
|
outReadEvent() will be called with the decrypted data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._clear()
|
self._clear()
|
||||||
|
|
||||||
def _clear(self):
|
def _clear(self):
|
||||||
#These store the various asynchronous operations (i.e.
|
#These store the various asynchronous operations (i.e.
|
||||||
#generators). Only one of them, at most, is ever active at a
|
#generators). Only one of them, at most, is ever active at a
|
||||||
#time.
|
#time.
|
||||||
self.handshaker = None
|
self.handshaker = None
|
||||||
self.closer = None
|
self.closer = None
|
||||||
self.reader = None
|
self.reader = None
|
||||||
self.writer = None
|
self.writer = None
|
||||||
|
|
||||||
#This stores the result from the last call to the
|
#This stores the result from the last call to the
|
||||||
#currently active operation. If 0 it indicates that the
|
#currently active operation. If 0 it indicates that the
|
||||||
#operation wants to read, if 1 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 wants to write. If None, there is no active
|
||||||
#operation.
|
#operation.
|
||||||
self.result = None
|
self.result = None
|
||||||
|
|
||||||
def _checkAssert(self, maxActive=1):
|
def _checkAssert(self, maxActive=1):
|
||||||
#This checks that only one operation, at most, is
|
#This checks that only one operation, at most, is
|
||||||
#active, and that self.result is set appropriately.
|
#active, and that self.result is set appropriately.
|
||||||
activeOps = 0
|
activeOps = 0
|
||||||
if self.handshaker:
|
if self.handshaker:
|
||||||
activeOps += 1
|
activeOps += 1
|
||||||
if self.closer:
|
if self.closer:
|
||||||
activeOps += 1
|
activeOps += 1
|
||||||
if self.reader:
|
if self.reader:
|
||||||
activeOps += 1
|
activeOps += 1
|
||||||
if self.writer:
|
if self.writer:
|
||||||
activeOps += 1
|
activeOps += 1
|
||||||
|
|
||||||
if self.result == None:
|
if self.result == None:
|
||||||
if activeOps != 0:
|
if activeOps != 0:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
elif self.result in (0,1):
|
elif self.result in (0,1):
|
||||||
if activeOps != 1:
|
if activeOps != 1:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
else:
|
else:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
if activeOps > maxActive:
|
if activeOps > maxActive:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
|
|
||||||
def wantsReadEvent(self):
|
def wantsReadEvent(self):
|
||||||
"""If the state machine wants to read.
|
"""If the state machine wants to read.
|
||||||
|
|
||||||
If an operation is active, this returns whether or not the
|
If an operation is active, this returns whether or not the
|
||||||
operation wants to read from the socket. If an operation is
|
operation wants to read from the socket. If an operation is
|
||||||
not active, this returns None.
|
not active, this returns None.
|
||||||
|
|
||||||
@rtype: bool or None
|
@rtype: bool or None
|
||||||
@return: If the state machine wants to read.
|
@return: If the state machine wants to read.
|
||||||
"""
|
"""
|
||||||
if self.result != None:
|
if self.result != None:
|
||||||
return self.result == 0
|
return self.result == 0
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def wantsWriteEvent(self):
|
def wantsWriteEvent(self):
|
||||||
"""If the state machine wants to write.
|
"""If the state machine wants to write.
|
||||||
|
|
||||||
If an operation is active, this returns whether or not the
|
If an operation is active, this returns whether or not the
|
||||||
operation wants to write to the socket. If an operation is
|
operation wants to write to the socket. If an operation is
|
||||||
not active, this returns None.
|
not active, this returns None.
|
||||||
|
|
||||||
@rtype: bool or None
|
@rtype: bool or None
|
||||||
@return: If the state machine wants to write.
|
@return: If the state machine wants to write.
|
||||||
"""
|
"""
|
||||||
if self.result != None:
|
if self.result != None:
|
||||||
return self.result == 1
|
return self.result == 1
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def outConnectEvent(self):
|
def outConnectEvent(self):
|
||||||
"""Called when a handshake operation completes.
|
"""Called when a handshake operation completes.
|
||||||
|
|
||||||
May be overridden in subclass.
|
May be overridden in subclass.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def outCloseEvent(self):
|
def outCloseEvent(self):
|
||||||
"""Called when a close operation completes.
|
"""Called when a close operation completes.
|
||||||
|
|
||||||
May be overridden in subclass.
|
May be overridden in subclass.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def outReadEvent(self, readBuffer):
|
def outReadEvent(self, readBuffer):
|
||||||
"""Called when a read operation completes.
|
"""Called when a read operation completes.
|
||||||
|
|
||||||
May be overridden in subclass."""
|
May be overridden in subclass."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def outWriteEvent(self):
|
def outWriteEvent(self):
|
||||||
"""Called when a write operation completes.
|
"""Called when a write operation completes.
|
||||||
|
|
||||||
May be overridden in subclass."""
|
May be overridden in subclass."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def inReadEvent(self):
|
def inReadEvent(self):
|
||||||
"""Tell the state machine it can read from the socket."""
|
"""Tell the state machine it can read from the socket."""
|
||||||
try:
|
try:
|
||||||
self._checkAssert()
|
self._checkAssert()
|
||||||
if self.handshaker:
|
if self.handshaker:
|
||||||
self._doHandshakeOp()
|
self._doHandshakeOp()
|
||||||
elif self.closer:
|
elif self.closer:
|
||||||
self._doCloseOp()
|
self._doCloseOp()
|
||||||
elif self.reader:
|
elif self.reader:
|
||||||
self._doReadOp()
|
self._doReadOp()
|
||||||
elif self.writer:
|
elif self.writer:
|
||||||
self._doWriteOp()
|
self._doWriteOp()
|
||||||
else:
|
else:
|
||||||
self.reader = self.tlsConnection.readAsync(16384)
|
self.reader = self.tlsConnection.readAsync(16384)
|
||||||
self._doReadOp()
|
self._doReadOp()
|
||||||
except:
|
except:
|
||||||
self._clear()
|
self._clear()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def inWriteEvent(self):
|
def inWriteEvent(self):
|
||||||
"""Tell the state machine it can write to the socket."""
|
"""Tell the state machine it can write to the socket."""
|
||||||
try:
|
try:
|
||||||
self._checkAssert()
|
self._checkAssert()
|
||||||
if self.handshaker:
|
if self.handshaker:
|
||||||
self._doHandshakeOp()
|
self._doHandshakeOp()
|
||||||
elif self.closer:
|
elif self.closer:
|
||||||
self._doCloseOp()
|
self._doCloseOp()
|
||||||
elif self.reader:
|
elif self.reader:
|
||||||
self._doReadOp()
|
self._doReadOp()
|
||||||
elif self.writer:
|
elif self.writer:
|
||||||
self._doWriteOp()
|
self._doWriteOp()
|
||||||
else:
|
else:
|
||||||
self.outWriteEvent()
|
self.outWriteEvent()
|
||||||
except:
|
except:
|
||||||
self._clear()
|
self._clear()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _doHandshakeOp(self):
|
def _doHandshakeOp(self):
|
||||||
try:
|
try:
|
||||||
self.result = self.handshaker.next()
|
self.result = self.handshaker.next()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
self.handshaker = None
|
self.handshaker = None
|
||||||
self.result = None
|
self.result = None
|
||||||
self.outConnectEvent()
|
self.outConnectEvent()
|
||||||
|
|
||||||
def _doCloseOp(self):
|
def _doCloseOp(self):
|
||||||
try:
|
try:
|
||||||
self.result = self.closer.next()
|
self.result = self.closer.next()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
self.closer = None
|
self.closer = None
|
||||||
self.result = None
|
self.result = None
|
||||||
self.outCloseEvent()
|
self.outCloseEvent()
|
||||||
|
|
||||||
def _doReadOp(self):
|
def _doReadOp(self):
|
||||||
self.result = self.reader.next()
|
self.result = self.reader.next()
|
||||||
if not self.result in (0,1):
|
if not self.result in (0,1):
|
||||||
readBuffer = self.result
|
readBuffer = self.result
|
||||||
self.reader = None
|
self.reader = None
|
||||||
self.result = None
|
self.result = None
|
||||||
self.outReadEvent(readBuffer)
|
self.outReadEvent(readBuffer)
|
||||||
|
|
||||||
def _doWriteOp(self):
|
def _doWriteOp(self):
|
||||||
try:
|
try:
|
||||||
self.result = self.writer.next()
|
self.result = self.writer.next()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
self.writer = None
|
self.writer = None
|
||||||
self.result = None
|
self.result = None
|
||||||
|
|
||||||
def setHandshakeOp(self, handshaker):
|
def setHandshakeOp(self, handshaker):
|
||||||
"""Start a handshake operation.
|
"""Start a handshake operation.
|
||||||
|
|
||||||
@type handshaker: generator
|
@type handshaker: generator
|
||||||
@param handshaker: A generator created by using one of the
|
@param handshaker: A generator created by using one of the
|
||||||
asynchronous handshake functions (i.e. handshakeServerAsync, or
|
asynchronous handshake functions (i.e. handshakeServerAsync, or
|
||||||
handshakeClientxxx(..., async=True).
|
handshakeClientxxx(..., async=True).
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self._checkAssert(0)
|
self._checkAssert(0)
|
||||||
self.handshaker = handshaker
|
self.handshaker = handshaker
|
||||||
self._doHandshakeOp()
|
self._doHandshakeOp()
|
||||||
except:
|
except:
|
||||||
self._clear()
|
self._clear()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def setServerHandshakeOp(self, **args):
|
def setServerHandshakeOp(self, **args):
|
||||||
"""Start a handshake operation.
|
"""Start a handshake operation.
|
||||||
|
|
||||||
The arguments passed to this function will be forwarded to
|
The arguments passed to this function will be forwarded to
|
||||||
L{tlslite.TLSConnection.TLSConnection.handshakeServerAsync}.
|
L{tlslite.TLSConnection.TLSConnection.handshakeServerAsync}.
|
||||||
"""
|
"""
|
||||||
handshaker = self.tlsConnection.handshakeServerAsync(**args)
|
handshaker = self.tlsConnection.handshakeServerAsync(**args)
|
||||||
self.setHandshakeOp(handshaker)
|
self.setHandshakeOp(handshaker)
|
||||||
|
|
||||||
def setCloseOp(self):
|
def setCloseOp(self):
|
||||||
"""Start a close operation.
|
"""Start a close operation.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self._checkAssert(0)
|
self._checkAssert(0)
|
||||||
self.closer = self.tlsConnection.closeAsync()
|
self.closer = self.tlsConnection.closeAsync()
|
||||||
self._doCloseOp()
|
self._doCloseOp()
|
||||||
except:
|
except:
|
||||||
self._clear()
|
self._clear()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def setWriteOp(self, writeBuffer):
|
def setWriteOp(self, writeBuffer):
|
||||||
"""Start a write operation.
|
"""Start a write operation.
|
||||||
|
|
||||||
@type writeBuffer: str
|
@type writeBuffer: str
|
||||||
@param writeBuffer: The string to transmit.
|
@param writeBuffer: The string to transmit.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self._checkAssert(0)
|
self._checkAssert(0)
|
||||||
self.writer = self.tlsConnection.writeAsync(writeBuffer)
|
self.writer = self.tlsConnection.writeAsync(writeBuffer)
|
||||||
self._doWriteOp()
|
self._doWriteOp()
|
||||||
except:
|
except:
|
||||||
self._clear()
|
self._clear()
|
||||||
raise
|
raise
|
||||||
|
|
@ -1,163 +1,163 @@
|
|||||||
"""
|
"""
|
||||||
A helper class for using TLS Lite with stdlib clients
|
A helper class for using TLS Lite with stdlib clients
|
||||||
(httplib, xmlrpclib, imaplib, poplib).
|
(httplib, xmlrpclib, imaplib, poplib).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from gdata.tlslite.Checker import Checker
|
from gdata.tlslite.Checker import Checker
|
||||||
|
|
||||||
class ClientHelper:
|
class ClientHelper:
|
||||||
"""This is a helper class used to integrate TLS Lite with various
|
"""This is a helper class used to integrate TLS Lite with various
|
||||||
TLS clients (e.g. poplib, smtplib, httplib, etc.)"""
|
TLS clients (e.g. poplib, smtplib, httplib, etc.)"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
username=None, password=None, sharedKey=None,
|
username=None, password=None, sharedKey=None,
|
||||||
certChain=None, privateKey=None,
|
certChain=None, privateKey=None,
|
||||||
cryptoID=None, protocol=None,
|
cryptoID=None, protocol=None,
|
||||||
x509Fingerprint=None,
|
x509Fingerprint=None,
|
||||||
x509TrustList=None, x509CommonName=None,
|
x509TrustList=None, x509CommonName=None,
|
||||||
settings = None):
|
settings = None):
|
||||||
"""
|
"""
|
||||||
For client authentication, use one of these argument
|
For client authentication, use one of these argument
|
||||||
combinations:
|
combinations:
|
||||||
- username, password (SRP)
|
- username, password (SRP)
|
||||||
- username, sharedKey (shared-key)
|
- username, sharedKey (shared-key)
|
||||||
- certChain, privateKey (certificate)
|
- certChain, privateKey (certificate)
|
||||||
|
|
||||||
For server authentication, you can either rely on the
|
For server authentication, you can either rely on the
|
||||||
implicit mutual authentication performed by SRP or
|
implicit mutual authentication performed by SRP or
|
||||||
shared-keys, or you can do certificate-based server
|
shared-keys, or you can do certificate-based server
|
||||||
authentication with one of these argument combinations:
|
authentication with one of these argument combinations:
|
||||||
- cryptoID[, protocol] (requires cryptoIDlib)
|
- cryptoID[, protocol] (requires cryptoIDlib)
|
||||||
- x509Fingerprint
|
- x509Fingerprint
|
||||||
- x509TrustList[, x509CommonName] (requires cryptlib_py)
|
- x509TrustList[, x509CommonName] (requires cryptlib_py)
|
||||||
|
|
||||||
Certificate-based server authentication is compatible with
|
Certificate-based server authentication is compatible with
|
||||||
SRP or certificate-based client authentication. It is
|
SRP or certificate-based client authentication. It is
|
||||||
not compatible with shared-keys.
|
not compatible with shared-keys.
|
||||||
|
|
||||||
The constructor does not perform the TLS handshake itself, but
|
The constructor does not perform the TLS handshake itself, but
|
||||||
simply stores these arguments for later. The handshake is
|
simply stores these arguments for later. The handshake is
|
||||||
performed only when this class needs to connect with the
|
performed only when this class needs to connect with the
|
||||||
server. Then you should be prepared to handle TLS-specific
|
server. Then you should be prepared to handle TLS-specific
|
||||||
exceptions. See the client handshake functions in
|
exceptions. See the client handshake functions in
|
||||||
L{tlslite.TLSConnection.TLSConnection} for details on which
|
L{tlslite.TLSConnection.TLSConnection} for details on which
|
||||||
exceptions might be raised.
|
exceptions might be raised.
|
||||||
|
|
||||||
@type username: str
|
@type username: str
|
||||||
@param username: SRP or shared-key username. Requires the
|
@param username: SRP or shared-key username. Requires the
|
||||||
'password' or 'sharedKey' argument.
|
'password' or 'sharedKey' argument.
|
||||||
|
|
||||||
@type password: str
|
@type password: str
|
||||||
@param password: SRP password for mutual authentication.
|
@param password: SRP password for mutual authentication.
|
||||||
Requires the 'username' argument.
|
Requires the 'username' argument.
|
||||||
|
|
||||||
@type sharedKey: str
|
@type sharedKey: str
|
||||||
@param sharedKey: Shared key for mutual authentication.
|
@param sharedKey: Shared key for mutual authentication.
|
||||||
Requires the 'username' argument.
|
Requires the 'username' argument.
|
||||||
|
|
||||||
@type certChain: L{tlslite.X509CertChain.X509CertChain} or
|
@type certChain: L{tlslite.X509CertChain.X509CertChain} or
|
||||||
L{cryptoIDlib.CertChain.CertChain}
|
L{cryptoIDlib.CertChain.CertChain}
|
||||||
@param certChain: Certificate chain for client authentication.
|
@param certChain: Certificate chain for client authentication.
|
||||||
Requires the 'privateKey' argument. Excludes the SRP or
|
Requires the 'privateKey' argument. Excludes the SRP or
|
||||||
shared-key related arguments.
|
shared-key related arguments.
|
||||||
|
|
||||||
@type privateKey: L{tlslite.utils.RSAKey.RSAKey}
|
@type privateKey: L{tlslite.utils.RSAKey.RSAKey}
|
||||||
@param privateKey: Private key for client authentication.
|
@param privateKey: Private key for client authentication.
|
||||||
Requires the 'certChain' argument. Excludes the SRP or
|
Requires the 'certChain' argument. Excludes the SRP or
|
||||||
shared-key related arguments.
|
shared-key related arguments.
|
||||||
|
|
||||||
@type cryptoID: str
|
@type cryptoID: str
|
||||||
@param cryptoID: cryptoID for server authentication. Mutually
|
@param cryptoID: cryptoID for server authentication. Mutually
|
||||||
exclusive with the 'x509...' arguments.
|
exclusive with the 'x509...' arguments.
|
||||||
|
|
||||||
@type protocol: str
|
@type protocol: str
|
||||||
@param protocol: cryptoID protocol URI for server
|
@param protocol: cryptoID protocol URI for server
|
||||||
authentication. Requires the 'cryptoID' argument.
|
authentication. Requires the 'cryptoID' argument.
|
||||||
|
|
||||||
@type x509Fingerprint: str
|
@type x509Fingerprint: str
|
||||||
@param x509Fingerprint: Hex-encoded X.509 fingerprint for
|
@param x509Fingerprint: Hex-encoded X.509 fingerprint for
|
||||||
server authentication. Mutually exclusive with the 'cryptoID'
|
server authentication. Mutually exclusive with the 'cryptoID'
|
||||||
and 'x509TrustList' arguments.
|
and 'x509TrustList' arguments.
|
||||||
|
|
||||||
@type x509TrustList: list of L{tlslite.X509.X509}
|
@type x509TrustList: list of L{tlslite.X509.X509}
|
||||||
@param x509TrustList: A list of trusted root certificates. The
|
@param x509TrustList: A list of trusted root certificates. The
|
||||||
other party must present a certificate chain which extends to
|
other party must present a certificate chain which extends to
|
||||||
one of these root certificates. The cryptlib_py module must be
|
one of these root certificates. The cryptlib_py module must be
|
||||||
installed to use this parameter. Mutually exclusive with the
|
installed to use this parameter. Mutually exclusive with the
|
||||||
'cryptoID' and 'x509Fingerprint' arguments.
|
'cryptoID' and 'x509Fingerprint' arguments.
|
||||||
|
|
||||||
@type x509CommonName: str
|
@type x509CommonName: str
|
||||||
@param x509CommonName: The end-entity certificate's 'CN' field
|
@param x509CommonName: The end-entity certificate's 'CN' field
|
||||||
must match this value. For a web server, this is typically a
|
must match this value. For a web server, this is typically a
|
||||||
server name such as 'www.amazon.com'. Mutually exclusive with
|
server name such as 'www.amazon.com'. Mutually exclusive with
|
||||||
the 'cryptoID' and 'x509Fingerprint' arguments. Requires the
|
the 'cryptoID' and 'x509Fingerprint' arguments. Requires the
|
||||||
'x509TrustList' argument.
|
'x509TrustList' argument.
|
||||||
|
|
||||||
@type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
|
@type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
|
||||||
@param settings: Various settings which can be used to control
|
@param settings: Various settings which can be used to control
|
||||||
the ciphersuites, certificate types, and SSL/TLS versions
|
the ciphersuites, certificate types, and SSL/TLS versions
|
||||||
offered by the client.
|
offered by the client.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.username = None
|
self.username = None
|
||||||
self.password = None
|
self.password = None
|
||||||
self.sharedKey = None
|
self.sharedKey = None
|
||||||
self.certChain = None
|
self.certChain = None
|
||||||
self.privateKey = None
|
self.privateKey = None
|
||||||
self.checker = None
|
self.checker = None
|
||||||
|
|
||||||
#SRP Authentication
|
#SRP Authentication
|
||||||
if username and password and not \
|
if username and password and not \
|
||||||
(sharedKey or certChain or privateKey):
|
(sharedKey or certChain or privateKey):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
|
|
||||||
#Shared Key Authentication
|
#Shared Key Authentication
|
||||||
elif username and sharedKey and not \
|
elif username and sharedKey and not \
|
||||||
(password or certChain or privateKey):
|
(password or certChain or privateKey):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.sharedKey = sharedKey
|
self.sharedKey = sharedKey
|
||||||
|
|
||||||
#Certificate Chain Authentication
|
#Certificate Chain Authentication
|
||||||
elif certChain and privateKey and not \
|
elif certChain and privateKey and not \
|
||||||
(username or password or sharedKey):
|
(username or password or sharedKey):
|
||||||
self.certChain = certChain
|
self.certChain = certChain
|
||||||
self.privateKey = privateKey
|
self.privateKey = privateKey
|
||||||
|
|
||||||
#No Authentication
|
#No Authentication
|
||||||
elif not password and not username and not \
|
elif not password and not username and not \
|
||||||
sharedKey and not certChain and not privateKey:
|
sharedKey and not certChain and not privateKey:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Bad parameters")
|
raise ValueError("Bad parameters")
|
||||||
|
|
||||||
#Authenticate the server based on its cryptoID or fingerprint
|
#Authenticate the server based on its cryptoID or fingerprint
|
||||||
if sharedKey and (cryptoID or protocol or x509Fingerprint):
|
if sharedKey and (cryptoID or protocol or x509Fingerprint):
|
||||||
raise ValueError("Can't use shared keys with other forms of"\
|
raise ValueError("Can't use shared keys with other forms of"\
|
||||||
"authentication")
|
"authentication")
|
||||||
|
|
||||||
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
|
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
|
||||||
x509TrustList, x509CommonName)
|
x509TrustList, x509CommonName)
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
|
||||||
self.tlsSession = None
|
self.tlsSession = None
|
||||||
|
|
||||||
def _handshake(self, tlsConnection):
|
def _handshake(self, tlsConnection):
|
||||||
if self.username and self.password:
|
if self.username and self.password:
|
||||||
tlsConnection.handshakeClientSRP(username=self.username,
|
tlsConnection.handshakeClientSRP(username=self.username,
|
||||||
password=self.password,
|
password=self.password,
|
||||||
checker=self.checker,
|
checker=self.checker,
|
||||||
settings=self.settings,
|
settings=self.settings,
|
||||||
session=self.tlsSession)
|
session=self.tlsSession)
|
||||||
elif self.username and self.sharedKey:
|
elif self.username and self.sharedKey:
|
||||||
tlsConnection.handshakeClientSharedKey(username=self.username,
|
tlsConnection.handshakeClientSharedKey(username=self.username,
|
||||||
sharedKey=self.sharedKey,
|
sharedKey=self.sharedKey,
|
||||||
settings=self.settings)
|
settings=self.settings)
|
||||||
else:
|
else:
|
||||||
tlsConnection.handshakeClientCert(certChain=self.certChain,
|
tlsConnection.handshakeClientCert(certChain=self.certChain,
|
||||||
privateKey=self.privateKey,
|
privateKey=self.privateKey,
|
||||||
checker=self.checker,
|
checker=self.checker,
|
||||||
settings=self.settings,
|
settings=self.settings,
|
||||||
session=self.tlsSession)
|
session=self.tlsSession)
|
||||||
self.tlsSession = tlsConnection.session
|
self.tlsSession = tlsConnection.session
|
@ -1,52 +1,52 @@
|
|||||||
|
|
||||||
class IntegrationHelper:
|
class IntegrationHelper:
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
username=None, password=None, sharedKey=None,
|
username=None, password=None, sharedKey=None,
|
||||||
certChain=None, privateKey=None,
|
certChain=None, privateKey=None,
|
||||||
cryptoID=None, protocol=None,
|
cryptoID=None, protocol=None,
|
||||||
x509Fingerprint=None,
|
x509Fingerprint=None,
|
||||||
x509TrustList=None, x509CommonName=None,
|
x509TrustList=None, x509CommonName=None,
|
||||||
settings = None):
|
settings = None):
|
||||||
|
|
||||||
self.username = None
|
self.username = None
|
||||||
self.password = None
|
self.password = None
|
||||||
self.sharedKey = None
|
self.sharedKey = None
|
||||||
self.certChain = None
|
self.certChain = None
|
||||||
self.privateKey = None
|
self.privateKey = None
|
||||||
self.checker = None
|
self.checker = None
|
||||||
|
|
||||||
#SRP Authentication
|
#SRP Authentication
|
||||||
if username and password and not \
|
if username and password and not \
|
||||||
(sharedKey or certChain or privateKey):
|
(sharedKey or certChain or privateKey):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
|
|
||||||
#Shared Key Authentication
|
#Shared Key Authentication
|
||||||
elif username and sharedKey and not \
|
elif username and sharedKey and not \
|
||||||
(password or certChain or privateKey):
|
(password or certChain or privateKey):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.sharedKey = sharedKey
|
self.sharedKey = sharedKey
|
||||||
|
|
||||||
#Certificate Chain Authentication
|
#Certificate Chain Authentication
|
||||||
elif certChain and privateKey and not \
|
elif certChain and privateKey and not \
|
||||||
(username or password or sharedKey):
|
(username or password or sharedKey):
|
||||||
self.certChain = certChain
|
self.certChain = certChain
|
||||||
self.privateKey = privateKey
|
self.privateKey = privateKey
|
||||||
|
|
||||||
#No Authentication
|
#No Authentication
|
||||||
elif not password and not username and not \
|
elif not password and not username and not \
|
||||||
sharedKey and not certChain and not privateKey:
|
sharedKey and not certChain and not privateKey:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Bad parameters")
|
raise ValueError("Bad parameters")
|
||||||
|
|
||||||
#Authenticate the server based on its cryptoID or fingerprint
|
#Authenticate the server based on its cryptoID or fingerprint
|
||||||
if sharedKey and (cryptoID or protocol or x509Fingerprint):
|
if sharedKey and (cryptoID or protocol or x509Fingerprint):
|
||||||
raise ValueError("Can't use shared keys with other forms of"\
|
raise ValueError("Can't use shared keys with other forms of"\
|
||||||
"authentication")
|
"authentication")
|
||||||
|
|
||||||
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
|
self.checker = Checker(cryptoID, protocol, x509Fingerprint,
|
||||||
x509TrustList, x509CommonName)
|
x509TrustList, x509CommonName)
|
||||||
self.settings = settings
|
self.settings = settings
|
@ -1,139 +1,139 @@
|
|||||||
"""TLS Lite + asyncore."""
|
"""TLS Lite + asyncore."""
|
||||||
|
|
||||||
|
|
||||||
import asyncore
|
import asyncore
|
||||||
from gdata.tlslite.TLSConnection import TLSConnection
|
from gdata.tlslite.TLSConnection import TLSConnection
|
||||||
from AsyncStateMachine import AsyncStateMachine
|
from AsyncStateMachine import AsyncStateMachine
|
||||||
|
|
||||||
|
|
||||||
class TLSAsyncDispatcherMixIn(AsyncStateMachine):
|
class TLSAsyncDispatcherMixIn(AsyncStateMachine):
|
||||||
"""This class can be "mixed in" with an
|
"""This class can be "mixed in" with an
|
||||||
L{asyncore.dispatcher} to add TLS support.
|
L{asyncore.dispatcher} to add TLS support.
|
||||||
|
|
||||||
This class essentially sits between the dispatcher and the select
|
This class essentially sits between the dispatcher and the select
|
||||||
loop, intercepting events and only calling the dispatcher when
|
loop, intercepting events and only calling the dispatcher when
|
||||||
applicable.
|
applicable.
|
||||||
|
|
||||||
In the case of handle_read(), a read operation will be activated,
|
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
|
and when it completes, the bytes will be placed in a buffer where
|
||||||
the dispatcher can retrieve them by calling recv(), and the
|
the dispatcher can retrieve them by calling recv(), and the
|
||||||
dispatcher's handle_read() will be called.
|
dispatcher's handle_read() will be called.
|
||||||
|
|
||||||
In the case of handle_write(), the dispatcher's handle_write() will
|
In the case of handle_write(), the dispatcher's handle_write() will
|
||||||
be called, and when it calls send(), a write operation will be
|
be called, and when it calls send(), a write operation will be
|
||||||
activated.
|
activated.
|
||||||
|
|
||||||
To use this class, you must combine it with an asyncore.dispatcher,
|
To use this class, you must combine it with an asyncore.dispatcher,
|
||||||
and pass in a handshake operation with setServerHandshakeOp().
|
and pass in a handshake operation with setServerHandshakeOp().
|
||||||
|
|
||||||
Below is an example of using this class with medusa. This class is
|
Below is an example of using this class with medusa. This class is
|
||||||
mixed in with http_channel to create http_tls_channel. Note:
|
mixed in with http_channel to create http_tls_channel. Note:
|
||||||
1. the mix-in is listed first in the inheritance list
|
1. the mix-in is listed first in the inheritance list
|
||||||
|
|
||||||
2. the input buffer size must be at least 16K, otherwise the
|
2. the input buffer size must be at least 16K, otherwise the
|
||||||
dispatcher might not read all the bytes from the TLS layer,
|
dispatcher might not read all the bytes from the TLS layer,
|
||||||
leaving some bytes in limbo.
|
leaving some bytes in limbo.
|
||||||
|
|
||||||
3. IE seems to have a problem receiving a whole HTTP response in a
|
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
|
single TLS record, so HTML pages containing '\\r\\n\\r\\n' won't
|
||||||
be displayed on IE.
|
be displayed on IE.
|
||||||
|
|
||||||
Add the following text into 'start_medusa.py', in the 'HTTP Server'
|
Add the following text into 'start_medusa.py', in the 'HTTP Server'
|
||||||
section::
|
section::
|
||||||
|
|
||||||
from tlslite.api import *
|
from tlslite.api import *
|
||||||
s = open("./serverX509Cert.pem").read()
|
s = open("./serverX509Cert.pem").read()
|
||||||
x509 = X509()
|
x509 = X509()
|
||||||
x509.parse(s)
|
x509.parse(s)
|
||||||
certChain = X509CertChain([x509])
|
certChain = X509CertChain([x509])
|
||||||
|
|
||||||
s = open("./serverX509Key.pem").read()
|
s = open("./serverX509Key.pem").read()
|
||||||
privateKey = parsePEMKey(s, private=True)
|
privateKey = parsePEMKey(s, private=True)
|
||||||
|
|
||||||
class http_tls_channel(TLSAsyncDispatcherMixIn,
|
class http_tls_channel(TLSAsyncDispatcherMixIn,
|
||||||
http_server.http_channel):
|
http_server.http_channel):
|
||||||
ac_in_buffer_size = 16384
|
ac_in_buffer_size = 16384
|
||||||
|
|
||||||
def __init__ (self, server, conn, addr):
|
def __init__ (self, server, conn, addr):
|
||||||
http_server.http_channel.__init__(self, server, conn, addr)
|
http_server.http_channel.__init__(self, server, conn, addr)
|
||||||
TLSAsyncDispatcherMixIn.__init__(self, conn)
|
TLSAsyncDispatcherMixIn.__init__(self, conn)
|
||||||
self.tlsConnection.ignoreAbruptClose = True
|
self.tlsConnection.ignoreAbruptClose = True
|
||||||
self.setServerHandshakeOp(certChain=certChain,
|
self.setServerHandshakeOp(certChain=certChain,
|
||||||
privateKey=privateKey)
|
privateKey=privateKey)
|
||||||
|
|
||||||
hs.channel_class = http_tls_channel
|
hs.channel_class = http_tls_channel
|
||||||
|
|
||||||
If the TLS layer raises an exception, the exception will be caught
|
If the TLS layer raises an exception, the exception will be caught
|
||||||
in asyncore.dispatcher, which will call close() on this class. The
|
in asyncore.dispatcher, which will call close() on this class. The
|
||||||
TLS layer always closes the TLS connection before raising an
|
TLS layer always closes the TLS connection before raising an
|
||||||
exception, so the close operation will complete right away, causing
|
exception, so the close operation will complete right away, causing
|
||||||
asyncore.dispatcher.close() to be called, which closes the socket
|
asyncore.dispatcher.close() to be called, which closes the socket
|
||||||
and removes this instance from the asyncore loop.
|
and removes this instance from the asyncore loop.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, sock=None):
|
def __init__(self, sock=None):
|
||||||
AsyncStateMachine.__init__(self)
|
AsyncStateMachine.__init__(self)
|
||||||
|
|
||||||
if sock:
|
if sock:
|
||||||
self.tlsConnection = TLSConnection(sock)
|
self.tlsConnection = TLSConnection(sock)
|
||||||
|
|
||||||
#Calculate the sibling I'm being mixed in with.
|
#Calculate the sibling I'm being mixed in with.
|
||||||
#This is necessary since we override functions
|
#This is necessary since we override functions
|
||||||
#like readable(), handle_read(), etc., but we
|
#like readable(), handle_read(), etc., but we
|
||||||
#also want to call the sibling's versions.
|
#also want to call the sibling's versions.
|
||||||
for cl in self.__class__.__bases__:
|
for cl in self.__class__.__bases__:
|
||||||
if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine:
|
if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine:
|
||||||
self.siblingClass = cl
|
self.siblingClass = cl
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
|
|
||||||
def readable(self):
|
def readable(self):
|
||||||
result = self.wantsReadEvent()
|
result = self.wantsReadEvent()
|
||||||
if result != None:
|
if result != None:
|
||||||
return result
|
return result
|
||||||
return self.siblingClass.readable(self)
|
return self.siblingClass.readable(self)
|
||||||
|
|
||||||
def writable(self):
|
def writable(self):
|
||||||
result = self.wantsWriteEvent()
|
result = self.wantsWriteEvent()
|
||||||
if result != None:
|
if result != None:
|
||||||
return result
|
return result
|
||||||
return self.siblingClass.writable(self)
|
return self.siblingClass.writable(self)
|
||||||
|
|
||||||
def handle_read(self):
|
def handle_read(self):
|
||||||
self.inReadEvent()
|
self.inReadEvent()
|
||||||
|
|
||||||
def handle_write(self):
|
def handle_write(self):
|
||||||
self.inWriteEvent()
|
self.inWriteEvent()
|
||||||
|
|
||||||
def outConnectEvent(self):
|
def outConnectEvent(self):
|
||||||
self.siblingClass.handle_connect(self)
|
self.siblingClass.handle_connect(self)
|
||||||
|
|
||||||
def outCloseEvent(self):
|
def outCloseEvent(self):
|
||||||
asyncore.dispatcher.close(self)
|
asyncore.dispatcher.close(self)
|
||||||
|
|
||||||
def outReadEvent(self, readBuffer):
|
def outReadEvent(self, readBuffer):
|
||||||
self.readBuffer = readBuffer
|
self.readBuffer = readBuffer
|
||||||
self.siblingClass.handle_read(self)
|
self.siblingClass.handle_read(self)
|
||||||
|
|
||||||
def outWriteEvent(self):
|
def outWriteEvent(self):
|
||||||
self.siblingClass.handle_write(self)
|
self.siblingClass.handle_write(self)
|
||||||
|
|
||||||
def recv(self, bufferSize=16384):
|
def recv(self, bufferSize=16384):
|
||||||
if bufferSize < 16384 or self.readBuffer == None:
|
if bufferSize < 16384 or self.readBuffer == None:
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
returnValue = self.readBuffer
|
returnValue = self.readBuffer
|
||||||
self.readBuffer = None
|
self.readBuffer = None
|
||||||
return returnValue
|
return returnValue
|
||||||
|
|
||||||
def send(self, writeBuffer):
|
def send(self, writeBuffer):
|
||||||
self.setWriteOp(writeBuffer)
|
self.setWriteOp(writeBuffer)
|
||||||
return len(writeBuffer)
|
return len(writeBuffer)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if hasattr(self, "tlsConnection"):
|
if hasattr(self, "tlsConnection"):
|
||||||
self.setCloseOp()
|
self.setCloseOp()
|
||||||
else:
|
else:
|
||||||
asyncore.dispatcher.close(self)
|
asyncore.dispatcher.close(self)
|
@ -1,196 +1,196 @@
|
|||||||
"""TLS Lite + Twisted."""
|
"""TLS Lite + Twisted."""
|
||||||
|
|
||||||
from twisted.protocols.policies import ProtocolWrapper, WrappingFactory
|
from twisted.protocols.policies import ProtocolWrapper, WrappingFactory
|
||||||
from twisted.python.failure import Failure
|
from twisted.python.failure import Failure
|
||||||
|
|
||||||
from AsyncStateMachine import AsyncStateMachine
|
from AsyncStateMachine import AsyncStateMachine
|
||||||
from gdata.tlslite.TLSConnection import TLSConnection
|
from gdata.tlslite.TLSConnection import TLSConnection
|
||||||
from gdata.tlslite.errors import *
|
from gdata.tlslite.errors import *
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import errno
|
import errno
|
||||||
|
|
||||||
|
|
||||||
#The TLSConnection is created around a "fake socket" that
|
#The TLSConnection is created around a "fake socket" that
|
||||||
#plugs it into the underlying Twisted transport
|
#plugs it into the underlying Twisted transport
|
||||||
class _FakeSocket:
|
class _FakeSocket:
|
||||||
def __init__(self, wrapper):
|
def __init__(self, wrapper):
|
||||||
self.wrapper = wrapper
|
self.wrapper = wrapper
|
||||||
self.data = ""
|
self.data = ""
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
ProtocolWrapper.write(self.wrapper, data)
|
ProtocolWrapper.write(self.wrapper, data)
|
||||||
return len(data)
|
return len(data)
|
||||||
|
|
||||||
def recv(self, numBytes):
|
def recv(self, numBytes):
|
||||||
if self.data == "":
|
if self.data == "":
|
||||||
raise socket.error, (errno.EWOULDBLOCK, "")
|
raise socket.error, (errno.EWOULDBLOCK, "")
|
||||||
returnData = self.data[:numBytes]
|
returnData = self.data[:numBytes]
|
||||||
self.data = self.data[numBytes:]
|
self.data = self.data[numBytes:]
|
||||||
return returnData
|
return returnData
|
||||||
|
|
||||||
class TLSTwistedProtocolWrapper(ProtocolWrapper, AsyncStateMachine):
|
class TLSTwistedProtocolWrapper(ProtocolWrapper, AsyncStateMachine):
|
||||||
"""This class can wrap Twisted protocols to add TLS support.
|
"""This class can wrap Twisted protocols to add TLS support.
|
||||||
|
|
||||||
Below is a complete example of using TLS Lite with a Twisted echo
|
Below is a complete example of using TLS Lite with a Twisted echo
|
||||||
server.
|
server.
|
||||||
|
|
||||||
There are two server implementations below. Echo is the original
|
There are two server implementations below. Echo is the original
|
||||||
protocol, which is oblivious to TLS. Echo1 subclasses Echo and
|
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 connects. Echo2 subclasses Echo and
|
||||||
negotiates TLS when the client sends "STARTTLS"::
|
negotiates TLS when the client sends "STARTTLS"::
|
||||||
|
|
||||||
from twisted.internet.protocol import Protocol, Factory
|
from twisted.internet.protocol import Protocol, Factory
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
from twisted.protocols.policies import WrappingFactory
|
from twisted.protocols.policies import WrappingFactory
|
||||||
from twisted.protocols.basic import LineReceiver
|
from twisted.protocols.basic import LineReceiver
|
||||||
from twisted.python import log
|
from twisted.python import log
|
||||||
from twisted.python.failure import Failure
|
from twisted.python.failure import Failure
|
||||||
import sys
|
import sys
|
||||||
from tlslite.api import *
|
from tlslite.api import *
|
||||||
|
|
||||||
s = open("./serverX509Cert.pem").read()
|
s = open("./serverX509Cert.pem").read()
|
||||||
x509 = X509()
|
x509 = X509()
|
||||||
x509.parse(s)
|
x509.parse(s)
|
||||||
certChain = X509CertChain([x509])
|
certChain = X509CertChain([x509])
|
||||||
|
|
||||||
s = open("./serverX509Key.pem").read()
|
s = open("./serverX509Key.pem").read()
|
||||||
privateKey = parsePEMKey(s, private=True)
|
privateKey = parsePEMKey(s, private=True)
|
||||||
|
|
||||||
verifierDB = VerifierDB("verifierDB")
|
verifierDB = VerifierDB("verifierDB")
|
||||||
verifierDB.open()
|
verifierDB.open()
|
||||||
|
|
||||||
class Echo(LineReceiver):
|
class Echo(LineReceiver):
|
||||||
def connectionMade(self):
|
def connectionMade(self):
|
||||||
self.transport.write("Welcome to the echo server!\\r\\n")
|
self.transport.write("Welcome to the echo server!\\r\\n")
|
||||||
|
|
||||||
def lineReceived(self, line):
|
def lineReceived(self, line):
|
||||||
self.transport.write(line + "\\r\\n")
|
self.transport.write(line + "\\r\\n")
|
||||||
|
|
||||||
class Echo1(Echo):
|
class Echo1(Echo):
|
||||||
def connectionMade(self):
|
def connectionMade(self):
|
||||||
if not self.transport.tlsStarted:
|
if not self.transport.tlsStarted:
|
||||||
self.transport.setServerHandshakeOp(certChain=certChain,
|
self.transport.setServerHandshakeOp(certChain=certChain,
|
||||||
privateKey=privateKey,
|
privateKey=privateKey,
|
||||||
verifierDB=verifierDB)
|
verifierDB=verifierDB)
|
||||||
else:
|
else:
|
||||||
Echo.connectionMade(self)
|
Echo.connectionMade(self)
|
||||||
|
|
||||||
def connectionLost(self, reason):
|
def connectionLost(self, reason):
|
||||||
pass #Handle any TLS exceptions here
|
pass #Handle any TLS exceptions here
|
||||||
|
|
||||||
class Echo2(Echo):
|
class Echo2(Echo):
|
||||||
def lineReceived(self, data):
|
def lineReceived(self, data):
|
||||||
if data == "STARTTLS":
|
if data == "STARTTLS":
|
||||||
self.transport.setServerHandshakeOp(certChain=certChain,
|
self.transport.setServerHandshakeOp(certChain=certChain,
|
||||||
privateKey=privateKey,
|
privateKey=privateKey,
|
||||||
verifierDB=verifierDB)
|
verifierDB=verifierDB)
|
||||||
else:
|
else:
|
||||||
Echo.lineReceived(self, data)
|
Echo.lineReceived(self, data)
|
||||||
|
|
||||||
def connectionLost(self, reason):
|
def connectionLost(self, reason):
|
||||||
pass #Handle any TLS exceptions here
|
pass #Handle any TLS exceptions here
|
||||||
|
|
||||||
factory = Factory()
|
factory = Factory()
|
||||||
factory.protocol = Echo1
|
factory.protocol = Echo1
|
||||||
#factory.protocol = Echo2
|
#factory.protocol = Echo2
|
||||||
|
|
||||||
wrappingFactory = WrappingFactory(factory)
|
wrappingFactory = WrappingFactory(factory)
|
||||||
wrappingFactory.protocol = TLSTwistedProtocolWrapper
|
wrappingFactory.protocol = TLSTwistedProtocolWrapper
|
||||||
|
|
||||||
log.startLogging(sys.stdout)
|
log.startLogging(sys.stdout)
|
||||||
reactor.listenTCP(1079, wrappingFactory)
|
reactor.listenTCP(1079, wrappingFactory)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
||||||
This class works as follows:
|
This class works as follows:
|
||||||
|
|
||||||
Data comes in and is given to the AsyncStateMachine for handling.
|
Data comes in and is given to the AsyncStateMachine for handling.
|
||||||
AsyncStateMachine will forward events to this class, and we'll
|
AsyncStateMachine will forward events to this class, and we'll
|
||||||
pass them on to the ProtocolHandler, which will proxy them to the
|
pass them on to the ProtocolHandler, which will proxy them to the
|
||||||
wrapped protocol. The wrapped protocol may then call back into
|
wrapped protocol. The wrapped protocol may then call back into
|
||||||
this class, and these calls will be proxied into the
|
this class, and these calls will be proxied into the
|
||||||
AsyncStateMachine.
|
AsyncStateMachine.
|
||||||
|
|
||||||
The call graph looks like this:
|
The call graph looks like this:
|
||||||
- self.dataReceived
|
- self.dataReceived
|
||||||
- AsyncStateMachine.inReadEvent
|
- AsyncStateMachine.inReadEvent
|
||||||
- self.out(Connect|Close|Read)Event
|
- self.out(Connect|Close|Read)Event
|
||||||
- ProtocolWrapper.(connectionMade|loseConnection|dataReceived)
|
- ProtocolWrapper.(connectionMade|loseConnection|dataReceived)
|
||||||
- self.(loseConnection|write|writeSequence)
|
- self.(loseConnection|write|writeSequence)
|
||||||
- AsyncStateMachine.(setCloseOp|setWriteOp)
|
- AsyncStateMachine.(setCloseOp|setWriteOp)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#WARNING: IF YOU COPY-AND-PASTE THE ABOVE CODE, BE SURE TO REMOVE
|
#WARNING: IF YOU COPY-AND-PASTE THE ABOVE CODE, BE SURE TO REMOVE
|
||||||
#THE EXTRA ESCAPING AROUND "\\r\\n"
|
#THE EXTRA ESCAPING AROUND "\\r\\n"
|
||||||
|
|
||||||
def __init__(self, factory, wrappedProtocol):
|
def __init__(self, factory, wrappedProtocol):
|
||||||
ProtocolWrapper.__init__(self, factory, wrappedProtocol)
|
ProtocolWrapper.__init__(self, factory, wrappedProtocol)
|
||||||
AsyncStateMachine.__init__(self)
|
AsyncStateMachine.__init__(self)
|
||||||
self.fakeSocket = _FakeSocket(self)
|
self.fakeSocket = _FakeSocket(self)
|
||||||
self.tlsConnection = TLSConnection(self.fakeSocket)
|
self.tlsConnection = TLSConnection(self.fakeSocket)
|
||||||
self.tlsStarted = False
|
self.tlsStarted = False
|
||||||
self.connectionLostCalled = False
|
self.connectionLostCalled = False
|
||||||
|
|
||||||
def connectionMade(self):
|
def connectionMade(self):
|
||||||
try:
|
try:
|
||||||
ProtocolWrapper.connectionMade(self)
|
ProtocolWrapper.connectionMade(self)
|
||||||
except TLSError, e:
|
except TLSError, e:
|
||||||
self.connectionLost(Failure(e))
|
self.connectionLost(Failure(e))
|
||||||
ProtocolWrapper.loseConnection(self)
|
ProtocolWrapper.loseConnection(self)
|
||||||
|
|
||||||
def dataReceived(self, data):
|
def dataReceived(self, data):
|
||||||
try:
|
try:
|
||||||
if not self.tlsStarted:
|
if not self.tlsStarted:
|
||||||
ProtocolWrapper.dataReceived(self, data)
|
ProtocolWrapper.dataReceived(self, data)
|
||||||
else:
|
else:
|
||||||
self.fakeSocket.data += data
|
self.fakeSocket.data += data
|
||||||
while self.fakeSocket.data:
|
while self.fakeSocket.data:
|
||||||
AsyncStateMachine.inReadEvent(self)
|
AsyncStateMachine.inReadEvent(self)
|
||||||
except TLSError, e:
|
except TLSError, e:
|
||||||
self.connectionLost(Failure(e))
|
self.connectionLost(Failure(e))
|
||||||
ProtocolWrapper.loseConnection(self)
|
ProtocolWrapper.loseConnection(self)
|
||||||
|
|
||||||
def connectionLost(self, reason):
|
def connectionLost(self, reason):
|
||||||
if not self.connectionLostCalled:
|
if not self.connectionLostCalled:
|
||||||
ProtocolWrapper.connectionLost(self, reason)
|
ProtocolWrapper.connectionLost(self, reason)
|
||||||
self.connectionLostCalled = True
|
self.connectionLostCalled = True
|
||||||
|
|
||||||
|
|
||||||
def outConnectEvent(self):
|
def outConnectEvent(self):
|
||||||
ProtocolWrapper.connectionMade(self)
|
ProtocolWrapper.connectionMade(self)
|
||||||
|
|
||||||
def outCloseEvent(self):
|
def outCloseEvent(self):
|
||||||
ProtocolWrapper.loseConnection(self)
|
ProtocolWrapper.loseConnection(self)
|
||||||
|
|
||||||
def outReadEvent(self, data):
|
def outReadEvent(self, data):
|
||||||
if data == "":
|
if data == "":
|
||||||
ProtocolWrapper.loseConnection(self)
|
ProtocolWrapper.loseConnection(self)
|
||||||
else:
|
else:
|
||||||
ProtocolWrapper.dataReceived(self, data)
|
ProtocolWrapper.dataReceived(self, data)
|
||||||
|
|
||||||
|
|
||||||
def setServerHandshakeOp(self, **args):
|
def setServerHandshakeOp(self, **args):
|
||||||
self.tlsStarted = True
|
self.tlsStarted = True
|
||||||
AsyncStateMachine.setServerHandshakeOp(self, **args)
|
AsyncStateMachine.setServerHandshakeOp(self, **args)
|
||||||
|
|
||||||
def loseConnection(self):
|
def loseConnection(self):
|
||||||
if not self.tlsStarted:
|
if not self.tlsStarted:
|
||||||
ProtocolWrapper.loseConnection(self)
|
ProtocolWrapper.loseConnection(self)
|
||||||
else:
|
else:
|
||||||
AsyncStateMachine.setCloseOp(self)
|
AsyncStateMachine.setCloseOp(self)
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data):
|
||||||
if not self.tlsStarted:
|
if not self.tlsStarted:
|
||||||
ProtocolWrapper.write(self, data)
|
ProtocolWrapper.write(self, data)
|
||||||
else:
|
else:
|
||||||
#Because of the FakeSocket, write operations are guaranteed to
|
#Because of the FakeSocket, write operations are guaranteed to
|
||||||
#terminate immediately.
|
#terminate immediately.
|
||||||
AsyncStateMachine.setWriteOp(self, data)
|
AsyncStateMachine.setWriteOp(self, data)
|
||||||
|
|
||||||
def writeSequence(self, seq):
|
def writeSequence(self, seq):
|
||||||
if not self.tlsStarted:
|
if not self.tlsStarted:
|
||||||
ProtocolWrapper.writeSequence(self, seq)
|
ProtocolWrapper.writeSequence(self, seq)
|
||||||
else:
|
else:
|
||||||
#Because of the FakeSocket, write operations are guaranteed to
|
#Because of the FakeSocket, write operations are guaranteed to
|
||||||
#terminate immediately.
|
#terminate immediately.
|
||||||
AsyncStateMachine.setWriteOp(self, "".join(seq))
|
AsyncStateMachine.setWriteOp(self, "".join(seq))
|
@ -1,5 +1,5 @@
|
|||||||
"""Pure-Python RSA implementation."""
|
"""Pure-Python RSA implementation."""
|
||||||
|
|
||||||
from cryptomath import *
|
from cryptomath import *
|
||||||
import xmltools
|
import xmltools
|
||||||
from ASN1Parser import ASN1Parser
|
from ASN1Parser import ASN1Parser
|
||||||
@ -8,7 +8,7 @@ from RSAKey import *
|
|||||||
class Python_RSAKey(RSAKey):
|
class Python_RSAKey(RSAKey):
|
||||||
def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0):
|
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):
|
if (n and not e) or (e and not n):
|
||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
self.n = n
|
self.n = n
|
||||||
self.e = e
|
self.e = e
|
||||||
self.d = d
|
self.d = d
|
||||||
@ -122,61 +122,61 @@ class Python_RSAKey(RSAKey):
|
|||||||
bytes = base64ToBytes(s)
|
bytes = base64ToBytes(s)
|
||||||
return Python_RSAKey._parsePKCS8(bytes)
|
return Python_RSAKey._parsePKCS8(bytes)
|
||||||
else:
|
else:
|
||||||
start = s.find("-----BEGIN RSA PRIVATE KEY-----")
|
start = s.find("-----BEGIN RSA PRIVATE KEY-----")
|
||||||
if start != -1:
|
if start != -1:
|
||||||
end = s.find("-----END RSA PRIVATE KEY-----")
|
end = s.find("-----END RSA PRIVATE KEY-----")
|
||||||
if end == -1:
|
if end == -1:
|
||||||
raise SyntaxError("Missing PEM Postfix")
|
raise SyntaxError("Missing PEM Postfix")
|
||||||
s = s[start+len("-----BEGIN RSA PRIVATE KEY -----") : end]
|
s = s[start+len("-----BEGIN RSA PRIVATE KEY -----") : end]
|
||||||
bytes = base64ToBytes(s)
|
bytes = base64ToBytes(s)
|
||||||
return Python_RSAKey._parseSSLeay(bytes)
|
return Python_RSAKey._parseSSLeay(bytes)
|
||||||
raise SyntaxError("Missing PEM Prefix")
|
raise SyntaxError("Missing PEM Prefix")
|
||||||
parsePEM = staticmethod(parsePEM)
|
parsePEM = staticmethod(parsePEM)
|
||||||
|
|
||||||
def parseXML(s):
|
def parseXML(s):
|
||||||
element = xmltools.parseAndStripWhitespace(s)
|
element = xmltools.parseAndStripWhitespace(s)
|
||||||
return Python_RSAKey._parseXML(element)
|
return Python_RSAKey._parseXML(element)
|
||||||
parseXML = staticmethod(parseXML)
|
parseXML = staticmethod(parseXML)
|
||||||
|
|
||||||
def _parsePKCS8(bytes):
|
def _parsePKCS8(bytes):
|
||||||
p = ASN1Parser(bytes)
|
p = ASN1Parser(bytes)
|
||||||
|
|
||||||
version = p.getChild(0).value[0]
|
version = p.getChild(0).value[0]
|
||||||
if version != 0:
|
if version != 0:
|
||||||
raise SyntaxError("Unrecognized PKCS8 version")
|
raise SyntaxError("Unrecognized PKCS8 version")
|
||||||
|
|
||||||
rsaOID = p.getChild(1).value
|
rsaOID = p.getChild(1).value
|
||||||
if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
|
if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
|
||||||
raise SyntaxError("Unrecognized AlgorithmIdentifier")
|
raise SyntaxError("Unrecognized AlgorithmIdentifier")
|
||||||
|
|
||||||
#Get the privateKey
|
#Get the privateKey
|
||||||
privateKeyP = p.getChild(2)
|
privateKeyP = p.getChild(2)
|
||||||
|
|
||||||
#Adjust for OCTET STRING encapsulation
|
#Adjust for OCTET STRING encapsulation
|
||||||
privateKeyP = ASN1Parser(privateKeyP.value)
|
privateKeyP = ASN1Parser(privateKeyP.value)
|
||||||
|
|
||||||
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
|
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
|
||||||
_parsePKCS8 = staticmethod(_parsePKCS8)
|
_parsePKCS8 = staticmethod(_parsePKCS8)
|
||||||
|
|
||||||
def _parseSSLeay(bytes):
|
def _parseSSLeay(bytes):
|
||||||
privateKeyP = ASN1Parser(bytes)
|
privateKeyP = ASN1Parser(bytes)
|
||||||
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
|
return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
|
||||||
_parseSSLeay = staticmethod(_parseSSLeay)
|
_parseSSLeay = staticmethod(_parseSSLeay)
|
||||||
|
|
||||||
def _parseASN1PrivateKey(privateKeyP):
|
def _parseASN1PrivateKey(privateKeyP):
|
||||||
version = privateKeyP.getChild(0).value[0]
|
version = privateKeyP.getChild(0).value[0]
|
||||||
if version != 0:
|
if version != 0:
|
||||||
raise SyntaxError("Unrecognized RSAPrivateKey version")
|
raise SyntaxError("Unrecognized RSAPrivateKey version")
|
||||||
n = bytesToNumber(privateKeyP.getChild(1).value)
|
n = bytesToNumber(privateKeyP.getChild(1).value)
|
||||||
e = bytesToNumber(privateKeyP.getChild(2).value)
|
e = bytesToNumber(privateKeyP.getChild(2).value)
|
||||||
d = bytesToNumber(privateKeyP.getChild(3).value)
|
d = bytesToNumber(privateKeyP.getChild(3).value)
|
||||||
p = bytesToNumber(privateKeyP.getChild(4).value)
|
p = bytesToNumber(privateKeyP.getChild(4).value)
|
||||||
q = bytesToNumber(privateKeyP.getChild(5).value)
|
q = bytesToNumber(privateKeyP.getChild(5).value)
|
||||||
dP = bytesToNumber(privateKeyP.getChild(6).value)
|
dP = bytesToNumber(privateKeyP.getChild(6).value)
|
||||||
dQ = bytesToNumber(privateKeyP.getChild(7).value)
|
dQ = bytesToNumber(privateKeyP.getChild(7).value)
|
||||||
qInv = bytesToNumber(privateKeyP.getChild(8).value)
|
qInv = bytesToNumber(privateKeyP.getChild(8).value)
|
||||||
return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
|
return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
|
||||||
_parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey)
|
_parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey)
|
||||||
|
|
||||||
def _parseXML(element):
|
def _parseXML(element):
|
||||||
try:
|
try:
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user