2022-01-22 03:42:22 +01:00
|
|
|
package web
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/sha256"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2022-01-22 15:29:01 +01:00
|
|
|
"log"
|
2022-01-22 03:42:22 +01:00
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/dchest/uniuri"
|
|
|
|
"golang.org/x/term"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
userFileName = "user.db"
|
|
|
|
)
|
|
|
|
|
|
|
|
type UserRecord struct {
|
|
|
|
User []byte `json:"Username"`
|
|
|
|
Seed []byte `json:"Seed"`
|
|
|
|
Passwd [32]byte `json:"Password"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func hashPassword(seed []byte, passwd []byte) [32]byte {
|
|
|
|
input := append(seed, passwd...)
|
|
|
|
return sha256.Sum256(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
func addUser(username []byte, passwd []byte) {
|
|
|
|
var users []UserRecord
|
|
|
|
var err error
|
|
|
|
|
|
|
|
seed := []byte(uniuri.NewLen(64))
|
|
|
|
hashed := hashPassword(seed, passwd)
|
|
|
|
|
|
|
|
exist := false
|
|
|
|
file, err := os.ReadFile(userFileName)
|
|
|
|
|
|
|
|
if (err == nil) && (json.Unmarshal(file, users) == nil) {
|
|
|
|
// update the existing user if it exists
|
|
|
|
for _, u := range users {
|
|
|
|
if bytes.Equal(u.User, username) {
|
|
|
|
u.Seed = seed
|
|
|
|
u.Passwd = hashed
|
|
|
|
exist = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !exist {
|
|
|
|
users = append(users, UserRecord{username, seed, hashed})
|
|
|
|
}
|
|
|
|
|
|
|
|
output, err := json.Marshal(users)
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to marshal passwords", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
os.WriteFile(userFileName, output, 0660)
|
|
|
|
}
|
|
|
|
|
|
|
|
func AddUser(username string) {
|
|
|
|
fmt.Println("Please type your password (it will not be echoed back):")
|
|
|
|
passwd, err := term.ReadPassword(int(os.Stdin.Fd()))
|
|
|
|
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to read password", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-01-23 00:27:42 +01:00
|
|
|
if len(passwd) < 12 {
|
|
|
|
fmt.Println("Password too short, at least 12 bytes")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-01-22 03:42:22 +01:00
|
|
|
fmt.Println("Please type your password again:")
|
|
|
|
passwd2, err := term.ReadPassword(int(os.Stdin.Fd()))
|
|
|
|
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to read password", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !bytes.Equal(passwd, passwd2) {
|
|
|
|
fmt.Println("Password mismatch, try again")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
addUser([]byte(username), passwd)
|
|
|
|
}
|
|
|
|
|
|
|
|
func DelUser(username string) {
|
|
|
|
var users []UserRecord
|
|
|
|
var err error
|
|
|
|
|
|
|
|
exist := false
|
|
|
|
file, err := os.ReadFile(userFileName)
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to read users file", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err = json.Unmarshal(file, &users)
|
|
|
|
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to parse json format", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
// update the existing user if it exists
|
|
|
|
for i, u := range users {
|
|
|
|
if bytes.Equal(u.User, []byte(username)) {
|
|
|
|
users = append(users[:i], users[i+1:]...)
|
|
|
|
exist = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if exist {
|
|
|
|
output, err := json.Marshal(users)
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to marshal passwords", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
os.WriteFile(userFileName, output, 0660)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 15:29:01 +01:00
|
|
|
func ListUsers() {
|
|
|
|
var users []UserRecord
|
|
|
|
var err error
|
|
|
|
|
|
|
|
file, err := os.ReadFile(userFileName)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Failed to read users file", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err = json.Unmarshal(file, &users)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Failed to parse json format", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// update the existing user if it exists
|
|
|
|
fmt.Println("Users of the system:")
|
|
|
|
for _, u := range users {
|
|
|
|
fmt.Println(" ", string(u.User))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 03:42:22 +01:00
|
|
|
func ValidateUser(username []byte, passwd []byte) bool {
|
|
|
|
var users []UserRecord
|
|
|
|
var err error
|
|
|
|
|
|
|
|
file, err := os.ReadFile(userFileName)
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to read users file", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
err = json.Unmarshal(file, &users)
|
|
|
|
|
|
|
|
if err != nil {
|
2022-01-22 15:29:01 +01:00
|
|
|
log.Println("Failed to parse json format", err)
|
2022-01-22 03:42:22 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// update the existing user if it exists
|
|
|
|
for _, u := range users {
|
|
|
|
if bytes.Equal(u.User, []byte(username)) {
|
|
|
|
hashed := hashPassword(u.Seed, passwd)
|
|
|
|
return bytes.Equal(hashed[:], u.Passwd[:])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|