Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ that looks like the following:
"policy_version": "2"
},
"use_fs_keyring_for_v1_policies": false
"metadata_dir": ""
}
```

Expand Down Expand Up @@ -310,6 +311,10 @@ The fields are:
kernels, it's better to not use this setting and instead (re-)create your
encrypted directories with `"policy_version": "2"`.

* "metadata_dir" specifies a path to store the fscrypt metadata directory
(.fscrypt). This is useful if you want to put this outside
of any filesystem or directory configured for encryption.

## Setting up for login protectors

If you want any encrypted directories to be protected by your login passphrase,
Expand Down Expand Up @@ -456,15 +461,18 @@ copy the contents of the source directory into it.

For directories protected by a `custom_passphrase` or `raw_key` protector, all
metadata needed to unlock the directory (excluding the actual passphrase or raw
key, of course) is located in the `.fscrypt` directory at the root of the
filesystem that contains the encrypted directory. For example, if you have an
encrypted directory `/home/$USER/private` that is protected by a custom
key, of course) is located by default in the `.fscrypt` directory at the root
of the filesystem that contains the encrypted directory. For example, if you
have an encrypted directory `/home/$USER/private` that is protected by a custom
passphrase, all `fscrypt` metadata needed to unlock the directory with that
custom passphrase will be located in `/home/.fscrypt` if you are using a
dedicated `/home` filesystem or in `/.fscrypt` if you aren't. If desired, you
can back up the `fscrypt` metadata by making a copy of this directory, although
this isn't too important since this metadata is located on the same filesystem
as the encrypted directory(s).
custom passphrase will be located by default in `/home/.fscrypt` if you are
using a dedicated `/home` filesystem or in `/.fscrypt` if you aren't.
Alternately, you can specify a different location for fscrypt metadata by
setting the `"metadata_dir"` field in the [Configuration
file](#configuration-file).
If desired, you can back up the `fscrypt` metadata by making a copy of this
directory, although this isn't too important since this metadata is located on
the same filesystem as the encrypted directory(s).

`pam_passphrase` (login passphrase) protectors are a bit different as they are
always stored on the root filesystem, in `/.fscrypt`. This ties them to the
Expand Down
2 changes: 2 additions & 0 deletions actions/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func NewContextFromPath(path string, targetUser *user.User) (*Context, error) {
if ctx.Mount, err = filesystem.FindMount(path); err != nil {
return nil, err
}
ctx.Mount.MetadataPath = ctx.Config.MetadataDir

log.Printf("%s is on %s filesystem %q (%s)", path,
ctx.Mount.FilesystemType, ctx.Mount.Path, ctx.Mount.Device)
Expand All @@ -90,6 +91,7 @@ func NewContextFromMountpoint(mountpoint string, targetUser *user.User) (*Contex
if ctx.Mount, err = filesystem.GetMount(mountpoint); err != nil {
return nil, err
}
ctx.Mount.MetadataPath = ctx.Config.MetadataDir

log.Printf("found %s filesystem %q (%s)", ctx.Mount.FilesystemType,
ctx.Mount.Path, ctx.Mount.Device)
Expand Down
19 changes: 19 additions & 0 deletions cli-tests/t_metadata_dir.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

# fscrypt setup filesystem
Metadata directories created at "MNT_ROOT/fscrypt_metadata/.fscrypt".

# fscrypt encrypt directory
policies
protectors
"MNT/dir" is encrypted with fscrypt.

Policy: desc1
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: Yes

Protected with 1 protector:
PROTECTOR LINKED DESCRIPTION
desc2 No custom protector "prot"

# Lock directory
"MNT/dir" is now locked.
35 changes: 35 additions & 0 deletions cli-tests/t_metadata_dir.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash

# Test metadata_dir config option.

cd "$(dirname "$0")"
. common.sh

# filesystem setup

mddir=$MNT_ROOT/fscrypt_metadata
mkdir "$mddir"
sed -e "s+\"metadata_dir\": \"\"+\"metadata_dir\": \"$mddir\"+" \
-i "$FSCRYPT_CONF"

dir="$MNT/dir"
mkdir "$dir"

_print_header "fscrypt setup filesystem"
_rm_metadata "$MNT"
fscrypt setup "$MNT"
[ ! -e "$MNT/.fscrypt" ]
[ -e "$mddir/.fscrypt" ]

_print_header "fscrypt encrypt directory"
echo hunter2 | fscrypt encrypt --quiet --source=custom_passphrase --name=prot "$dir"
ls "$mddir"/.fscrypt
[ -n "$(find "$mddir"/.fscrypt/policies -type f)" ]
[ -n "$(find "$mddir"/.fscrypt/protectors -type f)" ]
fscrypt status "$dir"
echo contents > "$dir"/file

_print_header "Lock directory"
fscrypt lock "$dir"

rm -rf "$mddir"
10 changes: 9 additions & 1 deletion filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ var SortDescriptorsByLastMtime = false
// "/", meaning that the entire filesystem is mounted, but
// it can differ for bind mounts.
// ReadOnly - True if this is a read-only mount
// MetadataPath - Absolute path to store metadata information, if
// different from mountpoint.
//
// In order to use a Mount to store fscrypt metadata, some directories must be
// setup first. Specifically, the directories created look like:
Expand Down Expand Up @@ -176,6 +178,7 @@ type Mount struct {
DeviceNumber DeviceNumber
Subtree string
ReadOnly bool
MetadataPath string
}

// PathSorter allows mounts to be sorted by Path.
Expand Down Expand Up @@ -211,7 +214,12 @@ func (m *Mount) String() string {

// BaseDir returns the path to the base fscrypt directory for this filesystem.
func (m *Mount) BaseDir() string {
rawBaseDir := filepath.Join(m.Path, baseDirName)
rawBaseDir := ""
if m.MetadataPath != "" {
rawBaseDir = filepath.Join(m.MetadataPath, baseDirName)
} else {
rawBaseDir = filepath.Join(m.Path, baseDirName)
}
// We allow the base directory to be a symlink, but some callers need
// the real path, so dereference the symlink here if needed. Since the
// directory the symlink points to may not exist yet, we have to read
Expand Down
6 changes: 5 additions & 1 deletion metadata/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ var testConfigString = `{
"filenames": "AES_256_CTS",
"policy_version": "1"
},
"use_fs_keyring_for_v1_policies": false
"use_fs_keyring_for_v1_policies": false,
"metadata_dir": ""
}
`

Expand Down Expand Up @@ -104,6 +105,9 @@ func TestOptionalFields(t *testing.T) {
if cfg.GetUseFsKeyringForV1Policies() {
t.Error("use_fs_keyring_for_v1_policies should be false, but was true")
}
if cfg.GetMetadataDir() != "" {
t.Errorf("metadata_dir should be empty, but was %s", cfg.GetMetadataDir())
}
if cfg.Options.PolicyVersion != 0 {
t.Errorf("policy version should be 0, but was %d", cfg.Options.PolicyVersion)
}
Expand Down
Loading