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