mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-16 21:56:40 -05:00
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>
This commit is contained in:
parent
7960b4259d
commit
5bde8d705b
1 changed files with 42 additions and 3 deletions
|
@ -15,26 +15,34 @@
|
|||
package caddyauth
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
caddycmd "github.com/caddyserver/caddy/v2/cmd"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"golang.org/x/crypto/scrypt"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
func init() {
|
||||
caddycmd.RegisterCommand(caddycmd.Command{
|
||||
Name: "hash-password",
|
||||
Func: cmdHashPassword,
|
||||
Usage: "--plaintext <password> [--salt <string>] [--algorithm <name>]",
|
||||
Usage: "[--algorithm <name>] [--salt <string>] [--plaintext <password>]",
|
||||
Short: "Hashes a password and writes base64",
|
||||
Long: `
|
||||
Convenient way to hash a plaintext password. The resulting
|
||||
hash is written to stdout as a base64 string.
|
||||
|
||||
--plaintext, when omitted, will be read from stdin. If
|
||||
Caddy is attached to a controlling tty, the plaintext will
|
||||
not be echoed.
|
||||
|
||||
--algorithm may be bcrypt or scrypt. If script, the default
|
||||
parameters are used.
|
||||
|
||||
|
@ -52,16 +60,47 @@ be provided (scrypt).
|
|||
}
|
||||
|
||||
func cmdHashPassword(fs caddycmd.Flags) (int, error) {
|
||||
var err error
|
||||
|
||||
algorithm := fs.String("algorithm")
|
||||
plaintext := []byte(fs.String("plaintext"))
|
||||
salt := []byte(fs.String("salt"))
|
||||
|
||||
if len(plaintext) == 0 {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("password is required")
|
||||
if terminal.IsTerminal(int(os.Stdin.Fd())) {
|
||||
fmt.Print("Enter password: ")
|
||||
plaintext, err = terminal.ReadPassword(int(os.Stdin.Fd()))
|
||||
fmt.Println()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
fmt.Print("Confirm password: ")
|
||||
confirmation, err := terminal.ReadPassword(int(os.Stdin.Fd()))
|
||||
fmt.Println()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
if !bytes.Equal(plaintext, confirmation) {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("password does not match")
|
||||
}
|
||||
} else {
|
||||
rd := bufio.NewReader(os.Stdin)
|
||||
plaintext, err = rd.ReadBytes('\n')
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
plaintext = plaintext[:len(plaintext)-1] // Trailing newline
|
||||
}
|
||||
|
||||
if len(plaintext) == 0 {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("plaintext is required")
|
||||
}
|
||||
}
|
||||
|
||||
var hash []byte
|
||||
var err error
|
||||
switch algorithm {
|
||||
case "bcrypt":
|
||||
hash, err = bcrypt.GenerateFromPassword(plaintext, bcrypt.DefaultCost)
|
||||
|
|
Loading…
Reference in a new issue