def get_available_teams(rq):
     self.assertEqual(rq['command'], 'get_available_teams')
     return {
         'teams': [{
             'team_uid': api.generate_record_uid(),
             'team_name': 'Team 1'
         }, {
             'team_uid': api.generate_record_uid(),
             'team_name': 'Team 2'
         }]
     }
Beispiel #2
0
def prepare_record_add_or_update(update_flag, params, records):
    """
    Find what records to import or update.

    If update_flag is False:
        If a 100% match is found for a record, then just skip requesting anything; it doesn't need to be changed.
        Otherwise import the record, risking creating an almost-duplicate.
    If update_flag is True:
       if a unique field match (on title, login, and url) is found, then request a change in password only.
       Do not update the TOTP custom field, even if it exists.
    """
    recs_to_import_or_update = records
    del records
    preexisting_entire_record_hash = build_hash_dict(params, tokenize_full_preexisting_record)
    preexisting_partial_record_hash = build_hash_dict(params, tokenize_partial_preexisting_record)

    record_adds = []
    record_updates = []
    for rec_to_import_or_update in recs_to_import_or_update:
        perform_import_or_update = 'neither'

        full_hash_of_cur_rec = build_record_hash(rec_to_import_or_update, tokenize_full_import_record)
        partial_hash_of_cur_rec = build_record_hash(rec_to_import_or_update, tokenize_partial_import_record)
        # Decide what kind of operation is needed.
        if full_hash_of_cur_rec in preexisting_entire_record_hash:
            # We do not need to do a record update; we already have this record in its entirety.
            pass
        elif partial_hash_of_cur_rec in preexisting_partial_record_hash and update_flag:
            # This is a record to update instead of importing it.
            rec_to_import_or_update.uid = preexisting_partial_record_hash[partial_hash_of_cur_rec]
            perform_import_or_update = 'update'
        else:
            # Create a new UID for the new record, and signal that we need to do the import.
            # We do this conditionally for --update, and unconditionally for import without --update.
            rec_to_import_or_update.uid = api.generate_record_uid()
            perform_import_or_update = 'import'

        # Act on the selected operation.
        if perform_import_or_update == 'update':
            rec_req = construct_update_rec_req(params, preexisting_partial_record_hash, rec_to_import_or_update)
            # Schedule the record for later batch-update.
            record_updates.append(rec_req)
        elif perform_import_or_update == 'import':
            rec_req = construct_import_rec_req(params, preexisting_entire_record_hash, rec_to_import_or_update)
            # Schedule the record for later batch-addition.
            record_adds.append(rec_req)
        elif perform_import_or_update == 'neither':
            # Nothing to do.
            pass
        else:
            raise AssertionError('perform_import_or_update has a strange value: {}'.format(perform_import_or_update))

    return record_adds, record_updates
