activitypub: Sign the Host header too
Mastodon with `AUTHORIZED_FETCH` enabled requires the `Host` header to be signed too, add it to the default for `setting.Federation.GetHeaders` and `setting.Federation.PostHeaders`. For this to work, we need to sign the request later: not immediately after `NewRequest`, but just before sending them out with `client.Do`. Doing so also lets us use `setting.Federation.GetHeaders` (we were using `.PostHeaders` even for GET requests before). Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
This commit is contained in:
parent
c031881a20
commit
cd17eb0fa7
2 changed files with 30 additions and 13 deletions
|
@ -36,16 +36,19 @@ func CurrentTime() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func containsRequiredHTTPHeaders(method string, headers []string) error {
|
func containsRequiredHTTPHeaders(method string, headers []string) error {
|
||||||
var hasRequestTarget, hasDate, hasDigest bool
|
var hasRequestTarget, hasDate, hasDigest, hasHost bool
|
||||||
for _, header := range headers {
|
for _, header := range headers {
|
||||||
hasRequestTarget = hasRequestTarget || header == httpsig.RequestTarget
|
hasRequestTarget = hasRequestTarget || header == httpsig.RequestTarget
|
||||||
hasDate = hasDate || header == "Date"
|
hasDate = hasDate || header == "Date"
|
||||||
hasDigest = hasDigest || header == "Digest"
|
hasDigest = hasDigest || header == "Digest"
|
||||||
|
hasHost = hasHost || header == "Host"
|
||||||
}
|
}
|
||||||
if !hasRequestTarget {
|
if !hasRequestTarget {
|
||||||
return fmt.Errorf("missing http header for %s: %s", method, httpsig.RequestTarget)
|
return fmt.Errorf("missing http header for %s: %s", method, httpsig.RequestTarget)
|
||||||
} else if !hasDate {
|
} else if !hasDate {
|
||||||
return fmt.Errorf("missing http header for %s: Date", method)
|
return fmt.Errorf("missing http header for %s: Date", method)
|
||||||
|
} else if !hasHost {
|
||||||
|
return fmt.Errorf("missing http header for %s: Host", method)
|
||||||
} else if !hasDigest && method != http.MethodGet {
|
} else if !hasDigest && method != http.MethodGet {
|
||||||
return fmt.Errorf("missing http header for %s: Digest", method)
|
return fmt.Errorf("missing http header for %s: Digest", method)
|
||||||
}
|
}
|
||||||
|
@ -99,29 +102,36 @@ func NewClient(ctx context.Context, user *user_model.User, pubID string) (c *Cli
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRequest function
|
// NewRequest function
|
||||||
func (c *Client) NewRequest(method string, b []byte, to string) (req *http.Request, err error) {
|
func (c *Client) newRequest(method string, b []byte, to string) (req *http.Request, err error) {
|
||||||
buf := bytes.NewBuffer(b)
|
buf := bytes.NewBuffer(b)
|
||||||
req, err = http.NewRequest(method, to, buf)
|
req, err = http.NewRequest(method, to, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Add("Content-Type", ActivityStreamsContentType)
|
req.Header.Add("Accept", "application/json, "+ActivityStreamsContentType)
|
||||||
req.Header.Add("Date", CurrentTime())
|
req.Header.Add("Date", CurrentTime())
|
||||||
|
req.Header.Add("Host", req.URL.Host)
|
||||||
req.Header.Add("User-Agent", "Gitea/"+setting.AppVer)
|
req.Header.Add("User-Agent", "Gitea/"+setting.AppVer)
|
||||||
signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.postHeaders, httpsig.Signature, httpsigExpirationTime)
|
req.Header.Add("Content-Type", ActivityStreamsContentType)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = signer.SignRequest(c.priv, c.pubID, req, b)
|
|
||||||
return req, err
|
return req, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post function
|
// Post function
|
||||||
func (c *Client) Post(b []byte, to string) (resp *http.Response, err error) {
|
func (c *Client) Post(b []byte, to string) (resp *http.Response, err error) {
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
if req, err = c.NewRequest(http.MethodPost, b, to); err != nil {
|
if req, err = c.newRequest(http.MethodPost, b, to); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.postHeaders, httpsig.Signature, httpsigExpirationTime)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := signer.SignRequest(c.priv, c.pubID, req, b); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
resp, err = c.client.Do(req)
|
resp, err = c.client.Do(req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
@ -129,10 +139,17 @@ func (c *Client) Post(b []byte, to string) (resp *http.Response, err error) {
|
||||||
// Create an http GET request with forgejo/gitea specific headers
|
// Create an http GET request with forgejo/gitea specific headers
|
||||||
func (c *Client) Get(to string) (resp *http.Response, err error) {
|
func (c *Client) Get(to string) (resp *http.Response, err error) {
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
emptyBody := []byte{0}
|
if req, err = c.newRequest(http.MethodGet, nil, to); err != nil {
|
||||||
if req, err = c.NewRequest(http.MethodGet, emptyBody, to); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.getHeaders, httpsig.Signature, httpsigExpirationTime)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := signer.SignRequest(c.priv, c.pubID, req, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
resp, err = c.client.Do(req)
|
resp, err = c.client.Do(req)
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ var (
|
||||||
MaxSize: 4,
|
MaxSize: 4,
|
||||||
Algorithms: []string{"rsa-sha256", "rsa-sha512", "ed25519"},
|
Algorithms: []string{"rsa-sha256", "rsa-sha512", "ed25519"},
|
||||||
DigestAlgorithm: "SHA-256",
|
DigestAlgorithm: "SHA-256",
|
||||||
GetHeaders: []string{"(request-target)", "Date"},
|
GetHeaders: []string{"(request-target)", "Date", "Host"},
|
||||||
PostHeaders: []string{"(request-target)", "Date", "Digest"},
|
PostHeaders: []string{"(request-target)", "Date", "Host", "Digest"},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue