Skip to content

Commit 88ad0f1

Browse files
committed
[ci] Update tests in relation to possibilities of both backend and clientside key derivation
1 parent b47fbb9 commit 88ad0f1

File tree

8 files changed

+129
-79
lines changed

8 files changed

+129
-79
lines changed

backend/globaleaks/tests/handlers/admin/test_operation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_admin_test_mail(self):
6464
def test_admin_test_set_user_password(self):
6565
return self._test_operation_handler('set_user_password',
6666
{'user_id': self.dummyReceiver_1['id'],
67-
'password': 'GlobaLeaks123!'})
67+
'password': helpers.VALID_PASSWORD1})
6868

6969
def test_admin_test_send_password_reset_email(self):
7070
return self._test_operation_handler('send_password_reset_email',

backend/globaleaks/tests/handlers/auth/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def test_single_session_per_whistleblower(self):
257257
valid_session = Sessions.get(second_id)
258258
self.assertTrue(valid_session is not None)
259259

260-
self.assertEqual(valid_session.user_role, 'whistleblower')
260+
self.assertEqual(valid_session.role, 'whistleblower')
261261

262262
wbtip_handler = self.request(headers={'x-session': second_id},
263263
handler_cls=WBTipInstance)

backend/globaleaks/tests/handlers/auth/test_auth.py

+55-14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,47 @@
1212
from globaleaks.tests import helpers
1313

1414

15+
class TestAuthTypeHandler(helpers.TestHandlerWithPopulatedDB):
16+
_handler = auth.AuthTypeHandler
17+
18+
# since all logins for roles admin, receiver and custodian happen
19+
# in the same way, the following tests are performed on the recipient user.
20+
21+
@inlineCallbacks
22+
def test_whistleblower_request(self):
23+
handler = self.request({
24+
'username': '',
25+
})
26+
27+
response = yield handler.post()
28+
self.assertTrue('type' in response)
29+
self.assertEqual(response['type'], 'key')
30+
self.assertTrue('salt' in response)
31+
self.assertEqual(response['salt'], helpers.VALID_SALT1)
32+
33+
@inlineCallbacks
34+
def test_receiver1_request(self):
35+
handler = self.request({
36+
'username': 'receiver1',
37+
})
38+
39+
response = yield handler.post()
40+
self.assertTrue('type' in response)
41+
self.assertEqual(response['type'], 'key')
42+
self.assertTrue('salt' in response)
43+
self.assertEqual(response['salt'], helpers.VALID_SALT1)
44+
45+
@inlineCallbacks
46+
def test_receiver2_request(self):
47+
handler = self.request({
48+
'username': 'receiver2',
49+
})
50+
51+
response = yield handler.post()
52+
self.assertTrue('type' in response)
53+
self.assertEqual(response['type'], 'password')
54+
55+
1556
class TestAuthentication(helpers.TestHandlerWithPopulatedDB):
1657
_handler = auth.AuthenticationHandler
1758

@@ -23,7 +64,7 @@ def test_successful_login(self):
2364
handler = self.request({
2465
'tid': 1,
2566
'username': 'admin',
26-
'password': helpers.VALID_PASSWORD1,
67+
'password': helpers.VALID_KEY1,
2768
'authcode': '',
2869
})
2970
response = yield handler.post()
@@ -34,7 +75,7 @@ def test_successful_multitenant_login_switch(self):
3475
handler = self.request({
3576
'tid': 1,
3677
'username': 'admin',
37-
'password': helpers.VALID_PASSWORD1,
78+
'password': helpers.VALID_KEY1,
3879
'authcode': ''
3980
})
4081

@@ -52,7 +93,7 @@ def test_accept_login_in_https(self):
5293
handler = self.request({
5394
'tid': 1,
5495
'username': 'admin',
55-
'password': helpers.VALID_PASSWORD1,
96+
'password': helpers.VALID_KEY1,
5697
'authcode': ''
5798
})
5899
State.tenants[1].cache['https_admin'] = True
@@ -64,7 +105,7 @@ def test_deny_login_in_https(self):
64105
handler = self.request({
65106
'tid': 1,
66107
'username': 'admin',
67-
'password': helpers.VALID_PASSWORD1,
108+
'password': helpers.VALID_KEY1,
68109
'authcode': ''
69110
})
70111
State.tenants[1].cache['https_admin'] = False
@@ -101,7 +142,7 @@ def test_single_session_per_user(self):
101142
handler = self.request({
102143
'tid': 1,
103144
'username': 'admin',
104-
'password': helpers.VALID_PASSWORD1,
145+
'password': helpers.VALID_KEY1,
105146
'authcode': '',
106147
})
107148

@@ -110,7 +151,7 @@ def test_single_session_per_user(self):
110151
handler = self.request({
111152
'tid': 1,
112153
'username': 'admin',
113-
'password': helpers.VALID_PASSWORD1,
154+
'password': helpers.VALID_KEY1,
114155
'authcode': '',
115156
})
116157

@@ -124,7 +165,7 @@ def test_session_is_revoked(self):
124165
auth_handler = self.request({
125166
'tid': 1,
126167
'username': 'receiver1',
127-
'password': helpers.VALID_PASSWORD1,
168+
'password': helpers.VALID_KEY1,
128169
'authcode': '',
129170
})
130171

@@ -140,7 +181,7 @@ def test_session_is_revoked(self):
140181
auth_handler = self.request({
141182
'tid': 1,
142183
'username': 'receiver1',
143-
'password': helpers.VALID_PASSWORD1,
184+
'password': helpers.VALID_KEY1,
144185
'authcode': '',
145186
})
146187

@@ -166,7 +207,7 @@ def test_login_reject_on_ip_filtering(self):
166207
handler = self.request({
167208
'tid': 1,
168209
'username': 'admin',
169-
'password': helpers.VALID_PASSWORD1,
210+
'password': helpers.VALID_KEY1,
170211
'authcode': ''
171212
}, client_addr=b'192.168.1.1')
172213
yield self.assertFailure(handler.post(), errors.AccessLocationInvalid)
@@ -179,7 +220,7 @@ def test_login_success_on_ip_filtering(self):
179220
handler = self.request({
180221
'tid': 1,
181222
'username': 'admin',
182-
'password': helpers.VALID_PASSWORD1,
223+
'password': helpers.VALID_KEY1,
183224
'authcode': ''
184225
}, client_addr=b'192.168.2.1')
185226
response = yield handler.post()
@@ -192,15 +233,15 @@ class TestReceiptAuth(helpers.TestHandlerWithPopulatedDB):
192233
@inlineCallbacks
193234
def test_invalid_whistleblower_login(self):
194235
handler = self.request({
195-
'receipt': 'INVALIDRECEIPT',
236+
'receipt': 'INVALIDRECEIPT'
196237
})
197238
yield self.assertFailure(handler.post(), errors.InvalidAuthentication)
198239

199240
@inlineCallbacks
200241
def test_successful_whistleblower_login(self):
201242
yield self.perform_full_submission_actions()
202243
handler = self.request({
203-
'receipt': self.lastReceipt,
244+
'receipt': self.lastReceipt
204245
})
205246
handler.request.client_using_tor = True
206247
response = yield handler.post()
@@ -257,7 +298,7 @@ def test_single_session_per_whistleblower(self):
257298
valid_session = Sessions.get(second_id)
258299
self.assertTrue(valid_session is not None)
259300

260-
self.assertEqual(valid_session.user_role, 'whistleblower')
301+
self.assertEqual(valid_session.role, 'whistleblower')
261302

262303
wbtip_handler = self.request(headers={'x-session': second_id},
263304
handler_cls=WBTipInstance)
@@ -276,7 +317,7 @@ def test_successful_admin_session_setup_renewal_and_logout(self):
276317
handler = self.request({
277318
'tid': 1,
278319
'username': 'admin',
279-
'password': helpers.VALID_PASSWORD1,
320+
'password': helpers.VALID_KEY1,
280321
'authcode': ''
281322
})
282323

backend/globaleaks/tests/handlers/user/test_user.py

+7-26
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# -*- coding: utf-8 -*
2-
import base64
32
import time
43

54
from cryptography.hazmat.backends import default_backend
65
from cryptography.hazmat.primitives.twofactor.totp import TOTP
76
from cryptography.hazmat.primitives.hashes import SHA1
87

8+
from nacl.encoding import Base32Encoder
9+
910
from twisted.internet.defer import inlineCallbacks
1011

1112
from globaleaks.handlers import user
@@ -116,7 +117,7 @@ def test_2fa(self):
116117
self.assertFailure(handler.put(), errors.InvalidTwoFactorAuthCode)
117118

118119
# Attempt enrolling for 2FA with a valid token
119-
totp = TOTP(base64.b32decode(totp_secret), 6, SHA1(), 30, default_backend())
120+
totp = TOTP(Base32Encoder.decode(totp_secret), 6, SHA1(), 30, default_backend())
120121
current_token = totp.generate(time.time()).decode()
121122

122123
data_request = {
@@ -158,30 +159,10 @@ def _test_operation_handler(self, operation, args={}):
158159

159160
@inlineCallbacks
160161
def test_user_change_password(self):
161-
valid_password = 'validPassword1!'
162-
163-
weak_passwords = [
164-
'invalidpassword1!', # no uppercase characters
165-
'INVALIDPASSWORD1!', # no lowercase characters
166-
'invalidPassword!!', # no number characters
167-
'invalidPassword11', # no symbol characters
168-
'shortP1!' # short password below 10 characters
169-
]
170-
171-
for password in weak_passwords:
172-
yield self.assertFailure(self._test_operation_handler('change_password',
173-
{'password': password,
174-
'current': helpers.VALID_PASSWORD1}),
175-
errors.InputValidationError)
176-
177-
yield self.assertFailure(self._test_operation_handler('change_password',
178-
{'password': valid_password,
179-
'current': 'INVALID_OLD_PASSWORD'}),
180-
errors.InvalidOldPassword)
181-
182-
yield self._test_operation_handler('change_password',
183-
{'password': valid_password,
184-
'current': helpers.VALID_PASSWORD1})
162+
yield self.assertFailure(self._test_operation_handler('change_password', {'password': helpers.VALID_KEY1}),
163+
errors.PasswordReuseError)
164+
165+
yield self._test_operation_handler('change_password', {'password': helpers.VALID_KEY2})
185166

186167
def test_user_get_recovery_key(self):
187168
return self._test_operation_handler('get_recovery_key')

backend/globaleaks/tests/handlers/whistleblower/test_submission.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from globaleaks.orm import tw
99
from globaleaks.rest import errors
1010
from globaleaks.tests import helpers
11+
from globaleaks.utils.crypto import GCE
1112

1213

1314
class TestSubmission(helpers.TestHandlerWithPopulatedDB):
@@ -61,7 +62,7 @@ def test_update_submission(self):
6162
self.submission_desc = yield self.get_dummy_submission(self.dummyContext['id'])
6263

6364
self.submission_desc['answers'] = yield self.fill_random_answers(self.dummyContext['questionnaire_id'])
64-
receipt = yield self.create_submission(self.submission_desc)
65+
receipt = GCE.derive_key((yield self.create_submission(self.submission_desc)), helpers.VALID_SALT1)
6566

6667
session = yield auth.login_whistleblower(1, receipt, True)
6768

backend/globaleaks/tests/helpers.py

+20-17
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
from globaleaks.settings import Settings
4444
from globaleaks.state import State, TenantState
4545
from globaleaks.utils import tempdict, token
46-
from globaleaks.utils.crypto import generateRandomKey, GCE
46+
from globaleaks.utils.crypto import GCE, generateRandomKey, sha512
4747
from globaleaks.utils.securetempfile import SecureTemporaryFile
4848
from globaleaks.utils.utility import datetime_now, uuid4
4949
from globaleaks.utils.log import log
@@ -64,11 +64,7 @@
6464
INVALID_PASSWORD = 'antani'
6565

6666
KEY = GCE.generate_key()
67-
<<<<<<< HEAD
6867
USER_KEY = GCE.derive_key(VALID_PASSWORD1, VALID_SALT1)
69-
=======
70-
USER_KEY = Base64Encoder.decode(GCE.derive_key(VALID_PASSWORD1, VALID_SALT1).encode())
71-
>>>>>>> c06715e00 (...)
7268
USER_PRV_KEY, USER_PUB_KEY = GCE.generate_keypair()
7369
USER_PRV_KEY_ENC = Base64Encoder.encode(GCE.symmetric_encrypt(USER_KEY, USER_PRV_KEY))
7470
USER_BKP_KEY, USER_REC_KEY = GCE.generate_recovery_key(USER_PRV_KEY)
@@ -163,9 +159,16 @@ def init_state():
163159

164160
@transact
165161
def mock_users_keys(session):
162+
session.query(models.Config).filter(models.Config.tid == 1, models.Config.var_name == u'receipt_salt').one().value = VALID_SALT1
163+
166164
for user in session.query(models.User):
167-
user.hash = VALID_HASH1
168-
user.salt = VALID_SALT1
165+
if user.username == 'receiver2':
166+
user.salt = VALID_SALT2
167+
user.hash = VALID_HASH2
168+
else:
169+
user.salt = VALID_SALT1
170+
user.hash = VALID_HASH1
171+
169172
user.crypto_prv_key = USER_PRV_KEY_ENC
170173
user.crypto_pub_key = USER_PUB_KEY
171174
user.crypto_bkp_key = USER_BKP_KEY
@@ -257,7 +260,7 @@ def __init__(self):
257260
self.dummyUser = {
258261
'id': '',
259262
'username': '[email protected]',
260-
'password': VALID_PASSWORD1,
263+
'password': VALID_KEY1,
261264
'old_password': '',
262265
'salt': VALID_SALT1,
263266
'role': 'receiver',
@@ -326,7 +329,7 @@ def __init__(self):
326329
'languages_supported': [], # ignored
327330
'languages_enabled': ['it', 'en'],
328331
'latest_version': __version__,
329-
'receipt_salt': '<<the Lannisters send their regards>>',
332+
'receipt_salt': VALID_SALT1,
330333
'maximum_filesize': 30,
331334
'allow_indexing': False,
332335
'disable_submissions': False,
@@ -400,12 +403,12 @@ def __init__(self):
400403
'node_name': 'test',
401404
'admin_username': 'admin',
402405
'admin_name': 'Giovanni Pellerano',
403-
'admin_password': 'P4ssword!@#',
406+
'admin_password': VALID_KEY1,
404407
'admin_mail_address': '[email protected]',
405408
'admin_escrow': True,
406409
'receiver_username': 'receipient',
407410
'receiver_name': 'Fabio Pietrosanti',
408-
'receiver_password': 'P4ssword!@#',
411+
'receiver_password': VALID_KEY1,
409412
'receiver_mail_address': '[email protected]',
410413
'profile': 'default',
411414
'skip_admin_account_creation': False,
@@ -653,7 +656,7 @@ def get_dummy_user(self, role, username):
653656
new_u['username'] = username
654657
new_u['name'] = new_u['public_name'] = new_u['mail_address'] = "%s@%s.xxx" % (username, username)
655658
new_u['description'] = ''
656-
new_u['password'] = VALID_PASSWORD1
659+
new_u['password'] = VALID_KEY1
657660
new_u['enabled'] = True
658661
new_u['salt'] = VALID_SALT1
659662

@@ -875,11 +878,11 @@ def perform_submission_actions(self, session_id):
875878
self.dummySubmission['score'] = 0
876879
self.dummySubmission['removed_files'] = []
877880

878-
self.lastReceipt = (yield create_submission(1,
879-
self.dummySubmission,
880-
session,
881-
True,
882-
False))['receipt']
881+
self.lastReceipt = GCE.derive_key((yield create_submission(1,
882+
self.dummySubmission,
883+
session,
884+
True,
885+
False))['receipt'], VALID_SALT1)
883886

884887
@inlineCallbacks
885888
def perform_post_submission_actions(self):

0 commit comments

Comments
 (0)