key add/passwd: handle UTF-16 encoding correctly

Just use the exact some function for load a password from a file
everywhere.
This commit is contained in:
Michael Eischer 2024-06-05 22:14:45 +02:00
parent ef85a81e83
commit c55665be2c
3 changed files with 19 additions and 15 deletions

View file

@ -0,0 +1,8 @@
Bugfix: correctly handle UTF-16 password files in `key add/passwd`
`key add` and `key passwd` did not properly decode UTF-16 encoded password read
from a password file. This has been fix to match the decoding when opening a
repository.
https://github.com/restic/restic/issues/4850
https://github.com/restic/restic/pull/4851

View file

@ -3,8 +3,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"os"
"strings"
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/repository"
@ -123,14 +121,6 @@ func getNewPassword(ctx context.Context, gopts GlobalOptions, newPasswordFile st
"enter password again: ") "enter password again: ")
} }
func loadPasswordFromFile(pwdFile string) (string, error) {
s, err := os.ReadFile(pwdFile)
if os.IsNotExist(err) {
return "", errors.Fatalf("%s does not exist", pwdFile)
}
return strings.TrimSpace(string(s)), errors.Wrap(err, "Readfile")
}
func switchToNewKeyAndRemoveIfBroken(ctx context.Context, repo *repository.Repository, key *repository.Key, pw string) error { func switchToNewKeyAndRemoveIfBroken(ctx context.Context, repo *repository.Repository, key *repository.Key, pw string) error {
// Verify new key to make sure it really works. A broken key can render the // Verify new key to make sure it really works. A broken key can render the
// whole repository inaccessible // whole repository inaccessible

View file

@ -268,11 +268,7 @@ func resolvePassword(opts GlobalOptions, envStr string) (string, error) {
return (strings.TrimSpace(string(output))), nil return (strings.TrimSpace(string(output))), nil
} }
if opts.PasswordFile != "" { if opts.PasswordFile != "" {
s, err := textfile.Read(opts.PasswordFile) return loadPasswordFromFile(opts.PasswordFile)
if errors.Is(err, os.ErrNotExist) {
return "", errors.Fatalf("%s does not exist", opts.PasswordFile)
}
return strings.TrimSpace(string(s)), errors.Wrap(err, "Readfile")
} }
if pwd := os.Getenv(envStr); pwd != "" { if pwd := os.Getenv(envStr); pwd != "" {
@ -282,6 +278,16 @@ func resolvePassword(opts GlobalOptions, envStr string) (string, error) {
return "", nil return "", nil
} }
// loadPasswordFromFile loads a password from a file while stripping a BOM and
// converting the password to UTF-8.
func loadPasswordFromFile(pwdFile string) (string, error) {
s, err := textfile.Read(pwdFile)
if errors.Is(err, os.ErrNotExist) {
return "", errors.Fatalf("%s does not exist", pwdFile)
}
return strings.TrimSpace(string(s)), errors.Wrap(err, "Readfile")
}
// readPassword reads the password from the given reader directly. // readPassword reads the password from the given reader directly.
func readPassword(in io.Reader) (password string, err error) { func readPassword(in io.Reader) (password string, err error) {
sc := bufio.NewScanner(in) sc := bufio.NewScanner(in)