@marcel91200 / caddy Mirror · read-only
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 11, 01:00 UTC

master
go 97 lines 2.85 KB
Raw
1 // Copyright 2015 Matthew Holt and The Caddy Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package caddyauth
16
17 import (
18 "io"
19 "os"
20 "strings"
21 "testing"
22
23 "github.com/spf13/pflag"
24 "golang.org/x/crypto/bcrypt"
25
26 caddycmd "github.com/caddyserver/caddy/v2/cmd"
27 )
28
29 func TestHashPasswordFromStdin(t *testing.T) {
30 for _, algorithm := range []string{bcryptName, argon2idName} {
31 for _, tc := range []struct{ input, password string }{
32 {"secret\n", "secret"},
33 {"secret\r\n", "secret"},
34 {"secret", "secret"},
35 {"secret\r", "secret\r"}, // no line ending, so the \r is part of the password
36 } {
37 name := algorithm + "/" + strings.NewReplacer("\r", `\r`, "\n", `\n`).Replace(tc.input)
38 t.Run(name, func(t *testing.T) {
39 hash := hashPasswordWithStdin(t, algorithm, tc.input)
40 var ok bool
41 var err error
42 if algorithm == bcryptName {
43 ok, err = BcryptHash{}.Compare([]byte(hash), []byte(tc.password))
44 } else {
45 ok, err = Argon2idHash{}.Compare([]byte(hash), []byte(tc.password))
46 }
47 if err != nil || !ok {
48 t.Fatalf("hash %q does not match the password (err: %v)", hash, err)
49 }
50 })
51 }
52 }
53 }
54
55 // hashPasswordWithStdin runs the hash-password command with input
56 // piped to stdin and returns what it wrote to stdout.
57 func hashPasswordWithStdin(t *testing.T, algorithm, input string) string {
58 t.Helper()
59
60 stdinR, stdinW, err := os.Pipe()
61 if err != nil {
62 t.Fatal(err)
63 }
64 stdoutR, stdoutW, err := os.Pipe()
65 if err != nil {
66 t.Fatal(err)
67 }
68 origStdin, origStdout := os.Stdin, os.Stdout
69 os.Stdin, os.Stdout = stdinR, stdoutW
70 defer func() { os.Stdin, os.Stdout = origStdin, origStdout }()
71
72 if _, err := stdinW.WriteString(input); err != nil {
73 t.Fatal(err)
74 }
75 stdinW.Close()
76
77 fs := pflag.NewFlagSet("hash-password", pflag.ContinueOnError)
78 fs.String("plaintext", "", "")
79 fs.String("algorithm", algorithm, "")
80 fs.Int("bcrypt-cost", bcrypt.MinCost, "")
81 fs.Uint32("argon2id-time", defaultArgon2idTime, "")
82 fs.Uint32("argon2id-memory", defaultArgon2idMemory, "")
83 fs.Uint8("argon2id-threads", defaultArgon2idThreads, "")
84 fs.Uint32("argon2id-keylen", defaultArgon2idKeylen, "")
85
86 code, err := cmdHashPassword(caddycmd.Flags{FlagSet: fs})
87 stdoutW.Close()
88 if err != nil {
89 t.Fatalf("hash-password failed (exit code %d): %v", code, err)
90 }
91
92 out, err := io.ReadAll(stdoutR)
93 if err != nil {
94 t.Fatal(err)
95 }
96 return strings.TrimSpace(string(out))
97 }