summaryrefslogtreecommitdiff
path: root/internal/federation/authenticate.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2024-01-31 15:15:28 +0100
committerLibravatar GitHub <noreply@github.com>2024-01-31 14:15:28 +0000
commitb614d33c408b4910ace29567b7c27b45a528a2b4 (patch)
treed7418dad819ae5b1a5f8a94917ae0c2ee1f9d0f5 /internal/federation/authenticate.go
parentImprove context descendant sorting (#2579) (diff)
downloadgotosocial-b614d33c408b4910ace29567b7c27b45a528a2b4.tar.xz
[feature] Try HTTP signature validation with and without query params for incoming requests (#2591)
* [feature] Verify signatures both with + without query params * Bump to tagged version
Diffstat (limited to 'internal/federation/authenticate.go')
-rw-r--r--internal/federation/authenticate.go62
1 files changed, 50 insertions, 12 deletions
diff --git a/internal/federation/authenticate.go b/internal/federation/authenticate.go
index fe611af8c..6899e5ad3 100644
--- a/internal/federation/authenticate.go
+++ b/internal/federation/authenticate.go
@@ -28,7 +28,6 @@ import (
"time"
"codeberg.org/gruf/go-kv"
- "github.com/go-fed/httpsig"
"github.com/superseriousbusiness/activity/streams"
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/config"
@@ -37,6 +36,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/log"
+ "github.com/superseriousbusiness/httpsig"
)
var (
@@ -509,24 +509,62 @@ var signingAlgorithms = []httpsig.Algorithm{
httpsig.ED25519, // Try ED25519 as a long shot.
}
-// verifyAuth verifies auth using generated verifier, according to pubkey and our supported signing algorithms.
-func verifyAuth(l *log.Entry, verifier httpsig.Verifier, pubKey *rsa.PublicKey) bool {
+// Cheeky type to wrap a signing option with a
+// description of that option for logging purposes.
+type signingOption struct {
+ desc string // Description of this options set.
+ sigOpt httpsig.SignatureOption // The options themselves.
+}
+
+var signingOptions = []signingOption{
+ {
+ // Prefer include query params.
+ desc: "include query params",
+ sigOpt: httpsig.SignatureOption{
+ ExcludeQueryStringFromPathPseudoHeader: false,
+ },
+ },
+ {
+ // Fall back to exclude query params.
+ desc: "exclude query params",
+ sigOpt: httpsig.SignatureOption{
+ ExcludeQueryStringFromPathPseudoHeader: true,
+ },
+ },
+}
+
+// verifyAuth verifies auth using generated verifier,
+// according to pubkey, our supported signing algorithms,
+// and signature options. The loops in the function are
+// arranged in such a way that the most common combos are
+// tried first, so that we can hopefully succeed quickly
+// without wasting too many CPU cycles.
+func verifyAuth(
+ l *log.Entry,
+ verifier httpsig.VerifierWithOptions,
+ pubKey *rsa.PublicKey,
+) bool {
if pubKey == nil {
return false
}
- // Loop through all supported algorithms.
+ // Loop through supported algorithms.
for _, algo := range signingAlgorithms {
- // Verify according to pubkey and algo.
- err := verifier.Verify(pubKey, algo)
- if err != nil {
- l.Tracef("authentication NOT PASSED with %s: %v", algo, err)
- continue
- }
+ // Loop through signing options.
+ for _, opt := range signingOptions {
- l.Tracef("authenticated PASSED with %s", algo)
- return true
+ // Try to verify according to this pubkey,
+ // algo, and signing options combination.
+ err := verifier.VerifyWithOptions(pubKey, algo, opt.sigOpt)
+ if err != nil {
+ l.Tracef("authentication NOT PASSED with %s (%s): %v", algo, opt.desc, err)
+ continue
+ }
+
+ l.Tracef("authenticated PASSED with %s (%s)", algo, opt.desc)
+ return true
+ }
}
return false