PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/Sabre/HTTP/DigestAuthTest.php

https://github.com/KOLANICH/SabreDAV
PHP | 228 lines | 156 code | 65 blank | 7 comment | 0 complexity | 9823637bfaf516ff2f99273ab8d595d9 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. namespace Sabre\HTTP;
  3. require_once 'Sabre/HTTP/ResponseMock.php';
  4. class DigestAuthTest extends \PHPUnit_Framework_TestCase {
  5. /**
  6. * @var Sabre\HTTP\ResponseMock
  7. */
  8. private $response;
  9. /**
  10. * @var Sabre\HTTP\DigestAuth
  11. */
  12. private $auth;
  13. const REALM = 'SabreDAV unittest';
  14. public function setUp() {
  15. $this->response = new ResponseMock();
  16. $this->auth = new DigestAuth();
  17. $this->auth->setRealm(self::REALM);
  18. $this->auth->setHTTPResponse($this->response);
  19. }
  20. public function testDigest() {
  21. list($nonce,$opaque) = $this->getServerTokens();
  22. $username = 'admin';
  23. $password = 12345;
  24. $nc = '00002';
  25. $cnonce = uniqid();
  26. $digestHash = md5(
  27. md5($username . ':' . self::REALM . ':' . $password) . ':' .
  28. $nonce . ':' .
  29. $nc . ':' .
  30. $cnonce . ':' .
  31. 'auth:' .
  32. md5('GET' . ':' . '/')
  33. );
  34. $request = new Request(array(
  35. 'REQUEST_METHOD' => 'GET',
  36. 'PHP_AUTH_DIGEST' => 'username="'.$username.'", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth,nc='.$nc.',cnonce="' . $cnonce . '"',
  37. ));
  38. $this->auth->setHTTPRequest($request);
  39. $this->auth->init();
  40. $this->assertEquals($username,$this->auth->getUserName());
  41. $this->assertEquals(self::REALM,$this->auth->getRealm());
  42. $this->assertTrue($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . $password)),'Authentication is deemed invalid through validateA1');
  43. $this->assertTrue($this->auth->validatePassword($password),'Authentication is deemed invalid through validatePassword');
  44. }
  45. public function testDigestCGIFormat() {
  46. list($nonce,$opaque) = $this->getServerTokens();
  47. $username = 'admin';
  48. $password = 12345;
  49. $nc = '00002';
  50. $cnonce = uniqid();
  51. $digestHash = md5(
  52. md5($username . ':' . self::REALM . ':' . $password) . ':' .
  53. $nonce . ':' .
  54. $nc . ':' .
  55. $cnonce . ':' .
  56. 'auth:' .
  57. md5('GET' . ':' . '/')
  58. );
  59. $request = new Request(array(
  60. 'REQUEST_METHOD' => 'GET',
  61. 'HTTP_AUTHORIZATION' => 'Digest username="'.$username.'", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth,nc='.$nc.',cnonce="' . $cnonce . '"',
  62. ));
  63. $this->auth->setHTTPRequest($request);
  64. $this->auth->init();
  65. $this->assertTrue($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . $password)),'Authentication is deemed invalid through validateA1');
  66. $this->assertTrue($this->auth->validatePassword($password),'Authentication is deemed invalid through validatePassword');
  67. }
  68. public function testDigestApacheEdgeCase() {
  69. list($nonce,$opaque) = $this->getServerTokens();
  70. $username = 'admin';
  71. $password = 12345;
  72. $nc = '00002';
  73. $cnonce = uniqid();
  74. $digestHash = md5(
  75. md5($username . ':' . self::REALM . ':' . $password) . ':' .
  76. $nonce . ':' .
  77. $nc . ':' .
  78. $cnonce . ':' .
  79. 'auth:' .
  80. md5('GET' . ':' . '/')
  81. );
  82. $request = new Request(array(
  83. 'REQUEST_METHOD' => 'GET',
  84. 'REDIRECT_HTTP_AUTHORIZATION' => 'Digest username="'.$username.'", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth,nc='.$nc.',cnonce="' . $cnonce . '"',
  85. ));
  86. $this->auth->setHTTPRequest($request);
  87. $this->auth->init();
  88. $this->assertTrue($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . $password)),'Authentication is deemed invalid through validateA1');
  89. $this->assertTrue($this->auth->validatePassword($password),'Authentication is deemed invalid through validatePassword');
  90. }
  91. public function testInvalidDigest() {
  92. list($nonce,$opaque) = $this->getServerTokens();
  93. $username = 'admin';
  94. $password = 12345;
  95. $nc = '00002';
  96. $cnonce = uniqid();
  97. $digestHash = md5(
  98. md5($username . ':' . self::REALM . ':' . $password) . ':' .
  99. $nonce . ':' .
  100. $nc . ':' .
  101. $cnonce . ':' .
  102. 'auth:' .
  103. md5('GET' . ':' . '/')
  104. );
  105. $request = new Request(array(
  106. 'REQUEST_METHOD' => 'GET',
  107. 'PHP_AUTH_DIGEST' => 'username="'.$username.'", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth,nc='.$nc.',cnonce="' . $cnonce . '"',
  108. ));
  109. $this->auth->setHTTPRequest($request);
  110. $this->auth->init();
  111. $this->assertFalse($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . ($password . 'randomness'))),'Authentication is deemed invalid through validateA1');
  112. }
  113. public function testInvalidDigest2() {
  114. $request = new Request(array(
  115. 'REQUEST_METHOD' => 'GET',
  116. 'HTTP_AUTHORIZATION' => 'basic blablabla',
  117. ));
  118. $this->auth->setHTTPRequest($request);
  119. $this->auth->init();
  120. $this->assertFalse($this->auth->validateA1(md5('user:realm:password')));
  121. }
  122. public function testDigestAuthInt() {
  123. $this->auth->setQOP(DigestAuth::QOP_AUTHINT | DigestAuth::QOP_AUTH);
  124. list($nonce,$opaque) = $this->getServerTokens(DigestAuth::QOP_AUTHINT| DigestAuth::QOP_AUTH);
  125. $username = 'admin';
  126. $password = 12345;
  127. $nc = '00003';
  128. $cnonce = uniqid();
  129. $digestHash = md5(
  130. md5($username . ':' . self::REALM . ':' . $password) . ':' .
  131. $nonce . ':' .
  132. $nc . ':' .
  133. $cnonce . ':' .
  134. 'auth-int:' .
  135. md5('POST' . ':' . '/' . ':' . md5('body'))
  136. );
  137. $request = new Request(array(
  138. 'REQUEST_METHOD' => 'POST',
  139. 'PHP_AUTH_DIGEST' => 'username="'.$username.'", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth-int,nc='.$nc.',cnonce="' . $cnonce . '"',
  140. ));
  141. $request->setBody('body');
  142. $this->auth->setHTTPRequest($request);
  143. $this->auth->init();
  144. $this->assertTrue($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . $password)),'Authentication is deemed invalid through validateA1');
  145. }
  146. private function getServerTokens($qop = DigestAuth::QOP_AUTH) {
  147. $this->auth->requireLogin();
  148. switch($qop) {
  149. case DigestAuth::QOP_AUTH : $qopstr='auth'; break;
  150. case DigestAuth::QOP_AUTHINT : $qopstr='auth-int'; break;
  151. default : $qopstr='auth,auth-int'; break;
  152. }
  153. $test = preg_match('/Digest realm="'.self::REALM.'",qop="'.$qopstr.'",nonce="([0-9a-f]*)",opaque="([0-9a-f]*)"/',
  154. $this->response->headers['WWW-Authenticate'],$matches);
  155. $this->assertTrue($test==true,'The WWW-Authenticate response didn\'t match our pattern. We received: ' . $this->response->headers['WWW-Authenticate']);
  156. $nonce = $matches[1];
  157. $opaque = $matches[2];
  158. // Reset our environment
  159. $this->setUp();
  160. $this->auth->setQOP($qop);
  161. return array($nonce,$opaque);
  162. }
  163. }