Fix response to federation /invite to match the format expected by synapse (#221)
* Fix response to /invite to match the format expected by synapse * gb vendor update github.com/matrix-org/gomatrixserverlib * Use gomatrixserverlib.RespInvite * gb vendor update github.com/matrix-org/gomatrixserverlibmain
parent
5740cb3e58
commit
6cb9d900b9
|
@ -101,6 +101,6 @@ func Invite(
|
||||||
// the other servers in the room that we have been invited.
|
// the other servers in the room that we have been invited.
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: 200,
|
Code: 200,
|
||||||
JSON: &signedEvent,
|
JSON: gomatrixserverlib.RespInvite{Event: signedEvent},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@
|
||||||
{
|
{
|
||||||
"importpath": "github.com/matrix-org/gomatrixserverlib",
|
"importpath": "github.com/matrix-org/gomatrixserverlib",
|
||||||
"repository": "https://github.com/matrix-org/gomatrixserverlib",
|
"repository": "https://github.com/matrix-org/gomatrixserverlib",
|
||||||
"revision": "2e9caead882bcdeb999cf4677cfff47e39d3271e",
|
"revision": "fe45d482f2280c9f92f09eb6650e7aa3cca051c5",
|
||||||
"branch": "master"
|
"branch": "master"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -114,7 +114,7 @@ func (fc *Client) LookupUserInfo(matrixServer ServerName, token string) (u UserI
|
||||||
var response *http.Response
|
var response *http.Response
|
||||||
response, err = fc.client.Get(url.String())
|
response, err = fc.client.Get(url.String())
|
||||||
if response != nil {
|
if response != nil {
|
||||||
defer response.Body.Close()
|
defer response.Body.Close() // nolint: errcheck
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -152,7 +152,7 @@ func (fc *Client) LookupUserInfo(matrixServer ServerName, token string) (u UserI
|
||||||
// return a cached copy of the keys or whether they will need to retrieve a fresh
|
// return a cached copy of the keys or whether they will need to retrieve a fresh
|
||||||
// copy of the keys.
|
// copy of the keys.
|
||||||
// Returns the keys or an error if there was a problem talking to the server.
|
// Returns the keys or an error if there was a problem talking to the server.
|
||||||
func (fc *Client) LookupServerKeys(
|
func (fc *Client) LookupServerKeys( // nolint: gocyclo
|
||||||
matrixServer ServerName, keyRequests map[PublicKeyRequest]Timestamp,
|
matrixServer ServerName, keyRequests map[PublicKeyRequest]Timestamp,
|
||||||
) (map[PublicKeyRequest]ServerKeys, error) {
|
) (map[PublicKeyRequest]ServerKeys, error) {
|
||||||
url := url.URL{
|
url := url.URL{
|
||||||
|
@ -185,7 +185,7 @@ func (fc *Client) LookupServerKeys(
|
||||||
|
|
||||||
response, err := fc.client.Post(url.String(), "application/json", bytes.NewBuffer(requestBytes))
|
response, err := fc.client.Post(url.String(), "application/json", bytes.NewBuffer(requestBytes))
|
||||||
if response != nil {
|
if response != nil {
|
||||||
defer response.Body.Close()
|
defer response.Body.Close() // nolint: errcheck
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestToClientEvent(t *testing.T) {
|
func TestToClientEvent(t *testing.T) { // nolint: gocyclo
|
||||||
ev, err := NewEventFromTrustedJSON([]byte(`{
|
ev, err := NewEventFromTrustedJSON([]byte(`{
|
||||||
"type": "m.room.name",
|
"type": "m.room.name",
|
||||||
"state_key": "",
|
"state_key": "",
|
||||||
|
|
|
@ -315,6 +315,7 @@ func (e Event) Sign(signingName string, keyID KeyID, privateKey ed25519.PrivateK
|
||||||
return Event{
|
return Event{
|
||||||
redacted: e.redacted,
|
redacted: e.redacted,
|
||||||
eventJSON: eventJSON,
|
eventJSON: eventJSON,
|
||||||
|
fields: e.fields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +362,7 @@ const (
|
||||||
// Returns an error if the total length of the event JSON is too long.
|
// Returns an error if the total length of the event JSON is too long.
|
||||||
// Returns an error if the event ID doesn't match the origin of the event.
|
// Returns an error if the event ID doesn't match the origin of the event.
|
||||||
// https://matrix.org/docs/spec/client_server/r0.2.0.html#size-limits
|
// https://matrix.org/docs/spec/client_server/r0.2.0.html#size-limits
|
||||||
func (e Event) CheckFields() error {
|
func (e Event) CheckFields() error { // nolint: gocyclo
|
||||||
if len(e.eventJSON) > maxEventLength {
|
if len(e.eventJSON) > maxEventLength {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"gomatrixserverlib: event is too long, length %d > maximum %d",
|
"gomatrixserverlib: event is too long, length %d > maximum %d",
|
||||||
|
|
|
@ -86,7 +86,7 @@ func (s StateNeeded) Tuples() (res []StateKeyTuple) {
|
||||||
// AuthEventReferences returns the auth_events references for the StateNeeded. Returns an error if the
|
// AuthEventReferences returns the auth_events references for the StateNeeded. Returns an error if the
|
||||||
// provider returns an error. If an event is missing from the provider but is required in StateNeeded, it
|
// provider returns an error. If an event is missing from the provider but is required in StateNeeded, it
|
||||||
// is skipped over: no error is returned.
|
// is skipped over: no error is returned.
|
||||||
func (s StateNeeded) AuthEventReferences(provider AuthEventProvider) (refs []EventReference, err error) {
|
func (s StateNeeded) AuthEventReferences(provider AuthEventProvider) (refs []EventReference, err error) { // nolint: gocyclo
|
||||||
var e *Event
|
var e *Event
|
||||||
if s.Create {
|
if s.Create {
|
||||||
if e, err = provider.Create(); err != nil {
|
if e, err = provider.Create(); err != nil {
|
||||||
|
@ -294,7 +294,7 @@ func (a *AuthEvents) ThirdPartyInvite(stateKey string) (*Event, error) {
|
||||||
func NewAuthEvents(events []*Event) AuthEvents {
|
func NewAuthEvents(events []*Event) AuthEvents {
|
||||||
a := AuthEvents{make(map[StateKeyTuple]*Event)}
|
a := AuthEvents{make(map[StateKeyTuple]*Event)}
|
||||||
for _, e := range events {
|
for _, e := range events {
|
||||||
a.AddEvent(e)
|
a.AddEvent(e) // nolint: errcheck
|
||||||
}
|
}
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
@ -775,7 +775,7 @@ type membershipAllower struct {
|
||||||
|
|
||||||
// newMembershipAllower loads the information needed to authenticate the m.room.member event
|
// newMembershipAllower loads the information needed to authenticate the m.room.member event
|
||||||
// from the auth events.
|
// from the auth events.
|
||||||
func newMembershipAllower(authEvents AuthEventProvider, event Event) (m membershipAllower, err error) {
|
func newMembershipAllower(authEvents AuthEventProvider, event Event) (m membershipAllower, err error) { // nolint: gocyclo
|
||||||
stateKey := event.StateKey()
|
stateKey := event.StateKey()
|
||||||
if stateKey == nil {
|
if stateKey == nil {
|
||||||
err = errorf("m.room.member must be a state event")
|
err = errorf("m.room.member must be a state event")
|
||||||
|
@ -816,7 +816,7 @@ func newMembershipAllower(authEvents AuthEventProvider, event Event) (m membersh
|
||||||
}
|
}
|
||||||
|
|
||||||
// membershipAllowed checks whether the membership event is allowed
|
// membershipAllowed checks whether the membership event is allowed
|
||||||
func (m *membershipAllower) membershipAllowed(event Event) error {
|
func (m *membershipAllower) membershipAllowed(event Event) error { // nolint: gocyclo
|
||||||
if m.create.roomID != event.RoomID() {
|
if m.create.roomID != event.RoomID() {
|
||||||
return errorf("create event has different roomID: %q != %q", event.RoomID(), m.create.roomID)
|
return errorf("create event has different roomID: %q != %q", event.RoomID(), m.create.roomID)
|
||||||
}
|
}
|
||||||
|
@ -896,7 +896,7 @@ func (m *membershipAllower) membershipAllowedFromThirdPartyInvite() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// membershipAllowedSelf determines if the change made by the user to their own membership is allowed.
|
// membershipAllowedSelf determines if the change made by the user to their own membership is allowed.
|
||||||
func (m *membershipAllower) membershipAllowedSelf() error {
|
func (m *membershipAllower) membershipAllowedSelf() error { // nolint: gocyclo
|
||||||
if m.newMember.Membership == join {
|
if m.newMember.Membership == join {
|
||||||
// A user that is not in the room is allowed to join if the room
|
// A user that is not in the room is allowed to join if the room
|
||||||
// join rules are "public".
|
// join rules are "public".
|
||||||
|
@ -930,7 +930,7 @@ func (m *membershipAllower) membershipAllowedSelf() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// membershipAllowedOther determines if the user is allowed to change the membership of another user.
|
// membershipAllowedOther determines if the user is allowed to change the membership of another user.
|
||||||
func (m *membershipAllower) membershipAllowedOther() error {
|
func (m *membershipAllower) membershipAllowedOther() error { // nolint: gocyclo
|
||||||
senderLevel := m.powerLevels.userLevel(m.senderID)
|
senderLevel := m.powerLevels.userLevel(m.senderID)
|
||||||
targetLevel := m.powerLevels.userLevel(m.targetID)
|
targetLevel := m.powerLevels.userLevel(m.targetID)
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,9 @@ func TestStateNeededForJoin(t *testing.T) {
|
||||||
StateKey: &skey,
|
StateKey: &skey,
|
||||||
Sender: "@u1:a",
|
Sender: "@u1:a",
|
||||||
}
|
}
|
||||||
b.SetContent(memberContent{"join", nil})
|
if err := b.SetContent(memberContent{"join", nil}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
testStateNeededForAuth(t, `[{
|
testStateNeededForAuth(t, `[{
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@u1:a",
|
"state_key": "@u1:a",
|
||||||
|
@ -149,7 +151,9 @@ func TestStateNeededForInvite(t *testing.T) {
|
||||||
StateKey: &skey,
|
StateKey: &skey,
|
||||||
Sender: "@u1:a",
|
Sender: "@u1:a",
|
||||||
}
|
}
|
||||||
b.SetContent(memberContent{"invite", nil})
|
if err := b.SetContent(memberContent{"invite", nil}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
testStateNeededForAuth(t, `[{
|
testStateNeededForAuth(t, `[{
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@u2:b",
|
"state_key": "@u2:b",
|
||||||
|
@ -170,11 +174,13 @@ func TestStateNeededForInvite3PID(t *testing.T) {
|
||||||
Sender: "@u1:a",
|
Sender: "@u1:a",
|
||||||
}
|
}
|
||||||
|
|
||||||
b.SetContent(memberContent{"invite", &memberThirdPartyInvite{
|
if err := b.SetContent(memberContent{"invite", &memberThirdPartyInvite{
|
||||||
Signed: memberThirdPartyInviteSigned{
|
Signed: memberThirdPartyInviteSigned{
|
||||||
Token: "my_token",
|
Token: "my_token",
|
||||||
},
|
},
|
||||||
}})
|
}}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
testStateNeededForAuth(t, `[{
|
testStateNeededForAuth(t, `[{
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@u2:b",
|
"state_key": "@u2:b",
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ func checkEventContentHash(eventJSON []byte) error {
|
||||||
|
|
||||||
sha256Hash := sha256.Sum256(hashableEventJSON)
|
sha256Hash := sha256.Sum256(hashableEventJSON)
|
||||||
|
|
||||||
if bytes.Compare(sha256Hash[:], []byte(hashes.Sha256)) != 0 {
|
if !bytes.Equal(sha256Hash[:], []byte(hashes.Sha256)) {
|
||||||
return fmt.Errorf("Invalid Sha256 content hash: %v != %v", sha256Hash[:], []byte(hashes.Sha256))
|
return fmt.Errorf("Invalid Sha256 content hash: %v != %v", sha256Hash[:], []byte(hashes.Sha256))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ func verifyEventSignature(signingName string, keyID KeyID, publicKey ed25519.Pub
|
||||||
|
|
||||||
// VerifyEventSignatures checks that each event in a list of events has valid
|
// VerifyEventSignatures checks that each event in a list of events has valid
|
||||||
// signatures from the server that sent it.
|
// signatures from the server that sent it.
|
||||||
func VerifyEventSignatures(events []Event, keyRing KeyRing) error {
|
func VerifyEventSignatures(events []Event, keyRing KeyRing) error { // nolint: gocyclo
|
||||||
var toVerify []VerifyJSONRequest
|
var toVerify []VerifyJSONRequest
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
redactedJSON, err := redactEvent(event.eventJSON)
|
redactedJSON, err := redactEvent(event.eventJSON)
|
||||||
|
|
|
@ -18,8 +18,9 @@ package gomatrixserverlib
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"golang.org/x/crypto/ed25519"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVerifyEventSignatureTestVectors(t *testing.T) {
|
func TestVerifyEventSignatureTestVectors(t *testing.T) {
|
||||||
|
|
|
@ -2,11 +2,12 @@ package gomatrixserverlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/matrix-org/gomatrix"
|
|
||||||
"golang.org/x/crypto/ed25519"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/matrix-org/gomatrix"
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
// An FederationClient is a matrix federation client that adds
|
// An FederationClient is a matrix federation client that adds
|
||||||
|
@ -42,7 +43,7 @@ func (ac *FederationClient) doRequest(r FederationRequest, resBody interface{})
|
||||||
|
|
||||||
res, err := ac.client.Do(req)
|
res, err := ac.client.Do(req)
|
||||||
if res != nil {
|
if res != nil {
|
||||||
defer res.Body.Close()
|
defer res.Body.Close() // nolint: errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -76,6 +77,10 @@ func (ac *FederationClient) doRequest(r FederationRequest, resBody interface{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resBody == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return json.Unmarshal(contents, resBody)
|
return json.Unmarshal(contents, resBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +129,22 @@ func (ac *FederationClient) SendJoin(s ServerName, event Event) (res RespSendJoi
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExchangeThirdPartyInvite sends the builder of a m.room.member event of
|
||||||
|
// "invite" membership derived from a response from invites sent by an identity
|
||||||
|
// server.
|
||||||
|
// This is used to exchange a m.room.third_party_invite event for a m.room.member
|
||||||
|
// one in a room the local server isn't a member of.
|
||||||
|
func (ac *FederationClient) ExchangeThirdPartyInvite(s ServerName, builder EventBuilder) (err error) {
|
||||||
|
path := "/_matrix/federation/v1/exchange_third_party_invite/" +
|
||||||
|
url.PathEscape(builder.RoomID)
|
||||||
|
req := NewFederationRequest("PUT", s, path)
|
||||||
|
if err = req.SetContent(builder); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ac.doRequest(req, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// LookupState retrieves the room state for a room at an event from a
|
// LookupState retrieves the room state for a room at an event from a
|
||||||
// remote matrix server as full matrix events.
|
// remote matrix server as full matrix events.
|
||||||
func (ac *FederationClient) LookupState(s ServerName, roomID, eventID string) (res RespState, err error) {
|
func (ac *FederationClient) LookupState(s ServerName, roomID, eventID string) (res RespState, err error) {
|
||||||
|
|
|
@ -185,9 +185,7 @@ func (r RespSendJoin) MarshalJSON() ([]byte, error) {
|
||||||
// (This protocol oddity is the result of a typo in the synapse matrix
|
// (This protocol oddity is the result of a typo in the synapse matrix
|
||||||
// server, and is preserved to maintain compatibility.)
|
// server, and is preserved to maintain compatibility.)
|
||||||
|
|
||||||
return json.Marshal([]interface{}{200, respSendJoinFields{
|
return json.Marshal([]interface{}{200, respSendJoinFields(r)})
|
||||||
r.StateEvents, r.AuthEvents,
|
|
||||||
}})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaller
|
// UnmarshalJSON implements json.Unmarshaller
|
||||||
|
@ -203,8 +201,7 @@ func (r *RespSendJoin) UnmarshalJSON(data []byte) error {
|
||||||
if err := json.Unmarshal(tuple[1], &fields); err != nil {
|
if err := json.Unmarshal(tuple[1], &fields); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.StateEvents = fields.StateEvents
|
*r = RespSendJoin(fields)
|
||||||
r.AuthEvents = fields.AuthEvents
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,3 +281,39 @@ func checkAllowedByAuthEvents(event Event, eventsByID map[string]*Event) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RespInvite is the content of a response to PUT /_matrix/federation/v1/invite/{roomID}/{eventID}
|
||||||
|
type RespInvite struct {
|
||||||
|
// The invite event signed by recipient server.
|
||||||
|
Event Event
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaller
|
||||||
|
func (r RespInvite) MarshalJSON() ([]byte, error) {
|
||||||
|
// The wire format of a RespInvite is slightly is sent as the second element
|
||||||
|
// of a two element list where the first element is the constant integer 200.
|
||||||
|
// (This protocol oddity is the result of a typo in the synapse matrix
|
||||||
|
// server, and is preserved to maintain compatibility.)
|
||||||
|
return json.Marshal([]interface{}{200, respInviteFields(r)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaller
|
||||||
|
func (r *RespInvite) UnmarshalJSON(data []byte) error {
|
||||||
|
var tuple []rawJSON
|
||||||
|
if err := json.Unmarshal(data, &tuple); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(tuple) != 2 {
|
||||||
|
return fmt.Errorf("gomatrixserverlib: invalid invite response, invalid length: %d != 2", len(tuple))
|
||||||
|
}
|
||||||
|
var fields respInviteFields
|
||||||
|
if err := json.Unmarshal(tuple[1], &fields); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*r = RespInvite(fields)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type respInviteFields struct {
|
||||||
|
Event Event `json:"event"`
|
||||||
|
}
|
||||||
|
|
|
@ -2,23 +2,17 @@
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
golint ./...
|
echo "Installing lint search engine..."
|
||||||
misspell -error .
|
go get github.com/alecthomas/gometalinter/
|
||||||
|
gometalinter --config=linter.json --install --update
|
||||||
|
|
||||||
# gofmt doesn't exit with an error code if the files don't match the expected
|
echo "Looking for lint..."
|
||||||
# format. So we have to run it and see if it outputs anything.
|
gometalinter --config=linter.json
|
||||||
if gofmt -l -s . 2>&1 | read
|
|
||||||
then
|
|
||||||
echo "Error: not all code had been formatted with gofmt."
|
|
||||||
echo "Fixing the following files"
|
|
||||||
gofmt -s -w -l .
|
|
||||||
echo
|
|
||||||
echo "Please add them to the commit"
|
|
||||||
git status --short
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ineffassign .
|
echo "Double checking spelling..."
|
||||||
go tool vet --all --shadow .
|
misspell -error src *.md
|
||||||
gocyclo -over 16 .
|
|
||||||
go test -timeout 5s . ./...
|
echo "Testing..."
|
||||||
|
go test
|
||||||
|
|
||||||
|
echo "Done!"
|
||||||
|
|
|
@ -2,9 +2,10 @@ package gomatrixserverlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/ed25519"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A PublicKeyRequest is a request for a public key with a particular key ID.
|
// A PublicKeyRequest is a request for a public key with a particular key ID.
|
||||||
|
@ -72,7 +73,7 @@ type VerifyJSONResult struct {
|
||||||
// The caller should check the Result field for each entry to see if it was valid.
|
// The caller should check the Result field for each entry to see if it was valid.
|
||||||
// Returns an error if there was a problem talking to the database or one of the other methods
|
// Returns an error if there was a problem talking to the database or one of the other methods
|
||||||
// of fetching the public keys.
|
// of fetching the public keys.
|
||||||
func (k *KeyRing) VerifyJSONs(requests []VerifyJSONRequest) ([]VerifyJSONResult, error) {
|
func (k *KeyRing) VerifyJSONs(requests []VerifyJSONRequest) ([]VerifyJSONResult, error) { // nolint: gocyclo
|
||||||
results := make([]VerifyJSONResult, len(requests))
|
results := make([]VerifyJSONResult, len(requests))
|
||||||
keyIDs := make([][]KeyID, len(requests))
|
keyIDs := make([][]KeyID, len(requests))
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var privateKeySeed1 = `QJvXAPj0D9MUb1exkD8pIWmCvT1xajlsB8jRYz/G5HE`
|
var privateKeySeed1 = `QJvXAPj0D9MUb1exkD8pIWmCvT1xajlsB8jRYz/G5HE`
|
||||||
var privateKeySeed2 = `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`
|
|
||||||
|
|
||||||
// testKeys taken from a copy of synapse.
|
// testKeys taken from a copy of synapse.
|
||||||
var testKeys = `{
|
var testKeys = `{
|
||||||
|
|
|
@ -110,7 +110,7 @@ func FetchKeysDirect(serverName ServerName, addr, sni string) (*ServerKeys, *tls
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
defer tcpconn.Close()
|
defer tcpconn.Close() // nolint: errcheck
|
||||||
tlsconn := tls.Client(tcpconn, &tls.Config{
|
tlsconn := tls.Client(tcpconn, &tls.Config{
|
||||||
ServerName: sni,
|
ServerName: sni,
|
||||||
InsecureSkipVerify: true, // This must be specified even though the TLS library will ignore it.
|
InsecureSkipVerify: true, // This must be specified even though the TLS library will ignore it.
|
||||||
|
@ -134,7 +134,7 @@ func FetchKeysDirect(serverName ServerName, addr, sni string) (*ServerKeys, *tls
|
||||||
// Read the 200 OK from the server.
|
// Read the 200 OK from the server.
|
||||||
response, err := http.ReadResponse(bufio.NewReader(tlsconn), request)
|
response, err := http.ReadResponse(bufio.NewReader(tlsconn), request)
|
||||||
if response != nil {
|
if response != nil {
|
||||||
defer response.Body.Close()
|
defer response.Body.Close() // nolint: errcheck
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -164,9 +164,9 @@ type KeyChecks struct {
|
||||||
MatchingServerName bool // Does the server name match what was requested.
|
MatchingServerName bool // Does the server name match what was requested.
|
||||||
FutureValidUntilTS bool // The valid until TS is in the future.
|
FutureValidUntilTS bool // The valid until TS is in the future.
|
||||||
HasEd25519Key bool // The server has at least one ed25519 key.
|
HasEd25519Key bool // The server has at least one ed25519 key.
|
||||||
|
HasTLSFingerprint bool // The server has at least one fingerprint.
|
||||||
AllEd25519ChecksOK *bool // All the Ed25519 checks are ok. or null if there weren't any to check.
|
AllEd25519ChecksOK *bool // All the Ed25519 checks are ok. or null if there weren't any to check.
|
||||||
Ed25519Checks map[KeyID]Ed25519Checks // Checks for Ed25519 keys.
|
Ed25519Checks map[KeyID]Ed25519Checks // Checks for Ed25519 keys.
|
||||||
HasTLSFingerprint bool // The server has at least one fingerprint.
|
|
||||||
AllTLSFingerprintChecksOK *bool // All the fingerprint checks are ok.
|
AllTLSFingerprintChecksOK *bool // All the fingerprint checks are ok.
|
||||||
TLSFingerprintChecks []TLSFingerprintChecks // Checks for TLS fingerprints.
|
TLSFingerprintChecks []TLSFingerprintChecks // Checks for TLS fingerprints.
|
||||||
MatchingTLSFingerprint *bool // The TLS fingerprint for the connection matches one of the listed fingerprints.
|
MatchingTLSFingerprint *bool // The TLS fingerprint for the connection matches one of the listed fingerprints.
|
||||||
|
@ -206,7 +206,7 @@ func checkFingerprint(connState *tls.ConnectionState, sha256Fingerprints []Base6
|
||||||
cert := connState.PeerCertificates[0]
|
cert := connState.PeerCertificates[0]
|
||||||
digest := sha256.Sum256(cert.Raw)
|
digest := sha256.Sum256(cert.Raw)
|
||||||
for _, fingerprint := range sha256Fingerprints {
|
for _, fingerprint := range sha256Fingerprints {
|
||||||
if bytes.Compare(digest[:], fingerprint) == 0 {
|
if bytes.Equal(digest[:], fingerprint) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"Enable": [
|
||||||
|
"vet",
|
||||||
|
"vetshadow",
|
||||||
|
"gotype",
|
||||||
|
"deadcode",
|
||||||
|
"gocyclo",
|
||||||
|
"golint",
|
||||||
|
"varcheck",
|
||||||
|
"structcheck",
|
||||||
|
"aligncheck",
|
||||||
|
"ineffassign",
|
||||||
|
"gas",
|
||||||
|
"misspell",
|
||||||
|
"gosimple",
|
||||||
|
"megacheck",
|
||||||
|
"unparam",
|
||||||
|
"goimports",
|
||||||
|
"goconst",
|
||||||
|
"unconvert",
|
||||||
|
"errcheck",
|
||||||
|
"interfacer",
|
||||||
|
"testify"
|
||||||
|
]
|
||||||
|
}
|
|
@ -4,13 +4,14 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/matrix-org/util"
|
|
||||||
"golang.org/x/crypto/ed25519"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/matrix-org/util"
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A FederationRequest is a request to send to a remote server or a request
|
// A FederationRequest is a request to send to a remote server or a request
|
||||||
|
@ -156,7 +157,7 @@ func (r *FederationRequest) HTTPRequest() (*http.Request, error) {
|
||||||
//
|
//
|
||||||
// qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / %x80-FF
|
// qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / %x80-FF
|
||||||
//
|
//
|
||||||
func isSafeInHTTPQuotedString(text string) bool {
|
func isSafeInHTTPQuotedString(text string) bool { // nolint: gocyclo
|
||||||
for i := 0; i < len(text); i++ {
|
for i := 0; i < len(text); i++ {
|
||||||
c := text[i]
|
c := text[i]
|
||||||
switch {
|
switch {
|
||||||
|
@ -234,7 +235,7 @@ func VerifyHTTPRequest(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an error if there was a problem reading the content of the request
|
// Returns an error if there was a problem reading the content of the request
|
||||||
func readHTTPRequest(req *http.Request) (*FederationRequest, error) {
|
func readHTTPRequest(req *http.Request) (*FederationRequest, error) { // nolint: gocyclo
|
||||||
var result FederationRequest
|
var result FederationRequest
|
||||||
|
|
||||||
result.fields.Method = req.Method
|
result.fields.Method = req.Method
|
||||||
|
|
|
@ -4,10 +4,11 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"golang.org/x/crypto/ed25519"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This GET request is taken from a request made by a synapse run by sytest.
|
// This GET request is taken from a request made by a synapse run by sytest.
|
||||||
|
@ -62,7 +63,7 @@ func TestSignGetRequest(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
got := string(buf.Bytes())
|
got := buf.String()
|
||||||
want := exampleGetRequest
|
want := exampleGetRequest
|
||||||
if want != got {
|
if want != got {
|
||||||
t.Errorf("Wanted %q got %q", want, got)
|
t.Errorf("Wanted %q got %q", want, got)
|
||||||
|
@ -121,7 +122,7 @@ func TestSignPutRequest(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
got := string(buf.Bytes())
|
got := buf.String()
|
||||||
want := examplePutRequest
|
want := examplePutRequest
|
||||||
if want != got {
|
if want != got {
|
||||||
t.Errorf("Wanted %q got %q", want, got)
|
t.Errorf("Wanted %q got %q", want, got)
|
||||||
|
@ -159,7 +160,6 @@ func TestVerifyPutRequest(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var privateKey1 = mustLoadPrivateKey(privateKeySeed1)
|
var privateKey1 = mustLoadPrivateKey(privateKeySeed1)
|
||||||
var privateKey2 = mustLoadPrivateKey(privateKeySeed2)
|
|
||||||
|
|
||||||
func mustLoadPrivateKey(seed string) ed25519.PrivateKey {
|
func mustLoadPrivateKey(seed string) ed25519.PrivateKey {
|
||||||
seedBytes, err := base64.RawStdEncoding.DecodeString(seed)
|
seedBytes, err := base64.RawStdEncoding.DecodeString(seed)
|
||||||
|
|
|
@ -38,12 +38,12 @@ type DNSResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupServer looks up a matrix server in DNS.
|
// LookupServer looks up a matrix server in DNS.
|
||||||
func LookupServer(serverName ServerName) (*DNSResult, error) {
|
func LookupServer(serverName ServerName) (*DNSResult, error) { // nolint: gocyclo
|
||||||
var result DNSResult
|
var result DNSResult
|
||||||
result.Hosts = map[string]HostResult{}
|
result.Hosts = map[string]HostResult{}
|
||||||
|
|
||||||
hosts := map[string][]net.SRV{}
|
hosts := map[string][]net.SRV{}
|
||||||
if strings.Index(string(serverName), ":") == -1 {
|
if !strings.Contains(string(serverName), ":") {
|
||||||
// If there isn't an explicit port set then try to look up the SRV record.
|
// If there isn't an explicit port set then try to look up the SRV record.
|
||||||
var err error
|
var err error
|
||||||
result.SRVCName, result.SRVRecords, err = net.LookupSRV("matrix", "tcp", string(serverName))
|
result.SRVCName, result.SRVRecords, err = net.LookupSRV("matrix", "tcp", string(serverName))
|
||||||
|
|
|
@ -18,6 +18,7 @@ package gomatrixserverlib
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (r *stateResolver) Member(key string) (*Event, error) {
|
||||||
return r.resolvedMembers[key], nil
|
return r.resolvedMembers[key], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *stateResolver) addConflicted(events []Event) {
|
func (r *stateResolver) addConflicted(events []Event) { // nolint: gocyclo
|
||||||
type conflictKey struct {
|
type conflictKey struct {
|
||||||
eventType string
|
eventType string
|
||||||
stateKey string
|
stateKey string
|
||||||
|
|
Loading…
Reference in New Issue