Esempio n. 1
0
def init(owner, users, groups):
    """
    init will initialize a new share root as the given user principal. This
    includes setting up . and .. in the root directory, as well as adding the
    .users and .groups files that list trusted user public keys and group
    memberships respectively. This function will only allocate the share's
    root, but not map it to any particular share at the server. The new root's
    i is returned so that this can be done by the caller.
    """
    if not isinstance(owner, User):
        raise TypeError("{} is not a User, is a {}".format(owner, type(owner)))

    node = Inode()
    node.kind = 0
    node.ex = True
    node.ctime = time.time()
    node.mtime = node.ctime

    ihash = secfs.store.block.store(node.bytes(), None)  # inodes not encrypted
    root_i = secfs.tables.modmap(owner, I(owner), ihash)
    if root_i == None:
        raise RuntimeError

    new_ihash = secfs.store.tree.add(root_i, b'.', root_i)
    secfs.tables.modmap(owner, root_i, new_ihash)
    new_ihash = secfs.store.tree.add(
        root_i, b'..',
        root_i)  # TODO(eforde): why would .. be mapped to root_i?
    secfs.tables.modmap(owner, root_i, new_ihash)
    print("CREATED ROOT AT", new_ihash)

    init = {
        b".users": users,
        b".groups": groups,
    }

    import pickle
    for fn, c in init.items():
        bts = pickle.dumps(c)

        node = Inode()
        node.kind = 1
        node.size = len(bts)
        node.mtime = node.ctime
        node.ctime = time.time()
        node.blocks = [secfs.store.block.store(bts,
                                               None)]  # don't encrypt init

        ihash = secfs.store.block.store(node.bytes(),
                                        None)  # inodes not encrypted
        i = secfs.tables.modmap(owner, I(owner), ihash)
        link(owner, i, root_i, fn)

    return root_i
Esempio n. 2
0
def _create(parent_i, name, create_as, create_for, isdir):
    """
    _create allocates a new file, and links it into the directory at parent_i
    with the given name. The new file is owned by create_for, but is created
    using the credentials of create_as. This distinction is necessary as a user
    principal is needed for the final i when creating a file as a group.
    """
    if not isinstance(parent_i, I):
        raise TypeError("{} is not an I, is a {}".format(
            parent_i, type(parent_i)))
    if not isinstance(create_as, User):
        raise TypeError("{} is not a User, is a {}".format(
            create_as, type(create_as)))
    if not isinstance(create_for, Principal):
        raise TypeError("{} is not a Principal, is a {}".format(
            create_for, type(create_for)))

    assert create_as.is_user()  # only users can create
    assert create_as == create_for or create_for.is_group(
    )  # create for yourself or for a group

    if create_for.is_group() and create_for not in groupmap:
        raise PermissionError(
            "cannot create for unknown group {}".format(create_for))

    # This check is performed by link() below, but better to fail fast
    if not secfs.access.can_write(create_as, parent_i):
        if parent_i.p.is_group():
            raise PermissionError(
                "cannot create in group-writeable directory {0} as {1}; user is not in group"
                .format(parent_i, create_as))
        else:
            raise PermissionError(
                "cannot create in user-writeable directory {0} as {1}".format(
                    parent_i, create_as))

    node = Inode()
    node.ctime = time.time()
    node.mtime = node.ctime
    node.kind = 0 if isdir else 1
    node.ex = isdir

    # FIXME
    #
    # Here, you will need to:
    #
    #  - store the newly created inode (node.bytes()) on the server
    #  - map that block to an i owned by the user
    #  - if a directory is being created, create entries for . and ..
    #  - if create_for is a group, you will also have to create a group i for
    #    that group, and point it to the user's i
    #  - call link() to link the new i into the directory at parent_i with the
    #    given name
    #
    # Also make sure that you *return the final i* for the new inode!
    return I(User(0), 0)
