Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jovuit
funkwhale
Commits
9017acdb
Verified
Commit
9017acdb
authored
Jun 24, 2018
by
Eliot Berriot
Browse files
Fix
#328
: Validate Date header in HTTP Signatures
parent
2a7333df
Changes
4
Hide whitespace changes
Inline
Side-by-side
api/funkwhale_api/federation/factories.py
View file @
9017acdb
...
...
@@ -5,6 +5,7 @@ import requests
import
requests_http_signature
from
django.conf
import
settings
from
django.utils
import
timezone
from
django.utils.http
import
http_date
from
funkwhale_api.factories
import
registry
...
...
@@ -39,7 +40,7 @@ class SignedRequestFactory(factory.Factory):
default_headers
=
{
"User-Agent"
:
"Test"
,
"Host"
:
"test.host"
,
"Date"
:
"Right now"
,
"Date"
:
http_date
(
timezone
.
now
().
timestamp
())
,
"Content-Type"
:
"application/activity+json"
,
}
if
extracted
:
...
...
api/funkwhale_api/federation/signing.py
View file @
9017acdb
import
datetime
import
logging
import
pytz
from
django
import
forms
from
django.utils
import
timezone
from
django.utils.http
import
parse_http_date
import
requests
import
requests_http_signature
...
...
@@ -7,8 +13,33 @@ from . import exceptions, utils
logger
=
logging
.
getLogger
(
__name__
)
# the request Date should be between now - 30s and now + 30s
DATE_HEADER_VALID_FOR
=
30
def
verify_date
(
raw_date
):
if
not
raw_date
:
raise
forms
.
ValidationError
(
"Missing date header"
)
try
:
ts
=
parse_http_date
(
raw_date
)
except
ValueError
as
e
:
raise
forms
.
ValidationError
(
str
(
e
))
dt
=
datetime
.
datetime
.
utcfromtimestamp
(
ts
)
dt
=
dt
.
replace
(
tzinfo
=
pytz
.
utc
)
delta
=
datetime
.
timedelta
(
seconds
=
DATE_HEADER_VALID_FOR
)
now
=
timezone
.
now
()
if
dt
<
now
-
delta
or
dt
>
now
+
delta
:
raise
forms
.
ValidationError
(
"Request Date is too far in the future or in the past"
)
return
dt
def
verify
(
request
,
public_key
):
verify_date
(
request
.
headers
.
get
(
"Date"
))
return
requests_http_signature
.
HTTPSignatureAuth
.
verify
(
request
,
key_resolver
=
lambda
**
kwargs
:
public_key
,
use_auth_header
=
False
)
...
...
api/tests/federation/test_signing.py
View file @
9017acdb
import
cryptography.exceptions
import
datetime
from
django.utils.http
import
http_date
from
django
import
forms
import
pytest
from
funkwhale_api.federation
import
keys
,
signing
...
...
@@ -36,6 +39,20 @@ def test_verify_fails_with_wrong_key(nodb_factories):
signing
.
verify
(
prepared_request
,
wrong_public
)
def
test_verify_fails_with_wrong_date
(
nodb_factories
,
now
):
too_old
=
now
-
datetime
.
timedelta
(
seconds
=
31
)
too_old
=
http_date
(
too_old
.
timestamp
())
private
,
public
=
nodb_factories
[
"federation.KeyPair"
]()
auth
=
nodb_factories
[
"federation.SignatureAuth"
](
key
=
private
)
request
=
nodb_factories
[
"federation.SignedRequest"
](
auth
=
auth
,
headers
=
{
"Date"
:
too_old
}
)
prepared_request
=
request
.
prepare
()
with
pytest
.
raises
(
forms
.
ValidationError
):
signing
.
verify
(
prepared_request
,
public
)
def
test_can_verify_django_request
(
factories
,
fake_request
):
private_key
,
public_key
=
keys
.
get_key_pair
()
signed_request
=
factories
[
"federation.SignedRequest"
](
...
...
@@ -95,14 +112,18 @@ def test_can_verify_django_request_digest_failure(factories, fake_request):
signing
.
verify_django
(
django_request
,
public_key
)
def
test_can_verify_django_request_failure
(
factories
,
fake_request
):
def
test_can_verify_django_request_failure
(
factories
,
fake_request
,
now
):
private_key
,
public_key
=
keys
.
get_key_pair
()
signed_request
=
factories
[
"federation.SignedRequest"
](
auth__key
=
private_key
,
auth__headers
=
[
"date"
]
)
prepared
=
signed_request
.
prepare
()
django_request
=
fake_request
.
get
(
"/"
,
**
{
"HTTP_DATE"
:
"Wrong"
,
"HTTP_SIGNATURE"
:
prepared
.
headers
[
"signature"
]}
"/"
,
**
{
"HTTP_DATE"
:
http_date
((
now
+
datetime
.
timedelta
(
seconds
=
31
)).
timestamp
()),
"HTTP_SIGNATURE"
:
prepared
.
headers
[
"signature"
],
}
)
with
pytest
.
raises
(
cryptography
.
exceptions
.
InvalidSignature
):
with
pytest
.
raises
(
forms
.
ValidationError
):
signing
.
verify_django
(
django_request
,
public_key
)
changes/changelog.d/328.bugfix
0 → 100644
View file @
9017acdb
Validate Date header in HTTP Signatures (#328)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment