0ecaa7f40a
Signed-off-by: Dave Trombley <dave.trombley@gmail.com>
54 lines
1.5 KiB
Go
54 lines
1.5 KiB
Go
package basic
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"encoding/base64"
|
|
"encoding/csv"
|
|
"errors"
|
|
"os"
|
|
)
|
|
|
|
// ErrSHARequired - returned in error field of challenge when the htpasswd was not made using SHA1 algorithm.
|
|
// (SHA1 is considered obsolete but the alternative for htpasswd is MD5, or system crypt...)
|
|
var ErrSHARequired = errors.New("htpasswd file must use SHA (htpasswd -s)")
|
|
|
|
// HTPasswd - holds a path to a system .htpasswd file and the machinery to parse it.
|
|
type HTPasswd struct {
|
|
path string
|
|
reader *csv.Reader
|
|
}
|
|
|
|
// NewHTPasswd - Create a new HTPasswd with the given path to .htpasswd file.
|
|
func NewHTPasswd(htpath string) *HTPasswd {
|
|
return &HTPasswd{path: htpath}
|
|
}
|
|
|
|
// AuthenticateUser - Check a given user:password credential against the receiving HTPasswd's file.
|
|
func (htpasswd *HTPasswd) AuthenticateUser(user string, pwd string) (bool, error) {
|
|
|
|
// Hash the credential.
|
|
sha := sha1.New()
|
|
sha.Write([]byte(pwd))
|
|
hash := base64.StdEncoding.EncodeToString(sha.Sum(nil))
|
|
|
|
// Open the file.
|
|
in, err := os.Open(htpasswd.path)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// Parse the contents of the standard .htpasswd until we hit the end or find a match.
|
|
reader := csv.NewReader(in)
|
|
reader.Comma = ':'
|
|
reader.Comment = '#'
|
|
reader.TrimLeadingSpace = true
|
|
for entry, readerr := reader.Read(); entry != nil || readerr != nil; entry, readerr = reader.Read() {
|
|
if entry[0] == user {
|
|
if len(entry[1]) < 6 || entry[1][0:5] != "{SHA}" {
|
|
return false, ErrSHARequired
|
|
}
|
|
return entry[1][5:] == hash, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|