Matrix/utils/requestChecker.go
2020-10-11 23:11:30 +02:00

111 lines
3.2 KiB
Go

package utils
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
"nutfactory.org/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) (response *ErrorResponse) {
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[2], "ed25519") {
response = &ErrorResponse{ErrorMessage: "Missing ed25519 Signature Key"}
return
}
key := strings.Split(strings.Replace(strings.Split(keys[2], "=")[1], "\"", "", 2), ":")[1]
signature := strings.Replace(strings.Split(keys[2], "=")[1], "\"", "", 2)
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
content := buf.String()
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, []byte(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 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
}