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

This commit is contained in:
slawek committed 2026-10-26 00:43:55 +01:00
1 parent ec93bc6a2d
commit 07dbe91d0c
5 files changed
+23 -5

No files matched your search

+5 -2
View File
@@ -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)
+5 -1
View File
@@ -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)