From d4bf5bb279371df953927e3ea16e837cd679c204 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sun, 3 May 2015 17:37:12 +0200 Subject: [PATCH] server: Add config --- archiver.go | 2 +- cache.go | 2 +- cmd/restic/main.go | 5 ++-- server/key.go | 4 +-- server/server.go | 66 ++++++++++++++++++++++++++++++++++------------ 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/archiver.go b/archiver.go index ca8542b65..f77efb4ad 100644 --- a/archiver.go +++ b/archiver.go @@ -184,7 +184,7 @@ func (arch *Archiver) SaveFile(p *Progress, node *Node) error { } chnker := GetChunker("archiver.SaveFile") - chnker.Reset(file, arch.s.ChunkerPolynomial()) + chnker.Reset(file, arch.s.Config.ChunkerPolynomial) resultChannels := [](<-chan saveResult){} defer FreeChunker("archiver.SaveFile", chnker) diff --git a/cache.go b/cache.go index 56fe3e321..a3c7b8953 100644 --- a/cache.go +++ b/cache.go @@ -24,7 +24,7 @@ func NewCache(s *server.Server) (*Cache, error) { return nil, err } - basedir := filepath.Join(cacheDir, s.ID()) + basedir := filepath.Join(cacheDir, s.Config.ID) debug.Log("Cache.New", "opened cache at %v", basedir) return &Cache{base: basedir}, nil diff --git a/cmd/restic/main.go b/cmd/restic/main.go index 5bbb8b586..a6de28edf 100644 --- a/cmd/restic/main.go +++ b/cmd/restic/main.go @@ -74,14 +74,13 @@ func (cmd CmdInit) Execute(args []string) error { } s := server.NewServer(be) - - _, err = server.CreateMasterKey(s, pw) + err = s.CreateMasterKey(pw) if err != nil { fmt.Fprintf(os.Stderr, "creating key in backend at %s failed: %v\n", opts.Repo, err) os.Exit(1) } - fmt.Printf("created restic backend %v at %s\n", s.ID()[:10], opts.Repo) + fmt.Printf("created restic backend %v at %s\n", s.Config.ID[:10], opts.Repo) fmt.Println("Please note that knowledge of your password is required to access the repository.") fmt.Println("Losing your password means that your data is irrecoverably lost.") diff --git a/server/key.go b/server/key.go index 677870c87..1e4294984 100644 --- a/server/key.go +++ b/server/key.go @@ -50,9 +50,9 @@ type Key struct { name string } -// CreateMasterKey creates a new master key in the given backend and encrypts +// createMasterKey creates a new master key in the given backend and encrypts // it with the password. -func CreateMasterKey(s *Server, password string) (*Key, error) { +func createMasterKey(s *Server, password string) (*Key, error) { return AddKey(s, password, nil) } diff --git a/server/server.go b/server/server.go index 198792adf..be79727c4 100644 --- a/server/server.go +++ b/server/server.go @@ -2,7 +2,9 @@ package server import ( "bytes" + "crypto/rand" "crypto/sha256" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -16,10 +18,19 @@ import ( "github.com/restic/restic/pack" ) +// Config contains the configuration for a repository. +type Config struct { + Version uint `json:"version"` + ID string `json:"id"` + ChunkerPolynomial chunker.Pol `json:"chunker_polynomial"` +} + +// Server is used to access a repository in a backend. type Server struct { - be backend.Backend - key *Key - idx *Index + be backend.Backend + Config Config + key *Key + idx *Index pm sync.Mutex packs []*pack.Packer @@ -32,11 +43,6 @@ func NewServer(be backend.Backend) *Server { } } -// ChunkerPolynomial returns the secret polynomial used for content defined chunking. -func (s *Server) ChunkerPolynomial() chunker.Pol { - return chunker.Pol(s.key.Master().ChunkerPolynomial) -} - // Find loads the list of all blobs of type t and searches for names which start // with prefix. If none is found, nil and ErrNoIDPrefixFound is returned. If // more than one is found, nil and ErrMultipleIDMatches is returned. @@ -365,12 +371,12 @@ func (s *Server) SaveJSON(t pack.BlobType, item interface{}) (backend.ID, error) // SaveJSONUnpacked serialises item as JSON and encrypts and saves it in the // backend as type t, without a pack. It returns the storage hash. func (s *Server) SaveJSONUnpacked(t backend.Type, item interface{}) (backend.ID, error) { - // create blob + // create file blob, err := s.be.Create() if err != nil { return nil, err } - debug.Log("Server.SaveJSONUnpacked", "create new pack %p", blob) + debug.Log("Server.SaveJSONUnpacked", "create new file %p", blob) // hash hw := backend.NewHashingWriter(blob, sha256.New()) @@ -521,6 +527,36 @@ func (s *Server) loadIndex(id string) error { return nil } +const repositoryIDSize = sha256.Size +const RepositoryVersion = 1 + +func (s *Server) createConfig() (err error) { + s.Config.ChunkerPolynomial, err = chunker.RandomPolynomial() + if err != nil { + return err + } + + newID := make([]byte, repositoryIDSize) + _, err = io.ReadFull(rand.Reader, newID) + if err != nil { + return err + } + + s.Config.ID = hex.EncodeToString(newID) + s.Config.Version = RepositoryVersion + + debug.Log("Server.createConfig", "New config: %#v", s.Config) + + _, err = s.SaveJSONUnpacked(backend.Config, s.Config) + return err +} + +func (s *Server) loadConfig(cfg *Config) error { + return s.LoadJSONUnpacked(backend.Config, nil, cfg) +} + +// SearchKey tries to find a key for which the supplied password works, +// afterwards the repository config is read and parsed. func (s *Server) SearchKey(password string) error { key, err := SearchKey(s, password) if err != nil { @@ -528,19 +564,19 @@ func (s *Server) SearchKey(password string) error { } s.key = key - return nil + return s.loadConfig(&s.Config) } // CreateMasterKey creates a new key with the supplied password, afterwards the // repository config is created. func (s *Server) CreateMasterKey(password string) error { - key, err := CreateMasterKey(s, password) + key, err := createMasterKey(s, password) if err != nil { return err } s.key = key - return nil + return s.createConfig() } func (s *Server) Decrypt(ciphertext []byte) ([]byte, error) { @@ -602,10 +638,6 @@ func (s *Server) Delete() error { return errors.New("Delete() called for backend that does not implement this method") } -func (s *Server) ID() string { - return "empty" -} - func (s *Server) Location() string { return s.be.Location() }