@marcel91200 / caddy Mirror · read-only / commits / 78e98c40
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

basicauth: Accept placeholders; move base64 decoding to provision

See https://caddy.community/t/v2-basicauth-bug/6738?u=matt

Matthew Holt committed Jan 7, 2020 at 08:50 UTC 78e98c40d35c0b3bc933886ce11cbf2d0cf44c99
2 files changed +32 -21
modules/caddyhttp/caddyauth/basicauth.go
+30 -5
@@ -15,6 +15,7 @@
15 package caddyauth
16
17 import (
18 + "encoding/base64"
19 "encoding/json"
20 "fmt"
21 "net/http"
@@ -66,12 +67,34 @@ func (hba *HTTPBasicAuth) Provision(ctx caddy.Context) error {
67 return fmt.Errorf("hash is required")
68 }
69
70 + repl := caddy.NewReplacer()
71 +
72 // load account list
73 hba.Accounts = make(map[string]Account)
71 - for _, acct := range hba.AccountList {
74 + for i, acct := range hba.AccountList {
75 if _, ok := hba.Accounts[acct.Username]; ok {
73 - return fmt.Errorf("username is not unique: %s", acct.Username)
76 + return fmt.Errorf("account %d: username is not unique: %s", i, acct.Username)
77 }
78 +
79 + acct.Username = repl.ReplaceAll(acct.Username, "")
80 + acct.Password = repl.ReplaceAll(string(acct.Password), "")
81 + acct.Salt = repl.ReplaceAll(string(acct.Salt), "")
82 +
83 + if acct.Username == "" || acct.Password == "" {
84 + return fmt.Errorf("account %d: username and password are required", i)
85 + }
86 +
87 + acct.password, err = base64.StdEncoding.DecodeString(acct.Password)
88 + if err != nil {
89 + return fmt.Errorf("base64-decoding password: %v", err)
90 + }
91 + if acct.Salt != "" {
92 + acct.salt, err = base64.StdEncoding.DecodeString(acct.Salt)
93 + if err != nil {
94 + return fmt.Errorf("base64-decoding salt: %v", err)
95 + }
96 + }
97 +
98 hba.Accounts[acct.Username] = acct
99 }
100 hba.AccountList = nil // allow GC to deallocate
@@ -104,7 +127,7 @@ func (hba HTTPBasicAuth) Authenticate(w http.ResponseWriter, req *http.Request)
127 // don't return early if account does not exist; we want
128 // to try to avoid side-channels that leak existence
129
107 - same, err := hba.Hash.Compare(account.Password, plaintextPassword, account.Salt)
130 + same, err := hba.Hash.Compare(account.password, plaintextPassword, account.salt)
131 if err != nil {
132 return User{}, false, err
133 }
@@ -134,11 +157,13 @@ type Account struct {
157 Username string `json:"username"`
158
159 // The user's hashed password, base64-encoded.
137 - Password []byte `json:"password"`
160 + Password string `json:"password"`
161
162 // The user's password salt, base64-encoded; for
163 // algorithms where external salt is needed.
141 - Salt []byte `json:"salt,omitempty"`
164 + Salt string `json:"salt,omitempty"`
165 +
166 + password, salt []byte
167 }
168
169 // Interface guards
modules/caddyhttp/caddyauth/caddyfile.go
+2 -16
@@ -15,8 +15,6 @@
15 package caddyauth
16
17 import (
18 - "encoding/base64"
19 -
18 "github.com/caddyserver/caddy/v2"
19 "github.com/caddyserver/caddy/v2/caddyconfig"
20 "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
@@ -76,22 +74,10 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
74 return nil, h.Err("username and password cannot be empty or missing")
75 }
76
79 - pwd, err := base64.StdEncoding.DecodeString(b64Pwd)
80 - if err != nil {
81 - return nil, h.Errf("decoding password: %v", err)
82 - }
83 - var salt []byte
84 - if b64Salt != "" {
85 - salt, err = base64.StdEncoding.DecodeString(b64Salt)
86 - if err != nil {
87 - return nil, h.Errf("decoding salt: %v", err)
88 - }
89 - }
90 -
77 ba.AccountList = append(ba.AccountList, Account{
78 Username: username,
93 - Password: pwd,
94 - Salt: salt,
79 + Password: b64Pwd,
80 + Salt: b64Salt,
81 })
82 }
83 }