Commit | Line | Data |
---|---|---|
5d5d3b35 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
fee14197 | 4 | | CiviCRM version 5 | |
5d5d3b35 | 5 | +--------------------------------------------------------------------+ |
f299f7db | 6 | | Copyright CiviCRM LLC (c) 2004-2020 | |
5d5d3b35 TO |
7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | ||
9ae2d27b | 28 | use Civi\Cxn\Rpc\Constants; |
5063e355 | 29 | use Civi\Cxn\Rpc\DefaultCertificateValidator; |
9ae2d27b | 30 | |
5d5d3b35 TO |
31 | /** |
32 | * | |
33 | * @package CRM | |
f299f7db | 34 | * @copyright CiviCRM LLC (c) 2004-2020 |
5d5d3b35 TO |
35 | */ |
36 | ||
37 | /** | |
38 | * This class helps to manage connections to third-party apps. | |
39 | */ | |
40 | class CRM_Cxn_BAO_Cxn extends CRM_Cxn_DAO_Cxn { | |
0849804a TO |
41 | |
42 | /** | |
43 | * Determine the current site's callback URL. | |
44 | * | |
45 | * @return string | |
46 | */ | |
5d5d3b35 TO |
47 | public static function getSiteCallbackUrl() { |
48 | $config = CRM_Core_Config::singleton(); | |
3e6b8905 | 49 | |
5d5d3b35 TO |
50 | if (preg_match('/^(http|https):/', $config->resourceBase)) { |
51 | $civiUrl = $config->resourceBase; | |
52 | } | |
53 | else { | |
54 | $civiUrl = rtrim(CRM_Utils_System::baseURL(), '/') . '/' . ltrim($config->resourceBase, '/'); | |
55 | } | |
3e6b8905 TO |
56 | |
57 | // In practice, this may not be necessary, but we want to prevent | |
58 | // edge-cases that downgrade security-level below system policy. | |
aaffa79f | 59 | if (Civi::settings()->get('enableSSL')) { |
3e6b8905 TO |
60 | $civiUrl = preg_replace('/^http:/', 'https:', $civiUrl); |
61 | } | |
62 | ||
5d5d3b35 TO |
63 | return rtrim($civiUrl, '/') . '/extern/cxn.php'; |
64 | } | |
65 | ||
0849804a TO |
66 | /** |
67 | * Update the AppMeta for any existing connections. | |
68 | * | |
69 | * @param array $appMeta | |
70 | * @throws \Civi\Cxn\Rpc\Exception\CxnException | |
71 | */ | |
5d5d3b35 TO |
72 | public static function updateAppMeta($appMeta) { |
73 | \Civi\Cxn\Rpc\AppMeta::validate($appMeta); | |
be2fb01f CW |
74 | CRM_Core_DAO::executeQuery('UPDATE civicrm_cxn SET app_meta = %1 WHERE app_guid = %2', [ |
75 | 1 => [json_encode($appMeta), 'String'], | |
76 | 2 => [$appMeta['appId'], 'String'], | |
77 | ]); | |
5d5d3b35 | 78 | } |
0efb07c0 | 79 | |
0849804a TO |
80 | /** |
81 | * Get the AppMeta for an existing connection. | |
82 | * | |
83 | * @param string $cxnId | |
84 | * @return array | |
85 | * @throws \Civi\Cxn\Rpc\Exception\CxnException | |
86 | */ | |
0efb07c0 | 87 | public static function getAppMeta($cxnId) { |
39151786 | 88 | $appMetaJson = CRM_Core_DAO::getFieldValue('CRM_Cxn_DAO_Cxn', $cxnId, 'app_meta', 'cxn_guid', TRUE); |
0efb07c0 TO |
89 | $appMeta = json_decode($appMetaJson, TRUE); |
90 | \Civi\Cxn\Rpc\AppMeta::validate($appMeta); | |
91 | return $appMeta; | |
92 | } | |
93 | ||
9ae2d27b TO |
94 | /** |
95 | * Parse the CIVICRM_CXN_CA constant. It may have the following | |
96 | * values: | |
97 | * - 'CiviRootCA'|undefined -- Use the production civicrm.org root CA | |
98 | * - 'CiviTestRootCA' -- Use the test civicrm.org root CA | |
99 | * - 'none' -- Do not perform any certificate verification. | |
100 | * | |
101 | * This constant is emphatically *not* exposed through Civi's "Settings" | |
102 | * system (or any other runtime-editable datastore). Manipulating | |
103 | * this setting can expose the system to man-in-the-middle attacks, | |
104 | * and allowing runtime manipulation would create a new vector | |
105 | * for escalating privileges. This setting must only be manipulated | |
106 | * by developers and sysadmins who already have full privileges | |
107 | * to edit the source. | |
108 | * | |
109 | * @return string|NULL | |
110 | * The PEM-encoded root certificate. NULL if verification is disabled. | |
111 | * @throws CRM_Core_Exception | |
112 | */ | |
13afc1a9 | 113 | public static function getCACert() { |
9ae2d27b TO |
114 | if (!defined('CIVICRM_CXN_CA') || CIVICRM_CXN_CA === 'CiviRootCA') { |
115 | $file = Constants::getCert(); | |
116 | } | |
117 | elseif (CIVICRM_CXN_CA === 'CiviTestRootCA') { | |
118 | $file = Constants::getTestCert(); | |
119 | } | |
120 | elseif (CIVICRM_CXN_CA === 'none') { | |
121 | return NULL; | |
122 | } | |
123 | else { | |
124 | throw new \CRM_Core_Exception("CIVICRM_CXN_CA is invalid."); | |
125 | } | |
126 | ||
127 | $content = file_get_contents($file); | |
128 | if (empty($content)) { | |
129 | // Fail hard. Returning an empty value is not acceptable. | |
130 | throw new \CRM_Core_Exception("Error loading CA certificate: $file"); | |
131 | } | |
132 | return $content; | |
133 | } | |
134 | ||
0849804a TO |
135 | /** |
136 | * Construct a client for performing registration actions. | |
137 | * | |
138 | * @return \Civi\Cxn\Rpc\RegistrationClient | |
139 | * @throws CRM_Core_Exception | |
140 | */ | |
9ae2d27b TO |
141 | public static function createRegistrationClient() { |
142 | $cxnStore = new \CRM_Cxn_CiviCxnStore(); | |
a661c5b9 TO |
143 | $viaPort = defined('CIVICRM_CXN_VIA') ? CIVICRM_CXN_VIA : NULL; |
144 | $client = new \Civi\Cxn\Rpc\RegistrationClient( | |
145 | $cxnStore, \CRM_Cxn_BAO_Cxn::getSiteCallbackUrl(), $viaPort); | |
9ae2d27b | 146 | $client->setLog(new \CRM_Utils_SystemLogger()); |
fc736b89 | 147 | $client->setCertValidator(self::createCertificateValidator()); |
5063e355 | 148 | $client->setHttp(CRM_Cxn_CiviCxnHttp::singleton()); |
9ae2d27b TO |
149 | return $client; |
150 | } | |
151 | ||
48716433 TO |
152 | /** |
153 | * Construct a server for handling API requests. | |
154 | * | |
155 | * @return \Civi\Cxn\Rpc\ApiServer | |
156 | */ | |
157 | public static function createApiServer() { | |
158 | $cxnStore = new CRM_Cxn_CiviCxnStore(); | |
159 | $apiServer = new \Civi\Cxn\Rpc\ApiServer($cxnStore); | |
160 | $apiServer->setLog(new CRM_Utils_SystemLogger()); | |
fc736b89 | 161 | $apiServer->setCertValidator(self::createCertificateValidator()); |
5063e355 | 162 | $apiServer->setHttp(CRM_Cxn_CiviCxnHttp::singleton()); |
be2fb01f | 163 | $apiServer->setRouter(['CRM_Cxn_ApiRouter', 'route']); |
48716433 TO |
164 | return $apiServer; |
165 | } | |
166 | ||
fc736b89 | 167 | /** |
7b966967 | 168 | * @return \Civi\Cxn\Rpc\DefaultCertificateValidator |
fc736b89 TO |
169 | * @throws CRM_Core_Exception |
170 | */ | |
171 | public static function createCertificateValidator() { | |
172 | $caCert = self::getCACert(); | |
173 | if ($caCert === NULL) { | |
5063e355 TO |
174 | return new DefaultCertificateValidator( |
175 | NULL, | |
176 | NULL, | |
177 | NULL, | |
178 | NULL | |
179 | ); | |
fc736b89 TO |
180 | } |
181 | else { | |
5063e355 TO |
182 | return new DefaultCertificateValidator( |
183 | $caCert, | |
184 | DefaultCertificateValidator::AUTOLOAD, | |
185 | DefaultCertificateValidator::AUTOLOAD, | |
186 | CRM_Cxn_CiviCxnHttp::singleton() | |
187 | ); | |
fc736b89 TO |
188 | } |
189 | } | |
5063e355 | 190 | |
5d5d3b35 | 191 | } |