feature,fix: add request validation and fix attachment
This commit is contained in:
parent
3e0a6353c9
commit
8597ae7147
3 changed files with 42 additions and 38 deletions
11
actor.go
11
actor.go
|
@ -28,12 +28,7 @@ import (
|
||||||
// Actor represents a local actor we can act on
|
// Actor represents a local actor we can act on
|
||||||
// behalf of.
|
// behalf of.
|
||||||
|
|
||||||
//type Attachment struct {
|
|
||||||
// Type string
|
|
||||||
// Name string
|
|
||||||
// Href string
|
|
||||||
// Rel string
|
|
||||||
//}
|
|
||||||
|
|
||||||
type Actor struct {
|
type Actor struct {
|
||||||
Name, summary, actorType, iri string
|
Name, summary, actorType, iri string
|
||||||
|
@ -70,7 +65,7 @@ func MakeActor(name, summary, actorType string) (Actor, error) {
|
||||||
following := make(map[string]interface{})
|
following := make(map[string]interface{})
|
||||||
rejected := make(map[string]interface{})
|
rejected := make(map[string]interface{})
|
||||||
requested := make(map[string]interface{})
|
requested := make(map[string]interface{})
|
||||||
var attachment []interface{}
|
attachment := make([]interface{},0)
|
||||||
followersIRI := baseURL + name + "/followers"
|
followersIRI := baseURL + name + "/followers"
|
||||||
publicKeyID := baseURL + name + "#main-key"
|
publicKeyID := baseURL + name + "#main-key"
|
||||||
iri := baseURL + name
|
iri := baseURL + name
|
||||||
|
@ -358,7 +353,7 @@ func (a *Actor) CreateNote(content, inReplyTo string,attachment []interface{}) {
|
||||||
if inReplyTo != "" {
|
if inReplyTo != "" {
|
||||||
note["inReplyTo"] = inReplyTo
|
note["inReplyTo"] = inReplyTo
|
||||||
}
|
}
|
||||||
if inReplyTo != nil {
|
if attachment != nil {
|
||||||
note["attachment"] = attachment
|
note["attachment"] = attachment
|
||||||
}
|
}
|
||||||
note["id"] = id
|
note["id"] = id
|
||||||
|
|
24
http.go
24
http.go
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/gologme/log"
|
"github.com/gologme/log"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/writefreely/go-nodeinfo"
|
"github.com/writefreely/go-nodeinfo"
|
||||||
|
"github.com/go-fed/httpsig"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -190,7 +190,27 @@ func Serve(actors map[string]Actor) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO check if it's actually an activity
|
// TODO check if it's actually an activity
|
||||||
|
verifier, err := httpsig.NewVerifier(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error then creating verifier")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pubKeyId := verifier.KeyId()
|
||||||
|
algo := httpsig.RSA_SHA256
|
||||||
|
ra,err := NewRemoteActor(pubKeyId)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Can't fetch remote actor")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
verified := verifier.Verify(ra.publicKey, algo)
|
||||||
|
log.Info(verified)
|
||||||
|
if verified != nil {
|
||||||
|
log.Error("Signature mismatch")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
// check if case is going to be an issue
|
// check if case is going to be an issue
|
||||||
switch activity["type"] {
|
switch activity["type"] {
|
||||||
case "Follow":
|
case "Follow":
|
||||||
|
|
|
@ -1,35 +1,38 @@
|
||||||
package activityserve
|
package activityserve
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"encoding/pem"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gologme/log"
|
"github.com/gologme/log"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/rsa"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RemoteActor is a type that holds an actor
|
// RemoteActor is a type that holds an actor
|
||||||
// that we want to interact with
|
// that we want to interact with
|
||||||
type RemoteActor struct {
|
type RemoteActor struct {
|
||||||
iri, outbox, inbox, sharedInbox string
|
iri, outbox, inbox, sharedInbox string
|
||||||
url string
|
url string
|
||||||
info map[string]interface{}
|
info map[string]interface{}
|
||||||
|
publicKey *rsa.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRemoteActor returns a remoteActor which holds
|
// NewRemoteActor returns a remoteActor which holds
|
||||||
// all the info required for an actor we want to
|
// all the info required for an actor we want to
|
||||||
// interact with (not essentially sitting in our instance)
|
// interact with (not essentially sitting in our instance)
|
||||||
func NewRemoteActor(iri string) (RemoteActor, error) {
|
func NewRemoteActor(iri string) (RemoteActor, error) {
|
||||||
|
|
||||||
info, err := get(iri)
|
info, err := get(iri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("Couldn't get remote actor information")
|
log.Info("Couldn't get remote actor information")
|
||||||
log.Info(err)
|
log.Info(err)
|
||||||
return RemoteActor{}, err
|
return RemoteActor{}, err
|
||||||
}
|
}
|
||||||
|
publicKeyBlock := info["publicKey"].(map[string]interface {})
|
||||||
|
publicKeyPem := publicKeyBlock["publicKeyPem"].(string)
|
||||||
|
spkiBlock, _ := pem.Decode([]byte(publicKeyPem))
|
||||||
|
var spkiKey *rsa.PublicKey
|
||||||
|
pubInterface, _ := x509.ParsePKIXPublicKey(spkiBlock.Bytes)
|
||||||
|
spkiKey = pubInterface.(*rsa.PublicKey)
|
||||||
outbox, _ := info["outbox"].(string)
|
outbox, _ := info["outbox"].(string)
|
||||||
inbox, _ := info["inbox"].(string)
|
inbox, _ := info["inbox"].(string)
|
||||||
url, _ := info["url"].(string)
|
url, _ := info["url"].(string)
|
||||||
|
@ -48,6 +51,7 @@ func NewRemoteActor(iri string) (RemoteActor, error) {
|
||||||
inbox: inbox,
|
inbox: inbox,
|
||||||
sharedInbox: sharedInbox,
|
sharedInbox: sharedInbox,
|
||||||
url: url,
|
url: url,
|
||||||
|
publicKey: spkiKey,
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,35 +61,20 @@ func (ra RemoteActor) getLatestPosts(number int) (map[string]interface{}, error)
|
||||||
|
|
||||||
func get(iri string) (info map[string]interface{}, err error) {
|
func get(iri string) (info map[string]interface{}, err error) {
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
sactor,err := GetActor("server","Internal service actor","Service")
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", iri, buf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Info("Failed to get service actor")
|
||||||
log.Info(err)
|
log.Info(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.Header.Add("Accept", "application/activity+json")
|
responseData,err := sactor.signedHTTPGet(iri)
|
||||||
req.Header.Add("User-Agent", userAgent+" "+version)
|
|
||||||
req.Header.Add("Accept-Charset", "utf-8")
|
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("Cannot perform the request")
|
log.Info("Failed to make signed http get request")
|
||||||
log.Info(err)
|
log.Info(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
responseData, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
|
|
||||||
if !isSuccess(resp.StatusCode) {
|
|
||||||
err = fmt.Errorf("GET request to %s failed (%d): %s\nResponse: %s \nHeaders: %s", iri, resp.StatusCode, resp.Status, FormatJSON(responseData), FormatHeaders(req.Header))
|
|
||||||
log.Info(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var e interface{}
|
var e interface{}
|
||||||
err = json.Unmarshal(responseData, &e)
|
err = json.Unmarshal([]byte(responseData), &e)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("something went wrong when unmarshalling the json")
|
log.Info("something went wrong when unmarshalling the json")
|
||||||
|
|
Loading…
Reference in a new issue