├── reset.sh
├── bucky.db
├── bucky.gif
├── addon
├── bucky.png
├── manifest.json
└── bucky.js
├── lib
├── .DS_Store
└── requestcore
│ ├── .DS_Store
│ └── requestcore.class.php
├── scr
├── run_bucky.png
├── all_buckets.png
├── bucky_addon.png
├── manual_check.png
├── vulnerable_poc.png
└── dashboard_loading.png
├── services
└── .DS_Store
├── utilities
├── .DS_Store
├── response.class.php
├── manifest.class.php
├── info.class.php
├── request.class.php
├── stepconfig.class.php
├── json.class.php
├── batchrequest.class.php
├── policy.class.php
├── credentials.class.php
├── complextype.class.php
├── credential.class.php
├── mimetypes.class.php
├── simplexml.class.php
├── gzipdecode.class.php
├── array.class.php
└── utilities.class.php
├── index.php
├── .github
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── dbreset.php
├── run.sh
├── manual_check.php
├── all_buckets.php
├── process.php
├── README.md
├── config.inc.php
└── sdk.class.php
/reset.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rm bucky.db
3 | php dbreset.php
--------------------------------------------------------------------------------
/bucky.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/bucky.db
--------------------------------------------------------------------------------
/bucky.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/bucky.gif
--------------------------------------------------------------------------------
/addon/bucky.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/addon/bucky.png
--------------------------------------------------------------------------------
/lib/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/lib/.DS_Store
--------------------------------------------------------------------------------
/scr/run_bucky.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/scr/run_bucky.png
--------------------------------------------------------------------------------
/scr/all_buckets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/scr/all_buckets.png
--------------------------------------------------------------------------------
/scr/bucky_addon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/scr/bucky_addon.png
--------------------------------------------------------------------------------
/scr/manual_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/scr/manual_check.png
--------------------------------------------------------------------------------
/services/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/services/.DS_Store
--------------------------------------------------------------------------------
/utilities/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/utilities/.DS_Store
--------------------------------------------------------------------------------
/scr/vulnerable_poc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/scr/vulnerable_poc.png
--------------------------------------------------------------------------------
/lib/requestcore/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/lib/requestcore/.DS_Store
--------------------------------------------------------------------------------
/scr/dashboard_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smaranchand/bucky/HEAD/scr/dashboard_loading.png
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | Bucky
9 |
10 |
11 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/addon/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "Bucky",
4 | "version": "1.0",
5 |
6 |
7 | "description": "Bucky discovers AWS S3 buckets from the web pages and sends it to the backend engine to check for misconfiguration.",
8 |
9 | "icons": {
10 | "48": "bucky.png"
11 | },
12 |
13 | "content_scripts": [
14 | {
15 | "matches": ["*://*/*"],
16 | "js": ["bucky.js"]
17 | }
18 | ],
19 |
20 | "permissions": [
21 | "http://127.0.0.1/*",
22 | "webRequest"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/dbreset.php:
--------------------------------------------------------------------------------
1 | open('bucky.db');
6 | }
7 | }
8 | $db = new MyDB();
9 | if(!$db) {
10 | echo $db->lastErrorMsg();
11 | } else {
12 | $sql =<<exec($sql);
23 | if(!$ret){
24 | echo $db->lastErrorMsg();
25 | } else {
26 | echo "Database setup successful.";
27 | }
28 | $db->close();
29 | }
30 | ?>
31 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #Bucky is AWS S3 bucket discovery tool developed by https://twitter.com/smaranchand
3 | #Bucky Backend Engine automatically takes input from Bucky addon and check for misconfiguration.
4 | #Download Bucky aaddon from https://addons.mozilla.org/en-US/firefox/addon/bucky/
5 | #No changes done.
6 | echo "
7 | ____ _ __ ___
8 | | _ \ | | /_ | / _ \
9 | | |_) |_ _ ___| | ___ _ __ _| || | | |
10 | | _ <| | | |/ __| |/ / | | | \ \ / / || | | |
11 | | |_) | |_| | (__| <| |_| | \ V /| || |_| |
12 | |____/ \__,_|\___|_|\_\\__, | \_/ |_(_)___/
13 | __/ |
14 | |___/
15 | An automatic tool to find misconfigured AWS S3 buckets.
16 | Developed by : https://twitter.com/smaranchand
17 | ";
18 | php -S 127.0.0.1:13337
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/addon/bucky.js:
--------------------------------------------------------------------------------
1 | //If you think we can improve Bucky, then suggestions are welcomed.
2 | var sourcecode = document.documentElement.outerHTML;
3 | var pageurl= document.URL;
4 | var hostname= window.location.hostname;
5 | var s3bucketurl= sourcecode.match(/https:\/\/[a-z0-9-.]{3,63}\.s3\.([a-z0-9-]{5,19}\.|)amazonaws\.com/g);
6 | if (s3bucketurl==null)
7 | {
8 | var s3bucketname= sourcecode.match(/(?<=\/\/s3\.amazonaws.com\/)[a-z0-9-.]{3,63}(?=\/)/);
9 | if (s3bucketname==null)
10 | {
11 | }
12 | else
13 | sendBucket();
14 |
15 | }
16 | else
17 | {
18 | var s3bucketname= String(s3bucketurl[0]).match(/(?<=\/\/).*(?=\.s3)/);
19 | sendBucket();
20 | }
21 |
22 | function sendBucket() {
23 |
24 | var xhr = new XMLHttpRequest();
25 | xhr.open("POST", "http://127.0.0.1:13337/process.php", true);
26 | xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
27 | xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
28 | var body = ("bucketname="+s3bucketname+"&sourceurl="+pageurl+"&hostname="+hostname);
29 | xhr.send(body);
30 |
31 | }
--------------------------------------------------------------------------------
/manual_check.php:
--------------------------------------------------------------------------------
1 |
2 | Manual Check
3 |
4 |
5 |
38 |
39 |
42 |
43 |
44 |
50 |
51 |
--------------------------------------------------------------------------------
/utilities/response.class.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | All Buckets
4 |
50 |
51 |
54 |
55 |
56 |
57 | | SN |
58 | Bucket Name |
59 | Source URL |
60 | IP |
61 | POC |
62 | VULNERABLE |
63 |
64 | open('bucky.db');
68 | }
69 | }
70 |
71 | $db = new MyDB();
72 | if(!$db) {
73 | echo $db->lastErrorMsg();
74 | } else {
75 |
76 | }
77 |
78 | $sql =<<query($sql);
83 | while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
84 | echo "";
85 | echo "| ". $row['ID'] . " | ";
86 | echo "". $row['BUCKETNAME'] . " | ";
87 | echo "". $row['URL'] ." | ";
88 | echo "". $row['IP'] ." | ";
89 | echo "". $row['POC'] ." | ";
90 | echo "".$row['VULNERABLE'] ." | ";
91 | }
92 | $db->close();
93 | ?>
--------------------------------------------------------------------------------
/utilities/manifest.class.php:
--------------------------------------------------------------------------------
1 | function.
36 | * @return string A YAML manifest document.
37 | */
38 | public static function json($json)
39 | {
40 | $map = json_decode($json, true);
41 | return sfYaml::dump($map);
42 | }
43 |
44 | /**
45 | * Takes an associative array to convert to a YAML manifest.
46 | *
47 | * @param array $map (Required) An associative array.
48 | * @return string A YAML manifest document.
49 | */
50 | public static function map($map)
51 | {
52 | return sfYaml::dump($map);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/utilities/info.class.php:
--------------------------------------------------------------------------------
1 | api_version;
64 | unset($obj);
65 | }
66 |
67 | return $collect;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/process.php:
--------------------------------------------------------------------------------
1 | open('bucky.db');
12 | }
13 | }
14 |
15 | $db = new MyDB();
16 | if(!$db){
17 | echo $db->lastErrorMsg();
18 | } else {
19 | }
20 |
21 | $sql =<<YES' );
24 |
25 | EOF;
26 |
27 | $ret = $db->exec($sql);
28 | if(!$ret) {
29 | echo $db->lastErrorMsg();
30 | } else {
31 |
32 | header("refresh:3; url=all_buckets.php");
33 | echo "S3 Bucket $newbucket seems vulnerable, Check dashboard for more information.";
34 |
35 | }
36 | $db->close();
37 | }
38 |
39 | function bucketfailed(){
40 | $newbucket=$_POST['bucketname'];
41 | $sourceurl=$_POST['sourceurl'];
42 | $hostname=$_POST['hostname'];
43 | $serverip= gethostbyname("$hostname");
44 | class MyDB extends SQLite3 {
45 | function __construct() {
46 | $this->open('bucky.db');
47 | }
48 | }
49 |
50 | $db = new MyDB();
51 | if(!$db){
52 | echo $db->lastErrorMsg();
53 | } else {
54 | }
55 |
56 | $sql =<<exec($sql);
63 | if(!$ret) {
64 | echo $db->lastErrorMsg();
65 | } else {
66 | header("refresh:3; url=manual_check.php");
67 | echo "S3 Bucket $newbucket doesnot seems vulnerable, Check dashboard for more information.";
68 | }
69 | $db->close();
70 | }
71 |
72 | $newbucket=$_POST['bucketname'];
73 | error_reporting(0);
74 | require_once 'sdk.class.php';
75 | $s3 = new AmazonS3();
76 | $response = $s3->create_object($newbucket, 'bucky.txt', array(
77 | 'contentType' => 'text/plain',
78 | 'body' => 'S3 bucket misconfiguration is discovered.
79 | Discovered by Bucky.
80 | Developed by: https://twitter.com/smaranchand',
81 | 'acl'=>AmazonS3::ACL_PUBLIC,
82 | ));
83 | if ((int) $response->isOK())
84 | bucketsuccess();
85 | else
86 | bucketfailed();
87 | ?>
88 |
--------------------------------------------------------------------------------
/utilities/request.class.php:
--------------------------------------------------------------------------------
1 | ).
33 | */
34 | public $request_class = 'CFRequest';
35 |
36 | /**
37 | * The default class to use for HTTP Responses (defaults to ).
38 | */
39 | public $response_class = 'CFResponse';
40 |
41 | /**
42 | * The active credential set.
43 | */
44 | public $credentials;
45 |
46 |
47 | /*%******************************************************************************************%*/
48 | // CONSTRUCTOR
49 |
50 | /**
51 | * Constructs a new instance of this class.
52 | *
53 | * @param string $url (Optional) The URL to request or service endpoint to query.
54 | * @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
55 | * @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
56 | * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
57 | * @return $this A reference to the current instance.
58 | */
59 | public function __construct($url = null, $proxy = null, $helpers = null, CFCredential $credentials = null)
60 | {
61 | parent::__construct($url, $proxy, $helpers);
62 |
63 | // Standard settings for all requests
64 | $this->set_useragent(CFRUNTIME_USERAGENT);
65 | $this->credentials = $credentials;
66 | $this->cacert_location = ($this->credentials['certificate_authority'] ? $this->credentials['certificate_authority'] : false);
67 |
68 | if (strpos(parse_url($url, PHP_URL_HOST), 'dynamodb') === 0)
69 | {
70 | $this->use_gzip_enconding = false;
71 | }
72 |
73 | return $this;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/utilities/stepconfig.class.php:
--------------------------------------------------------------------------------
1 | config = $config;
52 | }
53 |
54 | /**
55 | * Constructs a new instance of this class, and allows chaining.
56 | *
57 | * @param array $config (Required) An associative array representing the Hadoop step configuration.
58 | * @return $this A reference to the current instance.
59 | */
60 | public static function init($config)
61 | {
62 | if (version_compare(PHP_VERSION, '5.3.0', '<'))
63 | {
64 | throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
65 | }
66 |
67 | $self = get_called_class();
68 | return new $self($config);
69 | }
70 |
71 | /**
72 | * Returns a JSON representation of the object when typecast as a string.
73 | *
74 | * @return string A JSON representation of the object.
75 | * @link http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring PHP Magic Methods
76 | */
77 | public function __toString()
78 | {
79 | return json_encode($this->config);
80 | }
81 |
82 | /**
83 | * Returns the configuration data.
84 | *
85 | * @return array The configuration data.
86 | */
87 | public function get_config()
88 | {
89 | return $this->config;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/utilities/json.class.php:
--------------------------------------------------------------------------------
1 | SimpleXMLElement. Has a default value of CFSimpleXML.
36 | * @return CFSimpleXML An XML representation of the data.
37 | */
38 | public static function to_xml($json, $parser = 'CFSimpleXML')
39 | {
40 | // If we haven't parsed the JSON, do it
41 | if (!is_array($json))
42 | {
43 | // Handle the case of JSON-encoded NULL value
44 | if ($json === 'null')
45 | {
46 | $json = null;
47 | }
48 | else
49 | {
50 | $json = json_decode($json, true);
51 |
52 | if (function_exists('json_last_error'))
53 | {
54 | // Did we encounter an error?
55 | switch (json_last_error())
56 | {
57 | case JSON_ERROR_DEPTH:
58 | throw new JSON_Exception('Maximum stack depth exceeded.');
59 |
60 | case JSON_ERROR_CTRL_CHAR:
61 | throw new JSON_Exception('Unexpected control character found.');
62 |
63 | case JSON_ERROR_SYNTAX:
64 | throw new JSON_Exception('Syntax error; Malformed JSON.');
65 |
66 | case JSON_ERROR_STATE_MISMATCH:
67 | throw new JSON_Exception('Invalid or malformed JSON.');
68 | }
69 | }
70 | // json_last_error() not available?
71 | elseif ($json === null)
72 | {
73 | throw new JSON_Exception('Unknown JSON error. Be sure to validate your JSON and read the notes on http://php.net/json_decode.');
74 | }
75 | }
76 | }
77 |
78 | // Hand off for the recursive work
79 | $string = Transmogrifier::to_xml($json, 'rootElement');
80 |
81 | return simplexml_load_string($string, $parser, LIBXML_NOCDATA);
82 | }
83 | }
84 |
85 |
86 | /**
87 | * Default JSON Exception.
88 | */
89 | class JSON_Exception extends Exception {}
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | # Project is on temporary hold.
5 |
6 | # Bucky
7 | Bucky is an automatic tool designed to discover S3 bucket misconfiguration, Bucky consists up of two modules Bucky firefox addon and Bucky backend engine. Bucky addon reads the source code of the webpages and uses Regular Expression(Regex) to match the S3 bucket used as Content Delivery Network(CDN) and sends it to the Bucky Backend engine. The backend engine receives the data from addon and checks if the S3 bucket is publicly writeable or not. Bucky automatically uploads a text file as Proof Of Concept(PoC) if the bucket is vulnerable.
8 |
9 |
10 | # Working
11 | Bucky addon sends the details of s3 bucket name discovered from a user visited web pages to backend engine.
12 | It uses [AWS PHP SDK](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/getting-started_installation.html) to discover misconfiguration.
13 | Users can also check for S3 bucket misconfiguration manually. All the results from automatic and manuall check are populated to dashboard.
14 |
15 | Checkout video https://vimeo.com/444442588
16 |
17 | # Installation
18 |
19 | ```
20 | git clone https://github.com/smaranchand/bucky.git
21 | cd bucky
22 |
23 | ```
24 |
25 | Requirements: AWS Access Keys and PHP installation
26 |
27 | Get AWS Access Keys: https://console.aws.amazon.com/iam/home?#/security_credentials
28 |
29 | PHP installation: Install according to your OS, apt install php7.3 / brew install php7.3
30 |
31 |
32 | Currently, Bucky addon is not published in the Firefox addon store; as soon as the addon will be published, the addon link will be provided.
33 |
34 | For now, users can manually load the addon into the browser to do so
35 |
36 | 1. Open Firefox browser and visit about:debugging
37 | 2. Click on "This Firefox" > Load Temporary Add-on
38 | 3. Select the addon located at bucky/addon/bucky.js
39 |
40 | Add AWS Access keys:
41 | ```
42 | cd bucky/
43 | nano config.inc.php
44 | Add your AWS Access Key ID and Secret Access Key. (On-Line 57 and 61)
45 | ```
46 |
47 |
48 | # Usage
49 |
50 | To use Bucky, load the Bucky addon to the browser and start backend engine.
51 | ```
52 | cd bucky/
53 | chmod +x run.sh
54 | ./run.sh
55 |
56 | The backend engine runs on http://127.0.0.1:13337
57 | Browse websites, Bucky will discover S3 buckets automatically and will be reflected in the dashboard.
58 | Visit the above address to access Bucky dashboard.
59 | ```
60 |
61 | # Screenshots
62 | Running Bucky
63 |
64 | 
65 |
66 | Loading Addon
67 |
68 | 
69 | User Interface
70 |
71 | 
72 |
73 | All Buckets
74 |
75 | 
76 | Manual Check
77 |
78 | 
79 |
80 | POC By Bucky
81 |
82 | 
83 |
84 |
85 |
86 | # Note
87 | Bucky is not a perfect tool to discover S3 buckets, it is well known that Bucky lacks many feautres and it may fail to detect the misconfiguration sometimes. Certain changes and development are in pipeline. I really appreciate the feedbacks and contribution.
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/config.inc.php:
--------------------------------------------------------------------------------
1 | array(
54 |
55 | // Amazon Web Services Key. Found in the AWS Security Credentials. You can also pass
56 | // this value as the first parameter to a service constructor.
57 | 'key' => 'YOUR_AWS_KEY',
58 |
59 | // Amazon Web Services Secret Key. Found in the AWS Security Credentials. You can also
60 | // pass this value as the second parameter to a service constructor.
61 | 'secret' => 'YOUR_SECRET',
62 |
63 | // This option allows you to configure a preferred storage type to use for caching by
64 | // default. This can be changed later using the set_cache_config() method.
65 | //
66 | // Valid values are: `apc`, `xcache`, or a file system path such as `./cache` or
67 | // `/tmp/cache/`.
68 | 'default_cache_config' => '',
69 |
70 | // Determines which Cerificate Authority file to use.
71 | //
72 | // A value of boolean `false` will use the Certificate Authority file available on the
73 | // system. A value of boolean `true` will use the Certificate Authority provided by the
74 | // SDK. Passing a file system path to a Certificate Authority file (chmodded to `0755`)
75 | // will use that.
76 | //
77 | // Leave this set to `false` if you're not sure.
78 | 'certificate_authority' => false
79 | ),
80 |
81 | // Specify a default credential set to use if there are more than one.
82 | '@default' => 'development'
83 | ));
84 |
--------------------------------------------------------------------------------
/utilities/batchrequest.class.php:
--------------------------------------------------------------------------------
1 | queue = array();
80 | $this->limit = $limit ? $limit : -1;
81 | $this->credentials = new CFCredential(array());
82 | return $this;
83 | }
84 |
85 | /**
86 | * Sets the AWS credentials to use for the batch request.
87 | *
88 | * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
89 | * @return $this A reference to the current instance.
90 | */
91 | public function use_credentials(CFCredential $credentials)
92 | {
93 | $this->credentials = $credentials;
94 | return $this;
95 | }
96 |
97 | /**
98 | * Adds a new cURL handle to the request queue.
99 | *
100 | * @param resource $handle (Required) A cURL resource to add to the queue.
101 | * @return $this A reference to the current instance.
102 | */
103 | public function add($handle)
104 | {
105 | $this->queue[] = $handle;
106 | return $this;
107 | }
108 |
109 | /**
110 | * Executes the batch request queue.
111 | *
112 | * @param array $opt (DO NOT USE) Enabled for compatibility with the method this overrides, although any values passed will be ignored.
113 | * @return array An indexed array of objects.
114 | */
115 | public function send($opt = null)
116 | {
117 | $http = new $this->request_class(null, $this->proxy, null, $this->credentials);
118 |
119 | // Make the request
120 | $response = $http->send_multi_request($this->queue, array(
121 | 'limit' => $this->limit
122 | ));
123 |
124 | return $response;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/utilities/policy.class.php:
--------------------------------------------------------------------------------
1 | (e.g. , ).
45 | * @param string|array $policy (Required) The associative array representing the S3 policy to use, or a string of JSON content.
46 | * @return $this A reference to the current instance.
47 | * @link http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?HTTPPOSTForms.html S3 Policies
48 | * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?AccessPolicyLanguage.html Access Policy Language
49 | */
50 | public function __construct($auth, $policy)
51 | {
52 | $this->auth = $auth;
53 |
54 | if (is_array($policy)) // We received an associative array...
55 | {
56 | $this->json_policy = json_encode($policy);
57 | }
58 | else // We received a valid, parseable JSON string...
59 | {
60 | $this->json_policy = json_encode(json_decode($policy, true));
61 | }
62 |
63 | return $this;
64 | }
65 |
66 | /**
67 | * Alternate approach to constructing a new instance. Supports chaining.
68 | *
69 | * @param CFRuntime $auth (Required) An instance of any authenticated AWS object that is an instance of (e.g. , ).
70 | * @param string|array $policy (Required) The associative array representing the S3 policy to use, or a string of JSON content.
71 | * @return $this A reference to the current instance.
72 | */
73 | public static function init($auth, $policy)
74 | {
75 | if (version_compare(PHP_VERSION, '5.3.0', '<'))
76 | {
77 | throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
78 | }
79 |
80 | $self = get_called_class();
81 | return new $self($auth, $policy);
82 | }
83 |
84 | /**
85 | * Get the key from the authenticated instance.
86 | *
87 | * @return string The key from the authenticated instance.
88 | */
89 | public function get_key()
90 | {
91 | return $this->auth->key;
92 | }
93 |
94 | /**
95 | * Base64-encodes the JSON string.
96 | *
97 | * @return string The Base64-encoded version of the JSON string.
98 | */
99 | public function get_policy()
100 | {
101 | return base64_encode($this->json_policy);
102 | }
103 |
104 | /**
105 | * Gets the JSON string with the whitespace removed.
106 | *
107 | * @return string The JSON string without extraneous whitespace.
108 | */
109 | public function get_json()
110 | {
111 | return $this->json_policy;
112 | }
113 |
114 | /**
115 | * Gets the JSON string with the whitespace removed.
116 | *
117 | * @return string The Base64-encoded, signed JSON string.
118 | */
119 | public function get_policy_signature()
120 | {
121 | return base64_encode(hash_hmac('sha1', $this->get_policy(), $this->auth->secret_key));
122 | }
123 |
124 | /**
125 | * Decode a policy that was returned from the service.
126 | *
127 | * @param string $response (Required) The policy returned by AWS that you want to decode into an object.
128 | * @return string The Base64-encoded, signed JSON string.
129 | */
130 | public static function decode_policy($response)
131 | {
132 | return json_decode(urldecode($response), true);
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/utilities/credentials.class.php:
--------------------------------------------------------------------------------
1 | class enables developers to easily switch between multiple sets of credentials.
23 | *
24 | * @version 2012.07.13
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 CFCredentials
30 | {
31 | /**
32 | * The key used to specify the default credential set
33 | */
34 | const DEFAULT_KEY = '@default';
35 |
36 | /**
37 | * The key used to identify inherited credentials
38 | */
39 | const INHERIT_KEY = '@inherit';
40 |
41 | /**
42 | * Stores the credentials
43 | */
44 | protected static $credentials = array();
45 |
46 | /**
47 | * Prevents this class from being constructed
48 | */
49 | final private function __construct() {}
50 |
51 | /**
52 | * Stores the credentials for re-use.
53 | *
54 | * @param array $credential_sets (Required) The named credential sets that should be made available to the application.
55 | * @return void
56 | */
57 | public static function set(array $credential_sets)
58 | {
59 | // Make sure a default credential set is specified or can be inferred
60 | if (count($credential_sets) === 1)
61 | {
62 | $credential_sets[self::DEFAULT_KEY] = reset($credential_sets);
63 | }
64 |
65 | // Resolve any @inherit tags
66 | foreach ($credential_sets as $credential_name => &$credential_set)
67 | {
68 | if (is_array($credential_set))
69 | {
70 | foreach ($credential_set as $credential_key => &$credential_value)
71 | {
72 | if ($credential_key === self::INHERIT_KEY)
73 | {
74 | if (!isset($credential_sets[$credential_value]))
75 | {
76 | throw new CFCredentials_Exception('The credential set, "' . $credential_value . '", does not exist and cannot be inherited.');
77 | }
78 |
79 | $credential_set = array_merge($credential_sets[$credential_value], $credential_set);
80 | unset($credential_set[self::INHERIT_KEY]);
81 | }
82 | }
83 | }
84 | }
85 |
86 | // Normalize the value of the @default credential set
87 | if (isset($credential_sets[self::DEFAULT_KEY]))
88 | {
89 | $default = $credential_sets[self::DEFAULT_KEY];
90 | if (is_string($default))
91 | {
92 | if (!isset($credential_sets[$default]))
93 | {
94 | throw new CFCredentials_Exception('The credential set, "' . $default . '", does not exist and cannot be used as the default credential set.');
95 | }
96 |
97 | $credential_sets[self::DEFAULT_KEY] = $credential_sets[$default];
98 | }
99 | }
100 |
101 | // Store the credentials
102 | self::$credentials = $credential_sets;
103 | }
104 |
105 | /**
106 | * Retrieves the requested credentials from the internal credential store.
107 | *
108 | * @param string $credential_set (Optional) The name of the credential set to retrieve. The default value is set in DEFAULT_KEY.
109 | * @return stdClass A stdClass object where the properties represent the keys that were provided.
110 | */
111 | public static function get($credential_name = self::DEFAULT_KEY)
112 | {
113 | // Make sure the credential set exists
114 | if (!isset(self::$credentials[$credential_name]))
115 | {
116 | throw new CFCredentials_Exception('The credential set, "' . $credential_name . '", does not exist and cannot be retrieved.');
117 | }
118 |
119 | // Return the credential set as an object
120 | return new CFCredential(self::$credentials[$credential_name]);
121 | }
122 |
123 | /**
124 | * Retrieves a list of all available credential set names.
125 | *
126 | * @return CFArray A list of all available credential set names.
127 | */
128 | public static function list_sets()
129 | {
130 | return new CFArray(array_keys(self::$credentials));
131 | }
132 | }
133 |
134 | class CFCredentials_Exception extends Exception {}
135 |
--------------------------------------------------------------------------------
/utilities/complextype.class.php:
--------------------------------------------------------------------------------
1 | function.
35 | * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
36 | * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
37 | * @return array The option group parameters to merge into another method's `$opt` parameter.
38 | */
39 | public static function json($json, $member = '', $default_key = '')
40 | {
41 | return self::option_group(json_decode($json, true), $member, $default_key);
42 | }
43 |
44 | /**
45 | * Takes a YAML object, as a string, to convert to query string keys.
46 | *
47 | * @param string $yaml (Required) A YAML object.
48 | * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
49 | * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
50 | * @return array The option group parameters to merge into another method's `$opt` parameter.
51 | */
52 | public static function yaml($yaml, $member = '', $default_key = '')
53 | {
54 | return self::option_group(sfYaml::load($yaml), $member, $default_key);
55 | }
56 |
57 | /**
58 | * Takes an associative array to convert to query string keys.
59 | *
60 | * @param array $map (Required) An associative array.
61 | * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
62 | * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
63 | * @return array The option group parameters to merge into another method's `$opt` parameter.
64 | */
65 | public static function map($map, $member = '', $default_key = '')
66 | {
67 | return self::option_group($map, $member, $default_key);
68 | }
69 |
70 | /**
71 | * A protected method that is used by , and