def register_customer_key(customer_public_key_id, customer_public_key): """ Check/refresh/store customer public key locally. """ if not customer_public_key_id or not customer_public_key: lg.warn('customer public key was not provided in the request') return False customer_public_key_id = my_keys.latest_key_id(customer_public_key_id) if my_keys.is_key_registered(customer_public_key_id): known_customer_public_key = my_keys.get_public_key_raw( customer_public_key_id) if known_customer_public_key == customer_public_key: lg.info( 'customer public key %r already known and public key is matching' % customer_public_key_id) else: lg.warn('rewriting customer public key %r' % customer_public_key_id) my_keys.erase_key(customer_public_key_id) key_id, key_object = my_keys.read_key_info(customer_public_key) if not my_keys.register_key(key_id, key_object): lg.err('failed to register customer public key: %r' % customer_public_key_id) return False lg.info('new customer public key registered: %r' % customer_public_key_id) return True
def on_key_received(newpacket, info, status, error_message): block = encrypted.Unserialize(newpacket.Payload) if block is None: lg.out( 2, 'key_ring.on_key_received ERROR reading data from %s' % newpacket.RemoteID) return False try: key_data = block.Data() key_json = json.loads(key_data) key_id = key_json['key_id'] key_id, key_object = my_keys.read_key_info(key_json) if key_object.isPublic(): # received key is a public key if my_keys.is_key_registered(key_id): # but we already have a key with that ID if my_keys.is_key_private(key_id): # we should not overwrite existing private key raise Exception('private key already registered') if my_keys.get_public_key_raw( key_id, 'openssh') != key_object.toString('openssh'): # and we should not overwrite existing public key as well raise Exception( 'another key already registered with that ID') p2p_service.SendAck(newpacket) lg.warn('received existing public key: %s, skip' % key_id) return True if not my_keys.register_key(key_id, key_object): raise Exception('key register failed') else: lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) if _Debug: lg.info( 'received and stored locally a new key %s, include_private=%s' % (key_id, key_json.get('include_private'))) return True # received key is a private key if my_keys.is_key_registered(key_id): # check if we already have that key if my_keys.is_key_private(key_id): # we have already private key with same ID!!! if my_keys.get_private_key_raw( key_id, 'openssh') != key_object.toString('openssh'): # and this is a new private key : we should not overwrite! raise Exception('private key already registered') # this is the same private key p2p_service.SendAck(newpacket) lg.warn('received existing private key: %s, skip' % key_id) return True # but we have a public key with same ID if my_keys.get_public_key_raw( key_id, 'openssh') != key_object.public().toString('openssh'): # and we should not overwrite existing public key as well raise Exception('another key already registered with that ID') lg.info('erasing public key %s' % key_id) my_keys.erase_key(key_id) if not my_keys.register_key(key_id, key_object): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True # no private key with given ID was registered if not my_keys.register_key(key_id, key_object): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True except Exception as exc: lg.exc() p2p_service.SendFail(newpacket, str(exc)) return False
def request(self, json_payload, newpacket, info): from twisted.internet import reactor # @UnresolvedImport from logs import lg from main import events from crypt import my_keys from p2p import p2p_service from contacts import contactsdb from storage import accounting from userid import global_id customer_idurl = newpacket.OwnerID customer_id = global_id.UrlToGlobalID(customer_idurl) bytes_for_customer = 0 try: bytes_for_customer = int(json_payload['needed_bytes']) except: lg.warn("wrong payload" % newpacket.Payload) return p2p_service.SendFail(newpacket, 'wrong payload') try: customer_public_key = json_payload['customer_public_key'] customer_public_key_id = customer_public_key['key_id'] except: customer_public_key = None customer_public_key_id = None data_owner_idurl = None target_customer_idurl = None family_position = json_payload.get('position') ecc_map = json_payload.get('ecc_map') family_snapshot = json_payload.get('family_snapshot') key_id = json_payload.get('key_id') target_customer_id = json_payload.get('customer_id') if key_id: # this is a request from external user to access shared data stored by one of my customers # this is "second" customer requesting data from "first" customer if not key_id or not my_keys.is_valid_key_id(key_id): lg.warn('missed or invalid key id') return p2p_service.SendFail(newpacket, 'invalid key id') target_customer_idurl = global_id.GlobalUserToIDURL( target_customer_id) if not contactsdb.is_customer(target_customer_idurl): lg.warn("target user %s is not a customer" % target_customer_id) return p2p_service.SendFail(newpacket, 'not a customer') if target_customer_idurl == customer_idurl: lg.warn('customer %s requesting shared access to own files' % customer_idurl) return p2p_service.SendFail(newpacket, 'invalid case') if not my_keys.is_key_registered(key_id): lg.warn('key not registered: %s' % key_id) p2p_service.SendFail(newpacket, 'key not registered') return False data_owner_idurl = my_keys.split_key_id(key_id)[1] if data_owner_idurl != target_customer_idurl and data_owner_idurl != customer_idurl: # pretty complex scenario: # external customer requesting access to data which belongs not to that customer # this is "third" customer accessing data belongs to "second" customer # TODO: for now just stop it lg.warn( 'under construction, key_id=%s customer_idurl=%s target_customer_idurl=%s' % ( key_id, customer_idurl, target_customer_idurl, )) p2p_service.SendFail(newpacket, 'under construction') return False # do not create connection with that customer, only accept the request lg.info( 'external customer %s requested access to shared data at %s' % ( customer_id, key_id, )) return p2p_service.SendAck(newpacket, 'accepted') # key_id is not present in the request: # this is a request to connect new customer (or reconnect existing one) to that supplier if not bytes_for_customer or bytes_for_customer < 0: lg.warn("wrong payload : %s" % newpacket.Payload) return p2p_service.SendFail(newpacket, 'wrong storage value') current_customers = contactsdb.customers() if accounting.check_create_customers_quotas(): lg.out(6, 'service_supplier.request created a new space file') space_dict = accounting.read_customers_quotas() try: free_bytes = int(space_dict[b'free']) except: lg.exc() return p2p_service.SendFail(newpacket, 'broken space file') if (customer_idurl not in current_customers and customer_idurl in list(space_dict.keys())): lg.warn("broken space file") return p2p_service.SendFail(newpacket, 'broken space file') if (customer_idurl in current_customers and customer_idurl not in list(space_dict.keys())): lg.warn("broken customers file") return p2p_service.SendFail(newpacket, 'broken customers file') if customer_idurl in current_customers: free_bytes += int(space_dict.get(customer_idurl, 0)) space_dict[b'free'] = free_bytes current_customers.remove(customer_idurl) space_dict.pop(customer_idurl) new_customer = False else: new_customer = True lg.out( 8, ' new_customer=%s current_allocated_bytes=%s' % ( new_customer, space_dict.get(customer_idurl), )) from supplier import local_tester if free_bytes <= bytes_for_customer: contactsdb.update_customers(current_customers) contactsdb.remove_customer_meta_info(customer_idurl) contactsdb.save_customers() accounting.write_customers_quotas(space_dict) if customer_public_key_id: my_keys.erase_key(customer_public_key_id) reactor.callLater( 0, local_tester.TestUpdateCustomers) # @UndefinedVariable if new_customer: lg.out( 8, " NEW CUSTOMER: DENIED !!!!!!!!!!! not enough space available" ) events.send('new-customer-denied', dict(idurl=customer_idurl)) else: lg.out( 8, " OLD CUSTOMER: DENIED !!!!!!!!!!! not enough space available" ) events.send('existing-customer-denied', dict(idurl=customer_idurl)) return p2p_service.SendAck(newpacket, 'deny') space_dict[b'free'] = free_bytes - bytes_for_customer current_customers.append(customer_idurl) space_dict[customer_idurl] = bytes_for_customer contactsdb.update_customers(current_customers) contactsdb.save_customers() contactsdb.add_customer_meta_info( customer_idurl, { 'ecc_map': ecc_map, 'position': family_position, 'family_snapshot': family_snapshot, }) accounting.write_customers_quotas(space_dict) if customer_public_key_id: my_keys.erase_key(customer_public_key_id) try: if not my_keys.is_key_registered(customer_public_key_id): key_id, key_object = my_keys.read_key_info( customer_public_key) if not my_keys.register_key(key_id, key_object): lg.err('failed to register customer public key') except: lg.exc() else: lg.warn('customer public key was not provided in the request') reactor.callLater( 0, local_tester.TestUpdateCustomers) # @UndefinedVariable if new_customer: lg.out( 8, " NEW CUSTOMER: ACCEPTED %s family_position=%s ecc_map=%s allocated_bytes=%s" % (customer_idurl, family_position, ecc_map, bytes_for_customer)) lg.out( 8, " family_snapshot=%r !!!!!!!!!!!!!!" % family_snapshot, ) events.send( 'new-customer-accepted', dict( idurl=customer_idurl, allocated_bytes=bytes_for_customer, ecc_map=ecc_map, position=family_position, family_snapshot=family_snapshot, key_id=customer_public_key_id, )) else: lg.out( 8, " OLD CUSTOMER: ACCEPTED %s family_position=%s ecc_map=%s allocated_bytes=%s" % (customer_idurl, family_position, ecc_map, bytes_for_customer)) lg.out( 8, " family_snapshot=%r !!!!!!!!!!!!!!" % family_snapshot) events.send( 'existing-customer-accepted', dict( idurl=customer_idurl, allocated_bytes=bytes_for_customer, ecc_map=ecc_map, position=family_position, key_id=customer_public_key_id, family_snapshot=family_snapshot, )) return p2p_service.SendAck(newpacket, 'accepted')
def on_key_received(newpacket, info, status, error_message): """ Callback will be executed when I receive a new key from one remote user. """ block = encrypted.Unserialize(newpacket.Payload) if block is None: lg.err('failed reading key info from %s' % newpacket.RemoteID) return False try: key_data = block.Data() key_json = serialization.BytesToDict(key_data, keys_to_text=True, values_to_text=True) key_id = key_json['key_id'] key_label = key_json.get('label', '') key_id, key_object = my_keys.read_key_info(key_json) if key_object.isSigned(): if not my_keys.verify_key_info_signature(key_json): raise Exception('key signature verification failed') if key_object.isPublic(): # received key is a public key if my_keys.is_key_registered(key_id): # but we already have a key with that ID if my_keys.is_key_private(key_id): # we should not overwrite existing private key raise Exception('private key already registered') if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): # and we should not overwrite existing public key as well raise Exception('another public key already registered with that ID and it is not matching') p2p_service.SendAck(newpacket) lg.warn('received existing public key: %s, skip' % key_id) return True if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') else: lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) if _Debug: lg.info('received and stored locally a new key %s, include_private=%s' % (key_id, key_json.get('include_private'))) return True # received key is a private key if my_keys.is_key_registered(key_id): # check if we already have that key if my_keys.is_key_private(key_id): # we have already private key with same ID!!! if my_keys.get_private_key_raw(key_id) != key_object.toPrivateString(): # and this is a new private key : we should not overwrite! raise Exception('private key already registered and it is not matching') # this is the same private key p2p_service.SendAck(newpacket) lg.warn('received existing private key: %s, skip' % key_id) return True # but we have a public key with same ID already if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): # and we should not overwrite existing public key as well raise Exception('another public key already registered with that ID and it is not matching with private key') lg.info('erasing public key %s' % key_id) my_keys.erase_key(key_id) if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True # no private key with given ID was registered if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True except Exception as exc: lg.exc() p2p_service.SendFail(newpacket, strng.to_text(exc)) return False
def on_key_received(newpacket, info, status, error_message): """ Callback will be executed when I receive a new key from one remote user. """ block = encrypted.Unserialize(newpacket.Payload) if block is None: lg.err('failed reading key info from %s' % newpacket.RemoteID) return False try: key_data = block.Data() key_json = serialization.BytesToDict(key_data, keys_to_text=True, values_to_text=True) # key_id = strng.to_text(key_json['key_id']) key_label = strng.to_text(key_json.get('label', '')) key_id, key_object = my_keys.read_key_info(key_json) if key_object.isSigned(): if not my_keys.verify_key_info_signature(key_json): raise Exception('received key signature verification failed: %r' % key_json) # TODO: must also compare "signature_pubkey" with pub key of the creator of the key! if key_object.isPublic(): # received key is a public key if my_keys.is_key_registered(key_id): # but we already have a key with that ID if my_keys.is_key_private(key_id): # we should not overwrite existing private key # TODO: check other scenarios raise Exception('private key already registered with %r' % key_id) if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): my_keys.erase_key(key_id) if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') else: lg.info('replaced existing key %s, is_public=%s' % (key_id, key_object.isPublic())) # normally should not overwrite existing public key # TODO: look more if need to add some extra checks # for example need to be able to overwrite or erase remotely some keys to cleanup # raise Exception('another public key already registered with %r and new key is not matching' % key_id) p2p_service.SendAck(newpacket) lg.warn('received existing public key: %s, skip' % key_id) return True if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') else: lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) if _Debug: lg.info('received and stored locally a new key %s, include_private=%s' % (key_id, key_json.get('include_private'))) return True # received key is a private key if my_keys.is_key_registered(key_id): # check if we already have that key if my_keys.is_key_private(key_id): # we have already private key with same ID!!! if my_keys.get_private_key_raw(key_id) != key_object.toPrivateString(): # and this is a new private key : we should not overwrite! raise Exception('private key already registered and it is not matching with received copy') # this is the same private key p2p_service.SendAck(newpacket) lg.warn('received again an exact copy of already existing private key: %s, skip' % key_id) return True # but we have a public key with same ID already # if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): # # and we should not overwrite existing public key as well # raise Exception('another public key already registered with that ID and it is not matching with private key') lg.info('erasing public key %s' % key_id) my_keys.erase_key(key_id) if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True # no private key with given ID was registered if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True except Exception as exc: lg.exc() p2p_service.SendFail(newpacket, strng.to_text(exc)) return False
def request(self, json_payload, newpacket, info): from twisted.internet import reactor from logs import lg from main import events from crypt import my_keys from p2p import p2p_service from contacts import contactsdb from storage import accounting bytes_for_customer = None try: bytes_for_customer = json_payload['needed_bytes'] except: lg.warn("wrong payload" % newpacket.Payload) return p2p_service.SendFail(newpacket, 'wrong payload') try: customer_public_key = json_payload['customer_public_key'] customer_public_key_id = customer_public_key['key_id'] except: customer_public_key = None customer_public_key_id = None if not bytes_for_customer or bytes_for_customer < 0: lg.warn("wrong payload : %s" % newpacket.Payload) return p2p_service.SendFail(newpacket, 'wrong storage value') current_customers = contactsdb.customers() if accounting.check_create_customers_quotas(): lg.out(6, 'service_supplier.request created a new space file') space_dict = accounting.read_customers_quotas() try: free_bytes = int(space_dict['free']) except: lg.exc() return p2p_service.SendFail(newpacket, 'broken space file') if (newpacket.OwnerID not in current_customers and newpacket.OwnerID in space_dict.keys()): lg.warn("broken space file") return p2p_service.SendFail(newpacket, 'broken space file') if (newpacket.OwnerID in current_customers and newpacket.OwnerID not in space_dict.keys()): lg.warn("broken customers file") return p2p_service.SendFail(newpacket, 'broken customers file') if newpacket.OwnerID in current_customers: free_bytes += int(space_dict[newpacket.OwnerID]) space_dict['free'] = free_bytes current_customers.remove(newpacket.OwnerID) space_dict.pop(newpacket.OwnerID) new_customer = False else: new_customer = True from supplier import local_tester if free_bytes <= bytes_for_customer: contactsdb.update_customers(current_customers) contactsdb.save_customers() accounting.write_customers_quotas(space_dict) if customer_public_key_id: my_keys.erase_key(customer_public_key_id) reactor.callLater(0, local_tester.TestUpdateCustomers) if new_customer: lg.out( 8, " NEW CUSTOMER: DENIED !!!!!!!!!!! not enough space available" ) events.send('new-customer-denied', dict(idurl=newpacket.OwnerID)) else: lg.out( 8, " OLD CUSTOMER: DENIED !!!!!!!!!!! not enough space available" ) events.send('existing-customer-denied', dict(idurl=newpacket.OwnerID)) return p2p_service.SendAck(newpacket, 'deny') space_dict['free'] = free_bytes - bytes_for_customer current_customers.append(newpacket.OwnerID) space_dict[newpacket.OwnerID] = bytes_for_customer contactsdb.update_customers(current_customers) contactsdb.save_customers() accounting.write_customers_quotas(space_dict) if customer_public_key_id: my_keys.erase_key(customer_public_key_id) try: if not my_keys.is_key_registered(customer_public_key_id): key_id, key_object = my_keys.read_key_info( customer_public_key) if not my_keys.register_key(key_id, key_object): lg.warn('failed to register customer public key') except: lg.exc() else: lg.warn('customer public key was not provided in the request') reactor.callLater(0, local_tester.TestUpdateCustomers) if new_customer: lg.out(8, " NEW CUSTOMER: ACCEPTED !!!!!!!!!!!!!!") events.send('new-customer-accepted', dict(idurl=newpacket.OwnerID)) else: lg.out(8, " OLD CUSTOMER: ACCEPTED !!!!!!!!!!!!!!") events.send('existing-customer-accepted', dict(idurl=newpacket.OwnerID)) return p2p_service.SendAck(newpacket, 'accepted')