Skip to content

Commit 7813af7

Browse files
authored
Merge pull request #338 from google/remove-protector-from-policy
cmd/fscrypt: don't load protector in remove-protector-from-policy
2 parents 6ec8ee0 + 6ebd5a5 commit 7813af7

8 files changed

Lines changed: 108 additions & 24 deletions

File tree

actions/policy.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -461,14 +461,15 @@ func (policy *Policy) AddProtector(protector *Protector) error {
461461
}
462462

463463
// RemoveProtector updates the data that is wrapping the Policy Key so that the
464-
// provided Protector is no longer protecting the specified Policy. If an error
465-
// is returned, no data has been changed. Note that no protector links are
464+
// protector with the given descriptor is no longer protecting the specified
465+
// Policy. If an error is returned, no data has been changed. Note that the
466+
// protector itself won't be removed, nor will a link to the protector be
466467
// removed (in the case where the protector and policy are on different
467-
// filesystems). The policy and protector can be locked or unlocked.
468-
func (policy *Policy) RemoveProtector(protector *Protector) error {
469-
idx, ok := policy.findWrappedKeyIndex(protector.Descriptor())
468+
// filesystems). The policy can be locked or unlocked.
469+
func (policy *Policy) RemoveProtector(protectorDescriptor string) error {
470+
idx, ok := policy.findWrappedKeyIndex(protectorDescriptor)
470471
if !ok {
471-
return &ErrNotProtected{policy.Descriptor(), protector.Descriptor()}
472+
return &ErrNotProtected{policy.Descriptor(), protectorDescriptor}
472473
}
473474

474475
if len(policy.data.WrappedPolicyKeys) == 1 {

actions/policy_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func TestPolicyGoodRemoveProtector(t *testing.T) {
114114
t.Fatal(err)
115115
}
116116

117-
err = pol.RemoveProtector(pro1)
117+
err = pol.RemoveProtector(pro1.Descriptor())
118118
if err != nil {
119119
t.Error(err)
120120
}
@@ -135,11 +135,11 @@ func TestPolicyBadRemoveProtector(t *testing.T) {
135135
}
136136
defer cleanupProtector(pro2)
137137

138-
if pol.RemoveProtector(pro2) == nil {
138+
if pol.RemoveProtector(pro2.Descriptor()) == nil {
139139
t.Error("we should not be able to remove a protector we did not add")
140140
}
141141

142-
if pol.RemoveProtector(pro1) == nil {
142+
if pol.RemoveProtector(pro1.Descriptor()) == nil {
143143
t.Error("we should not be able to remove all the protectors from a policy")
144144
}
145145
}

cli-tests/common.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,40 @@ _get_enabled_fs_count()
7272
echo "$count"
7373
}
7474

75+
# Gets the descriptor of the given protector.
76+
_get_protector_descriptor()
77+
{
78+
local mnt=$1
79+
local source=$2
80+
81+
case $source in
82+
custom)
83+
local name=$3
84+
local description="custom protector \\\"$name\\\""
85+
;;
86+
login)
87+
local user=$3
88+
local description="login protector for $user"
89+
;;
90+
*)
91+
_fail "Unknown protector source $source"
92+
esac
93+
94+
local descriptor
95+
descriptor=$(fscrypt status "$mnt" |
96+
awk -F ' *' '{ if ($3 == "'"$description"'") print $1 }')
97+
if [ -z "$descriptor" ]; then
98+
_fail "Can't find $description on $mnt"
99+
fi
100+
echo "$descriptor"
101+
}
102+
103+
# Gets the descriptor of the login protector for $TEST_USER.
104+
_get_login_descriptor()
105+
{
106+
_get_protector_descriptor "$MNT_ROOT" login "$TEST_USER"
107+
}
108+
75109
# Prints the number of filesystems that have fscrypt metadata.
76110
_get_setup_fs_count()
77111
{

cli-tests/t_change_passphrase.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ echo pass1 | fscrypt encrypt --quiet --name=prot --skip-unlock "$dir"
1414
_print_header "Try to unlock with wrong passphrase"
1515
_expect_failure "echo pass2 | fscrypt unlock --quiet '$dir'"
1616
_expect_failure "mkdir '$dir/subdir'"
17-
protector=$(fscrypt status "$dir" | awk '/custom protector/{print $1}')
17+
protector=$(_get_protector_descriptor "$dir" custom prot)
1818

1919
_print_header "Change passphrase"
2020
echo $'pass1\npass2' | \

cli-tests/t_encrypt_login.sh

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,13 @@ show_status()
2727
fi
2828
}
2929

30-
get_login_protector()
31-
{
32-
fscrypt status "$dir" | awk '/login protector/{print $1}'
33-
}
34-
3530
begin "Encrypt with login protector"
3631
chown "$TEST_USER" "$dir"
3732
_user_do "echo TEST_USER_PASS | fscrypt encrypt --quiet --source=pam_passphrase '$dir'"
3833
show_status true
3934
recovery_passphrase=$(grep -E '^ +[a-z]{20}$' "$dir/fscrypt_recovery_readme.txt" | sed 's/^ +//')
40-
recovery_protector=$(fscrypt status "$dir" | awk '/Recovery passphrase/{print $1}')
41-
login_protector=$(get_login_protector)
35+
recovery_protector=$(_get_protector_descriptor "$MNT" custom 'Recovery passphrase for dir')
36+
login_protector=$(_get_login_descriptor)
4237
_print_header "=> Lock, then unlock with login passphrase"
4338
_user_do "fscrypt lock '$dir'"
4439
# FIXME: should we be able to use $MNT:$login_protector here?
@@ -63,7 +58,7 @@ begin "Encrypt with login protector as root"
6358
echo TEST_USER_PASS | fscrypt encrypt --quiet --source=pam_passphrase --user="$TEST_USER" "$dir"
6459
show_status true
6560
# The newly-created login protector should be owned by the user, not root.
66-
login_protector=$(get_login_protector)
61+
login_protector=$(_get_login_descriptor)
6762
owner=$(stat -c "%U:%G" "$MNT_ROOT/.fscrypt/protectors/$login_protector")
6863
echo -e "\nProtector is owned by $owner"
6964

