From 20b955231b738ca2e3981d7f94a97d73c46b4167 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 16 Apr 2024 11:36:51 -0500 Subject: [PATCH] Confirm webhook is from a trusted source (fix #16) --- config.go | 29 ++++++++++++++++++++++++----- main.go | 30 ++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/config.go b/config.go index ca8e30a..d8a0ff4 100644 --- a/config.go +++ b/config.go @@ -10,9 +10,10 @@ import ( // Configuration stores information retrieved from a configuration file type Configuration struct { - port int64 - sites_dir string - matrix struct { + port int64 + sites_dir string + trusted_servers []string + matrix struct { homeserver string username string password string @@ -91,12 +92,30 @@ func parseConfig(path string, config *Configuration) { panic(err) } + // Trusted servers + var trusted_servers lua.LValue + getTableFromTable(L, table, "trusted_servers", &trusted_servers) // Get the 'trusted_servers' table + // Make sure 'config.trusted_servers' is of type 'table' + if trusted_servers_type := trusted_servers.Type().String(); trusted_servers_type != "table" && + trusted_servers_type != "nil" { + log.Fatalf("config.trusted_servers is of type : '%s', not 'table'", trusted_servers_type) + } else if trusted_servers_type != "nil" { // If type is not nil (has to be table or it would've been caught already) + for i := 1; i <= L.ObjLen(trusted_servers); i++ { // Loop through every trusted server + lv := L.GetTable(trusted_servers, lua.LNumber(i)) + if text, ok := lv.(lua.LString); ok { // Value is string + config.trusted_servers = append(config.trusted_servers, string(text)) + } else if _, ok := lv.(*lua.LNilType); !ok { // Value is not a string, and is not nil + log.Fatalf("config.trusted_servers[%d] is of type : '%s', not 'string'", i, lv.Type().String()) + } + } + } + // Matrix config var matrix lua.LValue - getTableFromTable(L, table, "matrix", &matrix) // Get the 'matrix' sub table + getTableFromTable(L, table, "matrix", &matrix) // Get the 'matrix' table // Make sure 'config.matrix' is of type 'table' if matrix_type := matrix.Type().String(); matrix_type != "table" && matrix_type != "nil" { - log.Fatalf("config.matrix is of type : '%s', not 'table'", matrix.Type().String()) + log.Fatalf("config.matrix is of type : '%s', not 'table'", matrix_type) } else if matrix_type != "nil" { if _, err := getBoolFromTable(L, matrix, "disabled", &config.matrix.disabled); err != nil { panic(err) diff --git a/main.go b/main.go index 0ac8229..95045a6 100644 --- a/main.go +++ b/main.go @@ -4,10 +4,12 @@ package main import ( "encoding/json" "fmt" - "github.com/akamensky/argparse" "log" "net/http" "os" + "strings" + + "github.com/akamensky/argparse" ) // Circle emoji storage. @@ -109,15 +111,35 @@ func main() { configuration.matrix.disabled = *disable_matrix || configuration.matrix.disabled http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // Webhook receiver + log.Print("Recieved request!") var data map[string]interface{} err := json.NewDecoder(r.Body).Decode(&data) if err != nil { log.Panic(err) return } - - go handler(data) // Run the handler - fmt.Fprint(w, "Received!") + check_ips := []string{ // IPs of client to check against trusted_servers + strings.Split(r.RemoteAddr, ":")[0], + r.Header.Get("x-forwarded-for"), + } + found_trusted_server := false + for _, server := range configuration.trusted_servers { + if found_trusted_server { + break + } + for _, ip := range check_ips { + if ip == server { + log.Printf("Request IP matches a trusted server (%s)", ip) + go handler(data) // Run the handler + fmt.Fprint(w, "Received!") + found_trusted_server = true + break + } + } + } + if !found_trusted_server { + log.Print("Request IP doesn't match a trusted server! Dropping...") + } }) // Attempt to create sites_dir if exists, _ := fileExists(configuration.sites_dir); !exists {