commit 72b0b77e9bb4ea20ed6f59e953371e8d59e0767e
parent 108b72ed9d805d088ad5ebbe0c8eb9495ad07432
Author: Sean Enck <sean@ttypty.com>
Date: Sat, 5 Oct 2024 11:28:59 -0400
allow restricting character set
Diffstat:
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)
}
}