提交 91dd044d 作者: Jeromy

config: guard against privkey being overwritten in fsrepo setConfig

License: MIT
Signed-off-by: 's avatarJeromy <why@ipfs.io>
上级 671425ea
...@@ -163,36 +163,61 @@ included in the output of this command. ...@@ -163,36 +163,61 @@ included in the output of this command.
return return
} }
idmap, ok := cfg["Identity"].(map[string]interface{}) err = scrubValue(cfg, []string{config.IdentityTag, config.PrivKeyTag})
if !ok { if err != nil {
res.SetError(errors.New("config has no identity"), cmds.ErrNormal) res.SetError(err, cmds.ErrNormal)
return return
} }
privKeyKey := "" // make sure we both find the name of privkey and we delete it output, err := config.HumanOutput(cfg)
for key, _ := range idmap { if err != nil {
if strings.ToLower(key) == "privkey" { res.SetError(err, cmds.ErrNormal)
if privKeyKey != "" {
res.SetError(errors.New("found multiple PrivKey keys"), cmds.ErrNormal)
return return
} }
privKeyKey = key
res.SetOutput(bytes.NewReader(output))
},
}
func scrubValue(m map[string]interface{}, key []string) error {
find := func(m map[string]interface{}, k string) (string, interface{}, bool) {
lckey := strings.ToLower(k)
for mkey, val := range m {
lcmkey := strings.ToLower(mkey)
if lckey == lcmkey {
return mkey, val, true
} }
} }
if privKeyKey == "" { return "", nil, false
res.SetError(errors.New("haven't found PriveKey key"), cmds.ErrNormal)
} }
delete(idmap, privKeyKey) cur := m
for _, k := range key[:len(key)-1] {
foundk, val, ok := find(cur, k)
if !ok {
return fmt.Errorf("failed to find specified key")
}
output, err := config.HumanOutput(cfg) if foundk != k {
if err != nil { // case mismatch, calling this an error
res.SetError(err, cmds.ErrNormal) return fmt.Errorf("case mismatch in config, expected %q but got %q", k, foundk)
return
} }
res.SetOutput(bytes.NewReader(output)) mval, mok := val.(map[string]interface{})
}, if !mok {
return fmt.Errorf("%s was not a map", foundk)
}
cur = mval
}
todel, _, ok := find(cur, key[len(key)-1])
if !ok {
return fmt.Errorf("%s, not found", strings.Join(key, "."))
}
delete(cur, todel)
return nil
} }
var configEditCmd = &cmds.Command{ var configEditCmd = &cmds.Command{
...@@ -265,19 +290,10 @@ func getConfig(r repo.Repo, key string) (*ConfigField, error) { ...@@ -265,19 +290,10 @@ func getConfig(r repo.Repo, key string) (*ConfigField, error) {
} }
func setConfig(r repo.Repo, key string, value interface{}) (*ConfigField, error) { func setConfig(r repo.Repo, key string, value interface{}) (*ConfigField, error) {
keyF, err := getConfig(r, "Identity.PrivKey") err := r.SetConfigKey(key, value)
if err != nil {
return nil, errors.New("failed to get PrivKey")
}
privkey := keyF.Value
err = r.SetConfigKey(key, value)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to set config value: %s (maybe use --json?)", err) return nil, fmt.Errorf("failed to set config value: %s (maybe use --json?)", err)
} }
err = r.SetConfigKey("Identity.PrivKey", privkey)
if err != nil {
return nil, errors.New("failed to set PrivKey")
}
return getConfig(r, key) return getConfig(r, key)
} }
...@@ -301,7 +317,7 @@ func replaceConfig(r repo.Repo, file io.Reader) error { ...@@ -301,7 +317,7 @@ func replaceConfig(r repo.Repo, file io.Reader) error {
return errors.New("setting private key with API is not supported") return errors.New("setting private key with API is not supported")
} }
keyF, err := getConfig(r, "Identity.PrivKey") keyF, err := getConfig(r, config.PrivKeySelector)
if err != nil { if err != nil {
return fmt.Errorf("Failed to get PrivKey") return fmt.Errorf("Failed to get PrivKey")
} }
......
...@@ -5,6 +5,10 @@ import ( ...@@ -5,6 +5,10 @@ import (
ic "gx/ipfs/QmUWER4r4qMvaCnX5zREcfyiWN7cXN9g3a7fkRqNz8qWPP/go-libp2p-crypto" ic "gx/ipfs/QmUWER4r4qMvaCnX5zREcfyiWN7cXN9g3a7fkRqNz8qWPP/go-libp2p-crypto"
) )
const IdentityTag = "Identity"
const PrivKeyTag = "PrivKey"
const PrivKeySelector = IdentityTag + "." + PrivKeyTag
// Identity tracks the configuration of the local node's identity. // Identity tracks the configuration of the local node's identity.
type Identity struct { type Identity struct {
PeerID string PeerID string
......
...@@ -482,6 +482,14 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error { ...@@ -482,6 +482,14 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
return err return err
} }
// Load private key to guard against it being overwritten.
// NOTE: this is a temporary measure to secure this field until we move
// keys out of the config file.
pkval, err := common.MapGetKV(mapconf, config.PrivKeySelector)
if err != nil {
return err
}
// Get the type of the value associated with the key // Get the type of the value associated with the key
oldValue, err := common.MapGetKV(mapconf, key) oldValue, err := common.MapGetKV(mapconf, key)
ok := true ok := true
...@@ -523,6 +531,11 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error { ...@@ -523,6 +531,11 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
return err return err
} }
// replace private key, in case it was overwritten.
if err := common.MapSetKV(mapconf, "Identity.PrivKey", pkval); err != nil {
return err
}
// This step doubles as to validate the map against the struct // This step doubles as to validate the map against the struct
// before serialization // before serialization
conf, err := config.FromMap(mapconf) conf, err := config.FromMap(mapconf)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论