From 4641faefc2aec4762de1cd625641d07b2f3bf5d5 Mon Sep 17 00:00:00 2001 From: ngn Date: Tue, 13 Aug 2024 22:25:36 +0300 Subject: [PATCH] update: better CSS border colors --- .gitignore | 2 + Makefile | 9 +++ README.md | 26 ++++-- compose.yml | 12 --- lib/db.go | 52 ++++++------ lib/lib/config.go | 33 ++++++++ lib/lib/package.go | 135 +++++++++++++++++++++++++++++++ lib/lib/pool.go | 145 +++++++++++++++++++++++++++++++++ lib/lib/util.go | 104 ++++++++++++++++++++++++ lib/user.go | 72 ++++++++--------- lib/util.go | 64 +++++++-------- lib/vuln.go | 196 ++++++++++++++++++++++----------------------- main.go | 62 +++++++------- public/index.css | 4 +- public/login.css | 2 +- public/manage.css | 4 +- routes/index.go | 124 ++++++++++++++-------------- routes/login.go | 70 ++++++++-------- routes/manage.go | 64 +++++++-------- routes/new.go | 78 +++++++++--------- routes/status.go | 60 +++++++------- 21 files changed, 873 insertions(+), 445 deletions(-) create mode 100644 Makefile delete mode 100644 compose.yml create mode 100644 lib/lib/config.go create mode 100644 lib/lib/package.go create mode 100644 lib/lib/pool.go create mode 100644 lib/lib/util.go diff --git a/.gitignore b/.gitignore index 180a4f1..3a1cab5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ +docker-compose.yml +compose.yml security db/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..43f73f2 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: security + +security: */*.go *.go + go build -o $@ + +format: + gofmt -s -w . + +.PHONY: format diff --git a/README.md b/README.md index d6c72a6..1749b64 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,32 @@ -# security | MatterLinux Security Tracker -Soruce code of MatterLinux's security tracker, located at +# security | MatterLinux security tracker +Soruce code of MatterLinux's security tracker, located at [security.matterlinux.xyz](https://security.matterlinux.xyz) ### Deployment -Web server can be built and deployed with docker: +Web server can be built and deployed with docker compose, here is an +example configuration: +```yaml +version: "3" + +services: + security: + image: mattersecurity + restart: unless-stopped + build: + context: ./ + ports: + - "127.0.0.1:9876:9876" + volumes: + - "./db:/app/db" +``` +After saving the configuration file, you can build and run the docker container: ```bash -docker build --tag mattersecurity . -mkdir -pv db docker-compose up -d ``` ### Adding users After running the application at least once, you can users using -the `adduser.sh` script. This script will add the specified user with a +the `adduser.sh` script. This script will add the specified user with a randomly generated passwords to the sqlite database. For example: ```bash ./adduser.sh ngn diff --git a/compose.yml b/compose.yml deleted file mode 100644 index eaafe05..0000000 --- a/compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: "3" - -services: - security: - image: mattersecurity - restart: unless-stopped - build: - context: ./ - ports: - - "127.0.0.1:9876:9876" - volumes: - - "./db:/app/db" diff --git a/lib/db.go b/lib/db.go index 3ccb942..f1bfe30 100644 --- a/lib/db.go +++ b/lib/db.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - _ "github.com/mattn/go-sqlite3" + _ "github.com/mattn/go-sqlite3" ) var Db *sql.DB @@ -35,34 +35,32 @@ const create_vulns string = ` ` func LoadDatabase() error { - _, err := os.Stat("db") - if err != nil && os.IsNotExist(err) { - err = os.Mkdir("db", os.ModePerm) - if err != nil { - return err - } - } + _, err := os.Stat("db") + if err != nil && os.IsNotExist(err) { + err = os.Mkdir("db", os.ModePerm) + if err != nil { + return err + } + } - if err != nil && !os.IsNotExist(err) { - return fmt.Errorf("cannot access to db directory") - } + if err != nil && !os.IsNotExist(err) { + return fmt.Errorf("cannot access to db directory") + } - Db, err = sql.Open("sqlite3", "db/data.db") - if err != nil { - return err - } + Db, err = sql.Open("sqlite3", "db/data.db") + if err != nil { + return err + } - _, err = Db.Exec(create_users) - if err != nil { - return err - } + _, err = Db.Exec(create_users) + if err != nil { + return err + } - _, err = Db.Exec(create_vulns) - if err != nil { - return err - } - - return nil + _, err = Db.Exec(create_vulns) + if err != nil { + return err + } + + return nil } - - diff --git a/lib/lib/config.go b/lib/lib/config.go new file mode 100644 index 0000000..56a5175 --- /dev/null +++ b/lib/lib/config.go @@ -0,0 +1,33 @@ +package lib + +import ( + "encoding/json" + "os" +) + +type Config struct { + Pools []Pool `json:"pools"` +} + +func (c *Config) Load(list *[]Package, file string) error { + var ( + content []byte + err error + ) + + if content, err = os.ReadFile(file); err != nil { + return err + } + + if err = json.Unmarshal(content, c); err != nil { + return err + } + + for _, p := range c.Pools { + if err = p.Load(list); err != nil { + return err + } + } + + return nil +} diff --git a/lib/lib/package.go b/lib/lib/package.go new file mode 100644 index 0000000..6fcb7e2 --- /dev/null +++ b/lib/lib/package.go @@ -0,0 +1,135 @@ +package lib + +import ( + "archive/tar" + "bufio" + "compress/gzip" + "fmt" + "io" + "net/url" + "os" + "path" + "strings" + + "git.matterlinux.xyz/matter/tracker/log" + "github.com/bigkevmcd/go-configparser" +) + +type Package struct { + Name string `json:"name"` + Pool *Pool `json:"-"` + Version string `json:"version"` + Depends []string `json:"depends"` + Size string `json:"size"` + Desc string `json:"desc"` + Archive string `json:"archive"` +} + +func (p *Package) Files() []string { + var ( + gzip_reader io.Reader + header *tar.Header + result []string + file *os.File + err error + ) + + if file, err = os.Open(p.Archive); err != nil { + log.Error("Failed to open %s", p.Archive) + return result + } + defer file.Close() + + if gzip_reader, err = gzip.NewReader(bufio.NewReader(file)); err != nil { + log.Error("Failed to create reader for %s", p.Archive) + return result + } + + reader := tar.NewReader(gzip_reader) + + for header, err = reader.Next(); err == nil; header, err = reader.Next() { + if header.Typeflag != tar.TypeReg { + continue + } + + if path.Base(header.Name) != "files.tar.gz" { + continue + } + + if result, err = GetFiles(reader); err == nil { + break + } + + log.Error("Failed to get file list for %s: %s", p.Archive, err.Error()) + return []string{} + } + + return result +} + +func (p *Package) URL() string { + if nil == p.Pool { + return "" + } + url, _ := url.JoinPath(p.Pool.Source, "src/branch/"+p.Pool.Branch+"/src", p.Name) + return url +} + +func (p *Package) DependsToStr() string { + var depends string = "" + for _, d := range p.Depends { + depends += fmt.Sprintf("%s ", d) + } + return depends +} + +func (p *Package) Load(r io.Reader) error { + var ( + err error + size int64 + depends string = "" + section string = "DEFAULT" + ) + + parser := configparser.New() + if err = parser.ParseReader(r); err != nil { + return err + } + + for _, s := range parser.Sections() { + if s == "DEFAULT" { + continue + } + section = s + break + } + + if section == "DEFAULT" { + return fmt.Errorf("DATA does not contain any sections") + } + + p.Name = section + + if p.Version, err = parser.Get(section, "version"); err != nil { + return err + } + + if size, err = parser.GetInt64(section, "size"); err != nil { + return err + } + p.Size = SizeFromBytes(size) + + if p.Desc, err = parser.Get(section, "desc"); err != nil { + return err + } + + depends, _ = parser.Get(section, "depends") + + if depends == "" { + p.Depends = []string{} + } else { + p.Depends = strings.Split(depends, ",") + } + + return nil +} diff --git a/lib/lib/pool.go b/lib/lib/pool.go new file mode 100644 index 0000000..f06b4ec --- /dev/null +++ b/lib/lib/pool.go @@ -0,0 +1,145 @@ +package lib + +import ( + "archive/tar" + "bufio" + "compress/gzip" + "fmt" + "io" + "os" + "path" + + "github.com/bigkevmcd/go-configparser" +) + +type Pool struct { + Maintainer string `json:"-"` + Pubkey string `json:"-"` + Size string `json:"-"` + + Display string `json:"display"` + Branch string `json:"branch"` + Source string `json:"source"` + Name string `json:"name"` + URL string `json:"url"` + Dir string `json:"dir"` +} + +func (p *Pool) Load(list *[]Package) error { + var err error + + if p.Dir == "" { + return fmt.Errorf("pool directory is not specified") + } + + if err = p.LoadInfo(); err != nil { + return err + } + + if err = p.LoadList(list); err != nil { + return err + } + + return nil +} + +func (p *Pool) LoadList(list *[]Package) error { + var ( + list_path string + list_file *os.File + gzip_reader io.Reader + header *tar.Header + err error + ) + + list_path = path.Join(p.Dir, "LIST") + + if list_file, err = os.Open(list_path); err != nil { + return err + } + defer list_file.Close() + + if gzip_reader, err = gzip.NewReader(bufio.NewReader(list_file)); err != nil { + return err + } + + reader := tar.NewReader(gzip_reader) + + for header, err = reader.Next(); err == nil; header, err = reader.Next() { + if header.Typeflag != tar.TypeReg { + continue + } + + if path.Base(header.Name) != "DATA" { + return fmt.Errorf("LIST archive contains an unknown file") + } + + var pkg Package + + if err = pkg.Load(reader); err != nil { + return err + } + + pkg.Archive = path.Join(p.Dir, fmt.Sprintf("%s_%s.mpf", pkg.Name, pkg.Version)) + pkg.Pool = p + + *list = append(*list, pkg) + } + + return nil +} + +func (p *Pool) LoadInfo() error { + var ( + info_path string + info_file *os.File + section string + size int64 + err error + ) + + info_path = path.Join(p.Dir, "INFO") + + if info_file, err = os.Open(info_path); err != nil { + return err + } + + parser := configparser.New() + + if err = parser.ParseReader(bufio.NewReader(info_file)); err != nil { + return err + } + + section = "DEFAULT" + + for _, s := range parser.Sections() { + if s == "DEFAULT" { + continue + } + section = s + break + } + + if section == "DEFAULT" { + return fmt.Errorf("DATA does not contain any sections") + } + + if p.Name != section { + return fmt.Errorf("pool name (\"%s\") doesn't match with \"%s\"", p.Name, section) + } + + if p.Maintainer, err = parser.Get(p.Name, "maintainer"); err != nil { + return err + } + + if size, err = parser.GetInt64(section, "size"); err != nil { + return err + } + p.Size = SizeFromBytes(size) + + if p.Pubkey, err = parser.Get(section, "pubkey"); err != nil { + return err + } + + return nil +} diff --git a/lib/lib/util.go b/lib/lib/util.go new file mode 100644 index 0000000..45c6fd3 --- /dev/null +++ b/lib/lib/util.go @@ -0,0 +1,104 @@ +package lib + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "strings" + "time" + + "github.com/gofiber/fiber/v2" +) + +func GetFiles(r io.Reader) ([]string, error) { + var ( + gzip_reader io.Reader + header *tar.Header + result []string + err error + ) + + if gzip_reader, err = gzip.NewReader(r); err != nil { + return result, err + } + + reader := tar.NewReader(gzip_reader) + + for header, err = reader.Next(); err == nil; header, err = reader.Next() { + if header.Typeflag != tar.TypeReg { + continue + } + + result = append(result, header.Name) + } + + return result, nil +} + +func ListToStr(l []string) string { + res := "" + for _, e := range l { + res += e + " " + } + return res +} + +func RenderError(c *fiber.Ctx, code int) error { + var msg string = "Server Error" + c.Status(code) + + switch code { + case 404: + msg = "Not Found" + } + + return c.Render("error", fiber.Map{ + "msg": msg, + }) +} + +func SizeFromBytes(size int64) string { + if size > 1024*1024*1024 { + return fmt.Sprintf("%dGB", (size / 1024 / 1024 / 1024)) + } else if size > 1024*1024 { + return fmt.Sprintf("%dMB", (size / 1024 / 1024)) + } else if size > 1024 { + return fmt.Sprintf("%dKB", (size / 1024)) + } + return fmt.Sprintf("%dB", size) +} + +func TimePassed(t time.Time) string { + diff := time.Since(t) + res := fmt.Sprintf( + "%ds ago", + int(diff.Seconds()), + ) + + if diff.Minutes() > 1 { + res = fmt.Sprintf( + "%dm and %ds ago", + int(diff.Minutes()), int(diff.Seconds())-(int(diff.Minutes())*60), + ) + } + + if diff.Hours() > 1 { + res = fmt.Sprintf("%dh and %dm ago", + int(diff.Hours()), + int(diff.Minutes())-(int(diff.Hours())*60), + ) + } + + return res +} + +func SanitizeXSS(s string) string { + var bad []string = []string{"~", "'", "\"", "/", "<", ">", "?", "=", "#", "(", ")", "{", "}", "*", "!", "`", "[", "]"} + + for _, c := range bad { + s = strings.ReplaceAll(s, c, "") + } + + return s +} diff --git a/lib/user.go b/lib/user.go index 0442fc8..314677c 100644 --- a/lib/user.go +++ b/lib/user.go @@ -7,54 +7,54 @@ import ( ) type User struct { - Username string - Password string - Cookie string + Username string + Password string + Cookie string } func GetUser(c *fiber.Ctx) (User, error) { - users, err := LoadUsers() - if err != nil { - return User{}, err - } + users, err := LoadUsers() + if err != nil { + return User{}, err + } - for i, u := range users { - if c.Cookies("auth") == u.Cookie { - return users[i], nil - } - } + for i, u := range users { + if c.Cookies("auth") == u.Cookie { + return users[i], nil + } + } - return User{}, fmt.Errorf("user not found") + return User{}, fmt.Errorf("user not found") } func LoadUsers() ([]User, error) { - var users []User - - rows, err := Db.Query("SELECT * FROM users") - if err != nil { - return users, err - } - defer rows.Close() + var users []User - for rows.Next() { - var u User - rows.Scan(&u.Username, &u.Password, &u.Cookie) - users = append(users, u) - } - - return users, nil + rows, err := Db.Query("SELECT * FROM users") + if err != nil { + return users, err + } + defer rows.Close() + + for rows.Next() { + var u User + rows.Scan(&u.Username, &u.Password, &u.Cookie) + users = append(users, u) + } + + return users, nil } func UpdateUser(u User) error { - smt, err := Db.Prepare("UPDATE users SET password=?, cookie=? WHERE username=?") - if err != nil { - return err - } + smt, err := Db.Prepare("UPDATE users SET password=?, cookie=? WHERE username=?") + if err != nil { + return err + } - _, err = smt.Exec(u.Password, u.Cookie, u.Username) - if err != nil { - return err - } + _, err = smt.Exec(u.Password, u.Cookie, u.Username) + if err != nil { + return err + } - return nil + return nil } diff --git a/lib/util.go b/lib/util.go index 89d87c6..3890743 100644 --- a/lib/util.go +++ b/lib/util.go @@ -12,46 +12,46 @@ import ( ) func GetFTime() string { - return time.Now().Format("01/02/2006") + return time.Now().Format("01/02/2006") } func GetRandom() string { - buf := make([]byte, 128) - _, err := rand.Read(buf) - if err != nil { - log.Fatalf("Failed to get random bytes: %s", err.Error()) - } + buf := make([]byte, 128) + _, err := rand.Read(buf) + if err != nil { + log.Fatalf("Failed to get random bytes: %s", err.Error()) + } - return GetSHA256(buf) + return GetSHA256(buf) } func GetSHA256(s []byte) string { - sum := sha256.Sum256(s) - return fmt.Sprintf("%x", sum) + sum := sha256.Sum256(s) + return fmt.Sprintf("%x", sum) } func ContainsCase(s1 string, s2 string) bool { - return strings.Contains( - strings.ToLower(s1), strings.ToLower(s2), - ) -} - -func RenderError(c *fiber.Ctx, code int) error{ - var msg string = "Server Error" - c.Status(code) - - switch code { - case 404: - msg = "Not Found" - case 500: - msg = "Server error" - case 403: - msg = "Forbidden" - case 400: - msg = "Bad request" - } - - return c.Render("error", fiber.Map{ - "msg": msg, - }) + return strings.Contains( + strings.ToLower(s1), strings.ToLower(s2), + ) +} + +func RenderError(c *fiber.Ctx, code int) error { + var msg string = "Server Error" + c.Status(code) + + switch code { + case 404: + msg = "Not Found" + case 500: + msg = "Server error" + case 403: + msg = "Forbidden" + case 400: + msg = "Bad request" + } + + return c.Render("error", fiber.Map{ + "msg": msg, + }) } diff --git a/lib/vuln.go b/lib/vuln.go index 02a13c7..7097c13 100644 --- a/lib/vuln.go +++ b/lib/vuln.go @@ -7,131 +7,131 @@ import ( ) type Vuln struct { - ID string - Desc string - Source string - Severity string - Package string - Versions string - Status string - Message string - Author string - Date string - Updated string + ID string + Desc string + Source string + Severity string + Package string + Versions string + Status string + Message string + Author string + Date string + Updated string } func ValidSeverity(s string) bool { - switch s { - case "Low": - return true - case "Medium": - return true - case "High": - return true - case "Critical": - return true - } - return false + switch s { + case "Low": + return true + case "Medium": + return true + case "High": + return true + case "Critical": + return true + } + return false } func (v Vuln) StatusColor() string { - switch v.Status { - case "Waiting for review": - return "blue" - case "Ongoing review": - return "blue" - case "Working on a patch": - return "blue" - case "Won't patch": - return "red" - case "Patched": - return "green" - case "Not affected": - return "red" - } + switch v.Status { + case "Waiting for review": + return "blue" + case "Ongoing review": + return "blue" + case "Working on a patch": + return "blue" + case "Won't patch": + return "red" + case "Patched": + return "green" + case "Not affected": + return "red" + } - return "" + return "" } func GetID() string { - now := time.Now() - mic := strconv.FormatInt(now.UnixMicro(), 10) - sig := GetSHA256([]byte(mic))[:5] + now := time.Now() + mic := strconv.FormatInt(now.UnixMicro(), 10) + sig := GetSHA256([]byte(mic))[:5] - return fmt.Sprintf( - "MPSI-%s%s-%s", - now.Format("06"), now.Format("01"), sig, - ) + return fmt.Sprintf( + "MPSI-%s%s-%s", + now.Format("06"), now.Format("01"), sig, + ) } func LoadVulns() ([]Vuln, error) { - var vulns []Vuln - - rows, err := Db.Query("SELECT * FROM vulns") - if err != nil { - return vulns, err - } - defer rows.Close() + var vulns []Vuln - for rows.Next() { - var v Vuln - rows.Scan( - &v.ID, &v.Desc, &v.Source, &v.Severity, - &v.Package, &v.Versions, &v.Status, &v.Message, - &v.Author, &v.Date, &v.Updated) - vulns = append(vulns, v) - } - - return vulns, nil + rows, err := Db.Query("SELECT * FROM vulns") + if err != nil { + return vulns, err + } + defer rows.Close() + + for rows.Next() { + var v Vuln + rows.Scan( + &v.ID, &v.Desc, &v.Source, &v.Severity, + &v.Package, &v.Versions, &v.Status, &v.Message, + &v.Author, &v.Date, &v.Updated) + vulns = append(vulns, v) + } + + return vulns, nil } func FindVuln(id string) (Vuln, bool) { - var vuln Vuln + var vuln Vuln - smt, err := Db.Prepare("SELECT * FROM vulns WHERE id=?") - if err != nil { - return vuln, false - } + smt, err := Db.Prepare("SELECT * FROM vulns WHERE id=?") + if err != nil { + return vuln, false + } - row := smt.QueryRow(id) - err = row.Scan( - &vuln.ID, &vuln.Desc, &vuln.Source, &vuln.Severity, - &vuln.Package, &vuln.Versions, &vuln.Status, &vuln.Message, - &vuln.Author, &vuln.Date, &vuln.Updated) - if err != nil { - return vuln, false - } + row := smt.QueryRow(id) + err = row.Scan( + &vuln.ID, &vuln.Desc, &vuln.Source, &vuln.Severity, + &vuln.Package, &vuln.Versions, &vuln.Status, &vuln.Message, + &vuln.Author, &vuln.Date, &vuln.Updated) + if err != nil { + return vuln, false + } - return vuln, true + return vuln, true } -func AddVuln(v Vuln) error{ - smt, err := Db.Prepare("INSERT INTO vulns VALUES(?,?,?,?,?,?,?,?,?,?,?)") - if err != nil { - return err - } +func AddVuln(v Vuln) error { + smt, err := Db.Prepare("INSERT INTO vulns VALUES(?,?,?,?,?,?,?,?,?,?,?)") + if err != nil { + return err + } - _, err = smt.Exec(&v.ID, &v.Desc, &v.Source, &v.Severity, - &v.Package, &v.Versions, &v.Status, &v.Message, - &v.Author, &v.Date, &v.Updated) - if err != nil { - return err - } + _, err = smt.Exec(&v.ID, &v.Desc, &v.Source, &v.Severity, + &v.Package, &v.Versions, &v.Status, &v.Message, + &v.Author, &v.Date, &v.Updated) + if err != nil { + return err + } - return nil -} + return nil +} func UpdateVuln(v Vuln) error { - smt, err := Db.Prepare("UPDATE vulns SET status=?, message=?, author=?, severity=?, updated=? WHERE id=?") - if err != nil { - return err - } + smt, err := Db.Prepare("UPDATE vulns SET status=?, message=?, author=?, severity=?, updated=? WHERE id=?") + if err != nil { + return err + } - _, err = smt.Exec(v.Status, v.Message, - v.Author, v.Severity, GetFTime(), v.ID) - if err != nil { - return err - } + _, err = smt.Exec(v.Status, v.Message, + v.Author, v.Severity, GetFTime(), v.ID) + if err != nil { + return err + } - return nil + return nil } diff --git a/main.go b/main.go index a17c571..aa4efb4 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ /* - * security | MatterLinux Package Security Tracker - * MatterLinux 2023-2024 (https://matterlinux.xyz) + * security | MatterLinux Package Security Tracker + * MatterLinux 2023-2024 (https://matterlinux.xyz) * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . -*/ + */ package main @@ -30,39 +30,39 @@ import ( ) func main() { - log.SetFlags(log.Lshortfile | log.Ltime) + log.SetFlags(log.Lshortfile | log.Ltime) - engine := html.New("./templates", ".html") - app := fiber.New(fiber.Config{ - DisableStartupMessage: true, - Views: engine, - }) + engine := html.New("./templates", ".html") + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + Views: engine, + }) - err := lib.LoadDatabase() - if err != nil { - log.Fatalf("Failed to load database: %s", err.Error()) - } + err := lib.LoadDatabase() + if err != nil { + log.Fatalf("Failed to load database: %s", err.Error()) + } - app.Static("/", "./public") - app.Get("/", routes.GETIndex) - app.Get("/details/:id", routes.GETDetails) + app.Static("/", "./public") + app.Get("/", routes.GETIndex) + app.Get("/details/:id", routes.GETDetails) - app.Get("/login", routes.GETLogin) - app.Post("/login", routes.POSTLogin) + app.Get("/login", routes.GETLogin) + app.Post("/login", routes.POSTLogin) - app.Use("/manage", routes.MiddleAuth) - app.Get("/manage", routes.GETManage) - app.Get("/manage/logout", routes.GETLogout) - app.Post("/manage/new", routes.POSTNew) - app.Post("/manage/status", routes.POSTStatus) + app.Use("/manage", routes.MiddleAuth) + app.Get("/manage", routes.GETManage) + app.Get("/manage/logout", routes.GETLogout) + app.Post("/manage/new", routes.POSTNew) + app.Post("/manage/status", routes.POSTStatus) - app.Get("*", func(c *fiber.Ctx) error { - return lib.RenderError(c, 404) - }) + app.Get("*", func(c *fiber.Ctx) error { + return lib.RenderError(c, 404) + }) - log.Printf("Starting MatterLinux Security Tracker on port 9876") - err = app.Listen(":9876") - if err != nil { - log.Fatalf("Error starting server: %s", err) - } + log.Printf("Starting MatterLinux Security Tracker on port 9876") + err = app.Listen(":9876") + if err != nil { + log.Fatalf("Error starting server: %s", err) + } } diff --git a/public/index.css b/public/index.css index 8ccd872..23ae97e 100644 --- a/public/index.css +++ b/public/index.css @@ -1,7 +1,7 @@ .vuln { padding: 30px; background: var(--dark-second); - border: solid 1px var(--bright-main); + border: solid 1px var(--bright-second); color: var(--bright-second); } @@ -113,7 +113,7 @@ gap: 10px; background: var(--dark-second); - border: solid 1px var(--bright-main); + border: solid 1px var(--bright-second); } .search-header { diff --git a/public/login.css b/public/login.css index d87b233..30586e3 100644 --- a/public/login.css +++ b/public/login.css @@ -1,7 +1,7 @@ form { background: var(--dark-second); padding: 30px; - border: solid 1px var(--bright-main); + border: solid 1px var(--bright-second); display: flex; flex-direction: column; diff --git a/public/manage.css b/public/manage.css index 593f121..7cda89e 100644 --- a/public/manage.css +++ b/public/manage.css @@ -3,7 +3,7 @@ main a { flex-direction: column; font-size: 15px; - color: var(--bright-main); + color: var(--bright-second); text-align: right; margin-bottom: 10px; } @@ -15,7 +15,7 @@ main a:hover { form { background: var(--dark-second); padding: 30px; - border: solid 1px var(--bright-main); + border: solid 1px var(--bright-second); display: flex; flex-direction: column; diff --git a/routes/index.go b/routes/index.go index bcf7e24..ad11d7d 100644 --- a/routes/index.go +++ b/routes/index.go @@ -13,78 +13,78 @@ import ( var PAGE_SIZE = 32 func GetPage(c *fiber.Ctx) (int, int, int) { - page, err := strconv.Atoi(c.Query("p")) - if err != nil || page <= 0 { - page = 1 - } - - return page, page*PAGE_SIZE, (page*PAGE_SIZE)-PAGE_SIZE + page, err := strconv.Atoi(c.Query("p")) + if err != nil || page <= 0 { + page = 1 + } + + return page, page * PAGE_SIZE, (page * PAGE_SIZE) - PAGE_SIZE } func GETDetails(c *fiber.Ctx) error { - id := c.Params("id") - if id == "" || !strings.HasPrefix(id, "MPSI-") { - return lib.RenderError(c, 404) - } + id := c.Params("id") + if id == "" || !strings.HasPrefix(id, "MPSI-") { + return lib.RenderError(c, 404) + } - v, suc := lib.FindVuln(id) - if !suc { - return lib.RenderError(c, 404) - } - - return c.Render("details", fiber.Map{ - "v": v, - }) + v, suc := lib.FindVuln(id) + if !suc { + return lib.RenderError(c, 404) + } + + return c.Render("details", fiber.Map{ + "v": v, + }) } func GETIndex(c *fiber.Ctx) error { - cur, max, min := GetPage(c) - search_qu := c.Query("q") - search_in := c.Query("i") + cur, max, min := GetPage(c) + search_qu := c.Query("q") + search_in := c.Query("i") - vulns, err := lib.LoadVulns() - if err != nil { - log.Printf("Failed to load vulns: %s", err.Error()) - return lib.RenderError(c, 500) - } + vulns, err := lib.LoadVulns() + if err != nil { + log.Printf("Failed to load vulns: %s", err.Error()) + return lib.RenderError(c, 500) + } - results := []lib.Vuln{} - for i := len(vulns)-1; i >= 0; i-- { - if i >= max || i < min { - continue - } - - switch search_in { - case "desc": - if !lib.ContainsCase(vulns[i].Desc, search_qu){ - continue - } - case "id": - if !lib.ContainsCase(vulns[i].ID, search_qu) { - continue - } - case "pkg": - if !lib.ContainsCase(vulns[i].Package, search_qu) { - continue - } - case "status": - if !lib.ContainsCase(vulns[i].Status, search_qu) { - continue - } - } + results := []lib.Vuln{} + for i := len(vulns) - 1; i >= 0; i-- { + if i >= max || i < min { + continue + } - results = append(results, vulns[i]) + switch search_in { + case "desc": + if !lib.ContainsCase(vulns[i].Desc, search_qu) { + continue + } + case "id": + if !lib.ContainsCase(vulns[i].ID, search_qu) { + continue + } + case "pkg": + if !lib.ContainsCase(vulns[i].Package, search_qu) { + continue + } + case "status": + if !lib.ContainsCase(vulns[i].Status, search_qu) { + continue + } + } - } + results = append(results, vulns[i]) - pages := int64(math.Ceil(float64(len(results))/float64(PAGE_SIZE))) - return c.Render("index", fiber.Map{ - "pages": pages, - "current": cur, - "next": cur+1, - "prev": cur-1, - "vulns": results, - "query": search_qu, - "in": search_in, - }) + } + + pages := int64(math.Ceil(float64(len(results)) / float64(PAGE_SIZE))) + return c.Render("index", fiber.Map{ + "pages": pages, + "current": cur, + "next": cur + 1, + "prev": cur - 1, + "vulns": results, + "query": search_qu, + "in": search_in, + }) } diff --git a/routes/login.go b/routes/login.go index cc9aaab..027042c 100644 --- a/routes/login.go +++ b/routes/login.go @@ -8,47 +8,47 @@ import ( ) func POSTLogin(c *fiber.Ctx) error { - body := struct{ - Username string `form:"username"` - Password string `form:"password"` - }{} + body := struct { + Username string `form:"username"` + Password string `form:"password"` + }{} - err := c.BodyParser(&body) - if err != nil { - return lib.RenderError(c, 400) - } + err := c.BodyParser(&body) + if err != nil { + return lib.RenderError(c, 400) + } - users, err := lib.LoadUsers() - if err != nil { - log.Printf("Failed to load users: %s", err.Error()) - return lib.RenderError(c, 500) - } + users, err := lib.LoadUsers() + if err != nil { + log.Printf("Failed to load users: %s", err.Error()) + return lib.RenderError(c, 500) + } - for _, u := range users { - if u.Username == u.Username && - u.Password == lib.GetSHA256([]byte(body.Password)) { - u.Cookie = lib.GetRandom() - c.Cookie(&fiber.Cookie{ - Name: "auth", - Value: u.Cookie, - }) - err = lib.UpdateUser(u) - if err != nil { - log.Printf("Failed to update user: %s", err.Error()) - return lib.RenderError(c, 500) - } - return c.Redirect("/manage") - } - } + for _, u := range users { + if u.Username == u.Username && + u.Password == lib.GetSHA256([]byte(body.Password)) { + u.Cookie = lib.GetRandom() + c.Cookie(&fiber.Cookie{ + Name: "auth", + Value: u.Cookie, + }) + err = lib.UpdateUser(u) + if err != nil { + log.Printf("Failed to update user: %s", err.Error()) + return lib.RenderError(c, 500) + } + return c.Redirect("/manage") + } + } - c.Status(403) - return c.Render("login", fiber.Map{}) + c.Status(403) + return c.Render("login", fiber.Map{}) } func GETLogin(c *fiber.Ctx) error { - if c.Cookies("auth") != "" { - return c.Redirect("/manage") - } + if c.Cookies("auth") != "" { + return c.Redirect("/manage") + } - return c.Render("login", fiber.Map{}) + return c.Render("login", fiber.Map{}) } diff --git a/routes/manage.go b/routes/manage.go index 1b8aa68..7470af8 100644 --- a/routes/manage.go +++ b/routes/manage.go @@ -8,49 +8,49 @@ import ( ) func MiddleAuth(c *fiber.Ctx) error { - cookie := c.Cookies("auth") + cookie := c.Cookies("auth") - if cookie == "" { - return c.Redirect("/login") - } + if cookie == "" { + return c.Redirect("/login") + } - users, err := lib.LoadUsers() - if err != nil { - log.Printf("Failed to load users: %s", err.Error()) - return lib.RenderError(c, 500) - } + users, err := lib.LoadUsers() + if err != nil { + log.Printf("Failed to load users: %s", err.Error()) + return lib.RenderError(c, 500) + } - for _, u := range users { - if u.Cookie == "notset" || u.Cookie == "" { - continue - } + for _, u := range users { + if u.Cookie == "notset" || u.Cookie == "" { + continue + } - if cookie == u.Cookie { - return c.Next() - } - } + if cookie == u.Cookie { + return c.Next() + } + } - c.ClearCookie("auth") - return c.Redirect("/login") + c.ClearCookie("auth") + return c.Redirect("/login") } func GETManage(c *fiber.Ctx) error { - return c.Render("manage", fiber.Map{}) + return c.Render("manage", fiber.Map{}) } func GETLogout(c *fiber.Ctx) error { - user, err := lib.GetUser(c) - if err != nil { - log.Printf("Failed to load user: %s", err.Error()) - return lib.RenderError(c, 500) - } + user, err := lib.GetUser(c) + if err != nil { + log.Printf("Failed to load user: %s", err.Error()) + return lib.RenderError(c, 500) + } - user.Cookie = "notset" - err = lib.UpdateUser(user) - if err != nil { - log.Printf("Failed to save users: %s", err.Error()) - return lib.RenderError(c, 500) - } + user.Cookie = "notset" + err = lib.UpdateUser(user) + if err != nil { + log.Printf("Failed to save users: %s", err.Error()) + return lib.RenderError(c, 500) + } - return c.Redirect("/login") + return c.Redirect("/login") } diff --git a/routes/new.go b/routes/new.go index 174445a..0b6b26b 100644 --- a/routes/new.go +++ b/routes/new.go @@ -8,48 +8,48 @@ import ( ) func POSTNew(c *fiber.Ctx) error { - body := struct{ - Desc string `form:"desc"` - Source string `form:"source"` - Severity string `form:"severity"` - Package string `form:"package"` - Versions string `form:"versions"` - }{} - - err := c.BodyParser(&body) - if err != nil { - return lib.RenderError(c, 400) - } + body := struct { + Desc string `form:"desc"` + Source string `form:"source"` + Severity string `form:"severity"` + Package string `form:"package"` + Versions string `form:"versions"` + }{} - user, err := lib.GetUser(c) - if err != nil { - log.Printf("Failed to get the user: %s", err.Error()) - return lib.RenderError(c, 500) - } + err := c.BodyParser(&body) + if err != nil { + return lib.RenderError(c, 400) + } - if !lib.ValidSeverity(body.Severity){ - return lib.RenderError(c, 400) - } + user, err := lib.GetUser(c) + if err != nil { + log.Printf("Failed to get the user: %s", err.Error()) + return lib.RenderError(c, 500) + } - v := lib.Vuln{ - ID: lib.GetID(), - Desc: body.Desc, - Source: body.Source, - Severity: body.Severity, - Package: body.Package, - Versions: body.Versions, - Status: "Waiting for review", - Message: "This vulnerability is waiting for a review from the maintainers", - Author: user.Username, - Date: lib.GetFTime(), - Updated: lib.GetFTime(), - } + if !lib.ValidSeverity(body.Severity) { + return lib.RenderError(c, 400) + } - err = lib.AddVuln(v) - if err != nil { - log.Printf("Failed to add vuln: %s", err.Error()) - return lib.RenderError(c, 500) - } + v := lib.Vuln{ + ID: lib.GetID(), + Desc: body.Desc, + Source: body.Source, + Severity: body.Severity, + Package: body.Package, + Versions: body.Versions, + Status: "Waiting for review", + Message: "This vulnerability is waiting for a review from the maintainers", + Author: user.Username, + Date: lib.GetFTime(), + Updated: lib.GetFTime(), + } - return c.Redirect("/manage") + err = lib.AddVuln(v) + if err != nil { + log.Printf("Failed to add vuln: %s", err.Error()) + return lib.RenderError(c, 500) + } + + return c.Redirect("/manage") } diff --git a/routes/status.go b/routes/status.go index 83bfe1d..20a2cfa 100644 --- a/routes/status.go +++ b/routes/status.go @@ -10,39 +10,39 @@ import ( ) func POSTStatus(c *fiber.Ctx) error { - body := struct{ - ID string `form:"id"` - Status string `form:"status"` - Message string `form:"message"` - }{} - - err := c.BodyParser(&body) - if err != nil { - return lib.RenderError(c, 400) - } + body := struct { + ID string `form:"id"` + Status string `form:"status"` + Message string `form:"message"` + }{} - user, err := lib.GetUser(c) - if err != nil { - log.Printf("Failed to get the user: %s", err.Error()) - return lib.RenderError(c, 500) - } + err := c.BodyParser(&body) + if err != nil { + return lib.RenderError(c, 400) + } - vuln, suc := lib.FindVuln(body.ID) - if !suc { - return lib.RenderError(c, 404) - } + user, err := lib.GetUser(c) + if err != nil { + log.Printf("Failed to get the user: %s", err.Error()) + return lib.RenderError(c, 500) + } - vuln.Message = body.Message - vuln.Status = body.Status - if vuln.Author != user.Username && !strings.Contains(vuln.Author, ", "+user.Username){ - vuln.Author += ", "+user.Username - } + vuln, suc := lib.FindVuln(body.ID) + if !suc { + return lib.RenderError(c, 404) + } - err = lib.UpdateVuln(vuln) - if err != nil { - log.Printf("Failed to update the vuln: %s", err.Error()) - return lib.RenderError(c, 500) - } + vuln.Message = body.Message + vuln.Status = body.Status + if vuln.Author != user.Username && !strings.Contains(vuln.Author, ", "+user.Username) { + vuln.Author += ", " + user.Username + } - return c.Redirect("/manage") + err = lib.UpdateVuln(vuln) + if err != nil { + log.Printf("Failed to update the vuln: %s", err.Error()) + return lib.RenderError(c, 500) + } + + return c.Redirect("/manage") }