+/*
+godlighty -- highly-customizable HTTP, HTTP/2, HTTPS server
+Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package godlighty
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strings"
+)
+
+var Unauthorized = errors.New("failed authorization")
+
+func performAuth(w http.ResponseWriter, r *http.Request, cfg *AuthCfg) (string, error) {
+ username, password, ok := r.BasicAuth()
+ if !ok {
+ w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, cfg.Realm))
+ w.WriteHeader(http.StatusUnauthorized)
+ return username, Unauthorized
+ }
+ data, err := ioutil.ReadFile(cfg.Passwords)
+ if err != nil {
+ return username, err
+ }
+ for _, line := range strings.Split(string(data), "\n") {
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+ cols := strings.Split(line, ":")
+ if len(cols) != 2 {
+ continue
+ }
+ if cols[0] == username {
+ d := sha256.Sum256([]byte(password))
+ if hex.EncodeToString(d[:]) == cols[1] {
+ return username, nil
+ } else {
+ w.WriteHeader(http.StatusUnauthorized)
+ return username, Unauthorized
+ }
+ }
+ }
+ w.WriteHeader(http.StatusUnauthorized)
+ return username, Unauthorized
+}