cli-tests/t_metadata.out

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
ext4 filesystem "MNT" has 3 protectors and 1 policy
2+
3+
PROTECTOR LINKED DESCRIPTION
4+
desc1 No custom protector "foo"
5+
desc2 No custom protector "bar"
6+
desc3 No custom protector "baz"
7+
8+
POLICY UNLOCKED PROTECTORS
9+
desc4 No desc1, desc2, desc3
10+
ext4 filesystem "MNT" has 2 protectors and 1 policy
11+
12+
PROTECTOR LINKED DESCRIPTION
13+
desc1 No custom protector "foo"
14+
desc2 No custom protector "bar"
15+
16+
POLICY UNLOCKED PROTECTORS
17+
desc4 No desc1

cli-tests/t_metadata.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
3+
# Test 'fscrypt metadata'.
4+
5+
cd "$(dirname "$0")"
6+
. common.sh
7+
8+
# Create three protectors, and a policy protected by them.
9+
echo foo | fscrypt metadata create protector "$MNT" \
10+
--quiet --name=foo --source=custom_passphrase
11+
echo bar | fscrypt metadata create protector "$MNT" \
12+
--quiet --name=bar --source=custom_passphrase
13+
echo baz | fscrypt metadata create protector "$MNT" \
14+
--quiet --name=baz --source=custom_passphrase
15+
prot_foo=$MNT:$(_get_protector_descriptor "$MNT" custom foo)
16+
prot_bar=$MNT:$(_get_protector_descriptor "$MNT" custom bar)
17+
desc_baz=$(_get_protector_descriptor "$MNT" custom baz)
18+
prot_baz=$MNT:$desc_baz
19+
echo foo | fscrypt metadata create policy "$MNT" --quiet \
20+
--protector="$prot_foo"
21+
policy=$MNT:$(fscrypt status "$MNT" | grep -A10 "^POLICY" | \
22+
tail -1 | awk '{print $1}')
23+
echo -e "bar\nfoo" | fscrypt metadata add-protector-to-policy --quiet \
24+
--policy="$policy" --protector="$prot_bar"
25+
echo -e "baz\nfoo" | fscrypt metadata add-protector-to-policy --quiet \
26+
--policy="$policy" --protector="$prot_baz" --unlock-with="$prot_foo"
27+
fscrypt status "$MNT"
28+
29+
# Remove two of the protectors from the policy.
30+
# Make sure that this works even if the protector was already deleted.
31+
fscrypt metadata remove-protector-from-policy --quiet --force \
32+
--policy="$policy" --protector="$prot_bar"
33+
rm "$MNT/.fscrypt/protectors/$desc_baz"
34+
fscrypt metadata remove-protector-from-policy --quiet --force \
35+
--policy="$policy" --protector="$prot_baz"
36+
fscrypt status "$MNT"

cmd/fscrypt/commands.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,29 +1083,30 @@ func removeProtectorAction(c *cli.Context) error {
10831083
return err
10841084
}
10851085

1086-
// We do not need to unlock anything for this operation
1087-
protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
1086+
// We only need the protector descriptor, not the protector itself.
1087+
ctx, protectorDescriptor, err := parseMetadataFlag(protectorFlag.Value, nil)
10881088
if err != nil {
10891089
return newExitError(c, err)
10901090
}
1091-
policy, err := getPolicyFromFlag(policyFlag.Value, protector.Context.TargetUser)
1091+
// We don't need to unlock the policy for this operation.
1092+
policy, err := getPolicyFromFlag(policyFlag.Value, ctx.TargetUser)
10921093
if err != nil {
10931094
return newExitError(c, err)
10941095
}
10951096

10961097
prompt := fmt.Sprintf("Stop protecting policy %s with protector %s?",
1097-
policy.Descriptor(), protector.Descriptor())
1098+
policy.Descriptor(), protectorDescriptor)
10981099
warning := "All files using this policy will NO LONGER be accessible with this protector!!"
10991100
if err := askConfirmation(prompt, false, warning); err != nil {
11001101
return newExitError(c, err)
11011102
}
11021103

1103-
if err := policy.RemoveProtector(protector); err != nil {
1104+
if err := policy.RemoveProtector(protectorDescriptor); err != nil {
11041105
return newExitError(c, err)
11051106
}
11061107

11071108
fmt.Fprintf(c.App.Writer, "Protector %s no longer protecting policy %s.\n",
1108-
protector.Descriptor(), policy.Descriptor())
1109+
protectorDescriptor, policy.Descriptor())
11091110
return nil
11101111
}
11111112

0 commit comments

Comments
 (0)