SharedKey.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service_WindowsAzure
  17. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. */
  21. /**
  22. * @category Zend
  23. * @package Zend_Service_WindowsAzure
  24. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  25. * @license http://framework.zend.com/license/new-bsd New BSD License
  26. */
  27. class Zend_Service_WindowsAzure_Credentials_SharedKey
  28. extends Zend_Service_WindowsAzure_Credentials_CredentialsAbstract
  29. {
  30. /**
  31. * Sign request URL with credentials
  32. *
  33. * @param string $requestUrl Request URL
  34. * @param string $resourceType Resource type
  35. * @param string $requiredPermission Required permission
  36. * @return string Signed request URL
  37. */
  38. public function signRequestUrl(
  39. $requestUrl = '',
  40. $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN,
  41. $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
  42. ) {
  43. return $requestUrl;
  44. }
  45. /**
  46. * Sign request headers with credentials
  47. *
  48. * @param string $httpVerb HTTP verb the request will use
  49. * @param string $path Path for the request
  50. * @param string $queryString Query string for the request
  51. * @param array $headers x-ms headers to add
  52. * @param boolean $forTableStorage Is the request for table storage?
  53. * @param string $resourceType Resource type
  54. * @param string $requiredPermission Required permission
  55. * @param mixed $rawData Raw post data
  56. * @return array Array of headers
  57. */
  58. public function signRequestHeaders(
  59. $httpVerb = Zend_Http_Client::GET,
  60. $path = '/',
  61. $queryString = '',
  62. $headers = null,
  63. $forTableStorage = false,
  64. $resourceType = Zend_Service_WindowsAzure_Storage::RESOURCE_UNKNOWN,
  65. $requiredPermission = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
  66. $rawData = null
  67. ) {
  68. // http://github.com/sriramk/winazurestorage/blob/214010a2f8931bac9c96dfeb337d56fe084ca63b/winazurestorage.py
  69. // Table storage?
  70. if ($forTableStorage) {
  71. require_once 'Zend/Service/WindowsAzure/Credentials/Exception.php';
  72. throw new Zend_Service_WindowsAzure_Credentials_Exception('The Windows Azure SDK for PHP does not support SharedKey authentication on table storage. Use SharedKeyLite authentication instead.');
  73. }
  74. // Determine path
  75. if ($this->_usePathStyleUri) {
  76. $path = substr($path, strpos($path, '/'));
  77. }
  78. // Determine query
  79. $queryString = $this->_prepareQueryStringForSigning($queryString);
  80. // Canonicalized headers
  81. $canonicalizedHeaders = array();
  82. // Request date
  83. $requestDate = '';
  84. if (isset($headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'])) {
  85. $requestDate = $headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'];
  86. } else {
  87. $requestDate = gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123
  88. $canonicalizedHeaders[] = Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date:' . $requestDate;
  89. }
  90. // Build canonicalized headers
  91. if (!is_null($headers)) {
  92. foreach ($headers as $header => $value) {
  93. if (is_bool($value)) {
  94. $value = $value === true ? 'True' : 'False';
  95. }
  96. $headers[$header] = $value;
  97. if (substr($header, 0, strlen(Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER)) == Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER) {
  98. $canonicalizedHeaders[] = strtolower($header) . ':' . $value;
  99. }
  100. }
  101. }
  102. sort($canonicalizedHeaders);
  103. // Build canonicalized resource string
  104. $canonicalizedResource = '/' . $this->_accountName;
  105. if ($this->_usePathStyleUri) {
  106. $canonicalizedResource .= '/' . $this->_accountName;
  107. }
  108. $canonicalizedResource .= $path;
  109. if ($queryString !== '') {
  110. $queryStringItems = $this->_makeArrayOfQueryString($queryString);
  111. foreach ($queryStringItems as $key => $value) {
  112. $canonicalizedResource .= "\n" . strtolower($key) . ':' . urldecode($value);
  113. }
  114. }
  115. // Content-Length header
  116. $contentLength = '';
  117. if (strtoupper($httpVerb) != Zend_Http_Client::GET
  118. && strtoupper($httpVerb) != Zend_Http_Client::DELETE
  119. && strtoupper($httpVerb) != Zend_Http_Client::HEAD) {
  120. $contentLength = 0;
  121. if (!is_null($rawData)) {
  122. $contentLength = strlen($rawData);
  123. }
  124. }
  125. // Create string to sign
  126. $stringToSign = array();
  127. $stringToSign[] = strtoupper($httpVerb); // VERB
  128. $stringToSign[] = $this->_issetOr($headers, 'Content-Encoding', ''); // Content-Encoding
  129. $stringToSign[] = $this->_issetOr($headers, 'Content-Language', ''); // Content-Language
  130. $stringToSign[] = $contentLength; // Content-Length
  131. $stringToSign[] = $this->_issetOr($headers, 'Content-MD5', ''); // Content-MD5
  132. $stringToSign[] = $this->_issetOr($headers, 'Content-Type', ''); // Content-Type
  133. $stringToSign[] = ""; // Date
  134. $stringToSign[] = $this->_issetOr($headers, 'If-Modified-Since', ''); // If-Modified-Since
  135. $stringToSign[] = $this->_issetOr($headers, 'If-Match', ''); // If-Match
  136. $stringToSign[] = $this->_issetOr($headers, 'If-None-Match', ''); // If-None-Match
  137. $stringToSign[] = $this->_issetOr($headers, 'If-Unmodified-Since', ''); // If-Unmodified-Since
  138. $stringToSign[] = $this->_issetOr($headers, 'Range', ''); // Range
  139. if (!$forTableStorage && count($canonicalizedHeaders) > 0) {
  140. $stringToSign[] = implode("\n", $canonicalizedHeaders); // Canonicalized headers
  141. }
  142. $stringToSign[] = $canonicalizedResource; // Canonicalized resource
  143. $stringToSign = implode("\n", $stringToSign);
  144. $signString = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true));
  145. // Sign request
  146. $headers[Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'] = $requestDate;
  147. $headers['Authorization'] = 'SharedKey ' . $this->_accountName . ':' . $signString;
  148. // Return headers
  149. return $headers;
  150. }
  151. }