worker.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package inbox
  2. import (
  3. "context"
  4. "crypto/x509"
  5. "encoding/pem"
  6. "fmt"
  7. "net/http"
  8. "net/url"
  9. "strings"
  10. "github.com/pkg/errors"
  11. "github.com/go-fed/httpsig"
  12. "github.com/owncast/owncast/activitypub/apmodels"
  13. "github.com/owncast/owncast/activitypub/persistence"
  14. "github.com/owncast/owncast/activitypub/resolvers"
  15. "github.com/owncast/owncast/persistence/configrepository"
  16. log "github.com/sirupsen/logrus"
  17. )
  18. func handle(request apmodels.InboxRequest) {
  19. if verified, err := Verify(request.Request); err != nil {
  20. log.Debugln("Error in attempting to verify request", err)
  21. return
  22. } else if !verified {
  23. log.Debugln("Request failed verification", err)
  24. return
  25. }
  26. if err := resolvers.Resolve(context.Background(), request.Body, handleUpdateRequest, handleFollowInboxRequest, handleLikeRequest, handleAnnounceRequest, handleUndoInboxRequest, handleCreateRequest); err != nil {
  27. log.Debugln("resolver error:", err)
  28. }
  29. }
  30. // Verify will Verify the http signature of an inbound request as well as
  31. // check it against the list of blocked domains.
  32. // nolint: cyclop
  33. func Verify(request *http.Request) (bool, error) {
  34. verifier, err := httpsig.NewVerifier(request)
  35. if err != nil {
  36. return false, errors.Wrap(err, "failed to create key verifier for request")
  37. }
  38. pubKeyID, err := url.Parse(verifier.KeyId())
  39. if err != nil {
  40. return false, errors.Wrap(err, "failed to parse key to get key ID")
  41. }
  42. // Force federation only via servers using https.
  43. if pubKeyID.Scheme != "https" {
  44. return false, errors.New("federated servers must use https: " + pubKeyID.String())
  45. }
  46. signature := request.Header.Get("signature")
  47. if signature == "" {
  48. return false, errors.New("http signature header not found in request")
  49. }
  50. var algorithmString string
  51. signatureComponents := strings.Split(signature, ",")
  52. for _, component := range signatureComponents {
  53. kv := strings.Split(component, "=")
  54. if kv[0] == "algorithm" {
  55. algorithmString = kv[1]
  56. break
  57. }
  58. }
  59. algorithmString = strings.Trim(algorithmString, "\"")
  60. if algorithmString == "" {
  61. return false, errors.New("Unable to determine algorithm to verify request")
  62. }
  63. publicKey, err := resolvers.GetResolvedPublicKeyFromIRI(pubKeyID.String())
  64. if err != nil {
  65. return false, errors.Wrap(err, "failed to resolve actor from IRI to fetch key")
  66. }
  67. var publicKeyActorIRI *url.URL
  68. if ownerProp := publicKey.GetW3IDSecurityV1Owner(); ownerProp != nil {
  69. publicKeyActorIRI = ownerProp.Get()
  70. }
  71. if publicKeyActorIRI == nil {
  72. return false, errors.New("public key owner IRI is empty")
  73. }
  74. // Test to see if the actor is in the list of blocked federated domains.
  75. if isBlockedDomain(publicKeyActorIRI.Hostname()) {
  76. return false, errors.New("domain is blocked")
  77. }
  78. // If actor is specifically blocked, then fail validation.
  79. if blocked, err := isBlockedActor(publicKeyActorIRI); err != nil || blocked {
  80. return false, err
  81. }
  82. key := publicKey.GetW3IDSecurityV1PublicKeyPem().Get()
  83. block, _ := pem.Decode([]byte(key))
  84. if block == nil {
  85. log.Errorln("failed to parse PEM block containing the public key")
  86. return false, errors.New("failed to parse PEM block containing the public key")
  87. }
  88. parsedKey, err := x509.ParsePKIXPublicKey(block.Bytes)
  89. if err != nil {
  90. log.Errorln("failed to parse DER encoded public key: " + err.Error())
  91. return false, errors.Wrap(err, "failed to parse DER encoded public key")
  92. }
  93. algos := []httpsig.Algorithm{
  94. httpsig.Algorithm(algorithmString), // try stated algorithm first then other common algorithms
  95. httpsig.RSA_SHA256, // <- used by almost all fedi software
  96. httpsig.RSA_SHA512,
  97. }
  98. // The verifier will verify the Digest in addition to the HTTP signature
  99. triedAlgos := make(map[httpsig.Algorithm]error)
  100. for _, algorithm := range algos {
  101. if _, tried := triedAlgos[algorithm]; !tried {
  102. err := verifier.Verify(parsedKey, algorithm)
  103. if err == nil {
  104. return true, nil
  105. }
  106. triedAlgos[algorithm] = err
  107. }
  108. }
  109. return false, fmt.Errorf("http signature verification error(s) for: %s: %+v", pubKeyID.String(), triedAlgos)
  110. }
  111. func isBlockedDomain(domain string) bool {
  112. configRepository := configrepository.Get()
  113. blockedDomains := configRepository.GetBlockedFederatedDomains()
  114. for _, blockedDomain := range blockedDomains {
  115. if strings.Contains(domain, blockedDomain) {
  116. return true
  117. }
  118. }
  119. return false
  120. }
  121. func isBlockedActor(actorIRI *url.URL) (bool, error) {
  122. blockedactor, err := persistence.GetFollower(actorIRI.String())
  123. if blockedactor != nil && blockedactor.DisabledAt != nil {
  124. return true, errors.Wrap(err, "remote actor is blocked")
  125. }
  126. return false, nil
  127. }