mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-29 13:26:38 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3905dc6e41 | ||
|
|
7c577b5778 | ||
|
|
aa10016f77 | ||
|
|
a39952489a | ||
|
|
b9175d7ff3 |
+13
-8
@@ -14,9 +14,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// LibmuttonInit creates the libmutton config structure based on user input.
|
// LibmuttonInit creates the libmutton config structure based on user input.
|
||||||
// rcwPassphrase and clientSpecificIniData can be left blank if not needed.
|
// rcwPassword and clientSpecificIniData can be left blank if not needed.
|
||||||
func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][3]string, rcwPassphrase []byte, preserveOldConfigDir bool) error {
|
func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][3]string, rcwPassword []byte, preserveOldConfigDir bool, forceOfflineMode bool) error {
|
||||||
r := strings.ToLower(inputCB("Configure SSH settings (for synchronization)? (Y/n)"))
|
var r string
|
||||||
|
if !forceOfflineMode {
|
||||||
|
r = strings.ToLower(inputCB("Configure SSH settings (for synchronization)? (Y/n)"))
|
||||||
|
} else {
|
||||||
|
r = "n"
|
||||||
|
}
|
||||||
if len(r) > 0 && r[0] == 'n' {
|
if len(r) > 0 && r[0] == 'n' {
|
||||||
// initialize libmutton directories
|
// initialize libmutton directories
|
||||||
_, err := global.DirInit(preserveOldConfigDir)
|
_, err := global.DirInit(preserveOldConfigDir)
|
||||||
@@ -35,7 +40,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][
|
|||||||
} else {
|
} else {
|
||||||
// ensure ssh key file exists (and is a file)
|
// ensure ssh key file exists (and is a file)
|
||||||
fallbackSSHKey := back.Home + global.PathSeparator + ".ssh" + global.PathSeparator + "id_ed25519"
|
fallbackSSHKey := back.Home + global.PathSeparator + ".ssh" + global.PathSeparator + "id_ed25519"
|
||||||
sshKeyPath := cmp.Or(back.ExpandPathWithHome(inputCB(back.AnsiBold+"Note:"+back.AnsiReset+" Only key-based authentication is supported (keys may optionally be passphrase-protected).\n The remote server must already be in your ~"+global.PathSeparator+".ssh"+global.PathSeparator+"known_hosts file.\n\nSSH private identity file path (falls back to \""+fallbackSSHKey+"\"):")), fallbackSSHKey)
|
sshKeyPath := cmp.Or(back.ExpandPathWithHome(inputCB(back.AnsiBold+"Note:"+back.AnsiReset+" Only key-based authentication is supported (keys may optionally be password-protected).\n The remote server must already be in your ~"+global.PathSeparator+".ssh"+global.PathSeparator+"known_hosts file.\n\nSSH private identity file path (falls back to \""+fallbackSSHKey+"\"):")), fallbackSSHKey)
|
||||||
_, err := back.TargetIsFile(sshKeyPath, true)
|
_, err := back.TargetIsFile(sshKeyPath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to find SSH identity file: " + err.Error())
|
return errors.New("unable to find SSH identity file: " + err.Error())
|
||||||
@@ -84,8 +89,8 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// generate rcw sanity check file (if requested)
|
// generate rcw sanity check file (if requested)
|
||||||
if len(rcwPassphrase) > 0 {
|
if len(rcwPassword) > 0 {
|
||||||
err := RCWSanityCheckGen(rcwPassphrase)
|
err := RCWSanityCheckGen(rcwPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -94,8 +99,8 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RCWSanityCheckGen generates the RCW sanity check file for libmutton.
|
// RCWSanityCheckGen generates the RCW sanity check file for libmutton.
|
||||||
func RCWSanityCheckGen(passphrase []byte) error {
|
func RCWSanityCheckGen(password []byte) error {
|
||||||
err := wrappers.GenSanityCheck(global.ConfigDir+global.PathSeparator+"sanity.rcw", passphrase)
|
err := wrappers.GenSanityCheck(global.ConfigDir+global.PathSeparator+"sanity.rcw", password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to generate sanity check file: " + err.Error())
|
return errors.New("unable to generate sanity check file: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ func WriteEntry(targetLocation string, decBytes []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EntryRefresh re-encrypts all libmutton entries with a new passphrase
|
// EntryRefresh re-encrypts all libmutton entries with a new password
|
||||||
// and optimizes each entry to ensure they are as slim as possible.
|
// and optimizes each entry to ensure they are as slim as possible.
|
||||||
// This includes stripping trailing whitespace/newlines/carriage returns
|
// This includes stripping trailing whitespace/newlines/carriage returns
|
||||||
// from each field and running each note through ClampTrailingWhitespace
|
// from each field and running each note through ClampTrailingWhitespace
|
||||||
// to ensure each note line is optimized as possible without breaking
|
// to ensure each note line is optimized as possible without breaking
|
||||||
// Markdown formatting.
|
// Markdown formatting.
|
||||||
// Be sure to verify passphrases before using as input for this function!!
|
// Be sure to verify passwords before using as input for this function!!
|
||||||
func EntryRefresh(oldRCWPassphrase, newRCWPassphrase []byte, removeOldDir bool) error {
|
func EntryRefresh(oldRCWPassword, newRCWPassword []byte, removeOldDir bool) error {
|
||||||
// ensure global.EntryRoot+"-new" and global.EntryRoot-"old" do not exist
|
// ensure global.EntryRoot+"-new" and global.EntryRoot-"old" do not exist
|
||||||
dirEnds := []string{"-new", "-old"}
|
dirEnds := []string{"-new", "-old"}
|
||||||
for i, dirEnd := range dirEnds {
|
for i, dirEnd := range dirEnds {
|
||||||
@@ -63,7 +63,7 @@ func EntryRefresh(oldRCWPassphrase, newRCWPassphrase []byte, removeOldDir bool)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to open \"" + targetLocation + "\" for decryption: " + err.Error())
|
return errors.New("unable to open \"" + targetLocation + "\" for decryption: " + err.Error())
|
||||||
}
|
}
|
||||||
decBytes, err := wrappers.Decrypt(encBytes, oldRCWPassphrase)
|
decBytes, err := wrappers.Decrypt(encBytes, oldRCWPassword)
|
||||||
decryptedEntry := strings.Split(string(decBytes), "\n")
|
decryptedEntry := strings.Split(string(decBytes), "\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -91,8 +91,8 @@ func EntryRefresh(oldRCWPassphrase, newRCWPassphrase []byte, removeOldDir bool)
|
|||||||
decryptedEntry = append(fieldsMain, fieldsNote...)
|
decryptedEntry = append(fieldsMain, fieldsNote...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-encrypt the entry with the new passphrase
|
// re-encrypt the entry with the new password
|
||||||
encBytes = wrappers.Encrypt([]byte(strings.Join(decryptedEntry, "\n")), newRCWPassphrase)
|
encBytes = wrappers.Encrypt([]byte(strings.Join(decryptedEntry, "\n")), newRCWPassword)
|
||||||
|
|
||||||
// write the entry to the new directory
|
// write the entry to the new directory
|
||||||
err = os.WriteFile(global.EntryRoot+"-new"+strings.ReplaceAll(entryName, "/", global.PathSeparator), encBytes, 0600)
|
err = os.WriteFile(global.EntryRoot+"-new"+strings.ReplaceAll(entryName, "/", global.PathSeparator), encBytes, 0600)
|
||||||
@@ -101,7 +101,7 @@ func EntryRefresh(oldRCWPassphrase, newRCWPassphrase []byte, removeOldDir bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate new sanity check file
|
// generate new sanity check file
|
||||||
err = RCWSanityCheckGen(newRCWPassphrase)
|
err = RCWSanityCheckGen(newRCWPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-21
@@ -14,15 +14,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var Daemonize = true
|
var Daemonize = true
|
||||||
var RetryPassphrase = true
|
var RetryPassword = true
|
||||||
|
|
||||||
// RCWDArgument reads the passphrase from stdin and caches it via an RCW daemon.
|
// RCWDArgument reads the password from stdin and caches it via an RCW daemon.
|
||||||
func RCWDArgument() {
|
func RCWDArgument() {
|
||||||
passphrase := back.ReadFromStdin()
|
password := back.ReadFromStdin()
|
||||||
if passphrase == "" {
|
if password == "" {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
daemon.Start([]byte(passphrase))
|
daemon.Start([]byte(password))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptFileToSlice decrypts an RCW wrapped file and returns the contents as a slice of (trimmed) strings.
|
// DecryptFileToSlice decrypts an RCW wrapped file and returns the contents as a slice of (trimmed) strings.
|
||||||
@@ -34,14 +34,14 @@ func DecryptFileToSlice(targetLocation string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decrypt data using RCW daemon
|
// decrypt data using RCW daemon
|
||||||
passphrase := launchRCWDProcess()
|
password := launchRCWDProcess()
|
||||||
if passphrase == nil {
|
if password == nil {
|
||||||
// if daemon is already running, use it to decrypt the data
|
// if daemon is already running, use it to decrypt the data
|
||||||
return strings.Split(string(daemon.GetDec(encBytes)), "\n"), nil
|
return strings.Split(string(daemon.GetDec(encBytes)), "\n"), nil
|
||||||
}
|
}
|
||||||
// if the daemon is not already running, use wrappers.Decrypt
|
// if the daemon is not already running, use wrappers.Decrypt
|
||||||
// directly to avoid waiting for socket file creation
|
// directly to avoid waiting for socket file creation
|
||||||
decBytes, err := wrappers.Decrypt(encBytes, passphrase)
|
decBytes, err := wrappers.Decrypt(encBytes, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("unable to decrypt \"" + targetLocation + "\": " + err.Error())
|
return nil, errors.New("unable to decrypt \"" + targetLocation + "\": " + err.Error())
|
||||||
}
|
}
|
||||||
@@ -50,43 +50,43 @@ func DecryptFileToSlice(targetLocation string) ([]string, error) {
|
|||||||
|
|
||||||
// EncryptBytes encrypts a byte slice using RCW and returns the encrypted data.
|
// EncryptBytes encrypts a byte slice using RCW and returns the encrypted data.
|
||||||
func EncryptBytes(decBytes []byte) []byte {
|
func EncryptBytes(decBytes []byte) []byte {
|
||||||
passphrase := launchRCWDProcess()
|
password := launchRCWDProcess()
|
||||||
if passphrase == nil {
|
if password == nil {
|
||||||
// if daemon is already running, use it to encrypt the data
|
// if daemon is already running, use it to encrypt the data
|
||||||
return daemon.GetEnc(decBytes)
|
return daemon.GetEnc(decBytes)
|
||||||
}
|
}
|
||||||
// if the daemon is not already running, use wrappers.Encrypt
|
// if the daemon is not already running, use wrappers.Encrypt
|
||||||
// directly to avoid waiting for socket file creation
|
// directly to avoid waiting for socket file creation
|
||||||
return wrappers.Encrypt(decBytes, passphrase)
|
return wrappers.Encrypt(decBytes, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
// launchRCWDProcess launches an RCW daemon to cache a passphrase.
|
// launchRCWDProcess launches an RCW daemon to cache a password.
|
||||||
// If the daemon is not already running OR if not running in daemonize mode,
|
// If the daemon is not already running OR if not running in daemonize mode,
|
||||||
// it collects and returns the passphrase (otherwise returns nil).
|
// it collects and returns the password (otherwise returns nil).
|
||||||
func launchRCWDProcess() []byte {
|
func launchRCWDProcess() []byte {
|
||||||
if Daemonize && daemon.IsOpen() {
|
if Daemonize && daemon.IsOpen() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var passphrase []byte
|
var password []byte
|
||||||
if RetryPassphrase {
|
if RetryPassword {
|
||||||
for {
|
for {
|
||||||
passphrase = global.GetPassphrase("RCW Passphrase:")
|
password = global.GetPassword("RCW Password:")
|
||||||
err := wrappers.RunSanityCheck(global.ConfigDir+global.PathSeparator+"sanity.rcw", passphrase)
|
err := wrappers.RunSanityCheck(global.ConfigDir+global.PathSeparator+"sanity.rcw", password)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fmt.Println(back.AnsiError + "Incorrect passphrase" + back.AnsiReset)
|
fmt.Println(back.AnsiError + "Incorrect password" + back.AnsiReset)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// in this mode, it is up to the client to perform the sanity check
|
// in this mode, it is up to the client to perform the sanity check
|
||||||
passphrase = global.GetPassphrase("RCW Passphrase:")
|
password = global.GetPassword("RCW Password:")
|
||||||
}
|
}
|
||||||
|
|
||||||
if Daemonize {
|
if Daemonize {
|
||||||
cmd := exec.Command(os.Args[0], "startrcwd")
|
cmd := exec.Command(os.Args[0], "startrcwd")
|
||||||
_ = back.WriteToStdin(cmd, string(passphrase))
|
_ = back.WriteToStdin(cmd, string(password))
|
||||||
_ = cmd.Start()
|
_ = cmd.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
return passphrase
|
return password
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
**libmutton v0.4.1**
|
||||||
|
October 26, 2025
|
||||||
|
|
||||||
|
This is a dependency bump release with only minor changes for developers.
|
||||||
|
|
||||||
|
## Breaking (for developers)
|
||||||
|
- (b9175d7ff3bea3bc703c20468defebcb1ac7e412) Standardized on "password" rather than a mix of "passphrase"/"password"
|
||||||
|
- Some function names changed as a result
|
||||||
|
- (aa10016f77b0be66ab75279df967f5d080d2b826) Developers using `LibmuttonInit` can now force clients into offline mode programmatically
|
||||||
|
- This means `LibmuttonInit` now requires an extra parameter
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- Bumped (direct/replaced)
|
||||||
|
- Go: v1.24.6 => v1.25.3
|
||||||
|
- github.com/pkg/sftp: v1.13.9 => v1.13.10
|
||||||
|
- golang.org/x/crypto: v0.41.0 => v0.43.0
|
||||||
|
- github.com/rwinkhart/sys: v0.35.0 => v0.37.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
**libmutton v0.4.0**
|
**libmutton v0.4.0**
|
||||||
August 17, 2025
|
August 17, 2025
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -3,11 +3,11 @@ package global
|
|||||||
type ByteInputFetcher func(prompt string) []byte
|
type ByteInputFetcher func(prompt string) []byte
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GetPassphrase ByteInputFetcher // Clients should set this to a function that fetches hidden input from the user
|
GetPassword ByteInputFetcher // Clients should set this to a function that fetches hidden input from the user
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LibmuttonVersion = "0.4.0" // Untagged releases feature a letter suffix corresponding to the eventual release version, e.g "0.2.A" -> "0.2.0", "0.2.B" -> "0.2.1"
|
LibmuttonVersion = "0.4.1" // Untagged releases feature a letter suffix corresponding to the eventual release version, e.g "0.2.A" -> "0.2.0", "0.2.B" -> "0.2.1"
|
||||||
|
|
||||||
FSSpace = "\u259d" // ▝ Space/list separator
|
FSSpace = "\u259d" // ▝ Space/list separator
|
||||||
FSPath = "\u259e" // ▞ Path separator
|
FSPath = "\u259e" // ▞ Path separator
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
module github.com/rwinkhart/libmutton
|
module github.com/rwinkhart/libmutton
|
||||||
|
|
||||||
go 1.24.6
|
go 1.25.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/pkg/sftp v1.13.9
|
github.com/pkg/sftp v1.13.10
|
||||||
github.com/pquerna/otp v1.5.0
|
github.com/pquerna/otp v1.5.0
|
||||||
github.com/rwinkhart/go-boilerplate v0.1.0
|
github.com/rwinkhart/go-boilerplate v0.1.0
|
||||||
github.com/rwinkhart/rcw v0.2.2
|
github.com/rwinkhart/rcw v0.2.2
|
||||||
golang.design/x/clipboard v0.7.1 // only for mobile builds
|
golang.design/x/clipboard v0.7.1 // only for mobile builds
|
||||||
golang.org/x/crypto v0.41.0
|
golang.org/x/crypto v0.43.0
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,12 +17,12 @@ require (
|
|||||||
github.com/boombuler/barcode v1.1.0 // indirect
|
github.com/boombuler/barcode v1.1.0 // indirect
|
||||||
github.com/kr/fs v0.1.0 // indirect
|
github.com/kr/fs v0.1.0 // indirect
|
||||||
github.com/rwinkhart/peercred-mini v0.1.1 // indirect
|
github.com/rwinkhart/peercred-mini v0.1.1 // indirect
|
||||||
golang.org/x/exp/shiny v0.0.0-20250813145105-42675adae3e6 // indirect; only for mobile builds
|
golang.org/x/exp/shiny v0.0.0-20251017212417-90e834f514db // indirect; only for mobile builds
|
||||||
golang.org/x/image v0.30.0 // indirect; only for mobile builds
|
golang.org/x/image v0.32.0 // indirect; only for mobile builds
|
||||||
golang.org/x/mobile v0.0.0-20250813145510-f12310a0cfd9 // indirect; only for mobile builds
|
golang.org/x/mobile v0.0.0-20251021151156-188f512ec823 // indirect; only for mobile builds
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
golang.org/x/sys v0.37.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace golang.org/x/sys => github.com/rwinkhart/sys v0.35.0
|
replace golang.org/x/sys => github.com/rwinkhart/sys v0.37.0
|
||||||
|
|
||||||
replace github.com/Microsoft/go-winio => github.com/rwinkhart/go-winio-easy-pipe-handles v0.0.0-20250407031321-96994a0e8410
|
replace github.com/Microsoft/go-winio => github.com/rwinkhart/go-winio-easy-pipe-handles v0.0.0-20250407031321-96994a0e8410
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ github.com/boombuler/barcode v1.1.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw=
|
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
|
||||||
github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA=
|
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
|
||||||
@@ -21,81 +20,25 @@ github.com/rwinkhart/peercred-mini v0.1.1 h1:hDoqSEwynJN4w8OWlZNSQAjAum/ocP3AYF7
|
|||||||
github.com/rwinkhart/peercred-mini v0.1.1/go.mod h1:dstv+IydIklCnffwAZgD2AWqkGe0mETn3lLtqJjYAeI=
|
github.com/rwinkhart/peercred-mini v0.1.1/go.mod h1:dstv+IydIklCnffwAZgD2AWqkGe0mETn3lLtqJjYAeI=
|
||||||
github.com/rwinkhart/rcw v0.2.2 h1:bTUi3BLjrcoibi5YDlzeiVKo608EmGetymXbJVM3oYE=
|
github.com/rwinkhart/rcw v0.2.2 h1:bTUi3BLjrcoibi5YDlzeiVKo608EmGetymXbJVM3oYE=
|
||||||
github.com/rwinkhart/rcw v0.2.2/go.mod h1:lhTErVEG3klKVJkcoHuTw5pDHiS3Irlj7Z03IshHh7M=
|
github.com/rwinkhart/rcw v0.2.2/go.mod h1:lhTErVEG3klKVJkcoHuTw5pDHiS3Irlj7Z03IshHh7M=
|
||||||
github.com/rwinkhart/sys v0.35.0 h1:6ZikETjyuv9ndnSEnXQmp/M3lxyCHWoHAm3lGzy0pnE=
|
github.com/rwinkhart/sys v0.37.0 h1:fX7Zv1ndDoUI4Mi2ABy/sqlxNRYQALVWvYSXglPRVBc=
|
||||||
github.com/rwinkhart/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
github.com/rwinkhart/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
golang.design/x/clipboard v0.7.1 h1:OEG3CmcYRBNnRwpDp7+uWLiZi3hrMRJpE9JkkkYtz2c=
|
golang.design/x/clipboard v0.7.1 h1:OEG3CmcYRBNnRwpDp7+uWLiZi3hrMRJpE9JkkkYtz2c=
|
||||||
golang.design/x/clipboard v0.7.1/go.mod h1:i5SiIqj0wLFw9P/1D7vfILFK0KHMk7ydE72HRrUIgkg=
|
golang.design/x/clipboard v0.7.1/go.mod h1:i5SiIqj0wLFw9P/1D7vfILFK0KHMk7ydE72HRrUIgkg=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/exp/shiny v0.0.0-20251017212417-90e834f514db h1:NmsmaSkEAq6A8r0Q78WxD0IygJNCs6J3uYDgNuPkXYM=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/exp/shiny v0.0.0-20251017212417-90e834f514db/go.mod h1:QMAAUorQ8fzCK0C6mr4X4XV9BEp7Al6+jlejJvfYKw4=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc=
|
||||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
golang.org/x/mobile v0.0.0-20251021151156-188f512ec823 h1:M0DtBf/UvJoTH+tk6tgHT2NVxNEJCYhVu1g/xeD+GEk=
|
||||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
golang.org/x/mobile v0.0.0-20251021151156-188f512ec823/go.mod h1:3QSlP0AtP6HPTLbsxfgfefGN76jpIB9yBsMqB8UY37I=
|
||||||
golang.org/x/exp/shiny v0.0.0-20250813145105-42675adae3e6 h1:UmlTtCyqnD3jxsGe973Y9uZydewwYUboXPux+RCcKQU=
|
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||||
golang.org/x/exp/shiny v0.0.0-20250813145105-42675adae3e6/go.mod h1:QnFR+evpZFrYgSiu+d/Rn6g/6bNqLQTp+rzKaVpFoeI=
|
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||||
golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4=
|
|
||||||
golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c=
|
|
||||||
golang.org/x/mobile v0.0.0-20250813145510-f12310a0cfd9 h1:tf0OY/FXi1sPkoNVKP4w+GStqIfqbFUqDoDDm4B+iCg=
|
|
||||||
golang.org/x/mobile v0.0.0-20250813145510-f12310a0cfd9/go.mod h1:wNiuiJfmmgv45sw8EHpNeVWqpxLeEwQ8bkUIhuOYUh8=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
|
||||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
|
||||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
|
||||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|
||||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
mkdir -p ./1output
|
mkdir -p ./1output
|
||||||
cd ..
|
cd ..
|
||||||
GOOS=linux CGO_ENABLED=0 GOAMD64=v2 go build -o ./packaging/1output/libmuttonserver-linux-x86_64_v2 -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
GOOS=linux CGO_ENABLED=0 GOAMD64=v2 go build -o ./packaging/1output/libmuttonserver-linux-x86_64_v2 -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
||||||
GOOS=linux GOARCH=arm64 GOARM64=v8.0 CGO_ENABLED=0 go build -o ./packaging/1output/libmuttonserver-linux-arm64v8.0.exe -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
GOOS=linux GOARCH=arm64 GOARM64=v8.0 CGO_ENABLED=0 go build -o ./packaging/1output/libmuttonserver-linux-arm64v8.0 -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
||||||
GOOS=linux GOARCH=arm64 GOARM64=v8.7 CGO_ENABLED=0 go build -o ./packaging/1output/libmuttonserver-linux-arm64v8.7.exe -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
GOOS=linux GOARCH=arm64 GOARM64=v8.7 CGO_ENABLED=0 go build -o ./packaging/1output/libmuttonserver-linux-arm64v8.7 -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
||||||
GOOS=windows CGO_ENABLED=0 GOAMD64=v2 go build -o ./packaging/1output/libmuttonserver-windows-x86_64_v2.exe -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
GOOS=windows CGO_ENABLED=0 GOAMD64=v2 go build -o ./packaging/1output/libmuttonserver-windows-x86_64_v2.exe -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
||||||
GOOS=windows GOARCH=arm64 GOARM64=v8.7 CGO_ENABLED=0 go build -o ./packaging/1output/libmuttonserver-windows-arm64v8.7.exe -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
GOOS=windows GOARCH=arm64 GOARM64=v8.7 CGO_ENABLED=0 go build -o ./packaging/1output/libmuttonserver-windows-arm64v8.7.exe -ldflags="-s -w" -trimpath ./libmuttonserver.go
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
// offlineMode (whether the client is in offline mode).
|
// offlineMode (whether the client is in offline mode).
|
||||||
// sshIsWindows (whether the remote server is running Windows),
|
// sshIsWindows (whether the remote server is running Windows),
|
||||||
// sshEntryRoot (the root directory for entries on the remote server),
|
// sshEntryRoot (the root directory for entries on the remote server),
|
||||||
// Only supports key-based authentication (passphrases are supported for CLI-based implementations).
|
// Only supports key-based authentication (passwords are supported for CLI-based implementations).
|
||||||
func GetSSHClient() (*ssh.Client, bool, bool, string, error) {
|
func GetSSHClient() (*ssh.Client, bool, bool, string, error) {
|
||||||
// get SSH config info
|
// get SSH config info
|
||||||
sshUserConfig, err := cfg.ParseConfig([][2]string{{"LIBMUTTON", "offlineMode"}, {"LIBMUTTON", "sshUser"}, {"LIBMUTTON", "sshIP"}, {"LIBMUTTON", "sshPort"}, {"LIBMUTTON", "sshKey"}, {"LIBMUTTON", "sshKeyProtected"}, {"LIBMUTTON", "sshEntryRoot"}, {"LIBMUTTON", "sshIsWindows"}})
|
sshUserConfig, err := cfg.ParseConfig([][2]string{{"LIBMUTTON", "offlineMode"}, {"LIBMUTTON", "sshUser"}, {"LIBMUTTON", "sshIP"}, {"LIBMUTTON", "sshPort"}, {"LIBMUTTON", "sshKey"}, {"LIBMUTTON", "sshKeyProtected"}, {"LIBMUTTON", "sshEntryRoot"}, {"LIBMUTTON", "sshIsWindows"}})
|
||||||
@@ -70,7 +70,7 @@ func GetSSHClient() (*ssh.Client, bool, bool, string, error) {
|
|||||||
if keyFileProtected != "true" {
|
if keyFileProtected != "true" {
|
||||||
parsedKey, err = ssh.ParsePrivateKey(key)
|
parsedKey, err = ssh.ParsePrivateKey(key)
|
||||||
} else {
|
} else {
|
||||||
parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, global.GetPassphrase("Enter passphrase for your SSH keyfile:"))
|
parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, global.GetPassword("Enter password for your SSH keyfile:"))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, false, "", errors.New("unable to parse private key: " + keyFile)
|
return nil, false, false, "", errors.New("unable to parse private key: " + keyFile)
|
||||||
|
|||||||
+3
-3
@@ -16,12 +16,12 @@ These are as follows:
|
|||||||
- `termux`: Allows creating an Android binary that can interact with the Termux clipboard (for Android)
|
- `termux`: Allows creating an Android binary that can interact with the Termux clipboard (for Android)
|
||||||
|
|
||||||
## Required Global Variable Manipulation
|
## Required Global Variable Manipulation
|
||||||
- `global.GetPassphrase` must be set to allow for different types of clients (CLI, GUI, TUI) to prompt for the passphrase in the most appropriate way.
|
- `global.GetPassword` must be set to allow for different types of clients (CLI, GUI, TUI) to prompt for the password in the most appropriate way.
|
||||||
- `crypt.Daemonize`, true by default, determines whether to make use of the RCW daemon for passphrase caching. This may be best to disable for interactive clients.
|
- `crypt.Daemonize`, true by default, determines whether to make use of the RCW daemon for password caching. This may be best to disable for interactive clients.
|
||||||
|
|
||||||
## Required Arguments
|
## Required Arguments
|
||||||
- `clipclear`: Should be accepted by all non-interactive CLI libmutton implementations (not required for interactive GUI/TUI implementations). In order to clear the clipboard on a timer, non-interactive libmutton-based password managers call another instance of their executable with the `clipclear` argument (e.g. `mutn clipclear`) with the intended clipboard contents provided via STDIN. If after 30 seconds the clipboard contents have not changed, they are cleared. Please accept a `clipclear` argument that calls `core.ClipClearArgument()`.
|
- `clipclear`: Should be accepted by all non-interactive CLI libmutton implementations (not required for interactive GUI/TUI implementations). In order to clear the clipboard on a timer, non-interactive libmutton-based password managers call another instance of their executable with the `clipclear` argument (e.g. `mutn clipclear`) with the intended clipboard contents provided via STDIN. If after 30 seconds the clipboard contents have not changed, they are cleared. Please accept a `clipclear` argument that calls `core.ClipClearArgument()`.
|
||||||
- `startrcwd`: Should be accepted by all libmutton implementations making use of the RCW daemon to cache passphrases. Please accept a `startrcwd` argument that calls `core.RCWDArgument()`.
|
- `startrcwd`: Should be accepted by all libmutton implementations making use of the RCW daemon to cache passwords. Please accept a `startrcwd` argument that calls `core.RCWDArgument()`.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
libmutton-based password manager clients should all share the same INI configuration file.
|
libmutton-based password manager clients should all share the same INI configuration file.
|
||||||
|
|||||||
Reference in New Issue
Block a user