From bf929144d781b4b1bb97494654e8627c601669c2 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Date: Fri, 17 Dec 2021 15:15:39 +0100 Subject: [PATCH 1/3] Fix khmac: allowing separators in userids and adding some test cases (#161) * fixing khmac * allowing separators in hmac token userid and adding some test cases * fix unit test import reference * making tests work again --- .github/workflows/python.yml | 2 +- authapi/api/tests.py | 46 ++++++++++++++++++++++++++++++++++-- authapi/utils.py | 22 ++++++++++------- 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 1153eaca..ab5c912c 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -33,7 +33,7 @@ jobs: - uses: actions/checkout@v2 - name: Install node run: | - export TZ=Europe/Madrid + export TZ=UTC ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone apt update apt install -y tzdata diff --git a/authapi/api/tests.py b/authapi/api/tests.py index 616a92e9..8ac89d16 100644 --- a/authapi/api/tests.py +++ b/authapi/api/tests.py @@ -30,7 +30,7 @@ from .models import ACL, AuthEvent, Action, BallotBox, TallySheet, SuccessfulLogin from authmethods.models import Code, MsgLog from authmethods import m_sms_otp -from utils import verifyhmac, reproducible_json_dumps +from utils import HMACToken, verifyhmac, reproducible_json_dumps from authmethods.utils import get_cannonical_tlf, get_user_code def flush_db_load_fixture(ffile="initial.json"): @@ -135,6 +135,49 @@ def delete(self, url, data): return super(JClient, self).delete(url, jdata, content_type="application/json", HTTP_AUTH=self.auth_token) +class TestHmacToken(TestCase): + def test_verify_simple_token(self): + cases = [ + dict( + token="khmac:///sha-256;48a51120ffd034872c4f1fcd3e61f23bade1181309a66c79bcb33e7838423540/example@nvotes.com:AuthEvent:150017:vote:1620927640", + digest='sha-256', + hash='48a51120ffd034872c4f1fcd3e61f23bade1181309a66c79bcb33e7838423540', + msg='example@nvotes.com:AuthEvent:150017:vote:1620927640', + timestamp='1620927640', + userid='example@nvotes.com', + other_values=['AuthEvent', '150017', 'vote'] + ) + ] + self._verify_cases(cases) + + def test_verify_tricky_token(self): + ''' + This is a tricky token because the message contains the '/', ':' and ';' + separators, meaning that the implementation might get confused if not + implemented properly. + ''' + cases = [ + dict( + token="khmac:///sha-256;48a51120ffd034872c4f1fcd3e61f23bade1181309a66c79bcb33e7838423540/ex:amp./le@nvot;es.com:AuthEvent:150017:vote:1620927640", + digest='sha-256', + hash='48a51120ffd034872c4f1fcd3e61f23bade1181309a66c79bcb33e7838423540', + msg='ex:amp./le@nvot;es.com:AuthEvent:150017:vote:1620927640', + timestamp='1620927640', + userid='ex:amp./le@nvot;es.com', + other_values=['AuthEvent', '150017', 'vote'] + ) + ] + self._verify_cases(cases) + + def _verify_cases(self, cases): + for case in cases: + token = HMACToken(case['token']) + self.assertEqual(token.digest, case['digest']) + self.assertEqual(token.hash, case['hash']) + self.assertEqual(token.msg, case['msg']) + self.assertEqual(token.timestamp, case['timestamp']) + self.assertEqual(token.userid, case['userid']) + self.assertEqual(token.other_values, case['other_values']) class ApiTestCreateNotReal(TestCase): def setUpTestData(): @@ -2601,7 +2644,6 @@ def setUp(self): def genhmac(self, key, msg): import hmac - import datetime if not key or not msg: return diff --git a/authapi/utils.py b/authapi/utils.py index 23cbe3e5..1365a18e 100644 --- a/authapi/utils.py +++ b/authapi/utils.py @@ -188,17 +188,22 @@ def verifyhmac(key, msg, seconds=300, at=None): valid = valid and at.check_expiration(seconds) return valid - class HMACToken: def __init__(self, token): self.token = token l = len('khmac:///') self.head = token[0:l] - msg = token[l:] - self.digest, msg = msg.split(';') - self.hash, msg = msg.split('/') - self.msg = msg - self.timestamp = self.msg.split(':')[-1] + tails = token[l:] + self.digest, data = tails.split(';', 1) + self.hash, self.msg = data.split('/', 1) + msg_split = self.msg.split(':') + self.timestamp = msg_split[-1] + if len(msg_split) >= 5: + self.userid = ':'.join(msg_split[0:-4]) + self.other_values = msg_split[-4:-1] + else: + self.userid = msg_split[0] + self.other_values = msg_split[1:-1] def check_expiration(self, seconds=300): t = self.timestamp @@ -214,15 +219,14 @@ def get_userid(self): ''' Note! Can only be used if it's an auth token, with userid ''' - userid = self.msg.split(':')[0] - return userid + return self.userid def get_other_values(self): ''' Removed the userid and the timestamp, returns the list of string objects in the message, that are separated by ':' ''' - return self.msg.split(':')[1:-1] + return self.other_values def constant_time_compare(val1, val2): From 300149d0e042e42f04c04acb765737f173ea1637 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Dec 2021 16:10:43 +0100 Subject: [PATCH 2/3] Bump reportlab from 3.5.34 to 3.5.55 (#163) Bumps [reportlab](http://www.reportlab.com/) from 3.5.34 to 3.5.55. --- updated-dependencies: - dependency-name: reportlab dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8d67c9dd..033e9acf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ ptyprocess==0.5.1 python-dateutil==2.5.3 pytz==2016.4 raven==5.19.0 -reportlab==3.5.34 +reportlab==3.5.55 requests==2.22.0 simplegeneric==0.8.1 traitlets==4.3.3 From 9357332abb24c65b609f2f81f61c86fadbddc22e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Dec 2021 16:10:24 +0100 Subject: [PATCH 3/3] Bump django from 2.2.24 to 2.2.25 (#164) Bumps [django](https://github.com/django/django) from 2.2.24 to 2.2.25. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/2.2.24...2.2.25) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 033e9acf..1dd8bdc5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ billiard==3.6.3.0 celery==5.0.5 contextlib2==0.5.3 decorator==4.0.10 -Django==2.2.24 +Django==2.2.25 django-celery-results==2.0.1 django-cors-headers==3.2.1 django-nose==1.4.5