Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1821634
AWS.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
5 KB
Subscribers
None
AWS.php
View Options
<?php
namespace
Sabre\HTTP\Auth
;
use
Sabre\HTTP\Util
;
/**
* HTTP AWS Authentication handler
*
* Use this class to leverage amazon's AWS authentication header
*
* @copyright Copyright (C) 2009-2015 fruux GmbH (https://fruux.com/).
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class
AWS
extends
AbstractAuth
{
/**
* The signature supplied by the HTTP client
*
* @var string
*/
private
$signature
=
null
;
/**
* The accesskey supplied by the HTTP client
*
* @var string
*/
private
$accessKey
=
null
;
/**
* An error code, if any
*
* This value will be filled with one of the ERR_* constants
*
* @var int
*/
public
$errorCode
=
0
;
const
ERR_NOAWSHEADER
=
1
;
const
ERR_MD5CHECKSUMWRONG
=
2
;
const
ERR_INVALIDDATEFORMAT
=
3
;
const
ERR_REQUESTTIMESKEWED
=
4
;
const
ERR_INVALIDSIGNATURE
=
5
;
/**
* Gathers all information from the headers
*
* This method needs to be called prior to anything else.
*
* @return bool
*/
function
init
()
{
$authHeader
=
$this
->
request
->
getHeader
(
'Authorization'
);
$authHeader
=
explode
(
' '
,
$authHeader
);
if
(
$authHeader
[
0
]
!=
'AWS'
||
!
isset
(
$authHeader
[
1
]))
{
$this
->
errorCode
=
self
::
ERR_NOAWSHEADER
;
return
false
;
}
list
(
$this
->
accessKey
,
$this
->
signature
)
=
explode
(
':'
,
$authHeader
[
1
]);
return
true
;
}
/**
* Returns the username for the request
*
* @return string
*/
function
getAccessKey
()
{
return
$this
->
accessKey
;
}
/**
* Validates the signature based on the secretKey
*
* @param string $secretKey
* @return bool
*/
function
validate
(
$secretKey
)
{
$contentMD5
=
$this
->
request
->
getHeader
(
'Content-MD5'
);
if
(
$contentMD5
)
{
// We need to validate the integrity of the request
$body
=
$this
->
request
->
getBody
(
true
);
$this
->
request
->
setBody
(
$body
,
true
);
if
(
$contentMD5
!=
base64_encode
(
md5
(
$body
,
true
)))
{
// content-md5 header did not match md5 signature of body
$this
->
errorCode
=
self
::
ERR_MD5CHECKSUMWRONG
;
return
false
;
}
}
if
(!
$requestDate
=
$this
->
request
->
getHeader
(
'x-amz-date'
))
$requestDate
=
$this
->
request
->
getHeader
(
'Date'
);
if
(!
$this
->
validateRFC2616Date
(
$requestDate
))
return
false
;
$amzHeaders
=
$this
->
getAmzHeaders
();
$signature
=
base64_encode
(
$this
->
hmacsha1
(
$secretKey
,
$this
->
request
->
getMethod
()
.
"
\n
"
.
$contentMD5
.
"
\n
"
.
$this
->
request
->
getHeader
(
'Content-type'
)
.
"
\n
"
.
$requestDate
.
"
\n
"
.
$amzHeaders
.
$this
->
request
->
getUrl
()
)
);
if
(
$this
->
signature
!=
$signature
)
{
$this
->
errorCode
=
self
::
ERR_INVALIDSIGNATURE
;
return
false
;
}
return
true
;
}
/**
* Returns an HTTP 401 header, forcing login
*
* This should be called when username and password are incorrect, or not supplied at all
*
* @return void
*/
function
requireLogin
()
{
$this
->
response
->
addHeader
(
'WWW-Authenticate'
,
'AWS'
);
$this
->
response
->
setStatus
(
401
);
}
/**
* Makes sure the supplied value is a valid RFC2616 date.
*
* If we would just use strtotime to get a valid timestamp, we have no way of checking if a
* user just supplied the word 'now' for the date header.
*
* This function also makes sure the Date header is within 15 minutes of the operating
* system date, to prevent replay attacks.
*
* @param string $dateHeader
* @return bool
*/
protected
function
validateRFC2616Date
(
$dateHeader
)
{
$date
=
Util
::
parseHTTPDate
(
$dateHeader
);
// Unknown format
if
(!
$date
)
{
$this
->
errorCode
=
self
::
ERR_INVALIDDATEFORMAT
;
return
false
;
}
$min
=
new
\DateTime
(
'-15 minutes'
);
$max
=
new
\DateTime
(
'+15 minutes'
);
// We allow 15 minutes around the current date/time
if
(
$date
>
$max
||
$date
<
$min
)
{
$this
->
errorCode
=
self
::
ERR_REQUESTTIMESKEWED
;
return
false
;
}
return
$date
;
}
/**
* Returns a list of AMZ headers
*
* @return string
*/
protected
function
getAmzHeaders
()
{
$amzHeaders
=
[];
$headers
=
$this
->
request
->
getHeaders
();
foreach
(
$headers
as
$headerName
=>
$headerValue
)
{
if
(
strpos
(
strtolower
(
$headerName
),
'x-amz-'
)
===
0
)
{
$amzHeaders
[
strtolower
(
$headerName
)]
=
str_replace
([
"
\r\n
"
],
[
' '
],
$headerValue
[
0
])
.
"
\n
"
;
}
}
ksort
(
$amzHeaders
);
$headerStr
=
''
;
foreach
(
$amzHeaders
as
$h
=>
$v
)
{
$headerStr
.=
$h
.
':'
.
$v
;
}
return
$headerStr
;
}
/**
* Generates an HMAC-SHA1 signature
*
* @param string $key
* @param string $message
* @return string
*/
private
function
hmacsha1
(
$key
,
$message
)
{
if
(
function_exists
(
'hash_hmac'
))
{
return
hash_hmac
(
'sha1'
,
$message
,
$key
,
true
);
}
$blocksize
=
64
;
if
(
strlen
(
$key
)
>
$blocksize
)
{
$key
=
pack
(
'H*'
,
sha1
(
$key
));
}
$key
=
str_pad
(
$key
,
$blocksize
,
chr
(
0x00
));
$ipad
=
str_repeat
(
chr
(
0x36
),
$blocksize
);
$opad
=
str_repeat
(
chr
(
0x5c
),
$blocksize
);
$hmac
=
pack
(
'H*'
,
sha1
((
$key
^
$opad
)
.
pack
(
'H*'
,
sha1
((
$key
^
$ipad
)
.
$message
))));
return
$hmac
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Tue, Dec 24, 7:47 AM (22 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
915356
Default Alt Text
AWS.php (5 KB)
Attached To
rDAVCAL DokuWiki DAVCal PlugIn
Event Timeline
Log In to Comment