daemon: forbid "setconfig" command to change rpcserver settings in-flight
It is much easier to reason about the rpcserver if we don't allow changing its basic settings while it is already running. What does it mean to change the TCP port it is listening on ("rpcport") if it's already running? It is even problematic to change the rpcpassword: care needs to be taken to already update it for the current server.
(ref https://github.com/spesmilo/electrum/issues/6762)
This commit disallows changing all of the "rpc*" config variables if the daemon is already running.
---
Simultaneously, it also ensures rpc_password is always set and auth cannot be disabled.
Previously if there was a daemon running, and the user ran
`$ electrum setconfig rpcpassword ""` that would leave the RPC unauthenticated
for the current session. However next time the daemon restarted, get_rpc_credentials would see
the unset password and generate one.
I think this was the worst of both worlds:
- we did not really allow removing the rpc password, except for the current session, and
- perhaps unexpectedly, we would generate a new password on daemon restart
Instead now we explicitly make sure the RPC server can never get into a state where it does not have a password set.
Based on a report by `Zuzana Kotásková <36777@mail.vsfs.cz>`
This commit is contained in:
+3
-3
@@ -180,6 +180,7 @@ def wait_until_daemon_becomes_ready(*, config: SimpleConfig, timeout=5) -> bool:
|
||||
def get_rpc_credentials(config: SimpleConfig) -> Tuple[str, str]:
|
||||
rpc_user = config.RPC_USERNAME or None
|
||||
rpc_password = config.RPC_PASSWORD or None
|
||||
# note: we explicitly forbid empty/unset password, and will generate one now instead
|
||||
if rpc_user is None or rpc_password is None:
|
||||
rpc_user = 'user'
|
||||
bits = 128
|
||||
@@ -219,9 +220,8 @@ class AuthenticatedServer(Logger):
|
||||
self._methods[name] = f
|
||||
|
||||
async def authenticate(self, headers):
|
||||
if self.rpc_password == '':
|
||||
# RPC authentication is disabled
|
||||
return
|
||||
if not self.rpc_password:
|
||||
raise Exception('Server RPC password is unset. This should not happen.')
|
||||
auth_string = headers.get('Authorization', None)
|
||||
if auth_string is None:
|
||||
raise AuthenticationInvalidOrMissing('CredentialsMissing')
|
||||
|
||||
Reference in New Issue
Block a user