Skip to content

Commit

Permalink
Always re-encrypt when fsck is invoked with --decrypt (gopasspw#2119)
Browse files Browse the repository at this point in the history
* Always re-encrypt when fsck is invoked with --decrypt
* Explain convertedSecret check

Fixes gopasspw#2015

RELEASE_NOTES=[BUGFIX] Always re-encrypt when fsck is invoked with --decrypt.

Signed-off-by: Dominik Schulz <[email protected]>
  • Loading branch information
dominikschulz authored Jan 18, 2022
1 parent 59da5f0 commit 1bac71a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 22 deletions.
20 changes: 20 additions & 0 deletions internal/backend/storage/gitfs/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package gitfs
import (
"context"
"fmt"

"github.com/gopasspw/gopass/pkg/debug"
)

// Get retrieves the named content.
Expand Down Expand Up @@ -58,9 +60,27 @@ func (g *Git) Fsck(ctx context.Context) error {
if err := g.fixConfig(ctx); err != nil {
return fmt.Errorf("failed to fix git config: %w", err)
}

// add any untracked files.
if err := g.addUntrackedFiles(ctx); err != nil {
return fmt.Errorf("failed to add untracked files: %w", err)
}
return g.fs.Fsck(ctx)
}

func (g *Git) addUntrackedFiles(ctx context.Context) error {
ut := g.ListUntrackedFiles(ctx)
if len(ut) < 1 && !g.HasStagedChanges(ctx) {
debug.Log("no untracked or staged files found")
return nil
}
debug.Log("untracked files found: %v", ut)
if err := g.Add(ctx, ut...); err != nil {
return fmt.Errorf("failed to add untracked files: %w", err)
}
return g.Commit(ctx, "fsck")
}

// Link creates a symlink.
func (g *Git) Link(ctx context.Context, from, to string) error {
return g.fs.Link(ctx, from, to)
Expand Down
54 changes: 32 additions & 22 deletions internal/store/leaf/fsck.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,42 @@ type convertedSecret interface {
}

func (s *Store) fsckCheckEntry(ctx context.Context, name string) error {
if err := s.fsckCheckRecipients(ctx, name); err != nil {
out.Warningf(ctx, "Checking recipients for %s failed: %s", name, err)
}

// make sure we can actually decode this secret
// if this fails there is no way we could fix this
if IsFsckDecrypt(ctx) {
// we need to make sure Parsing is enabled in order to parse old Mime secrets
ctx = ctxutil.WithShowParsing(ctx, true)
secret, err := s.Get(ctx, name)
if err != nil {
return fmt.Errorf("failed to decode secret %s: %w", name, err)
}
if cs, ok := secret.(convertedSecret); ok && cs.FromMime() {
out.Warningf(ctx, "leftover Mime secret: %s\nYou should consider editing it to re-encrypt it.", name)
}
if !IsFsckDecrypt(ctx) {
return nil
}

// we need to make sure Parsing is enabled in order to parse old Mime secrets
ctx = ctxutil.WithShowParsing(ctx, true)
sec, err := s.Get(ctx, name)
if err != nil {
return fmt.Errorf("failed to decode secret %s: %w", name, err)
}

// check if this is still an old MIME secret.
// Note: the secret was already converted when it was parsed during Get.
// This is just checking if it was converted from MIME or not.
// This branch is pretty much useless right now, but I'd like to add some
// reporting on how many secrets were converted from MIME to new format.
// TODO: report these stats
if cs, ok := sec.(convertedSecret); ok && cs.FromMime() {
debug.Log("leftover Mime secret: %s", name)
}

out.Printf(ctx, "Re-encrypting %s to fix recipients and storage format.", name)
if err := s.Set(ctxutil.WithCommitMessage(ctx, "fsck --decrypt to fix recipients and format"), name, sec); err != nil {
return fmt.Errorf("failed to write secret: %w", err)
}

return nil
}

func (s *Store) fsckCheckRecipients(ctx context.Context, name string) error {
// now compare the recipients this secret was encoded for and fix it if
// if doesn't match
ciphertext, err := s.storage.Get(ctx, s.passfile(name))
Expand Down Expand Up @@ -113,18 +135,6 @@ func (s *Store) fsckCheckEntry(ctx context.Context, name string) error {
if len(extra) > 0 {
out.Errorf(ctx, "Extra recipients on %s: %+v\nRun fsck with the --decrypt flag to re-encrypt it automatically, or edit this secret yourself.", name, extra)
}

if IsFsckDecrypt(ctx) && (len(missing) > 0 || len(extra) > 0) {
out.Printf(ctx, "Re-encrypting automatically %s to fix the recipients.", name)
sec, err := s.Get(ctx, name)
if err != nil {
return fmt.Errorf("failed to decode secret: %w", err)
}
if err := s.Set(ctxutil.WithCommitMessage(ctx, "fsck fix recipients"), name, sec); err != nil {
return fmt.Errorf("failed to write secret: %w", err)
}
}

return nil
}

Expand Down

0 comments on commit 1bac71a

Please sign in to comment.