Beispiel #3
0
def generate_data():
    r1 = record.Record()
    r1.record_uid = api.generate_record_uid()
    r1.folder = 'Old Folder'
    r1.title = 'Record 1'
    r1.login = '******'
    r1.password = '******'
    r1.login_url = 'https://keepersecurity.com/1'
    r1.set_field('field1', 'value1')
    r1.notes = 'note1'
    r1.attachments = [{
        'name':
        'Attachment 1',
        'key':
        base64.urlsafe_b64encode(
            api.generate_aes_key()).decode('utf-8').rstrip('='),
        'id':
        'ABCDEFGH',
        'size':
        1000
    }]
    r1.revision = 1
    r1_key = register_record(r1, 1)

    r2 = record.Record()
    r2.record_uid = api.generate_record_uid()
    r2.title = 'Record 2'
    r2.login = '******'
    r2.password = '******'
    r2.login_url = 'https://keepersecurity.com/2'
    r2.set_field('field2', 'value2')
    r2.notes = 'note2'
    r2.revision = 2
    r2_key = register_record(r2, 2)

    register_records_to_folder(None, [r1.record_uid, r2.record_uid])

    r3 = record.Record()
    r3.record_uid = api.generate_record_uid()
    r3.title = 'Record 3'
    r3.login = '******'
    r3.password = '******'
    r3.login_url = 'https://keepersecurity.com/3'
    r3.revision = 3
    r3_key = register_record(r3)

    sf1 = shared_folder.SharedFolder()
    sf1.shared_folder_uid = api.generate_record_uid()
    sf1.default_manage_records = False
    sf1.default_manage_users = False
    sf1.default_can_edit = False
    sf1.default_can_share = False
    sf1.name = 'Shared Folder 1'
    sf1_key = register_shared_folder(sf1, {r3.record_uid: r3_key})
    register_records_to_folder(sf1.shared_folder_uid, [r3.record_uid])
    _USER_FOLDER_SHARED_FOLDER.append(
        {'shared_folder_uid': sf1.shared_folder_uid})

    t1 = team.Team()
    t1.team_uid = api.generate_record_uid()
    t1.name = 'Team 1'
    t1.restrict_edit = True
    t1.restrict_share = True
    t1.restrict_view = False

    register_team(t1, 1, {sf1.shared_folder_uid: sf1_key})

    folder_key = api.generate_aes_key()
    _USER_FOLDERS.append({
        'folder_uid':
        api.generate_record_uid(),
        'key_type':
        1,
        'user_folder_key':
        api.encrypt_aes(folder_key, _USER_DATA_KEY),
        'revision':
        200,
        'type':
        'user_folder',
        'data':
        api.encrypt_aes(
            json.dumps({
                'name': 'User Folder 1'
            }).encode('utf-8'), folder_key)
    })
    def test_enterprise_push_command(self):
        params = get_connected_params()
        api.query_enterprise(params)

        cmd = enterprise.EnterprisePushCommand()

        template_body = '''
[
    {
        "title": "Record For ${user_name}",
        "login": "******",
        "password": "******",
        "login_url": "https://keepersecurity.com",
        "notes": "notes",
        "custom_fields": {
            "key1": "value1",
            "key2": "${user_email}"
        }
    },
    {
        "title": "Empty record"
    }

]'''
        templates = json.loads(template_body)
        values = {
            'user_name': api.generate_record_uid(),
            'generate_password': api.generate_record_uid(),
            'user_email': api.generate_record_uid()
        }
        cmd.enumerate_and_substitute_dict_fields(templates[0], values)
        cmd.enumerate_and_substitute_dict_fields(templates[1], values)
        self.assertEqual(templates[0]['title'],
                         'Record For {0}'.format(values['user_name']))
        self.assertEqual(templates[0]['password'], values['generate_password'])
        self.assertEqual(templates[0]['custom_fields']['key2'],
                         values['user_email'])
        self.assertEqual(templates[1]['title'], 'Empty record')

        with self.assertRaises(CommandError):
            cmd.execute(params, file='template.json')

        with self.assertRaises(CommandError):
            cmd.execute(params, user=[ent_env.user2_email])

        def get_public_keys(_params, emails):
            for email in emails:
                emails[email] = vault_env.public_key

        with mock.patch('builtins.open', mock.mock_open(read_data=template_body)), \
                mock.patch('os.path.abspath', return_value='template.json'), \
                mock.patch('os.path.isfile', return_value=True), \
                mock.patch('keepercommander.commands.enterprise.EnterpriseCommand.get_public_keys') as m_pk:

            m_pk.side_effect = get_public_keys

            TestEnterprise.expected_commands = ['execute']
            cmd.execute(params,
                        file='template.json',
                        team=[ent_env.team1_name])
            self.assertEqual(len(TestEnterprise.expected_commands), 0)

            TestEnterprise.expected_commands = ['execute']
            cmd.execute(params,
                        file='template.json',
                        user=[ent_env.user2_email])
            self.assertEqual(len(TestEnterprise.expected_commands), 0)
