Skip to content
Snippets Groups Projects
Verified Commit a8cf6aa5 authored by Jonas Röger's avatar Jonas Röger
Browse files

Added server side ability for reporting bugs

parent ba8f7f28
No related branches found
No related tags found
No related merge requests found
Pipeline #1909 passed with warnings
package wtfd
import (
"errors"
"fmt"
"time"
"strconv"
"net/smtp"
)
var (
serviceDeskDomain = "jroeger.de"
serviceDeskUser = "noreply"
serviceDeskPort = 25 // server to server smtp port
serviceDeskEnabled = true
rateLimitInterval float64 = 180 // 3 Minutes
rateLimitReports = 2 // 2 Reports during interval before beeing rate limited
userAccess map[string]access = make(map[string]access)
)
type access struct {
lastBlock time.Time // Currently unused
lastAccess []time.Time
}
/**
* Check if user is rate limited
*/
func BRIsUserRateLimited(u *User) bool {
record, ok := userAccess[u.Name]
if !ok {
return false
}
/* Ok if no critical ammount of records */
if len(record.lastAccess) < rateLimitReports {
return false
}
/* Check if earliest record is in interval, then block */
if time.Since(record.lastAccess[0]).Seconds() < rateLimitInterval {
return true
}
return false
}
/**
* Register a user access
*/
func registerUserAccess(u *User) {
record, ok := userAccess[u.Name]
if !ok {
/* New record */
record = access{
lastBlock: time.Time{},
lastAccess: []time.Time{time.Now()},
}
} else if len(record.lastAccess) < rateLimitReports {
/* No critical ammount of records */
record.lastAccess = append(record.lastAccess, time.Now())
} else if !BRIsUserRateLimited(u) {
/* Cycle access */
record.lastAccess = record.lastAccess[1:]
record.lastAccess = append(record.lastAccess, time.Now())
}
userAccess[u.Name] = record
}
/**
* Send bugreport
*/
func BRDispatchBugreport(u *User, subject string, content string) error {
if !serviceDeskEnabled {
return errors.New("Service Desk is disabled")
}
recipient := serviceDeskUser + "@" + serviceDeskDomain
recipients := []string{recipient}
formatContent := fmt.Sprintf("From: %s\nSubject: %s\n\n%s", u.Name, subject, content)
err := smtp.SendMail(serviceDeskDomain+":"+strconv.Itoa(serviceDeskPort),
nil, u.Name, recipients, []byte(formatContent))
if err == nil {
registerUserAccess(u)
}
return err
}
......@@ -300,6 +300,51 @@ func logout(w http.ResponseWriter, r *http.Request) {
}
func reportBug(w http.ResponseWriter, r *http.Request) {
var err error
if r.Method != "POST" {
w.WriteHeader(http.StatusBadRequest)
_, _ = fmt.Fprintf(w, "Invalid Request")
return
}
/* Check user login */
user, ok := getUser(r)
if !ok {
w.WriteHeader(http.StatusInternalServerError)
_, _ = fmt.Fprintf(w, "Server Error: %v", "Not logged in")
return
}
/* Check if user is rate limited */
if BRIsUserRateLimited(&user) {
w.WriteHeader(http.StatusTooManyRequests)
_, _ = fmt.Fprint(w, "Too many requsets")
return
}
/* Read and Check form */
if err = r.ParseForm() ; err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = fmt.Fprintf(w, "Server Error: %v", "Not logged in")
return
}
subject := r.FormValue("subject")
content := r.FormValue("content")
if subject == "" || content == "" {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, "Invaild Request")
return
}
/* Try to dispatch bugreport */
if err = BRDispatchBugreport(&user, subject , content); err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = fmt.Fprintf(w, "Server Error: %v", err)
}
}
func solutionview(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
chall, err := challs.Find(vars["chall"])
......@@ -493,6 +538,7 @@ func Server() error {
r.HandleFunc("/register", register)
r.HandleFunc("/submitflag", submitFlag)
r.HandleFunc("/ws", leaderboardWS)
r.HandleFunc("/reportbug", reportBug)
r.HandleFunc("/{chall}", mainpage)
r.HandleFunc("/detailview/{chall}", detailview)
r.HandleFunc("/solutionview/{chall}", solutionview)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment