nip86: fix hash checking and always return a valid RPC response with an error instead of http errors.

This commit is contained in:
fiatjaf
2024-07-11 15:37:09 -03:00
parent 9d6dad073a
commit 71daea9d7b

View File

@@ -42,53 +42,59 @@ type RelayManagementAPI struct {
func (rl *Relay) HandleNIP86(w http.ResponseWriter, r *http.Request) { func (rl *Relay) HandleNIP86(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/nostr+json+rpc") w.Header().Set("Content-Type", "application/nostr+json+rpc")
var (
resp nip86.Response
ctx = r.Context()
req nip86.Request
mp nip86.MethodParams
evt nostr.Event
payloadHash [32]byte
)
payload, err := io.ReadAll(r.Body) payload, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
http.Error(w, "empty request", 400) resp.Error = "empty request"
return goto respond
} }
payloadHash := sha256.Sum256(nil) payloadHash = sha256.Sum256(payload)
auth := r.Header.Get("Authorization") {
spl := strings.Split(auth, "Nostr ") auth := r.Header.Get("Authorization")
if len(spl) != 2 { spl := strings.Split(auth, "Nostr ")
http.Error(w, "missing auth", 401) if len(spl) != 2 {
return resp.Error = "missing auth"
goto respond
}
if evtj, err := base64.StdEncoding.DecodeString(spl[1]); err != nil {
resp.Error = "invalid base64 auth"
goto respond
} else if err := json.Unmarshal(evtj, &evt); err != nil {
resp.Error = "invalid auth event json"
goto respond
} else if ok, _ := evt.CheckSignature(); !ok {
resp.Error = "invalid auth event"
goto respond
} else if pht := evt.Tags.GetFirst([]string{"payload", hex.EncodeToString(payloadHash[:])}); pht == nil {
resp.Error = "invalid auth event payload hash"
goto respond
} else if evt.CreatedAt < nostr.Now()-30 {
resp.Error = "auth event is too old"
goto respond
}
} }
var evt nostr.Event
if evtj, err := base64.StdEncoding.DecodeString(spl[1]); err != nil {
http.Error(w, "invalid base64 auth", 401)
return
} else if err := json.Unmarshal(evtj, &evt); err != nil {
http.Error(w, "invalid auth event json", 401)
return
} else if ok, _ := evt.CheckSignature(); !ok {
http.Error(w, "invalid auth event", 401)
return
} else if pht := evt.Tags.GetFirst([]string{"payload", hex.EncodeToString(payloadHash[:])}); pht == nil {
http.Error(w, "invalid auth event payload hash", 401)
return
} else if evt.CreatedAt < nostr.Now()-30 {
http.Error(w, "auth event is too old", 401)
return
}
var req nip86.Request
if err := json.Unmarshal(payload, &req); err != nil { if err := json.Unmarshal(payload, &req); err != nil {
http.Error(w, "invalid json body", 400) resp.Error = "invalid json body"
return goto respond
} }
mp, err := nip86.DecodeRequest(req) mp, err = nip86.DecodeRequest(req)
if err != nil { if err != nil {
http.Error(w, "invalid params: "+err.Error(), 400) resp.Error = fmt.Sprintf("invalid params: %s", err)
return goto respond
} }
var resp nip86.Response ctx = context.WithValue(ctx, nip86HeaderAuthKey, evt.PubKey)
ctx := context.WithValue(r.Context(), nip86HeaderAuthKey, evt.PubKey)
for _, rac := range rl.ManagementAPI.RejectAPICall { for _, rac := range rl.ManagementAPI.RejectAPICall {
if reject, msg := rac(ctx, mp); reject { if reject, msg := rac(ctx, mp); reject {
resp.Error = msg resp.Error = msg