Beispiel #5
0
def prepare_record_add(params, records):
    record_hash = {}
    for r_uid in params.record_cache:
        rec = api.get_record(params, r_uid)
        h = hashlib.sha256()
        for token in tokenize_record(rec):
            h.update(token.encode())
        record_hash[h.hexdigest()] = r_uid

    record_adds = []
    for rec in records:
        h = hashlib.sha256()
        for token in tokenize_import_record(rec):
            h.update(token.encode())
        r_hash = h.hexdigest()
        if r_hash in record_hash:
            rec.uid = record_hash[r_hash]
        else:
            rec.uid = api.generate_record_uid()
            record_hash[r_hash] = rec.uid
            record_key = os.urandom(32)
            rec_req = folder_pb2.RecordRequest()
            rec_req.recordUid = base64.urlsafe_b64decode(rec.uid + '==')
            rec_req.recordType = 0
            rec_req.encryptedRecordKey = base64.urlsafe_b64decode(
                api.encrypt_aes(record_key, params.data_key) + '==')
            rec_req.howLongAgo = 0
            rec_req.folderType = 1

            folder_uid = None
            if rec.folders:
                folder_uid = rec.folders[0].uid
            if folder_uid:
                if folder_uid in params.folder_cache:
                    folder = params.folder_cache[folder_uid]
                    if folder.type in {
                            BaseFolderNode.SharedFolderType,
                            BaseFolderNode.SharedFolderFolderType
                    }:
                        rec_req.folderUid = base64.urlsafe_b64decode(
                            folder.uid + '==')
                        rec_req.folderType = 2 if folder.type == BaseFolderNode.SharedFolderType else 3

                        sh_uid = folder.uid if folder.type == BaseFolderNode.SharedFolderType else folder.shared_folder_uid
                        sf = params.shared_folder_cache[sh_uid]
                        rec_req.encryptedRecordFolderKey = base64.urlsafe_b64decode(
                            api.encrypt_aes(
                                record_key,
                                sf['shared_folder_key_unencrypted']) + '==')
                    else:
                        rec_req.folderType = 1
                        if folder.type != BaseFolderNode.RootFolderType:
                            rec_req.folderUid = base64.urlsafe_b64decode(
                                folder.uid + '==')

            custom_fields = []
            totp = None
            if rec.custom_fields:
                for cf in rec.custom_fields:
                    if cf == TWO_FACTOR_CODE:
                        totp = rec.custom_fields[cf]
                    else:
                        custom_fields.append({
                            'name': cf,
                            'value': rec.custom_fields[cf]
                        })

            data = {
                'title': rec.title or '',
                'secret1': rec.login or '',
                'secret2': rec.password or '',
                'link': rec.login_url or '',
                'notes': rec.notes or '',
                'custom': custom_fields
            }
            rec_req.recordData = base64.urlsafe_b64decode(
                api.encrypt_aes(json.dumps(data).encode('utf-8'), record_key) +
                '==')
            if totp:
                extra = {
                    'fields': [{
                        'id': api.generate_record_uid(),
                        'field_type': 'totp',
                        'field_title': 'Two-Factor Code',
                        'type': 0,
                        'data': totp
                    }]
                }
                rec_req.extra = base64.urlsafe_b64decode(
                    api.encrypt_aes(
                        json.dumps(extra).encode('utf-8'), record_key) + '==')
            record_adds.append(rec_req)

    return record_adds
