secubox-openwrt/package/secubox/luci-app-auth-guardian/root/usr/libexec/rpcd/luci.auth-guardian
CyberMind-FR 31a87c5d7a feat(structure): reorganize luci-app packages into package/secubox/ + appstore migration
Major structural reorganization and feature additions:

## Folder Reorganization
- Move 17 luci-app-* packages to package/secubox/ (except luci-app-secubox core hub)
- Update all tooling to support new structure:
  - secubox-tools/quick-deploy.sh: search both locations
  - secubox-tools/validate-modules.sh: validate both directories
  - secubox-tools/fix-permissions.sh: fix permissions in both locations
  - .github/workflows/test-validate.yml: build from both paths
- Update README.md links to new package/secubox/ paths

## AppStore Migration (Complete)
- Add catalog entries for all remaining luci-app packages:
  - network-tweaks.json: Network optimization tools
  - secubox-bonus.json: Documentation & demos hub
- Total: 24 apps in AppStore catalog (22 existing + 2 new)
- New category: 'documentation' for docs/demos/tutorials

## VHost Manager v2.0 Enhancements
- Add profile activation system for Internal Services and Redirects
- Implement createVHost() API wrapper for template-based deployment
- Fix Virtual Hosts view rendering with proper LuCI patterns
- Fix RPCD backend shell script errors (remove invalid local declarations)
- Extend backend validation for nginx return directives (redirect support)
- Add section_id parameter for named VHost profiles
- Add Remove button to Redirects page for feature parity
- Update README to v2.0 with comprehensive feature documentation

## Network Tweaks Dashboard
- Close button added to component details modal

Files changed: 340+ (336 renames with preserved git history)
Packages affected: 19 luci-app, 2 secubox-app, 1 theme, 4 tools

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 14:59:38 +01:00

518 lines
13 KiB
Bash
Executable File

