Refactor security configuration handling: update LoginHelper to retrieve security settings from the correct config path and adjust max_clients default value; modify APIEndpoints to ensure distinct admin and guest passwords, and enhance identity key validation logic in API responses.

This commit is contained in:
Lloyd
2025-12-18 15:02:23 +00:00
parent ccc908ce32
commit c98a33eda5
4 changed files with 102 additions and 29 deletions
+3 -3
View File
@@ -55,10 +55,10 @@ class LoginHelper:
"allow_read_only": settings.get("allow_read_only", True),
}
else:
# Repeater uses security from its config
security = config.get("security", {})
# Repeater uses security from repeater.security in config
security = config.get("repeater", {}).get("security", {})
final_security = {
"max_clients": security.get("max_clients", 50),
"max_clients": security.get("max_clients", 10),
"admin_password": security.get("admin_password", "admin123"),
"guest_password": security.get("guest_password", "guest123"),
"allow_read_only": security.get("allow_read_only", True),
+1 -2
View File
@@ -168,12 +168,11 @@ class RepeaterDaemon:
)
# Register default repeater identity
repeater_config = self.config.get("repeater", {})
self.login_helper.register_identity(
name="repeater",
identity=self.local_identity,
identity_type="repeater",
config=repeater_config # Pass repeater config (includes security settings)
config=self.config # Pass full config so repeater can access top-level security section
)
# Register room server identities with their configs
+25 -2
View File
@@ -1141,6 +1141,12 @@ class APIEndpoints:
if not name:
return self._error("Missing required field: name")
# Validate passwords are different if both provided
admin_pw = settings.get("admin_password")
guest_pw = settings.get("guest_password")
if admin_pw and guest_pw and admin_pw == guest_pw:
return self._error("admin_password and guest_password must be different")
# Auto-generate identity key if not provided
key_was_generated = False
if not identity_key:
@@ -1301,15 +1307,32 @@ class APIEndpoints:
return self._error(f"Identity with name '{new_name}' already exists")
identity["name"] = new_name
# Only update identity_key if a non-empty value is provided
# Only update identity_key if a valid full key is provided
# Silently reject truncated keys (containing "...") or invalid hex strings
if "identity_key" in data and data["identity_key"]:
identity["identity_key"] = data["identity_key"]
new_key = data["identity_key"]
# Check if it's a truncated key (contains "...") or not a valid 64-char hex string
if "..." not in new_key and len(new_key) == 64:
try:
# Validate it's proper hex
bytes.fromhex(new_key)
identity["identity_key"] = new_key
logger.info(f"Updated identity_key for '{name}'")
except ValueError:
# Invalid hex, silently ignore
pass
if "settings" in data:
# Merge settings
if "settings" not in identity:
identity["settings"] = {}
identity["settings"].update(data["settings"])
# Validate passwords are different if both are now set
admin_pw = identity["settings"].get("admin_password")
guest_pw = identity["settings"].get("guest_password")
if admin_pw and guest_pw and admin_pw == guest_pw:
return self._error("admin_password and guest_password must be different")
# Save to config
room_servers[identity_index] = identity
+73 -22
View File
@@ -699,7 +699,7 @@ paths:
get:
tags: [ACL]
summary: List ACL clients
description: Get list of clients in access control list
description: Get list of authenticated clients in access control list for an identity
parameters:
- name: identity_hash
in: query
@@ -730,7 +730,32 @@ paths:
clients:
type: array
items:
$ref: '#/components/schemas/ACLEntry'
$ref: '#/components/schemas/ACLClient'
count:
type: integer
description: Number of clients returned
filter:
type: string
nullable: true
description: Filter applied (if any)
examples:
success:
value:
success: true
data:
clients:
- public_key: "03ccf3bb0bed9a51...21416fff"
public_key_full: "03ccf3bb0bed9a5109868a1e33ed020519aab6dbb30e42df3b11a21d21416fff"
address: "e1"
permissions: "admin"
last_activity: 1766065148
last_login_success: 1766065146
last_timestamp: 1766065146
identity_name: "rrrrr"
identity_type: "room_server"
identity_hash: "0xC5"
count: 1
filter: null
/acl_remove_client:
post:
@@ -1441,32 +1466,58 @@ components:
description: Maximum messages to keep (room_server only, hard limit 32)
example: 32
ACLEntry:
ACLClient:
type: object
required: [action, network_address, port]
required: [public_key, public_key_full, address, permissions]
properties:
action:
public_key:
type: string
enum: [allow, deny]
description: Truncated public key for display (first 24 and last 8 chars)
example: "03ccf3bb0bed9a51...21416fff"
public_key_full:
type: string
pattern: '^[0-9a-fA-F]{64}$'
description: Full client public key (64 hex chars)
example: "03ccf3bb0bed9a5109868a1e33ed020519aab6dbb30e42df3b11a21d21416fff"
address:
type: string
description: Client address identifier
example: "e1"
permissions:
type: string
enum: [admin, guest, read_only]
description: |
- allow: Permit packets from this address
- deny: Block packets from this address
example: allow
network_address:
type: string
description: IP address or CIDR range (e.g., 192.168.1.0/24)
example: "192.168.1.0/24"
port:
Client permission level:
- admin: Full access
- guest: Limited access
- read_only: Read-only access
example: "admin"
last_activity:
type: integer
minimum: 0
maximum: 65535
description: Source port (0 = any port)
example: 0
comment:
description: Unix timestamp of last activity
example: 1766065148
last_login_success:
type: integer
description: Unix timestamp of last successful login
example: 1766065146
last_timestamp:
type: integer
description: Unix timestamp from last client message
example: 1766065146
identity_name:
type: string
maxLength: 200
description: Optional description
example: "Allow local network"
description: Name of the identity this client is authenticated to
example: "rrrrr"
identity_type:
type: string
enum: [repeater, room_server]
description: Type of identity
example: "room_server"
identity_hash:
type: string
pattern: '^0x[0-9a-fA-F]{2}$'
description: Hash of the identity
example: "0xC5"
securitySchemes:
# Future: API key authentication