Beispiel #6
0
def prepare_folder_add(params, folders, records):
    folder_hash = {}
    for f_uid in params.folder_cache:
        fol = params.folder_cache[f_uid]
        h = hashlib.md5()
        hs = '{0}|{1}'.format((fol.name or '').lower(), fol.parent_uid or '')
        h.update(hs.encode())
        shared_folder_key = None
        if fol.type in {
                BaseFolderNode.SharedFolderType,
                BaseFolderNode.SharedFolderFolderType
        }:
            sf_uid = fol.shared_folder_uid if fol.type == BaseFolderNode.SharedFolderFolderType else fol.uid
            if sf_uid in params.shared_folder_cache:
                shared_folder_key = params.shared_folder_cache[sf_uid][
                    'shared_folder_key_unencrypted']
        folder_hash[h.hexdigest()] = f_uid, fol.type, shared_folder_key

    folder_add = []  # type: [folder_pb2.FolderRequest]
    if folders:
        for fol in folders:
            skip_folder = False
            parent_uid = ''
            comps = list(path_components(fol.path))
            for i in range(len(comps)):
                comp = comps[i]
                h = hashlib.md5()
                hs = '{0}|{1}'.format(comp.lower(), parent_uid)
                h.update(hs.encode())
                digest = h.hexdigest()

                is_last = False
                if i == len(comps) - 1:
                    is_last = True

                if digest not in folder_hash:
                    folder_uid = api.generate_record_uid()
                    folder_type = 'shared_folder' if is_last else 'user_folder'

                    fol_req = folder_pb2.FolderRequest()
                    fol_req.folderUid = base64.urlsafe_b64decode(folder_uid +
                                                                 '==')
                    fol_req.folderType = 2 if folder_type == 'shared_folder' else 1

                    if parent_uid:
                        fol_req.parentFolderUid = base64.urlsafe_b64decode(
                            parent_uid + '==')

                    folder_key = os.urandom(32)
                    fol_req.encryptedFolderKey = base64.urlsafe_b64decode(
                        api.encrypt_aes(folder_key, params.data_key) + '==')

                    data = {'name': comp}
                    fol_req.folderData = base64.urlsafe_b64decode(
                        api.encrypt_aes(
                            json.dumps(data).encode('utf-8'), folder_key) +
                        '==')

                    if folder_type == 'shared_folder':
                        fol_req.sharedFolderFields.encryptedFolderName = base64.urlsafe_b64decode(
                            api.encrypt_aes(comp.encode('utf-8'), folder_key) +
                            '==')
                        fol_req.sharedFolderFields.manageUsers = fol.manage_users
                        fol_req.sharedFolderFields.manageRecords = fol.manage_records
                        fol_req.sharedFolderFields.canEdit = fol.can_edit
                        fol_req.sharedFolderFields.canShare = fol.can_share

                    folder_add.append(fol_req)
                    folder_hash[
                        digest] = folder_uid, folder_type, folder_key if folder_type == 'shared_folder' else None
                else:
                    folder_uid, folder_type, folder_key = folder_hash[digest]
                    if is_last:
                        skip_folder = folder_type != 'shared_folder'
                    else:
                        skip_folder = folder_type != 'user_folder'

                parent_uid = folder_uid
                if skip_folder:
                    break

    if records:
        for rec in records:
            if rec.folders:
                for fol in rec.folders:
                    parent_uid = ''
                    parent_shared_folder_uid = None
                    parent_shared_folder_key = None
                    parent_type = ''
                    for is_domain in [True, False]:
                        path = fol.domain if is_domain else fol.path
                        if not path:
                            continue

                        comps = list(path_components(path))
                        for i in range(len(comps)):
                            comp = comps[i]
                            h = hashlib.md5()
                            hs = '{0}|{1}'.format(comp.lower(), parent_uid)
                            h.update(hs.encode())
                            digest = h.hexdigest()

                            if digest not in folder_hash:
                                is_shared = False
                                if i == len(comps) - 1:
                                    is_shared = is_domain

                                folder_uid = api.generate_record_uid()
                                if not parent_type or parent_type == 'user_folder':
                                    folder_type = 'shared_folder' if is_shared else 'user_folder'
                                else:
                                    folder_type = 'shared_folder_folder'

                                fol_req = folder_pb2.FolderRequest()
                                fol_req.folderUid = base64.urlsafe_b64decode(
                                    folder_uid + '==')
                                fol_req.folderType = 2 if folder_type == 'shared_folder' else 3 if folder_type == 'shared_folder_folder' else 1

                                if parent_uid:
                                    fol_req.parentFolderUid = base64.urlsafe_b64decode(
                                        parent_uid + '==')
                                    if folder_type == 'shared_folder_folder' and parent_uid == parent_shared_folder_uid:
                                        fol_req.parentFolderUid = b''

                                folder_key = os.urandom(32)
                                if folder_type == 'shared_folder_folder':
                                    fol_req.encryptedFolderKey = base64.urlsafe_b64decode(
                                        api.encrypt_aes(
                                            folder_key,
                                            parent_shared_folder_key
                                            or params.data_key) + '==')
                                else:
                                    fol_req.encryptedFolderKey = base64.urlsafe_b64decode(
                                        api.encrypt_aes(
                                            folder_key, params.data_key) +
                                        '==')

                                data = {'name': comp}
                                fol_req.folderData = base64.urlsafe_b64decode(
                                    api.encrypt_aes(
                                        json.dumps(data).encode('utf-8'),
                                        folder_key) + '==')

                                if folder_type == 'shared_folder':
                                    fol_req.sharedFolderFields.encryptedFolderName = base64.urlsafe_b64decode(
                                        api.encrypt_aes(
                                            comp.encode('utf-8'), folder_key) +
                                        '==')

                                    parent_shared_folder_key = folder_key
                                    parent_shared_folder_uid = folder_uid

                                elif folder_type == 'shared_folder_folder':
                                    if parent_shared_folder_uid:
                                        fol_req.sharedFolderFolderFields.sharedFolderUid = base64.urlsafe_b64decode(
                                            parent_shared_folder_uid + '==')

                                folder_add.append(fol_req)
                                folder_hash[
                                    digest] = folder_uid, folder_type, parent_shared_folder_key
                            else:
                                folder_uid, folder_type, parent_shared_folder_key = folder_hash[
                                    digest]

                            if folder_type == 'shared_folder':
                                parent_shared_folder_uid = folder_uid

                            parent_uid = folder_uid
                            parent_type = folder_type

                    fol.uid = parent_uid

    return folder_add
