From d853b35654c93ed6742a250453fca13ee8bcfe00 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sun, 22 Feb 2026 11:43:49 -0500 Subject: [PATCH] enforce a users usage understanding by adding a startup configuration parameter that must be set; --- configs/config.example.yml | 13 +++++++ configs/fne-config.example.yml | 13 +++++++ src/fne/HostFNE.cpp | 7 ++++ src/host/Host.Config.cpp | 7 ++++ tools/dvmcfggen/wizard.py | 70 ++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+) diff --git a/configs/config.example.yml b/configs/config.example.yml index adc7a1ab..70c2f629 100644 --- a/configs/config.example.yml +++ b/configs/config.example.yml @@ -5,6 +5,19 @@ # Flag indicating whether the host will run as a background or foreground task. daemon: true +# +# This flag should be set to 'true', it simply means that you acknowledge the license and restrictions of use for this +# software, at no time should THIS SOFTWARE EVER BE USED IN PUBLIC SAFETY OR LIFE SAFETY CRITICAL APPLICATIONS. This +# software project is provided solely for personal, non-commercial, hobbyist use; any commercial, professional, +# governmental, or other non-hobbyist use is strictly discouraged, fully unsupported and expressly disclaimed by +# the authors. +# +# By using this software, you agree to indemnify, defend, and hold harmless the authors, contributors, and affiliated +# parties from and against any and all claims, liabilities, damages, losses, or expenses (including reasonable +# attorneys’ fees) arising out of or relating to any unlawful, unauthorized, or improper use of the software. +# +iAgreeNotToBeStupid: false + # # Logging Configuration # diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml index c0773240..6ed93b7e 100644 --- a/configs/fne-config.example.yml +++ b/configs/fne-config.example.yml @@ -5,6 +5,19 @@ # Flag indicating whether the host will run as a background or foreground task. daemon: true +# +# This flag should be set to 'true', it simply means that you acknowledge the license and restrictions of use for this +# software, at no time should THIS SOFTWARE EVER BE USED IN PUBLIC SAFETY OR LIFE SAFETY CRITICAL APPLICATIONS. This +# software project is provided solely for personal, non-commercial, hobbyist use; any commercial, professional, +# governmental, or other non-hobbyist use is strictly discouraged, fully unsupported and expressly disclaimed by +# the authors. +# +# By using this software, you agree to indemnify, defend, and hold harmless the authors, contributors, and affiliated +# parties from and against any and all claims, liabilities, damages, losses, or expenses (including reasonable +# attorneys’ fees) arising out of or relating to any unlawful, unauthorized, or improper use of the software. +# +iAgreeNotToBeStupid: false + # # Logging Configuration # Logging Levels: diff --git a/src/fne/HostFNE.cpp b/src/fne/HostFNE.cpp index 5fce38fd..9007c1b8 100644 --- a/src/fne/HostFNE.cpp +++ b/src/fne/HostFNE.cpp @@ -342,6 +342,13 @@ bool HostFNE::readParams() bool sendTalkgroups = systemConf["sendTalkgroups"].as(true); m_peerReplicaSavesACL = systemConf["peerReplicaSaveACL"].as(false); + bool iAgreeNotToBeStupid = systemConf["iAgreeNotToBeStupid"].as(false); + if (!iAgreeNotToBeStupid) { + LogError(LOG_HOST, HIGHLY_UNNECESSARY_DISCLAIMER_FOR_THE_MENTAL); + LogError(LOG_HOST, "You must agree to software license terms, and not to be stupid to use this software."); + return false; + } + if (m_pingTime == 0U) { m_pingTime = 5U; } diff --git a/src/host/Host.Config.cpp b/src/host/Host.Config.cpp index 76630916..fa8bfcf8 100644 --- a/src/host/Host.Config.cpp +++ b/src/host/Host.Config.cpp @@ -59,6 +59,13 @@ bool Host::readParams() m_duplex = systemConf["duplex"].as(true); bool simplexSameFreq = systemConf["simplexSameFrequency"].as(false); + bool iAgreeNotToBeStupid = systemConf["iAgreeNotToBeStupid"].as(false); + if (!iAgreeNotToBeStupid) { + LogError(LOG_HOST, HIGHLY_UNNECESSARY_DISCLAIMER_FOR_THE_MENTAL); + LogError(LOG_HOST, "You must agree to software license terms, and not to be stupid to use this software."); + return false; + } + m_timeout = systemConf["timeout"].as(120U); m_rfModeHang = systemConf["rfModeHang"].as(10U); m_rfTalkgroupHang = systemConf["rfTalkgroupHang"].as(10U); diff --git a/tools/dvmcfggen/wizard.py b/tools/dvmcfggen/wizard.py index 1cf4d7cc..d0f75f6b 100644 --- a/tools/dvmcfggen/wizard.py +++ b/tools/dvmcfggen/wizard.py @@ -122,6 +122,13 @@ class ConfigWizard: console.print() + # Step 1b: Usage Agreement (REQUIRED - not overridable with answers file) + if not self._confirm_usage_agreement(): + console.print("\n[red]Usage agreement not accepted. Configuration wizard cancelled.[/red]") + return None + + console.print() + # Step 2: Create base config self.config = DVMConfig() self.config.config = get_template(self.template_name) @@ -137,6 +144,34 @@ class ConfigWizard: return None + def _confirm_usage_agreement(self) -> bool: + """ + Display and confirm the usage agreement. + This prompt CANNOT be overridden by answers file. + """ + console.print("[bold yellow]Usage Agreement[/bold yellow]\n") + console.print( + "[yellow]⚠ IMPORTANT NOTICE[/yellow]\n" + "This software is provided solely for personal, non-commercial, hobbyist use.\n" + "Use in public safety or life safety critical applications is STRICTLY PROHIBITED.\n\n" + "[red]DO NOT use this software for:[/red]\n" + " • Emergency services (police, fire, EMS)\n" + " • Life safety critical operations\n" + " • Commercial use without explicit permission\n" + " • Any governmental or professional application\n\n" + "[yellow]By continuing, you acknowledge:[/yellow]\n" + " • You understand the restrictions on this software\n" + " • You agree to use it only for hobbyist purposes\n" + " • You indemnify the authors against any misuse\n" + ) + + # This is INTENTIONALLY not using _get_answer() + # License agreement must be explicitly confirmed each time + return Confirm.ask( + "Do you agree to these terms and understand the restrictions?", + default=False + ) + def _choose_template(self) -> Optional[str]: """Choose configuration template""" console.print("[bold]Step 1: Choose Configuration Template[/bold]\n") @@ -1098,6 +1133,34 @@ class TrunkingWizard: self.answers = answers or {} self.iden_table: IdenTable = create_default_iden_table() + def _confirm_usage_agreement(self) -> bool: + """ + Display and confirm the usage agreement. + This prompt CANNOT be overridden by answers file. + """ + console.print("[bold yellow]Usage Agreement[/bold yellow]\n") + console.print( + "[yellow]⚠ IMPORTANT NOTICE[/yellow]\n" + "This software is provided solely for personal, non-commercial, hobbyist use.\n" + "Use in public safety or life safety critical applications is STRICTLY PROHIBITED.\n\n" + "[red]DO NOT use this software for:[/red]\n" + " • Emergency services (police, fire, EMS)\n" + " • Life safety critical operations\n" + " • Commercial use without explicit permission\n" + " • Any governmental or professional application\n\n" + "[yellow]By continuing, you acknowledge:[/yellow]\n" + " • You understand the restrictions on this software\n" + " • You agree to use it only for hobbyist purposes\n" + " • You indemnify the authors against any misuse\n" + ) + + # This is INTENTIONALLY not using _get_answer() + # Usage agreement must be explicitly confirmed each time + return Confirm.ask( + "Do you agree to these terms and understand the restrictions?", + default=False + ) + def _get_answer(self, key: str, prompt_func, *args, **kwargs) -> Any: """ Get answer from answers file or prompt user @@ -1135,6 +1198,13 @@ class TrunkingWizard: )) console.print() + # Usage Agreement (REQUIRED - not overridable with answers file) + if not self._confirm_usage_agreement(): + console.print("\n[red]Usage agreement not accepted. Configuration wizard cancelled.[/red]") + return None + + console.print() + # System basics console.print("[bold]Step 1: System Configuration[/bold]\n")