lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 72b0b77e9bb4ea20ed6f59e953371e8d59e0767e
parent 108b72ed9d805d088ad5ebbe0c8eb9495ad07432
Author: Sean Enck <sean@ttypty.com>
Date:   Sat,  5 Oct 2024 11:28:59 -0400

allow restricting character set

Diffstat:
Minternal/app/core_test.go | 2+-
Minternal/app/pwgen.go | 21+++++++++++++++++++++
Minternal/app/pwgen_test.go | 6++++++
Minternal/config/vars.go | 12++++++++++++
Minternal/config/vars_test.go | 2+-
5 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/internal/app/core_test.go b/internal/app/core_test.go @@ -13,7 +13,7 @@ func TestUsage(t *testing.T) { t.Errorf("invalid usage, out of date? %d", len(u)) } u, _ = app.Usage(true, "lb") - if len(u) != 114 { + if len(u) != 115 { t.Errorf("invalid verbose usage, out of date? %d", len(u)) } for _, usage := range u { diff --git a/internal/app/pwgen.go b/internal/app/pwgen.go @@ -6,6 +6,7 @@ import ( "fmt" "math/rand" "os/exec" + "slices" "strings" "text/template" @@ -55,6 +56,14 @@ func GeneratePassword(cmd CommandOptions) error { if err != nil { return err } + chars := config.EnvPasswordGenChars.Get() + hasChars := len(chars) > 0 + var allowedChars []rune + if hasChars { + for _, c := range chars { + allowedChars = append(allowedChars, c) + } + } caser := cases.Title(lang) var choices []string for _, line := range strings.Split(string(wordResults), "\n") { @@ -63,6 +72,18 @@ func GeneratePassword(cmd CommandOptions) error { continue } use := line + if hasChars { + res := "" + for _, c := range use { + if slices.Contains(allowedChars, c) { + res = fmt.Sprintf("%s%c", res, c) + } + } + if res == "" { + continue + } + use = res + } if capitalize { use = caser.String(use) } diff --git a/internal/app/pwgen_test.go b/internal/app/pwgen_test.go @@ -80,6 +80,12 @@ func TestGenerate(t *testing.T) { os.Setenv("LOCKBOX_PWGEN_TITLE", "yes") os.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s a a a a a a a a a a a a a a a", pwgenPath)) testPasswordGen(t, "A-A-A-A") + os.Setenv("LOCKBOX_PWGEN_CHARS", "bc") + os.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s abc abc abc abc abc aaa aaa aa a", pwgenPath)) + testPasswordGen(t, "Bc-Bc-Bc-Bc") + os.Unsetenv("LOCKBOX_PWGEN_CHARS") + os.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s a a a a a a a a a a a a a a a", pwgenPath)) + os.Setenv("LOCKBOX_PWGEN_TITLE", "no") os.Setenv("LOCKBOX_PWGEN_TITLE", "no") testPasswordGen(t, "a-a-a-a") // NOTE: this allows templating below in golang diff --git a/internal/config/vars.go b/internal/config/vars.go @@ -390,6 +390,18 @@ This value can NOT be an expansion itself.`, desc: "Disable password generation.", }), }) + // EnvPasswordGenChars allows for restricting which characters can be used + EnvPasswordGenChars = environmentRegister( + EnvironmentString{ + environmentDefault: newDefaultedEnvironment("", + environmentBase{ + subKey: "CHARS", + cat: genCategory, + desc: "The set of allowed characters in output words (empty means any characters are allowed).", + }), + allowed: []string{"<list of characters>"}, + canDefault: true, + }) ) // GetReKey will get the rekey environment settings diff --git a/internal/config/vars_test.go b/internal/config/vars_test.go @@ -105,7 +105,7 @@ func TestListVariables(t *testing.T) { known[trim] = struct{}{} } l := len(known) - if l != 32 { + if l != 33 { t.Errorf("invalid env count, outdated? %d", l) } }