def update_conversation(sender_local_key_id, recipient_local_key_id, payload_type, payload_time, payload_message_id):
    conversation_id = get_conversation_id(sender_local_key_id, recipient_local_key_id, payload_type)
    if conversation_id is None:
        lg.err('failed to update conversation, local_key_id was not found')
        return None
    sql = 'SELECT * FROM conversations WHERE conversation_id=?'
    params = [conversation_id, ]
    found_conversation = list(cur().execute(sql, params))
    if found_conversation:
        sql = 'UPDATE conversations SET last_updated_time=?, last_message_id=? WHERE conversation_id=?'
        params = [payload_time, payload_message_id, conversation_id, ]
    else:
        sql = 'INSERT INTO conversations (conversation_id, payload_type, started_time, last_updated_time, last_message_id) VALUES (?, ?, ?, ?, ?)'
        params = [conversation_id, payload_type, payload_time, payload_time, payload_message_id, ]
    if _Debug:
        lg.args(_DebugLevel, conversation_id=conversation_id, found_conversation=len(found_conversation), params=params)
    cur().execute(sql, params)
    db().commit()
    if not found_conversation:
        listeners.push_snapshot('conversation', snap_id=conversation_id, data=build_json_conversation(
            conversation_id=conversation_id,
            type=MESSAGE_TYPE_CODES.get(int(payload_type), 'private_message'),
            started=payload_time,
            last_updated=payload_time,
            last_message_id=payload_message_id,
        ))
    return conversation_id
示例#2
0
def populate_messages(recipient_id=None,
                      sender_id=None,
                      message_types=[],
                      offset=0,
                      limit=100):
    if recipient_id:
        if not recipient_id.count('@'):
            from contacts import contactsdb
            recipient_idurl = contactsdb.find_correspondent_by_nickname(
                recipient_id)
            if not recipient_idurl:
                lg.err('recipient %r was not found' % recipient_id)
                return
            recipient_id = global_id.UrlToGlobalID(recipient_idurl)
        recipient_glob_id = global_id.ParseGlobalID(recipient_id)
        if not recipient_glob_id['idurl']:
            lg.err('wrong recipient_id')
            return
        recipient_id = global_id.MakeGlobalID(**recipient_glob_id)
        if not my_keys.is_valid_key_id(recipient_id):
            lg.err('invalid recipient_id: %s' % recipient_id)
            return
    if sender_id:
        sender_local_key_id = my_keys.get_local_key_id(sender_id)
        if sender_local_key_id is None:
            return
    if recipient_id:
        recipient_local_key_id = my_keys.get_local_key_id(recipient_id)
        if recipient_local_key_id is None:
            lg.warn('recipient %r local key id was not registered' %
                    recipient_id)
            return
    for row in query_messages(
            sender_id=sender_id,
            recipient_id=recipient_id,
            bidirectional=False,
            message_types=message_types,
            offset=offset,
            limit=limit,
            raw_results=True,
    ):
        conversation_id = get_conversation_id(row[0], row[2], int(row[5]))
        if conversation_id is None:
            continue
        snap_id = '{}/{}'.format(conversation_id, row[7])
        listeners.push_snapshot('message',
                                snap_id=snap_id,
                                created=row[6],
                                data=build_json_message(
                                    sender=row[1],
                                    recipient=row[3],
                                    direction='in' if row[4] == 0 else 'out',
                                    conversation_id=conversation_id,
                                    message_type=MESSAGE_TYPE_CODES.get(
                                        int(row[5]), 'private_message'),
                                    message_time=row[6],
                                    message_id=row[7],
                                    data=json.loads(row[8]),
                                ))
