diff --git a/galenectl/galenectl.go b/galenectl/galenectl.go index 05cfd2d..aee2de0 100644 --- a/galenectl/galenectl.go +++ b/galenectl/galenectl.go @@ -20,6 +20,7 @@ import ( "golang.org/x/crypto/bcrypt" "golang.org/x/crypto/pbkdf2" + "golang.org/x/term" "github.com/jech/galene/group" ) @@ -240,14 +241,15 @@ func setUsage(cmd *flag.FlagSet, cmdname string, format string, args ...any) { } func hashPasswordCmd(cmdname string, args []string) { - var algorithm string + var password, algorithm string var iterations, cost, length, saltlen int cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) setUsage(cmd, cmdname, - "%v [option...] %v [option...] password...\n", + "%v [option...] %v [option...]\n", os.Args[0], cmdname, ) + cmd.StringVar(&password, "password", "", "new `password`") cmd.StringVar(&algorithm, "type", "pbkdf2", "password `type`") cmd.IntVar(&iterations, "iterations", 4096, @@ -258,23 +260,31 @@ func hashPasswordCmd(cmdname string, args []string) { cmd.IntVar(&saltlen, "salt", 8, "salt `length` (pbkdf2)") cmd.Parse(args) - if cmd.NArg() == 0 { + if cmd.NArg() != 0 { cmd.Usage() os.Exit(1) } - for _, pw := range cmd.Args() { - p, err := makePassword( - pw, algorithm, iterations, length, saltlen, cost, - ) + if algorithm != "wildcard" && password == "" { + fmt.Fprint(os.Stdin, "New password: ") + pw, err := term.ReadPassword(int(os.Stdin.Fd())) + fmt.Println() if err != nil { - log.Fatalf("Make password: %v", err) - } - e := json.NewEncoder(os.Stdout) - err = e.Encode(p) - if err != nil { - log.Fatalf("Encode: %v", err) + log.Fatalf("ReadPassword: %v", err) } + password = string(pw) + } + + p, err := makePassword( + password, algorithm, iterations, length, saltlen, cost, + ) + if err != nil { + log.Fatalf("Make password: %v", err) + } + e := json.NewEncoder(os.Stdout) + err = e.Encode(p) + if err != nil { + log.Fatalf("Encode: %v", err) } } @@ -382,17 +392,18 @@ func deleteValue(url string) error { func setPasswordCmd(cmdname string, args []string) { var groupname, username string var wildcard bool - var algorithm string + var password, algorithm string var iterations, cost, length, saltlen int cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) setUsage(cmd, cmdname, - "%v [option...] %v [option...] password\n", + "%v [option...] %v [option...]\n", os.Args[0], cmdname, ) cmd.StringVar(&groupname, "group", "", "group `name`") cmd.StringVar(&username, "user", "", "user `name`") cmd.BoolVar(&wildcard, "wildcard", false, "set wildcard user's password") + cmd.StringVar(&password, "password", "", "new `password`") cmd.StringVar(&algorithm, "type", "pbkdf2", "password `type`") cmd.IntVar(&iterations, "iterations", 4096, @@ -403,7 +414,7 @@ func setPasswordCmd(cmdname string, args []string) { cmd.IntVar(&saltlen, "salt", 8, "salt `length` (pbkdf2)") cmd.Parse(args) - if cmd.NArg() != 1 { + if cmd.NArg() != 0 { cmd.Usage() os.Exit(1) } @@ -421,9 +432,18 @@ func setPasswordCmd(cmdname string, args []string) { os.Exit(1) } + if algorithm != "wildcard" && password == "" { + fmt.Fprint(os.Stdin, "New password: ") + pw, err := term.ReadPassword(int(os.Stdin.Fd())) + fmt.Println() + if err != nil { + log.Fatalf("ReadPassword: %v", err) + } + password = string(pw) + } + pw, err := makePassword( - cmd.Args()[0], - algorithm, iterations, length, saltlen, cost, + password, algorithm, iterations, length, saltlen, cost, ) if err != nil { log.Fatalf("Make password: %v", err) diff --git a/go.mod b/go.mod index b0e1088..ebe3c7e 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/pion/webrtc/v3 v3.3.1 golang.org/x/crypto v0.27.0 golang.org/x/sys v0.25.0 + golang.org/x/term v0.24.0 ) require ( diff --git a/go.sum b/go.sum index 664b277..88bd1ba 100644 --- a/go.sum +++ b/go.sum @@ -196,6 +196,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=