Beispiel #7
0
def prepare_record_add(params, records):
    record_hash = {}
    for r_uid in params.record_cache:
        rec = api.get_record(params, r_uid)
        h = hashlib.md5()
        hs = '{0}|{1}|{2}'.format(rec.title or '', rec.login or '',
                                  rec.password or '')
        h.update(hs.encode())
        record_hash[h.hexdigest()] = r_uid

    record_adds = []
    for rec in records:
        h = hashlib.md5()
        hs = '{0}|{1}|{2}'.format(rec.title or '', rec.login or '',
                                  rec.password or '')
        h.update(hs.encode())
        rec_hash = h.hexdigest()

        record_uid = record_hash.get(rec_hash)
        if record_uid is None:
            record_key = os.urandom(32)
            record_uid = api.generate_record_uid()
            req = {
                'command': 'record_add',
                'record_uid': record_uid,
                'record_type': 'password',
                'record_key': api.encrypt_aes(record_key, params.data_key),
                'how_long_ago': 0,
                'folder_type': 'user_folder'
            }
            folder_uid = None
            if rec.folders:
                if len(rec.folders) > 0:
                    folder_uid = rec.folders[0].uid
            if folder_uid:
                if folder_uid in params.folder_cache:
                    folder = params.folder_cache[folder_uid]
                    if folder.type in {
                            BaseFolderNode.SharedFolderType,
                            BaseFolderNode.SharedFolderFolderType
                    }:
                        req['folder_uid'] = folder.uid
                        req['folder_type'] = 'shared_folder' if folder.type == BaseFolderNode.SharedFolderType else 'shared_folder_folder'

                        sh_uid = folder.uid if folder.type == BaseFolderNode.SharedFolderType else folder.shared_folder_uid
                        sf = params.shared_folder_cache[sh_uid]
                        req['folder_key'] = api.encrypt_aes(
                            record_key, sf['shared_folder_key_unencrypted'])
                        if 'key_type' not in sf:
                            if 'teams' in sf:
                                for team in sf['teams']:
                                    req['team_uid'] = team['team_uid']
                                    if team['manage_records']:
                                        break
                    else:
                        req['folder_type'] = 'user_folder'
                        if folder.type != BaseFolderNode.RootFolderType:
                            req['folder_uid'] = folder.uid

            custom_fields = []
            if rec.custom_fields:
                for cf in rec.custom_fields:
                    custom_fields.append({
                        'name': cf,
                        'value': rec.custom_fields[cf]
                    })

            data = {
                'title': rec.title or '',
                'secret1': rec.login or '',
                'secret2': rec.password or '',
                'link': rec.login_url or '',
                'notes': rec.notes or '',
                'custom': custom_fields
            }
            req['data'] = api.encrypt_aes(
                json.dumps(data).encode('utf-8'), record_key)
            record_adds.append(req)

        rec.uid = record_uid

    return record_adds
