4 * Auto-detect list of certificate-authorities for use by HTTPS clients.
6 * This is designed to provide sane defaults for typical one-way
11 static private $_singleton;
14 * Provide a singleton instance to simplify integration. If you prefer
15 * to manage the lifecycle of the config object, then consider using
16 * "probe()" or "new" instead.
18 * @return CA_Config_Curl
20 static public function singleton()
22 if (! self
::$_singleton) {
24 self
::$_singleton = self
::probe($CA_CONFIG ?
$CA_CONFIG : array());
26 return self
::$_singleton;
30 * Factory fuction which produces a configuration based on a policy and based
31 * on local system resources.
33 * @param $policy array:
34 * - enable_ssl: bool; default: TRUE
35 * - verify_peer: bool; default: TRUE
36 * - cafile: string, path to aggregated PEM; overrides any system defaults
37 * - fallback_cafile: string, path to aggregated PEM; used on systems which lack default; set FALSE to disable
38 * - fallback_ttl: int, seconds, the max age of the fallback cafile before it's regarded as stale; default: 5 years
39 * @return CA_Config_Curl
41 static public function probe($policy = array())
43 if (isset($policy['enable_ssl']) && $policy['enable_ssl'] === FALSE) {
44 return new CA_Config_Curl(FALSE, FALSE, NULL);
46 $version = curl_version();
47 if (!in_array('https', $version['protocols'])) {
48 return new CA_Config_Curl(FALSE, FALSE, NULL);
50 if (isset($policy['verify_peer']) && $policy['verify_peer'] === FALSE) {
51 return new CA_Config_Curl(TRUE, FALSE, NULL);
53 if (isset($policy['cafile'])) {
54 if (file_exists($policy['cafile']) && is_readable($policy['cafile'])) {
55 return new CA_Config_Curl(TRUE, TRUE, $policy['cafile']);
57 throw new Exception("Certificate Authority file is missing. Please contact the system administrator. See also: " . $policy['cafile']);
61 if (!isset($policy['fallback_ttl'])) {
62 $policy['fallback_ttl'] = 5 * 364 * 24 * 60 * 60;
64 if (!isset($policy['fallback_cafile'])) {
65 $policy['fallback_cafile'] = dirname(__FILE__
) . '/cacert.pem';
67 // can't directly detect if system has CA pre-configured; use heuristic based on OS
68 if (strtoupper(substr(PHP_OS
, 0, 3)) === 'WIN') {
69 // PHP probably doesn't have a default cafile
70 if (empty($policy['fallback_cafile']) ||
!file_exists($policy['fallback_cafile'])) {
71 throw new Exception("Certificate Authority file is required on Windows. Please contact the system administrator.");
72 } elseif (time() > filemtime($policy['fallback_cafile']) +
$policy['fallback_ttl']) {
73 throw new Exception("Certificate Authority file is too old. Please contact the system administrator. See also: " . $policy['fallback_cafile']);
75 return new CA_Config_Curl(TRUE, TRUE, $policy['fallback_cafile']);
78 // Most PHP builds include a built-in reference to a CA list
79 return new CA_Config_Curl(TRUE, TRUE, NULL);
83 public function __construct($enableSSL, $verifyPeer, $caFile)
85 $this->enableSSL
= $enableSSL;
86 $this->verifyPeer
= $verifyPeer;
87 $this->caFile
= $caFile;
91 * Whether SSL is supported at all
95 public function isEnableSSL()
97 return $this->enableSSL
;
101 * Whether server certifiates should be verified
105 public function isVerifyPeer()
107 return $this->verifyPeer
;
111 * Path to a CA file (if available/applicable)
115 public function getCaFile()
117 return $this->caFile
;
121 * Format the CA config in a manner appropriate to curl_setopt_array()
125 public function toCurlOptions()
128 $options[CURLOPT_SSL_VERIFYPEER
] = $this->verifyPeer
;
129 $options[CURLOPT_SSL_VERIFYHOST
] = $this->verifyPeer ?
2 : 0;
131 $options[CURLOPT_CAINFO
] = $this->caFile
;
132 } // else: system default