Fix behaviour when remote actor got deleted

This commit is contained in:
Jan-Lukas Else 2020-11-13 16:29:22 +01:00
parent abb0fb0d92
commit 7acdca8b92
1 changed files with 33 additions and 19 deletions

View File

@ -86,11 +86,25 @@ func apHandleInbox(w http.ResponseWriter, r *http.Request) {
} }
blogIri := blog.apIri() blogIri := blog.apIri()
// Verify request // Verify request
requestActor, err := apVerifySignature(r) requestActor, requestKey, requestActorStatus, err := apVerifySignature(r)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
if requestActorStatus != 0 {
if requestActorStatus == http.StatusGone || requestActorStatus == http.StatusNotFound {
u, err := url.Parse(requestKey)
if err == nil {
u.Fragment = ""
u.RawFragment = ""
apRemoveFollower(blogName, u.String())
w.WriteHeader(http.StatusAccepted)
return
}
}
http.Error(w, "Error when trying to get request actor", http.StatusBadRequest)
return
}
// Parse activity // Parse activity
activity := make(map[string]interface{}) activity := make(map[string]interface{})
err = json.NewDecoder(r.Body).Decode(&activity) err = json.NewDecoder(r.Body).Decode(&activity)
@ -169,31 +183,31 @@ func apHandleInbox(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
} }
func apVerifySignature(r *http.Request) (*asPerson, error) { func apVerifySignature(r *http.Request) (*asPerson, string, int, error) {
verifier, err := httpsig.NewVerifier(r) verifier, err := httpsig.NewVerifier(r)
if err != nil { if err != nil {
// Error with signature header etc. // Error with signature header etc.
return nil, err return nil, "", 0, err
} }
keyID := verifier.KeyId() keyID := verifier.KeyId()
actor, err := apGetRemoteActor(keyID) actor, statusCode, err := apGetRemoteActor(keyID)
if err != nil { if err != nil || actor == nil || statusCode != 0 {
// Actor not found or something else bad // Actor not found or something else bad
return nil, err return nil, keyID, statusCode, err
} }
if actor == nil || actor.PublicKey == nil || actor.PublicKey.PublicKeyPem == "" { if actor.PublicKey == nil || actor.PublicKey.PublicKeyPem == "" {
return nil, errors.New("Actor has no public key") return nil, keyID, 0, errors.New("Actor has no public key")
} }
block, _ := pem.Decode([]byte(actor.PublicKey.PublicKeyPem)) block, _ := pem.Decode([]byte(actor.PublicKey.PublicKeyPem))
if block == nil { if block == nil {
return nil, errors.New("Public key invalid") return nil, keyID, 0, errors.New("Public key invalid")
} }
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes) pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil { if err != nil {
// Unable to parse public key // Unable to parse public key
return nil, err return nil, keyID, 0, err
} }
return actor, verifier.Verify(pubKey, httpsig.RSA_SHA256) return actor, keyID, 0, verifier.Verify(pubKey, httpsig.RSA_SHA256)
} }
func handleWellKnownHostMeta(w http.ResponseWriter, r *http.Request) { func handleWellKnownHostMeta(w http.ResponseWriter, r *http.Request) {
@ -201,27 +215,27 @@ func handleWellKnownHostMeta(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" type="application/xrd+xml" template="https://` + r.Host + `/.well-known/webfinger?resource={uri}"/></XRD>`)) w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" type="application/xrd+xml" template="https://` + r.Host + `/.well-known/webfinger?resource={uri}"/></XRD>`))
} }
func apGetRemoteActor(iri string) (*asPerson, error) { func apGetRemoteActor(iri string) (*asPerson, int, error) {
req, err := http.NewRequest(http.MethodGet, iri, nil) req, err := http.NewRequest(http.MethodGet, iri, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
req.Header.Add("Accept", contentTypeAS) req.Header.Add("Accept", contentTypeAS)
req.Header.Add("User-Agent", "GoBlog") req.Header.Add("User-Agent", "GoBlog")
resp, err := http.DefaultClient.Do(req) resp, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if !apRequestIsSuccess(resp.StatusCode) { if !apRequestIsSuccess(resp.StatusCode) {
return nil, err return nil, resp.StatusCode, nil
} }
actor := &asPerson{} actor := &asPerson{}
err = json.NewDecoder(resp.Body).Decode(actor) err = json.NewDecoder(resp.Body).Decode(actor)
defer resp.Body.Close() defer resp.Body.Close()
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
return actor, nil return actor, 0, nil
} }
func apGetAllFollowers(blog string) (map[string]string, error) { func apGetAllFollowers(blog string) (map[string]string, error) {
@ -325,8 +339,8 @@ func apAccept(blogName string, blog *configBlog, follow map[string]interface{})
// actor and object are equal // actor and object are equal
return return
} }
follower, err := apGetRemoteActor(newFollower) follower, status, err := apGetRemoteActor(newFollower)
if err != nil { if err != nil || status != 0 {
// Couldn't retrieve remote actor info // Couldn't retrieve remote actor info
log.Println("Failed to retrieve remote actor info:", newFollower) log.Println("Failed to retrieve remote actor info:", newFollower)
return return