@marcel91200 / caddy Mirror · read-only / commits / 5bde8d70
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

cmd: hash-password: Support reading from stdin (#3373)

Closes #3365 * http: Add support in hash-password for reading from terminals/stdin * FIXUP: Run gofmt -s * FIXUP * FIXUP: Apply suggestions from code review Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * FIXUP Co-authored-by: Matt Holt <mholt@users.noreply.github.com>

Andrew Zhou committed May 11, 2020 at 15:10 UTC 5bde8d705b9c9cae6751ccf95b7b8acfc1bbb7f5
1 file changed +42 -3
modules/caddyhttp/caddyauth/command.go
+42 -3
@@ -15,26 +15,34 @@
15 package caddyauth
16
17 import (
18 + "bufio"
19 + "bytes"
20 "encoding/base64"
21 "flag"
22 "fmt"
23 + "os"
24
25 "github.com/caddyserver/caddy/v2"
26 caddycmd "github.com/caddyserver/caddy/v2/cmd"
27 "golang.org/x/crypto/bcrypt"
28 "golang.org/x/crypto/scrypt"
29 + "golang.org/x/crypto/ssh/terminal"
30 )
31
32 func init() {
33 caddycmd.RegisterCommand(caddycmd.Command{
34 Name: "hash-password",
35 Func: cmdHashPassword,
32 - Usage: "--plaintext <password> [--salt <string>] [--algorithm <name>]",
36 + Usage: "[--algorithm <name>] [--salt <string>] [--plaintext <password>]",
37 Short: "Hashes a password and writes base64",
38 Long: `
39 Convenient way to hash a plaintext password. The resulting
40 hash is written to stdout as a base64 string.
41
42 +--plaintext, when omitted, will be read from stdin. If
43 +Caddy is attached to a controlling tty, the plaintext will
44 +not be echoed.
45 +
46 --algorithm may be bcrypt or scrypt. If script, the default
47 parameters are used.
48
@@ -52,16 +60,47 @@ be provided (scrypt).
60 }
61
62 func cmdHashPassword(fs caddycmd.Flags) (int, error) {
63 + var err error
64 +
65 algorithm := fs.String("algorithm")
66 plaintext := []byte(fs.String("plaintext"))
67 salt := []byte(fs.String("salt"))
68
69 if len(plaintext) == 0 {
60 - return caddy.ExitCodeFailedStartup, fmt.Errorf("password is required")
70 + if terminal.IsTerminal(int(os.Stdin.Fd())) {
71 + fmt.Print("Enter password: ")
72 + plaintext, err = terminal.ReadPassword(int(os.Stdin.Fd()))
73 + fmt.Println()
74 + if err != nil {
75 + return caddy.ExitCodeFailedStartup, err
76 + }
77 +
78 + fmt.Print("Confirm password: ")
79 + confirmation, err := terminal.ReadPassword(int(os.Stdin.Fd()))
80 + fmt.Println()
81 + if err != nil {
82 + return caddy.ExitCodeFailedStartup, err
83 + }
84 +
85 + if !bytes.Equal(plaintext, confirmation) {
86 + return caddy.ExitCodeFailedStartup, fmt.Errorf("password does not match")
87 + }
88 + } else {
89 + rd := bufio.NewReader(os.Stdin)
90 + plaintext, err = rd.ReadBytes('\n')
91 + if err != nil {
92 + return caddy.ExitCodeFailedStartup, err
93 + }
94 +
95 + plaintext = plaintext[:len(plaintext)-1] // Trailing newline
96 + }
97 +
98 + if len(plaintext) == 0 {
99 + return caddy.ExitCodeFailedStartup, fmt.Errorf("plaintext is required")
100 + }
101 }
102
103 var hash []byte
64 - var err error
104 switch algorithm {
105 case "bcrypt":
106 hash, err = bcrypt.GenerateFromPassword(plaintext, bcrypt.DefaultCost)