]> Cypherpunks.ru repositories - gocheese.git/blob - passwd.go
More convenient trusted-host
[gocheese.git] / passwd.go
1 /*
2 GoCheese -- Python private package repository and caching proxy
3 Copyright (C) 2019-2022 Sergey Matveev <stargrave@stargrave.org>
4               2019-2022 Elena Balakhonova <balakhonova_e@riseup.net>
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package main
20
21 import (
22         "bufio"
23         "errors"
24         "log"
25         "os"
26         "strings"
27         "sync"
28 )
29
30 var (
31         Passwords  map[string]Auther = make(map[string]Auther)
32         PasswordsM sync.RWMutex
33 )
34
35 type Auther interface {
36         Auth(password string) bool
37 }
38
39 func strToAuther(verifier string) (string, Auther, error) {
40         st := strings.SplitN(verifier, "$", 3)
41         if len(st) != 3 || st[0] != "" {
42                 return "", nil, errors.New("invalid verifier structure")
43         }
44         algorithm := st[1]
45         var auther Auther
46         var err error
47         switch algorithm {
48         case "argon2i":
49                 auther, err = parseArgon2i(st[2])
50         case "sha256":
51                 auther, err = parseSHA256(st[2])
52         default:
53                 err = errors.New("unknown hashing algorithm")
54         }
55         return algorithm, auther, err
56 }
57
58 func passwdReader(fd *os.File) bool {
59         isGood := true
60         scanner := bufio.NewScanner(fd)
61         for scanner.Scan() {
62                 t := scanner.Text()
63                 if len(t) == 0 {
64                         continue
65                 }
66                 splitted := strings.Split(t, ":")
67                 if len(splitted) != 2 {
68                         log.Println("wrong login:password format:", t)
69                         isGood = false
70                         continue
71                 }
72                 login := splitted[0]
73                 passwd := splitted[1]
74                 if passwd == "" {
75                         log.Println("deleting login:", login)
76                         PasswordsM.Lock()
77                         delete(Passwords, login)
78                         PasswordsM.Unlock()
79                         continue
80                 }
81                 _, auther, err := strToAuther(passwd)
82                 if err != nil {
83                         log.Println("login:", login, "invalid password:", err)
84                         isGood = false
85                         continue
86                 }
87                 log.Println("adding password for:", login)
88                 PasswordsM.Lock()
89                 Passwords[login] = auther
90                 PasswordsM.Unlock()
91         }
92         return isGood
93 }
94
95 func passwdLister(fd *os.File) {
96         PasswordsM.RLock()
97         logins := make([]string, 0, len(Passwords))
98         for login := range Passwords {
99                 logins = append(logins, login)
100         }
101         PasswordsM.RUnlock()
102         for _, login := range logins {
103                 fd.WriteString(login + "\n")
104         }
105 }