#!/bin/sh
# Auth Guardian RPCD Backend
# OAuth2 authentication and voucher system
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
# Configuration paths
CONFIG_FILE="/etc/config/auth_guardian"
SESSIONS_FILE="/tmp/auth_guardian_sessions.json"
LOGS_FILE="/tmp/auth_guardian_logs.json"
# Initialize storage
init_storage() {
mkdir -p /tmp/auth_guardian
[ ! -f "$SESSIONS_FILE" ] && echo '[]' > "$SESSIONS_FILE"
[ ! -f "$LOGS_FILE" ] && echo '[]' > "$LOGS_FILE"
touch "$CONFIG_FILE"
}
# Generate unique ID
generate_id() {
head -c 8 /dev/urandom | hexdump -e '"%016x"'
}
# Generate voucher code
generate_voucher_code() {
local part1=$(head -c 3 /dev/urandom | hexdump -e '"%06x"' | tr '[:lower:]' '[:upper:]')
local part2=$(head -c 3 /dev/urandom | hexdump -e '"%06x"' | tr '[:lower:]' '[:upper:]')
local part3=$(head -c 3 /dev/urandom | hexdump -e '"%06x"' | tr '[:lower:]' '[:upper:]')
echo "${part1}-${part2}-${part3}"
}
# Add log entry
add_log() {
local event="$1"
local details="$2"
local mac="$3"
init_storage
local timestamp=$(date -Iseconds)
local entry="{\"timestamp\":\"$timestamp\",\"event\":\"$event\",\"details\":\"$details\",\"mac\":\"$mac\"}"
if [ -f "$LOGS_FILE" ]; then
jq ". += [$entry] | .[-500:]" "$LOGS_FILE" > "${LOGS_FILE}.tmp" 2>/dev/null && mv "${LOGS_FILE}.tmp" "$LOGS_FILE"
fi
}
# Get system status
status() {
init_storage
json_init
config_load auth_guardian
local enabled auth_method
config_get enabled global enabled "0"
config_get auth_method global auth_method "splash"
json_add_boolean "enabled" "$enabled"
json_add_string "auth_method" "$auth_method"
# Count active sessions
local sessions=0
if [ -f "$SESSIONS_FILE" ]; then
sessions=$(jq '[.[] | select(.active == true)] | length' "$SESSIONS_FILE" 2>/dev/null || echo 0)
fi
json_add_int "active_sessions" "$sessions"
# Count OAuth providers
local provider_count=0
config_foreach count_section oauth_provider && provider_count=$?
json_add_int "oauth_providers" "$provider_count"
# Count vouchers
local voucher_count=0
local active_vouchers=0
config_foreach count_vouchers voucher
json_add_int "total_vouchers" "$voucher_count"
json_add_int "active_vouchers" "$active_vouchers"
# Check nodogsplash
local captive_portal=0
pgrep -x nodogsplash >/dev/null 2>&1 && captive_portal=1
json_add_boolean "captive_portal_active" "$captive_portal"
json_dump
}
count_section() {
return $(( $? + 1 ))
}
count_vouchers() {
voucher_count=$((voucher_count + 1))
local used
config_get used "$1" used "0"
[ "$used" = "0" ] && active_vouchers=$((active_vouchers + 1))
}
# List OAuth providers
list_providers() {
config_load auth_guardian
json_init
json_add_array "providers"
_add_provider() {
local name client_id client_secret redirect_uri enabled
config_get name "$1" name ""
config_get client_id "$1" client_id ""
config_get client_secret "$1" client_secret ""
config_get redirect_uri "$1" redirect_uri ""
config_get enabled "$1" enabled "0"
json_add_object ""
json_add_string "id" "$1"
json_add_string "name" "$name"
json_add_string "client_id" "$client_id"
json_add_string "client_secret" "${client_secret:0:10}..." # Masked
json_add_string "redirect_uri" "$redirect_uri"
json_add_boolean "enabled" "$enabled"
json_close_object
}
config_foreach _add_provider oauth_provider
json_close_array
json_dump
}
# Set OAuth provider
set_provider() {
read -r input
json_load "$input"
local provider name client_id client_secret redirect_uri
json_get_var provider provider
json_get_var name name
json_get_var client_id client_id
json_get_var client_secret client_secret
json_get_var redirect_uri redirect_uri
if [ -z "$provider" ] || [ -z "$client_id" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Provider type and client_id required"
json_dump
return
fi
# Create or update provider
local section_id="oauth_$(echo $provider | tr '[:upper:]' '[:lower:]')"
uci -q delete "auth_guardian.${section_id}" 2>/dev/null
uci set "auth_guardian.${section_id}=oauth_provider"
uci set "auth_guardian.${section_id}.name=$name"
uci set "auth_guardian.${section_id}.provider=$provider"
uci set "auth_guardian.${section_id}.client_id=$client_id"
uci set "auth_guardian.${section_id}.client_secret=$client_secret"
uci set "auth_guardian.${section_id}.redirect_uri=$redirect_uri"
uci set "auth_guardian.${section_id}.enabled=1"
uci commit auth_guardian
add_log "provider_configured" "OAuth provider $name configured" ""
json_init
json_add_boolean "success" 1
json_add_string "message" "OAuth provider configured"
json_add_string "provider_id" "$section_id"
json_dump
}
# Delete OAuth provider
delete_provider() {
read -r input
json_load "$input"
local provider_id
json_get_var provider_id provider_id
if [ -z "$provider_id" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Provider ID required"
json_dump
return
fi
uci -q delete "auth_guardian.${provider_id}" 2>/dev/null
uci commit auth_guardian
add_log "provider_deleted" "OAuth provider $provider_id deleted" ""
json_init
json_add_boolean "success" 1
json_add_string "message" "Provider deleted"
json_dump
}
# List all vouchers
list_vouchers() {
config_load auth_guardian
json_init
json_add_array "vouchers"
_add_voucher() {
local code duration_hours data_limit_mb created used note
config_get code "$1" code ""
config_get duration_hours "$1" duration_hours "24"
config_get data_limit_mb "$1" data_limit_mb "0"
config_get created "$1" created ""
config_get used "$1" used "0"
config_get note "$1" note ""
config_get used_by "$1" used_by ""
config_get used_at "$1" used_at ""
json_add_object ""
json_add_string "id" "$1"
json_add_string "code" "$code"
json_add_int "duration_hours" "$duration_hours"
json_add_int "data_limit_mb" "$data_limit_mb"
json_add_string "created" "$created"
json_add_boolean "used" "$used"
json_add_string "note" "$note"
json_add_string "used_by" "$used_by"
json_add_string "used_at" "$used_at"
json_close_object
}
config_foreach _add_voucher voucher
json_close_array
json_dump
}
# Create voucher
create_voucher() {
read -r input
json_load "$input"
local duration_hours data_limit_mb note
json_get_var duration_hours duration_hours
json_get_var data_limit_mb data_limit_mb
json_get_var note note
# Defaults
duration_hours=${duration_hours:-24}
data_limit_mb=${data_limit_mb:-0}
note=${note:-""}
# Generate voucher code
local code=$(generate_voucher_code)
local voucher_id="v_$(generate_id)"
local timestamp=$(date -Iseconds)
# Save to UCI
uci set "auth_guardian.${voucher_id}=voucher"
uci set "auth_guardian.${voucher_id}.code=$code"
uci set "auth_guardian.${voucher_id}.duration_hours=$duration_hours"
uci set "auth_guardian.${voucher_id}.data_limit_mb=$data_limit_mb"
uci set "auth_guardian.${voucher_id}.created=$timestamp"
uci set "auth_guardian.${voucher_id}.used=0"
uci set "auth_guardian.${voucher_id}.note=$note"
uci commit auth_guardian
add_log "voucher_created" "Voucher $code created" ""
json_init
json_add_boolean "success" 1
json_add_string "message" "Voucher created"
json_add_string "voucher_id" "$voucher_id"
json_add_string "code" "$code"
json_add_int "duration_hours" "$duration_hours"
json_add_int "data_limit_mb" "$data_limit_mb"
json_dump
}
# Delete voucher
delete_voucher() {
read -r input
json_load "$input"
local voucher_id
json_get_var voucher_id voucher_id
if [ -z "$voucher_id" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Voucher ID required"
json_dump
return
fi
config_load auth_guardian
local code
config_get code "$voucher_id" code ""
uci -q delete "auth_guardian.${voucher_id}" 2>/dev/null
uci commit auth_guardian
add_log "voucher_deleted" "Voucher $code deleted" ""
json_init
json_add_boolean "success" 1
json_add_string "message" "Voucher deleted"
json_dump
}
# Validate voucher code
validate_voucher() {
read -r input
json_load "$input"
local code mac
json_get_var code code
json_get_var mac mac
if [ -z "$code" ]; then
json_init
json_add_boolean "valid" 0
json_add_string "error" "Voucher code required"
json_dump
return
fi
# Search for voucher
config_load auth_guardian
local found=0
local voucher_id=""
local duration=24
local data_limit=0
local used=0
_check_voucher() {
local v_code v_used
config_get v_code "$1" code ""
config_get v_used "$1" used "0"
if [ "$v_code" = "$code" ]; then
found=1
voucher_id="$1"
config_get duration "$1" duration_hours "24"
config_get data_limit "$1" data_limit_mb "0"
used="$v_used"
fi
}
config_foreach _check_voucher voucher
if [ "$found" = "1" ] && [ "$used" = "0" ]; then
# Mark as used
local timestamp=$(date -Iseconds)
uci set "auth_guardian.${voucher_id}.used=1"
uci set "auth_guardian.${voucher_id}.used_by=$mac"
uci set "auth_guardian.${voucher_id}.used_at=$timestamp"
uci commit auth_guardian
# Authorize MAC via nodogsplash if available
if command -v ndsctl >/dev/null 2>&1 && [ -n "$mac" ]; then
ndsctl auth "$mac" >/dev/null 2>&1
fi
add_log "voucher_used" "Voucher $code validated" "$mac"
json_init
json_add_boolean "valid" 1
json_add_string "message" "Voucher valid and activated"
json_add_int "duration_hours" "$duration"
json_add_int "data_limit_mb" "$data_limit"
json_dump
else
json_init
json_add_boolean "valid" 0
json_add_string "error" "Invalid or already used voucher"
json_dump
fi
}
# List active sessions
list_sessions() {
init_storage
json_init
json_add_array "sessions"
# Get sessions from nodogsplash if available
if command -v ndsctl >/dev/null 2>&1; then
ndsctl json 2>/dev/null | jq -c '.clients[]?' 2>/dev/null | while IFS= read -r client; do
local mac=$(echo "$client" | jq -r '.mac // ""')
local ip=$(echo "$client" | jq -r '.ip // ""')
local uploaded=$(echo "$client" | jq -r '.uploaded // 0')
local downloaded=$(echo "$client" | jq -r '.downloaded // 0')
local duration=$(echo "$client" | jq -r '.duration // 0')
json_add_object ""
json_add_string "mac" "$mac"
json_add_string "ip" "$ip"
json_add_int "uploaded_bytes" "$uploaded"
json_add_int "downloaded_bytes" "$downloaded"
json_add_int "duration_seconds" "$duration"
json_add_boolean "active" 1
json_add_string "auth_method" "voucher"
json_close_object
done
fi
# Also add from sessions file
if [ -f "$SESSIONS_FILE" ]; then
jq -c '.[]?' "$SESSIONS_FILE" 2>/dev/null | while IFS= read -r session; do
echo "$session"
done
fi
json_close_array
json_dump
}
# Revoke session
revoke_session() {
read -r input
json_load "$input"
local mac
json_get_var mac mac
if [ -z "$mac" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "MAC address required"
json_dump
return
fi
# Deauth via nodogsplash
if command -v ndsctl >/dev/null 2>&1; then
ndsctl deauth "$mac" >/dev/null 2>&1
fi
# Remove from sessions file
if [ -f "$SESSIONS_FILE" ]; then
jq "map(select(.mac != \"$mac\"))" "$SESSIONS_FILE" > "${SESSIONS_FILE}.tmp" 2>/dev/null && mv "${SESSIONS_FILE}.tmp" "$SESSIONS_FILE"
fi
add_log "session_revoked" "Session revoked for $mac" "$mac"
json_init
json_add_boolean "success" 1
json_add_string "message" "Session revoked"
json_dump
}
# Get authentication logs
get_logs() {
read -r input
json_load "$input"
local limit
json_get_var limit limit
limit=${limit:-100}
init_storage
json_init
json_add_array "logs"
if [ -f "$LOGS_FILE" ]; then
jq -c ".[-${limit}:][]" "$LOGS_FILE" 2>/dev/null | while IFS= read -r entry; do
echo "$entry"
done
fi
json_close_array
json_dump
}
# Main dispatcher
case "$1" in
list)
cat << 'EOF'
{
"status": {},
"list_providers": {},
"set_provider": { "provider": "string", "name": "string", "client_id": "string", "client_secret": "string", "redirect_uri": "string" },
"delete_provider": { "provider_id": "string" },
"list_vouchers": {},
"create_voucher": { "duration_hours": 24, "data_limit_mb": 0, "note": "string" },
"delete_voucher": { "voucher_id": "string" },
"validate_voucher": { "code": "string", "mac": "string" },
"list_sessions": {},
"revoke_session": { "mac": "string" },
"get_logs": { "limit": 100 }
}
EOF
;;
call)
case "$2" in
status) status ;;
list_providers) list_providers ;;
set_provider) set_provider ;;
delete_provider) delete_provider ;;
list_vouchers) list_vouchers ;;
create_voucher) create_voucher ;;
delete_voucher) delete_voucher ;;
validate_voucher) validate_voucher ;;
list_sessions) list_sessions ;;
revoke_session) revoke_session ;;
get_logs) get_logs ;;
*)
json_init
json_add_int "error" -32601
json_add_string "message" "Method not found: $2"
json_dump
;;
esac
;;
esac