Esempio n. 3
0
def _create(parent_i, name, create_as, create_for, isdir, encrypt):
    """
    _create allocates a new file, and links it into the directory at parent_i
    with the given name. The new file is owned by create_for, but is created
    using the credentials of create_as. This distinction is necessary as a user
    principal is needed for the final i when creating a file as a group.
    """

    if not isinstance(parent_i, I):
        raise TypeError("{} is not an I, is a {}".format(
            parent_i, type(parent_i)))
    if not isinstance(create_as, User):
        raise TypeError("{} is not a User, is a {}".format(
            create_as, type(create_as)))
    if not isinstance(create_for, Principal):
        raise TypeError("{} is not a Principal, is a {}".format(
            create_for, type(create_for)))

    assert create_as.is_user()  # only users can create
    assert create_as == create_for or create_for.is_group(
    )  # create for yourself or for a group

    if create_for.is_group() and create_for not in groupmap:
        raise PermissionError(
            "cannot create for unknown group {}".format(create_for))

    # This check is performed by link() below, but better to fail fast
    if not secfs.access.can_write(create_as, parent_i):
        if parent_i.p.is_group():
            raise PermissionError(
                "cannot create in group-writeable directory {0} as {1}; user is not in group"
                .format(parent_i, create_as))
        else:
            raise PermissionError(
                "cannot create in user-writeable directory {0} as {1}".format(
                    parent_i, create_as))

    # TODO(eforde): encrypt if parent directory is encrypted
    # encrypt = encrypt or parent_i.encrypted

    node = Inode()
    node.encrypted = 1 if encrypt else 0
    node.ctime = time.time()
    node.mtime = node.ctime
    node.kind = 0 if isdir else 1
    node.ex = isdir

    # store the newly created inode on the server
    new_hash = secfs.store.block.store(node.bytes(),
                                       None)  # inodes not encrypted
    # map the block to an i owned by create_for, created with credentials of create_as
    new_i = secfs.tables.modmap(create_as, I(create_for), new_hash)
    if isdir:
        # create . and .. if this is a directory
        table_key = secfs.tables.get_itable_key(create_for, create_as)
        new_ihash = secfs.store.tree.add(new_i, b'.', new_i, table_key)
        secfs.tables.modmap(create_as, new_i, new_ihash)
        new_ihash = secfs.store.tree.add(new_i, b'..', parent_i, table_key)
        secfs.tables.modmap(create_as, new_i, new_ihash)

    # link the new i into the directoy at parent_i with the given name
    link(create_as, new_i, parent_i, name)

    return new_i
Esempio n. 4
0
def _create(parent_i, name, create_as, create_for, isdir, encrypt):
    """
    _create allocates a new file, and links it into the directory at parent_i
    with the given name. The new file is owned by create_for, but is created
    using the credentials of create_as. This distinction is necessary as a user
    principal is needed for the final i when creating a file as a group.
    """
    if not isinstance(parent_i, I):
        raise TypeError("{} is not an I, is a {}".format(
            parent_i, type(parent_i)))
    if not isinstance(create_as, User):
        raise TypeError("{} is not a User, is a {}".format(
            create_as, type(create_as)))
    if not isinstance(create_for, Principal):
        raise TypeError("{} is not a Principal, is a {}".format(
            create_for, type(create_for)))

    assert create_as.is_user()  # only users can create
    assert create_as == create_for or create_for.is_group(
    )  # create for yourself or for a group

    if create_for.is_group() and create_for not in groupmap:
        raise PermissionError(
            "cannot create for unknown group {}".format(create_for))

    # This check is performed by link() below, but better to fail fast
    if not secfs.access.can_write(create_as, parent_i):
        if parent_i.p.is_group():
            raise PermissionError(
                "cannot create in group-writeable directory {0} as {1}; user is not in group"
                .format(parent_i, create_as))
        else:
            raise PermissionError(
                "cannot create in user-writeable directory {0} as {1}".format(
                    parent_i, create_as))

    node = Inode()
    node.ctime = time.time()
    node.mtime = node.ctime
    node.kind = 0 if isdir else 1
    node.ex = isdir

    # Encrypt if needed
    sym_key = None
    if encrypt:
        symkey = Fernet.generate_key()
        node.encrypt(create_for, symkey)

    # Here, you will need to:
    #
    #  - [DONE] store the newly created inode (node.bytes()) on the server
    #  - [DONE] map that block to an i owned by the user
    #  - [DONE] if a directory is being created, create entries for . and ..
    #  - [DONE] if create_for is a group, you will
    #    also have to create a group i for that group, and point it to the user's i
    #  - [DONE] call link() to link the new i into the directory at parent_i with the
    #    given name
    #
    # Also make sure that you *return the final i* for the new inode!

    new_ihash = secfs.store.block.store(node.bytes())
    new_i = secfs.tables.modmap(create_as, I(create_for), new_ihash)

    if isdir:
        # link calls tree.add and modmap within
        link(create_as, new_i, new_i, b'.')
        link(create_as, parent_i, new_i, b'..')

    # Finally link this directory to the parent
    link(create_as, new_i, parent_i, name)
    return new_i