Allow disabling RPC client TLS for localhost only.

This commit introduces a new flag, --noclienttls, which can be used to disable
TLS for the RPC client.  However, the flag can only be used when the RPC
client is connecting to localhost interfaces.  This is intended to prevent
accidentally leaking sensitive data when switching between local and
remote servers.
This commit is contained in:
Javed Khan 2015-01-09 14:50:59 +05:30
parent 469a6f86eb
commit edaddb0d95
3 changed files with 38 additions and 28 deletions

View file

@ -90,15 +90,18 @@ func walletMain() error {
go func() {
// Read CA certs and create the RPC client.
certs, err := ioutil.ReadFile(cfg.CAFile)
if err != nil {
log.Warnf("Cannot open CA file: %v", err)
// If there's an error reading the CA file, continue
// with nil certs and without the client connection
certs = nil
var certs []byte
if !cfg.DisableClientTLS {
certs, err = ioutil.ReadFile(cfg.CAFile)
if err != nil {
log.Warnf("Cannot open CA file: %v", err)
// If there's an error reading the CA file, continue
// with nil certs and without the client connection
certs = nil
}
}
rpcc, err := chain.NewClient(activeNet.Params, cfg.RPCConnect,
cfg.BtcdUsername, cfg.BtcdPassword, certs)
cfg.BtcdUsername, cfg.BtcdPassword, certs, cfg.DisableClientTLS)
if err != nil {
log.Errorf("Cannot create chain server RPC client: %v", err)
return

View file

@ -51,7 +51,7 @@ type Client struct {
quitMtx sync.Mutex
}
func NewClient(net *btcnet.Params, connect, user, pass string, certs []byte) (*Client, error) {
func NewClient(net *btcnet.Params, connect, user, pass string, certs []byte, disableTLS bool) (*Client, error) {
client := Client{
netParams: net,
enqueueNotification: make(chan interface{}),
@ -76,6 +76,7 @@ func NewClient(net *btcnet.Params, connect, user, pass string, certs []byte) (*C
Pass: pass,
Certificates: certs,
DisableConnectOnNew: true,
DisableTLS: disableTLS,
}
c, err := btcrpcclient.New(&conf, &ntfnCallbacks)
if err != nil {

View file

@ -70,6 +70,7 @@ type config struct {
RPCMaxClients int64 `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"`
RPCMaxWebsockets int64 `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"`
DisableServerTLS bool `long:"noservertls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"`
DisableClientTLS bool `long:"noclienttls" description:"Disable TLS for the RPC client -- NOTE: This is only allowed if the RPC client is connecting to localhost"`
MainNet bool `long:"mainnet" description:"Use the main Bitcoin network (default testnet3)"`
SimNet bool `long:"simnet" description:"Use the simulation test network (default testnet3)"`
KeypoolSize uint `short:"k" long:"keypoolsize" description:"DEPRECATED -- Maximum number of addresses in keypool"`
@ -371,27 +372,32 @@ func loadConfig() (*config, []string, error) {
"127.0.0.1": struct{}{},
"::1": struct{}{},
}
// If CAFile is unset, choose either the copy or local btcd cert.
if cfg.CAFile == "" {
cfg.CAFile = filepath.Join(cfg.DataDir, defaultCAFilename)
RPCHost, _, err := net.SplitHostPort(cfg.RPCConnect)
if err != nil {
return nil, nil, err
}
if cfg.DisableClientTLS {
if _, ok := localhostListeners[RPCHost]; !ok {
str := "%s: the --noclienttls option may not be used " +
"when connecting RPC to non localhost " +
"addresses: %s"
err := fmt.Errorf(str, funcName, cfg.RPCConnect)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
} else {
// If CAFile is unset, choose either the copy or local btcd cert.
if cfg.CAFile == "" {
cfg.CAFile = filepath.Join(cfg.DataDir, defaultCAFilename)
// If the CA copy does not exist, check if we're connecting to
// a local btcd and switch to its RPC cert if it exists.
if !fileExists(cfg.CAFile) {
host, _, err := net.SplitHostPort(cfg.RPCConnect)
if err != nil {
return nil, nil, err
}
switch host {
case "localhost":
fallthrough
case "127.0.0.1":
fallthrough
case "::1":
if fileExists(btcdHomedirCAFile) {
cfg.CAFile = btcdHomedirCAFile
// If the CA copy does not exist, check if we're connecting to
// a local btcd and switch to its RPC cert if it exists.
if !fileExists(cfg.CAFile) {
if _, ok := localhostListeners[RPCHost]; ok {
if fileExists(btcdHomedirCAFile) {
cfg.CAFile = btcdHomedirCAFile
}
}
}
}