An autotype utility for kpmenu
robotgo upstream accepted PRs: removing replacement
Egg beater missed one.

heads

tip
browse log

clone

read-only
https://hg.sr.ht/~ser/quasiauto
read/write
ssh://hg@hg.sr.ht/~ser/quasiauto

#Quasiauto

Build status File a bug here

Quasiauto performs autotyping and interactive autotyping for kpmenu. It's meant to do three things:

  1. As a trigger, it's designed to be run by a hotkey (set up in your window manager); it finds the title of the focused window and calls the kpmenu server process, passing it the window title.
  2. As an actor, it is called by the kpmenu server process with credentials from a Keepass entry matching the window title. It then either auto-types the information, or enters a quasi-automatic (hence the name) interactive mode.
  3. Using a patched robotgo, it can fetch the currently active window title, removing the need for [kpmenu](https://github.com/AlessioDP/kpmenu) to use xdotool on Linux.

Quasiauto started from a ticket to add autotype to kpmenu. The quasi-auto mode is an attempt to improve on autotype in a way that minimizes user interaction while making login data entry more robust than autotype, which is fragile in the face of unnecessarily involved Javascript login pages.

#Security

Ignoring the dependencies for Xorg interaction (robotgo), there is (relatively) little code and should be easy to audit, even for non-programmers. In particular, no network calls are made and this program should run when network jailed.

#Installation

Binaries can be downloaded here. Quasiauto can be compiled from source with either go install:

go install ser1.net/quasiauto

or by cloning and building yourself:

hg clone https://hg.sr.ht/~ser/quasiauto/
cd quasiauto
go build ./cmd/quasiauto

#Running

There's only one argument: -ms <millisecs>, which defines the amount of "lag" between simulated key presses. It is set to default at 50. All other data, it parses from STDIN.

The intended use is as a utility for kpmenu. The idea is that you install quasiauto and then bind a hotkey to call [kpmenu](https://github.com/AlessioDP/kpmenu) --autotype; kpmenu farms out the actual autotyping part to quasiauto. All in all, it would look like this:

  1. Install kpmenu; configure it as your KeePass client.
  2. Configure kpmenu to use quasiauto to identify the active window by adding this to ~/.config/kpmenu/config:
[executable]
CustomAutotypeWindowID="quasiauto -title"
  1. Bind a key in your window manager to call kpmenu; for example, in i3:
bindsym $mod+r exec /home/ser/.local/bin/kpmenu
bindsym $mod+t exec /home/ser/.local/bin/kpmenu --autotype

Now you can trigger autotyping by pressing MOD-t on a browser (or other) login window. This depends on having the correct window ID and key sequences set up in the KeePass DB, of course.

A way of testing this is using zenity. Say you have a sourcehut account, and a corresponding entry named Sourcehut in your KeePassDB. Run the following:

zenity --forms --add-entry "Username" --add-password "Password" --add-entry "TOTP" --title "Log in to Sourcehut"

Make sure the Username field is selected and press your MOD-t key, and if everything is configured correctly you should get autotyped credentials into the Zenity window.

quasiauto can autotype on behalf of any program that sends it data in the correct format.

#Limitations

VKEY is not implemented, as it's windows specific and I don't have access to a Windows computer.

I haven't found a way to ensure that no modifier keys are being held when autotype starts. Consequently, there's a risk that whatever hotkey trigger is set up might mean a meta key is still being held when typing starts. This is Not Good™, and avoiding this means you may have to insert a small delay (500ms) before executing the program. In my case, the various delays introduced by forking, parsing input, and so on is enough that I don't have a problem if I don't linger on the modifier; however, YMMV. I'll add a safety measure, if I can find a way to read the keyboard state and ensure it's clear in a platform-independent way.

#Development

Discussion of the feature is in a github ticket. The design is meant to

  1. Limit changes to kpmenu, and in particular, minimize added dependencies. Autotype requires UI interaction, and any UI library dependency -- and especially any cross-platform one -- has large overhead. Dependencies increase the code that must be reviewed for security, so this is an important consideration for kpmenu.
  2. Maintain the kpmenu security model, which rests on the fact that clients can not extract secret information from the server process. Secrets are available to only the server process or processes that it forks (e.g., xsel).

Quasiauto reads STDIN and expects (quasi-BNF):

sequence  ::= cmds "\n"
cmds      ::= cmds "{" cmd "}" | ""
cmd       ::= key | "TAB" | "ENTER" | "TOTP" | "DELAY" digits
digits    ::= [0-9]+
fields    ::= fields "\n" field | field
field     ::= key "\t" value
key       ::= [^\n\t]+
value     ::= [^n]+

For example:

{USERNAME}{TAB}{PASSWORD}{TAB}{TOTP}{ENTER}
Username	John B.
Password	BooTAY, BooTAY
OTP		1328765

#Metrics

         Coverage     Parse benchmark 	Exec benchmark
v0.2.0   94%          12734 		10801
v0.1.0   78%           8035