config: guard against privkey being overwritten in fsrepo setConfig

License: MIT
Signed-off-by: Jeromy <why@ipfs.io>
This commit is contained in:
Jeromy 2016-08-29 14:56:55 -07:00
parent 671425ea33
commit 91dd044d55
3 changed files with 63 additions and 30 deletions

View File

@ -163,28 +163,12 @@ included in the output of this command.
return
}
idmap, ok := cfg["Identity"].(map[string]interface{})
if !ok {
res.SetError(errors.New("config has no identity"), cmds.ErrNormal)
err = scrubValue(cfg, []string{config.IdentityTag, config.PrivKeyTag})
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
privKeyKey := "" // make sure we both find the name of privkey and we delete it
for key, _ := range idmap {
if strings.ToLower(key) == "privkey" {
if privKeyKey != "" {
res.SetError(errors.New("found multiple PrivKey keys"), cmds.ErrNormal)
return
}
privKeyKey = key
}
}
if privKeyKey == "" {
res.SetError(errors.New("haven't found PriveKey key"), cmds.ErrNormal)
}
delete(idmap, privKeyKey)
output, err := config.HumanOutput(cfg)
if err != nil {
res.SetError(err, cmds.ErrNormal)
@ -195,6 +179,47 @@ included in the output of this command.
},
}
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
}
}
return "", nil, false
}
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")
}
if foundk != k {
// case mismatch, calling this an error
return fmt.Errorf("case mismatch in config, expected %q but got %q", k, foundk)
}
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{
Helptext: cmds.HelpText{
Tagline: "Opens the config file for editing in $EDITOR.",
@ -265,19 +290,10 @@ func getConfig(r repo.Repo, key string) (*ConfigField, error) {
}
func setConfig(r repo.Repo, key string, value interface{}) (*ConfigField, error) {
keyF, err := getConfig(r, "Identity.PrivKey")
if err != nil {
return nil, errors.New("failed to get PrivKey")
}
privkey := keyF.Value
err = r.SetConfigKey(key, value)
err := r.SetConfigKey(key, value)
if err != nil {
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)
}
@ -301,7 +317,7 @@ func replaceConfig(r repo.Repo, file io.Reader) error {
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 {
return fmt.Errorf("Failed to get PrivKey")
}

View File

@ -5,6 +5,10 @@ import (
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.
type Identity struct {
PeerID string

View File

@ -482,6 +482,14 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
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
oldValue, err := common.MapGetKV(mapconf, key)
ok := true
@ -523,6 +531,11 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
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
// before serialization
conf, err := config.FromMap(mapconf)