Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support HS unbinding 3pids #67

Merged
merged 27 commits into from
Jun 8, 2018
Merged

Support HS unbinding 3pids #67

merged 27 commits into from
Jun 8, 2018

Conversation

dbkr
Copy link
Member

@dbkr dbkr commented May 24, 2018

As per spec draft matrix-org/matrix-spec-proposals#1194

Related synapse PR: matrix-org/synapse#3276

dbkr added 7 commits May 22, 2018 10:42
Adds autoincrement to local and global associations table so we
know IDs will never be re-used if we start deleting associations.

Also some bits of the unbind servlet.
Written in theory - comitting now before going to write the synapse
part
So I can test federation easily
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, it's missing some important things.

I'm also very concerned that we appear to be ignoring feedback from the community in how this API is implemented.

@@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

CREATE TABLE IF NOT EXISTS local_threepid_associations (id integer primary key, medium varchar(16) not null, address varchar(256) not null, mxid varchar(256) not null, ts integer not null, notBefore bigint not null, notAfter bigint not null);
CREATE UNIQUE INDEX IF NOT EXISTS medium_address on local_threepid_associations(medium, address);
CREATE TABLE IF NOT EXISTS local_threepid_associations (id integer primary key autoincrement, medium varchar(16) not null, address varchar(256) not null, mxid varchar(256) not null, ts integer, notBefore bigint, notAfter bigint);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you write a comment which explains what it means for the nullable fields to be null?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer in this schema file but I've commented it in the upgrade script

def upgradeSchema(self):
curVer = self._getSchemaVersion()

if curVer < 1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we do something to make new installations have schema v1 ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this wasn't thought through very well. Hopefully this is more sensible now.

)
cur.execute("DROP TABLE old_local_threepid_associations")

# same for global_threepid_associations
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, except we're keeping the not null constraints.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point: fixed

@@ -22,7 +23,7 @@
from sydent.db.invite_tokens import JoinTokenStore

from sydent.db.valsession import ThreePidValSessionStore
from sydent.db.threepid_associations import LocalAssociationStore
from sydent.db.threepid_associations import LocalAssociationStore, GlobalAssociationStore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks unused? don't you have a PEP8 checker which catches this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops. No, we probably should do if sydent were a better maintained project.

sydent/sydent.py Outdated
from http.servlets.replication import ReplicationPushServlet
from http.servlets.getvalidated3pidservlet import GetValidated3pidServlet
from http.servlets.store_invite_servlet import StoreInviteServlet

from db.version import VersionStore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be up with "from db.sqlitedb import SqliteDatabase" ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's gone now anyway

@@ -100,6 +102,9 @@ def pushUpdates(self, sgAssocs):
'/_matrix/identity/replicate/v1/push',
body)

# XXX: We'll also need to prune the deleted associations out of the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have tried to clarify in the comment

