domain blocking more work

This commit is contained in:
tsmethurst 2021-06-30 12:02:28 +02:00
commit 99eb3bf564
11 changed files with 160 additions and 58 deletions

View file

@ -1,6 +1,7 @@
package admin package admin
import ( import (
"errors"
"fmt" "fmt"
"net/http" "net/http"
@ -59,6 +60,10 @@ func (m *Module) DomainBlocksPOSTHandler(c *gin.Context) {
} }
func validateCreateDomainBlock(form *model.DomainBlockCreateRequest) error { func validateCreateDomainBlock(form *model.DomainBlockCreateRequest) error {
// TODO: add some validation here later if necessary // add some more validation here later if necessary
if form.Domain == "" {
return errors.New("empty domain provided")
}
return nil return nil
} }

View file

@ -115,7 +115,7 @@ func getPublicKeyFromResponse(c context.Context, b []byte, keyID *url.URL) (voca
// //
// Also note that this function *does not* dereference the remote account that the signature key is associated with. // Also note that this function *does not* dereference the remote account that the signature key is associated with.
// Other functions should use the returned URL to dereference the remote account, if required. // Other functions should use the returned URL to dereference the remote account, if required.
func (f *federator) AuthenticateFederatedRequest(requestedUsername string, r *http.Request) (*url.URL, error) { func (f *federator) AuthenticateFederatedRequest(requestedUsername string, r *http.Request) (*url.URL, bool, error) {
var publicKey interface{} var publicKey interface{}
var pkOwnerURI *url.URL var pkOwnerURI *url.URL
@ -126,23 +126,24 @@ func (f *federator) AuthenticateFederatedRequest(requestedUsername string, r *ht
verifier, err := httpsig.NewVerifier(r) verifier, err := httpsig.NewVerifier(r)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not create http sig verifier: %s", err) return nil, false, fmt.Errorf("could not create http sig verifier: %s", err)
} }
// The key ID should be given in the signature so that we know where to fetch it from the remote server. // The key ID should be given in the signature so that we know where to fetch it from the remote server.
// This will be something like https://example.org/users/whatever_requesting_user#main-key // This will be something like https://example.org/users/whatever_requesting_user#main-key
requestingPublicKeyID, err := url.Parse(verifier.KeyId()) requestingPublicKeyID, err := url.Parse(verifier.KeyId())
if err != nil { if err != nil {
return nil, fmt.Errorf("could not parse key id into a url: %s", err) return nil, false, fmt.Errorf("could not parse key id into a url: %s", err)
} }
// if the domain is blocked we want to make as few calls towards it as possible, so already bail here if that's the case! // if the domain is blocked we want to make as few calls towards it as possible, so already bail here if that's the case!
blockedDomain, err := f.blockedDomain(requestingPublicKeyID.Host) blockedDomain, err := f.blockedDomain(requestingPublicKeyID.Host)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not tell if domain %s was blocked or not: %s", requestingPublicKeyID.Host, err) return nil, false, fmt.Errorf("could not tell if domain %s was blocked or not: %s", requestingPublicKeyID.Host, err)
} }
if blockedDomain { if blockedDomain {
return nil, fmt.Errorf("host %s was domain blocked, aborting auth", requestingPublicKeyID.Host) f.log.Infof("domain %s is blocked", requestingPublicKeyID.Host)
return nil, false, nil
} }
requestingRemoteAccount := &gtsmodel.Account{} requestingRemoteAccount := &gtsmodel.Account{}
@ -152,12 +153,12 @@ func (f *federator) AuthenticateFederatedRequest(requestedUsername string, r *ht
// LOCAL ACCOUNT REQUEST // LOCAL ACCOUNT REQUEST
// the request is coming from INSIDE THE HOUSE so skip the remote dereferencing // the request is coming from INSIDE THE HOUSE so skip the remote dereferencing
if err := f.db.GetWhere([]db.Where{{Key: "public_key_uri", Value: requestingPublicKeyID.String()}}, requestingLocalAccount); err != nil { if err := f.db.GetWhere([]db.Where{{Key: "public_key_uri", Value: requestingPublicKeyID.String()}}, requestingLocalAccount); err != nil {
return nil, fmt.Errorf("couldn't get local account with public key uri %s from the database: %s", requestingPublicKeyID.String(), err) return nil, false, fmt.Errorf("couldn't get local account with public key uri %s from the database: %s", requestingPublicKeyID.String(), err)
} }
publicKey = requestingLocalAccount.PublicKey publicKey = requestingLocalAccount.PublicKey
pkOwnerURI, err = url.Parse(requestingLocalAccount.URI) pkOwnerURI, err = url.Parse(requestingLocalAccount.URI)
if err != nil { if err != nil {
return nil, fmt.Errorf("error parsing url %s: %s", requestingLocalAccount.URI, err) return nil, false, fmt.Errorf("error parsing url %s: %s", requestingLocalAccount.URI, err)
} }
} else if err := f.db.GetWhere([]db.Where{{Key: "public_key_uri", Value: requestingPublicKeyID.String()}}, requestingRemoteAccount); err == nil { } else if err := f.db.GetWhere([]db.Where{{Key: "public_key_uri", Value: requestingPublicKeyID.String()}}, requestingRemoteAccount); err == nil {
// REMOTE ACCOUNT REQUEST WITH KEY CACHED LOCALLY // REMOTE ACCOUNT REQUEST WITH KEY CACHED LOCALLY
@ -165,7 +166,7 @@ func (f *federator) AuthenticateFederatedRequest(requestedUsername string, r *ht
publicKey = requestingRemoteAccount.PublicKey publicKey = requestingRemoteAccount.PublicKey
pkOwnerURI, err = url.Parse(requestingRemoteAccount.URI) pkOwnerURI, err = url.Parse(requestingRemoteAccount.URI)
if err != nil { if err != nil {
return nil, fmt.Errorf("error parsing url %s: %s", requestingRemoteAccount.URI, err) return nil, false, fmt.Errorf("error parsing url %s: %s", requestingRemoteAccount.URI, err)
} }
} else { } else {
// REMOTE ACCOUNT REQUEST WITHOUT KEY CACHED LOCALLY // REMOTE ACCOUNT REQUEST WITHOUT KEY CACHED LOCALLY
@ -173,72 +174,55 @@ func (f *federator) AuthenticateFederatedRequest(requestedUsername string, r *ht
// so we need to authenticate the request properly by dereferencing the remote key // so we need to authenticate the request properly by dereferencing the remote key
transport, err := f.GetTransportForUser(requestedUsername) transport, err := f.GetTransportForUser(requestedUsername)
if err != nil { if err != nil {
return nil, fmt.Errorf("transport err: %s", err) return nil, false, fmt.Errorf("transport err: %s", err)
} }
// The actual http call to the remote server is made right here in the Dereference function. // The actual http call to the remote server is made right here in the Dereference function.
b, err := transport.Dereference(context.Background(), requestingPublicKeyID) b, err := transport.Dereference(context.Background(), requestingPublicKeyID)
if err != nil { if err != nil {
return nil, fmt.Errorf("error deferencing key %s: %s", requestingPublicKeyID.String(), err) return nil, false, fmt.Errorf("error deferencing key %s: %s", requestingPublicKeyID.String(), err)
} }
// if the key isn't in the response, we can't authenticate the request // if the key isn't in the response, we can't authenticate the request
requestingPublicKey, err := getPublicKeyFromResponse(context.Background(), b, requestingPublicKeyID) requestingPublicKey, err := getPublicKeyFromResponse(context.Background(), b, requestingPublicKeyID)
if err != nil { if err != nil {
return nil, fmt.Errorf("error getting key %s from response %s: %s", requestingPublicKeyID.String(), string(b), err) return nil, false, fmt.Errorf("error getting key %s from response %s: %s", requestingPublicKeyID.String(), string(b), err)
} }
// we should be able to get the actual key embedded in the vocab.W3IDSecurityV1PublicKey // we should be able to get the actual key embedded in the vocab.W3IDSecurityV1PublicKey
pkPemProp := requestingPublicKey.GetW3IDSecurityV1PublicKeyPem() pkPemProp := requestingPublicKey.GetW3IDSecurityV1PublicKeyPem()
if pkPemProp == nil || !pkPemProp.IsXMLSchemaString() { if pkPemProp == nil || !pkPemProp.IsXMLSchemaString() {
return nil, errors.New("publicKeyPem property is not provided or it is not embedded as a value") return nil, false, errors.New("publicKeyPem property is not provided or it is not embedded as a value")
} }
// and decode the PEM so that we can parse it as a golang public key // and decode the PEM so that we can parse it as a golang public key
pubKeyPem := pkPemProp.Get() pubKeyPem := pkPemProp.Get()
block, _ := pem.Decode([]byte(pubKeyPem)) block, _ := pem.Decode([]byte(pubKeyPem))
if block == nil || block.Type != "PUBLIC KEY" { if block == nil || block.Type != "PUBLIC KEY" {
return nil, errors.New("could not decode publicKeyPem to PUBLIC KEY pem block type") return nil, false, errors.New("could not decode publicKeyPem to PUBLIC KEY pem block type")
} }
publicKey, err = x509.ParsePKIXPublicKey(block.Bytes) publicKey, err = x509.ParsePKIXPublicKey(block.Bytes)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not parse public key from block bytes: %s", err) return nil, false, fmt.Errorf("could not parse public key from block bytes: %s", err)
} }
// all good! we just need the URI of the key owner to return // all good! we just need the URI of the key owner to return
pkOwnerProp := requestingPublicKey.GetW3IDSecurityV1Owner() pkOwnerProp := requestingPublicKey.GetW3IDSecurityV1Owner()
if pkOwnerProp == nil || !pkOwnerProp.IsIRI() { if pkOwnerProp == nil || !pkOwnerProp.IsIRI() {
return nil, errors.New("publicKeyOwner property is not provided or it is not embedded as a value") return nil, false, errors.New("publicKeyOwner property is not provided or it is not embedded as a value")
} }
pkOwnerURI = pkOwnerProp.GetIRI() pkOwnerURI = pkOwnerProp.GetIRI()
} }
if publicKey == nil { if publicKey == nil {
return nil, errors.New("returned public key was empty") return nil, false, errors.New("returned public key was empty")
} }
// do the actual authentication here! // do the actual authentication here!
algo := httpsig.RSA_SHA256 // TODO: make this more robust algo := httpsig.RSA_SHA256 // TODO: make this more robust
if err := verifier.Verify(publicKey, algo); err != nil { if err := verifier.Verify(publicKey, algo); err != nil {
return nil, fmt.Errorf("error verifying key %s: %s", requestingPublicKeyID.String(), err) return nil, false, nil
} }
return pkOwnerURI, nil return pkOwnerURI, true, nil
}
func (f *federator) blockedDomain(host string) (bool, error) {
b := &gtsmodel.DomainBlock{}
err := f.db.GetWhere([]db.Where{{Key: "domain", Value: host, CaseInsensitive: true}}, b)
if err == nil {
// block exists
return true, nil
}
if _, ok := err.(db.ErrNoEntries); ok {
// there are no entries so there's no block
return false, nil
}
// there's an actual error
return false, err
} }

