Esempio n. 1
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. 2
0
def get_inode(i):
    """
    Shortcut for retrieving an inode given its i.
    """
    ihash = secfs.tables.resolve(i)
    if ihash == None:
        raise LookupError("asked to resolve i {}, but i does not exist".format(i))

    return Inode.load(ihash)
Esempio n. 3
0
def get_inode(i):
    """
    Shortcut for retrieving an inode given its i.
    """
    ihash = secfs.tables.resolve(i)
    if ihash == None:
        raise LookupError(
            "asked to resolve i {}, but i does not exist".format(i))

    return Inode.load(ihash)
Esempio n. 4
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. 5
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. 6
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. 7
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.
    """
    # TODO: when encrypted, figure out what to do with keys and encryption.
    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
    # Ex3-note: set node.encryptfor = create_for instead
    if encrypt:
        node.encryptfor = create_for
    else:
        node.encryptfor = None

    # Here, we followed the recommendations.  We did the following:
    #
    #  - store the newly created inode (node.bytes()) on the server
    ihash = secfs.store.block.store(node.bytes())

    #  - map that block to an i owned by the user
    i = secfs.tables.modmap(create_as, I(create_as), ihash)

    #  - if a directory is being created, create entries for . and ..
    if isdir:
        # Ex3-note: Send create_as to do encryption for dir.
        new_ihash = secfs.store.tree.add(create_as, i, b'.', i)
        secfs.tables.modmap(create_as, i, new_ihash)
        new_ihash = secfs.store.tree.add(create_as, i, b'..', parent_i)
        secfs.tables.modmap(create_as, i, new_ihash)

    #  - 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
    if create_for.is_group():
        i = secfs.tables.modmap(create_as, I(create_for), i)

    #  - call link() to link the new i into the directory at parent_i with the
    #    given name
    link(create_as, i, parent_i, name)
    #
    # Also make sure that you *return the final i* for the new inode!
    return i
Esempio n. 8
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.owner = owner
    node.ctime = time.time()
    node.mtime = node.ctime

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

    # Ex3-note: tree.add uses owner for any encryption needed (not needed)
    new_ihash = secfs.store.tree.add(owner, root_i, b'.', root_i)
    secfs.tables.modmap(owner, root_i, new_ihash)
    new_ihash = secfs.store.tree.add(owner, root_i, b'..', 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()
        # Ex3-note: write(owner) encrypts if if needed (not needed).
        node.write(owner, bts)

        ihash = secfs.store.block.store(node.bytes())
        i = secfs.tables.modmap(owner, I(owner), ihash)
        link(owner, i, root_i, fn)

    return root_i
Esempio n. 9
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
Esempio n. 10
0
def _create(parent_i, name, create_as, create_for, isdir, encrypt=False, symm_key=None):
    """
    _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(encrypt)
    node.ctime = time.time()
    node.mtime = node.ctime
    node.kind = 0 if isdir else 1
    node.ex = isdir

    parent_node = get_inode(parent_i)

    # 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!
    ihash = secfs.store.block.store(node.bytes())
    i = secfs.tables.modmap(create_as, I(create_as), ihash)
    if i == None:
        raise RuntimeError
    if isdir:
        new_ihash = secfs.store.tree.add(i, b".", i, symm_key)
        secfs.tables.modmap(create_as, i, new_ihash)
        new_ihash = secfs.store.tree.add(i, b"..", parent_i, symm_key)
        secfs.tables.modmap(create_as, i, new_ihash)
    if create_for.is_group():
        group_i = secfs.tables.modmap(create_as, I(create_for), i)
        # TODO:we don't know whether to link to i or group_i
        # Passes same number of tests (57)
        if not parent_node.encrypt:
            link(create_as, group_i, parent_i, name)
        else:
            link(create_as, group_i, parent_i, name, symm_key)
        return group_i
    if not parent_node.encrypt:
        link(create_as, i, parent_i, name)
    else:
        link(create_as, i, parent_i, name, symm_key)
    return i