Beispiel #8
0
def prepare_folder_add(params, records):
    folder_hash = {}
    for f_uid in params.folder_cache:
        fol = params.folder_cache[f_uid]
        h = hashlib.md5()
        hs = '{0}|{1}'.format((fol.name or '').lower(), fol.parent_uid or '')
        h.update(hs.encode())
        shared_folder_key = None
        if fol.type in {
                BaseFolderNode.SharedFolderType,
                BaseFolderNode.SharedFolderFolderType
        }:
            sf_uid = fol.shared_folder_uid if fol.type == BaseFolderNode.SharedFolderFolderType else fol.uid
            if sf_uid in params.shared_folder_cache:
                shared_folder_key = params.shared_folder_cache[sf_uid][
                    'shared_folder_key_unencrypted']
        folder_hash[h.hexdigest()] = f_uid, fol.type, shared_folder_key

    folder_add = []

    for rec in records:
        if rec.folders:
            for fol in rec.folders:
                parent_uid = ''
                parent_shared_folder_uid = None
                parent_shared_folder_key = None
                parent_type = BaseFolderNode.RootFolderType
                for is_domain in [True, False]:
                    path = fol.domain if is_domain else fol.path
                    if not path:
                        continue

                    comps = list(path_components(path))
                    for i in range(len(comps)):
                        comp = comps[i]
                        h = hashlib.md5()
                        hs = '{0}|{1}'.format(comp.lower(), parent_uid)
                        h.update(hs.encode())
                        digest = h.hexdigest()
                        if digest not in folder_hash:
                            is_shared = False
                            if i == len(comps) - 1:
                                is_shared = is_domain
                            folder_uid = api.generate_record_uid()
                            request = {
                                'command': 'folder_add',
                                'folder_uid': folder_uid
                            }
                            if parent_type in {
                                    BaseFolderNode.UserFolderType,
                                    BaseFolderNode.RootFolderType
                            }:
                                folder_type = 'shared_folder' if is_shared else 'user_folder'
                            else:
                                folder_type = 'shared_folder_folder'
                            request['folder_type'] = folder_type

                            encryption_key = params.data_key
                            if request[
                                    'folder_type'] == 'shared_folder_folder' and parent_shared_folder_uid and parent_shared_folder_key:
                                encryption_key = parent_shared_folder_key
                                request[
                                    'shared_folder_uid'] = parent_shared_folder_uid

                            folder_key = os.urandom(32)
                            request['key'] = api.encrypt_aes(
                                folder_key, encryption_key)
                            if parent_type not in {
                                    BaseFolderNode.RootFolderType,
                                    BaseFolderNode.SharedFolderType
                            }:
                                request['parent_uid'] = parent_uid

                            if request['folder_type'] == 'shared_folder':
                                request['name'] = api.encrypt_aes(
                                    comp.encode('utf-8'), folder_key)
                                parent_shared_folder_key = folder_key

                            data = {'name': comp}
                            request['data'] = api.encrypt_aes(
                                json.dumps(data).encode('utf-8'), folder_key)
                            folder_add.append(request)
                            parent_uid = folder_uid
                            parent_type = folder_type
                            folder_hash[
                                digest] = parent_uid, parent_type, parent_shared_folder_key
                        else:
                            parent_uid, parent_type, parent_shared_folder_key = folder_hash[
                                digest]

                        if parent_type == BaseFolderNode.SharedFolderType:
                            parent_shared_folder_uid = parent_uid
                fol.uid = parent_uid

    return folder_add