示例#3
0
def load_key(key_id, keys_folder=None):
    global _LatestLocalKeyID
    if not is_valid_key_id(key_id):
        lg.warn('key is not valid: %r' % key_id)
        return False
    key_dict = read_key_file(key_id, keys_folder=keys_folder)
    try:
        key_object = rsa_key.RSAKey()
        key_object.fromDict(key_dict)
    except:
        lg.exc()
        return False
    if not key_object.isPublic():
        if not validate_key(key_object):
            lg.warn('validation failed for: %r' % key_id)
            return False
    known_keys()[key_id] = key_object
    if key_dict.get('need_to_convert'):
        save_key(key_id, keys_folder=keys_folder)
        lg.info('key %r format converted to JSON' % key_id)
    else:
        if key_object.local_key_id is not None:
            if _LatestLocalKeyID < key_object.local_key_id:
                _LatestLocalKeyID = key_object.local_key_id
                save_latest_local_key_id(keys_folder=keys_folder)
            local_keys()[key_object.local_key_id] = key_id
            local_keys_index()[
                key_object.toPublicString()] = key_object.local_key_id
            if _Debug:
                lg.out(
                    _DebugLevel,
                    'my_keys.load_key %r  label=%r  is_private=%r  local_key_id=%r  from %s'
                    % (
                        key_id,
                        key_object.label,
                        not key_object.isPublic(),
                        key_object.local_key_id,
                        keys_folder,
                    ))
        else:
            lg.warn('for key %r local_key_id was not set' % key_id)
    events.send('key-loaded',
                data=dict(
                    key_id=key_id,
                    label=key_object.label,
                    key_size=key_object.size(),
                ))
    listeners.push_snapshot('key',
                            snap_id=key_id,
                            data=make_key_info(
                                key_object=key_object,
                                key_id=key_id,
                                event='key-loaded',
                                include_private=False,
                                include_local_id=True,
                                include_signature=True,
                                include_label=True,
                            ))
    return True
def populate_conversations(message_types=[], offset=0, limit=100, order_by_time=True):
    for conv in fetch_conversations(
        order_by_time=order_by_time,
        message_types=message_types,
        offset=offset,
        limit=limit,
    ):
        listeners.push_snapshot('conversation', snap_id=conv['conversation_id'], data=conv)
示例#5
0
def populate_services():
    services_list = reversed(boot_up_order())
    for name in services_list:
        svc = services().get(name, None)
        if not svc:
            continue
        svc_data = svc.to_json()
        svc_data['event'] = None
        listeners.push_snapshot('service', snap_id=name, data=svc_data)
示例#6
0
def populate_keys():
    for key_id, key_object in known_keys().items():
        listeners.push_snapshot('key',
                                snap_id=key_id,
                                data=make_key_info(
                                    key_object=key_object,
                                    key_id=key_id,
                                    event=None,
                                    include_private=False,
                                    include_local_id=True,
                                    include_signature=True,
                                    include_label=True,
                                ))
示例#7
0
def sign_key(key_id, keys_folder=None, ignore_shared_keys=False, save=True):
    key_id = latest_key_id(strng.to_text(key_id))
    if not is_key_registered(key_id):
        lg.warn('key %s is not found' % key_id)
        return False
    if not keys_folder:
        keys_folder = settings.KeyStoreDir()
    key_object = known_keys()[key_id]
    if key_object.signed:
        if key_object.signed[1] != key.MyPublicKey():
            if ignore_shared_keys:
                if _Debug:
                    lg.dbg(
                        _DebugLevel,
                        'skip generating signature for shared key: %r' %
                        key_id)
                return True
            raise Exception(
                'must not generate and overwrite existing signature for shared key: %r'
                % key_id)
    signed_key_info = make_key_info(
        key_object=key_object,
        key_id=key_id,
        include_private=not key_object.isPublic(),
        generate_signature=True,
    )
    key_object.signed = (
        signed_key_info['signature'],
        signed_key_info['signature_pubkey'],
    )
    known_keys()[key_id] = key_object
    if save:
        save_key(key_id, keys_folder=keys_folder)
    events.send('key-signed',
                data=dict(
                    key_id=key_id,
                    label=key_object.label,
                    key_size=key_object.size(),
                ))
    listeners.push_snapshot('key',
                            snap_id=key_id,
                            data=make_key_info(
                                key_object=key_object,
                                key_id=key_id,
                                event='key-signed',
                                include_private=False,
                                include_local_id=True,
                                include_signature=True,
                                include_label=True,
                            ))
    return key_object
