def check_and_demangle_item(item): """Return demangled item if it is a valid mangled item, otherwise throw an exception (not necessarily of class error.Error). Ensures: either an exception is thrown or ret is a dictionary whose keys include 'type'.""" # note: not sure if this ough to be here... import crypto.RSA import hash import safe_pickle item_type = item['type'] if item_type == 'identity offline demangled': raise error.Error('impostor') elif item_type == 'identity offline': demangle = safe_pickle.loads(item['package']) if not crypto.RSA.construct(demangle['key']).verify( hash.hash_of(item['package']),item['signature']): raise error.Error('bad signature') demangle['type'] = 'identity offline demangled' return demangle else: return item
def decrypt(self, crypt): # Todo: catch errors self.lock.acquire() try: encrypted_key, encrypted_text = crypt key = self.key.decrypt((encrypted_key,)) while len(key) < 16: key = chr(0)+key decryptor = crypto.rijndael.rijndael(key, 16) text = decryptor.decrypt_cbc(encrypted_text) return safe_pickle.loads(text) finally: self.lock.release()
def handle(self, request, address,call_id): check.check_matches(request, (types.StringType,)) #=@R34 check.check_is_af_inet_address(address) #=@R31 self.lock.acquire() try: if request[0] == 'chat look': return (not self.quiet, self.activity) if request[0] in ['chat message 2']: unpacked = safe_pickle.loads(request[1]) # TODO check unpacked against template # TODO don't unpack twice (here and in receive task) sender = unpacked['from'] recipients = unpacked['to'] for recipient in recipients: if recipient[0] == self.app.name_server.public_key_name: break if recipient[2][:1] == '#' and \ self.channels.is_listening_to(recipient[2]) and \ sender[0] != self.app.name_server.public_key_name: break else: return None if not self.repeated(address,call_id): if self.quiet: new_item = (request, address, time.time()) check.check_matches(new_item, unread_message_list_item_tmpl) # Proof: @R34,@R31, and not having modified request or # address, and the relevant types being immutable # (partly by @E11). time.time() returns float. # Relevance: @R.I15. self.unread_message_list.append(new_item) self.set_prompt() del new_item else: self.receive(request,address,self.quiet,time.time()) # Proof of @R33: @R31; deep immutability by @E11. # Proof of @R35: time.time() returns float. return (not self.quiet, self.activity) finally: self.lock.release()
def receive(self, request, address, quiet, send_time, add_to_history=1): """send_time should be as if from time.time() (i.e. a float expressing seconds since the local machine's epoch) rather than the standardized timestamps sent over the network (i.e. a long expressing seconds since the Unix epoch of 1970).""" # TODO: more checking of message format # TODO: search for people not in acq list check.check_is_opt_address(address) #=@R33 fixme callers check.check_has_type(send_time, types.FloatType) #=@R35 fixme callers # fixme: should probably require that request be a tuple with 5+ elems. if 1: if not self.is_visible(): self.n_unseen_messages = self.n_unseen_messages + 1 if self.n_unseen_messages == 1: title = _('1 unseen message') else: title = _('%d unseen messages') % self.n_unseen_messages self.app.set_title(title) if request[0] == 'chat message 2': package = safe_pickle.loads(request[1]) text = package['text'] augmentation = package.get('aug') has_attachment = package.has_key('attach') attachment = package.get('attach') sender_key_name, sender_name = package['from'] recipients = package['to'] verify_text = request[1] verify_sig = request[2] else: # Legacy message format text = request[3] augmentation = None has_attachment = (len(request) == 6) if has_attachment: attachment = safe_pickle.loads(request[4]) recipients = request[2] if type(request[1]) == type(()): sender_key_name = request[1][0] sender_name = request[1][1] else: # Used not to send username with key name sender_key_name = request[1] sender_name = 'unknown' if has_attachment: verify_text = request[3].encode('utf8')+request[4] verify_sig = request[5] else: verify_text = request[3] verify_sig = request[4] if not augmentation: augmentation = chr(128) * len(text) self.show_received_message(sender_name,sender_key_name,address,recipients, text,verify_text,verify_sig,quiet, send_time,augmentation,has_attachment,attachment) #except error.Error: # self.show(_('Bad message received from ') + repr(address) + '\n') if add_to_history: self.lock.acquire() try: new_item = (request, send_time) check.check_matches(new_item, incoming_message_history_item_tmpl) # Proof: @R35, immutability of float, send_time not reassigned # in this function. # Relevance: @I16. self.incoming_message_history.append(new_item) while len(self.incoming_message_history) > settings.incoming_message_history_size: del self.incoming_message_history[0] finally: self.lock.release()
def gossip_fetch_thread(self,acq): self.fetch_threads+=1 if not self.running: self.fetch_threads-=1 return if acq.distance != None: #acq.start_watching(self.node, 1) acq.lock.acquire() online = acq.online address = acq.address distance = acq.distance acq.lock.release() if distance == None or not online: self.fetch_threads-=1 return pos = 0 fetch_timeout = node.make_timeout(settings.gossip_fetch_time) while not node.is_timed_out(fetch_timeout): try: ticket, template, wait = self.node.call(address,('gossip list',pos,pos+20)) if wait: yield 'call',(self.node,ticket) result = self.node.get_reply(ticket,template) if not check.matches(result, [(types.IntType, 'any', 'any')]): node.bad_peer(address, _("Bad reply to 'gossip list': ") + `result`) break if len(result) == 0: break all_ok = 1 # effic: sort self.gossip, sort the returned results, # to speed up searches for signatures. However, I # haven't yet seen gossip_fetch_task come up in # profiles. for item in result: already_there = 0 for wodge in self.gossip: if wodge.signature == item[2]: #if wodge.distance(self.app.name_server) > from_fixed(item[0])+distance: # # TODO: What to do with unit_decay_time? # wodge.initial_distance = from_fixed(item[0])+distance # wodge.initial_time = time.time() wodge.opinions[acq.name] = from_fixed(item[0]) - wodge.decay() already_there = 1 break if already_there: continue try: ticket, template, wait = self.node.call( address,('gossip get',item[2])) if wait: yield 'call',(self.node,ticket) string = self.node.get_reply(ticket, template) wodgewodge = safe_pickle.loads(string) except error.Error: all_ok = 0 break #TODO: Confirm signature of known people wodge = Wodge({ 'wodge': wodgewodge, 'string': string, 'signature': item[2], 'initial_time': time.time(), 'initial_distance': None, #'initial_distance': from_fixed(item[0]) + distance 'unit_decay_time': item[1], 'opinions': { acq.name : from_fixed(item[0]) }, 'collapsed': 0}) if not self.insert_wodge(wodge): all_ok = 0 break if not all_ok: break pos = pos + 18 except error.Error: break self.fetch_threads-=1