DigestDataTest.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Security\Http\Tests\Firewall;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Security\Http\Firewall\DigestData;
  13. class DigestDataTest extends TestCase
  14. {
  15. public function testGetResponse()
  16. {
  17. $digestAuth = new DigestData(
  18. 'username="user", realm="Welcome, robot!", '.
  19. 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '.
  20. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  21. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  22. );
  23. $this->assertEquals('b52938fc9e6d7c01be7702ece9031b42', $digestAuth->getResponse());
  24. }
  25. public function testGetUsername()
  26. {
  27. $digestAuth = new DigestData(
  28. 'username="user", realm="Welcome, robot!", '.
  29. 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '.
  30. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  31. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  32. );
  33. $this->assertEquals('user', $digestAuth->getUsername());
  34. }
  35. public function testGetUsernameWithQuote()
  36. {
  37. $digestAuth = new DigestData(
  38. 'username="\"user\"", realm="Welcome, robot!", '.
  39. 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '.
  40. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  41. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  42. );
  43. $this->assertEquals('"user"', $digestAuth->getUsername());
  44. }
  45. public function testGetUsernameWithQuoteAndEscape()
  46. {
  47. $digestAuth = new DigestData(
  48. 'username="\"u\\\\\"ser\"", realm="Welcome, robot!", '.
  49. 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '.
  50. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  51. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  52. );
  53. $this->assertEquals('"u\\"ser"', $digestAuth->getUsername());
  54. }
  55. public function testGetUsernameWithSingleQuote()
  56. {
  57. $digestAuth = new DigestData(
  58. 'username="\"u\'ser\"", realm="Welcome, robot!", '.
  59. 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '.
  60. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  61. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  62. );
  63. $this->assertEquals('"u\'ser"', $digestAuth->getUsername());
  64. }
  65. public function testGetUsernameWithSingleQuoteAndEscape()
  66. {
  67. $digestAuth = new DigestData(
  68. 'username="\"u\\\'ser\"", realm="Welcome, robot!", '.
  69. 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '.
  70. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  71. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  72. );
  73. $this->assertEquals('"u\\\'ser"', $digestAuth->getUsername());
  74. }
  75. public function testGetUsernameWithEscape()
  76. {
  77. $digestAuth = new DigestData(
  78. 'username="\"u\\ser\"", realm="Welcome, robot!", '.
  79. 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '.
  80. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  81. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  82. );
  83. $this->assertEquals('"u\\ser"', $digestAuth->getUsername());
  84. }
  85. /**
  86. * @group time-sensitive
  87. */
  88. public function testValidateAndDecode()
  89. {
  90. $time = microtime(true);
  91. $key = 'ThisIsAKey';
  92. $nonce = base64_encode($time.':'.md5($time.':'.$key));
  93. $digestAuth = new DigestData(
  94. 'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", '.
  95. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  96. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  97. );
  98. $digestAuth->validateAndDecode($key, 'Welcome, robot!');
  99. sleep(1);
  100. $this->assertTrue($digestAuth->isNonceExpired());
  101. }
  102. public function testCalculateServerDigest()
  103. {
  104. $this->calculateServerDigest('user', 'Welcome, robot!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
  105. }
  106. public function testCalculateServerDigestWithQuote()
  107. {
  108. $this->calculateServerDigest('\"user\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
  109. }
  110. public function testCalculateServerDigestWithQuoteAndEscape()
  111. {
  112. $this->calculateServerDigest('\"u\\\\\"ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
  113. }
  114. public function testCalculateServerDigestEscape()
  115. {
  116. $this->calculateServerDigest('\"u\\ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
  117. $this->calculateServerDigest('\"u\\ser\\\\\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
  118. }
  119. public function testIsNonceExpired()
  120. {
  121. $time = microtime(true) + 10;
  122. $key = 'ThisIsAKey';
  123. $nonce = base64_encode($time.':'.md5($time.':'.$key));
  124. $digestAuth = new DigestData(
  125. 'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", '.
  126. 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '.
  127. 'response="b52938fc9e6d7c01be7702ece9031b42"'
  128. );
  129. $digestAuth->validateAndDecode($key, 'Welcome, robot!');
  130. $this->assertFalse($digestAuth->isNonceExpired());
  131. }
  132. protected function setUp()
  133. {
  134. class_exists('Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener', true);
  135. }
  136. private function calculateServerDigest($username, $realm, $password, $key, $nc, $cnonce, $qop, $method, $uri)
  137. {
  138. $time = microtime(true);
  139. $nonce = base64_encode($time.':'.md5($time.':'.$key));
  140. $response = md5(
  141. md5($username.':'.$realm.':'.$password).':'.$nonce.':'.$nc.':'.$cnonce.':'.$qop.':'.md5($method.':'.$uri)
  142. );
  143. $digest = sprintf('username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"',
  144. $username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response
  145. );
  146. $digestAuth = new DigestData($digest);
  147. $this->assertEquals($digestAuth->getResponse(), $digestAuth->calculateServerDigest($password, $method));
  148. }
  149. }