package utils import ( "encoding/json" "fmt" "log" "net/http" "strings" "git.nutfactory.org/hoernschen/Matrix/config" ) type RequestSummary struct { Method string `json:"method,omitempty"` Uri string `json:"uri,omitempty"` Origin string `json:"origin,omitempty"` Destination string `json:"destination,omitempty"` Content string `json:"content,omitempty"` Signatures map[string]map[string]string `json:"signatures,omitempty"` } type ErrorResponse struct { ErrorCode string `json:"errcode,omitempty"` ErrorMessage string `json:"error,omitempty"` RetryTime int `json:"retry_after_ms,omitempty"` } func CheckRequest(r *http.Request) (response *ErrorResponse) { if !strings.Contains(r.Header.Get("Content-Type"), "application/json") { response = &ErrorResponse{ErrorMessage: "Content Type not JSON"} } return } func CheckAuthHeader(r *http.Request, content string) (response *ErrorResponse) { if !config.AuthentificationCheck { return } authHeader := r.Header.Get("Authorization") if authHeader == "" || !strings.Contains(authHeader, "X-Matrix") { response = &ErrorResponse{ErrorMessage: "Missing Authorization Header"} return } keys := strings.Split(authHeader, ",") origin := strings.Split(keys[0], "=")[1] if !strings.Contains(keys[1], "ed25519") { response = &ErrorResponse{ErrorMessage: "Missing ed25519 Signature Key"} return } key := strings.Split(strings.Replace(strings.Split(keys[1], "=")[1], "\"", "", 2), ":")[1] signature := strings.Replace(strings.Split(keys[2], "=")[1], "\"", "", 2) requestSummary := RequestSummary{ Method: r.Method, Uri: r.RequestURI, Origin: origin, Destination: config.Homeserver, Content: content, } requestSummaryString, err := json.Marshal(requestSummary) if err != nil { response = &ErrorResponse{ErrorMessage: "Error Creating Auth JSON String"} return } correct := VerifySignature([]byte(key), requestSummaryString, signature) if !correct { response = &ErrorResponse{ErrorMessage: "Signature in Auth Header is incorrect"} return } return } func CreateAuthHeader(method string, uri string, destination string, content string) (authHeader string, err error) { requestSummary := RequestSummary{ Method: method, Uri: uri, Origin: config.Homeserver, Destination: destination, Content: content, } SigningContent, err := json.Marshal(requestSummary) if err != nil { return } authHeader = fmt.Sprintf("X-Matrix origin=%s,key=%s,sig=%s", config.Homeserver, config.KeyId, Sign(SigningContent)) return } func GetAccessToken(r *http.Request) (token string, response *ErrorResponse) { token = r.URL.Query().Get("access_token") if token == "" { token = r.Header.Get("Authorization") if token == "" || !strings.Contains(token, "Bearer") { response = &ErrorResponse{ErrorCode: "M_MISSING_TOKEN"} } else { token = strings.Split(token, " ")[1] } } return } func HandleHTTPError(res *http.Response) (response *ErrorResponse) { log.Printf("Statuscode %s", res.Status) response = &ErrorResponse{} decoder := json.NewDecoder(res.Body) err := decoder.Decode(response) if err != nil { log.Printf("Error not parseable") return } log.Printf("%s (%s)", response.ErrorMessage, response.ErrorCode) return } func IsJSONString(s string) bool { var js string return json.Unmarshal([]byte(s), &js) == nil } func IsJSON(s string) bool { var js interface{} return json.Unmarshal([]byte(s), &js) == nil }