def x509_init(self): """ Set of X.509 certificate and read known_clients file. """ pemfile = os.path.join(xmpp.config.cachedir, self.client.appname + '.pem') if not os.path.isfile(pemfile): # FIXME: hide output and check for openssl os.system("openssl req -subj '/CN=%s' -x509 -nodes -days 365 -newkey "\ "rsa:1024 -keyout %s -out %s" % (self.client.appname, pemfile, pemfile)) self.x509_keyinfo = KeyInfo() self.x509_keyinfo.load_pemfile(pemfile) self.known_clients_x509 = [] known = os.path.join(xmpp.config.cachedir, 'known_clients') if os.path.isfile(known): for line in open(known).readlines(): key = KeyInfo() key.certificate.base64 = line.split(' ')[1] self.known_clients_x509.append(key.certificate)
class Credentials(object): """ Credentials for TLS authentication. As a default X.509 certificates from known_clients are read and openssl is used to create a client certificate. """ def __init__(self, client): self.client = client self.x509_init() def x509_init(self): """ Set of X.509 certificate and read known_clients file. """ pemfile = os.path.join(xmpp.config.cachedir, self.client.appname + '.pem') if not os.path.isfile(pemfile): # FIXME: hide output and check for openssl os.system("openssl req -subj '/CN=%s' -x509 -nodes -days 365 -newkey "\ "rsa:1024 -keyout %s -out %s" % (self.client.appname, pemfile, pemfile)) self.x509_keyinfo = KeyInfo() self.x509_keyinfo.load_pemfile(pemfile) self.known_clients_x509 = [] known = os.path.join(xmpp.config.cachedir, 'known_clients') if os.path.isfile(known): for line in open(known).readlines(): key = KeyInfo() key.certificate.base64 = line.split(' ')[1] self.known_clients_x509.append(key.certificate) def x509_supported(self): """ Return if X.509 certificates are supported. Default is true. """ return True def x509_check(self, certificate): """ Check the remote certificate. The default behaviour is only to allow known clients. If the certificate is ok, return True. """ return certificate.validate(self.known_clients_x509) def srp_supported(self): """ Return if SRP is supported """ return False def srp_get_password(self, remote): """ Function to return the SRP password. This can be a coroutine if needed. The function must be implemented by an inherting class and srp_supported() should return True in that case. """ raise NotImplementedError def handshake_initiator(self): """ Handshake part 1: initiator offer """ security = xmpp.Element('security', NS_XTLS) if self.x509_supported(): security.add_child('fingerprint', algo='sha1', content=self.x509_keyinfo.fingerprint) security.add_child('method', name='x509') if self.srp_supported(): security.add_child('method', name='srp') return security def handshake_responder(self, offer): """ Handshake part 2: responder offer """ security = xmpp.Element('security', NS_XTLS) for method in offer.get_children('method'): if method.name == 'x509' and self.x509_supported() and offer.fingerprint: fingerprint = offer.fingerprint.content for known in self.known_clients_x509: if fingerprint == known.fingerprint: security.add_child('fingerprint', algo='sha1', content=self.x509_keyinfo.fingerprint) security.add_child('method', name='x509') break if method.name == 'srp' and self.srp_supported(): security.add_child('method', name='srp') return security def handshake_finalize(self, offer): """ Handshake part 3: initiator final methods """ security = xmpp.Element('security', NS_XTLS) for m in offer.get_children('method'): if m.name == 'x509' and self.x509_supported() and offer.fingerprint: fingerprint = offer.fingerprint.content for known in self.known_clients_x509: if fingerprint == known.fingerprint: security.add_child('method', name='x509') return security for m in offer.get_children('method'): if m.name == 'srp' and self.srp_supported(): security.add_child('method', name='srp') return security return None @classmethod def install(cls): Client.credentials = cls