From d3846d5b04c153aba6f3ef72c3615fcfd0e3c174 Mon Sep 17 00:00:00 2001 From: usermaneGermane Date: Tue, 27 Oct 2026 23:00:22 +0200 Subject: [PATCH] MIT licence, neutral example addresses (1.4.2) Co-Authored-By: Claude Opus 5.5 --- LICENSE | 21 ++++++++++++++ README.md | 13 +++++++-- server/passman_setup.py | 6 ++-- server/version.py | 2 +- tests/test_server_setup.py | 58 +++++++++++++++++++------------------- 5 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..30d4b35 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 usermaneGermane + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 6e13817..796dfae 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,11 @@ number set to `0`: `192.168.0.3/24` means `192.168.0.0/24`. git clone --depth 1 https://github.com/usermaneGermane/PassMan-Server-Linux.git ~/PassMan-Server-Linux ``` +Or download `passman-server-linux-.tar.gz` from +[Releases](https://github.com/usermaneGermane/PassMan-Server-Linux/releases) +and unpack it; use that folder wherever these steps say +`~/PassMan-Server-Linux`. + This is only the source. The running service gets its own copy in step 2, so nothing you do in this folder later — pulling, switching branches, deleting it — touches the live server until you choose to update it. @@ -231,7 +236,7 @@ behind a router, on a VPN the server is not part of — needs its own rule. The setup's third question asks for those addresses, or give them directly: ```bash -sudo python3 /opt/passman/server/passman_setup.py setup --keep --allow-from 172.17.17.2 +sudo python3 /opt/passman/server/passman_setup.py setup --keep --allow-from 192.168.0.1 ``` Name one address or a network (`10.20.0.0/24`); repeat `--allow-from` or @@ -338,7 +343,7 @@ listens on whatever address the machine has. Three other things do: 1. **Firewall.** If the new address is on a different network, allow it and drop the old rule: ```bash - sudo ufw allow from 10.10.10.0/24 to any port 8787 proto tcp # the new network + sudo ufw allow from 192.168.0.0/24 to any port 8787 proto tcp # the new network sudo ufw delete allow from 192.168.1.0/24 to any port 8787 proto tcp ``` If you used step 4B instead, run the setup again and pick the new @@ -558,3 +563,7 @@ systems. Make a change to either in both repositories, so the two servers never drift apart. PassMan-Client-Windows and PassMan-Client-Linux each keep a copy of `passman_server.py` for their end-to-end sync tests; refresh those too. + +## License + +MIT — see [LICENSE](LICENSE). diff --git a/server/passman_setup.py b/server/passman_setup.py index 5e637fb..748bf26 100644 --- a/server/passman_setup.py +++ b/server/passman_setup.py @@ -14,7 +14,7 @@ and which port, writes them to sync.env, creates the token if there is none yet, and opens the port in the firewall for the networks it serves -- plus any other addresses you name, such as a PC on a network this machine is not -on (`--allow-from 172.17.17.2`): +on (`--allow-from 192.168.0.1`): - Linux: sync.env is /etc/passman/sync.env, which the systemd unit loads. The firewall rule is added when ufw is on; ufw is never switched on from @@ -184,7 +184,7 @@ def render_env(host, port, allow=()): def check_allow(text): """ - Extra addresses to let in, from "172.17.17.2, 10.20.0.0/24": a list of + Extra addresses to let in, from "192.168.0.1, 10.20.0.0/24": a list of addresses and networks, or a message. One address stays one address (no /32), so it matches a rule typed by hand. Everyone (/0) is refused: that is what the firewall is there to stop. @@ -285,7 +285,7 @@ def choose_port(ask, say, current): def choose_allow(ask, say, current): """Extra addresses; Enter keeps the current ones, - clears them.""" say("Let in any other addresses? For a PC on a network this machine is " - "not on, e.g. 172.17.17.2 or 10.20.0.0/24; comma-separated, - for " + "not on, e.g. 192.168.0.1 or 10.20.0.0/24; comma-separated, - for " "none.") shown = ",".join(current) or "none" while True: diff --git a/server/version.py b/server/version.py index 53d2c47..20242fa 100644 --- a/server/version.py +++ b/server/version.py @@ -7,4 +7,4 @@ in PassMan-Server-Windows, which has its own version. """ -__version__ = "1.4.1" +__version__ = "1.4.2" diff --git a/tests/test_server_setup.py b/tests/test_server_setup.py index 8c064f9..a4106d6 100644 --- a/tests/test_server_setup.py +++ b/tests/test_server_setup.py @@ -363,10 +363,10 @@ def allowed(tmp_path): @pytest.mark.parametrize("text, expected", [ - ("172.17.17.2", ["172.17.17.2"]), - (" 172.17.17.2 , 10.20.0.0/24 ", ["172.17.17.2", "10.20.0.0/24"]), + ("192.168.0.1", ["192.168.0.1"]), + (" 192.168.0.1 , 10.20.0.0/24 ", ["192.168.0.1", "10.20.0.0/24"]), ("10.20.0.7/24", ["10.20.0.0/24"]), - ("172.17.17.2/32", ["172.17.17.2"]), # matches a rule typed by hand + ("192.168.0.1/32", ["192.168.0.1"]), # matches a rule typed by hand ("1.2.3.4,1.2.3.4", ["1.2.3.4"]), ("-", []), ("none", []), ("", []), ]) @@ -382,9 +382,9 @@ def test_allow_from_refuses_everyone_and_nonsense(bad): def test_the_question_saves_extra_addresses(tmp_path): - out, _ = run_setup(tmp_path, answers=["", "", "172.17.17.2"]) - assert allowed(tmp_path) == "172.17.17.2" - assert "Also let in: 172.17.17.2" in out + out, _ = run_setup(tmp_path, answers=["", "", "192.168.0.1"]) + assert allowed(tmp_path) == "192.168.0.1" + assert "Also let in: 192.168.0.1" in out # Host and port are still what the server reads. env = passman_setup.read_env(tmp_path / "sync.env") assert listen(env) == ("0.0.0.0", 8787) @@ -397,19 +397,19 @@ def test_a_bad_extra_address_is_asked_again(tmp_path): def test_enter_keeps_the_extra_addresses_and_dash_clears_them(tmp_path): - run_setup(tmp_path, answers=["", "", "172.17.17.2"]) + run_setup(tmp_path, answers=["", "", "192.168.0.1"]) run_setup(tmp_path, answers=["", "", ""]) - assert allowed(tmp_path) == "172.17.17.2" + assert allowed(tmp_path) == "192.168.0.1" run_setup(tmp_path, answers=["", "", "-"]) assert allowed(tmp_path) is None def test_with_ufw_on_the_extra_address_gets_its_rule(tmp_path): - out, system = run_setup(tmp_path, answers=["2", "9443", "172.17.17.2"], + out, system = run_setup(tmp_path, answers=["2", "9443", "192.168.0.1"], system=FakeSystem(ufw=True)) assert system.ran("ufw allow from 192.168.1.0/24 to any port 9443 " "proto tcp") - assert system.ran("ufw allow from 172.17.17.2 to any port 9443 proto tcp") + assert system.ran("ufw allow from 192.168.0.1 to any port 9443 proto tcp") def test_allow_from_alone_adds_the_rule_without_a_restart(tmp_path): @@ -417,24 +417,24 @@ def test_allow_from_alone_adds_the_rule_without_a_restart(tmp_path): another network needs in. Only the firewall changes.""" run_setup(tmp_path, argv=["setup", "--host", "0.0.0.0", "--port", "9443"]) out, system = run_setup( - tmp_path, argv=["setup", "--keep", "--allow-from", "172.17.17.2"], + tmp_path, argv=["setup", "--keep", "--allow-from", "192.168.0.1"], system=FakeSystem(ufw=True, active=True)) - assert system.ran("ufw allow from 172.17.17.2 to any port 9443 proto tcp") + assert system.ran("ufw allow from 192.168.0.1 to any port 9443 proto tcp") assert not system.ran("ufw delete") assert not system.restarted - assert allowed(tmp_path) == "172.17.17.2" + assert allowed(tmp_path) == "192.168.0.1" def test_allow_from_repeats_and_none_clears(tmp_path): run_setup(tmp_path, argv=["setup", "--host", "0.0.0.0", "--port", "9443", - "--allow-from", "172.17.17.2", + "--allow-from", "192.168.0.1", "--allow-from", "10.20.0.0/24"]) - assert allowed(tmp_path) == "172.17.17.2,10.20.0.0/24" + assert allowed(tmp_path) == "192.168.0.1,10.20.0.0/24" _, system = run_setup(tmp_path, argv=["setup", "--keep", "--allow-from", "none"], system=FakeSystem(ufw=True)) assert allowed(tmp_path) is None - assert system.ran("ufw delete allow from 172.17.17.2 to any port 9443") + assert system.ran("ufw delete allow from 192.168.0.1 to any port 9443") assert system.ran("ufw delete allow from 10.20.0.0/24 to any port 9443") @@ -447,20 +447,20 @@ def test_a_bad_allow_from_stops_without_writing(tmp_path): def test_flags_and_keep_leave_the_extra_addresses_as_they_are(tmp_path): - run_setup(tmp_path, answers=["", "", "172.17.17.2"]) + run_setup(tmp_path, answers=["", "", "192.168.0.1"]) run_setup(tmp_path, argv=["setup", "--keep", "--port", "9000"]) - assert allowed(tmp_path) == "172.17.17.2" + assert allowed(tmp_path) == "192.168.0.1" run_setup(tmp_path, argv=["setup", "--keep"]) - assert allowed(tmp_path) == "172.17.17.2" + assert allowed(tmp_path) == "192.168.0.1" def test_a_new_port_moves_the_extra_rule_too(tmp_path): - run_setup(tmp_path, answers=["2", "", "172.17.17.2"], + run_setup(tmp_path, answers=["2", "", "192.168.0.1"], system=FakeSystem(ufw=True)) _, system = run_setup(tmp_path, argv=["setup", "--keep", "--port", "9443"], system=FakeSystem(ufw=True)) - assert system.ran("ufw delete allow from 172.17.17.2 to any port 8787") - assert system.ran("ufw allow from 172.17.17.2 to any port 9443") + assert system.ran("ufw delete allow from 192.168.0.1 to any port 8787") + assert system.ran("ufw allow from 192.168.0.1 to any port 9443") def test_this_machine_only_is_not_asked_and_opens_nothing(tmp_path): @@ -470,23 +470,23 @@ def test_this_machine_only_is_not_asked_and_opens_nothing(tmp_path): def test_with_ufw_off_the_extra_rule_is_printed(tmp_path): - out, system = run_setup(tmp_path, answers=["", "", "172.17.17.2"]) - assert "sudo ufw allow from 172.17.17.2 to any port 8787" in out + out, system = run_setup(tmp_path, answers=["", "", "192.168.0.1"]) + assert "sudo ufw allow from 192.168.0.1 to any port 8787" in out assert not system.ran("ufw allow") def test_windows_extra_addresses_join_the_one_rule(tmp_path): - out, system = win_setup(tmp_path, answers=["", "9443", "172.17.17.2"]) + out, system = win_setup(tmp_path, answers=["", "9443", "192.168.0.1"]) [rule] = system.ran("New-NetFirewallRule") - assert "-RemoteAddress 'LocalSubnet','172.17.17.2'" in rule - assert "and 172.17.17.2" in out + assert "-RemoteAddress 'LocalSubnet','192.168.0.1'" in rule + assert "and 192.168.0.1" in out def test_windows_upgrade_keeps_the_extra_addresses(tmp_path): - win_setup(tmp_path, answers=["", "", "172.17.17.2"]) + win_setup(tmp_path, answers=["", "", "192.168.0.1"]) _, system = win_setup(tmp_path, argv=["setup", "--keep"]) [rule] = system.ran("New-NetFirewallRule") - assert "'172.17.17.2'" in rule + assert "'192.168.0.1'" in rule # --- Windows ---------------------------------------------------------------