示例#8
0
def on_service_callback(result, service_name):
    if _Debug:
        lg.out(_DebugLevel,
               'driver.on_service_callback %s : [%s]' % (service_name, result))
    svc = services().get(service_name, None)
    if not svc:
        raise ServiceNotFound(service_name)
    if result == 'started':
        if _Debug:
            lg.out(_DebugLevel, '[%s] STARTED' % service_name)
        events.send('service-started', data=dict(name=service_name))
        relative_services = []
        for other_name in services().keys():
            if other_name == service_name:
                continue
            other_service = services().get(other_name, None)
            if not other_service:
                raise ServiceNotFound(other_name)
            if other_service.state == 'ON':
                continue
            for depend_name in other_service.dependent_on():
                if depend_name == service_name:
                    relative_services.append(other_service)
        if len(relative_services) > 0:
            for relative_service in relative_services:
                if not relative_service.enabled():
                    continue
                if relative_service.state == 'ON':
                    continue
                relative_service.automat('start')
    elif result == 'stopped':
        if _Debug:
            lg.out(_DebugLevel, '[%s] STOPPED' % service_name)
        events.send('service-stopped', data=dict(name=service_name))
        for depend_name in svc.dependent_on():
            depend_service = services().get(depend_name, None)
            if not depend_service:
                raise ServiceNotFound(depend_name)
            depend_service.automat('depend-service-stopped')
    elif result == 'depends_off':
        if _Debug:
            lg.out(_DebugLevel, '[%s] DEPENDS_OFF' % service_name)
        for depend_name in svc.dependent_on():
            depend_service = services().get(depend_name, None)
            if not depend_service:
                raise ServiceNotFound(depend_name)
            depend_service.automat('depend-service-stopped')
    svc_data = svc.to_json()
    svc_data['event'] = result
    listeners.push_snapshot('service', snap_id=service_name, data=svc_data)
    return result
示例#9
0
def add_correspondent(idurl, nickname=''):
    """
    Add correspondent, execute notification callback and return its position in
    the list.
    """
    global _CorrespondentsList
    global _CorrespondentsChangedCallback
    curlist = list(_CorrespondentsList)
    idurl = id_url.field(idurl)
    _CorrespondentsList.append((idurl.to_bin(), nickname, ))
    if _CorrespondentsChangedCallback is not None:
        _CorrespondentsChangedCallback(curlist, _CorrespondentsList)
    listeners.push_snapshot('correspondent', snap_id=idurl.to_bin(), data=dict(
        idurl=idurl.to_bin(),
        nickname=nickname,
    ))
    return len(curlist)
示例#10
0
def generate_key(key_id, label='', key_size=4096, keys_folder=None):
    global _LatestLocalKeyID
    key_id = latest_key_id(key_id)
    if is_key_registered(key_id):
        lg.warn('key %r already registered' % key_id)
        return None
    if not label:
        label = 'key%s' % utime.make_timestamp()
    if _Debug:
        lg.out(
            _DebugLevel, 'my_keys.generate_key %r of %d bits, label=%r' %
            (key_id, key_size, label))
    _LatestLocalKeyID += 1
    save_latest_local_key_id(keys_folder=keys_folder)
    key_object = rsa_key.RSAKey()
    key_object.generate(key_size)
    key_object.label = label
    key_object.local_key_id = _LatestLocalKeyID
    known_keys()[key_id] = key_object
    if _Debug:
        lg.out(_DebugLevel, '    key %r generated' % key_id)
    if not keys_folder:
        keys_folder = settings.KeyStoreDir()
    save_key(key_id, keys_folder=keys_folder)
    events.send('key-generated',
                data=dict(
                    key_id=key_id,
                    label=label,
                    key_size=key_size,
                ))
    listeners.push_snapshot('key',
                            snap_id=key_id,
                            data=make_key_info(
                                key_object=key_object,
                                key_id=key_id,
                                event='key-generated',
                                include_private=False,
                                include_local_id=True,
                                include_signature=True,
                                include_label=True,
                            ))
    return key_object
示例#11
0
def remove_correspondent(idurl):
    """
    Remove correspondent with given IDURL, execute notification callback and
    return True if success.
    """
    global _CorrespondentsList
    global _CorrespondentsChangedCallback
    curlist = list(_CorrespondentsList)
    idurl = id_url.field(idurl)
    for tupl in _CorrespondentsList:
        if idurl.to_bin() == id_url.field(tupl[0]).to_bin():
            _CorrespondentsList.remove(tupl)
            if _CorrespondentsChangedCallback is not None:
                _CorrespondentsChangedCallback(curlist, _CorrespondentsList)
            listeners.push_snapshot('correspondent', snap_id=idurl.to_bin(), deleted=True, data=dict(
                idurl=idurl.to_bin(),
                nickname=tupl[1],
            ))
            return True
    return False
