fix: the shell of a user's own POSIX account opens on the first setup that sets up console login, and the journal records each refused shell with the reason.
Release / release (push) Successful in 20s
Release / release (push) Successful in 20s
This commit is contained in:
1 parent
ec93bc6a2d
commit
07dbe91d0c
5 files changed
+23
-5
No files matched your search
@@ -913,7 +913,7 @@ ticket gets the shell. The WebSocket of RFC 6455 is implemented on the standard
|
||||
web service's `http.server`, server side only, without extensions. `systemd-run --pty` starts the
|
||||
shell in a transient unit with a PAM login session, outside the sandbox, and `setsid --ctty`
|
||||
makes the terminal its controlling terminal so window sizes reach the shell. A shell idle for
|
||||
`web.shell_idle_minutes` is closed, and the journal records every opening and end. The Router
|
||||
`web.shell_idle_minutes` is closed, and the journal records every opening, end and refusal. The Router
|
||||
Manager checks the session and the WebSocket's origin, and relays the bytes to the router after
|
||||
both handshakes.
|
||||
|
||||
|
||||
@@ -984,7 +984,7 @@ the router are the terminal's output. The shell is a PAM login session of the co
|
||||
run by `systemd-run` in a transient unit `vpn-router-shell-<id>`; sudo works as for SSH. It is closed after `web.shell_idle_minutes` without a keystroke, when the shell
|
||||
exits, or when the connection closes; the router then sends a close frame with the reason. The
|
||||
journal of `vpn-router-web` records who opened each shell, from which address, in which unit,
|
||||
when it ended and why.
|
||||
when it ended and why, and each refused ticket or shell with the reason.
|
||||
|
||||
### The /config page
|
||||
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
vpn-router (0.23.2-1) unstable; urgency=medium
|
||||
|
||||
fix: the shell of a user's own POSIX account opens on the first setup that sets up console login, and the journal records each refused shell with the reason.
|
||||
|
||||
* Setup restarts vpn-router-web when it adds ldap to the name service
|
||||
switch, so the web service finds the POSIX accounts of the directory.
|
||||
* The journal of vpn-router-web records each refused ticket and shell,
|
||||
with the user, the address and the reason.
|
||||
|
||||
-- Slawomir Koszewski <slawek@koszewscy.waw.pl> Mon, 02 Nov 2026 22:00:00 +0100
|
||||
|
||||
vpn-router (0.23.1-1) unstable; urgency=medium
|
||||
|
||||
fix: the shell runs as the console account of each member of admins, a local account or the user's own POSIX account in the directory, which also signs in with SSH and sudo, instead of one web.shell_user.
|
||||
|
||||
@@ -555,8 +555,8 @@ def manage_console(cfg):
|
||||
|
||||
The local group vpnrouter_ldap.CONSOLE_GROUP is created when missing, and sudo lets its members run any command
|
||||
with their password. nslcd serves the directory's posixAccounts with console login on through the local socket,
|
||||
and checks their passwords by binding as the user; the passwd line of the name service switch gains ldap, and PAM
|
||||
creates a home at the first login. While ssh.ldap_login is true, sshd accepts the password of the group's members;
|
||||
and checks their passwords by binding as the user; the passwd line of the name service switch gains ldap, which
|
||||
restarts the web service, and PAM creates a home at the first login. While ssh.ldap_login is true, sshd accepts the password of the group's members;
|
||||
a drop-in sshd -t refuses is removed again.
|
||||
"""
|
||||
group = vpnrouter_ldap.CONSOLE_GROUP
|
||||
@@ -601,6 +601,9 @@ def manage_console(cfg):
|
||||
for line in lines]
|
||||
if switched != lines:
|
||||
NSSWITCH.write_text(''.join(switched), encoding='utf-8')
|
||||
# A running process keeps the name service switch it read first, so the web service's shell would not find
|
||||
# the console accounts of the directory until it restarts.
|
||||
run(['systemctl', 'try-restart', 'vpn-router-web.service'], check=False)
|
||||
|
||||
if 'pam_mkhomedir' not in PAM_SESSION.read_text(encoding='utf-8'):
|
||||
run(['pam-auth-update', '--enable', 'mkhomedir'], check=False)
|
||||
|
||||
@@ -1193,9 +1193,11 @@ class Handler(BaseHTTPRequestHandler):
|
||||
The ticket must come from POST /shell for the user named by the token. Binary messages of the client are its
|
||||
keystrokes, a text message {"cols", "rows"} sets the window size, and binary messages of the server are the
|
||||
terminal's output. The shell ends after web.shell_idle_minutes without a keystroke, when it exits, or when the
|
||||
client closes the connection; the server then closes it with the reason. Each opening and end is logged.
|
||||
client closes the connection; the server then closes it with the reason. Each opening, end and refusal is logged
|
||||
with its reason.
|
||||
"""
|
||||
def refuse(code, message):
|
||||
log(f'shell of {name} from {self.client()} refused: {message}')
|
||||
body = json.dumps({'error': message}).encode() + b'\n'
|
||||
self.send_response(code)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
@@ -1360,6 +1362,8 @@ class Handler(BaseHTTPRequestHandler):
|
||||
elif directory == 'shell':
|
||||
code, document = shell_ticket(claims.get('sub'), payload) if (path, self.command) == ('/shell', 'POST') \
|
||||
else (404, {'error': f'no route {self.command} {path}'})
|
||||
if code != 200:
|
||||
log(f'shell ticket of {claims.get("sub")} from {self.client()} refused: {document["error"]}')
|
||||
body, kind = json.dumps(document, indent=2).encode() + b'\n', 'application/json'
|
||||
elif directory == 'account':
|
||||
code, document = account(claims['sub'], self.command, path, payload)
|
||||
|
||||
Reference in new issue
Block a user