PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/linotpd/src/linotp/tests/unit/lib/tokens/test_u2ftoken.py

https://gitlab.com/sheshanarayanag/LinOTP
Python | 343 lines | 304 code | 8 blank | 31 comment | 4 complexity | f18827277febae5f92147e1d394ec3c9 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. #
  3. # LinOTP - the open source solution for two factor authentication
  4. # Copyright (C) 2010 - 2016 LSE Leading Security Experts GmbH
  5. #
  6. # This file is part of LinOTP server.
  7. #
  8. # This program is free software: you can redistribute it and/or
  9. # modify it under the terms of the GNU Affero General Public
  10. # License, version 3, as published by the Free Software Foundation.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the
  18. # GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. #
  22. # E-mail: linotp@lsexperts.de
  23. # Contact: www.linotp.org
  24. # Support: www.lsexperts.de
  25. #
  26. import logging
  27. import sys
  28. if sys.version_info < (2, 7):
  29. try:
  30. import unittest2 as unittest
  31. except ImportError as exc:
  32. print "You need to install unittest2 on Python 2.6. Unittest2 is a "\
  33. "backport of new unittest features."
  34. raise exc
  35. else:
  36. import unittest
  37. from mock import MagicMock, Mock, patch
  38. class U2FTokenClassTestCase(unittest.TestCase):
  39. """
  40. This class tests the U2FTokenClass in isolation by mocking out
  41. all dependencies on other classes. Therefore the tests can be run without
  42. requiring an installed server.
  43. """
  44. def setUp(self):
  45. from linotp.lib.tokens.u2ftoken import U2FTokenClass
  46. # Without this logging in the tested class fails
  47. logging.basicConfig()
  48. model_token = MagicMock(
  49. spec=[
  50. "getInfo",
  51. "setType",
  52. ]
  53. ) # linotp.model.Token
  54. model_token.getInfo.return_value = u'' + '{\n}'
  55. self.u2f_token = U2FTokenClass(model_token)
  56. model_token.setType.assert_called_once_with("u2f")
  57. #
  58. # Test the _verifyCounterValue function
  59. #
  60. def test_verify_counter_decrease_in_overflow_range(self):
  61. """
  62. Test decreased counter in overflow range
  63. """
  64. self.u2f_token.getFromTokenInfo = Mock(return_value=(256 ** 4) - 500)
  65. self.u2f_token.token.LinOtpIsactive = True
  66. with self.assertRaises(ValueError):
  67. self.u2f_token._verifyCounterValue((256 ** 4) - 1000)
  68. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  69. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  70. def test_verify_counter_equal_in_overflow_range(self):
  71. """
  72. Test equal counter in overflow range
  73. """
  74. self.u2f_token.getFromTokenInfo = Mock(return_value=(256 ** 4) - 500)
  75. self.u2f_token.token.LinOtpIsactive = True
  76. with self.assertRaises(ValueError):
  77. self.u2f_token._verifyCounterValue((256 ** 4) - 500)
  78. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  79. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  80. def test_verify_counter_increase_in_overflow_range(self):
  81. """
  82. Test increased counter in the overflow range
  83. """
  84. self.u2f_token.getFromTokenInfo = Mock(return_value=(256 ** 4) - 500)
  85. self.u2f_token.addToTokenInfo = Mock()
  86. self.u2f_token.token.LinOtpIsactive = True
  87. self.u2f_token._verifyCounterValue((256 ** 4) - 400)
  88. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  89. self.u2f_token.addToTokenInfo.assert_called_once_with('counter', (256 ** 4) - 400)
  90. self.assertTrue(self.u2f_token.token.LinOtpIsactive)
  91. def test_verify_counter_overflow_out_of_range1(self):
  92. """
  93. Test overflow out of the accepted range
  94. """
  95. self.u2f_token.getFromTokenInfo = Mock(return_value=(256 ** 4) - 500)
  96. self.u2f_token.token.LinOtpIsactive = True
  97. with self.assertRaises(ValueError):
  98. self.u2f_token._verifyCounterValue(1001)
  99. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  100. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  101. def test_verify_counter_overflow_out_of_range2(self):
  102. """
  103. Test overflow out of the accepted range #2
  104. """
  105. self.u2f_token.getFromTokenInfo = Mock(return_value=(256 ** 4) - 1001)
  106. self.u2f_token.token.LinOtpIsactive = True
  107. with self.assertRaises(ValueError):
  108. self.u2f_token._verifyCounterValue(0)
  109. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  110. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  111. def test_verify_counter_legal_overflow(self):
  112. """
  113. Test legal counter overflow
  114. """
  115. self.u2f_token.getFromTokenInfo = Mock(return_value=(256 ** 4) - 1000)
  116. self.u2f_token.addToTokenInfo = Mock()
  117. self.u2f_token.token.LinOtpIsactive = True
  118. self.u2f_token._verifyCounterValue(1000)
  119. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  120. self.u2f_token.addToTokenInfo.assert_called_once_with('counter', 1000)
  121. self.assertTrue(self.u2f_token.token.LinOtpIsactive)
  122. def test_verify_counter_decreased1(self):
  123. """
  124. Test decreased counter
  125. """
  126. self.u2f_token.getFromTokenInfo = Mock(return_value=500)
  127. self.u2f_token.token.LinOtpIsactive = True
  128. with self.assertRaises(ValueError):
  129. self.u2f_token._verifyCounterValue(499)
  130. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  131. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  132. def test_verify_counter_decreased2(self):
  133. """
  134. Test decreased counter #2
  135. """
  136. self.u2f_token.getFromTokenInfo = Mock(return_value=500)
  137. self.u2f_token.token.LinOtpIsactive = True
  138. with self.assertRaises(ValueError):
  139. self.u2f_token._verifyCounterValue(0)
  140. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  141. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  142. def test_verify_counter_equal(self):
  143. """
  144. Test equal counter
  145. """
  146. self.u2f_token.getFromTokenInfo = Mock(return_value=500)
  147. self.u2f_token.token.LinOtpIsactive = True
  148. with self.assertRaises(ValueError):
  149. self.u2f_token._verifyCounterValue(500)
  150. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  151. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  152. def test_verify_counter_increased1(self):
  153. """
  154. Test legal increased counter
  155. """
  156. self.u2f_token.getFromTokenInfo = Mock(return_value=500)
  157. self.u2f_token.addToTokenInfo = Mock()
  158. self.u2f_token.token.LinOtpIsactive = True
  159. self.u2f_token._verifyCounterValue(501)
  160. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  161. self.u2f_token.addToTokenInfo.assert_called_once_with('counter', 501)
  162. self.assertTrue(self.u2f_token.token.LinOtpIsactive)
  163. def test_verify_counter_increased2(self):
  164. """
  165. Test legal increased counter #2
  166. """
  167. self.u2f_token.getFromTokenInfo = Mock(return_value=500)
  168. self.u2f_token.addToTokenInfo = Mock()
  169. self.u2f_token.token.LinOtpIsactive = True
  170. self.u2f_token._verifyCounterValue(5000)
  171. self.u2f_token.getFromTokenInfo.assert_called_once_with('counter', None)
  172. self.u2f_token.addToTokenInfo.assert_called_once_with('counter', 5000)
  173. self.assertTrue(self.u2f_token.token.LinOtpIsactive)
  174. #
  175. # Test the update function
  176. #
  177. def test_update_requested_phase_unknown_current_phase_None(self):
  178. """
  179. Test update function with an unknown requested_phase parameter and current_phase None
  180. """
  181. self.u2f_token.getFromTokenInfo = Mock(return_value=None)
  182. param = dict(description=None, phase='some_unknown_phase')
  183. with self.assertRaises(Exception):
  184. self.u2f_token.update(param)
  185. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  186. def test_update_requested_phase_unknown_current_phase_registration(self):
  187. """
  188. Test update function with an unknown requested_phase parameter and current_phase 'registration'
  189. """
  190. self.u2f_token.getFromTokenInfo = Mock(return_value='registration')
  191. param = dict(description=None, phase='some_unknown_phase')
  192. with self.assertRaises(Exception):
  193. self.u2f_token.update(param)
  194. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  195. def test_update_requested_phase_unknown_current_phase_authentication(self):
  196. """
  197. Test update function with an unknown requested_phase parameter and current_phase 'authentication'
  198. """
  199. self.u2f_token.getFromTokenInfo = Mock(return_value='authentication')
  200. param = dict(description=None, phase='some_unknown_phase')
  201. with self.assertRaises(Exception):
  202. self.u2f_token.update(param)
  203. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  204. def test_update_requested_phase_registration1_current_phase_None(self):
  205. """
  206. Test update function with requested_phase 'registration1' and current_phase None
  207. """
  208. self.u2f_token.getFromTokenInfo = Mock(return_value=None)
  209. self.u2f_token.addToTokenInfo = Mock()
  210. param = dict(description=None, phase='registration1')
  211. self.u2f_token.update(param)
  212. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  213. self.u2f_token.addToTokenInfo.assert_called_once_with('phase', 'registration')
  214. self.assertFalse(self.u2f_token.token.LinOtpIsactive)
  215. def test_update_requested_phase_registration1_current_phase_registration(self):
  216. """
  217. Test update function with requested_phase 'registration1' and current_phase 'registration'
  218. """
  219. self.u2f_token.getFromTokenInfo = Mock(return_value='registration')
  220. param = dict(description=None, phase='registration1')
  221. with self.assertRaises(Exception):
  222. self.u2f_token.update(param)
  223. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  224. def test_update_requested_phase_registration1_current_phase_authentication(self):
  225. """
  226. Test update function with requested_phase 'registration1' and current_phase 'authentication'
  227. """
  228. self.u2f_token.getFromTokenInfo = Mock(return_value='authentication')
  229. param = dict(description=None, phase='registration1')
  230. with self.assertRaises(Exception):
  231. self.u2f_token.update(param)
  232. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  233. def test_update_requested_phase_registration2_current_phase_None(self):
  234. """
  235. Test update function with requested_phase 'registration2' and current_phase None
  236. """
  237. self.u2f_token.getFromTokenInfo = Mock(return_value=None)
  238. param = dict(description=None, phase='registration2')
  239. with self.assertRaises(Exception):
  240. self.u2f_token.update(param)
  241. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  242. def test_update_requested_phase_registration2_current_phase_registration_correct_pin(self):
  243. """
  244. Test update function with requested_phase 'registration2' and current_phase registration
  245. and a correct pin
  246. """
  247. self.u2f_token.getFromTokenInfo = Mock(return_value='registration')
  248. patcher = patch('linotp.lib.tokens.u2ftoken.check_pin', spec=True)
  249. check_pin_mock = patcher.start()
  250. check_pin_mock.return_value = True
  251. param = dict(description=None, phase='registration2', pin='test!pin')
  252. self.u2f_token.update(param)
  253. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  254. check_pin_mock.assert_called_once_with(self.u2f_token, 'test!pin')
  255. patcher.stop()
  256. def test_update_requested_phase_registration2_current_phase_registration_wrong_pin(self):
  257. """
  258. Test update function with requested_phase 'registration2' and current_phase registration
  259. and a wrong pin
  260. """
  261. self.u2f_token.getFromTokenInfo = Mock(return_value='registration')
  262. patcher = patch('linotp.lib.tokens.u2ftoken.check_pin', spec=True)
  263. check_pin_mock = patcher.start()
  264. check_pin_mock.return_value = False
  265. param = dict(description=None, phase='registration2', pin='test!pin')
  266. with self.assertRaises(ValueError):
  267. self.u2f_token.update(param)
  268. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  269. check_pin_mock.assert_called_once_with(self.u2f_token, 'test!pin')
  270. patcher.stop()
  271. def test_update_requested_phase_registration2_current_phase_authentication(self):
  272. """
  273. Test update function with requested_phase 'registration2' and current_phase 'authentication'
  274. """
  275. self.u2f_token.getFromTokenInfo = Mock(return_value='authentication')
  276. param = dict(description=None, phase='registration2')
  277. with self.assertRaises(Exception):
  278. self.u2f_token.update(param)
  279. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  280. def test_update_requested_phase_None_current_phase_None(self):
  281. """
  282. Test update function with requested_phase None and current_phase None
  283. """
  284. self.u2f_token.getFromTokenInfo = Mock(return_value=None)
  285. param = dict(description=None, phase=None)
  286. with self.assertRaises(Exception):
  287. self.u2f_token.update(param)
  288. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  289. def test_update_requested_phase_None_current_phase_registration(self):
  290. """
  291. Test update function with an requested_phase None and current_phase 'registration'
  292. """
  293. self.u2f_token.getFromTokenInfo = Mock(return_value='registration')
  294. param = dict(description=None, phase=None)
  295. with self.assertRaises(Exception):
  296. self.u2f_token.update(param)
  297. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  298. def test_update_requested_phase_None_current_phase_authentication(self):
  299. """
  300. Test update function with requested_phase None and current_phase 'authentication'
  301. """
  302. self.u2f_token.getFromTokenInfo = Mock(return_value='authentication')
  303. param = dict(description=None, phase=None)
  304. with self.assertRaises(Exception):
  305. self.u2f_token.update(param)
  306. self.u2f_token.getFromTokenInfo.assert_called_once_with('phase', None)
  307. if __name__ == '__main__':
  308. unittest.main()