View file

@ -21,6 +21,10 @@ func (f *federator) DereferenceRemoteAccount(username string, remoteAccountID *u
f.startHandshake(username, remoteAccountID) f.startHandshake(username, remoteAccountID)
defer f.stopHandshake(username, remoteAccountID) defer f.stopHandshake(username, remoteAccountID)
if blocked, err := f.blockedDomain(remoteAccountID.Host); blocked || err != nil {
return nil, fmt.Errorf("DereferenceRemoteAccount: domain %s is blocked", remoteAccountID.Host)
}
transport, err := f.GetTransportForUser(username) transport, err := f.GetTransportForUser(username)
if err != nil { if err != nil {
return nil, fmt.Errorf("transport err: %s", err) return nil, fmt.Errorf("transport err: %s", err)
@ -66,6 +70,10 @@ func (f *federator) DereferenceRemoteAccount(username string, remoteAccountID *u
} }
func (f *federator) DereferenceRemoteStatus(username string, remoteStatusID *url.URL) (typeutils.Statusable, error) { func (f *federator) DereferenceRemoteStatus(username string, remoteStatusID *url.URL) (typeutils.Statusable, error) {
if blocked, err := f.blockedDomain(remoteStatusID.Host); blocked || err != nil {
return nil, fmt.Errorf("DereferenceRemoteStatus: domain %s is blocked", remoteStatusID.Host)
}
transport, err := f.GetTransportForUser(username) transport, err := f.GetTransportForUser(username)
if err != nil { if err != nil {
return nil, fmt.Errorf("transport err: %s", err) return nil, fmt.Errorf("transport err: %s", err)
@ -148,6 +156,10 @@ func (f *federator) DereferenceRemoteStatus(username string, remoteStatusID *url
} }
func (f *federator) DereferenceRemoteInstance(username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error) { func (f *federator) DereferenceRemoteInstance(username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error) {
if blocked, err := f.blockedDomain(remoteInstanceURI.Host); blocked || err != nil {
return nil, fmt.Errorf("DereferenceRemoteInstance: domain %s is blocked", remoteInstanceURI.Host)
}
transport, err := f.GetTransportForUser(username) transport, err := f.GetTransportForUser(username)
if err != nil { if err != nil {
return nil, fmt.Errorf("transport err: %s", err) return nil, fmt.Errorf("transport err: %s", err)
@ -186,6 +198,14 @@ func (f *federator) DereferenceStatusFields(status *gtsmodel.Status, requestingU
}) })
l.Debug("entering function") l.Debug("entering function")
statusURI, err := url.Parse(status.URI)
if err != nil {
return fmt.Errorf("DereferenceStatusFields: couldn't parse status URI %s: %s", status.URI, err)
}
if blocked, err := f.blockedDomain(statusURI.Host); blocked || err != nil {
return fmt.Errorf("DereferenceStatusFields: domain %s is blocked", statusURI.Host)
}
t, err := f.GetTransportForUser(requestingUsername) t, err := f.GetTransportForUser(requestingUsername)
if err != nil { if err != nil {
return fmt.Errorf("error creating transport: %s", err) return fmt.Errorf("error creating transport: %s", err)
@ -321,6 +341,14 @@ func (f *federator) DereferenceAccountFields(account *gtsmodel.Account, requesti
"requestingUsername": requestingUsername, "requestingUsername": requestingUsername,
}) })
accountURI, err := url.Parse(account.URI)
if err != nil {
return fmt.Errorf("DereferenceAccountFields: couldn't parse account URI %s: %s", account.URI, err)
}
if blocked, err := f.blockedDomain(accountURI.Host); blocked || err != nil {
return fmt.Errorf("DereferenceAccountFields: domain %s is blocked", accountURI.Host)
}
t, err := f.GetTransportForUser(requestingUsername) t, err := f.GetTransportForUser(requestingUsername)
if err != nil { if err != nil {
return fmt.Errorf("error getting transport for user: %s", err) return fmt.Errorf("error getting transport for user: %s", err)
@ -342,12 +370,20 @@ func (f *federator) DereferenceAccountFields(account *gtsmodel.Account, requesti
func (f *federator) DereferenceAnnounce(announce *gtsmodel.Status, requestingUsername string) error { func (f *federator) DereferenceAnnounce(announce *gtsmodel.Status, requestingUsername string) error {
if announce.GTSBoostedStatus == nil || announce.GTSBoostedStatus.URI == "" { if announce.GTSBoostedStatus == nil || announce.GTSBoostedStatus.URI == "" {
// we can't do anything unfortunately // we can't do anything unfortunately
return errors.New("dereferenceAnnounce: no URI to dereference") return errors.New("DereferenceAnnounce: no URI to dereference")
}
boostedStatusURI, err := url.Parse(announce.GTSBoostedStatus.URI)
if err != nil {
return fmt.Errorf("DereferenceAnnounce: couldn't parse boosted status URI %s: %s", announce.GTSBoostedStatus.URI, err)
}
if blocked, err := f.blockedDomain(boostedStatusURI.Host); blocked || err != nil {
return fmt.Errorf("DereferenceAnnounce: domain %s is blocked", boostedStatusURI.Host)
} }
// check if we already have the boosted status in the database // check if we already have the boosted status in the database
boostedStatus := &gtsmodel.Status{} boostedStatus := &gtsmodel.Status{}
err := f.db.GetWhere([]db.Where{{Key: "uri", Value: announce.GTSBoostedStatus.URI}}, boostedStatus) err = f.db.GetWhere([]db.Where{{Key: "uri", Value: announce.GTSBoostedStatus.URI}}, boostedStatus)
if err == nil { if err == nil {
// nice, we already have it so we don't actually need to dereference it from remote // nice, we already have it so we don't actually need to dereference it from remote
announce.Content = boostedStatus.Content announce.Content = boostedStatus.Content
@ -364,12 +400,7 @@ func (f *federator) DereferenceAnnounce(announce *gtsmodel.Status, requestingUse
} }
// we don't have it so we need to dereference it // we don't have it so we need to dereference it
remoteStatusURI, err := url.Parse(announce.GTSBoostedStatus.URI) statusable, err := f.DereferenceRemoteStatus(requestingUsername, boostedStatusURI)
if err != nil {
return fmt.Errorf("dereferenceAnnounce: error parsing url %s: %s", announce.GTSBoostedStatus.URI, err)
}
statusable, err := f.DereferenceRemoteStatus(requestingUsername, remoteStatusURI)
if err != nil { if err != nil {
return fmt.Errorf("dereferenceAnnounce: error dereferencing remote status with id %s: %s", announce.GTSBoostedStatus.URI, err) return fmt.Errorf("dereferenceAnnounce: error dereferencing remote status with id %s: %s", announce.GTSBoostedStatus.URI, err)
} }
@ -460,6 +491,14 @@ func (f *federator) DereferenceAnnounce(announce *gtsmodel.Status, requestingUse
// SIDE EFFECTS: remote header and avatar will be stored in local storage, and the database will be updated // SIDE EFFECTS: remote header and avatar will be stored in local storage, and the database will be updated
// to reflect the creation of these new attachments. // to reflect the creation of these new attachments.
func (f *federator) fetchHeaderAndAviForAccount(targetAccount *gtsmodel.Account, t transport.Transport, refresh bool) error { func (f *federator) fetchHeaderAndAviForAccount(targetAccount *gtsmodel.Account, t transport.Transport, refresh bool) error {
accountURI, err := url.Parse(targetAccount.URI)
if err != nil {
return fmt.Errorf("fetchHeaderAndAviForAccount: couldn't parse account URI %s: %s", targetAccount.URI, err)
}
if blocked, err := f.blockedDomain(accountURI.Host); blocked || err != nil {
return fmt.Errorf("fetchHeaderAndAviForAccount: domain %s is blocked", accountURI.Host)
}
if targetAccount.AvatarRemoteURL != "" && (targetAccount.AvatarMediaAttachmentID == "" || refresh) { if targetAccount.AvatarRemoteURL != "" && (targetAccount.AvatarMediaAttachmentID == "" || refresh) {
a, err := f.mediaHandler.ProcessRemoteHeaderOrAvatar(t, &gtsmodel.MediaAttachment{ a, err := f.mediaHandler.ProcessRemoteHeaderOrAvatar(t, &gtsmodel.MediaAttachment{
RemoteURL: targetAccount.AvatarRemoteURL, RemoteURL: targetAccount.AvatarRemoteURL,

View file

@ -119,10 +119,15 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr
return nil, false, fmt.Errorf("could not fetch requested account with username %s: %s", username, err) return nil, false, fmt.Errorf("could not fetch requested account with username %s: %s", username, err)
} }
publicKeyOwnerURI, err := f.AuthenticateFederatedRequest(requestedAccount.Username, r) publicKeyOwnerURI, authenticated, err := f.AuthenticateFederatedRequest(requestedAccount.Username, r)
if err != nil { if err != nil {
l.Debugf("request not authenticated: %s", err) l.Debugf("request not authenticated: %s", err)
return ctx, false, fmt.Errorf("not authenticated: %s", err) return ctx, false, err
}
if !authenticated {
w.WriteHeader(http.StatusForbidden)
return ctx, false, nil
} }
// authentication has passed, so add an instance entry for this instance if it hasn't been done already // authentication has passed, so add an instance entry for this instance if it hasn't been done already
@ -230,6 +235,14 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er
} }
for _, uri := range actorIRIs { for _, uri := range actorIRIs {
blockedDomain, err := f.blockedDomain(uri.Host);
if err != nil {
return false, fmt.Errorf("error checking domain block: %s", err)
}
if blockedDomain {
return true, nil
}
a := &gtsmodel.Account{} a := &gtsmodel.Account{}
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: uri.String()}}, a); err != nil { if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: uri.String()}}, a); err != nil {
_, ok := err.(db.ErrNoEntries) _, ok := err.(db.ErrNoEntries)

View file

@ -42,7 +42,13 @@ type Federator interface {
FederatingDB() federatingdb.DB FederatingDB() federatingdb.DB
// AuthenticateFederatedRequest can be used to check the authenticity of incoming http-signed requests for federating resources. // AuthenticateFederatedRequest can be used to check the authenticity of incoming http-signed requests for federating resources.
// The given username will be used to create a transport for making outgoing requests. See the implementation for more detailed comments. // The given username will be used to create a transport for making outgoing requests. See the implementation for more detailed comments.
AuthenticateFederatedRequest(username string, r *http.Request) (*url.URL, error) //
// If the request is valid and passes authentication, the URL of the key owner ID will be returned, as well as true, and nil.
//
// If the request does not pass authentication, or there's a domain block, nil, false, nil will be returned.
//
// If something goes wrong during authentication, nil, false, and an error will be returned.
AuthenticateFederatedRequest(username string, r *http.Request) (*url.URL, bool, error)
// FingerRemoteAccount performs a webfinger lookup for a remote account, using the .well-known path. It will return the ActivityPub URI for that // FingerRemoteAccount performs a webfinger lookup for a remote account, using the .well-known path. It will return the ActivityPub URI for that
// account, or an error if it doesn't exist or can't be retrieved. // account, or an error if it doesn't exist or can't be retrieved.
FingerRemoteAccount(requestingUsername string, targetUsername string, targetDomain string) (*url.URL, error) FingerRemoteAccount(requestingUsername string, targetUsername string, targetDomain string) (*url.URL, error)
@ -97,6 +103,7 @@ func NewFederator(db db.DB, federatingDB federatingdb.DB, transportController tr
clock: &Clock{}, clock: &Clock{},
typeConverter: typeConverter, typeConverter: typeConverter,
transportController: transportController, transportController: transportController,
mediaHandler: mediaHandler,
log: log, log: log,
handshakeSync: &sync.Mutex{}, handshakeSync: &sync.Mutex{},
} }

View file

@ -30,6 +30,9 @@ import (
) )
func (f *federator) FingerRemoteAccount(requestingUsername string, targetUsername string, targetDomain string) (*url.URL, error) { func (f *federator) FingerRemoteAccount(requestingUsername string, targetUsername string, targetDomain string) (*url.URL, error) {
if blocked, err := f.blockedDomain(targetDomain); blocked || err != nil {
return nil, fmt.Errorf("FingerRemoteAccount: domain %s is blocked", targetDomain)
}
t, err := f.GetTransportForUser(requestingUsername) t, err := f.GetTransportForUser(requestingUsername)
if err != nil { if err != nil {

View file

@ -0,0 +1,23 @@
package federation
import (
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)
func (f *federator) blockedDomain(host string) (bool, error) {
b := &gtsmodel.DomainBlock{}
err := f.db.GetWhere([]db.Where{{Key: "domain", Value: host, CaseInsensitive: true}}, b)
if err == nil {
// block exists
return true, nil
}
if _, ok := err.(db.ErrNoEntries); ok {
// there are no entries so there's no block
return false, nil
}
// there's an actual error
return false, err
}

View file

@ -35,7 +35,7 @@ func (p *processor) DomainBlockCreate(account *gtsmodel.Account, form *apimodel.
domainBlock := &gtsmodel.DomainBlock{} domainBlock := &gtsmodel.DomainBlock{}
err := p.db.GetWhere([]db.Where{{Key: "domain", Value: form.Domain, CaseInsensitive: true}}, domainBlock) err := p.db.GetWhere([]db.Where{{Key: "domain", Value: form.Domain, CaseInsensitive: true}}, domainBlock)
if err != nil { if err != nil {
if _, ok := err.(db.ErrNoEntries); ok { if _, ok := err.(db.ErrNoEntries); !ok {
// something went wrong in the DB // something went wrong in the DB
return nil, gtserror.NewErrorInternalError(fmt.Errorf("DomainBlockCreate: db error checking for existence of domain block %s: %s", form.Domain, err)) return nil, gtserror.NewErrorInternalError(fmt.Errorf("DomainBlockCreate: db error checking for existence of domain block %s: %s", form.Domain, err))
} }
@ -130,6 +130,7 @@ selectAccountsLoop:
} }
// an actual error has occurred // an actual error has occurred
l.Errorf("domainBlockProcessSideEffects: db error selecting accounts for domain %s: %s", block.Domain, err) l.Errorf("domainBlockProcessSideEffects: db error selecting accounts for domain %s: %s", block.Domain, err)
break selectAccountsLoop
} }
for i, a := range accounts { for i, a := range accounts {

View file

@ -106,8 +106,8 @@ func (p *processor) GetFediUser(requestedUsername string, request *http.Request)
} }
} else if util.IsUserPath(request.URL) { } else if util.IsUserPath(request.URL) {
// if it's a user path, we want to fully authenticate the request before we serve any data, and then we can serve a more complete profile // if it's a user path, we want to fully authenticate the request before we serve any data, and then we can serve a more complete profile
requestingAccountURI, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request) requestingAccountURI, authenticated, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request)
if err != nil { if err != nil || !authenticated {
return nil, gtserror.NewErrorNotAuthorized(err) return nil, gtserror.NewErrorNotAuthorized(err)
} }
@ -152,8 +152,8 @@ func (p *processor) GetFediFollowers(requestedUsername string, request *http.Req
} }
// authenticate the request // authenticate the request
requestingAccountURI, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request) requestingAccountURI, authenticated, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request)
if err != nil { if err != nil || !authenticated {
return nil, gtserror.NewErrorNotAuthorized(err) return nil, gtserror.NewErrorNotAuthorized(err)
} }
@ -197,8 +197,8 @@ func (p *processor) GetFediFollowing(requestedUsername string, request *http.Req
} }
// authenticate the request // authenticate the request
requestingAccountURI, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request) requestingAccountURI, authenticated, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request)
if err != nil { if err != nil || !authenticated {
return nil, gtserror.NewErrorNotAuthorized(err) return nil, gtserror.NewErrorNotAuthorized(err)
} }
@ -242,8 +242,8 @@ func (p *processor) GetFediStatus(requestedUsername string, requestedStatusID st
} }
// authenticate the request // authenticate the request
requestingAccountURI, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request) requestingAccountURI, authenticated, err := p.federator.AuthenticateFederatedRequest(requestedUsername, request)
if err != nil { if err != nil || !authenticated {
return nil, gtserror.NewErrorNotAuthorized(err) return nil, gtserror.NewErrorNotAuthorized(err)
} }
@ -356,6 +356,5 @@ func (p *processor) GetNodeInfo(request *http.Request) (*apimodel.Nodeinfo, gtse
func (p *processor) InboxPost(ctx context.Context, w http.ResponseWriter, r *http.Request) (bool, error) { func (p *processor) InboxPost(ctx context.Context, w http.ResponseWriter, r *http.Request) (bool, error) {
contextWithChannel := context.WithValue(ctx, util.APFromFederatorChanKey, p.fromFederator) contextWithChannel := context.WithValue(ctx, util.APFromFederatorChanKey, p.fromFederator)
posted, err := p.federator.FederatingActor().PostInbox(contextWithChannel, w, r) return p.federator.FederatingActor().PostInbox(contextWithChannel, w, r)
return posted, err
} }

View file

@ -2,6 +2,7 @@ package visibility
import ( import (
"errors" "errors"
"net/url"
"fmt" "fmt"
@ -16,6 +17,15 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount
"statusID": targetStatus.ID, "statusID": targetStatus.ID,
}) })
uri, err := url.Parse(targetStatus.URI)
if err != nil {
return false, fmt.Errorf("StatusVisible: error parsing uri: %s", targetStatus.URI)
}
if blocked, err := f.blockedDomain(uri.Host); blocked || err != nil {
l.Debugf("domain %s is blocked", uri.Host)
return blocked, err
}
aaaaaaaaaa
relevantAccounts, err := f.pullRelevantAccountsFromStatus(targetStatus) relevantAccounts, err := f.pullRelevantAccountsFromStatus(targetStatus)
if err != nil { if err != nil {
l.Debugf("error pulling relevant accounts for status %s: %s", targetStatus.ID, err) l.Debugf("error pulling relevant accounts for status %s: %s", targetStatus.ID, err)

View file

@ -3,6 +3,7 @@ package visibility
import ( import (
"fmt" "fmt"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
) )
@ -79,3 +80,20 @@ type relevantAccounts struct {
BoostedReplyToAccount *gtsmodel.Account BoostedReplyToAccount *gtsmodel.Account
MentionedAccounts []*gtsmodel.Account MentionedAccounts []*gtsmodel.Account
} }
func (f *filter) blockedDomain(host string) (bool, error) {
b := &gtsmodel.DomainBlock{}
err := f.db.GetWhere([]db.Where{{Key: "domain", Value: host, CaseInsensitive: true}}, b)
if err == nil {
// block exists
return true, nil
}
if _, ok := err.(db.ErrNoEntries); ok {
// there are no entries so there's no block
return false, nil
}
// there's an actual error
return false, err
}