multisql/pass/pass.go
2022-11-23 14:52:22 +01:00

81 lines
1.6 KiB
Go

package pass
import (
"bytes"
"fmt"
)
type pgpassrow struct {
hostname string
port string
database string
username string
password string
}
type PassDb struct {
db []pgpassrow
cache map[string]*pgpassrow
}
func Load(file string, master []byte) (*PassDb, error) {
data, err := DecryptFile(master, file)
if err != nil {
return nil, err
}
lines := bytes.Split(data, []byte{'\n'})
var rows []pgpassrow
for i, line := range lines {
line = bytes.TrimRight(line, "\n\r \t")
if len(line) == 0 || line[0] == byte('#') {
continue
}
fields := bytes.Split(line, []byte{':'})
if len(fields) != 5 {
return nil, fmt.Errorf("błąd w pliku hasłeł %s:%d: niewłaściwa liczba pól", file, i)
}
rows = append(rows, pgpassrow{
hostname: string(fields[0]),
port: string(fields[1]),
database: string(fields[2]),
username: string(fields[3]),
password: string(fields[4]),
})
}
return &PassDb{
db: rows,
cache: make(map[string]*pgpassrow),
}, nil
}
func match(value string, pattern string) bool {
return pattern == "*" || pattern == value
}
func (self *PassDb) FindPassword(host string, port uint, database string, user string) string {
myport := fmt.Sprintf("%d", port)
key := fmt.Sprintf("%s:%s:%s:%s", host, myport, database, user)
cached, ok := self.cache[key]
if ok {
return cached.password
}
// pierwszy pasujący do wzorca
for i := range self.db {
if match(host, self.db[i].hostname) &&
match(myport, self.db[i].port) &&
match(database, self.db[i].database) &&
match(user, self.db[i].username) {
self.cache[key] = &self.db[i]
return self.db[i].password
}
}
return ""
}