walletmanager funcs done, now for wallet funcs
This commit is contained in:
parent
8d81c5f0cc
commit
d76746d79e
@ -1,3 +1,6 @@
|
||||
https://api.kde.org/frameworks/kwallet/html/index.html
|
||||
https://invent.kde.org/frameworks/kwallet/-/blob/master/src/api/KWallet/kwallet.h
|
||||
|
||||
https://github.com/99designs/keyring/blob/master/kwallet.go
|
||||
|
||||
Dbus methods etc.: https://invent.kde.org/frameworks/kwallet/-/blob/master/src/api/KWallet/org.kde.KWallet.xml
|
||||
|
141
consts.go
141
consts.go
@ -1,5 +1,20 @@
|
||||
package gokwallet
|
||||
|
||||
// KwalletD Dbus returns.
|
||||
const (
|
||||
DbusSuccess int32 = 0
|
||||
DbusFailure int32 = 1
|
||||
)
|
||||
|
||||
// KwalletD Dbus enums for WalletItem types.
|
||||
const (
|
||||
kwalletdEnumTypeUnknown = iota // UnknownItem
|
||||
kwalletdEnumTypePassword // Password
|
||||
kwalletdEnumTypeStream // Blob
|
||||
kwalletdEnumTypeMap // Map
|
||||
kwalletdEnumTypeUnused = 0xffff // 65535
|
||||
)
|
||||
|
||||
// KWalletD Dbus interfaces.
|
||||
const (
|
||||
// DbusService is the Dbus service bus identifier.
|
||||
@ -14,6 +29,21 @@ const (
|
||||
DefaultWalletName string = "kdewallet"
|
||||
// DefaultAppID is the default name for the application (see WalletManager.AppID).
|
||||
DefaultAppID string = "GoKwallet"
|
||||
// DefaultWindowID is 0; we aren't guaranteed to have a window, so we pass 0 (per upstream headers' comments).
|
||||
DefaultWindowID int64 = 0
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultRecurseOpts *RecurseOpts = &RecurseOpts{
|
||||
All: false,
|
||||
Wallets: true,
|
||||
Folders: true,
|
||||
AllWalletItems: false,
|
||||
Passwords: false,
|
||||
Maps: false,
|
||||
Blobs: false,
|
||||
UnknownItems: false,
|
||||
}
|
||||
)
|
||||
|
||||
// WalletManager interface.
|
||||
@ -94,10 +124,10 @@ const (
|
||||
// DbusWMOpenAsync opens (unlocks) a Wallet asynchronously.
|
||||
DbusWMOpenAsync string = DbusInterfaceWM + ".openAsync"
|
||||
|
||||
// DbusWMOpenPath opens (unlocks) a Wallet by its filepath.
|
||||
// DbusWMOpenPath opens a Wallet by its filepath.
|
||||
DbusWMOpenPath string = DbusInterfaceWM + ".openPath"
|
||||
|
||||
// DbusWMOpenPathAsync opens (unlocks) a Wallet by its filepath asynchronously.
|
||||
// DbusWMOpenPathAsync opens a Wallet by its filepath asynchronously.
|
||||
DbusWMOpenPathAsync string = DbusInterfaceWM + ".openPath"
|
||||
|
||||
// DbusWMPamOpen opens (unlocks) a Wallet via PAM.
|
||||
@ -112,19 +142,31 @@ const (
|
||||
// DbusWMReadEntry fetches a WalletItem by its name from a Folder (as a byteslice).
|
||||
DbusWMReadEntry string = DbusInterfaceWM + ".readEntry"
|
||||
|
||||
// DbusWMReadEntryList returns a map of WalletItem objects in a Folder.
|
||||
/*
|
||||
DbusWMReadEntryList returns a map of WalletItem objects in a Folder.
|
||||
|
||||
Deprecated: use DbusWMEntriesList instead.
|
||||
*/
|
||||
DbusWMReadEntryList string = DbusInterfaceWM + ".readEntryList"
|
||||
|
||||
// DbusWMReadMap returns a Map from a Folder (as a byteslice).
|
||||
DbusWMReadMap string = DbusInterfaceWM + ".readMap"
|
||||
|
||||
// DbusWMReadMapList returns a map of Map objects in a Folder.
|
||||
/*
|
||||
DbusWMReadMapList returns a map of Map objects in a Folder.
|
||||
|
||||
Deprecated: use DbusWMMapList instead.
|
||||
*/
|
||||
DbusWMReadMapList string = DbusInterfaceWM + ".readMapList"
|
||||
|
||||
// DbusWMReadPassword returns a Password from a Folder (as a byteslice).
|
||||
DbusWMReadPassword string = DbusInterfaceWM + ".readPassword"
|
||||
|
||||
// DbusWMReadPasswordList returns a map of Password objects in a Folder.
|
||||
/*
|
||||
DbusWMReadPasswordList returns a map of Password objects in a Folder.
|
||||
|
||||
Deprecated: use DbusWMPasswordList instead.
|
||||
*/
|
||||
DbusWMReadPasswordList string = DbusInterfaceWM + ".readPasswordList"
|
||||
|
||||
// DbusWMReconfigure is [FUNCTION UNKNOWN/UNDOCUMENTED; TODO? NOT IMPLEMENTED.]
|
||||
@ -163,92 +205,3 @@ const (
|
||||
// DbusPath is the path for DbusService.
|
||||
DbusPath string = "/modules/kwalletd5"
|
||||
)
|
||||
|
||||
// Recursion options.
|
||||
|
||||
/*
|
||||
RecurseNone specifies that no recursion should be done.
|
||||
If present, it takes precedent over all over RecurseOptsFlags present.
|
||||
|
||||
Performed in/from:
|
||||
WalletManager
|
||||
Wallet
|
||||
Folder
|
||||
(WalletItem)
|
||||
*/
|
||||
const RecurseNone RecurseOptsFlag = 0
|
||||
const (
|
||||
/*
|
||||
RecurseWallet indicates that Wallet objects should have Wallet.Update called.
|
||||
|
||||
Performed in/from: WalletManager
|
||||
*/
|
||||
RecurseWallet RecurseOptsFlag = 1 << iota
|
||||
/*
|
||||
RecurseFolder indicates that Folder objects should have Folder.Update called.
|
||||
|
||||
Performed in/from:
|
||||
Wallet
|
||||
|
||||
May be performed in/from (depending on other flags):
|
||||
WalletManager
|
||||
*/
|
||||
RecurseFolder
|
||||
/*
|
||||
RecurseWalletItem indicates that all WalletItem entries should have (WalletItem).Update() called.
|
||||
If present, it takes precedent over all over relevant RecurseOptsFlags present
|
||||
(RecursePassword, RecurseMap, RecurseBlob, RecurseUnknown).
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other flags):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
RecurseWalletItem
|
||||
/*
|
||||
RecursePassword indicates that Password objects should have Password.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other flags):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
RecursePassword
|
||||
/*
|
||||
RecurseMap indicates that Map objects should have Map.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other flags):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
RecurseMap
|
||||
/*
|
||||
RecurseBlob indicates that Blob objects should have Blob.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other flags):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
RecurseBlob
|
||||
/*
|
||||
RecurseUnknown indicates that UnknownItem objects should have UnknownItem.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other flags):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
RecurseUnknown
|
||||
)
|
||||
|
5
doc.go
5
doc.go
@ -5,7 +5,7 @@ Package gokwallet serves as a Golang interface to KDE's KWallet (https://utils.k
|
||||
|
||||
Note that to use this library, the running machine must have both Dbus and kwalletd running.
|
||||
|
||||
Note that this library interfaces with kwalletd. KWallet is in the process of moving to libsecret/SecretService
|
||||
Relatedly, note also that this library interfaces with kwalletd. KWallet is in the process of moving to libsecret/SecretService
|
||||
(see https://bugs.kde.org/show_bug.cgi?id=313216 and https://invent.kde.org/frameworks/kwallet/-/merge_requests/11),
|
||||
thus replacing kwalletd.
|
||||
While there is a pull request in place, it has not yet been merged in (and it may be a while before downstream
|
||||
@ -72,5 +72,8 @@ Usage
|
||||
|
||||
Full documentation can be found via inline documentation.
|
||||
Additionally, use either https://pkg.go.dev/r00t2.io/gokwallet or https://pkg.go.dev/golang.org/x/tools/cmd/godoc (or `go doc`) in the source root.
|
||||
|
||||
You most likely do *not* want to call any New<object> function directly;
|
||||
NewWalletManager with its RecurseOpts parameter (`recursion`) should get you everything you want/need.
|
||||
*/
|
||||
package gokwallet
|
||||
|
20
errs.go
Normal file
20
errs.go
Normal file
@ -0,0 +1,20 @@
|
||||
package gokwallet
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
/*
|
||||
ErrNotInitialized will be triggered if attempting to interact with an object that has not been properly initialized.
|
||||
Notably, in most/all cases this means that it was not created via a New<object> func (for instance,
|
||||
this would lead to a Wallet missing a handler).
|
||||
It is intended as a safety check (so that you don't accidentally delete a wallet with e.g. a handler of 0 when
|
||||
trying to delete a different wallet).
|
||||
*/
|
||||
ErrNotInitialized error = errors.New("object not properly initialized")
|
||||
/*
|
||||
ErrOperationFailed is a generic failure message that will occur of a Dbus operation returns non-success.
|
||||
*/
|
||||
ErrOperationFailed error = errors.New("a Dbus operation has failed to execute successfully")
|
||||
)
|
56
folder_funcs.go
Normal file
56
folder_funcs.go
Normal file
@ -0,0 +1,56 @@
|
||||
package gokwallet
|
||||
|
||||
/*
|
||||
NewF returns a Wallet. It requires a RecurseOpts
|
||||
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||
It also requires a WalletManager and wallet name.
|
||||
*/
|
||||
func NewFolder(w *Wallet, name string, recursion *RecurseOpts) (folder *Folder, err error) {
|
||||
|
||||
if !w.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
folder = &Folder{
|
||||
DbusObject: w.DbusObject,
|
||||
Name: name,
|
||||
Passwords: nil,
|
||||
Maps: nil,
|
||||
BinaryData: nil,
|
||||
Unknown: nil,
|
||||
Recurse: recursion,
|
||||
wm: w.wm,
|
||||
wallet: w,
|
||||
// handle: 0,
|
||||
isInit: false,
|
||||
}
|
||||
|
||||
if err = folder.folderCheck(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if folder.Recurse.All || folder.Recurse.Wallets {
|
||||
if err = folder.Update(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
folder.isInit = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (f *Folder) Update() (err error) {
|
||||
|
||||
// TODO.
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (f *Folder) folderCheck() (err error) {
|
||||
|
||||
// TODO.
|
||||
|
||||
return
|
||||
}
|
110
funcs.go
Normal file
110
funcs.go
Normal file
@ -0,0 +1,110 @@
|
||||
package gokwallet
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
/*
|
||||
NewRecurseOpts returns a RecurseOpts based on the specified options.
|
||||
See the documentation for RecurseOpts for descriptions of the behaviour for each recursion option.
|
||||
warn is a MultiError but should be treated as warnings rather than strictly errors.
|
||||
*/
|
||||
func NewRecurseOpts(recurseAll, wallets, folders, recurseAllWalletItems, passwords, maps, blobs, unknownItems bool) (opts *RecurseOpts, warn error) {
|
||||
|
||||
var err []error = make([]error, 0)
|
||||
|
||||
if recurseAll {
|
||||
if !wallets {
|
||||
err = append(err, errors.New("wallets was specified as false but recurseAll is true; recurseAll overrides wallets to true"))
|
||||
wallets = true
|
||||
}
|
||||
if !folders {
|
||||
err = append(err, errors.New("folders was specified as false but recurseAll is true; recurseAll overrides folders to true"))
|
||||
folders = true
|
||||
}
|
||||
// NOTE: This is commented out because we control these explicitly with recurseAllWalletItems.
|
||||
/*
|
||||
if !passwords {
|
||||
err = append(err, errors.New("passwords was specified as false but recurseAll is true; recurseAll overrides passwords to true"))
|
||||
passwords = true
|
||||
}
|
||||
if !maps {
|
||||
err = append(err, errors.New("maps was specified as false but recurseAll is true; recurseAll overrides maps to true"))
|
||||
maps = true
|
||||
}
|
||||
if !blobs {
|
||||
err = append(err, errors.New("blobs was specified as false but recurseAll is true; recurseAll overrides blobs to true"))
|
||||
blobs = true
|
||||
}
|
||||
if !unknownItems {
|
||||
err = append(err, errors.New("unknownItems was specified as false but recurseAll is true; recurseAll overrides unknownItems to true"))
|
||||
unknownItems = true
|
||||
}
|
||||
if !recurseAllWalletItems {
|
||||
err = append(
|
||||
err,
|
||||
errors.New(
|
||||
"recurseAllWalletItems was specified as false but recurseAll is true; recurseAll overrides recurseAllWalletItems to true",
|
||||
),
|
||||
)
|
||||
recurseAllWalletItems = true
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
if recurseAllWalletItems {
|
||||
if !passwords {
|
||||
err = append(
|
||||
err,
|
||||
errors.New(
|
||||
"passwords was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides passwords to true",
|
||||
),
|
||||
)
|
||||
passwords = true
|
||||
}
|
||||
if !maps {
|
||||
err = append(
|
||||
err,
|
||||
errors.New(
|
||||
"maps was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides maps to true",
|
||||
),
|
||||
)
|
||||
maps = true
|
||||
}
|
||||
if !blobs {
|
||||
err = append(
|
||||
err,
|
||||
errors.New(
|
||||
"blobs was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides blobs to true",
|
||||
),
|
||||
)
|
||||
blobs = true
|
||||
}
|
||||
if !unknownItems {
|
||||
err = append(
|
||||
err,
|
||||
errors.New(
|
||||
"unknownItems was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides unknownItems to true",
|
||||
),
|
||||
)
|
||||
unknownItems = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opts = &RecurseOpts{
|
||||
All: recurseAll,
|
||||
Wallets: wallets,
|
||||
Folders: folders,
|
||||
AllWalletItems: recurseAllWalletItems,
|
||||
Passwords: passwords,
|
||||
Maps: maps,
|
||||
Blobs: blobs,
|
||||
UnknownItems: unknownItems,
|
||||
}
|
||||
|
||||
if err != nil && len(err) > 0 {
|
||||
warn = NewErrors(err...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
2
go.mod
2
go.mod
@ -4,5 +4,5 @@ go 1.17
|
||||
|
||||
require (
|
||||
github.com/godbus/dbus/v5 v5.0.6
|
||||
r00t2.io/goutils v1.0.1
|
||||
r00t2.io/goutils v1.1.0
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@ -2,6 +2,6 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7
|
||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/jszwec/csvutil v1.5.0/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg=
|
||||
r00t2.io/goutils v1.0.1 h1:f1m2QRBF8XsW3peYf1I2q37npgf+5bmJBbrLzCFtm34=
|
||||
r00t2.io/goutils v1.0.1/go.mod h1:CMK3RGnMSyjDSfYxeFQl/oJTkkUMS1jhSTdGTkAPpQw=
|
||||
r00t2.io/goutils v1.1.0 h1:vJqEWvdX0TKDyT+hTgws0wA1dc/F8JkQKw5cDHz0wH0=
|
||||
r00t2.io/goutils v1.1.0/go.mod h1:CMK3RGnMSyjDSfYxeFQl/oJTkkUMS1jhSTdGTkAPpQw=
|
||||
r00t2.io/sysutils v0.0.0-20210224054841-55ac47c86928/go.mod h1:XzJkBF6SHAODEszJlOcjtGoTHwYnZZNmseA6PyOujes=
|
||||
|
57
multierror_funcs.go
Normal file
57
multierror_funcs.go
Normal file
@ -0,0 +1,57 @@
|
||||
package gokwallet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
NewErrors returns a new MultiError based on a slice of error.Error (errs).
|
||||
Any nil errors are trimmed. If there are no actual errors after trimming, err will be nil.
|
||||
*/
|
||||
func NewErrors(errs ...error) (err error) {
|
||||
|
||||
if errs == nil || len(errs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var realErrs []error = make([]error, 0)
|
||||
|
||||
for _, e := range errs {
|
||||
if e == nil {
|
||||
continue
|
||||
}
|
||||
realErrs = append(realErrs, e)
|
||||
}
|
||||
|
||||
if len(realErrs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
err = &MultiError{
|
||||
Errors: realErrs,
|
||||
ErrorSep: "\n",
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e *MultiError) Error() (errStr string) {
|
||||
|
||||
var numErrs int
|
||||
|
||||
if e == nil || len(e.Errors) == 0 {
|
||||
return
|
||||
} else {
|
||||
numErrs = len(e.Errors)
|
||||
}
|
||||
|
||||
for idx, err := range e.Errors {
|
||||
if (idx + 1) < numErrs {
|
||||
errStr += fmt.Sprintf(err.Error(), e.ErrorSep)
|
||||
} else {
|
||||
errStr += err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
182
types.go
182
types.go
@ -2,7 +2,6 @@ package gokwallet
|
||||
|
||||
import (
|
||||
"github.com/godbus/dbus/v5"
|
||||
"r00t2.io/goutils/types"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -45,8 +44,22 @@ type WalletManager struct {
|
||||
/*
|
||||
Wallets is the collection of Wallets accessible in/to this WalletManager.
|
||||
Wallet.Name is the map key.
|
||||
(TODO: When wallet file support is added, the *filename* will be the map key.
|
||||
This is to mitigate namespace conflicts between Dbus and file wallets.)
|
||||
*/
|
||||
Wallets map[string]*Wallet `json:"wallets"`
|
||||
// Recurse contains the relevant RecurseOpts.
|
||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||
// Enabled is true if KWalletD is enabled/running.
|
||||
Enabled bool `json:"enabled"`
|
||||
// Local is the "local" wallet.
|
||||
Local *Wallet `json:"local_wallet"`
|
||||
// Network is the "network" wallet.
|
||||
Network *Wallet `json:"network_wallet"`
|
||||
// isInit flags whether this is "properly" set up (i.e. was initialized via NewWalletManager).
|
||||
isInit bool
|
||||
// walletFiles are (resolved and vetted) wallet files (kwl, xml).
|
||||
walletFiles []string
|
||||
}
|
||||
|
||||
// Wallet contains one or more (or none) Folder objects.
|
||||
@ -59,6 +72,22 @@ type Wallet struct {
|
||||
Folder.Name is the map key.
|
||||
*/
|
||||
Folders map[string]*Folder `json:"folders"`
|
||||
// Recurse contains the relevant RecurseOpts.
|
||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||
// IsUnlocked specifies if this Wallet is open ("unlocked") or not.
|
||||
IsUnlocked bool `json:"open"`
|
||||
/*
|
||||
FilePath is:
|
||||
- empty if this is an internal Wallet, or
|
||||
- the filepath to the wallet file if this is an on-disk wallet (either .kwl or .xml)
|
||||
*/
|
||||
FilePath string `json:"wallet_file"`
|
||||
// wm is the parent WalletManager this Wallet was fetched from.
|
||||
wm *WalletManager
|
||||
// handle is this Wallet's handler number.
|
||||
handle int32
|
||||
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||
isInit bool
|
||||
}
|
||||
|
||||
// Folder contains secret object collections of Password, Map, Blob, and UnknownItem objects.
|
||||
@ -86,6 +115,16 @@ type Folder struct {
|
||||
Unknown.Name is the map key.
|
||||
*/
|
||||
Unknown map[string]*UnknownItem `json:"unknown"`
|
||||
// Recurse contains the relevant RecurseOpts.
|
||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||
// wm is the parent WalletManager that Folder.wallet was fetched from.
|
||||
wm *WalletManager
|
||||
// wallet is the parent Wallet this Folder was fetched from.
|
||||
wallet *Wallet
|
||||
// handle is this Folder's handler number.
|
||||
handle int32
|
||||
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||
isInit bool
|
||||
}
|
||||
|
||||
// Password is a straightforward single-value secret of text.
|
||||
@ -95,6 +134,18 @@ type Password struct {
|
||||
Name string `json:"name"`
|
||||
// Value is this Password's value.
|
||||
Value string `json:"value"`
|
||||
// Recurse contains the relevant RecurseOpts.
|
||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||
// wm is the parent WalletManager that Password.folder.wallet was fetched from.
|
||||
wm *WalletManager
|
||||
// wallet is the parent Wallet that Password.folder was fetched from.
|
||||
wallet *Wallet
|
||||
// folder is the parent Folder this Password was fetched from.
|
||||
folder *Folder
|
||||
// handle is this Password's handler number.
|
||||
handle int32
|
||||
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||
isInit bool
|
||||
}
|
||||
|
||||
// Map is a dictionary or key/value secret.
|
||||
@ -104,6 +155,18 @@ type Map struct {
|
||||
Name string `json:"name"`
|
||||
// Value is this Map's value.
|
||||
Value map[string]string `json:"value"`
|
||||
// Recurse contains the relevant RecurseOpts.
|
||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||
// wm is the parent WalletManager that Map.folder.wallet was fetched from.
|
||||
wm *WalletManager
|
||||
// wallet is the parent Wallet that Map.folder was fetched from.
|
||||
wallet *Wallet
|
||||
// folder is the parent Folder this Map was fetched from.
|
||||
folder *Folder
|
||||
// handle is this Map's handler number.
|
||||
handle int32
|
||||
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||
isInit bool
|
||||
}
|
||||
|
||||
// Blob (binary large object, typographically BLOB) is secret binary data.
|
||||
@ -113,6 +176,18 @@ type Blob struct {
|
||||
Name string `json:"name"`
|
||||
// Value is this Blob's value.
|
||||
Value []byte `json:"value"`
|
||||
// Recurse contains the relevant RecurseOpts.
|
||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||
// wm is the parent WalletManager that Blob.folder.wallet was fetched from.
|
||||
wm *WalletManager
|
||||
// wallet is the parent Wallet that Blob.folder was fetched from.
|
||||
wallet *Wallet
|
||||
// folder is the parent Folder this Blob was fetched from.
|
||||
folder *Folder
|
||||
// handle is this Blob's handler number.
|
||||
handle int32
|
||||
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||
isInit bool
|
||||
}
|
||||
|
||||
/*
|
||||
@ -126,6 +201,18 @@ type UnknownItem struct {
|
||||
Name string `json:"name"`
|
||||
// Value is the Dbus path of this UnknownItem.
|
||||
Value dbus.ObjectPath `json:"value"`
|
||||
// Recurse contains the relevant RecurseOpts.
|
||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||
// wm is the parent WalletManager that UnknownItem.folder.wallet was fetched from.
|
||||
wm *WalletManager
|
||||
// wallet is the parent Wallet that UnknownItem.folder was fetched from.
|
||||
wallet *Wallet
|
||||
// folder is the parent Folder this UnknownItem was fetched from.
|
||||
folder *Folder
|
||||
// handle is this UnknownItem's handler number.
|
||||
handle int32
|
||||
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||
isInit bool
|
||||
}
|
||||
|
||||
// WalletItem is an interface to manage wallet objects: Password, Map, Blob, or UnknownItem.
|
||||
@ -134,8 +221,93 @@ type WalletItem interface {
|
||||
}
|
||||
|
||||
/*
|
||||
RecurseOptsFlag is used to determine whether or not to recurse into items and fully populate them.
|
||||
One would use a types.BitMask as a parameter type and do <BitMask>.HasFlag(<RecurseOptsFlag>).
|
||||
See consts.go for the actual flags.
|
||||
RecurseOpts controls whether recursion should be done on objects when fetching them.
|
||||
E.g. if fetching a WalletManager (via NewWalletManager) and RecurseOpts.Wallet is true,
|
||||
then WalletManager.Wallets will be populated with Wallet objects.
|
||||
*/
|
||||
type RecurseOptsFlag types.MaskBit
|
||||
type RecurseOpts struct {
|
||||
/*
|
||||
All, if true, specifies that all possible recursions should be done.
|
||||
If true, it takes precedent over all over RecurseOpts fields (with the exception of RecurseOpts.AllWalletItems).
|
||||
|
||||
Performed in/from:
|
||||
WalletManager
|
||||
Wallet
|
||||
Folder
|
||||
(WalletItem)
|
||||
*/
|
||||
All bool `json:"none"`
|
||||
/*
|
||||
Wallets, if true, indicates that Wallet objects should have Wallet.Update called.
|
||||
|
||||
Performed in/from: WalletManager
|
||||
*/
|
||||
Wallets bool `json:"wallet"`
|
||||
/*
|
||||
Folders, if true, indicates that Folder objects should have Folder.Update called.
|
||||
|
||||
Performed in/from:
|
||||
Wallet
|
||||
|
||||
May be performed in/from (depending on other fields):
|
||||
WalletManager
|
||||
*/
|
||||
Folders bool `json:"folder"`
|
||||
/*
|
||||
AllWalletItems, if true, indicates that all WalletItem entries should have (WalletItem).Update() called.
|
||||
If true, it takes precedent over all over relevant RecurseOpts fields for each WalletItem type
|
||||
(i.e. RecurseOpts.Passwords, RecurseOpts.Maps, RecurseOpts.Blobs, RecurseOpts.UnknownItems).
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other fields):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
AllWalletItems bool `json:"wallet_item"`
|
||||
/*
|
||||
Passwords, if true, indicates that Password objects should have Password.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other fields):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
Passwords bool `json:"password"`
|
||||
/*
|
||||
Maps, if true, indicates that Map objects should have Map.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other fields):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
Maps bool `json:"map"`
|
||||
/*
|
||||
Blobs, if true, indicates that Blob objects should have Blob.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other fields):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
Blobs bool `json:"blob"`
|
||||
/*
|
||||
UnknownItems indicates that UnknownItem objects should have UnknownItem.Update() called.
|
||||
|
||||
Performed in/from:
|
||||
Folder
|
||||
|
||||
May be performed in/from (depending on other fields):
|
||||
WalletManager
|
||||
Wallet
|
||||
*/
|
||||
UnknownItems bool `json:"unknown_item"`
|
||||
}
|
||||
|
35
utils.go
Normal file
35
utils.go
Normal file
@ -0,0 +1,35 @@
|
||||
package gokwallet
|
||||
|
||||
/*
|
||||
resultCheck checks the result code from a Dbus call and returns an error if not successful.
|
||||
See also resultPassed.
|
||||
*/
|
||||
func resultCheck(result int32) (err error) {
|
||||
|
||||
// This is technically way more complex than it needs to be, but is extendable for future use.
|
||||
switch i := result; i {
|
||||
case DbusSuccess:
|
||||
err = nil
|
||||
case DbusFailure:
|
||||
err = ErrOperationFailed
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
resultPassed checks the result code from a Dbus call and returns a boolean as to whether the result is pass or not.
|
||||
See also resultCheck.
|
||||
*/
|
||||
func resultPassed(result int32) (passed bool) {
|
||||
|
||||
// This is technically way more complex than it needs to be, but is extendable for future use.
|
||||
switch i := result; i {
|
||||
case DbusSuccess:
|
||||
passed = true
|
||||
case DbusFailure:
|
||||
passed = false
|
||||
}
|
||||
|
||||
return
|
||||
}
|
189
wallet_funcs.go
189
wallet_funcs.go
@ -1,14 +1,191 @@
|
||||
package gokwallet
|
||||
|
||||
import (
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
/*
|
||||
NewWallet returns a Wallet. It requires a RecurseOpts
|
||||
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||
It also requires a WalletManager and wallet name.
|
||||
*/
|
||||
func NewWallet(wm *WalletManager, name string, recursion *RecurseOpts) (wallet *Wallet, err error) {
|
||||
|
||||
func NewWallet(wm *WalletManager, path dbus.ObjectPath) (wallet *Wallet, err error) {
|
||||
if !wm.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
var open bool
|
||||
wallet = &Wallet{
|
||||
DbusObject: wm.DbusObject,
|
||||
Name: name,
|
||||
Folders: nil,
|
||||
Recurse: recursion,
|
||||
wm: wm,
|
||||
// handle: 0,
|
||||
isInit: false,
|
||||
}
|
||||
|
||||
_ = open
|
||||
// TODO: remove this and leave to caller, since it might use PamOpen instead? Fail back to it?
|
||||
if err = wallet.walletCheck(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if wallet.Recurse.All || wallet.Recurse.Wallets {
|
||||
if err = wallet.Update(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
wallet.isInit = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Close closes a Wallet.
|
||||
func (w *Wallet) Close() (err error) {
|
||||
|
||||
var rslt int32
|
||||
|
||||
if !w.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||
if err = w.Dbus.Call(
|
||||
DbusWMClose, 0, w.handle, false, w.wm.AppID,
|
||||
).Store(&rslt); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = resultCheck(rslt)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
ForceClose is like Close but will still close a Wallet even if currently in use by the WalletManager.
|
||||
(Despite the insinuation by the name, this should be a relatively safe operation).
|
||||
*/
|
||||
func (w *Wallet) ForceClose() (err error) {
|
||||
|
||||
var rslt int32
|
||||
|
||||
if !w.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||
if err = w.Dbus.Call(
|
||||
DbusWMClose, 0, w.handle, true, w.wm.AppID,
|
||||
).Store(&rslt); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = resultCheck(rslt)
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// IsOpen returns whether a Wallet is open ("unlocked") or not (as well as updates Wallet.IsOpen).
|
||||
func (w *Wallet) IsOpen() (isOpen bool, err error) {
|
||||
|
||||
// We can call the same method with w.handle instead of w.Name. We don't have a handler yet though.
|
||||
if err = w.Dbus.Call(
|
||||
DbusWMIsOpen, 0, w.Name,
|
||||
).Store(&w.IsUnlocked); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
isOpen = w.IsUnlocked
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListFolders lists all Folder names in a Wallet.
|
||||
func (w *Wallet) ListFolders() (folderList []string, err error) {
|
||||
|
||||
if err = w.walletCheck(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = w.Dbus.Call(
|
||||
DbusWMFolderList, 0, w.handle, w.wm.AppID,
|
||||
).Store(&folderList); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
Open will open ("unlock") a Wallet.
|
||||
It will no-op if the Wallet is already open.
|
||||
*/
|
||||
func (w *Wallet) Open() (err error) {
|
||||
|
||||
if _, err = w.IsOpen(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !w.IsUnlocked {
|
||||
if err = w.Dbus.Call(
|
||||
DbusWMOpen, 0,
|
||||
).Store(&w.handle); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
w.IsUnlocked = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Update fetches/updates all Folder objects in a Wallet.
|
||||
func (w *Wallet) Update() (err error) {
|
||||
|
||||
var folderNames []string
|
||||
var errs []error = make([]error, 0)
|
||||
|
||||
if folderNames, err = w.ListFolders(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
w.Folders = make(map[string]*Folder)
|
||||
|
||||
for _, fn := range folderNames {
|
||||
if w.Folders[fn], err = NewFolder(w, fn, w.Recurse); err != nil {
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if errs != nil && len(errs) > 0 {
|
||||
err = NewErrors(errs...)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// walletCheck will check if a Wallet is (initialized and) opened and, if not, attempt to open it.
|
||||
func (w *Wallet) walletCheck() (err error) {
|
||||
|
||||
if !w.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = w.IsOpen(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !w.IsUnlocked {
|
||||
if err = w.Open(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -5,11 +5,12 @@ import (
|
||||
)
|
||||
|
||||
/*
|
||||
NewWalletManager returns a WalletManager.
|
||||
NewWalletManager returns a WalletManager. It requires a RecurseOpts
|
||||
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||
If appId is empty/nil, DefaultAppID will be used as the app ID.
|
||||
If appId is specified, only the first string is used.
|
||||
*/
|
||||
func NewWalletManager(appID ...string) (wm *WalletManager, err error) {
|
||||
func NewWalletManager(recursion *RecurseOpts, appID ...string) (wm *WalletManager, err error) {
|
||||
|
||||
var realAppID string
|
||||
|
||||
@ -19,13 +20,245 @@ func NewWalletManager(appID ...string) (wm *WalletManager, err error) {
|
||||
realAppID = DefaultAppID
|
||||
}
|
||||
|
||||
if wm, err = newWM(realAppID, recursion); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
NewWalletManagerFiles returns a WalletManager from one or more filePaths (*.kwl, *.tar, or *.xml exports).
|
||||
Note that if the wallet file was created via an "encrypted export", it will be a .kwl file
|
||||
inside a .tar.
|
||||
err will contain a MultiError if any filepaths specified do not exist or cannot be opened.
|
||||
It requires a RecurseOpts (you can use DefaultRecurseOpts, call NewRecurseOpts,
|
||||
or provide your own RecurseOpts struct).
|
||||
If appId is empty, DefaultAppID will be used as the app ID.
|
||||
*/
|
||||
/* TODO: POC this before exposing. I have NO idea if it'll work.
|
||||
func NewWalletManagerFiles(recursion *RecurseOpts, appId string, filePaths ...string) (wm *WalletManager, err error) {
|
||||
|
||||
var exist bool
|
||||
var errs []error = make([]error, 0)
|
||||
var realFilePaths []string = make([]string, 0)
|
||||
|
||||
if appId == "" {
|
||||
appId = DefaultAppID
|
||||
}
|
||||
|
||||
for _, f := range filePaths {
|
||||
if f == "" {
|
||||
continue
|
||||
}
|
||||
if exist, err = paths.RealPathExists(&f); err != nil {
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
if !exist {
|
||||
err = errors.New(fmt.Sprintf("%v does not exist", f))
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
realFilePaths = append(realFilePaths, f)
|
||||
}
|
||||
|
||||
// TODO: do the actual newWM here.
|
||||
|
||||
if errs != nil && len(errs) > 0 {
|
||||
err = NewErrors(errs...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
CloseWallet closes a Wallet.
|
||||
Unlike Wallet.Close, this closes access for ALL applications/WalletManagers
|
||||
for the specified Wallet - not just this WalletManager.
|
||||
*/
|
||||
func (wm *WalletManager) CloseWallet(walletName string) (err error) {
|
||||
var rslt int32
|
||||
|
||||
if !wm.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||
if err = wm.Dbus.Call(
|
||||
DbusWMClose, 0, walletName, false,
|
||||
).Store(&rslt); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = resultCheck(rslt)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
ForceCloseWallet is like WalletManager.CloseWallet but will still close a Wallet even if currently in use.
|
||||
Unlike Wallet.ForceClose, this closes access for ALL applications/WalletManagers
|
||||
for the specified Wallet - not just this WalletManager.
|
||||
*/
|
||||
func (wm *WalletManager) FprceCloseWallet(walletName string) (err error) {
|
||||
|
||||
var rslt int32
|
||||
|
||||
if !wm.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||
if err = wm.Dbus.Call(
|
||||
DbusWMClose, 0, walletName, false,
|
||||
).Store(&rslt); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = resultCheck(rslt)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CloseAllWallets closes all Wallet objects. They do *not* need to be part of WalletManager.Wallets.
|
||||
func (wm *WalletManager) CloseAllWallets() (err error) {
|
||||
|
||||
var call *dbus.Call
|
||||
|
||||
if !wm.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
call = wm.Dbus.Call(
|
||||
DbusWMCloseAllWallets, 0,
|
||||
)
|
||||
err = call.Err
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// IsEnabled returns whether KWallet is enabled or not (and also updates WalletManager.Enabled).
|
||||
func (wm *WalletManager) IsEnabled() (enabled bool, err error) {
|
||||
|
||||
if !wm.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
if err = wm.Dbus.Call(
|
||||
DbusWMIsEnabled, 0,
|
||||
).Store(&wm.Enabled); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
enabled = wm.Enabled
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// LocalWallet returns the "local" wallet (and updates WalletManager.Local).
|
||||
func (wm *WalletManager) LocalWallet() (w *Wallet, err error) {
|
||||
|
||||
var wn string
|
||||
|
||||
if err = wm.Dbus.Call(
|
||||
DbusWMLocalWallet, 0,
|
||||
).Store(&wn); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if w, err = NewWallet(wm, wn, wm.Recurse); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
wm.Local = w
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NetworkWallet returns the "network" wallet (and updates WalletManager.Network).
|
||||
func (wm *WalletManager) NetworkWallet() (w *Wallet, err error) {
|
||||
|
||||
var wn string
|
||||
|
||||
if err = wm.Dbus.Call(
|
||||
DbusWMNetWallet, 0,
|
||||
).Store(&wn); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if w, err = NewWallet(wm, wn, wm.Recurse); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
wm.Network = w
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// WalletNames returns a list of available Wallet names.
|
||||
func (wm *WalletManager) WalletNames() (wallets []string, err error) {
|
||||
|
||||
if err = wm.Dbus.Call(
|
||||
DbusWMWallets, 0,
|
||||
).Store(&wallets); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Update fetches/updates all Wallet objects in a WalletManager.
|
||||
func (wm *WalletManager) Update() (err error) {
|
||||
|
||||
var walletNames []string
|
||||
var errs []error = make([]error, 0)
|
||||
|
||||
if !wm.isInit {
|
||||
err = ErrNotInitialized
|
||||
return
|
||||
}
|
||||
|
||||
if walletNames, err = wm.WalletNames(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
wm.Wallets = make(map[string]*Wallet)
|
||||
|
||||
for _, wn := range walletNames {
|
||||
|
||||
if wm.Wallets[wn], err = NewWallet(wm, wn, wm.Recurse); err != nil {
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if errs != nil && len(errs) > 0 {
|
||||
err = NewErrors(errs...)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// newWM is what does the heavy lifting behind NewWalletManager and NewWalletManagerFiles.
|
||||
func newWM(appId string, recursion *RecurseOpts, filePaths ...string) (wm *WalletManager, err error) {
|
||||
|
||||
wm = &WalletManager{
|
||||
DbusObject: &DbusObject{
|
||||
Conn: nil,
|
||||
Dbus: nil,
|
||||
},
|
||||
AppID: realAppID,
|
||||
Wallets: make(map[string]*Wallet),
|
||||
AppID: appId,
|
||||
Wallets: nil,
|
||||
Recurse: recursion,
|
||||
}
|
||||
|
||||
if wm.DbusObject.Conn, err = dbus.SessionBus(); err != nil {
|
||||
@ -33,18 +266,19 @@ func NewWalletManager(appID ...string) (wm *WalletManager, err error) {
|
||||
}
|
||||
wm.DbusObject.Dbus = wm.DbusObject.Conn.Object(DbusService, dbus.ObjectPath(DbusPath))
|
||||
|
||||
return
|
||||
}
|
||||
if wm.Recurse.All || wm.Recurse.Wallets {
|
||||
if err = wm.Update(); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = wm.LocalWallet(); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = wm.NetworkWallet(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Update fetches/updates all Wallet objects in a WalletManager.
|
||||
*/
|
||||
func (wm *WalletManager) Update() (err error) {
|
||||
|
||||
var wallets []*Wallet
|
||||
|
||||
// TODO.
|
||||
_ = wallets
|
||||
wm.isInit = true
|
||||
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user