mirror of
https://github.com/syssecfsu/witty.git
synced 2024-11-28 15:09:27 +01:00
190 lines
3.5 KiB
Go
190 lines
3.5 KiB
Go
|
package cmd
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"crypto/sha256"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"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 {
|
||
|
goto nonexist
|
||
|
}
|
||
|
|
||
|
if err = json.Unmarshal(file, &users); err != nil {
|
||
|
log.Println("Failed to unmarsh file", err)
|
||
|
goto nonexist
|
||
|
}
|
||
|
|
||
|
// update the existing user if it exists
|
||
|
for i, u := range users {
|
||
|
if bytes.Equal(u.User, username) {
|
||
|
users[i].Seed = seed
|
||
|
users[i].Passwd = hashed
|
||
|
exist = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
nonexist:
|
||
|
if !exist {
|
||
|
users = append(users, UserRecord{username, seed, hashed})
|
||
|
}
|
||
|
|
||
|
output, err := json.Marshal(users)
|
||
|
if err != nil {
|
||
|
log.Println("Failed to marshal passwords", err)
|
||
|
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 {
|
||
|
log.Println("Failed to read password", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if len(passwd) < 12 {
|
||
|
fmt.Println("Password too short, at least 12 bytes")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
fmt.Println("Please type your password again:")
|
||
|
passwd2, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||
|
|
||
|
if err != nil {
|
||
|
log.Println("Failed to read password", err)
|
||
|
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 {
|
||
|
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
|
||
|
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 {
|
||
|
log.Println("Failed to marshal passwords", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
os.WriteFile(userFileName, output, 0660)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func ValidateUser(username []byte, passwd []byte) bool {
|
||
|
var users []UserRecord
|
||
|
var err error
|
||
|
|
||
|
file, err := os.ReadFile(userFileName)
|
||
|
if err != nil {
|
||
|
log.Println("Failed to read users file", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
err = json.Unmarshal(file, &users)
|
||
|
|
||
|
if err != nil {
|
||
|
log.Println("Failed to parse json format", err)
|
||
|
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
|
||
|
}
|