Use secure temporary config files
This commit is contained in:
committed by
Brandon McGinty
parent
3ba5e03208
commit
dcffa1efa1
+15
-5
@@ -8,6 +8,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -61,15 +62,24 @@ func (c *Config) saveConfigLocked() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tmp := c.fn + ".tmp"
|
file, err := os.CreateTemp(filepath.Dir(c.fn), filepath.Base(c.fn)+".tmp-")
|
||||||
if err := ioutil.WriteFile(tmp, data, 0600); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.Rename(tmp, c.fn); err != nil {
|
tmp := file.Name()
|
||||||
_ = os.Remove(tmp)
|
defer os.Remove(tmp)
|
||||||
|
if err := file.Chmod(0600); err != nil {
|
||||||
|
file.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
if _, err := file.Write(data); err != nil {
|
||||||
|
file.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := file.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Rename(tmp, c.fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func key(k uiterm.Key) *uiterm.Key {
|
func key(k uiterm.Key) *uiterm.Key {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -16,6 +17,25 @@ func TestSaveConfigReturnsWriteError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSaveConfigDoesNotUsePredictableTemporaryPath(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), "barnard.toml")
|
||||||
|
legacyTemp := path + ".tmp"
|
||||||
|
if err := os.WriteFile(legacyTemp, []byte("sentinel"), 0600); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cfg := NewConfig(&path)
|
||||||
|
if err := cfg.SaveConfig(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
contents, err := os.ReadFile(legacyTemp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(contents) != "sentinel" {
|
||||||
|
t.Fatalf("predictable temporary file was modified: %q", contents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestConcurrentConfigurationUpdatesAndWrites(t *testing.T) {
|
func TestConcurrentConfigurationUpdatesAndWrites(t *testing.T) {
|
||||||
path := filepath.Join(t.TempDir(), "barnard.toml")
|
path := filepath.Join(t.TempDir(), "barnard.toml")
|
||||||
cfg := NewConfig(&path)
|
cfg := NewConfig(&path)
|
||||||
|
|||||||
Reference in New Issue
Block a user