Remove explicit key handling

This commit is contained in:
Alexander Neumann 2014-12-21 18:10:19 +01:00
parent cc147c002e
commit ef41a77aff
14 changed files with 113 additions and 144 deletions

View File

@ -22,9 +22,8 @@ const (
)
type Archiver struct {
s Server
key *Key
ch *ContentHandler
s Server
ch *ContentHandler
bl *BlobList // blobs used for the current snapshot
parentBl *BlobList // blobs from the parent snapshot
@ -58,11 +57,10 @@ func (s *Stats) Add(other Stats) {
s.Other += other.Other
}
func NewArchiver(s Server, key *Key) (*Archiver, error) {
func NewArchiver(s Server) (*Archiver, error) {
var err error
arch := &Archiver{
s: s,
key: key,
fileToken: make(chan struct{}, maxConcurrentFiles),
blobToken: make(chan struct{}, maxConcurrentBlobs),
}
@ -82,7 +80,7 @@ func NewArchiver(s Server, key *Key) (*Archiver, error) {
arch.Filter = func(string, os.FileInfo) bool { return true }
arch.bl = NewBlobList()
arch.ch, err = NewContentHandler(s, key)
arch.ch, err = NewContentHandler(s)
if err != nil {
return nil, err
}

View File

@ -72,7 +72,7 @@ func (cmd CmdBackup) Execute(args []string) error {
return fmt.Errorf("wrong number of parameters, Usage: %s", cmd.Usage())
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
@ -81,7 +81,7 @@ func (cmd CmdBackup) Execute(args []string) error {
target := args[0]
if len(args) > 1 {
parentSnapshotID, err = backend.FindSnapshot(be, args[1])
parentSnapshotID, err = s.FindSnapshot(args[1])
if err != nil {
return fmt.Errorf("invalid id %q: %v", args[1], err)
}
@ -89,7 +89,7 @@ func (cmd CmdBackup) Execute(args []string) error {
fmt.Printf("found parent snapshot %v\n", parentSnapshotID)
}
arch, err := restic.NewArchiver(be, key)
arch, err := restic.NewArchiver(s)
if err != nil {
fmt.Fprintf(os.Stderr, "err: %v\n", err)
}
@ -183,7 +183,7 @@ func (cmd CmdBackup) Execute(args []string) error {
close(arch.ScannerStats)
}
plen, err := backend.PrefixLength(be, backend.Snapshot)
plen, err := s.PrefixLength(backend.Snapshot)
if err != nil {
return err
}

View File

@ -31,7 +31,7 @@ func (cmd CmdCat) Execute(args []string) error {
return fmt.Errorf("type or ID not specified, Usage: %s", cmd.Usage())
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
@ -47,13 +47,13 @@ func (cmd CmdCat) Execute(args []string) error {
}
// find snapshot id with prefix
id, err = backend.Find(be, backend.Snapshot, args[1])
id, err = s.FindSnapshot(args[1])
if err != nil {
return err
}
}
ch, err := restic.NewContentHandler(be, key)
ch, err := restic.NewContentHandler(s)
if err != nil {
return err
}
@ -73,13 +73,13 @@ func (cmd CmdCat) Execute(args []string) error {
}
// try storage id
buf, err := be.Get(backend.Data, id)
buf, err := s.Get(backend.Data, id)
if err != nil {
return err
}
// decrypt
buf, err = key.Decrypt(buf)
buf, err = s.Decrypt(buf)
if err != nil {
return err
}
@ -98,13 +98,13 @@ func (cmd CmdCat) Execute(args []string) error {
err := ch.LoadJSON(backend.Tree, id, &tree)
if err != nil {
// try storage id
buf, err := be.Get(backend.Tree, id)
buf, err := s.Get(backend.Tree, id)
if err != nil {
return err
}
// decrypt
buf, err = key.Decrypt(buf)
buf, err = s.Decrypt(buf)
if err != nil {
return err
}
@ -156,7 +156,7 @@ func (cmd CmdCat) Execute(args []string) error {
return nil
case "key":
data, err := be.Get(backend.Key, id)
data, err := s.Get(backend.Key, id)
if err != nil {
return err
}

View File

@ -110,10 +110,10 @@ func (c CmdFind) findInTree(ch *restic.ContentHandler, id backend.ID, path strin
return results, nil
}
func (c CmdFind) findInSnapshot(be restic.Server, key *restic.Key, id backend.ID) error {
func (c CmdFind) findInSnapshot(s restic.Server, id backend.ID) error {
debug("searching in snapshot %s\n for entries within [%s %s]", id, c.oldest, c.newest)
ch, err := restic.NewContentHandler(be, key)
ch, err := restic.NewContentHandler(s)
if err != nil {
return err
}
@ -166,7 +166,7 @@ func (c CmdFind) Execute(args []string) error {
}
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
@ -174,21 +174,21 @@ func (c CmdFind) Execute(args []string) error {
c.pattern = args[0]
if c.Snapshot != "" {
snapshotID, err := backend.FindSnapshot(be, c.Snapshot)
snapshotID, err := backend.FindSnapshot(s, c.Snapshot)
if err != nil {
return fmt.Errorf("invalid id %q: %v", args[1], err)
}
return c.findInSnapshot(be, key, snapshotID)
return c.findInSnapshot(s, snapshotID)
}
list, err := be.List(backend.Snapshot)
list, err := s.List(backend.Snapshot)
if err != nil {
return err
}
for _, snapshotID := range list {
err := c.findInSnapshot(be, key, snapshotID)
err := c.findInSnapshot(s, snapshotID)
if err != nil {
return err

View File

@ -75,10 +75,10 @@ func fsckTree(ch *restic.ContentHandler, id backend.ID) error {
return nil
}
func fsck_snapshot(be restic.Server, key *restic.Key, id backend.ID) error {
func fsck_snapshot(s restic.Server, id backend.ID) error {
debug("checking snapshot %v\n", id)
ch, err := restic.NewContentHandler(be, key)
ch, err := restic.NewContentHandler(s)
if err != nil {
return err
}
@ -108,27 +108,27 @@ func (cmd CmdFsck) Execute(args []string) error {
return fmt.Errorf("type or ID not specified, Usage: %s", cmd.Usage())
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
if len(args) == 1 && args[0] != "all" {
snapshotID, err := backend.FindSnapshot(be, args[0])
snapshotID, err := s.FindSnapshot(args[0])
if err != nil {
return fmt.Errorf("invalid id %q: %v", args[0], err)
}
return fsck_snapshot(be, key, snapshotID)
return fsck_snapshot(s, snapshotID)
}
list, err := be.List(backend.Snapshot)
list, err := s.List(backend.Snapshot)
if err != nil {
return err
}
for _, snapshotID := range list {
err := fsck_snapshot(be, key, snapshotID)
err := fsck_snapshot(s, snapshotID)
if err != nil {
return err

View File

@ -22,17 +22,17 @@ func init() {
}
}
func list_keys(be restic.Server, key *restic.Key) error {
func list_keys(s restic.Server) error {
tab := NewTable()
tab.Header = fmt.Sprintf(" %-10s %-10s %-10s %s", "ID", "User", "Host", "Created")
tab.RowFormat = "%s%-10s %-10s %-10s %s"
plen, err := backend.PrefixLength(be, backend.Key)
plen, err := s.PrefixLength(backend.Key)
if err != nil {
return err
}
backend.Each(be, backend.Key, func(id backend.ID, data []byte, err error) {
s.Each(backend.Key, func(id backend.ID, data []byte, err error) {
k := restic.Key{}
err = json.Unmarshal(data, &k)
if err != nil {
@ -40,7 +40,7 @@ func list_keys(be restic.Server, key *restic.Key) error {
}
var current string
if id.Equal(key.ID()) {
if id.Equal(s.Key().ID()) {
current = "*"
} else {
current = " "
@ -54,7 +54,7 @@ func list_keys(be restic.Server, key *restic.Key) error {
return nil
}
func add_key(be restic.Server, key *restic.Key) error {
func add_key(s restic.Server) error {
pw := readPassword("RESTIC_NEWPASSWORD", "enter password for new key: ")
pw2 := readPassword("RESTIC_NEWPASSWORD", "enter password again: ")
@ -62,7 +62,7 @@ func add_key(be restic.Server, key *restic.Key) error {
return errors.New("passwords do not match")
}
id, err := key.AddKey(be, pw)
id, err := s.Key().AddKey(s, pw)
if err != nil {
return fmt.Errorf("creating new key failed: %v\n", err)
}
@ -72,12 +72,12 @@ func add_key(be restic.Server, key *restic.Key) error {
return nil
}
func delete_key(be restic.Server, key *restic.Key, id backend.ID) error {
if id.Equal(key.ID()) {
func delete_key(s restic.Server, id backend.ID) error {
if id.Equal(s.Key().ID()) {
return errors.New("refusing to remove key currently used to access repository")
}
err := be.Remove(backend.Key, id)
err := s.Remove(backend.Key, id)
if err != nil {
return err
}
@ -86,7 +86,7 @@ func delete_key(be restic.Server, key *restic.Key, id backend.ID) error {
return nil
}
func change_password(be restic.Server, key *restic.Key) error {
func change_password(s restic.Server) error {
pw := readPassword("RESTIC_NEWPASSWORD", "enter password for new key: ")
pw2 := readPassword("RESTIC_NEWPASSWORD", "enter password again: ")
@ -95,13 +95,13 @@ func change_password(be restic.Server, key *restic.Key) error {
}
// add new key
id, err := key.AddKey(be, pw)
id, err := s.Key().AddKey(s, pw)
if err != nil {
return fmt.Errorf("creating new key failed: %v\n", err)
}
// remove old key
err = be.Remove(backend.Key, key.ID())
err = s.Remove(backend.Key, s.Key().ID())
if err != nil {
return err
}
@ -120,25 +120,25 @@ func (cmd CmdKey) Execute(args []string) error {
return fmt.Errorf("wrong number of arguments, Usage: %s", cmd.Usage())
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
switch args[0] {
case "list":
return list_keys(be, key)
return list_keys(s)
case "add":
return add_key(be, key)
return add_key(s)
case "rm":
id, err := backend.Find(be, backend.Key, args[1])
id, err := backend.Find(s, backend.Key, args[1])
if err != nil {
return err
}
return delete_key(be, key, id)
return delete_key(s, id)
case "change":
return change_password(be, key)
return change_password(s)
}
return nil

View File

@ -28,22 +28,22 @@ func (cmd CmdList) Execute(args []string) error {
return fmt.Errorf("type not specified, Usage: %s", cmd.Usage())
}
be, _, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
var (
t backend.Type
each func(backend.Type, func(backend.ID, []byte, error)) error = be.Each
each func(backend.Type, func(backend.ID, []byte, error)) error = s.Each
)
switch args[0] {
case "data":
t = backend.Data
each = be.EachDecrypted
each = s.EachDecrypted
case "trees":
t = backend.Tree
each = be.EachDecrypted
each = s.EachDecrypted
case "snapshots":
t = backend.Snapshot
case "maps":

View File

@ -63,22 +63,22 @@ func (cmd CmdLs) Usage() string {
return "ls snapshot-ID [DIR]"
}
func (cmd CmdLs) Execute(be restic.Server, key *restic.Key, args []string) error {
func (cmd CmdLs) Execute(s restic.Server, key *restic.Key, args []string) error {
if len(args) < 1 || len(args) > 2 {
return fmt.Errorf("wrong number of arguments, Usage: %s", cmd.Usage())
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
id, err := backend.FindSnapshot(be, args[0])
id, err := backend.FindSnapshot(s, args[0])
if err != nil {
return err
}
ch, err := restic.NewContentHandler(be, key)
ch, err := restic.NewContentHandler(s)
if err != nil {
return err
}

View File

@ -29,12 +29,12 @@ func (cmd CmdRestore) Execute(args []string) error {
return fmt.Errorf("wrong number of arguments, Usage: %s", cmd.Usage())
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
id, err := backend.FindSnapshot(be, args[0])
id, err := backend.FindSnapshot(s, args[0])
if err != nil {
errx(1, "invalid id %q: %v", args[0], err)
}
@ -42,7 +42,7 @@ func (cmd CmdRestore) Execute(args []string) error {
target := args[1]
// create restorer
res, err := restic.NewRestorer(be, key, id)
res, err := restic.NewRestorer(s, id)
if err != nil {
fmt.Fprintf(os.Stderr, "creating restorer failed: %v\n", err)
os.Exit(2)

View File

@ -92,12 +92,12 @@ func (cmd CmdSnapshots) Execute(args []string) error {
return fmt.Errorf("wrong number of arguments, usage: %s", cmd.Usage())
}
be, key, err := OpenRepo()
s, err := OpenRepo()
if err != nil {
return err
}
ch, err := restic.NewContentHandler(be, key)
ch, err := restic.NewContentHandler(s)
if err != nil {
return err
}
@ -107,7 +107,7 @@ func (cmd CmdSnapshots) Execute(args []string) error {
tab.RowFormat = "%-8s %-19s %-10s %s"
list := []*restic.Snapshot{}
backend.EachID(be, backend.Snapshot, func(id backend.ID) {
s.EachID(backend.Snapshot, func(id backend.ID) {
sn, err := restic.LoadSnapshot(ch, id)
if err != nil {
fmt.Fprintf(os.Stderr, "error loading snapshot %s: %v\n", id, err)
@ -127,7 +127,7 @@ func (cmd CmdSnapshots) Execute(args []string) error {
}
})
plen, err := backend.PrefixLength(be, backend.Snapshot)
plen, err := s.PrefixLength(backend.Snapshot)
if err != nil {
return err
}

View File

@ -129,20 +129,20 @@ func create(u string) (backend.Backend, error) {
return backend.CreateSFTP(url.Path[1:], "ssh", args...)
}
func OpenRepo() (restic.Server, *restic.Key, error) {
func OpenRepo() (restic.Server, error) {
be, err := open(opts.Repo)
if err != nil {
return restic.Server{}, nil, err
return restic.Server{}, err
}
s := restic.NewServer(be)
key, err := restic.SearchKey(s, readPassword("RESTIC_PASSWORD", "Enter Password for Repository: "))
err = s.SearchKey(readPassword("RESTIC_PASSWORD", "Enter Password for Repository: "))
if err != nil {
return restic.Server{}, nil, fmt.Errorf("unable to open repo: %v", err)
return restic.Server{}, fmt.Errorf("unable to open repo: %v", err)
}
return s, key, nil
return s, nil
}
func init() {
@ -171,59 +171,5 @@ func main() {
os.Exit(1)
}
// fmt.Printf("parser: %#v\n", parser)
// fmt.Printf("%#v\n", parser.Active.Name)
// if opts.Repo == "" {
// fmt.Fprintf(os.Stderr, "no repository specified, use -r or RESTIC_REPOSITORY variable\n")
// os.Exit(1)
// }
// if len(args) == 0 {
// cmds := []string{"init"}
// for k := range commands {
// cmds = append(cmds, k)
// }
// sort.Strings(cmds)
// fmt.Printf("nothing to do, available commands: [%v]\n", strings.Join(cmds, "|"))
// os.Exit(0)
// }
// cmd := args[0]
// switch cmd {
// case "init":
// err = commandInit(opts.Repo)
// if err != nil {
// errx(1, "error executing command %q: %v", cmd, err)
// }
// return
// case "version":
// fmt.Printf("%v\n", version)
// return
// }
// f, ok := commands[cmd]
// if !ok {
// errx(1, "unknown command: %q\n", cmd)
// }
// // read_password("enter password: ")
// repo, err := open(opts.Repo)
// if err != nil {
// errx(1, "unable to open repo: %v", err)
// }
// key, err := restic.SearchKey(repo, readPassword("RESTIC_PASSWORD", "Enter Password for Repository: "))
// if err != nil {
// errx(2, "unable to open repo: %v", err)
// }
// err = f(repo, key, args[1:])
// if err != nil {
// errx(1, "error executing command %q: %v", cmd, err)
// }
// restic.PoolAlloc()
}

View File

@ -11,18 +11,16 @@ import (
var ErrWrongData = errors.New("wrong data decrypt, checksum does not match")
type ContentHandler struct {
s Server
key *Key
s Server
bl *BlobList
}
// NewContentHandler creates a new content handler.
func NewContentHandler(s Server, key *Key) (*ContentHandler, error) {
func NewContentHandler(s Server) (*ContentHandler, error) {
ch := &ContentHandler{
s: s,
key: key,
bl: NewBlobList(),
s: s,
bl: NewBlobList(),
}
return ch, nil
@ -95,7 +93,7 @@ func (ch *ContentHandler) Save(t backend.Type, data []byte) (Blob, error) {
}
// encrypt blob
n, err := ch.key.Encrypt(ciphertext, data)
n, err := ch.s.Encrypt(ciphertext, data)
if err != nil {
return Blob{}, err
}
@ -139,7 +137,7 @@ func (ch *ContentHandler) Load(t backend.Type, id backend.ID) ([]byte, error) {
}
// decrypt
buf, err = ch.key.Decrypt(buf)
buf, err = ch.s.Decrypt(buf)
if err != nil {
return nil, err
}
@ -165,7 +163,7 @@ func (ch *ContentHandler) Load(t backend.Type, id backend.ID) ([]byte, error) {
}
// decrypt
buf, err = ch.key.Decrypt(buf)
buf, err = ch.s.Decrypt(buf)
if err != nil {
return nil, err
}
@ -207,7 +205,7 @@ func (ch *ContentHandler) LoadJSONRaw(t backend.Type, id backend.ID, item interf
}
// decrypt
buf, err = ch.key.Decrypt(buf)
buf, err = ch.s.Decrypt(buf)
if err != nil {
return err
}

View File

@ -11,24 +11,20 @@ import (
)
type Restorer struct {
s Server
key *Key
ch *ContentHandler
sn *Snapshot
s Server
ch *ContentHandler
sn *Snapshot
Error func(dir string, node *Node, err error) error
Filter func(item string, node *Node) bool
}
// NewRestorer creates a restorer preloaded with the content from the snapshot snid.
func NewRestorer(s Server, key *Key, snid backend.ID) (*Restorer, error) {
r := &Restorer{
s: s,
key: key,
}
func NewRestorer(s Server, snid backend.ID) (*Restorer, error) {
r := &Restorer{s: s}
var err error
r.ch, err = NewContentHandler(s, key)
r.ch, err = NewContentHandler(s)
if err != nil {
return nil, arrar.Annotate(err, "create contenthandler for restorer")
}

View File

@ -55,6 +55,37 @@ func (s Server) Backend() backend.Backend {
return s.be
}
func (s *Server) SearchKey(password string) error {
key, err := SearchKey(*s, password)
if err != nil {
return err
}
s.key = key
return nil
}
func (s Server) Decrypt(ciphertext []byte) ([]byte, error) {
if s.key == nil {
return nil, errors.New("key for server not set")
}
return s.key.Decrypt(ciphertext)
}
func (s Server) Encrypt(ciphertext, plaintext []byte) (int, error) {
if s.key == nil {
return 0, errors.New("key for server not set")
}
return s.key.Encrypt(ciphertext, plaintext)
}
func (s Server) Key() *Key {
return s.key
}
// Each calls Each() with the given parameters, Decrypt() on the ciphertext
// and, on successful decryption, f with the plaintext.
func (s Server) EachDecrypted(t backend.Type, f func(backend.ID, []byte, error)) error {