@@ -30,35 +30,151 @@ trait HTTPOptionsTrait{
30
30
protected $ curl_options = [];
31
31
32
32
/**
33
- * CA Root Certificates for use with CURL/SSL (if not configured in php.ini)
33
+ * CA Root Certificates for use with CURL/SSL (if not configured in php.ini or available in a default path )
34
34
*
35
35
* @var string
36
+ *
37
+ * @link https://curl.haxx.se/docs/caextract.html
36
38
* @link https://curl.haxx.se/ca/cacert.pem
37
39
* @link https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt
38
40
*/
39
41
protected $ ca_info = null ;
40
42
43
+ /**
44
+ * see CURLOPT_SSL_VERIFYPEER
45
+ * requires either HTTPOptions::$ca_info or a properly working system CA file
46
+ *
47
+ * @var bool
48
+ * @link http://php.net/manual/en/function.curl-setopt.php
49
+ */
50
+ protected $ ssl_verifypeer = true ;
51
+
41
52
/**
42
53
* HTTPOptionsTrait constructor
43
54
*
44
- * @throws \chillerlan\HTTP\ClientException
55
+ * @throws \Psr\Http\Client\ClientExceptionInterface
45
56
*/
46
57
protected function HTTPOptionsTrait ():void {
47
58
48
59
if (!is_array ($ this ->curl_options )){
49
60
$ this ->curl_options = [];
50
61
}
51
62
52
- // we cannot verify a peer against a non-existent ca file, so turn it off in that case
53
- /* if(!$this->ca_info || !is_file($this->ca_info)
54
- || (isset($this->curl_options[CURLOPT_CAINFO]) && !is_file($this->curl_options[CURLOPT_CAINFO]))){
63
+ if (!is_string ($ this ->user_agent ) || empty (trim ($ this ->user_agent ))){
64
+ throw new ClientException ('invalid user agent ' );
65
+ }
66
+
67
+ $ this ->setCA ();
68
+ }
69
+
70
+ /**
71
+ * @return void
72
+ * @throws \Psr\Http\Client\ClientExceptionInterface
73
+ */
74
+ protected function setCA ():void {
75
+
76
+ // disable verification if wanted so
77
+ if ($ this ->ssl_verifypeer !== true || (isset ($ this ->curl_options [CURLOPT_SSL_VERIFYPEER ]) && !$ this ->curl_options [CURLOPT_SSL_VERIFYPEER ])){
78
+ unset($ this ->curl_options [CURLOPT_CAINFO ], $ this ->curl_options [CURLOPT_CAPATH ]);
79
+
80
+ $ this ->curl_options [CURLOPT_SSL_VERIFYHOST ] = 0 ;
81
+ $ this ->curl_options [CURLOPT_SSL_VERIFYPEER ] = false ;
82
+
83
+ return ;
84
+ }
85
+
86
+ $ this ->curl_options [CURLOPT_SSL_VERIFYHOST ] = 2 ;
87
+ $ this ->curl_options [CURLOPT_SSL_VERIFYPEER ] = true ;
88
+
89
+ // a path/dir/link to a CA bundle is given, let's check that
90
+ if (is_string ($ this ->ca_info )){
91
+
92
+ // if you - for whatever obscure reason - need to check Windows .lnk links,
93
+ // see http://php.net/manual/en/function.is-link.php#91249
94
+ switch (true ){
95
+ case is_dir ($ this ->ca_info ):
96
+ case is_link ($ this ->ca_info ) && is_dir (readlink ($ this ->ca_info )): // @codeCoverageIgnore
97
+ $ this ->curl_options [CURLOPT_CAPATH ] = $ this ->ca_info ;
98
+ unset($ this ->curl_options [CURLOPT_CAINFO ]);
99
+ return ;
100
+
101
+ case is_file ($ this ->ca_info ):
102
+ case is_link ($ this ->ca_info ) && is_file (readlink ($ this ->ca_info )): // @codeCoverageIgnore
103
+ $ this ->curl_options [CURLOPT_CAINFO ] = $ this ->ca_info ;
104
+ unset($ this ->curl_options [CURLOPT_CAPATH ]);
105
+ return ;
106
+ }
107
+
108
+ throw new ClientException ('invalid path to SSL CA bundle (HTTPOptions::$ca_info): ' .$ this ->ca_info );
109
+ }
110
+
111
+ // we somehow landed here, so let's check if there's a CA bundle given via the cURL options
112
+ $ ca = $ this ->curl_options [CURLOPT_CAPATH ] ?? $ this ->curl_options [CURLOPT_CAINFO ] ?? false ;
113
+
114
+ if ($ ca ){
115
+
116
+ // just check if the file/path exists
117
+ switch (true ){
118
+ case is_dir ($ ca ):
119
+ case is_link ($ ca ) && is_dir (readlink ($ ca )): // @codeCoverageIgnore
120
+ unset($ this ->curl_options [CURLOPT_CAINFO ]);
121
+ return ;
122
+
123
+ case is_file ($ ca ):
124
+ case is_link ($ ca ) && is_file (readlink ($ ca )): // @codeCoverageIgnore
125
+ return ;
126
+ }
127
+
128
+ throw new ClientException ('invalid path to SSL CA bundle (CURLOPT_CAPATH/CURLOPT_CAINFO): ' .$ ca );
129
+ }
130
+
131
+ // check php.ini options - PHP should find the file by itself
132
+ if (file_exists (ini_get ('curl.cainfo ' ))){
133
+ return ; // @codeCoverageIgnore
134
+ }
135
+
136
+ // this is getting weird. as a last resort, we're going to check some default paths for a CA bundle file
137
+ $ cafiles = [
138
+ // check other php.ini settings
139
+ ini_get ('openssl.cafile ' ),
140
+ // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
141
+ '/etc/pki/tls/certs/ca-bundle.crt ' ,
142
+ // Ubuntu, Debian (provided by the ca-certificates package)
143
+ '/etc/ssl/certs/ca-certificates.crt ' ,
144
+ // FreeBSD (provided by the ca_root_nss package)
145
+ '/usr/local/share/certs/ca-root-nss.crt ' ,
146
+ // SLES 12 (provided by the ca-certificates package)
147
+ '/var/lib/ca-certificates/ca-bundle.pem ' ,
148
+ // OS X provided by homebrew (using the default path)
149
+ '/usr/local/etc/openssl/cert.pem ' ,
150
+ // Google app engine
151
+ '/etc/ca-certificates.crt ' ,
152
+ // Windows?
153
+ // http://php.net/manual/en/function.curl-setopt.php#110457
154
+ 'C: \\Windows \\system32 \\curl-ca-bundle.crt ' ,
155
+ 'C: \\Windows \\curl-ca-bundle.crt ' ,
156
+ 'C: \\Windows \\system32 \\cacert.pem ' ,
157
+ 'C: \\Windows \\cacert.pem ' ,
158
+ // working path
159
+ __DIR__ .'/cacert.pem ' ,
160
+ ];
161
+
162
+ foreach ($ cafiles as $ file ){
163
+ if (is_file ($ file ) || (is_link ($ file ) && is_file (readlink ($ file )))){
164
+ $ this ->curl_options [CURLOPT_CAINFO ] = $ file ;
165
+ return ;
166
+ }
167
+ }
55
168
56
- $this->curl_options += [
57
- CURLOPT_SSL_VERIFYPEER => false,
58
- CURLOPT_CAINFO => null,
59
- ];
60
- }*/
169
+ $ msg = 'No system CA bundle could be found in any of the the common system locations. '
170
+ .'In order to verify peer certificates, you will need to supply the path on disk to a certificate bundle via '
171
+ .'HTTPOptions::$ca_info or HTTPOptions::$curl_options. If you do not need a specific certificate bundle, '
172
+ .'then you can download a CA bundle over here: https://curl.haxx.se/docs/caextract.html. '
173
+ .'Once you have a CA bundle available on disk, you can set the "curl.cainfo" php.ini setting to point '
174
+ .'to the path to the file, allowing you to omit the $ca_info or $curl_options setting. '
175
+ .'See http://curl.haxx.se/docs/sslcerts.html for more information. ' ;
61
176
177
+ throw new ClientException ($ msg ); // @codeCoverageIgnore
62
178
}
63
179
64
180
}
0 commit comments