示例#12
0
 def state_changed(self, oldstate, newstate, event, *args, **kwargs):
     """
     Method to catch the moment when `online_status()` state were changed.
     """
     if _Debug:
         lg.out(_DebugLevel - 2, '%s : [%s]->[%s]' % (self.name, oldstate, newstate))
     if newstate == 'CONNECTED':
         lg.info('remote node connected : %s' % self.idurl)
         events.send('node-connected', data=dict(
             global_id=self.idurl.to_id(),
             idurl=self.idurl,
             old_state=oldstate,
             new_state=newstate,
         ))
         listeners.push_snapshot('online_status', snap_id=self.idurl.to_bin(), data=self.to_json())
     if newstate == 'OFFLINE' and oldstate != 'AT_STARTUP':
         lg.info('remote node disconnected : %s' % self.idurl)
         events.send('node-disconnected', data=dict(
             global_id=self.idurl.to_id(),
             idurl=self.idurl,
             old_state=oldstate,
             new_state=newstate,
         ))
         listeners.push_snapshot('online_status', snap_id=self.idurl.to_bin(), data=self.to_json())
     if newstate == 'PING?' and oldstate != 'AT_STARTUP':
         listeners.push_snapshot('online_status', snap_id=self.idurl.to_bin(), data=self.to_json())
示例#13
0
def erase_key(key_id, keys_folder=None):
    key_id = latest_key_id(key_id)
    if not is_key_registered(key_id):
        lg.warn('key %s is not registered' % key_id)
        return False
    if not keys_folder:
        keys_folder = settings.KeyStoreDir()
    if key_obj(key_id).isPublic():
        key_filepath = os.path.join(keys_folder, key_id + '.public')
        is_private = False
    else:
        key_filepath = os.path.join(keys_folder, key_id + '.private')
        is_private = True
    try:
        os.remove(key_filepath)
    except:
        lg.exc()
        return False
    k_obj = known_keys().pop(key_id)
    local_keys().pop(k_obj.local_key_id, None)
    local_keys_index().pop(k_obj.toPublicString(), None)
    gc.collect()
    if _Debug:
        lg.out(_DebugLevel,
               '    key %s removed, file %s deleted' % (key_id, key_filepath))
    events.send('key-erased', data=dict(key_id=key_id, is_private=is_private))
    listeners.push_snapshot('key',
                            snap_id=key_id,
                            deleted=True,
                            data=make_key_info(
                                key_object=None,
                                key_id=key_id,
                                event='key-erased',
                                include_private=False,
                                include_local_id=True,
                                include_signature=True,
                                include_label=True,
                            ))
    return True
示例#14
0
def populate_online_statuses():
    for online_s in online_statuses().values():
        listeners.push_snapshot('online_status', snap_id=online_s.idurl.to_bin(), data=online_s.to_json())
