Error handling, untested /api/login

This commit is contained in:
Tracker-Friendly 2024-05-02 01:47:13 +01:00
parent 646c201b6f
commit c7bd5ad1f6
2 changed files with 72 additions and 3 deletions

View File

@ -2,3 +2,4 @@
secretkey: supersecretkey secretkey: supersecretkey
port: 8080 port: 8080
host: localhost host: localhost
dblocation: /var/lib/maddy/credentials.db

72
main.go
View File

@ -3,6 +3,7 @@ package main
import ( import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"database/sql"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"os" "os"
@ -20,6 +21,13 @@ import (
const salt_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" const salt_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var DBLOCATION = "/var/lib/maddy/credentials.db"
func get_db_connection() *sql.DB {
db, _ := sql.Open("sqlite3", DBLOCATION)
return db
}
func genSalt(length int) string { func genSalt(length int) string {
if length <= 0 { if length <= 0 {
fmt.Println("[ERROR] Known in genSalt() at", strconv.FormatInt(time.Now().Unix(), 10)+":", "Salt length must be at least one.") fmt.Println("[ERROR] Known in genSalt() at", strconv.FormatInt(time.Now().Unix(), 10)+":", "Salt length must be at least one.")
@ -63,7 +71,7 @@ func main() {
SECRET_KEY := viper.GetString("Config.secretkey") SECRET_KEY := viper.GetString("Config.secretkey")
PORT := viper.GetString("Config.port") PORT := viper.GetString("Config.port")
HOST := viper.GetString("Config.host") HOST := viper.GetString("Config.host")
//DBLOCATION := viper.GetString("Config.dblocation") DBLOCATION = viper.GetString("Config.dblocation")
if SECRET_KEY == "supersecretkey" { if SECRET_KEY == "supersecretkey" {
fmt.Println("[WARNING] Secret key not set. Please set the secret key to a non-default value.") fmt.Println("[WARNING] Secret key not set. Please set the secret key to a non-default value.")
@ -93,32 +101,92 @@ func main() {
router.GET("/login", func(c *gin.Context) { router.GET("/login", func(c *gin.Context) {
session := sessions.Default(c) session := sessions.Default(c)
sessionid := genSalt(512)
session.Options(sessions.Options{ session.Options(sessions.Options{
SameSite: 3, SameSite: 3,
}) })
data, err := captcha.New(500, 100) data, err := captcha.New(500, 100)
if err != nil { if err != nil {
fmt.Println("[ERROR] Failed to generate captcha at", time.Now().Unix(), err)
c.String(500, "Failed to generate captcha") c.String(500, "Failed to generate captcha")
return return
} }
session.Set("captcha", data.Text) session.Set("captcha", data.Text)
session.Set("id", sessionid)
err = session.Save() err = session.Save()
if err != nil { if err != nil {
fmt.Println("[ERROR] Failed to save session in /login at", time.Now().Unix(), err)
c.String(500, "Failed to save session") c.String(500, "Failed to save session")
return return
} }
var b64bytes bytes.Buffer var b64bytes bytes.Buffer
err = data.WriteImage(&b64bytes) err = data.WriteImage(&b64bytes)
if err != nil { if err != nil {
fmt.Println("[ERROR] Failed to encode captcha at", time.Now().Unix(), err)
c.String(500, "Failed to encode captcha") c.String(500, "Failed to encode captcha")
return return
} }
c.HTML(200, "main.html", gin.H{ c.HTML(200, "main.html", gin.H{
"captcha_image": base64.StdEncoding.EncodeToString(b64bytes.Bytes()), "captcha_image": base64.StdEncoding.EncodeToString(b64bytes.Bytes()),
"unique_token": genSalt(512), "unique_token": sessionid,
}) })
}) })
router.POST("/api/signup", func(c *gin.Context) {
err := c.Request.ParseForm()
if err != nil {
c.String(400, "Failed to parse form")
return
}
data := c.Request.Form
session := sessions.Default(c)
if data.Get("captcha") != session.Get("captcha") {
c.HTML(200, "badcaptcha.html", gin.H{})
return
}
if data.Get("unique_token") != session.Get("id") {
c.HTML(200, "badtoken.html", gin.H{})
return
}
session.Delete("captcha")
session.Delete("id")
err = session.Save()
if err != nil {
fmt.Println("[ERROR] Failed to save session in /api/signup at", time.Now().Unix(), err)
c.String(500, "Failed to save session")
return
}
conn := get_db_connection()
defer func(conn *sql.DB) {
err := conn.Close()
if err != nil {
fmt.Println("[ERROR] Failed to defer database connection at", time.Now().Unix(), err)
c.String(500, "Failed to defer database connection")
return
}
}(conn)
hashedpass, err := computeBcrypt(10, data.Get("password"))
if err != nil {
fmt.Println("[ERROR] Failed to hash password connection at", time.Now().Unix(), err)
c.String(500, "Failed to hash password")
return
}
_, err = conn.Exec("INSERT INTO passwords (key, value) VALUES (?, ?)", data.Get("username"), hashedpass)
if err != nil {
c.HTML(500, "taken.html", gin.H{})
return
}
c.HTML(200, "postsignup.html", gin.H{})
})
fmt.Println("[INFO] Server started at", time.Now().Unix()) fmt.Println("[INFO] Server started at", time.Now().Unix())
fmt.Println("[INFO] Welcome to CTAMail! Today we are running on IP " + HOST + " on port " + PORT + ".") fmt.Println("[INFO] Welcome to CTAMail! Today we are running on IP " + HOST + " on port " + PORT + ".")
err := router.Run(HOST + ":" + PORT) err := router.Run(HOST + ":" + PORT)