GlitterWare / Passy

Offline password manager with cross-platform synchronization
https://glitterware.github.io/Passy/
GNU General Public License v3.0
144 stars 22 forks source link

[Suggestion]: standalone sync server (for arm,...) #81

Open umlaeute opened 11 months ago

umlaeute commented 11 months ago

Suggestion

i'm really interested in the "synchronization server", but...

i would like to run it on a dedicated armhf Debian box. afaics, the only way to install the server is via the Passy application itself, which is available on flatpak (for me)... but flatpak no longer does armhf builds. besides, that server would be headless, so I would be at a loss at extracting the binary anyhow.

so what are my options to get passy_cli to run this machine?

also, would it be a good idea to run the synchronization server on a publicly available server in the first place? (from a usability perspective, it would be great as i think it would allow me to synchronize devices that are in separate private networks (behind various layers of NATting; i don't know about the security perspective though - what are the dangers of exposing secrets via a public passy sync servers? and what if somebody exploited a weakness in the passy server to gain access to my publicly available box?)

Submission checklist

GleammerRay commented 11 months ago

Hello @umlaeute !

I believe that Dart supports ARM compilation and I've heard that there's been efforts to provide that for Flutter too, so building Passy CLI for ARM is probably possible.

However, I am afraid I cannot provide you with an ARM build of Passy at the moment. I will look into it and will notify you if I figure it out somehow, but I lack an ARM machine to build it.

Also, Argon2 libraries used in ARM builds would still be x86. I am able to add Argon2 ARM libraries for ARM builds but I would need to be able to build Passy on an ARM machine with graphical capabilities on it to implement and test that, which I do not have.

GleammerRay commented 11 months ago

Regarding the options you have at the moment, you might want to try emulating x86 on your ARM machine. There are various projects available on Github that may assist you in doing so, e.g. https://github.com/ptitSeb/box64. I can't guarantee that this will work on your machine but it's still something you can try in the meantime while I am finding a way to compile and test Passy ARM builds.

GleammerRay commented 11 months ago

@umlaeute , I apologize, I believe I missed a detail. You said that you have an armhf processor. I am afraid that it won't be possible to run Dart or Flutter programs on it, as Dart doesn't support 32bit architectures.

Edit 1:

You may want to consider getting an Oracle always-free server for Passy, they offer various x86_64 architectures along with some arm64 ones.

When it comes to Passy's server security, I have made sure that it doesn't let the user operate without proper authentication. Client makes sure that the server is legitimate through trust procedures. These trust procedures are carried out on both the server and the client to make it harder to steal trust information. The trust procedures are as follows:

  1. Client requests for the encrypted server trust file (which is saved on first connection to server, when the client adds it to its servers list).
  2. Client decrypts it and confirms that it is versioned newer than the local copy.
  3. Client updates local trusted connection data version and sends encrypted trusted connection data back to the server.
  4. Server updates trusted connection data version on its end.
  5. At this point, Passy client has made sure that it can trust the server.

The server only allows authenticated users to work with accounts, with authentication data being checked on each API call. If the authentication is missing, invalid or stale then the server will reject the API call, sending an error message instead. Server does not execute client code on any occasion and neither does the client. All connections are RSA encrypted which makes it impossible for any attacker to read the connection data.

umlaeute commented 11 months ago

I see (and thanks for the quick response)

Afaict, the clients connect via http, so: What are the options for running the sync server behind a proxy (eg apache2)? Possibly with some extra protection, like http-auth? (This is only for ensuring that nobody else can access the passy server in the first place)

GleammerRay commented 11 months ago

Passy does not utilize HTTP for any of its systems, it is using custom websocket protocols. It is using its own authentication system along with hybrid RSA encryption.

It should be possible to run Passy behind a proxy, there are no restrictions in place to prevent that.

GleammerRay commented 11 months ago

Hello @umlaeute !

It turns out that flutter apps can be built for armhf. I once again apologize for making a mistake, it turns out that only 32bit x86 building is not supported.

Great news: I have already managed to build Passy CLI for armhf! One thing is that it is missing Argon2 library, which means that, despite being unable to log in locally via the terminal interface, you should still be able to run a fully functional Passy server.

image

I am currently attempting to automate the building process with GitHub actions and will write back once again when a build succeeds. You are by far the most valuable issue contributor for Passy to date and I will do my best to provide the builds you require.

GleammerRay commented 11 months ago

Hello again @umlaeute .

You may now acquire the ARMv7 (armhf) build of Passy CLI from https://github.com/GlitterWare/Passy/releases/tag/v1.7.0.

For now Passy CLI does not offer an account creation command so first you will need to transfer your Passy data folder from your computer (default location is Documents/Passy) to your server. You may then verify that it's been transferred successfully by using passy_cli accounts list.

To install standalone server on your machine, use the install server command with Passy CLI. You may find more information on this command using passy_cli help ("Installation" section). Please tell me if you face any problems during the process.

GleammerRay commented 9 months ago

I am closing the issue for now and consider it resolved as I haven't received any responses for quite a while. Feel free to tell me if you face any problems and I hope that your data will forever remain safe.

umlaeute commented 9 months ago

sorry for not replying earlier.

truth is, i haven't been able to get the sync server to work on my arm machine (yet), but haven't had too much time to spend on the issue. i'll report back once i've made any progress (or failed to do so despite trying)

GleammerRay commented 9 months ago

Glad to hear for you! Feel free to inform me about any problems.

umlaeute commented 8 months ago

hmm.

today i've tried again, and this is how far i get:

my setup

the server is (as mentioned) an armv4 (odroidxu4):

$ uname -a
Linux myserver 4.14.222-odroidxu4 #1 SMP PREEMPT Mon Nov 22 12:13:27 UTC 2021 armv7l GNU/Linux

the server is running behind a NATting firewall, that forwards all traffic targetting my public IP (example.com) to the private IP (192.168.0.100).

install the server

$ ./passy-cli install server ~/passy-server 192.168.0.100 5592
[...]
$ cd ~/passy-server/
$ ./passy_cli
       ____                     
      |  _ \ __ _ ___ ___ _   _ 
      | |_) / _` / __/ __| | | |
      |  __/ (_| \__ \__ \ |_| |
      |_|   \__,_|___/___/\__, |
                          |___/ 

 Manage personal data on all platforms
   with military grade security. 🔒

  https://glitterware.github.io/Passy
 _____________________________________
|                                     |
| Welcome to Passy interactive shell! |
| 2024-02-20 19:40:15.134882Z UTC.    |
|                                     |
| Shell v2.0.0                        |
| Passy v1.7.0                        |
| Account data v2.4.0                 |
| Synchronization v2.1.0              |
|_____________________________________|

Type `help` for guidance.
Type `exit` to quit.

passy:hide:Failed to hide window:
Invalid argument(s): Failed to load dynamic library 'kernel32.dll': kernel32.dll: cannot open shared object file: No such file or directory
#0      _open (dart:ffi-patch/ffi_dynamic_library_patch.dart:11)
#1      new DynamicLibrary.open (dart:ffi-patch/ffi_dynamic_library_patch.dart:22)
#2      _kernel32 (package:win32/src/win32/kernel32.g.dart:22)
#3      _GetConsoleWindow (package:win32/src/win32/kernel32.g.dart)
#4      GetConsoleWindow (package:win32/src/win32/kernel32.g.dart)
#5      executeCommand (package:passy/passy_cli/bin/passy_cli.dart:850)
<asynchronous suspension>
#6      executeCommand (package:passy/passy_cli/bin/passy_cli.dart:798)
<asynchronous suspension>
#7      _autorun (package:passy/passy_cli/bin/passy_cli.dart:426)
<asynchronous suspension>
#8      load (package:passy/passy_cli/bin/passy_cli.dart:440)
<asynchronous suspension>

/tmp/passy_cli/bin/passy_cli/passy_cli_2024-02-20T20;40;15.153443/passy_cli
$

this doesn't look exactly promising (kernel32.dll, wtf? a backtrace??), however a process has been started and it is listening on the expected port (5592).

$ ps aux | grep passy_cli
umlaeute 18002 17.4  0.4  19996  8400 ?        Sl   20:40   0:20 /home/umlaeute/passy-server/passy_cli --no-autorun sleep 500 ; uninstall dir /tmp/passy_cli/bin/passy_cli/passy_cli_2024-02-20T20;40;15.153443 ; run /home/umlaeute/passy-server/autorun.pcli 2
$ lsof -n -p 18002 | grep LISTEN
dart:pass 18002 umlaeute    8u     IPv4 67152701      0t0      TCP 192.168.0.100:5592 (LISTEN)
dart:pass 18002 umlaeute    9u     IPv4 67152702      0t0      TCP 127.0.0.1:41943 (LISTEN)

connecting a device

well, this got me very lost at first (mostly still stumped by the backtrace on the server and no apparent feedback that it had successfully started). i ended up launching passy on my desktop and went to Settings->Synchronisation servers->Server setup which is a bit of a walkthrough.

anyhow, so I went back to Settings->Synchronisation servers->Connect to server add my public hostname (example.com) and port 5592 and hit Test connection.

I get a green :heavy_check_mark: . hooray.

so the next step is obviously to establish a proper connection:

  1. hit Connect to server
  2. this greets me with a Nickname can't be empty
    • so what is a nickname in this context? i don't remember having heard this word in the context of passy before. it's probably just some ad-hoc identification string so I can distringuish multiple connection servers.
  3. so fill in some arbitrary nickname (examplecom, as this is the connection to my example.com server) and hit Connect to server again.
  4. this gives me a Connecting popup that lasts for about 5 seconds and then goes away

i have no idea what state i'm currently in. did this succeed? did it fail? if the latter, it's probably because of my bogus nickname, try again with my username (umlaeute) again this gives me a Connecting popup that lasts for about 5 seconds and then goes away.

so what now? i have no idea. going back to Settings->Synchronisation servers->Synchronization logs, but there is nothing in there. the server (running in the background) doesn't give any hint on whether somebody connected, whether that was successful and what not.

at least my feeling tells me, that nothing is actually synched :disappointed:

possible improvements

improve the bootstrapping

the current way is really unnerving. i know you are trying to get a smooth experience for non-savy users, and that is a great goal. but for someone like me, who has been setting up and running servers for the last 20 years or so, the current scheme does not work well.

after much exoerimenting, it's obvious that all the server install and what not is really just copying the passy_cli itself to some other location and adds a autostart.pcli file that contains the default configuration. if i would have known this beforehand (without having to reverse-engineer the process) i might have just been able to issue these commands by hand (if had known which commands that were)

give feedback on the server

no detaching add the possibility to raise verbosity (e.g. receive connection; user 'foo' authenticated from 127.0.1.2;...

give feedback on the client

after seeing a popup that describes what the client is currently doing (Connecting...) I would really like to get an idea what worked and what did not work (Connection failed due to bamboozle)

documentation

well obviously. i'm bad at writing documentation myself. i hate it. but you really need some.

esp with a "military grade security" I as a user want to know how the system works and how I can use it.

if the "military grade security" echos my password in plaintext (accounts login <username> <password>) i get wobbly knees (it probably doesn't echo by itself; but so far the only way for me to test whether the client "works" is by manually logging in via passy_cli where i have to type a password that is now visible)

GleammerRay commented 8 months ago

Hello @umlaeute !

passy:hide:Failed to hide window:

It's weird that it doesn't occur on my GUI-less server but it's not a critical exception regardless. This is due to the hide window command failing to hide a GUI terminal window (because one probably doesn't exist). Ignore it for now, I'll try to replicate it later.

Nickname can't be empty

Nicknames are indeed arbitrary and are just for you to differentiate the servers. Most applications with custom client-server communication use this approach to server naming.

I have no idea what state i'm currently in

Hmm, that's odd. I didn't customize the timer on the Connecting... popup so it kind of just goes away without a reason if it stays on too long but thing is, it's not supposed to stay on that long anyway. Your Passy application is either meant to show an error popup or a successful connection popup.

Are you sure that you have transferred your Passy directory to your server device as ~/Documents/Passy (or a differently configured documents path) beforehand, as I have instructed you? You can check if it's installed correctly by running passy_cli accounts list - it should provide you with a list that includes your account name.

I will make sure to test the ARM server later again myself as well.

give feedback on the server / client

I will attempt adding more logging later, but Passy already generates verbose logs on each synchronization run as it is, so this is a very special case.

documentation

Passy CLI provides some documentation via the help command. I will consider adding more documentation later, but currently this is as far as it goes.

If you're talking about dedicated server documentation, I will most probably provide that in the foreseeable future. There's a need for more Passy CLI convenience setup commands as well to smooth the process (e.g. account creation, local server testing, etc.). At the moment I am indeed focusing on ease of use for basic users, but I hope to improve the convenience of traditional server setup later on, after I deal with the next release and the Play Store publishing process.

echos my password in plaintext

I believe that it will be possible to add an interactive login command for Passy CLI later on. I am also planning to develop Passy TUI as a separate project at a certain point which will be a convenient TUI wrapper for Passy CLI with pretty TUI colors and menus. I will improve on the Passy CLI feature set, but I do not want to make any unnecessary changes to any existing features and will keep it somewhat rudimentary.

I greatly appreciate your feedback and I hope that you'll stay to enjoy and help this project. Thank you!

umlaeute commented 8 months ago

Are you sure that you have transferred your Passy directory to your server device as ~/Documents/Passy (or a differently configured documents path) beforehand, as I have instructed you? You can check if it's installed correctly by running passy_cli accounts list - it should provide you with a list that includes your account name.

i did that and it did get a reasonable output.

GleammerRay commented 8 months ago

This is very odd, especially considering that the connection check succeeded. I will let you know if I find any way to reproduce and solve this problem.