示例#15
0
def insert_message(data,
                   message_id,
                   message_time=None,
                   sender=None,
                   recipient=None,
                   message_type=None,
                   direction=None):
    """
    Writes JSON message to the message database.
    """
    payload_time = message_time or utime.utcnow_to_sec1970()
    payload_message_id = strng.to_text(message_id)
    payload_type = MESSAGE_TYPES.get(message_type, 1)
    if not sender:
        sender = my_id.getGlobalID(key_alias='master')
    if not recipient:
        recipient = my_id.getGlobalID(key_alias='master')
    if direction is None:
        if message_type in [
                'private_message',
                None,
        ]:
            direction = 'out' if sender == my_id.getGlobalID(
                key_alias='master') else 'in'
        else:
            direction = 'in'
    else:
        direction = direction.replace('incoming',
                                      'in').replace('outgoing', 'out')
    if _Debug:
        lg.args(_DebugLevel,
                sender=sender,
                recipient=recipient,
                typ=payload_type,
                dir=direction,
                message_id=payload_message_id)
    recipient_local_key_id = my_keys.get_local_key_id(recipient)
    if payload_type in [
            3,
            4,
    ]:
        sender_local_key_id = recipient_local_key_id
    else:
        sender_local_key_id = my_keys.get_local_key_id(sender)
    if sender_local_key_id is None or recipient_local_key_id is None:
        lg.err(
            'failed to store message because local_key_id is not found, sender=%r recipient=%r'
            % (
                sender_local_key_id,
                recipient_local_key_id,
            ))
        return None
    cur().execute(
        '''INSERT INTO history (
            sender_local_key_id,
            sender_id,
            recipient_local_key_id,
            recipient_id,
            direction,
            payload_type,
            payload_time,
            payload_message_id,
            payload_body
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)''', (
            sender_local_key_id,
            sender,
            recipient_local_key_id,
            recipient,
            0 if direction == 'in' else 1,
            payload_type,
            payload_time,
            payload_message_id,
            data,
        ))
    db().commit()
    conversation_id = update_conversation(sender_local_key_id,
                                          recipient_local_key_id, payload_type,
                                          payload_time, payload_message_id)
    snap_id = '{}/{}'.format(conversation_id, payload_message_id)
    message_json = build_json_message(
        sender=sender,
        recipient=recipient,
        direction=direction,
        conversation_id=conversation_id,
        message_type=MESSAGE_TYPE_CODES.get(int(payload_type),
                                            'private_message'),
        message_time=payload_time,
        message_id=payload_message_id,
        data=data,
    )
    listeners.push_snapshot('message',
                            snap_id=snap_id,
                            created=payload_time,
                            data=message_json)
    return message_json
示例#16
0
def register_key(key_id, key_object_or_string, label='', keys_folder=None):
    global _LatestLocalKeyID
    key_id = latest_key_id(key_id)
    if is_key_registered(key_id):
        lg.warn('key %s already registered' % key_id)
        return None
    if not keys_folder:
        keys_folder = settings.KeyStoreDir()
    if not label:
        label = 'key%s' % utime.make_timestamp()
    if strng.is_string(key_object_or_string):
        key_object_or_string = strng.to_bin(key_object_or_string)
        if _Debug:
            lg.out(
                _DebugLevel,
                'my_keys.register_key %r from %d bytes openssh_input_string' %
                (key_id, len(key_object_or_string)))
        key_object = unserialize_key_to_object(key_object_or_string)
        if not key_object:
            lg.warn(
                'invalid openssh string, unserialize_key_to_object() failed')
            return None
    else:
        if _Debug:
            lg.out(_DebugLevel, 'my_keys.register_key %r from object' % key_id)
        key_object = key_object_or_string
    known_local_key_id = local_keys_index().get(key_object.toPublicString())
    if known_local_key_id is not None:
        known_key_id = local_keys().get(known_local_key_id)
        if known_key_id is not None:
            known_key_id = latest_key_id(known_key_id)
            if known_key_id != key_id:
                raise Exception(
                    'must not register same key with local_key_id=%r twice with different key_id: %r ~ %r'
                    % (
                        known_local_key_id,
                        known_key_id,
                        key_id,
                    ))
    new_local_key_id = known_local_key_id
    if new_local_key_id is None:
        _LatestLocalKeyID += 1
        save_latest_local_key_id(keys_folder=keys_folder)
        new_local_key_id = _LatestLocalKeyID
    key_object.local_key_id = new_local_key_id
    known_keys()[key_id] = key_object
    if _Debug:
        lg.out(_DebugLevel, '    key %r registered' % key_id)
    save_key(key_id, keys_folder=keys_folder)
    events.send('key-registered',
                data=dict(
                    key_id=key_id,
                    label=label,
                    key_size=key_object.size(),
                ))
    listeners.push_snapshot('key',
                            snap_id=key_id,
                            data=make_key_info(
                                key_object=key_object,
                                key_id=key_id,
                                event='key-registered',
                                include_private=False,
                                include_local_id=True,
                                include_signature=True,
                                include_label=True,
                            ))
    return key_object
示例#17
0
def populate_correspondents():
    for corr in correspondents():
        listeners.push_snapshot('correspondent', snap_id=corr[0], data=dict(
            idurl=corr[0],
            nickname=corr[1],
        ))