Skip to content

Commit

Permalink
Set vim options instead of sniffing the config (#2343)
Browse files Browse the repository at this point in the history
* Set vim options instead of sniffing the config

Fixes #2317

RELEASE_NOTES=[ENHANCEMENT] Set vim options instead of sniffing

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

* Add a note on vim hardening flags to the docs.

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>
  • Loading branch information
dominikschulz authored Sep 20, 2022
1 parent 7962f08 commit cb634f8
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 62 deletions.
25 changes: 18 additions & 7 deletions docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Alternatively, it can be installed via [chocolatey](https://chocolatey.org/packa
#### OpenBSD

For OpenBSD -current:

```
pkg_add gopass
```
Expand Down Expand Up @@ -117,6 +118,7 @@ touch foo
git add foo
git commit -S -m "test"
```

Here the `-S` flag will sign your commit using GPG, allowing you to test your GPG setup with git.
If you get an error like: "gpg failed to sign the data" try to see if creating a clear text signature works:

Expand All @@ -131,6 +133,7 @@ If this fails with an error: "Inappropriate ioctl for device" run the following
```

If you are using CSH or TCSH:

```
setenv GPG_TTY `tty`
```
Expand All @@ -141,6 +144,7 @@ If you are presented with a different error please investigate this before conti
set it in your `.zprofile`, `.bashrc` or simliar.

Also if you have both `gnupg` and `gnupg2` installed, make sure to use the latter in git:

```bash
git config --global gpg.program gpg2
```
Expand Down Expand Up @@ -287,6 +291,9 @@ autocmd BufNewFile,BufRead /dev/shm/gopass* setlocal noswapfile nobackup noundof
autocmd BufNewFile,BufRead /private/**/gopass** setlocal noswapfile nobackup noundofile viminfo=""
```

Note: gopass will attempt to detect the correct hardning flags to be used for the editor. It will pass them on
invocation.

### Migrating from pass to gopass

If you are migrating from pass to gopass, you can simply use your existing password store and everything should just work. Furthermore, it may be helpful to link the gopass binary so that you can use it as a drop-in replacement. For example, assuming `$HOME/bin/` exists and is present in your `$PATH`:
Expand Down Expand Up @@ -320,11 +327,12 @@ If you use zsh, `make install` or `make install-completion` should install the c
If zsh autocompletion is still not functional, or if you want to install it manually, you can run the following commands:

```bash
$ gopass completion zsh > ~/_gopass
$ sudo mv ~/_gopass /usr/share/zsh/site-functions/_gopass
$ rm -i ${ZDOTDIR:-${HOME:?No ZDOTDIR or HOME}}/.zcompdump && compinit
gopass completion zsh > ~/_gopass
sudo mv ~/_gopass /usr/share/zsh/site-functions/_gopass
rm -i ${ZDOTDIR:-${HOME:?No ZDOTDIR or HOME}}/.zcompdump && compinit

```

Then exit and re-run zsh if the last command failed.

Notice that it is important to directly redirect Gopass' output to a file,
Expand All @@ -334,17 +342,21 @@ completions directory, as defined by either the standard `/usr/share/zsh/site-fu
or by a user-specified `fpath` folder. It is not meant to used with `source`.

If zsh completion is still not working, you might want to add the following to your `.zshrc` file:

```bash
autoload -U compinit && compinit
```

if you don't have it already.

### Enable fish completion

If you use the [fish](https://fishshell.com/) shell, you can enable experimental shell completion by the following command:

```fish
$ mkdir -p ~/.config/fish/completions and; gopass completion fish > ~/.config/fish/completions/gopass.fish
mkdir -p ~/.config/fish/completions and; gopass completion fish > ~/.config/fish/completions/gopass.fish
```

and start a new shell afterwards.

Since writing fish completion scripts is not yet supported by the CLI library we use, this completion script is missing a few features. Feel free to contribute if you want to improve it.
Expand Down Expand Up @@ -415,10 +427,10 @@ $ gopass setup --crypto gpg --storage gitfs # used by default
If you have created a password store with `git`, `gopass` can easily clone it.

```bash
$ gopass clone git@gitlab.example.org:john/passwords.git
gopass clone git@gitlab.example.org:john/passwords.git
```

### Storing and Syncing your Password Store with Google Drive / Dropbox / Syncthing / etc.
### Storing and Syncing your Password Store with Google Drive / Dropbox / Syncthing / etc

The recommended way to use Gopass is to sync your store with a git repository, preferably a private one, since the name and path of your secrets might reveal information that you'd prefer to keep private.
However, shall you prefer to, you might also use the `noop` storage backend that is meant to store data on a cloud provider instead of a git server.
Expand Down Expand Up @@ -471,4 +483,3 @@ It will fail if the remote at `github.com/example/pass.git` is not empty.

The second command will clone the existing (no `--create` flag) remote `github.com/example/pass.git`
and mount it as the mount point `example`.

3 changes: 0 additions & 3 deletions internal/action/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ func (s *Action) Edit(c *cli.Context) error {

func (s *Action) edit(ctx context.Context, c *cli.Context, name string) error {
ed := editor.Path(c)
if err := editor.Check(ctx, ed); err != nil {
out.Warningf(ctx, "Failed to check editor config: %s", err)
}

// get existing content or generate new one from a template.
name, content, changed, err := s.editGetContent(ctx, name, c.Bool("create"))
Expand Down
4 changes: 0 additions & 4 deletions internal/action/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/gopasspw/gopass/internal/action/exit"
"github.com/gopasspw/gopass/internal/audit"
"github.com/gopasspw/gopass/internal/editor"
"github.com/gopasspw/gopass/internal/out"
"github.com/gopasspw/gopass/internal/queue"
"github.com/gopasspw/gopass/pkg/ctxutil"
"github.com/gopasspw/gopass/pkg/debug"
Expand All @@ -31,9 +30,6 @@ func (s *Action) Merge(c *cli.Context) error {
}

ed := editor.Path(c)
if err := editor.Check(ctx, ed); err != nil {
out.Warningf(ctx, "Failed to check editor config: %s", err)
}

content := &bytes.Buffer{}
for _, k := range c.Args().Slice() {
Expand Down
76 changes: 28 additions & 48 deletions internal/editor/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@ import (
"io"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"

"github.com/fatih/color"
"github.com/gopasspw/gopass/internal/out"
"github.com/gopasspw/gopass/pkg/ctxutil"
"github.com/gopasspw/gopass/pkg/debug"
"github.com/gopasspw/gopass/pkg/fsutil"
"github.com/gopasspw/gopass/pkg/tempfile"
shellquote "github.com/kballard/go-shellquote"
)
Expand All @@ -27,47 +22,9 @@ var (
// Stdout is exported for tests.
Stdout io.Writer = os.Stdout
// Stderr is exported for tests.
Stderr io.Writer = os.Stderr
vimOptsRe = regexp.MustCompile(`au(tocmd)?\s+BufNewFile,BufRead\s+.*gopass.*setlocal\s+noswapfile\s+nobackup\s+noundofile\s+viminfo=`)
Stderr io.Writer = os.Stderr
)

// Check will validate the editor config.
func Check(ctx context.Context, editor string) error {
if !strings.Contains(editor, "vi") {
return nil
}

uhd, err := os.UserHomeDir()
if err != nil {
return err
}

vrc := filepath.Join(uhd, ".vimrc")
if runtime.GOOS == "windows" {
vrc = filepath.Join(uhd, "_vimrc")
}

if !fsutil.IsFile(vrc) {
return nil
}

buf, err := os.ReadFile(vrc)
if err != nil {
return err
}

if vimOptsRe.Match(buf) {
debug.Log("Recommended settings found in %s", vrc)

return nil
}

debug.Log("%s did not match %s", string(buf), vimOptsRe)
out.Warningf(ctx, "Vim might leak credentials. Check your setup.\nhttps://go.gopass.pw/setup#securing-your-editor")

return nil
}

// Invoke will start the given editor and return the content.
func Invoke(ctx context.Context, editor string, content []byte) ([]byte, error) {
if !ctxutil.IsTerminal(ctx) {
Expand All @@ -93,19 +50,20 @@ func Invoke(ctx context.Context, editor string, content []byte) ([]byte, error)
return []byte{}, fmt.Errorf("failed to close tmpfile to start with %s %v: %w", editor, tmpfile.Name(), err)
}

var args []string
args := make([]string, 0, 4)
if runtime.GOOS != "windows" {
cmdArgs, err := shellquote.Split(editor)
if err != nil {
return []byte{}, fmt.Errorf("failed to parse EDITOR command `%s`", editor)
}

editor = cmdArgs[0]
args = append(cmdArgs[1:], tmpfile.Name())
} else {
args = []string{tmpfile.Name()}
args = append(args, cmdArgs[1:]...)
args = append(args, vimOptions(editor)...)
}

args = append(args, tmpfile.Name())

cmd := exec.Command(editor, args...)
cmd.Stdin = Stdin
cmd.Stdout = Stdout
Expand All @@ -128,3 +86,25 @@ func Invoke(ctx context.Context, editor string, content []byte) ([]byte, error)

return nContent, nil
}

func vimOptions(editor string) []string {
if editor != "vi" && editor != "vim" && editor != "neovim" {
return []string{}
}

path := "/dev/shm/gopass*"
if runtime.GOOS == "darwin" {
path = "/private/**/gopass**"
}
viminfo := `viminfo=""`
if editor == "neovim" {
viminfo = `shada=""`
}

return []string{
"-i", "NONE", // disable viminfo
"-n", // disable swap
"-c",
fmt.Sprintf("autocmd BufNewFile,BufRead %s setlocal noswapfile nobackup noundofile %s", path, viminfo),
}
}

0 comments on commit cb634f8

Please sign in to comment.