diff --git a/client/config.go b/client/config.go index a6ba0e5..4486c40 100644 --- a/client/config.go +++ b/client/config.go @@ -51,7 +51,7 @@ type Config struct { // Inner memoryPassword *memguard.LockedBuffer - additionalPasswords []string + additionalPasswords []*memguard.LockedBuffer me *Identity } @@ -130,5 +130,61 @@ func (c *Config) Clean() { c.memoryPassword.Destroy() c.memoryPassword = nil } - c.additionalPasswords = []string{} + for _, buf := range c.additionalPasswords { + if buf != nil { + buf.Destroy() + } + } + c.additionalPasswords = []*memguard.LockedBuffer{} +} + +// AddAdditionalPassword securely stores an additional password in protected memory +func (c *Config) AddAdditionalPassword(password string) { + buf := memguard.NewBufferFromBytes([]byte(password)) + c.additionalPasswords = append(c.additionalPasswords, buf) +} + +// GetAdditionalPasswords returns all additional passwords as strings +func (c *Config) GetAdditionalPasswords() ([]string, error) { + passwords := make([]string, 0, len(c.additionalPasswords)) + for _, buf := range c.additionalPasswords { + if buf == nil { + continue + } + passwords = append(passwords, string(buf.Bytes())) + } + return passwords, nil +} + +// GetAdditionalPasswordAt returns the password at the specified index +func (c *Config) GetAdditionalPasswordAt(index int) (string, error) { + if index < 0 || index >= len(c.additionalPasswords) { + return "", errors.New("index out of range") + } + if c.additionalPasswords[index] == nil { + return "", errors.New("password at index is nil") + } + return string(c.additionalPasswords[index].Bytes()), nil +} + +// RemoveAdditionalPasswordAt removes and destroys the password at the specified index +func (c *Config) RemoveAdditionalPasswordAt(index int) error { + if index < 0 || index >= len(c.additionalPasswords) { + return errors.New("index out of range") + } + if c.additionalPasswords[index] != nil { + c.additionalPasswords[index].Destroy() + } + c.additionalPasswords = append(c.additionalPasswords[:index], c.additionalPasswords[index+1:]...) + return nil +} + +// ClearAdditionalPasswords removes and destroys all additional passwords +func (c *Config) ClearAdditionalPasswords() { + for _, buf := range c.additionalPasswords { + if buf != nil { + buf.Destroy() + } + } + c.additionalPasswords = []*memguard.LockedBuffer{} } diff --git a/client/config_test.go b/client/config_test.go index b1a4db1..b3bf8c9 100644 --- a/client/config_test.go +++ b/client/config_test.go @@ -21,3 +21,61 @@ func TestConfigLoad(t *testing.T) { _ = GetConfig().Load("test.cfg") println(GetConfig().Chunksize) } + +func TestAdditionalPasswords(t *testing.T) { + c := GetConfig() + c.ClearAdditionalPasswords() + + // Test adding passwords + c.AddAdditionalPassword("password1") + c.AddAdditionalPassword("password2") + c.AddAdditionalPassword("password3") + + // Test getting all passwords + passwords, err := c.GetAdditionalPasswords() + if err != nil { + t.Fatalf("Failed to get passwords: %v", err) + } + if len(passwords) != 3 { + t.Fatalf("Expected 3 passwords, got %d", len(passwords)) + } + if passwords[0] != "password1" || passwords[1] != "password2" || passwords[2] != "password3" { + t.Fatalf("Password values don't match expected") + } + + // Test getting password at index + pass, err := c.GetAdditionalPasswordAt(1) + if err != nil { + t.Fatalf("Failed to get password at index 1: %v", err) + } + if pass != "password2" { + t.Fatalf("Expected 'password2', got '%s'", pass) + } + + // Test removing password at index + err = c.RemoveAdditionalPasswordAt(1) + if err != nil { + t.Fatalf("Failed to remove password: %v", err) + } + + passwords, err = c.GetAdditionalPasswords() + if err != nil { + t.Fatalf("Failed to get passwords after removal: %v", err) + } + if len(passwords) != 2 { + t.Fatalf("Expected 2 passwords after removal, got %d", len(passwords)) + } + if passwords[0] != "password1" || passwords[1] != "password3" { + t.Fatalf("Password values don't match expected after removal") + } + + // Test clearing all passwords + c.ClearAdditionalPasswords() + passwords, err = c.GetAdditionalPasswords() + if err != nil { + t.Fatalf("Failed to get passwords after clear: %v", err) + } + if len(passwords) != 0 { + t.Fatalf("Expected 0 passwords after clear, got %d", len(passwords)) + } +}