def creatorForNetloc(self, hostname, port):
context = SSL.Context(SSL.SSLv23_METHOD)
try:
_ecCurve = _OpenSSLECCurve(_defaultCurveName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you do matrix-org/synapse#3157 to this please

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


from sydent.http.servlets import get_args, jsonwrap
from sydent.hs_federation.verifier import NoAuthenticationError
from signedjson.sign import SignatureVerifyException
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before twisted, please

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -31,6 +32,7 @@
from http.servlets.pubkeyservlets import EphemeralPubkeyIsValidServlet, PubkeyIsValidServlet
from validators.emailvalidator import EmailValidator
from validators.msisdnvalidator import MsisdnValidator
from hs_federation.verifier import Verifier
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this appears to be missing from the PR

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, fixed

@richvdh richvdh assigned dbkr and unassigned richvdh Jun 1, 2018
dbkr added 8 commits June 4, 2018 13:42
 * Keep v0 schema in .sql scripts
 * Run schema scripts if version == 0
 * Do schema upgrades if v < current, so new db will get v0 schema then upgrade
@dbkr
Copy link
Member Author

dbkr commented Jun 4, 2018

Hopefully missing fewer things now.

@dbkr dbkr assigned richvdh and unassigned dbkr Jun 4, 2018
@richvdh richvdh assigned dbkr and richvdh and unassigned richvdh and dbkr Jun 5, 2018
# We always run the schema files if the version is zero: either the db is
# completely empty and schema-less or it has the v0 schema, which is safe to
# replay the schema files.
if curVer == 0:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, so the files on disk are the v0 schema, and new installations are made to be v1 by first running the v0 schema and then doing the upgrades?

that's fine, but saying so in the comment would help

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

cur.execute("DROP INDEX IF EXISTS local_threepid_medium_address")
cur.execute("ALTER TABLE local_threepid_associations RENAME TO old_local_threepid_associations");
cur.execute(
"CREATE TABLE local_threepid_associations (id integer primary key autoincrement, "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

triple-quotes are totally a thing btw

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(for reference, doesn't need changing now)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh true, although istr synapse used separate single line quotes. whatever.

def removeAssociation(self, threepid, mxid):
cur = self.sydent.db.cursor()

cur.execute(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we bother with this, ooi?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it's a REPLACE INTO, so we don't need to insert an empty record if there's nothing there to start with



"""
Verifies signed json blobs from Matrix Homeservers by finding the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this intended for the file or the class? if the file it goes at the top, if the class it goes inside the class

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yeah

logger = logging.getLogger(__name__)


class NoAuthenticationError(Exception):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this have a docstring describing what it represents please

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

client = FederationHttpClient(self.sydent)
result = yield client.get_json("https://%s:%s/_matrix/key/v2/server/" % host_port)
if 'verify_keys' not in result:
raise Exception("No key found in response")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be a SignatureVerifyException ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it probably ought to

XXX: This contains a very noddy version of the home server
SRV lookup and signature verification. It forms HTTPS URLs
from the result of the SRV lookup which will mean the Host:
parameter in the request will be wrong. It only looks at
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't the wrong Host header going to mess things up? People will have servers behind proxies which rely on it being right.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is taken from the impl I did for user directory searching. I've also realised we actually have another impl of this in sydent for the onbind callbacks (https://github.com/matrix-org/sydent/blob/master/sydent/threepid/bind.py#L91) which has the same shortcoming. I guess now is the time to fix both of them as this presumably is going to start impacting people.

auth_headers = request.requestHeaders.getRawHeaders(b"Authorization")

if not auth_headers:
raise NoAuthenticationError("Missing Authorization headers")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the logic behind when we raise a SignatureVerifyException and when a NoAuthenticationError?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly just me thinking that the you might want separate errors for them to be slightly more helpful (eg. for if you spelt Authorization with an s or something). Granted, with the way we're using it here we could just have the same exception type with a different message.

@defer.inlineCallbacks
def authenticate_request(self, request, content):
"""Authenticates a Matrix federation request based on the X-Matrix header
XXX: Copied largely from synapse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could do with some docstring regardless...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

signature each time and does not contact any other servers
to do perspectives checks.

:param acceptable_server_names If provided and not None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course we use different docstring conventions in different projects. Anyway there should be a colon after the param name aiui. And ideally documentation of a type.

https://pythonhosted.org/an_example_pypi_project/sphinx.html#function-definitions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@richvdh richvdh assigned dbkr and unassigned richvdh Jun 5, 2018
@dbkr
Copy link
Member Author

dbkr commented Jun 8, 2018

OK, this now does more sensible SRV lookup - ptal!

@dbkr dbkr assigned richvdh and unassigned dbkr Jun 8, 2018
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm modulo nits

json_request["signatures"].setdefault(origin, {})[key] = sig

if not json_request["signatures"]:
raise NoAuthenticationError("Missing Authorization headers")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is misleading

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, thanks

:param request: The request object to authenticate
:param content: The content of the request, if any
:type content: bytes or None
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you document the return val please

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@richvdh richvdh assigned dbkr and unassigned richvdh Jun 8, 2018
@dbkr dbkr merged commit 95d92d7 into master Jun 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants