2019-07-23 23:39:20 +02:00
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package syncthing
import (
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"os"
"github.com/pkg/errors"
"github.com/syncthing/syncthing/lib/config"
2019-11-29 09:11:52 +01:00
"github.com/syncthing/syncthing/lib/db/backend"
2019-08-15 16:29:37 +02:00
"github.com/syncthing/syncthing/lib/events"
2019-07-23 23:39:20 +02:00
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/tlsutil"
)
func LoadOrGenerateCertificate ( certFile , keyFile string ) ( tls . Certificate , error ) {
cert , err := tls . LoadX509KeyPair (
locations . Get ( locations . CertFile ) ,
locations . Get ( locations . KeyFile ) ,
)
if err != nil {
l . Infof ( "Generating ECDSA key and certificate for %s..." , tlsDefaultCommonName )
return tlsutil . NewCertificate (
locations . Get ( locations . CertFile ) ,
locations . Get ( locations . KeyFile ) ,
tlsDefaultCommonName ,
2019-10-16 20:31:46 +02:00
deviceCertLifetimeDays ,
2019-07-23 23:39:20 +02:00
)
}
return cert , nil
}
2019-08-15 16:29:37 +02:00
func DefaultConfig ( path string , myID protocol . DeviceID , evLogger events . Logger , noDefaultFolder bool ) ( config . Wrapper , error ) {
2019-07-23 23:39:20 +02:00
newCfg , err := config . NewWithFreePorts ( myID )
if err != nil {
return nil , err
}
if noDefaultFolder {
l . Infoln ( "We will skip creation of a default folder on first start" )
2020-11-20 14:21:54 +01:00
return config . Wrap ( path , newCfg , myID , evLogger ) , nil
2019-07-23 23:39:20 +02:00
}
2021-02-04 21:10:41 +01:00
fcfg := newCfg . Defaults . Folder . Copy ( )
fcfg . ID = "default"
fcfg . Label = "Default Folder"
fcfg . FilesystemType = fs . FilesystemTypeBasic
fcfg . Path = locations . Get ( locations . DefFolder )
newCfg . Folders = append ( newCfg . Folders , fcfg )
2019-07-23 23:39:20 +02:00
l . Infoln ( "Default folder created and/or linked to new config" )
2020-11-20 14:21:54 +01:00
return config . Wrap ( path , newCfg , myID , evLogger ) , nil
2019-07-23 23:39:20 +02:00
}
// LoadConfigAtStartup loads an existing config. If it doesn't yet exist, it
// creates a default one, without the default folder if noDefaultFolder is ture.
// Otherwise it checks the version, and archives and upgrades the config if
// necessary or returns an error, if the version isn't compatible.
2019-08-15 16:29:37 +02:00
func LoadConfigAtStartup ( path string , cert tls . Certificate , evLogger events . Logger , allowNewerConfig , noDefaultFolder bool ) ( config . Wrapper , error ) {
2019-07-23 23:39:20 +02:00
myID := protocol . NewDeviceID ( cert . Certificate [ 0 ] )
2020-08-25 08:11:14 +02:00
cfg , originalVersion , err := config . Load ( path , myID , evLogger )
2019-07-23 23:39:20 +02:00
if fs . IsNotExist ( err ) {
2019-08-15 16:29:37 +02:00
cfg , err = DefaultConfig ( path , myID , evLogger , noDefaultFolder )
2019-07-23 23:39:20 +02:00
if err != nil {
return nil , errors . Wrap ( err , "failed to generate default config" )
}
err = cfg . Save ( )
if err != nil {
return nil , errors . Wrap ( err , "failed to save default config" )
}
l . Infof ( "Default config saved. Edit %s to taste (with Syncthing stopped) or use the GUI" , cfg . ConfigPath ( ) )
} else if err == io . EOF {
return nil , errors . New ( "failed to load config: unexpected end of file. Truncated or empty configuration?" )
} else if err != nil {
return nil , errors . Wrap ( err , "failed to load config" )
}
2020-08-25 08:11:14 +02:00
if originalVersion != config . CurrentVersion {
if originalVersion == config . CurrentVersion + 1101 {
2019-07-23 23:39:20 +02:00
l . Infof ( "Now, THAT's what we call a config from the future! Don't worry. As long as you hit that wire with the connecting hook at precisely eighty-eight miles per hour the instant the lightning strikes the tower... everything will be fine." )
}
2020-08-25 08:11:14 +02:00
if originalVersion > config . CurrentVersion && ! allowNewerConfig {
return nil , fmt . Errorf ( "config file version (%d) is newer than supported version (%d). If this is expected, use -allow-newer-config to override." , originalVersion , config . CurrentVersion )
2019-07-23 23:39:20 +02:00
}
2020-08-25 08:11:14 +02:00
err = archiveAndSaveConfig ( cfg , originalVersion )
2019-07-23 23:39:20 +02:00
if err != nil {
return nil , errors . Wrap ( err , "config archive" )
}
}
return cfg , nil
}
2020-08-25 08:11:14 +02:00
func archiveAndSaveConfig ( cfg config . Wrapper , originalVersion int ) error {
2019-07-23 23:39:20 +02:00
// Copy the existing config to an archive copy
2020-08-25 08:11:14 +02:00
archivePath := cfg . ConfigPath ( ) + fmt . Sprintf ( ".v%d" , originalVersion )
2019-07-23 23:39:20 +02:00
l . Infoln ( "Archiving a copy of old config file format at:" , archivePath )
if err := copyFile ( cfg . ConfigPath ( ) , archivePath ) ; err != nil {
return err
}
// Do a regular atomic config sve
return cfg . Save ( )
}
func copyFile ( src , dst string ) error {
bs , err := ioutil . ReadFile ( src )
if err != nil {
return err
}
if err := ioutil . WriteFile ( dst , bs , 0600 ) ; err != nil {
// Attempt to clean up
os . Remove ( dst )
return err
}
return nil
}
2019-12-12 16:50:09 +01:00
func OpenDBBackend ( path string , tuning config . Tuning ) ( backend . Backend , error ) {
return backend . Open ( path , backend . Tuning ( tuning ) )
2019-07-23 23:39:20 +02:00
}