Skip to content

Commit

Permalink
Merge pull request #11 from quexten/feature/libportal-autotype
Browse files Browse the repository at this point in the history
Implement libportal autotype
  • Loading branch information
quexten authored Dec 6, 2023
2 parents 93b4dcf + 9175197 commit cb3c40d
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 23 deletions.
16 changes: 12 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,16 +172,24 @@ And then just run the command as usual:
restic backup
```

### Autofill
### Autotype based Autofill
[goldwarden_autofill.webm](https://github.com/quexten/goldwarden/assets/11866552/6ac7cdc2-0cd7-42fd-9fd0-cfff26e2ceee)

The autofill feature is a bit experimental. It autotypes the password via uinput. This needs a keyboardlayout to map the letters to
You can bind this to a hotkey in your desktop environment (i.e i3/sway config file, Gnome custom shortcuts, etc).

#### XDG-RemoteDesktop-Portal

By default, the remote desktop portal is used. As long as your desktop environment handle this (KDE and Gnome do, wlroots does not yet)
this enables autotyping without having to modify permissions.
`goldwarden autofill`

#### (Legacy) Uinput
If your desktop environment does not implement the remotedesktop portal, your only other option is uinput based autotype. This requires your user
to have access to the input group to use uinput to autotype. This needs a keyboardlayout to map the letters to
keycodes. Currently supported are qwerty and dvorak.
`goldwarden autofill --layout qwerty`
`goldwarden autofill --layout dvorak`

You can bind this to a hotkey in your desktop environment (i.e i3/sway config file, Gnome custom shortcuts, etc).

### Login with device
Approving other devices works out of the box and is enabled by default. If the agent is unlocked, you will be prompted
to approve the device. If you want to log into goldwarden using another device, add the "--passwordless" parameter to the login command.
Expand Down
14 changes: 2 additions & 12 deletions autofill/autofill.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func ListLogins(client client.Client) ([]messages.DecryptedLoginCipher, error) {
}
}

func Run(layout string, useCopyPaste bool, client client.Client) {
func Run(layout string, client client.Client) {
logins, err := ListLogins(client)
if err != nil {
panic(err)
Expand All @@ -70,17 +70,7 @@ func Run(layout string, useCopyPaste bool, client client.Client) {
panic(err)
}

if useCopyPaste {
clipboard.WriteAll(string(login.Username))
autotype.Paste(layout)
autotype.TypeString("\t", layout)
clipboard.WriteAll(login.Password)
autotype.Paste(layout)
} else {
autotype.TypeString(string(login.Username), layout)
autotype.TypeString("\t", layout)
autotype.TypeString(string(login.Password), layout)
}
autotype.TypeString(string(login.Username)+"\t"+string(login.Password), layout)

clipboard.WriteAll(login.TwoFactorCode)
c <- true
Expand Down
70 changes: 70 additions & 0 deletions autofill/autotype/libportalautotype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//go:build linux && !uinput

package autotype

import (
"fmt"
"time"

"github.com/godbus/dbus/v5"
)

var globalID = 0

const autoTypeDelay = 1 * time.Millisecond

func TypeString(textToType string, layout string) {
bus, err := dbus.SessionBus()
if err != nil {
panic(err)
}

obj := bus.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop")
obj.AddMatchSignal("org.freedesktop.portal.Request", "Response")

globalID++
obj.Call("org.freedesktop.portal.RemoteDesktop.CreateSession", 0, map[string]dbus.Variant{
"session_handle_token": dbus.MakeVariant("u" + fmt.Sprint(globalID)),
})

signals := make(chan *dbus.Signal, 10)
bus.Signal(signals)

var state = 0
var sessionHandle dbus.ObjectPath

for {
select {
case message := <-signals:
fmt.Println("Message:", message)
if state == 0 {
result := message.Body[1].(map[string]dbus.Variant)
resultSessionHandle := result["session_handle"]
sessionHandle = dbus.ObjectPath(resultSessionHandle.String()[1 : len(resultSessionHandle.String())-1])
obj.Call("org.freedesktop.portal.RemoteDesktop.SelectDevices", 0, sessionHandle, map[string]dbus.Variant{})
state = 1
} else if state == 1 {
obj.Call("org.freedesktop.portal.RemoteDesktop.Start", 0, sessionHandle, "", map[string]dbus.Variant{})
state = 2
} else if state == 2 {
state = 3
time.Sleep(200 * time.Millisecond)
for _, char := range textToType {
if char == '\t' {
obj.Call("org.freedesktop.portal.RemoteDesktop.NotifyKeyboardKeycode", 0, sessionHandle, map[string]dbus.Variant{}, 15, uint32(1))
time.Sleep(autoTypeDelay)
obj.Call("org.freedesktop.portal.RemoteDesktop.NotifyKeyboardKeycode", 0, sessionHandle, map[string]dbus.Variant{}, 15, uint32(0))
time.Sleep(autoTypeDelay)
} else {
obj.Call("org.freedesktop.portal.RemoteDesktop.NotifyKeyboardKeysym", 0, sessionHandle, map[string]dbus.Variant{}, int32(char), uint32(1))
time.Sleep(autoTypeDelay)
obj.Call("org.freedesktop.portal.RemoteDesktop.NotifyKeyboardKeysym", 0, sessionHandle, map[string]dbus.Variant{}, int32(char), uint32(0))
time.Sleep(autoTypeDelay)
}
}
bus.Close()
return
}
}
}
}
6 changes: 1 addition & 5 deletions autofill/autotype/uinputautotype.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build linux
//go:build linux && uinput

package autotype

Expand All @@ -7,7 +7,3 @@ import "github.com/quexten/goldwarden/autofill/autotype/uinput"
func TypeString(text string, layout string) error {
return uinput.TypeString(text, layout)
}

func Paste(layout string) error {
return uinput.Paste(layout)
}
3 changes: 1 addition & 2 deletions cmd/autofill.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ var autofillCmd = &cobra.Command{
Long: `Autofill credentials`,
Run: func(cmd *cobra.Command, args []string) {
layout := cmd.Flag("layout").Value.String()
useCopyPaste, _ := cmd.Flags().GetBool("use-copy-paste")
autofill.Run(layout, useCopyPaste, commandClient)
autofill.Run(layout, commandClient)
},
}

Expand Down

0 comments on commit cb3c40d

Please sign in to comment.