diff --git a/cmd/ppass/ppass.go b/cmd/ppass/ppass.go index cf4058b..758e779 100644 --- a/cmd/ppass/ppass.go +++ b/cmd/ppass/ppass.go @@ -37,8 +37,8 @@ var listCmd = &cobra.Command{ } var names []string - namespace := "root" - err = client.Call("Query.GetAllNames", &namespace, &names) + vault := "root" + err = client.Call("Query.GetAllNames", &vault, &names) if err != nil { Logger.Error(err) @@ -67,14 +67,14 @@ var generateCmd = &cobra.Command{ serviceName := args[0] var password *crypto.Password - np := rpc.NamespaceService{ Namespace: "root", Service: serviceName } + np := rpc.VaultService{ Vault: "root", Service: serviceName } err = client.Call("Query.Generate", &np, &password) if err != nil { Logger.Error(err) } - Logger.Info(*password) + Logger.Info(password.Password) }, } @@ -94,7 +94,7 @@ var showCmd = &cobra.Command{ serviceName := args[0] var password *crypto.Password - np := rpc.NamespaceService{ Namespace: "root", Service: serviceName } + np := rpc.VaultService{ Vault: "root", Service: serviceName } err = client.Call("Query.Get", &np, &password) if err != nil { @@ -106,14 +106,14 @@ var showCmd = &cobra.Command{ }, } -var namespaceCmd = &cobra.Command{ - Use: "namespace", - Short: "Add, delete or list namespaces", +var vaultCmd = &cobra.Command{ + Use: "vault", + Short: "Add, delete or list vaults", } -var addNamespaceCmd = &cobra.Command{ +var addVaultCmd = &cobra.Command{ Use: "add", - Short: "add a namespace", + Short: "add a vault", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { dbPath, _ := cmd.Flags().GetString("db") @@ -124,23 +124,23 @@ var addNamespaceCmd = &cobra.Command{ return } - namespace := args[0] + vault := args[0] var placeholder int - err = client.Call("Query.AddNamespace", &namespace, &placeholder) + err = client.Call("Query.AddVault", &vault, &placeholder) if err != nil { Logger.Error(err) return } - Logger.Infof("Namespace %s was added\n", namespace) + Logger.Infof("Vault %s was added\n", vault) }, } -var deleteNamespaceCmd = &cobra.Command{ +var deleteVaultCmd = &cobra.Command{ Use: "delete", - Short: "delete a namespace", + Short: "delete a vault", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { dbPath, _ := cmd.Flags().GetString("db") @@ -151,23 +151,23 @@ var deleteNamespaceCmd = &cobra.Command{ return } - namespace := args[0] + vault := args[0] var placeholder int - err = client.Call("Query.DeleteNamespace", &namespace, &placeholder) + err = client.Call("Query.DeleteVault", &vault, &placeholder) if err != nil { Logger.Error(err) return } - Logger.Infof("Namespace %s was deleted\n", namespace) + Logger.Infof("Vault %s was deleted\n", vault) }, } -var listNamespacesCmd = &cobra.Command{ +var listVaultsCmd = &cobra.Command{ Use: "list", - Short: "list all namespaces", + Short: "list all vaults", Run: func(cmd *cobra.Command, args []string) { dbPath, _ := cmd.Flags().GetString("db") client, err := rpc.Receive(dbPath) @@ -178,14 +178,14 @@ var listNamespacesCmd = &cobra.Command{ } var reply []string - err = client.Call("Query.ListNamespaces", 0, &reply) + err = client.Call("Query.ListVaults", 0, &reply) if err != nil { Logger.Error(err) return } - Logger.Info("Namespaces:") + Logger.Info("Vaults:") for _, ns := range reply { Logger.Info(ns) } @@ -230,19 +230,19 @@ var addPeerCmd = &cobra.Command{ return } - var namespace string + var vault string var peerString string if len(args) == 1 { - namespace = "root" + vault = "root" peerString = args[0] } else { - namespace = args[0] + vault = args[0] peerString = args[1] } var success *bool - np := rpc.NamespacePeer{ Namespace: namespace, Peer: peerString } + np := rpc.VaultPeer{ Vault: vault, Peer: peerString } err = client.Call("Query.AddPeer", &np, &success) if err != nil { @@ -250,7 +250,11 @@ var addPeerCmd = &cobra.Command{ return } - Logger.Info(*success) + if *success { + Logger.Infof("Added peer: %s", peerString) + } else { + Logger.Infof("Could not add peer: %s", peerString) + } }, } @@ -267,19 +271,19 @@ var removePeerCmd = &cobra.Command{ return } - var namespace string + var vault string var peerString string if len(args) == 1 { - namespace = "root" + vault = "root" peerString = args[0] } else { - namespace = args[0] + vault = args[0] peerString = args[1] } var success *bool - np := rpc.NamespacePeer{ Namespace: namespace, Peer: peerString } + np := rpc.VaultPeer{ Vault: vault, Peer: peerString } err = client.Call("Query.DeletePeer", &np, &success) if err != nil { @@ -287,7 +291,11 @@ var removePeerCmd = &cobra.Command{ return } - Logger.Info(*success) + if *success { + Logger.Infof("Removed peer: %s", peerString) + } else { + Logger.Infof("Could not find peer: %s", peerString) + } }, } @@ -304,26 +312,30 @@ var deleteCmd = &cobra.Command{ return } - var namespace string + var vault string var serviceName string if len(args) == 1 { - namespace = "root" + vault = "root" serviceName = args[0] } else { - namespace = args[0] + vault = args[0] serviceName = args[1] } var success *bool - np := rpc.NamespaceService{ Namespace: namespace, Service: serviceName } + np := rpc.VaultService{ Vault: vault, Service: serviceName } err = client.Call("Query.Delete", &np, &success) if err != nil { Logger.Error(err) } - Logger.Info(*success) + if *success { + Logger.Infof("Deleted password: %s", serviceName) + } else { + Logger.Infof("Could not find password: %s", serviceName) + } }, } @@ -336,20 +348,20 @@ func init() { peerCmd.AddCommand(removePeerCmd) peerCmd.AddCommand(infoCmd) - namespaceCmd.AddCommand(addNamespaceCmd) - namespaceCmd.AddCommand(deleteNamespaceCmd) - namespaceCmd.AddCommand(listNamespacesCmd) + vaultCmd.AddCommand(addVaultCmd) + vaultCmd.AddCommand(deleteVaultCmd) + vaultCmd.AddCommand(listVaultsCmd) rootCmd.AddCommand(listCmd) rootCmd.AddCommand(generateCmd) rootCmd.AddCommand(showCmd) rootCmd.AddCommand(deleteCmd) rootCmd.AddCommand(peerCmd) - rootCmd.AddCommand(namespaceCmd) + rootCmd.AddCommand(vaultCmd) } func main() { - InitLogger(true) + InitLogger(false) if err := rootCmd.Execute(); err != nil { Logger.Error(err) os.Exit(1) diff --git a/cmd/ppassd/ppassd.go b/cmd/ppassd/ppassd.go index 89eb88b..bf2e93f 100644 --- a/cmd/ppassd/ppassd.go +++ b/cmd/ppassd/ppassd.go @@ -85,10 +85,10 @@ func main() { storageHandler.Config = Cfg storageHandler.ConfigPath = configPath - Logger.Infof("Setting up Namespaces...") - storageHandler.InitNamespaces() + Logger.Infof("Setting up Vaults...") + storageHandler.InitVaults() - for _, val := range storageHandler.Namespaces { + for _, val := range storageHandler.Vaults { defer val.Close() } diff --git a/internal/rpc/rpc.go b/internal/rpc/rpc.go index 182976b..655f658 100644 --- a/internal/rpc/rpc.go +++ b/internal/rpc/rpc.go @@ -20,21 +20,21 @@ var StorageHandler *storage.StorageHandler type Query int -type NamespaceService struct { - Namespace string +type VaultService struct { + Vault string Service string } -type NamespacePeer struct { - Namespace string +type VaultPeer struct { + Vault string Peer string } -func (t *Query) Generate(np *NamespaceService, reply *crypto.Password) error { - val, ok := StorageHandler.Namespaces[np.Namespace] +func (t *Query) Generate(np *VaultService, reply *crypto.Password) error { + val, ok := StorageHandler.Vaults[np.Vault] if !ok { - return fmt.Errorf("Namespace does not exist") + return fmt.Errorf("Vault does not exist") } password := crypto.NewPassword(crypto.DEFAULT_LENGTH) @@ -59,12 +59,12 @@ func (t *Query) Generate(np *NamespaceService, reply *crypto.Password) error { return nil } -func (t *Query) Get(np *NamespaceService, reply *crypto.Password) error { - namespace := np.Namespace - val, ok := StorageHandler.Namespaces[namespace] +func (t *Query) Get(np *VaultService, reply *crypto.Password) error { + vault := np.Vault + val, ok := StorageHandler.Vaults[vault] if !ok { - return fmt.Errorf("Namespace does not exist") + return fmt.Errorf("Vault does not exist") } v, err := val.GetPassword(np.Service) @@ -85,12 +85,12 @@ func (t *Query) GetPeerString(_ *int, result *string) error { return nil } -func (t *Query) AddPeer(np *NamespacePeer, success *bool) error { - namespace := np.Namespace - val, ok := StorageHandler.Namespaces[namespace] +func (t *Query) AddPeer(np *VaultPeer, success *bool) error { + vault := np.Vault + val, ok := StorageHandler.Vaults[vault] if !ok { - return fmt.Errorf("Namespace does not exist") + return fmt.Errorf("Vault does not exist") } peer, err := storage.PeerFromString(np.Peer) @@ -107,12 +107,12 @@ func (t *Query) AddPeer(np *NamespacePeer, success *bool) error { return nil } -func (t *Query) DeletePeer(np *NamespacePeer, success *bool) error { - namespace := np.Namespace - val, ok := StorageHandler.Namespaces[namespace] +func (t *Query) DeletePeer(np *VaultPeer, success *bool) error { + vault := np.Vault + val, ok := StorageHandler.Vaults[vault] if !ok { - return fmt.Errorf("Namespace does not exist") + return fmt.Errorf("Vault does not exist") } peer, err := storage.PeerFromString(np.Peer) @@ -129,12 +129,12 @@ func (t *Query) DeletePeer(np *NamespacePeer, success *bool) error { return nil } -func (t *Query) Delete(np *NamespaceService, success *bool) error { - namespace := np.Namespace - val, ok := StorageHandler.Namespaces[namespace] +func (t *Query) Delete(np *VaultService, success *bool) error { + vault := np.Vault + val, ok := StorageHandler.Vaults[vault] if !ok { - return fmt.Errorf("Namespace does not exist") + return fmt.Errorf("Vault does not exist") } err := val.Delete(np.Service) @@ -147,25 +147,25 @@ func (t *Query) Delete(np *NamespaceService, success *bool) error { return nil } -func (t *Query) AddNamespace(namespace *string, _ *int) error { - _, err := StorageHandler.AddNamespace(*namespace) +func (t *Query) AddVault(vault *string, _ *int) error { + _, err := StorageHandler.AddVault(*vault) return err } -func (t *Query) DeleteNamespace(namespace *string, _ *int) error { - err := StorageHandler.DeleteNamespace(*namespace) +func (t *Query) DeleteVault(vault *string, _ *int) error { + err := StorageHandler.DeleteVault(*vault) return err } -func (t *Query) ListNamespaces(_ *int, reply *[]string) error { - *reply = StorageHandler.ListNamespaces() +func (t *Query) ListVaults(_ *int, reply *[]string) error { + *reply = StorageHandler.ListVaults() return nil } -func (t *Query) GetAllNames(namespace *string, reply *[]string) error { - Logger.Infof("Listing content of %s", *namespace) +func (t *Query) GetAllNames(vault *string, reply *[]string) error { + Logger.Infof("Listing content of %s", *vault) - val, ok := StorageHandler.Namespaces[*namespace] + val, ok := StorageHandler.Vaults[*vault] if !ok { return fmt.Errorf("Namesapce does not exist") diff --git a/internal/storage/storage.go b/internal/storage/storage.go index a4ec146..17afc3d 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -11,7 +11,6 @@ import ( "sync" "strings" - "github.com/ipfs/go-datastore/query" "github.com/libp2p/go-libp2p" dht "github.com/libp2p/go-libp2p-kad-dht" pubsub "github.com/libp2p/go-libp2p-pubsub" @@ -21,7 +20,6 @@ import ( "github.com/libp2p/go-libp2p/core/network" //"github.com/libp2p/go-libp2p/core/peerstore" discovery "github.com/libp2p/go-libp2p/p2p/discovery/routing" - ds "github.com/ipfs/go-datastore" ipfslite "github.com/hsanjuan/ipfs-lite" "github.com/google/uuid" @@ -29,13 +27,10 @@ import ( badger "github.com/ipfs/go-ds-badger2" dsq "github.com/ipfs/go-datastore/query" - crdt "github.com/ipfs/go-ds-crdt" crypto "github.com/libp2p/go-libp2p/core/crypto" routed "github.com/libp2p/go-libp2p/p2p/host/routed" agelib "filippo.io/age" - password "github.com/k4lipso/pentapass/internal/crypto" - "github.com/k4lipso/pentapass/internal/crypto/age" . "github.com/k4lipso/pentapass/internal/log" ) @@ -107,13 +102,13 @@ type Peer struct { Key string `json:"Key"` } -type NamespaceConfig struct { +type VaultConfig struct { Name string `json:"Name"` Id string `json:"Id"` Peers []Peer `json:"Peers"` } -type Config []NamespaceConfig +type Config []VaultConfig type WhitelistConnectionGater struct { @@ -148,7 +143,7 @@ func (wg *WhitelistConnectionGater) InterceptUpgraded(conn network.Conn) (allow return wg.InterceptPeerDial(conn.RemotePeer()), 0 } -func GetTrustedPeers(config []NamespaceConfig) map[string][]Peer { +func GetTrustedPeers(config []VaultConfig) map[string][]Peer { result := make(map[string][]Peer) for _, c := range config { result[c.Id] = c.Peers @@ -161,16 +156,6 @@ func InitRootNs() { //TODO: check if "SharedKeyRegistry" key exists, if not create } -type Namespace struct { - ID string - Datastore *crdt.Datastore - //Registry *sharedKeyRegistry - CancelFunc context.CancelFunc - ctx context.Context - Key *agelib.X25519Identity - TrustedPeers []Peer -} - func PeerFromString(str string) (Peer, error) { parts := strings.Split(str, "/") @@ -182,183 +167,6 @@ func PeerFromString(str string) (Peer, error) { return Peer{ Id: parts[0], Key: parts[1] }, nil } -func (n *Namespace) AddPeer(peer Peer) { - for _, CurrentPeer := range n.TrustedPeers { - if CurrentPeer.Id == peer.Id && CurrentPeer.Key == peer.Key { - return - } - } - - n.TrustedPeers = append(n.TrustedPeers, peer) -} - -func (n *Namespace) RemovePeer(peer Peer) { - var Peers []Peer - for _, CurrentPeer := range n.TrustedPeers { - if CurrentPeer.Id == peer.Id && CurrentPeer.Key == peer.Key { - continue - } - - Peers = append(Peers, CurrentPeer) - } - - n.TrustedPeers = Peers -} - -func (n *Namespace) GetRecipients() []string { - var result []string - - for _, peer := range n.TrustedPeers { - result = append(result, peer.Key) - } - - return result -} - -func (n *Namespace) Put(k string, v string) error { - key := ds.NewKey(k) - err := n.Datastore.Put(n.ctx, key, []byte(v)) - - if err != nil { - printErr(err) - } - - return err -} - -func (n *Namespace) Delete(k string) error { - key := ds.NewKey(k) - err := n.Datastore.Delete(n.ctx, key) - - if err != nil { - printErr(err) - } - - return err -} - -func (n *Namespace) GetPassword(k string) (password.Password, error) { - v, err := n.Datastore.Get(n.ctx, ds.NewKey(k)) - if err != nil { - printErr(err) - return password.Password{}, err - } - - val, err := age.Decrypt(v, n.Key) - - if err != nil { - printErr(err) - return password.Password{}, err - } - - pw, err := password.GetPasswordFromJson(val) - - if err != nil { - printErr(err) - return password.Password{}, err - } - - return pw, nil -} - - -func (n *Namespace) Get(k string) (string, error) { - v, err := n.Datastore.Get(n.ctx, ds.NewKey(k)) - if err != nil { - printErr(err) - return "", err - } - - return string(v), nil -} - -func (n *Namespace) GetAllNames() []string { - q := query.Query{} - results, err := n.Datastore.Query(n.ctx, q) - - if err != nil { - printErr(err) - } - - var result []string - for r := range results.Next() { - if r.Error != nil { - printErr(err) - continue - } - - result = append(result, r.Key) - } - - return result -} - -func (n *Namespace) List() { - q := query.Query{} - results, err := n.Datastore.Query(n.ctx, q) - - if err != nil { - printErr(err) - } - - for r := range results.Next() { - if r.Error != nil { - printErr(err) - continue - } - - val, err := age.Decrypt(r.Value, n.Key) - - if err != nil { - printErr(err) - continue - } - - Logger.Infof("[%s] -> %s\n", r.Key, string(val)) - } -} - -func (n *Namespace) GetAllPasswords() ([]password.Password, error) { - q := query.Query{} - results, err := n.Datastore.Query(n.ctx, q) - - if err != nil { - return nil, fmt.Errorf("Error during GetAllPasswords: %s", err) - } - - var result []password.Password - - for r := range results.Next() { - if r.Error != nil { - printErr(err) - continue - } - - val, err := age.Decrypt(r.Value, n.Key) - - if err != nil { - printErr(err) - continue - } - - pw, err := password.GetPasswordFromJson(val) - - if err != nil { - printErr(err) - continue - } - - result = append(result, pw) - } - - return result, nil -} - -func (n *Namespace) Close() { - n.CancelFunc() - n.Datastore.Close() -} - type StorageHandler struct { Ctx context.Context Store *badger.Datastore @@ -366,8 +174,8 @@ type StorageHandler struct { Ipfs *ipfslite.Peer PubSub *pubsub.PubSub Key *agelib.X25519Identity - Config []NamespaceConfig - Namespaces map[string]*Namespace + Config []VaultConfig + Vaults map[string]*Vault ConfigPath string } @@ -385,21 +193,21 @@ func (s *StorageHandler) UpdateConfig() { } func (s *StorageHandler) recreateConfig() { - var newCfg []NamespaceConfig - for key, val := range s.Namespaces { - newCfg = append(newCfg, NamespaceConfig{ + var newCfg []VaultConfig + for key, val := range s.Vaults { + newCfg = append(newCfg, VaultConfig{ Name: key, Id: val.ID, Peers: val.TrustedPeers, }) } s.Config = newCfg - //for idx, namespaceConfig := range s.Config { - // s.Config[idx].Peers = s.Namespaces[namespaceConfig.Name].TrustedPeers + //for idx, vaultConfig := range s.Config { + // s.Config[idx].Peers = s.Vaults[vaultConfig.Name].TrustedPeers //} } -func (s *StorageHandler) writeConfig(filename string, config []NamespaceConfig) error { +func (s *StorageHandler) writeConfig(filename string, config []VaultConfig) error { jsonData, err := json.Marshal(config) if err != nil { @@ -416,9 +224,9 @@ func (s *StorageHandler) writeConfig(filename string, config []NamespaceConfig) return nil } -func (s *StorageHandler) NewConfig(filename string) ([]NamespaceConfig, error) { +func (s *StorageHandler) NewConfig(filename string) ([]VaultConfig, error) { if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) { - err := s.writeConfig(filename, []NamespaceConfig{ + err := s.writeConfig(filename, []VaultConfig{ { Name: "root", Id: uuid.New().String(), @@ -442,7 +250,7 @@ func (s *StorageHandler) NewConfig(filename string) ([]NamespaceConfig, error) { return nil, fmt.Errorf("Could not read config file: %s", err) } - var result []NamespaceConfig + var result []VaultConfig err = json.Unmarshal(content, &result) @@ -453,29 +261,29 @@ func (s *StorageHandler) NewConfig(filename string) ([]NamespaceConfig, error) { return result, nil } -func (s *StorageHandler) GetDefaultNamespace(Name string) *Namespace { - return s.Namespaces["root"] +func (s *StorageHandler) GetDefaultVault(Name string) *Vault { + return s.Vaults["root"] } -func (s *StorageHandler) InitNamespaces() { - NamespaceMap := make(map[string]*Namespace) +func (s *StorageHandler) InitVaults() { + VaultMap := make(map[string]*Vault) for _, nsCfg := range s.Config { - ns1, err := CreateNamespace(nsCfg.Id, s) + ns1, err := CreateVault(nsCfg.Id, s) if err != nil { Logger.Fatal(err) } - NamespaceMap[nsCfg.Name] = ns1 + VaultMap[nsCfg.Name] = ns1 } - s.Namespaces = NamespaceMap + s.Vaults = VaultMap } -func IsTrustedPeer(ctx context.Context, id peer.ID, namespace string, config []NamespaceConfig) bool { +func IsTrustedPeer(ctx context.Context, id peer.ID, vault string, config []VaultConfig) bool { peerMap := GetTrustedPeers(config) - val, ok := peerMap[namespace] + val, ok := peerMap[vault] if ok { for _, v := range val { @@ -498,100 +306,48 @@ func PrintDBContent(ctx context.Context, store *badger.Datastore) { } } -func (s *StorageHandler) ListNamespaces() []string { +func (s *StorageHandler) ListVaults() []string { var result []string - for k := range s.Namespaces { + for k := range s.Vaults { result = append(result, k) } return result } -func (s *StorageHandler) DeleteNamespace(ID string) error { - ns, ok := s.Namespaces[ID] +func (s *StorageHandler) DeleteVault(ID string) error { + ns, ok := s.Vaults[ID] if !ok { - Logger.Debug("DeleteNamespace that does not exists") + Logger.Debug("DeleteVault that does not exists") return nil } - delete(s.Namespaces, ID) + delete(s.Vaults, ID) ns.Close() s.UpdateConfig() return nil } -func (s *StorageHandler) AddNamespace(Name string) (*Namespace, error) { - ns, ok := s.Namespaces[Name] +func (s *StorageHandler) AddVault(Name string) (*Vault, error) { + ns, ok := s.Vaults[Name] if ok { return ns, nil } - result, err := CreateNamespace(uuid.New().String(), s) + result, err := CreateVault(uuid.New().String(), s) if err != nil { return nil, err } result.TrustedPeers = append(result.TrustedPeers, s.GetSelfPeer()) - s.Namespaces[Name] = result + s.Vaults[Name] = result s.UpdateConfig() return result, nil } -func CreateNamespace(ID string, storageHandler *StorageHandler) (*Namespace, error) { - Logger.Infof("Creating Namespace %s\n", ID) - err := storageHandler.PubSub.RegisterTopicValidator( - ID, //== topicName - func(ctx context.Context, id peer.ID, msg *pubsub.Message) bool { - Logger.Debugf("PubSubmsg TOPIC: %s, PEER: %s\n", ID, id) - signer := msg.GetFrom() - trusted := IsTrustedPeer(ctx, signer, ID, storageHandler.Config) - if !trusted { - Logger.Debugf("discarded pubsub message from non trusted source %s\n", signer) - } - return trusted - }, - ) - if err != nil { - Logger.Errorf("error registering topic validator: %s", err) - } - - psubCtx, psubCancel := context.WithCancel(storageHandler.Ctx) - pubsubBC, err := crdt.NewPubSubBroadcaster(psubCtx, storageHandler.PubSub, ID) - if err != nil { - Logger.Fatal(err) - } - - opts := crdt.DefaultOptions() - //opts.Logger = Logger - opts.RebroadcastInterval = 5 * time.Second - opts.PutHook = func(k ds.Key, v []byte) { - Logger.Infof("Added: [%s]\n", k) - } - opts.DeleteHook = func(k ds.Key) { - Logger.Infof("Removed: [%s]\n", k) - } - - crdt, err := crdt.New(storageHandler.Store, ds.NewKey(ID), storageHandler.Ipfs, pubsubBC, opts) - if err != nil { - Logger.Fatal(err) - psubCancel() - return nil, err - } - - PeerMap := GetTrustedPeers(storageHandler.Config) - - val, ok := PeerMap[ID] - - if !ok { - Logger.Debug("namespace config does not contain any peers") - } - - return &Namespace{ID: ID, Datastore: crdt, CancelFunc: psubCancel, ctx: storageHandler.Ctx, Key: storageHandler.Key, TrustedPeers: val}, nil -} - func initDHT(ctx context.Context, h host.Host) *dht.IpfsDHT { // Start a DHT, for use in peer discovery. We can't just make a new DHT diff --git a/internal/storage/vault.go b/internal/storage/vault.go new file mode 100644 index 0000000..b858628 --- /dev/null +++ b/internal/storage/vault.go @@ -0,0 +1,262 @@ +package storage + +import ( + "context" + "fmt" + "time" + + "github.com/ipfs/go-datastore/query" + pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p/core/peer" + ds "github.com/ipfs/go-datastore" + + crdt "github.com/ipfs/go-ds-crdt" + + agelib "filippo.io/age" + password "github.com/k4lipso/pentapass/internal/crypto" + "github.com/k4lipso/pentapass/internal/crypto/age" + . "github.com/k4lipso/pentapass/internal/log" +) + +type Vault struct { + ID string + Datastore *crdt.Datastore + //Registry *sharedKeyRegistry + CancelFunc context.CancelFunc + ctx context.Context + Key *agelib.X25519Identity + TrustedPeers []Peer +} + +func (n *Vault) AddPeer(peer Peer) { + for _, CurrentPeer := range n.TrustedPeers { + if CurrentPeer.Id == peer.Id && CurrentPeer.Key == peer.Key { + return + } + } + + n.TrustedPeers = append(n.TrustedPeers, peer) +} + +func (n *Vault) RemovePeer(peer Peer) { + var Peers []Peer + for _, CurrentPeer := range n.TrustedPeers { + if CurrentPeer.Id == peer.Id && CurrentPeer.Key == peer.Key { + continue + } + + Peers = append(Peers, CurrentPeer) + } + + n.TrustedPeers = Peers +} + +func (n *Vault) GetRecipients() []string { + var result []string + + for _, peer := range n.TrustedPeers { + result = append(result, peer.Key) + } + + return result +} + +func (n *Vault) Put(k string, v string) error { + key := ds.NewKey(k) + err := n.Datastore.Put(n.ctx, key, []byte(v)) + + if err != nil { + printErr(err) + } + + return err +} + +func (n *Vault) Delete(k string) error { + key := ds.NewKey(k) + err := n.Datastore.Delete(n.ctx, key) + + if err != nil { + printErr(err) + } + + return err +} + +func (n *Vault) GetPassword(k string) (password.Password, error) { + v, err := n.Datastore.Get(n.ctx, ds.NewKey(k)) + if err != nil { + printErr(err) + return password.Password{}, err + } + + val, err := age.Decrypt(v, n.Key) + + if err != nil { + printErr(err) + return password.Password{}, err + } + + pw, err := password.GetPasswordFromJson(val) + + if err != nil { + printErr(err) + return password.Password{}, err + } + + return pw, nil +} + + +func (n *Vault) Get(k string) (string, error) { + v, err := n.Datastore.Get(n.ctx, ds.NewKey(k)) + if err != nil { + printErr(err) + return "", err + } + + return string(v), nil +} + +func (n *Vault) GetAllNames() []string { + q := query.Query{} + results, err := n.Datastore.Query(n.ctx, q) + + if err != nil { + printErr(err) + } + + var result []string + for r := range results.Next() { + if r.Error != nil { + printErr(err) + continue + } + + result = append(result, r.Key) + } + + return result +} + +func (n *Vault) List() { + q := query.Query{} + results, err := n.Datastore.Query(n.ctx, q) + + if err != nil { + printErr(err) + } + + for r := range results.Next() { + if r.Error != nil { + printErr(err) + continue + } + + val, err := age.Decrypt(r.Value, n.Key) + + if err != nil { + printErr(err) + continue + } + + Logger.Infof("[%s] -> %s\n", r.Key, string(val)) + } +} + +func (n *Vault) GetAllPasswords() ([]password.Password, error) { + q := query.Query{} + results, err := n.Datastore.Query(n.ctx, q) + + if err != nil { + return nil, fmt.Errorf("Error during GetAllPasswords: %s", err) + } + + var result []password.Password + + for r := range results.Next() { + if r.Error != nil { + printErr(err) + continue + } + + val, err := age.Decrypt(r.Value, n.Key) + + if err != nil { + printErr(err) + continue + } + + pw, err := password.GetPasswordFromJson(val) + + if err != nil { + printErr(err) + continue + } + + result = append(result, pw) + } + + return result, nil +} + +func (n *Vault) Close() { + n.CancelFunc() + n.Datastore.Close() +} + +func CreateVault(ID string, storageHandler *StorageHandler) (*Vault, error) { + Logger.Infof("Creating Vault %s\n", ID) + err := storageHandler.PubSub.RegisterTopicValidator( + ID, //== topicName + func(ctx context.Context, id peer.ID, msg *pubsub.Message) bool { + if id == storageHandler.Host.ID() { + return false + } + + Logger.Debugf("PubSubmsg TOPIC: %s, PEER: %s\n", ID, id) + trusted := IsTrustedPeer(ctx, id, ID, storageHandler.Config) + if !trusted { + Logger.Debugf("discarded pubsub message from non trusted source %s\n", id) + } + return trusted + }, + ) + if err != nil { + Logger.Errorf("error registering topic validator: %s", err) + } + + psubCtx, psubCancel := context.WithCancel(storageHandler.Ctx) + pubsubBC, err := crdt.NewPubSubBroadcaster(psubCtx, storageHandler.PubSub, ID) + if err != nil { + Logger.Fatal(err) + } + + opts := crdt.DefaultOptions() + //opts.Logger = Logger + opts.RebroadcastInterval = 5 * time.Second + opts.PutHook = func(k ds.Key, v []byte) { + Logger.Infof("Added: [%s]\n", k) + } + opts.DeleteHook = func(k ds.Key) { + Logger.Infof("Removed: [%s]\n", k) + } + + crdt, err := crdt.New(storageHandler.Store, ds.NewKey(ID), storageHandler.Ipfs, pubsubBC, opts) + if err != nil { + Logger.Fatal(err) + psubCancel() + return nil, err + } + + PeerMap := GetTrustedPeers(storageHandler.Config) + + val, ok := PeerMap[ID] + + if !ok { + Logger.Debug("vault config does not contain any peers") + } + + return &Vault{ID: ID, Datastore: crdt, CancelFunc: psubCancel, ctx: storageHandler.Ctx, Key: storageHandler.Key, TrustedPeers: val}, nil +} +