user management fix
This commit is contained in:
+60
-5
@@ -1,6 +1,8 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
import socket
|
||||
import sqlite3
|
||||
import struct
|
||||
import subprocess
|
||||
import threading
|
||||
@@ -16,6 +18,10 @@ BUFFER_SIZE = 65536
|
||||
POLKIT_ACTION = "org.sarlink.parentalcontrol.modify"
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Peer credentials and authorization
|
||||
# ============================================================
|
||||
|
||||
def get_peer_credentials(connection):
|
||||
credentials = connection.getsockopt(
|
||||
socket.SOL_SOCKET,
|
||||
@@ -26,7 +32,19 @@ def get_peer_credentials(connection):
|
||||
return struct.unpack("3i", credentials)
|
||||
|
||||
|
||||
def authorize_write(pid: int) -> bool:
|
||||
def authorize_write(pid: int, uid: int) -> bool:
|
||||
"""
|
||||
Authorize administrative operations.
|
||||
|
||||
Root is automatically authorized.
|
||||
|
||||
Non-root users must pass Polkit authorization.
|
||||
"""
|
||||
|
||||
# Root is already an administrator.
|
||||
if uid == 0:
|
||||
return True
|
||||
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError:
|
||||
@@ -53,6 +71,10 @@ def authorize_write(pid: int) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Database operations
|
||||
# ============================================================
|
||||
|
||||
class IPCOperations:
|
||||
|
||||
@staticmethod
|
||||
@@ -359,6 +381,10 @@ class IPCOperations:
|
||||
)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Allowed IPC methods
|
||||
# ============================================================
|
||||
|
||||
READ_METHODS = {
|
||||
"get_users",
|
||||
"get_user",
|
||||
@@ -377,7 +403,15 @@ WRITE_METHODS = {
|
||||
}
|
||||
|
||||
|
||||
def handle_request(request, pid):
|
||||
# ============================================================
|
||||
# Request handling
|
||||
# ============================================================
|
||||
|
||||
def handle_request(
|
||||
request,
|
||||
pid,
|
||||
uid,
|
||||
):
|
||||
method = request.get("method")
|
||||
arguments = request.get("args", {})
|
||||
|
||||
@@ -396,7 +430,7 @@ def handle_request(request, pid):
|
||||
return operation(**arguments)
|
||||
|
||||
if method in WRITE_METHODS:
|
||||
if not authorize_write(pid):
|
||||
if not authorize_write(pid, uid):
|
||||
raise PermissionError(
|
||||
"Administrative authorization required"
|
||||
)
|
||||
@@ -419,6 +453,10 @@ def handle_request(request, pid):
|
||||
)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Client handling
|
||||
# ============================================================
|
||||
|
||||
def handle_client(connection):
|
||||
try:
|
||||
pid, uid, gid = get_peer_credentials(
|
||||
@@ -456,6 +494,7 @@ def handle_client(connection):
|
||||
result = handle_request(
|
||||
request,
|
||||
pid,
|
||||
uid,
|
||||
)
|
||||
|
||||
response = {
|
||||
@@ -470,6 +509,13 @@ def handle_client(connection):
|
||||
"error_type": "authorization",
|
||||
}
|
||||
|
||||
except sqlite3.IntegrityError as exc:
|
||||
response = {
|
||||
"ok": False,
|
||||
"error": str(exc),
|
||||
"error_type": "database",
|
||||
}
|
||||
|
||||
except Exception as exc:
|
||||
response = {
|
||||
"ok": False,
|
||||
@@ -500,6 +546,10 @@ def handle_client(connection):
|
||||
connection.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# IPC server
|
||||
# ============================================================
|
||||
|
||||
class IPCServer:
|
||||
|
||||
def __init__(
|
||||
@@ -515,7 +565,10 @@ class IPCServer:
|
||||
self._stop_event = threading.Event()
|
||||
|
||||
def start(self):
|
||||
if self._thread is not None:
|
||||
if (
|
||||
self._thread is not None
|
||||
and self._thread.is_alive()
|
||||
):
|
||||
return
|
||||
|
||||
self.socket_path.parent.mkdir(
|
||||
@@ -564,7 +617,9 @@ class IPCServer:
|
||||
pass
|
||||
|
||||
if self._thread is not None:
|
||||
self._thread.join(timeout=2)
|
||||
self._thread.join(
|
||||
timeout=2
|
||||
)
|
||||
|
||||
self._thread = None
|
||||
self.server_socket = None
|
||||
|
||||
Reference in New Issue
Block a user