X-Git-Url: http://www.git.cypherpunks.ru/?p=gocheese.git;a=blobdiff_plain;f=passwd.go;fp=passwd.go;h=e5edc5241acfb60fcead30fe37b79acb18c47cb3;hp=95566e15da21b5fe708417c041f96babe404c51b;hb=c5ca3f66f1b3cd24e55d6e5fc95fdf61cac7aec6;hpb=356b13afa3db5a989a82cc4de910715d74681320 diff --git a/passwd.go b/passwd.go index 95566e1..e5edc52 100644 --- a/passwd.go +++ b/passwd.go @@ -18,22 +18,34 @@ package main import ( "bufio" + "context" "errors" "log" + "net/http" "os" "strings" "sync" ) var ( - Passwords map[string]Auther = make(map[string]Auther) + Passwords map[string]*User = make(map[string]*User) PasswordsM sync.RWMutex ) +type CtxUserKeyType struct{} + +var CtxUserKey CtxUserKeyType + type Auther interface { Auth(password string) bool } +type User struct { + name string + ro bool + auther Auther +} + func strToAuther(verifier string) (string, Auther, error) { st := strings.SplitN(verifier, "$", 3) if len(st) != 3 || st[0] != "" { @@ -62,8 +74,8 @@ func passwdReader(fd *os.File) bool { continue } splitted := strings.Split(t, ":") - if len(splitted) != 2 { - log.Println("wrong login:password format:", t) + if len(splitted) < 2 { + log.Println("wrong login:password[:ro] format:", t) isGood = false continue } @@ -82,9 +94,20 @@ func passwdReader(fd *os.File) bool { isGood = false continue } + var ro bool + if len(splitted) > 2 { + switch splitted[2] { + case "ro": + ro = true + default: + log.Println("wrong format of optional field:", t) + isGood = false + continue + } + } log.Println("adding password for:", login) PasswordsM.Lock() - Passwords[login] = auther + Passwords[login] = &User{name: login, ro: ro, auther: auther} PasswordsM.Unlock() } return isGood @@ -101,3 +124,27 @@ func passwdLister(fd *os.File) { fd.WriteString(login + "\n") } } + +func checkAuth(handler http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + username, password, gotAuth := r.BasicAuth() + var user *User + if gotAuth { + PasswordsM.RLock() + user = Passwords[username] + PasswordsM.RUnlock() + } + var passwordValid bool + if gotAuth && user != nil { + passwordValid = user.auther.Auth(password) + } + if (gotAuth && user == nil) || + (user != nil && !passwordValid) || + (*AuthRequired && !gotAuth) { + log.Println(r.RemoteAddr, "unauthenticated", username) + http.Error(w, "unauthenticated", http.StatusUnauthorized) + return + } + handler(w, r.WithContext(context.WithValue(r.Context(), CtxUserKey, user))) + } +}