1 | <?php namespace Arcanedev\Stripe\Http\Curl; |
||
13 | class SslChecker implements SslCheckerContract |
||
14 | { |
||
15 | /* ------------------------------------------------------------------------------------------------ |
||
16 | | Properties |
||
17 | | ------------------------------------------------------------------------------------------------ |
||
18 | */ |
||
19 | /** @var string */ |
||
20 | protected $url = ''; |
||
21 | |||
22 | /* ------------------------------------------------------------------------------------------------ |
||
23 | | Getters & Setters |
||
24 | | ------------------------------------------------------------------------------------------------ |
||
25 | */ |
||
26 | /** |
||
27 | * Get URL. |
||
28 | * |
||
29 | * @return string |
||
30 | */ |
||
31 | 6 | public function getUrl() |
|
35 | |||
36 | /** |
||
37 | * Set URL. |
||
38 | * |
||
39 | * @param string $url |
||
40 | * |
||
41 | * @return self |
||
42 | */ |
||
43 | 2 | public function setUrl($url) |
|
49 | |||
50 | /* ------------------------------------------------------------------------------------------------ |
||
51 | | Main Functions |
||
52 | | ------------------------------------------------------------------------------------------------ |
||
53 | */ |
||
54 | /** |
||
55 | * Preflight the SSL certificate presented by the backend. This isn't 100% |
||
56 | * bulletproof, in that we're not actually validating the transport used to |
||
57 | * communicate with Stripe, merely that the first attempt to does not use a |
||
58 | * revoked certificate. |
||
59 | * |
||
60 | * Unfortunately the interface to OpenSSL doesn't make it easy to check the |
||
61 | * certificate before sending potentially sensitive data on the wire. This |
||
62 | * approach raises the bar for an attacker significantly. |
||
63 | * |
||
64 | * @param string $url |
||
65 | * |
||
66 | * @return bool |
||
67 | */ |
||
68 | public function checkCert($url) |
||
88 | |||
89 | /* ------------------------------------------------------------------------------------------------ |
||
90 | | Check Functions |
||
91 | | ------------------------------------------------------------------------------------------------ |
||
92 | */ |
||
93 | /** |
||
94 | * Check black list. |
||
95 | * |
||
96 | * @param string $pemCert |
||
97 | * |
||
98 | * @throws \Arcanedev\Stripe\Exceptions\ApiConnectionException |
||
99 | */ |
||
100 | 2 | public function checkBlackList($pemCert) |
|
101 | { |
||
102 | 2 | if ($this->isBlackListed($pemCert)) { |
|
103 | 2 | throw new ApiConnectionException( |
|
104 | 'Invalid server certificate. You tried to connect to a server that has a revoked SSL certificate, '. |
||
105 | 'which means we cannot securely send data to that server. '. |
||
106 | 2 | 'Please email [email protected] if you need help connecting to the correct API server.' |
|
107 | ); |
||
108 | } |
||
109 | } |
||
110 | |||
111 | /** |
||
112 | * Checks if a valid PEM encoded certificate is blacklisted. |
||
113 | * |
||
114 | * @param string $cert |
||
115 | * |
||
116 | * @return bool |
||
117 | */ |
||
118 | 4 | public function isBlackListed($cert) |
|
119 | { |
||
120 | 4 | $lines = explode("\n", trim($cert)); |
|
121 | |||
122 | // Kludgily remove the PEM padding |
||
123 | 4 | array_shift($lines); |
|
124 | 4 | array_pop($lines); |
|
125 | |||
126 | 4 | $fingerprint = sha1(base64_decode(implode('', $lines))); |
|
127 | |||
128 | 4 | return in_array($fingerprint, [ |
|
129 | 4 | '05c0b3643694470a888c6e7feb5c9e24e823dc53', |
|
130 | '5b7dc7fbc98d78bf76d4d4fa6f597a0c901fad5c', |
||
131 | ]); |
||
132 | } |
||
133 | |||
134 | |||
135 | /** |
||
136 | * Stream Extension exists - Return true if one of the extensions not found. |
||
137 | * |
||
138 | * @return bool |
||
139 | */ |
||
140 | private function hasStreamExtensions() |
||
145 | |||
146 | /** |
||
147 | * Check if has errors or empty result. |
||
148 | * |
||
149 | * @param mixed $result |
||
150 | * @param int|null $errorNo |
||
151 | * @param string $errorStr |
||
152 | * |
||
153 | * @throws \Arcanedev\Stripe\Exceptions\ApiConnectionException |
||
154 | */ |
||
155 | 4 | private function checkResult($result, $errorNo, $errorStr) |
|
156 | { |
||
157 | if ( |
||
158 | 4 | ($errorNo !== 0 && $errorNo !== null) || $result === false |
|
159 | ) |
||
160 | 4 | throw new ApiConnectionException( |
|
161 | 4 | 'Could not connect to Stripe ('.$this->getUrl().'). Please check your internet connection and try again. ' . |
|
162 | 4 | 'If this problem persists, you should check Stripe\'s service status at https://twitter.com/stripestatus. ' . |
|
163 | 4 | 'Reason was: ' . $errorStr |
|
164 | ); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * Check if has SSL Errors |
||
169 | * |
||
170 | * @param int $errorNum |
||
171 | * |
||
172 | * @return bool |
||
173 | */ |
||
174 | 300 | public static function hasCertErrors($errorNum) |
|
175 | { |
||
176 | 300 | return in_array($errorNum, [ |
|
177 | 300 | CURLE_SSL_CACERT, |
|
178 | 300 | CURLE_SSL_PEER_CERTIFICATE, |
|
179 | 300 | CURLE_SSL_CACERT_BADFILE |
|
180 | ]); |
||
181 | } |
||
182 | |||
183 | /* ------------------------------------------------------------------------------------------------ |
||
184 | | Other Functions |
||
185 | | ------------------------------------------------------------------------------------------------ |
||
186 | */ |
||
187 | /** |
||
188 | * Prepare SSL URL. |
||
189 | * |
||
190 | * @param string $url |
||
191 | * |
||
192 | * @return string |
||
193 | */ |
||
194 | 2 | private function prepareUrl($url) |
|
200 | |||
201 | /** |
||
202 | * Open a socket connection. |
||
203 | * |
||
204 | * @return array |
||
205 | */ |
||
206 | private function streamSocketClient() |
||
207 | { |
||
208 | $result = stream_socket_client( |
||
209 | $this->getUrl(), |
||
210 | $errorNo, |
||
211 | $errorStr, |
||
212 | 30, |
||
213 | STREAM_CLIENT_CONNECT, |
||
214 | stream_context_create([ |
||
215 | 'ssl' => [ |
||
216 | 'capture_peer_cert' => true, |
||
217 | 'verify_peer' => true, |
||
218 | 'cafile' => self::caBundle(), |
||
219 | ], |
||
220 | ]) |
||
221 | ); |
||
222 | |||
223 | return [$result, $errorNo, $errorStr]; |
||
224 | } |
||
225 | |||
226 | /** |
||
227 | * Get the certificates file path. |
||
228 | * |
||
229 | * @return string |
||
230 | */ |
||
231 | 2 | public static function caBundle() |
|
235 | |||
236 | /** |
||
237 | * Show Stream Extension Warning (stream_socket_enable_crypto is not supported in HHVM). |
||
238 | * |
||
239 | * @return true |
||
240 | */ |
||
241 | 2 | private function showStreamExtensionWarning() |
|
251 | } |
||
252 |