lib: Handle adding enc folders on an existing conn (fixes #7509) (#7510)

This commit is contained in:
Simon Frei
2021-03-22 21:50:19 +01:00
committed by GitHub
parent f7929229c8
commit 924b96856f
11 changed files with 160 additions and 87 deletions
+42 -13
View File
@@ -14,6 +14,7 @@ import (
"fmt"
"io"
"strings"
"sync"
"time"
"github.com/gogo/protobuf/proto"
@@ -41,11 +42,11 @@ const (
// must decrypt those and answer requests by encrypting the data.
type encryptedModel struct {
model Model
folderKeys map[string]*[keySize]byte // folder ID -> key
folderKeys *folderKeyRegistry
}
func (e encryptedModel) Index(deviceID DeviceID, folder string, files []FileInfo) error {
if folderKey, ok := e.folderKeys[folder]; ok {
if folderKey, ok := e.folderKeys.get(folder); ok {
// incoming index data to be decrypted
if err := decryptFileInfos(files, folderKey); err != nil {
return err
@@ -55,7 +56,7 @@ func (e encryptedModel) Index(deviceID DeviceID, folder string, files []FileInfo
}
func (e encryptedModel) IndexUpdate(deviceID DeviceID, folder string, files []FileInfo) error {
if folderKey, ok := e.folderKeys[folder]; ok {
if folderKey, ok := e.folderKeys.get(folder); ok {
// incoming index data to be decrypted
if err := decryptFileInfos(files, folderKey); err != nil {
return err
@@ -65,7 +66,7 @@ func (e encryptedModel) IndexUpdate(deviceID DeviceID, folder string, files []Fi
}
func (e encryptedModel) Request(deviceID DeviceID, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
folderKey, ok := e.folderKeys[folder]
folderKey, ok := e.folderKeys.get(folder)
if !ok {
return e.model.Request(deviceID, folder, name, blockNo, size, offset, hash, weakHash, fromTemporary)
}
@@ -123,7 +124,7 @@ func (e encryptedModel) Request(deviceID DeviceID, folder, name string, blockNo,
}
func (e encryptedModel) DownloadProgress(deviceID DeviceID, folder string, updates []FileDownloadProgressUpdate) error {
if _, ok := e.folderKeys[folder]; !ok {
if _, ok := e.folderKeys.get(folder); !ok {
return e.model.DownloadProgress(deviceID, folder, updates)
}
@@ -135,42 +136,46 @@ func (e encryptedModel) ClusterConfig(deviceID DeviceID, config ClusterConfig) e
return e.model.ClusterConfig(deviceID, config)
}
func (e encryptedModel) Closed(conn Connection, err error) {
e.model.Closed(conn, err)
func (e encryptedModel) Closed(device DeviceID, err error) {
e.model.Closed(device, err)
}
// The encryptedConnection sits between the model and the encrypted device. It
// encrypts outgoing metadata and decrypts incoming responses.
type encryptedConnection struct {
ConnectionInfo
conn Connection
folderKeys map[string]*[keySize]byte // folder ID -> key
conn *rawConnection
folderKeys *folderKeyRegistry
}
func (e encryptedConnection) Start() {
e.conn.Start()
}
func (e encryptedConnection) SetFolderPasswords(passwords map[string]string) {
e.folderKeys.setPasswords(passwords)
}
func (e encryptedConnection) ID() DeviceID {
return e.conn.ID()
}
func (e encryptedConnection) Index(ctx context.Context, folder string, files []FileInfo) error {
if folderKey, ok := e.folderKeys[folder]; ok {
if folderKey, ok := e.folderKeys.get(folder); ok {
encryptFileInfos(files, folderKey)
}
return e.conn.Index(ctx, folder, files)
}
func (e encryptedConnection) IndexUpdate(ctx context.Context, folder string, files []FileInfo) error {
if folderKey, ok := e.folderKeys[folder]; ok {
if folderKey, ok := e.folderKeys.get(folder); ok {
encryptFileInfos(files, folderKey)
}
return e.conn.IndexUpdate(ctx, folder, files)
}
func (e encryptedConnection) Request(ctx context.Context, folder string, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
folderKey, ok := e.folderKeys[folder]
folderKey, ok := e.folderKeys.get(folder)
if !ok {
return e.conn.Request(ctx, folder, name, blockNo, offset, size, hash, weakHash, fromTemporary)
}
@@ -205,7 +210,7 @@ func (e encryptedConnection) Request(ctx context.Context, folder string, name st
}
func (e encryptedConnection) DownloadProgress(ctx context.Context, folder string, updates []FileDownloadProgressUpdate) {
if _, ok := e.folderKeys[folder]; !ok {
if _, ok := e.folderKeys.get(folder); !ok {
e.conn.DownloadProgress(ctx, folder, updates)
}
@@ -590,3 +595,27 @@ func isEncryptedParentFromComponents(pathComponents []string) bool {
}
return true
}
type folderKeyRegistry struct {
keys map[string]*[keySize]byte // folder ID -> key
mut sync.RWMutex
}
func newFolderKeyRegistry(passwords map[string]string) *folderKeyRegistry {
return &folderKeyRegistry{
keys: keysFromPasswords(passwords),
}
}
func (r *folderKeyRegistry) get(folder string) (*[keySize]byte, bool) {
r.mut.RLock()
key, ok := r.keys[folder]
r.mut.RUnlock()
return key, ok
}
func (r *folderKeyRegistry) setPasswords(passwords map[string]string) {
r.mut.Lock()
r.keys = keysFromPasswords(passwords)
r.mut.Unlock()
}