first working commit

This commit is contained in:
Louis Guidez 2024-02-27 13:39:34 +00:00
commit 0a2077c04c
5 changed files with 133 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.sqlite
build

30
Makefile Normal file
View file

@ -0,0 +1,30 @@
# Makefile for building the Go module
APP_NAME := maddy-hostux-check-password
# Set the source directory
SRC_DIR := .
# Go files
SRC := $(wildcard $(SRC_DIR)/*.go)
# Build directory
BUILD_DIR := ./build
# Set the Go compiler
GO := go
# Flags for go build
BUILD_FLAGS := -o $(BUILD_DIR)/$(APP_NAME)
.PHONY: all build clean
all: build
build: $(BUILD_DIR)/$(APP_NAME)
$(BUILD_DIR)/$(APP_NAME): $(SRC)
@mkdir -p $(BUILD_DIR)
$(GO) build $(BUILD_FLAGS) $(SRC_DIR)
clean:
rm -rf $(BUILD_DIR)

8
go.mod Normal file
View file

@ -0,0 +1,8 @@
module main
go 1.21.6
require (
github.com/mattn/go-sqlite3 v1.14.22
golang.org/x/crypto v0.20.0
)

4
go.sum Normal file
View file

@ -0,0 +1,4 @@
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=

89
main.go Normal file
View file

@ -0,0 +1,89 @@
package main
import (
"database/sql"
"fmt"
"os"
"time"
_ "github.com/mattn/go-sqlite3"
"golang.org/x/crypto/bcrypt"
)
/**
* Exit codes:
* 0: authentication successful
* 1: authentication failed (email address not found or password mismatch
* 2: other error
*/
func main() {
// Checks usage
if len(os.Args) != 2 {
fmt.Println("Usage: hostux_check_credentials [database.sqlite]")
os.Exit(2)
}
// Opens the SQLite database
dbFile := os.Args[1]
db, err := sql.Open("sqlite3", dbFile)
if err != nil {
fmt.Println("Error opening database:", err)
os.Exit(2)
}
defer db.Close()
// Reads stdin input (email address, password, each ends with \n)
var emailAddress, password string
fmt.Println("Enter email address:")
fmt.Scanln(&emailAddress)
fmt.Println("Enter password:")
fmt.Scanln(&password)
// Finds database records
rows, err := db.Query(`SELECT eap.id, eap.password FROM "email-addresses" AS ea
LEFT JOIN "email-addresses-passwords" AS eap ON ea.emailAddress = eap.emailAddress
WHERE ea.emailAddress = ?`, emailAddress)
if err != nil {
fmt.Println("Database error: ", err)
os.Exit(2)
}
defer rows.Close()
// Loops through records
for rows.Next() {
var hashedPassword string
var id int
err := rows.Scan(&id, &hashedPassword)
if err != nil {
fmt.Println("Database error: ", err)
os.Exit(2)
}
// Compares provided password with database
err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
if err == nil {
// No error = the passwords match
// Update lastAccess time
rows.Close()
_, err := db.Exec(`UPDATE "email-addresses-passwords"
SET lastAccess = ?
WHERE id = ?`, time.Now().Format(time.RFC3339), id)
if err != nil {
fmt.Println("Database error: ", err)
os.Exit(2)
}
fmt.Println("Authentication successful")
os.Exit(0)
}
}
// If we have not returned by now, it means that:
// * either there were no records
// * or no record matched the provided password
fmt.Println("Authentication failed: account not found or password incorrect")
os.Exit(1)
}