mirror of
https://github.com/markqvist/rnsh.git
synced 2024-10-01 01:15:37 -04:00
Merge pull request #25 from markqvist/identities_file
Allowed Identities File
This commit is contained in:
commit
13352ee4e2
@ -20,7 +20,7 @@ usage = \
|
||||
Usage:
|
||||
rnsh -l [-c <configdir>] [-i <identityfile> | -s <service_name>] [-v... | -q...] -p
|
||||
rnsh -l [-c <configdir>] [-i <identityfile> | -s <service_name>] [-v... | -q...]
|
||||
[-b <period>] (-n | -a <identity_hash> [-a <identity_hash>] ...) [-A | -C]
|
||||
[-b <period>] [-n] [-a <identity_hash>] ([-a <identity_hash>] ...) [-A | -C]
|
||||
[[--] <program> [<arg> ...]]
|
||||
rnsh [-c <configdir>] [-i <identityfile>] [-v... | -q...] -p
|
||||
rnsh [-c <configdir>] [-i <identityfile>] [-v... | -q...] [-N] [-m] [-w <timeout>]
|
||||
@ -40,7 +40,9 @@ Options:
|
||||
user rnsh is running under will be used.
|
||||
-b --announce PERIOD Announce on startup and every PERIOD seconds
|
||||
Specify 0 for PERIOD to announce on startup only.
|
||||
-a HASH --allowed HASH Specify identities allowed to connect
|
||||
-a HASH --allowed HASH Specify identities allowed to connect. Allowed identities
|
||||
can also be specified in ~/.rnsh/allowed_identities or
|
||||
~/.config/rnsh/allowed_identities, one hash per line.
|
||||
-n --no-auth Disable authentication
|
||||
-N --no-id Disable identify on connect
|
||||
-A --remote-command-as-args Concatenate remote command to argument list of <program>/shell
|
||||
|
@ -64,7 +64,9 @@ def _get_logger(name: str):
|
||||
_identity = None
|
||||
_reticulum = None
|
||||
_allow_all = False
|
||||
_allowed_file = None
|
||||
_allowed_identity_hashes = []
|
||||
_allowed_file_identity_hashes = []
|
||||
_cmd: [str] | None = None
|
||||
DATA_AVAIL_MSG = "data available"
|
||||
_finished: asyncio.Event = None
|
||||
@ -88,12 +90,37 @@ def _sigint_handler(sig, loop):
|
||||
else:
|
||||
raise KeyboardInterrupt()
|
||||
|
||||
def _reload_allowed_file():
|
||||
global _allowed_file, _allowed_file_identity_hashes
|
||||
log = _get_logger("_listen")
|
||||
if _allowed_file != None:
|
||||
try:
|
||||
with open(_allowed_file, "r") as file:
|
||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH // 8) * 2
|
||||
added = 0
|
||||
line = 0
|
||||
_allowed_file_identity_hashes = []
|
||||
for allow in file.read().replace("\r", "").split("\n"):
|
||||
line += 1
|
||||
if len(allow) == dest_len:
|
||||
try:
|
||||
destination_hash = bytes.fromhex(allow)
|
||||
_allowed_file_identity_hashes.append(destination_hash)
|
||||
added += 1
|
||||
except Exception:
|
||||
log.debug(f"Discarded invalid Identity hash in {_allowed_file} at line {line}")
|
||||
|
||||
ms = "y" if added == 1 else "ies"
|
||||
log.debug(f"Loaded {added} allowed identit{ms} from "+str(_allowed_file))
|
||||
except Exception as e:
|
||||
log.error(f"Error while reloading allowed indetities file: {e}")
|
||||
|
||||
|
||||
async def listen(configdir, command, identitypath=None, service_name=None, verbosity=0, quietness=0, allowed=None,
|
||||
disable_auth=None, announce_period=900, no_remote_command=True, remote_cmd_as_args=False,
|
||||
allowed_file=None, disable_auth=None, announce_period=900, no_remote_command=True, remote_cmd_as_args=False,
|
||||
loop: asyncio.AbstractEventLoop = None):
|
||||
global _identity, _allow_all, _allowed_identity_hashes, _reticulum, _cmd, _destination, _no_remote_command
|
||||
global _remote_cmd_as_args, _finished
|
||||
global _identity, _allow_all, _allowed_identity_hashes, _allowed_file, _allowed_file_identity_hashes
|
||||
global _reticulum, _cmd, _destination, _no_remote_command, _remote_cmd_as_args, _finished
|
||||
log = _get_logger("_listen")
|
||||
if not loop:
|
||||
loop = asyncio.get_running_loop()
|
||||
@ -135,6 +162,10 @@ async def listen(configdir, command, identitypath=None, service_name=None, verbo
|
||||
_allow_all = True
|
||||
session.ListenerSession.allow_all = True
|
||||
else:
|
||||
if allowed_file is not None:
|
||||
_allowed_file = allowed_file
|
||||
_reload_allowed_file()
|
||||
|
||||
if allowed is not None:
|
||||
for a in allowed:
|
||||
try:
|
||||
@ -154,10 +185,13 @@ async def listen(configdir, command, identitypath=None, service_name=None, verbo
|
||||
log.error(str(e))
|
||||
exit(1)
|
||||
|
||||
if len(_allowed_identity_hashes) < 1 and not disable_auth:
|
||||
if (len(_allowed_identity_hashes) < 1 and len(_allowed_file_identity_hashes) < 1) and not disable_auth:
|
||||
log.warning("Warning: No allowed identities configured, rnsh will not accept any connections!")
|
||||
|
||||
def link_established(lnk: RNS.Link):
|
||||
_reload_allowed_file()
|
||||
session.ListenerSession.allowed_file_identity_hashes = _allowed_file_identity_hashes
|
||||
print(str(_allowed_file_identity_hashes))
|
||||
session.ListenerSession(session.RNSOutlet.get_outlet(lnk), lnk.get_channel(), loop)
|
||||
_destination.set_link_established_callback(link_established)
|
||||
|
||||
|
@ -117,7 +117,13 @@ async def _rnsh_cli_main():
|
||||
return 0
|
||||
|
||||
if args.listen:
|
||||
# log.info("command " + args.command)
|
||||
allowed_file = None
|
||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||
if os.path.isfile(os.path.expanduser("~/.config/rnsh/allowed_identities")):
|
||||
allowed_file = os.path.expanduser("~/.config/rnsh/allowed_identities")
|
||||
elif os.path.isfile(os.path.expanduser("~/.rnsh/allowed_identities")):
|
||||
allowed_file = os.path.expanduser("~/.rnsh/allowed_identities")
|
||||
|
||||
await listener.listen(configdir=args.config,
|
||||
command=args.command_line,
|
||||
identitypath=args.identity,
|
||||
@ -125,6 +131,7 @@ async def _rnsh_cli_main():
|
||||
verbosity=args.verbose,
|
||||
quietness=args.quiet,
|
||||
allowed=args.allowed,
|
||||
allowed_file=allowed_file,
|
||||
disable_auth=args.no_auth,
|
||||
announce_period=args.announce,
|
||||
no_remote_command=args.no_remote_cmd,
|
||||
|
@ -69,6 +69,7 @@ class LSOutletBase(ABC):
|
||||
class ListenerSession:
|
||||
sessions: List[ListenerSession] = []
|
||||
allowed_identity_hashes: [any] = []
|
||||
allowed_file_identity_hashes: [any] = []
|
||||
allow_all: bool = False
|
||||
allow_remote_command: bool = False
|
||||
default_command: [str] = []
|
||||
@ -183,7 +184,7 @@ class ListenerSession:
|
||||
if self.state not in [LSState.LSSTATE_WAIT_IDENT, LSState.LSSTATE_WAIT_VERS]:
|
||||
self._protocol_error(LSState.LSSTATE_WAIT_IDENT.name)
|
||||
|
||||
if not self.allow_all and identity.hash not in self.allowed_identity_hashes:
|
||||
if not self.allow_all and identity.hash not in self.allowed_identity_hashes and identity.hash not in self.allowed_file_identity_hashes:
|
||||
self.terminate("Identity is not allowed.")
|
||||
|
||||
self.remote_identity = identity
|
||||
|
Loading…
Reference in New Issue
Block a user