Beispiel #9
0
def prepare_shared_folder_add(params, folders):
    folder_hash = {}
    for f_uid in params.folder_cache:
        fol = params.folder_cache[f_uid]
        h = hashlib.md5()
        hs = '{0}|{1}'.format((fol.name or '').lower(), fol.parent_uid or '')
        h.update(hs.encode())
        shared_folder_key = None
        if fol.type in {
                BaseFolderNode.SharedFolderType,
                BaseFolderNode.SharedFolderFolderType
        }:
            sf_uid = fol.shared_folder_uid if fol.type == BaseFolderNode.SharedFolderFolderType else fol.uid
            if sf_uid in params.shared_folder_cache:
                shared_folder_key = params.shared_folder_cache[sf_uid][
                    'shared_folder_key_unencrypted']
        folder_hash[h.hexdigest()] = f_uid, fol.type, shared_folder_key

    # public keys
    emails = {}
    for fol in folders:
        if fol.permissions:
            for perm in fol.permissions:
                if perm.name not in emails:
                    _, email = parseaddr(perm.name)
                    if email:
                        if email != params.user:
                            emails[email.lower()] = None
    if emails:
        request = {'command': "public_keys", 'key_owners': list(emails.keys())}
        try:
            rs = api.communicate(params, request)
            if 'public_keys' in rs:
                for pk in rs['public_keys']:
                    if 'public_key' in pk:
                        emails[pk['key_owner']] = pk['public_key']
        except Exception as e:
            logging.debug(e)

    shared_folder_add = []
    for fol in folders:
        skip_folder = False
        parent_uid = ''
        parent_type = ''
        parent_key = None
        comps = list(path_components(fol.path))
        for i in range(len(comps)):
            comp = comps[i]
            h = hashlib.md5()
            hs = '{0}|{1}'.format(comp.lower(), parent_uid)
            h.update(hs.encode())
            digest = h.hexdigest()

            is_last = False
            if i == len(comps) - 1:
                is_last = True
            if digest not in folder_hash:
                folder_uid = api.generate_record_uid()
                request = {'command': 'folder_add', 'folder_uid': folder_uid}
                folder_type = 'shared_folder' if is_last else 'user_folder'
                request['folder_type'] = folder_type

                encryption_key = params.data_key
                folder_key = os.urandom(32)
                request['key'] = api.encrypt_aes(folder_key, encryption_key)
                if parent_uid:
                    request['parent_uid'] = parent_uid
                if folder_type == 'shared_folder':
                    request['name'] = api.encrypt_aes(comp.encode('utf-8'),
                                                      folder_key)

                data = {'name': comp}
                request['data'] = api.encrypt_aes(
                    json.dumps(data).encode('utf-8'), folder_key)

                shared_folder_add.append(request)
                parent_uid = folder_uid
                parent_type = folder_type
                parent_key = folder_key
                folder_hash[
                    digest] = folder_uid, folder_type, folder_key if folder_type == 'shared_folder' else None
            else:
                parent_uid, parent_type, parent_key = folder_hash[digest]
                if is_last:
                    skip_folder = parent_type != 'shared_folder'
                else:
                    skip_folder = parent_type != 'user_folder'
            if skip_folder:
                break

        if not skip_folder and parent_type == 'shared_folder':
            request = {
                'command': 'shared_folder_update',
                'operation': 'update',
                'pt': 'Commander',
                'shared_folder_uid': parent_uid,
                'force_update': True,
                'default_manage_users': fol.manage_users,
                'default_manage_records': fol.manage_records,
                'default_can_edit': fol.can_edit,
                'default_can_share': fol.can_share
            }
            if fol.permissions:
                for perm in fol.permissions:
                    is_team = False
                    if perm.uid and params.team_cache:
                        is_team = perm.uid in params.team_cache
                    else:
                        _, email = parseaddr(perm.name)
                        if not email:
                            is_team = True
                        if is_team:
                            perm.uid = None
                            for team in params.team_cache:
                                if team['name'].lower() == perm.name.lower():
                                    perm.uid = team['team_uid']
                                    break
                    if is_team:
                        if perm.uid and perm.uid in params.team_cache:
                            if 'add_teams' not in request:
                                request['add_teams'] = []
                            team = params.team_cache[perm.uid]
                            request['add_teams'].append({
                                'team_uid':
                                perm.uid,
                                'manage_users':
                                perm.manage_users,
                                'manage_records':
                                perm.manage_records,
                                'shared_folder_key':
                                api.encrypt_aes(parent_key, team['team_key'])
                            })
                    else:
                        if 'add_users' not in request:
                            request['add_users'] = []
                        email = perm.name.lower()
                        if email == params.user.lower():
                            request['add_users'].append({
                                'username':
                                email,
                                'manage_users':
                                perm.manage_users,
                                'manage_records':
                                perm.manage_records,
                                'shared_folder_key':
                                api.encrypt_aes(parent_key, params.data_key)
                            })
                        elif email in emails:
                            public_key = emails[email]
                            if public_key:
                                try:
                                    rsa_key = RSA.importKey(
                                        base64.urlsafe_b64decode(public_key +
                                                                 '=='))
                                    request['add_users'].append({
                                        'username':
                                        email,
                                        'manage_users':
                                        perm.manage_users,
                                        'manage_records':
                                        perm.manage_records,
                                        'shared_folder_key':
                                        api.encrypt_rsa(parent_key, rsa_key)
                                    })
                                except:
                                    pass
            shared_folder_add.append(request)

    return shared_folder_add
Beispiel #10
0
import json

