Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License").
6
 * You may not use this file except in compliance with the License.
7
 * A copy of the License is located at
8
 *
9
 *  http://aws.amazon.com/apache2.0
10
 *
11
 * or in the "license" file accompanying this file. This file is distributed
12
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13
 * express or implied. See the License for the specific language governing
14
 * permissions and limitations under the License.
15
 */
16
 
17
 
18
/*%******************************************************************************************%*/
19
// CLASS
20
 
21
/**
22
 * Implements support for Signature v3 (AWS Query).
23
 *
24
 * @version 2011.11.22
25
 * @license See the included NOTICE.md file for more information.
26
 * @copyright See the included NOTICE.md file for more information.
27
 * @link http://aws.amazon.com/php/ PHP Developer Center
28
 */
29
class AuthV3Query extends Signer implements Signable
30
{
31
	/**
32
	 * Constructs a new instance of the <AuthV3Query> class.
33
	 *
34
	 * @param string $endpoint (Required) The endpoint to direct the request to.
35
	 * @param string $operation (Required) The operation to execute as a result of this request.
36
	 * @param array $payload (Required) The options to use as part of the payload in the request.
37
	 * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
38
	 * @return void
39
	 */
40
	public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
41
	{
42
		parent::__construct($endpoint, $operation, $payload, $credentials);
43
	}
44
 
45
	/**
46
	 * Generates a cURL handle with all of the required authentication bits set.
47
	 *
48
	 * @return resource A cURL handle ready for executing.
49
	 */
50
	public function authenticate()
51
	{
52
		// Determine signing values
53
		$current_time = time();
54
		$date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, $current_time);
55
		$timestamp = gmdate(CFUtilities::DATE_FORMAT_ISO8601, $current_time);
56
		$nonce = $this->util->generate_guid();
57
		$curlopts = array();
58
		$signed_headers = array();
59
 
60
		// Do we have an authentication token?
61
		if ($this->auth_token)
62
		{
63
			$headers['X-Amz-Security-Token'] = $this->auth_token;
64
			$query['SecurityToken'] = $this->auth_token;
65
		}
66
 
67
		$query['Action'] = $this->operation;
68
		$query['Version'] = $this->api_version;
69
 
70
		// Set custom CURLOPT settings
71
		if (is_array($this->payload) && isset($this->payload['curlopts']))
72
		{
73
			$curlopts = $this->payload['curlopts'];
74
			unset($this->payload['curlopts']);
75
		}
76
 
77
		// Merge in any options that were passed in
78
		if (is_array($this->payload))
79
		{
80
			$query = array_merge($query, $this->payload);
81
		}
82
 
83
		$return_curl_handle = isset($query['returnCurlHandle']) ? $query['returnCurlHandle'] : false;
84
		unset($query['returnCurlHandle']);
85
 
86
		// Do a case-sensitive, natural order sort on the array keys.
87
		uksort($query, 'strcmp');
88
		$canonical_query_string = $this->util->to_signable_string($query);
89
 
90
		// Remove the default scheme from the domain.
91
		$domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
92
 
93
		// Parse our request.
94
		$parsed_url = parse_url('http://' . $domain);
95
 
96
		// Set the proper host header.
97
		if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
98
		{
99
			$host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
100
		}
101
		else
102
		{
103
			$host_header = strtolower($parsed_url['host']);
104
		}
105
 
106
		// Set the proper request URI.
107
		$request_uri = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
108
 
109
		// Generate the querystring from $query
110
		$this->querystring = $this->util->to_query_string($query);
111
 
112
		// Gather information to pass along to other classes.
113
		$helpers = array(
114
			'utilities' => $this->utilities_class,
115
			'request' => $this->request_class,
116
			'response' => $this->response_class,
117
		);
118
 
119
		// Compose the request.
120
		$request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
121
		$request_url .= !isset($parsed_url['path']) ? '/' : '';
122
 
123
		// Instantiate the request class
124
		$request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
125
		$request->set_method('POST');
126
		$request->set_body($this->querystring);
127
		$headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
128
 
129
		// Pass along registered stream callbacks
130
		if ($this->registered_streaming_read_callback)
131
		{
132
			$request->register_streaming_read_callback($this->registered_streaming_read_callback);
133
		}
134
 
135
		if ($this->registered_streaming_write_callback)
136
		{
137
			$request->register_streaming_write_callback($this->registered_streaming_write_callback);
138
		}
139
 
140
		// Add authentication headers
141
		$headers['X-Amz-Nonce'] = $nonce;
142
		$headers['Date'] = $date;
143
		$headers['Content-Length'] = strlen($this->querystring);
144
		$headers['Content-MD5'] = $this->util->hex_to_base64(md5($this->querystring));
145
		$headers['Host'] = $host_header;
146
 
147
		// Sort headers
148
		uksort($headers, 'strnatcasecmp');
149
 
150
		// Prepare the string to sign (HTTPS)
151
		$this->string_to_sign = $date . $nonce;
152
 
153
		// Add headers to request and compute the string to sign
154
		foreach ($headers as $header_key => $header_value)
155
		{
156
			// Strip linebreaks from header values as they're illegal and can allow for security issues
157
			$header_value = str_replace(array("\r", "\n"), '', $header_value);
158
 
159
			// Add the header if it has a value
160
			if ($header_value !== '')
161
			{
162
				$request->add_header($header_key, $header_value);
163
			}
164
 
165
			// Generate the string to sign
166
			if (
167
				substr(strtolower($header_key), 0, 8) === 'content-' ||
168
				strtolower($header_key) === 'date' ||
169
				strtolower($header_key) === 'expires' ||
170
				strtolower($header_key) === 'host' ||
171
				substr(strtolower($header_key), 0, 6) === 'x-amz-'
172
			)
173
			{
174
				$signed_headers[] = $header_key;
175
			}
176
		}
177
 
178
		// Hash the AWS secret key and generate a signature for the request.
179
		$signature = base64_encode(hash_hmac('sha256', $this->string_to_sign, $this->secret_key, true));
180
 
181
		$headers['X-Amzn-Authorization'] = 'AWS3-HTTPS'
182
			. ' AWSAccessKeyId=' . $this->key
183
			. ',Algorithm=HmacSHA256'
184
			. ',SignedHeaders=' . implode(';', $signed_headers)
185
			. ',Signature=' . $signature;
186
 
187
		$request->add_header('X-Amzn-Authorization', $headers['X-Amzn-Authorization']);
188
		$request->request_headers = $headers;
189
 
190
		return $request;
191
	}
192
}