config: add stricter config parsing to avoid dangerous RPC auth combos

In this commit, we add an additional constraint to the RPC
configuration parsing. Before this commit, it was possible to start lnd
with either RPC server listening on an external interface *without*
authentication disabled. After this commit, if a user tries to start
the RPC server listening on an external interface without any sort of
RPC authentication, then the daemon will fail to start up.
This commit is contained in:
Olaoluwa Osuntokun 2018-01-28 15:03:12 -08:00
parent 0a4de859a2
commit e953c6abcf
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

View File

@ -464,7 +464,8 @@ func loadConfig() (*config, error) {
cfg.RPCListeners = append(cfg.RPCListeners, addr)
}
// Listen on the default interface/port if no REST listeners were specified.
// Listen on the default interface/port if no REST listeners were
// specified.
if len(cfg.RESTListeners) == 0 {
addr := fmt.Sprintf("localhost:%d", defaultRESTPort)
cfg.RESTListeners = append(cfg.RESTListeners, addr)
@ -476,6 +477,18 @@ func loadConfig() (*config, error) {
cfg.Listeners = append(cfg.Listeners, addr)
}
// For each of the RPC listeners (REST+gRPC), we'll ensure that users
// have specified a safe combo for authentication. If not, we'll bail
// out with an error.
err := enforceSafeAuthentication(cfg.RPCListeners, !cfg.NoMacaroons)
if err != nil {
return nil, err
}
err = enforceSafeAuthentication(cfg.RESTListeners, !cfg.NoMacaroons)
if err != nil {
return nil, err
}
// Remove all Listeners if listening is disabled.
if cfg.DisableListen {
cfg.Listeners = nil
@ -867,3 +880,39 @@ func normalizeAddresses(addrs []string, defaultPort string) []string {
}
return result
}
// enforceSafeAuthentication enforces "safe" authentication taking into account
// the interfaces that the RPC servers are listening on, and if macaroons are
// activated or not. To project users from using dangerous config combinations,
// we'll prevent disabling authentication if the sever is listening on a public
// interface.
func enforceSafeAuthentication(addrs []string, macaroonsActive bool) error {
isLoopback := func(addr string) bool {
loopBackAddrs := []string{"localhost", "127.0.0.1"}
for _, loopback := range loopBackAddrs {
if strings.Contains(addr, loopback) {
return true
}
}
return false
}
// We'll now examine all addresses that this RPC server is listening
// on. If it's a localhost address, we'll skip it, otherwise, we'll
// return an error if macaroons are inactive.
for _, addr := range addrs {
if isLoopback(addr) {
continue
}
if !macaroonsActive {
return fmt.Errorf("Detected RPC server listening on "+
"publicly reachable interface %v with "+
"authentication disabled! Refusing to start with "+
"--no-macaroons specified.", addr)
}
}
return nil
}