from data_vault import VaultEnvironment
from keepercommander import api, crypto, utils
from keepercommander.params import KeeperParams

_TREE_KEY = api.generate_aes_key()
_ENTERPRISE_ID = 123

_VAULT_ENV = VaultEnvironment()

_USE_DATA_KEY = True

_TEAM_KEY = api.generate_aes_key()
_TEAM1_UID = api.generate_record_uid()
_TEAM2_UID = api.generate_record_uid()
_TEAM1_NAME = 'Team 1'
_TEAM2_NAME = 'Team 2'

_NODE1_ID = (_ENTERPRISE_ID << 32) + 2
_NODE2_ID = (_ENTERPRISE_ID << 32) + 100

_USER1_ID = (_ENTERPRISE_ID << 32) + 201
_USER2_ID = (_ENTERPRISE_ID << 32) + 202
_USER2_EMAIL = '*****@*****.**'

_ROLE1_ID = (_ENTERPRISE_ID << 32) + 301
_ROLE1_NAME = 'Role 1'

_LAST_ID = 1000
Beispiel #11
0
def construct_import_rec_req(params, preexisting_record_hash, rec_to_import):
    """Build a rec_req for rec_to_import."""
    r_hash = build_record_hash(record=rec_to_import, tokenize_gen=tokenize_full_import_record)

    if r_hash in preexisting_record_hash:
        # Nothing to do.  We already have this identical record.
        return None
    else:
        rec_to_import.uid = api.generate_record_uid()
        preexisting_record_hash[r_hash] = rec_to_import.uid
        record_key = os.urandom(32)
        rec_req = folder_pb2.RecordRequest()
        rec_req.recordUid = base64.urlsafe_b64decode(rec_to_import.uid + '==')
        rec_req.recordType = 0
        rec_req.encryptedRecordKey = base64.urlsafe_b64decode(api.encrypt_aes(record_key, params.data_key) + '==')
        rec_req.howLongAgo = 0
        rec_req.folderType = 1

        folder_uid = None
        if rec_to_import.folders:
            folder_uid = rec_to_import.folders[0].uid
        if folder_uid:
            if folder_uid in params.folder_cache:
                folder = params.folder_cache[folder_uid]
                if folder.type in {BaseFolderNode.SharedFolderType, BaseFolderNode.SharedFolderFolderType}:
                    rec_req.folderUid = base64.urlsafe_b64decode(folder.uid + '==')
                    rec_req.folderType = 2 if folder.type == BaseFolderNode.SharedFolderType else 3

                    sh_uid = folder.uid if folder.type == BaseFolderNode.SharedFolderType else folder.shared_folder_uid
                    sf = params.shared_folder_cache[sh_uid]
                    rec_req.encryptedRecordFolderKey = base64.urlsafe_b64decode(
                        api.encrypt_aes(record_key, sf['shared_folder_key_unencrypted']) + '=='
                    )
                else:
                    rec_req.folderType = 1
                    if folder.type != BaseFolderNode.RootFolderType:
                        rec_req.folderUid = base64.urlsafe_b64decode(folder.uid + '==')

        custom_fields = []
        totp = None
        if rec_to_import.custom_fields:
            for cf in rec_to_import.custom_fields:
                if cf == TWO_FACTOR_CODE:
                    totp = rec_to_import.custom_fields[cf]
                else:
                    custom_fields.append({
                        'name': cf,
                        'value': rec_to_import.custom_fields[cf]
                    })

        data = {
            'title': rec_to_import.title or '',
            'secret1': rec_to_import.login or '',
            'secret2': rec_to_import.password or '',
            'link': rec_to_import.login_url or '',
            'notes': rec_to_import.notes or '',
            'custom': custom_fields
        }
        rec_req.recordData = base64.urlsafe_b64decode(api.encrypt_aes(json.dumps(data).encode('utf-8'), record_key) + '==')
        if totp:
            extra = {
                'fields': [
                    {
                        'id': api.generate_record_uid(),
                        'field_type': 'totp',
                        'field_title': 'Two-Factor Code',
                        'type': 0,
                        'data': totp
                    }]
            }
            rec_req.extra = base64.urlsafe_b64decode(api.encrypt_aes(json.dumps(extra).encode('utf-8'), record_key) + '==')
        return rec_req