diff options
author | Jessica Tallon <tsyesika@tsyesika.se> | 2015-08-21 17:57:39 +0200 |
---|---|---|
committer | Jessica Tallon <tsyesika@tsyesika.se> | 2015-08-21 17:57:39 +0200 |
commit | e9bb5879f772e4d546aadb4bb6f935c7c55b8000 (patch) | |
tree | 28a6c88d8b5e21bf4c0c4fbffdea4689595dd535 /mediagoblin/db | |
parent | 3b4ad554c7ae17b1b6e431e235e7744e7670be89 (diff) | |
download | mediagoblin-e9bb5879f772e4d546aadb4bb6f935c7c55b8000.tar.lz mediagoblin-e9bb5879f772e4d546aadb4bb6f935c7c55b8000.tar.xz mediagoblin-e9bb5879f772e4d546aadb4bb6f935c7c55b8000.zip |
Fix #5344 - OAuth NotImplemented exception
This introduces a migration which adds a dummy Client, RequestToken
and AccessToken. These are used when an invalid request comes in,
instead of bailing early, it needs dummy data to prevent timing
attacks.
This then implements the methods which get the IDs of the dummy
objects. If these are changed in the future a migration which checks
for the previous dummy object should be created and updates them to
reflect the new IDs/tokens.
Diffstat (limited to 'mediagoblin/db')
-rw-r--r-- | mediagoblin/db/migrations.py | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 00b0add1..d6806813 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -32,6 +32,8 @@ from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.sql import and_ from sqlalchemy.schema import UniqueConstraint +from mediagoblin import oauth +from mediagoblin.tools import crypto from mediagoblin.db.extratypes import JSONEncoded, MutationDict from mediagoblin.db.migration_tools import ( RegisterMigration, inspect_table, replace_table_hack) @@ -1616,3 +1618,60 @@ def federation_media_entry(db): )) db.commit() + +@RegisterMigration(36, MIGRATIONS) +def create_oauth1_dummies(db): + """ + Creates a dummy client, request and access tokens. + + This is used when invalid data is submitted but real clients and + access tokens. The use of dummy objects prevents timing attacks. + """ + metadata = MetaData(bind=db.bind) + client_table = inspect_table(metadata, "core__clients") + request_token_table = inspect_table(metadata, "core__request_tokens") + access_token_table = inspect_table(metadata, "core__access_tokens") + + # Whilst we don't rely on the secret key being unique or unknown to prevent + # unauthorized clients from using it to authenticate, we still as an extra + # layer of protection created a cryptographically secure key individual to + # each instance that should never be able to be known. + client_secret = crypto.random_string(50) + request_token_secret = crypto.random_string(50) + request_token_verifier = crypto.random_string(50) + access_token_secret = crypto.random_string(50) + + # Dummy created/updated datetime object + epoc_datetime = datetime.datetime.fromtimestamp(0) + + # Create the dummy Client + db.execute(client_table.insert().values( + id=oauth.DUMMY_CLIENT_ID, + secret=client_secret, + application_type="dummy", + created=epoc_datetime, + updated=epoc_datetime + )) + + # Create the dummy RequestToken + db.execute(request_token_table.insert().values( + token=oauth.DUMMY_REQUEST_TOKEN, + secret=request_token_secret, + client=oauth.DUMMY_CLIENT_ID, + verifier=request_token_verifier, + created=epoc_datetime, + updated=epoc_datetime, + callback="oob" + )) + + # Create the dummy AccessToken + db.execute(access_token_table.insert().values( + token=oauth.DUMMY_ACCESS_TOKEN, + secret=access_token_secret, + request_token=oauth.DUMMY_REQUEST_TOKEN, + created=epoc_datetime, + updated=epoc_datetime + )) + + # Commit the changes + db.commit() |