mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-27 20:36:29 -04:00
Make adjustments for easier CGO integration
This commit is contained in:
+3
-2
@@ -31,7 +31,8 @@ func Entry(vanityPath string, timestamp int64) error {
|
|||||||
// AllPasswordEntries adds age data for all un-aged entries containing passwords.
|
// AllPasswordEntries adds age data for all un-aged entries containing passwords.
|
||||||
// Each entry is aged with a random timestamp from within the last year to prevent
|
// Each entry is aged with a random timestamp from within the last year to prevent
|
||||||
// all entries having their passwords expire at the same time.
|
// all entries having their passwords expire at the same time.
|
||||||
func AllPasswordEntries(forceReage bool) error {
|
// Leave rcwPassword nil to use RCW demonization.
|
||||||
|
func AllPasswordEntries(forceReage bool, rcwPassword []byte) error {
|
||||||
allVanityPaths, _, err := synccommon.WalkEntryDir()
|
allVanityPaths, _, err := synccommon.WalkEntryDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to walk entry directory: " + err.Error())
|
return errors.New("unable to walk entry directory: " + err.Error())
|
||||||
@@ -48,7 +49,7 @@ func AllPasswordEntries(forceReage bool) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decSlice, err := crypt.DecryptFileToSlice(global.EntryRoot + vanityPath)
|
decSlice, err := crypt.DecryptFileToSlice(global.EntryRoot+vanityPath, rcwPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -13,7 +13,8 @@ import (
|
|||||||
|
|
||||||
// CopyShortcut (given a path) decrypts an
|
// CopyShortcut (given a path) decrypts an
|
||||||
// entry and copies a field to the clipboard.
|
// entry and copies a field to the clipboard.
|
||||||
func CopyShortcut(realPath string, field int) error {
|
// Leave rcwPassword nil to use RCW demonization.
|
||||||
|
func CopyShortcut(realPath string, field int, rcwPassword []byte) error {
|
||||||
// ensure realPath exists and is a file
|
// ensure realPath exists and is a file
|
||||||
_, err := back.TargetIsFile(realPath, true)
|
_, err := back.TargetIsFile(realPath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -21,7 +22,7 @@ func CopyShortcut(realPath string, field int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decrypt entry
|
// decrypt entry
|
||||||
decSlice, err := crypt.DecryptFileToSlice(realPath)
|
decSlice, err := crypt.DecryptFileToSlice(realPath, rcwPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to decrypt entry: " + err.Error())
|
return errors.New("unable to decrypt entry: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -10,7 +10,8 @@ import (
|
|||||||
// GetOldEntryData decrypts and returns old entry data (with all required lines present).
|
// GetOldEntryData decrypts and returns old entry data (with all required lines present).
|
||||||
// This is a wrapper around the DecryptFileToSlice function that ensures all required lines are present in the returned slice.
|
// This is a wrapper around the DecryptFileToSlice function that ensures all required lines are present in the returned slice.
|
||||||
// This makes it ideal for editing entries, as it guarantees at least a baseline slice length.
|
// This makes it ideal for editing entries, as it guarantees at least a baseline slice length.
|
||||||
func GetOldEntryData(realPath string, field int) ([]string, error) {
|
// Leave rcwPassword nil to use RCW demonization.
|
||||||
|
func GetOldEntryData(realPath string, field int, rcwPassword []byte) ([]string, error) {
|
||||||
// ensure realPath exists and is a file
|
// ensure realPath exists and is a file
|
||||||
_, err := back.TargetIsFile(realPath, true)
|
_, err := back.TargetIsFile(realPath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -18,7 +19,7 @@ func GetOldEntryData(realPath string, field int) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read old entry data
|
// read old entry data
|
||||||
decryptedEntry, err := crypt.DecryptFileToSlice(realPath)
|
decryptedEntry, err := crypt.DecryptFileToSlice(realPath, rcwPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("unable to decrypt entry: " + err.Error())
|
return nil, errors.New("unable to decrypt entry: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -19,8 +19,9 @@ import (
|
|||||||
|
|
||||||
// WriteEntry writes entryData to an encrypted file at realPath.
|
// WriteEntry writes entryData to an encrypted file at realPath.
|
||||||
// If the entry contains an updated password, an age file is also created.
|
// If the entry contains an updated password, an age file is also created.
|
||||||
func WriteEntry(realPath string, decSlice []string, passwordIsNew bool) error {
|
// Leave rcwPassword nil to use RCW demonization.
|
||||||
err := os.WriteFile(realPath, crypt.EncryptBytes([]byte(strings.Join(decSlice, "\n"))), 0600)
|
func WriteEntry(realPath string, decSlice []string, passwordIsNew bool, rcwPassword []byte) error {
|
||||||
|
err := os.WriteFile(realPath, crypt.EncryptBytes([]byte(strings.Join(decSlice, "\n")), rcwPassword), 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to write to file: " + err.Error())
|
return errors.New("unable to write to file: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-26
@@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/rwinkhart/rcw/wrappers"
|
"github.com/rwinkhart/rcw/wrappers"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Daemonize = true
|
|
||||||
var RetryPassword = true
|
var RetryPassword = true
|
||||||
|
|
||||||
// RCWDArgument reads the password from stdin and caches it via an RCW daemon.
|
// RCWDArgument reads the password from stdin and caches it via an RCW daemon.
|
||||||
@@ -25,23 +24,29 @@ func RCWDArgument() {
|
|||||||
daemon.Start([]byte(password))
|
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
|
||||||
func DecryptFileToSlice(realPath string) ([]string, error) {
|
// and returns the contents as a slice of (trimmed) strings.
|
||||||
|
// Leave rcwPassword nil to use RCW demonization.
|
||||||
|
func DecryptFileToSlice(realPath string, rcwPassword []byte) ([]string, error) {
|
||||||
// read encrypted file
|
// read encrypted file
|
||||||
encBytes, err := os.ReadFile(realPath)
|
encBytes, err := os.ReadFile(realPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("unable to open \"" + realPath + "\" for decryption: " + err.Error())
|
return nil, errors.New("unable to open \"" + realPath + "\" for decryption: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrypt data using RCW daemon
|
// if no password was provided, assume daemon mode
|
||||||
password := launchRCWDProcess()
|
if rcwPassword == nil {
|
||||||
if password == nil {
|
rcwPassword = launchRCWDProcess()
|
||||||
// if daemon is already running, use it to decrypt the data
|
// if rcwPassword is still nil, the daemon is already running;
|
||||||
return strings.Split(string(daemon.GetDec(encBytes)), "\n"), nil
|
// use it to encrypt the data
|
||||||
|
if rcwPassword == nil {
|
||||||
|
return strings.Split(string(daemon.GetDec(encBytes)), "\n"), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if the daemon is not already running, use wrappers.Decrypt
|
|
||||||
// directly to avoid waiting for socket file creation
|
// if the daemon is not being used/was not already running,
|
||||||
decBytes, err := wrappers.Decrypt(encBytes, password)
|
// use wrappers.Decrypt directly to avoid waiting for socket file creation
|
||||||
|
decBytes, err := wrappers.Decrypt(encBytes, rcwPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("unable to decrypt \"" + realPath + "\": " + err.Error())
|
return nil, errors.New("unable to decrypt \"" + realPath + "\": " + err.Error())
|
||||||
}
|
}
|
||||||
@@ -49,22 +54,28 @@ func DecryptFileToSlice(realPath 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 {
|
// Leave rcwPassword nil to use RCW demonization.
|
||||||
password := launchRCWDProcess()
|
func EncryptBytes(decBytes, rcwPassword []byte) []byte {
|
||||||
if password == nil {
|
// if no rcwPassword was provided, assume daemon mode
|
||||||
// if daemon is already running, use it to encrypt the data
|
if rcwPassword == nil {
|
||||||
return daemon.GetEnc(decBytes)
|
rcwPassword = launchRCWDProcess()
|
||||||
|
// if rcwPassword is still nil, the daemon is already running;
|
||||||
|
// use it to encrypt the data
|
||||||
|
if rcwPassword == nil {
|
||||||
|
return daemon.GetEnc(decBytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if the daemon is not already running, use wrappers.Encrypt
|
|
||||||
// directly to avoid waiting for socket file creation
|
// if the daemon is not being used/was not already running,
|
||||||
return wrappers.Encrypt(decBytes, password)
|
// use wrappers.Encrypt directly to avoid waiting for socket file creation
|
||||||
|
return wrappers.Encrypt(decBytes, rcwPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
// launchRCWDProcess launches an RCW daemon to cache a password.
|
// 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 password (otherwise returns nil).
|
// it collects and returns the password (otherwise returns nil).
|
||||||
func launchRCWDProcess() []byte {
|
func launchRCWDProcess() []byte {
|
||||||
if Daemonize && daemon.IsOpen() {
|
if daemon.IsOpen() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var password []byte
|
var password []byte
|
||||||
@@ -81,12 +92,10 @@ func launchRCWDProcess() []byte {
|
|||||||
password = global.GetPassword("RCW Password:")
|
password = global.GetPassword("RCW Password:")
|
||||||
}
|
}
|
||||||
|
|
||||||
if Daemonize {
|
cmd := exec.Command(os.Args[0], "startrcwd")
|
||||||
cmd := exec.Command(os.Args[0], "startrcwd")
|
cmd.SysProcAttr = global.GetSysProcAttr()
|
||||||
cmd.SysProcAttr = global.GetSysProcAttr()
|
_ = back.WriteToStdin(cmd, string(password))
|
||||||
_ = back.WriteToStdin(cmd, string(password))
|
_ = cmd.Start()
|
||||||
_ = cmd.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
return password
|
return password
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/rwinkhart/libmutton
|
module github.com/rwinkhart/libmutton
|
||||||
|
|
||||||
go 1.25.5
|
go 1.25.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/pkg/sftp v1.13.10
|
github.com/pkg/sftp v1.13.10
|
||||||
@@ -8,6 +8,7 @@ require (
|
|||||||
github.com/rwinkhart/go-boilerplate v0.1.1
|
github.com/rwinkhart/go-boilerplate v0.1.1
|
||||||
github.com/rwinkhart/rcw v0.2.4
|
github.com/rwinkhart/rcw v0.2.4
|
||||||
golang.org/x/crypto v0.46.0
|
golang.org/x/crypto v0.46.0
|
||||||
|
golang.org/x/sys v0.40.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -15,7 +16,6 @@ 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.2 // indirect
|
github.com/rwinkhart/peercred-mini v0.1.2 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace golang.org/x/sys => github.com/rwinkhart/sys v0.40.0
|
replace golang.org/x/sys => github.com/rwinkhart/sys v0.40.0
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ These are as follows:
|
|||||||
|
|
||||||
## Required Global Variable Manipulation
|
## Required Global Variable Manipulation
|
||||||
- `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.
|
- `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 password caching. This may be best to disable for interactive clients.
|
|
||||||
- `crypt.RetryPassword`, true by default, determines whether the crypt package should verify user-typed passwords and re-prompt if needed. Turn this off to handle this uniquely in the client.
|
- `crypt.RetryPassword`, true by default, determines whether the crypt package should verify user-typed passwords and re-prompt if needed. Turn this off to handle this uniquely in the client.
|
||||||
|
|
||||||
## Required Arguments
|
## Required Arguments
|
||||||
|
|||||||
Reference in New Issue
Block a user