def got_cancel(self, message): i = toint(message[1:5]) if i >= self.torrent.numpieces: self.fatal_error("Piece index out of range") return if self.upload: self.upload.got_cancel(i, toint(message[5:9]), toint(message[9:]))
def got_piece(self, message): i = toint(message[1:5]) if i >= self.torrent.numpieces: self.fatal_error("Piece index out of range") return if self.download.got_piece(i, toint(message[5:9]), message[9:]): for ep in self.torrent.active_streams: ep.send_have(i)
def _read_messages(self): yield 4 l = toint(self._message) yield l action = self._message yield 4 l = toint(self._message) yield l data = self._message self.callback(action, data)
def got_have(self, message): i = toint(message[1:]) if i >= self.torrent.numpieces: log.error("Piece index out of range") self.fatal_error() return self.download.got_have(i)
def got_partial(self, message): p_remain = toint(message[1:5]) self.partial_recv += message[5:] if len(self.partial_recv) > self.neighbor.config['max_message_length']: log.error("Received message longer than max length") return if len(message[5:]) == p_remain: self.got_message(self.partial_recv) self.partial_recv = ''
def _read_messages(self): """ Read messages off the line and relay or process them depending on connection type """ while True: yield 2 # Stream ID stream = toint(self._message) handler = self.get_stream_handler(stream) self._message = '' yield 4 # Message Length l = toint(self._message) if l > self.config['max_message_length']: log.warning("Received message longer than max length") # return self._message = '' yield l # Payload if handler == self: # Grab the stream ID to initialize the received stream self.incoming_stream_id = stream handler.got_message(self._message) self._message = ''
class Certificate: def __init__(self, loc=None, secure=False, tracker=False): self.secure = secure self.tracker = tracker if None in (global_cryptodir, global_randfile): raise CryptoError('Crypto not initialized, call initCrypto first') self.keyfile = os.path.join(global_cryptodir, '%s-key.pem' % (loc)) self.certfile = os.path.join(global_cryptodir, '%s-cert.pem' % (loc)) if not (os.path.exists(self.certfile) and os.path.exists(self.keyfile)): if self.tracker: hostname = self._gethostname() else: hostname = 'localhost' self._create(hostname=hostname) else: self._load() def _gethostname(self): from socket import gethostname hostname = gethostname() tmpname = raw_input("Please enter the tracker's hostname " \ "for the SSL certificate (default: %s): " % hostname) if tmpname.strip(" "): hostname = tmpname return hostname def _load(self): """Attempts to load the certificate and key from self.certfile and self.keyfile, Generates the certificate and key if they don't exist""" if not self.secure: self.rsakey = RSA.load_key(self.keyfile, m2util.no_passphrase_callback) else: # Allow 3 attempts before quitting i = 0 while i < 3: try: self.rsakey = RSA.load_key(self.keyfile) break except RSA.RSAError: i += 1 else: log.warning("\nInvalid password entered, exiting.") sys.exit() self.cert = X509.load_cert(self.certfile) @Anomos.Crypto.use_rand_file def _create(self, hostname='localhost'): # Make the RSA key self.rsakey = RSA.gen_key(2048, m2.RSA_F4) if self.secure: # Save the key, AES256-CBC encrypted self.rsakey.save_key(self.keyfile, 'aes_256_cbc') else: # Save the key unencrypted. self.rsakey.save_key(self.keyfile, None, callback=m2util.no_passphrase_callback) # Make the public key pkey = EVP.PKey() pkey.assign_rsa(self.rsakey, 0) # Generate the certificate self.cert = X509.X509() self.cert.set_serial_number(long(bttime())) self.cert.set_version(0x2) self.cert.set_pubkey(pkey) # Set the name on the certificate name = X509.X509_Name() name.CN = hostname self.cert.set_subject(name) self.cert.set_issuer(name) # Set the period of time the cert is valid for (5 years from issue) notBefore = m2.x509_get_not_before(self.cert.x509) notAfter = m2.x509_get_not_after(self.cert.x509) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, 60 * 60 * 24 * 365 * 5) # Sign the certificate self.cert.sign(pkey, 'sha1') # Save it self.cert.save_pem(self.certfile) def get_ctx(self, allow_unknown_ca=False, req_peer_cert=True, session=None): ctx = SSL.Context("sslv23") # Set certificate and private key m2.ssl_ctx_use_x509(ctx.ctx, self.cert.x509) m2.ssl_ctx_use_rsa_privkey(ctx.ctx, self.rsakey.rsa) if not m2.ssl_ctx_check_privkey(ctx.ctx): raise CryptoError('public/private key mismatch') # Ciphers/Options ctx.set_cipher_list(CIPHER_SET) ctx.set_options(CTX_OPTIONS) # CA settings cloc = os.path.join(global_certpath, 'cacert.root.pem') if ctx.load_verify_locations(cafile=cloc) != 1: log.error("Problem loading CA certificates") raise CryptoError('CA certificates not loaded') # Verification cb = mk_verify_cb(allow_unknown_ca=allow_unknown_ca) CTX_V_FLAGS = SSL.verify_peer if req_peer_cert: CTX_V_FLAGS |= SSL.verify_fail_if_no_peer_cert ctx.set_verify(CTX_V_FLAGS, 3, cb) # Session if session: ctx.set_session_id_ctx(session) return ctx def fingerprint(self): md = EVP.MessageDigest("sha1") md.update(self.rsakey.pub()[1]) return b2a_hex(md.digest()) def decrypt(self, data): """ Decrypts data encrypted with this public key @param data: The data, padding and all, to be decrypted @type data: string @raise CryptoError: Priv. decrypt fail or Bad Checksum @return: tuple (decrypted message, padding) if returnpad is true, string otherwise @rtype: tuple """ rsa_keysize_B = len(self.rsakey) / 8 # Decrypt the session key and IV with our private key try: tmpsk = self.rsakey.private_decrypt(data[:rsa_keysize_B], RSA.pkcs1_oaep_padding) except RSA.RSAError, e: raise CryptoError("A decryption error occurred: %s" % str(e)) sk = tmpsk[:32] # Session Key iv = tmpsk[32:] # IV sessionkey = Anomos.Crypto.AESKey(sk, iv) # Decrypt the rest of the message with the session key content = sessionkey.decrypt(data[rsa_keysize_B:]) msglen = content[:4] # first 4 bytes msglen_int = toint(msglen) pos = 4 message = content[pos:pos + msglen_int] # next msglen_int bytes pos += msglen_int givenchksum = content[pos:pos + 20] # next 20 bytes pos += 20 md = EVP.MessageDigest("sha1") md.update(msglen + message) mychksum = md.digest() if givenchksum != mychksum: raise CryptoError( "Bad Checksum - Data may have been tampered with") return (message, content[pos:])