Rev 1267 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
635 | daniel-mar | 1 | <?php |
2 | |||
3 | /* |
||
4 | * OIDplus 2.0 |
||
1086 | daniel-mar | 5 | * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft |
635 | daniel-mar | 6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); |
||
8 | * you may not use this file except in compliance with the License. |
||
9 | * You may obtain a copy of the License at |
||
10 | * |
||
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
||
12 | * |
||
13 | * Unless required by applicable law or agreed to in writing, software |
||
14 | * distributed under the License is distributed on an "AS IS" BASIS, |
||
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
16 | * See the License for the specific language governing permissions and |
||
17 | * limitations under the License. |
||
18 | */ |
||
19 | |||
1050 | daniel-mar | 20 | namespace ViaThinkSoft\OIDplus; |
635 | daniel-mar | 21 | |
1086 | daniel-mar | 22 | // phpcs:disable PSR1.Files.SideEffects |
23 | \defined('INSIDE_OIDPLUS') or die; |
||
24 | // phpcs:enable PSR1.Files.SideEffects |
||
25 | |||
1131 | daniel-mar | 26 | class OIDplusPageAdminRegistration extends OIDplusPagePluginAdmin |
27 | implements INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_1, /* oobeRequested, oobeEntry */ |
||
28 | INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_8 /* getNotifications */ |
||
29 | { |
||
635 | daniel-mar | 30 | |
1130 | daniel-mar | 31 | /** |
32 | * |
||
33 | */ |
||
635 | daniel-mar | 34 | /*private*/ const QUERY_REGISTER_V1 = '1.3.6.1.4.1.37476.2.5.2.1.1.1'; |
1130 | daniel-mar | 35 | |
36 | /** |
||
37 | * |
||
38 | */ |
||
635 | daniel-mar | 39 | /*private*/ const QUERY_UNREGISTER_V1 = '1.3.6.1.4.1.37476.2.5.2.1.2.1'; |
1130 | daniel-mar | 40 | |
41 | /** |
||
42 | * |
||
43 | */ |
||
635 | daniel-mar | 44 | /*private*/ const QUERY_LISTALLSYSTEMIDS_V1 = '1.3.6.1.4.1.37476.2.5.2.1.3.1'; |
1130 | daniel-mar | 45 | |
46 | /** |
||
47 | * |
||
48 | */ |
||
635 | daniel-mar | 49 | /*private*/ const QUERY_LIVESTATUS_V1 = '1.3.6.1.4.1.37476.2.5.2.1.4.1'; |
50 | |||
1116 | daniel-mar | 51 | /** |
52 | * @param string $actionID |
||
53 | * @return bool |
||
54 | */ |
||
55 | public function csrfUnlock(string $actionID): bool { |
||
635 | daniel-mar | 56 | if ($actionID == 'verify_pubkey') return true; |
57 | return parent::csrfUnlock($actionID); |
||
58 | } |
||
59 | |||
1116 | daniel-mar | 60 | /** |
1293 | daniel-mar | 61 | * This action is called by the ViaThinkSoft server in order to verify that the system is in the ownership of the correct private key |
1116 | daniel-mar | 62 | * @param array $params |
63 | * @return array |
||
64 | * @throws OIDplusException |
||
65 | */ |
||
1293 | daniel-mar | 66 | private function action_VerifyPubKey(array $params): array { |
67 | _CheckParamExists($params, 'challenge'); |
||
1181 | daniel-mar | 68 | |
1293 | daniel-mar | 69 | $payload = 'oidplus-verify-pubkey:'.sha3_512($params['challenge']); |
635 | daniel-mar | 70 | |
1293 | daniel-mar | 71 | $signature = ''; |
72 | if (!OIDplus::getPkiStatus() || !@openssl_sign($payload, $signature, OIDplus::getSystemPrivateKey())) { |
||
73 | throw new OIDplusException(_L('Signature failed')); |
||
74 | } |
||
635 | daniel-mar | 75 | |
1293 | daniel-mar | 76 | return array( |
77 | "status" => 0, |
||
78 | "response" => base64_encode($signature) |
||
79 | ); |
||
80 | } |
||
635 | daniel-mar | 81 | |
1293 | daniel-mar | 82 | /** |
83 | * @param string $actionID |
||
84 | * @param array $params |
||
85 | * @return array |
||
86 | * @throws OIDplusException |
||
87 | */ |
||
88 | public function action(string $actionID, array $params): array { |
||
89 | if ($actionID == 'verify_pubkey') { |
||
90 | return $this->action_VerifyPubKey($params); |
||
635 | daniel-mar | 91 | } else { |
1116 | daniel-mar | 92 | return parent::action($actionID, $params); |
635 | daniel-mar | 93 | } |
94 | } |
||
95 | |||
1116 | daniel-mar | 96 | /** |
97 | * @param string $id |
||
98 | * @param array $out |
||
99 | * @param bool $handled |
||
100 | * @return void |
||
101 | * @throws OIDplusConfigInitializationException |
||
102 | * @throws OIDplusException |
||
103 | */ |
||
104 | public function gui(string $id, array &$out, bool &$handled) { |
||
635 | daniel-mar | 105 | if ($id === 'oidplus:srv_registration') { |
106 | $handled = true; |
||
107 | $out['title'] = _L('System registration settings'); |
||
801 | daniel-mar | 108 | $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : ''; |
635 | daniel-mar | 109 | |
110 | if (!OIDplus::authUtils()->isAdminLoggedIn()) { |
||
1266 | daniel-mar | 111 | throw new OIDplusHtmlException(_L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')), $out['title'], 401); |
635 | daniel-mar | 112 | } |
113 | |||
114 | if (file_exists(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html')) { |
||
115 | $info = file_get_contents(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html'); |
||
116 | } else { |
||
117 | $info = file_get_contents(__DIR__ . '/info.html'); |
||
118 | } |
||
119 | |||
120 | list($html, $js, $css) = extractHtmlContents($info); |
||
121 | $info = ''; |
||
122 | if (!empty($js)) $info .= "<script>\n$js\n</script>"; |
||
123 | if (!empty($css)) $info .= "<style>\n$css\n</style>"; |
||
821 | daniel-mar | 124 | $info .= stripHtmlComments($html); |
635 | daniel-mar | 125 | |
126 | $out['text'] = $info; |
||
127 | |||
128 | if (!OIDplus::getPkiStatus()) { |
||
129 | $out['text'] .= '<p><font color="red">'._L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.').'</font></p>'; |
||
1181 | daniel-mar | 130 | } else if (!url_post_contents_available(true, $reason)) { |
131 | $out['text'] .= '<p><font color="red">'; |
||
132 | $out['text'] .= _L('OIDplus cannot connect to the Internet (%1). Therefore, you <b>cannot</b> register your OIDplus instance now.', $reason); |
||
133 | $out['text'] .= '</font></p>'; |
||
635 | daniel-mar | 134 | } else { |
135 | $out['text'] .= '<p><input type="button" onclick="openOidInPanel(\'oidplus:srvreg_status\');" value="'._L('Check status of the registration and collected data').'"></p>'; |
||
136 | |||
137 | if (OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) { |
||
138 | $out['text'] .= '<p><font color="red"><b>'._L('Attention!').'</b> '._L('<code>REGISTRATION_HIDE_SYSTEM</code> is set in the local configuration file! Therefore, this system will not register itself, despite of the settings below.').'</font></p>'; |
||
139 | } |
||
140 | |||
141 | $out['text'] .= '<p>'._L('You can adjust your privacy level here').':</p><p><select name="reg_privacy" id="reg_privacy">'; |
||
142 | |||
143 | # --- |
||
144 | |||
145 | $out['text'] .= '<option value="0"'; |
||
146 | if (OIDplus::config()->getValue('reg_privacy') == 0) { |
||
147 | $out['text'] .= ' selected'; |
||
148 | } else { |
||
149 | $out['text'] .= ''; |
||
150 | } |
||
151 | $out['text'] .= '>'._L('0 = Register to directory service and automatically publish RA/OID data at oid-info.com').'</option>'; |
||
152 | |||
153 | # --- |
||
154 | |||
155 | $out['text'] .= '<option value="1"'; |
||
156 | if (OIDplus::config()->getValue('reg_privacy') == 1) { |
||
157 | $out['text'] .= ' selected'; |
||
158 | } else { |
||
159 | $out['text'] .= ''; |
||
160 | } |
||
161 | $out['text'] .= '>'._L('1 = Only register to directory service').'</option>'; |
||
162 | |||
163 | # --- |
||
164 | |||
165 | $out['text'] .= '<option value="2"'; |
||
166 | if (OIDplus::config()->getValue('reg_privacy') == 2) { |
||
167 | $out['text'] .= ' selected'; |
||
168 | } else { |
||
169 | $out['text'] .= ''; |
||
170 | } |
||
171 | $out['text'] .= '>'._L('2 = Hide system').'</option>'; |
||
172 | |||
173 | # --- |
||
174 | |||
175 | $out['text'] .= '</select> <input type="button" value="'._L('Change').'" onclick="OIDplusPageAdminRegistration.crudActionRegPrivacyUpdate()"></p>'; |
||
176 | |||
177 | $out['text'] .= '<p>'._L('After clicking "change", your OIDplus system will contact the ViaThinkSoft server to adjust (add or remove information) your privacy setting. This may take a few minutes.').'</p>'; |
||
178 | |||
179 | $out['text'] .= '<p>'._L('<i>Privacy information:</i> Please note that removing your system from the directory does not automatically delete information about OIDs which are already published at oid-info.com. To remove already submitted OIDs at oid-info.com, please contact the <a href="mailto:admin@oid-info.com">OID Repository Webmaster</a>.').'</p>'; |
||
180 | } |
||
181 | } |
||
182 | if ($id === 'oidplus:srvreg_status') { |
||
183 | $handled = true; |
||
184 | $out['title'] = _L('Registration live status'); |
||
801 | daniel-mar | 185 | $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : ''; |
635 | daniel-mar | 186 | |
187 | if (!OIDplus::authUtils()->isAdminLoggedIn()) { |
||
1266 | daniel-mar | 188 | throw new OIDplusHtmlException(_L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')), $out['title'], 401); |
635 | daniel-mar | 189 | } |
190 | |||
191 | $query = self::QUERY_LIVESTATUS_V1; |
||
192 | |||
193 | $payload = array( |
||
777 | daniel-mar | 194 | "query" => $query, // we must include $query to the playload, because we want to sign it |
635 | daniel-mar | 195 | "lang" => OIDplus::getCurrentLang(), |
196 | "system_id" => OIDplus::getSystemId(false) |
||
197 | ); |
||
198 | |||
199 | $signature = ''; |
||
830 | daniel-mar | 200 | if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) { |
635 | daniel-mar | 201 | throw new OIDplusException(_L('Signature failed')); |
202 | } |
||
203 | |||
204 | $data = array( |
||
205 | "payload" => $payload, |
||
206 | "signature" => base64_encode($signature) |
||
207 | ); |
||
208 | |||
209 | if (function_exists('gzdeflate')) { |
||
210 | $compressed = "1"; |
||
211 | $data2 = gzdeflate(json_encode($data)); |
||
212 | } else { |
||
213 | $compressed = "0"; |
||
214 | $data2 = json_encode($data); |
||
215 | } |
||
1149 | daniel-mar | 216 | |
217 | $res = url_post_contents( |
||
218 | 'https://oidplus.viathinksoft.com/reg2/query.php', |
||
219 | array( |
||
220 | "query" => $query, |
||
221 | "compressed" => $compressed, |
||
222 | "data" => base64_encode($data2) |
||
223 | ) |
||
224 | ); |
||
225 | |||
226 | if ($res === false) { |
||
227 | throw new OIDplusException(_L('Communication with %1 server failed', 'ViaThinkSoft')); |
||
635 | daniel-mar | 228 | } |
229 | |||
230 | $json = @json_decode($res, true); |
||
231 | |||
232 | if (!$json) { |
||
1206 | daniel-mar | 233 | throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res), $out['title']); |
635 | daniel-mar | 234 | } |
235 | |||
236 | if (isset($json['error']) || ($json['status'] < 0)) { |
||
237 | if (isset($json['error'])) { |
||
1206 | daniel-mar | 238 | throw new OIDplusException(_L('Received error status code: %1',$json['error']), $out['title']); |
635 | daniel-mar | 239 | } else { |
1206 | daniel-mar | 240 | throw new OIDplusException(_L('Received error status code: %1',$json['status']), $out['title']); |
635 | daniel-mar | 241 | } |
242 | } |
||
243 | |||
244 | $out['text'] = '<p><a '.OIDplus::gui()->link('oidplus:srv_registration').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Go back to registration settings').'</a></p>' . |
||
245 | $json['content']; |
||
246 | } |
||
247 | } |
||
248 | |||
1116 | daniel-mar | 249 | /** |
250 | * @return bool |
||
251 | * @throws OIDplusException |
||
252 | */ |
||
253 | protected function areWeRegistered(): bool { |
||
635 | daniel-mar | 254 | // To check if we are registered. Check it "anonymously" (i.e. without revealing our system ID) |
715 | daniel-mar | 255 | $res = url_get_contents('https://oidplus.viathinksoft.com/reg2/query.php?query='.self::QUERY_LISTALLSYSTEMIDS_V1); |
1149 | daniel-mar | 256 | if ($res === false) return false; |
635 | daniel-mar | 257 | |
258 | $json = @json_decode($res, true); |
||
259 | |||
260 | if (!$json) { |
||
261 | return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res)); |
||
262 | } |
||
263 | |||
264 | if (isset($json['error']) || ($json['status'] < 0)) { |
||
265 | if (isset($json['error'])) { |
||
266 | return false; // throw new OIDplusException(_L('Received error status code: %1',$json['error'])); |
||
267 | } else { |
||
268 | return false; // throw new OIDplusException(_L('Received error status code: %1',$json['status'])); |
||
269 | } |
||
270 | } |
||
271 | |||
272 | $list = $json['list']; |
||
273 | |||
274 | return in_array(OIDplus::getSystemId(false), $list); |
||
275 | } |
||
276 | |||
1116 | daniel-mar | 277 | /** |
1130 | daniel-mar | 278 | * @param int|null $privacy_level |
1116 | daniel-mar | 279 | * @return false|void |
1130 | daniel-mar | 280 | * @throws OIDplusException|\OIDInfoException |
1116 | daniel-mar | 281 | */ |
1130 | daniel-mar | 282 | public function sendRegistrationQuery(int $privacy_level=null) { |
1029 | daniel-mar | 283 | |
635 | daniel-mar | 284 | if (is_null($privacy_level)) { |
285 | $privacy_level = OIDplus::config()->getValue('reg_privacy'); |
||
286 | } |
||
287 | |||
801 | daniel-mar | 288 | $system_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL); |
635 | daniel-mar | 289 | |
290 | // It is very important that we set the ping time NOW, because ViaThinkSoft might contact us during the ping, |
||
291 | // and this would cause an endless loop! |
||
292 | OIDplus::config()->setValue('reg_last_ping', time()); |
||
293 | |||
294 | if (!OIDplus::getPkiStatus()) return false; |
||
295 | |||
1181 | daniel-mar | 296 | if (!url_post_contents_available(true)) return false; |
297 | |||
635 | daniel-mar | 298 | if ($privacy_level == 2) { |
299 | // The user wants to unregister, but we only unregister if we are registered |
||
300 | if ($this->areWeRegistered()) { |
||
301 | $query = self::QUERY_UNREGISTER_V1; |
||
302 | |||
303 | $payload = array( |
||
777 | daniel-mar | 304 | "query" => $query, // we must include $query to the payload, because we want to sign it |
635 | daniel-mar | 305 | "system_id" => OIDplus::getSystemId(false) |
306 | ); |
||
307 | |||
308 | $signature = ''; |
||
830 | daniel-mar | 309 | if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) { |
635 | daniel-mar | 310 | return false; // throw new OIDplusException(_L('Signature failed')); |
311 | } |
||
312 | |||
313 | $data = array( |
||
314 | "payload" => $payload, |
||
315 | "signature" => base64_encode($signature) |
||
316 | ); |
||
317 | |||
318 | if (function_exists('gzdeflate')) { |
||
319 | $compressed = "1"; |
||
320 | $data2 = gzdeflate(json_encode($data)); |
||
321 | } else { |
||
322 | $compressed = "0"; |
||
323 | $data2 = json_encode($data); |
||
324 | } |
||
325 | |||
1149 | daniel-mar | 326 | $res = url_post_contents( |
327 | 'https://oidplus.viathinksoft.com/reg2/query.php', |
||
328 | array( |
||
1181 | daniel-mar | 329 | "query" => $query, |
1149 | daniel-mar | 330 | "compressed" => $compressed, |
1181 | daniel-mar | 331 | "data" => base64_encode($data2) |
1149 | daniel-mar | 332 | ) |
333 | ); |
||
334 | |||
335 | if ($res === false) return false; // throw new OIDplusException(_L('Communication with %1 server failed', 'ViaThinkSoft')); |
||
336 | |||
635 | daniel-mar | 337 | $json = @json_decode($res, true); |
338 | |||
339 | if (!$json) { |
||
340 | return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res)); |
||
341 | } |
||
342 | |||
343 | if (isset($json['error']) || ($json['status'] < 0)) { |
||
1116 | daniel-mar | 344 | return false; // throw new OIDplusException(_L('Received error status code: %1',isset($json['error']) ? $json['error'] : $json['status'])); |
635 | daniel-mar | 345 | } |
346 | } |
||
347 | } else { |
||
348 | if ($privacy_level == 0) { |
||
349 | $adminExportPlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.3.400'); // OIDplusPageAdminOIDInfoExport |
||
350 | if (!is_null($adminExportPlugin)) { |
||
941 | daniel-mar | 351 | list($oidinfo_xml, $dummy_content_type) = OIDplusPageAdminOIDInfoExport::outputXML(false); // no online check, because the query should be short (since the query is done while a visitor waits for the response) |
635 | daniel-mar | 352 | } else { |
353 | $oidinfo_xml = false; |
||
354 | } |
||
355 | } else { |
||
356 | $oidinfo_xml = false; |
||
357 | } |
||
358 | |||
359 | $query = self::QUERY_REGISTER_V1; |
||
360 | |||
361 | $root_oids = array(); |
||
362 | foreach (OIDplus::getEnabledObjectTypes() as $ot) { |
||
363 | if ($ot::ns() == 'oid') { |
||
364 | $res = OIDplus::db()->query("select id from ###objects where " . |
||
365 | "(parent = 'oid:' or " . |
||
366 | // The following two cases are special cases e.g. if there are multiple PEN or UUID-OIDs, and the system owner decides to use the IANA PEN as root OID, but actually, it is not "his" root then! The OIDs inside the IANA PEN root are his root then! |
||
367 | "parent in (select oid from ###asn1id where well_known = ?) or " . |
||
368 | "parent in (select oid from ###iri where well_known = ?)) and " . |
||
369 | // We assume hereby that RAs of well-known OIDs (e.g. IANA) will not use OIDplus for allocating OIDs: |
||
370 | "id not in (select oid from ###asn1id where well_known = ?) and " . |
||
1148 | daniel-mar | 371 | "id not in (select oid from ###iri where well_known = ?)", array(true, true, true, true)); |
1156 | daniel-mar | 372 | $res->naturalSortByField('id'); |
635 | daniel-mar | 373 | while ($row = $res->fetch_array()) { |
374 | $root_oids[] = substr($row['id'],strlen('oid:')); |
||
375 | } |
||
376 | } |
||
377 | } |
||
378 | $payload = array( |
||
777 | daniel-mar | 379 | "query" => $query, // we must include $query to the payload, because we want to sign it |
635 | daniel-mar | 380 | "privacy_level" => $privacy_level, |
381 | "system_id" => OIDplus::getSystemId(false), |
||
830 | daniel-mar | 382 | "public_key" => OIDplus::getSystemPublicKey(), |
635 | daniel-mar | 383 | "system_url" => $system_url, |
384 | "hide_system_url" => 0, |
||
385 | "hide_public_key" => 0, |
||
386 | "admin_email" => OIDplus::config()->getValue('admin_email'), |
||
387 | "system_title" => OIDplus::config()->getValue('system_title'), |
||
388 | "oidinfo_xml" => @base64_encode($oidinfo_xml), |
||
389 | "root_oids" => $root_oids, |
||
390 | "system_version" => OIDplus::getVersion(), |
||
391 | "system_install_type" => OIDplus::getInstallType() |
||
392 | ); |
||
393 | |||
394 | $signature = ''; |
||
830 | daniel-mar | 395 | if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::getSystemPrivateKey())) { |
635 | daniel-mar | 396 | return false; // throw new OIDplusException(_L('Signature failed')); |
397 | } |
||
398 | |||
399 | $data = array( |
||
400 | "payload" => $payload, |
||
401 | "signature" => base64_encode($signature) |
||
402 | ); |
||
403 | |||
404 | if (function_exists('gzdeflate')) { |
||
405 | $compressed = "1"; |
||
406 | $data2 = gzdeflate(json_encode($data)); |
||
407 | } else { |
||
408 | $compressed = "0"; |
||
409 | $data2 = json_encode($data); |
||
410 | } |
||
411 | |||
1149 | daniel-mar | 412 | $res = url_post_contents( |
413 | 'https://oidplus.viathinksoft.com/reg2/query.php', |
||
414 | array( |
||
415 | "query" => $query, |
||
416 | "compressed" => $compressed, |
||
417 | "data" => base64_encode($data2) |
||
418 | ) |
||
419 | ); |
||
420 | |||
421 | if ($res === false) return false; // throw new OIDplusException(_L('Communication with %1 server failed', 'ViaThinkSoft')); |
||
422 | |||
635 | daniel-mar | 423 | $json = @json_decode($res, true); |
424 | |||
425 | if (!$json) { |
||
426 | return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res)); |
||
427 | } |
||
428 | |||
429 | if (isset($json['error']) || ($json['status'] < 0)) { |
||
430 | if (isset($json['error'])) { |
||
431 | return false; // throw new OIDplusException(_L('Received error status code: %1',$json['error'])); |
||
432 | } else { |
||
433 | return false; // throw new OIDplusException(_L('Received error status code: %1',$json['status'])); |
||
434 | } |
||
435 | } else if ($json['status'] == 99/*Hash conflict*/) { |
||
1267 | daniel-mar | 436 | OIDplus::logger()->log("V2:[WARN]A", "Removing SystemID and key pair because there is a hash conflict with another OIDplus system!"); |
635 | daniel-mar | 437 | |
438 | // Delete the system ID since we have a conflict with the 31-bit hash! |
||
439 | OIDplus::config()->setValue('oidplus_private_key', ''); |
||
440 | OIDplus::config()->setValue('oidplus_public_key', ''); |
||
441 | |||
442 | // Try to generate a new system ID |
||
443 | OIDplus::getPkiStatus(true); |
||
444 | |||
445 | // Enforce a new registration attempt at the next page visit |
||
446 | // We will not try again here, because that might lead to an endless loop if the VTS server would always return 'HASH_CONFLCIT' |
||
447 | OIDplus::config()->setValue('reg_last_ping', 0); |
||
776 | daniel-mar | 448 | } else if ($json['status'] == 0/*OK*/) { |
449 | // Note: whois.viathinksoft.de:43 uses VGWhoIs, which uses these patterns: https://github.com/danielmarschall/vgwhois/blob/master/main/pattern/oid |
||
450 | // If your system gets acknowledged by ViaThinkSoft, then vts_whois will be filled with that server name whois.viathinksoft.de:43 |
||
451 | if (isset($json['vts_whois'])) OIDplus::config()->setValue('vts_whois', $json['vts_whois']); |
||
452 | |||
453 | // ViaThinkSoft certifies the system public key and other system attributes and root objects (requires human verification) |
||
454 | if (isset($json['vts_cert'])) OIDplus::config()->setValue('vts_cert', $json['vts_cert']); |
||
455 | if (isset($json['vts_ca'])) OIDplus::config()->setValue('vts_ca', $json['vts_ca']); |
||
635 | daniel-mar | 456 | } |
457 | } |
||
458 | } |
||
459 | |||
1116 | daniel-mar | 460 | /** |
461 | * @param bool $html |
||
462 | * @return void |
||
463 | * @throws OIDplusException |
||
464 | */ |
||
465 | public function init(bool $html=true) { |
||
699 | daniel-mar | 466 | if (OIDplus::getEditionInfo()['vendor'] != 'ViaThinkSoft') { |
467 | throw new OIDplusException(_L('This plugin is only available in the ViaThinkSoft edition of OIDplus')); |
||
468 | } |
||
469 | |||
635 | daniel-mar | 470 | // Note: It is important that the default value is '2', otherwise, systems which don't have CURL will fail |
471 | OIDplus::config()->prepareConfigKey('reg_privacy', '2=Hide your system, 1=Register your system to the ViaThinkSoft directory and oid-info.com, 0=Publish your system to ViaThinkSoft directory and all public contents (RA/OID) to oid-info.com', '2', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
||
472 | if (($value != '0') && ($value != '1') && ($value != '2')) { |
||
473 | throw new OIDplusException(_L('Please enter either 0, 1 or 2.')); |
||
474 | } |
||
475 | // Now do a recheck and notify the ViaThinkSoft server |
||
476 | if (($value == 2) || !OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) { |
||
477 | OIDplus::config()->setValue('reg_last_ping', 0); |
||
1181 | daniel-mar | 478 | if (!url_post_contents_available(true, $reason)) throw new OIDplusException(_L('The system cannot contact the ViaThinkSoft server to change the registration settings.').' '.$reason); |
635 | daniel-mar | 479 | $this->sendRegistrationQuery($value); |
480 | } |
||
481 | }); |
||
482 | OIDplus::config()->prepareConfigKey('reg_ping_interval', 'Registration ping interval (in seconds)', '3600', OIDplusConfig::PROTECTION_HIDDEN, function($value) { |
||
483 | |||
484 | }); |
||
485 | OIDplus::config()->prepareConfigKey('reg_last_ping', 'Last ping to ViaThinkSoft directory services', '0', OIDplusConfig::PROTECTION_HIDDEN, function($value) { |
||
486 | |||
487 | }); |
||
776 | daniel-mar | 488 | OIDplus::config()->prepareConfigKey('vts_whois', 'ViaThinkSoft Whois Server (if this system is recognized)', '', OIDplusConfig::PROTECTION_READONLY, function($value) { |
489 | |||
490 | }); |
||
491 | OIDplus::config()->prepareConfigKey('vts_cert', 'ViaThinkSoft certificate (requires registration)', '', OIDplusConfig::PROTECTION_HIDDEN, function($value) { |
||
492 | |||
493 | }); |
||
494 | OIDplus::config()->prepareConfigKey('vts_ca', 'ViaThinkSoft certificate root (requires registration)', '', OIDplusConfig::PROTECTION_HIDDEN, function($value) { |
||
495 | |||
496 | }); |
||
635 | daniel-mar | 497 | OIDplus::config()->prepareConfigKey('oobe_registration_done', '"Out Of Box Experience" wizard for OIDplusPageAdminRegistration done once?', '0', OIDplusConfig::PROTECTION_HIDDEN, function($value) {}); |
498 | |||
499 | // Is it time to register / renew the directory entry? |
||
500 | // Note: REGISTRATION_HIDE_SYSTEM is an undocumented constant that can be put in the userdata/baseconfig/config.inc.php files of a test system accessing the same database as the productive system that is registered. |
||
501 | // This avoids that the URL of a productive system is overridden with the URL of a cloned test system (since they use the same database, they also have the same system ID) |
||
502 | |||
503 | if (OIDplus::config()->getValue('oobe_registration_done') == '1') { |
||
504 | if (!OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) { |
||
505 | $privacy_level = OIDplus::config()->getValue('reg_privacy'); |
||
506 | |||
507 | if (PHP_SAPI !== 'cli') { // don't register when called from CLI, otherwise the oidinfo XML can't convert relative links into absolute links |
||
786 | daniel-mar | 508 | $last_ping = OIDplus::config()->getValue('reg_last_ping'); |
509 | if (!is_numeric($last_ping)) $last_ping = 0; |
||
510 | $last_ping_interval = OIDplus::config()->getValue('reg_ping_interval'); |
||
511 | if (!is_numeric($last_ping_interval)) $last_ping_interval = 3600; |
||
852 | daniel-mar | 512 | |
513 | // Cronjobs get half ping interval, to make sure that a web visitor won't get any delay |
||
514 | if (OIDplus::isCronjob()) $last_ping_interval /= 2; |
||
515 | |||
786 | daniel-mar | 516 | if ((time()-$last_ping >= $last_ping_interval)) { |
1185 | daniel-mar | 517 | try { |
518 | $this->sendRegistrationQuery(); |
||
519 | } catch (\Exception $e) { |
||
520 | // Don't do anything, because we don't want that a failed registration query blocks the system |
||
1267 | daniel-mar | 521 | OIDplus::logger()->log('V2:[WARN]A', 'System registration query crashed: %1', $e->getMessage()); |
1185 | daniel-mar | 522 | } |
635 | daniel-mar | 523 | } |
524 | } |
||
525 | } |
||
526 | } |
||
527 | } |
||
528 | |||
1116 | daniel-mar | 529 | /** |
530 | * @param array $json |
||
531 | * @param string|null $ra_email |
||
532 | * @param bool $nonjs |
||
533 | * @param string $req_goto |
||
534 | * @return bool |
||
535 | * @throws OIDplusException |
||
536 | */ |
||
537 | public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool { |
||
635 | daniel-mar | 538 | if (!OIDplus::authUtils()->isAdminLoggedIn()) return false; |
539 | |||
800 | daniel-mar | 540 | if (file_exists(__DIR__.'/img/main_icon16.png')) { |
801 | daniel-mar | 541 | $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png'; |
635 | daniel-mar | 542 | } else { |
543 | $tree_icon = null; // default icon (folder) |
||
544 | } |
||
545 | |||
546 | $json[] = array( |
||
547 | 'id' => 'oidplus:srv_registration', |
||
548 | 'icon' => $tree_icon, |
||
549 | 'text' => _L('System registration') |
||
550 | ); |
||
551 | |||
552 | return true; |
||
553 | } |
||
554 | |||
1116 | daniel-mar | 555 | /** |
556 | * @param string $request |
||
557 | * @return array|false |
||
558 | */ |
||
559 | public function tree_search(string $request) { |
||
635 | daniel-mar | 560 | return false; |
561 | } |
||
562 | |||
1116 | daniel-mar | 563 | /** |
1131 | daniel-mar | 564 | * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_1 |
1116 | daniel-mar | 565 | * @return bool |
566 | * @throws OIDplusException |
||
567 | */ |
||
635 | daniel-mar | 568 | public function oobeRequested(): bool { |
569 | return OIDplus::config()->getValue('oobe_registration_done') == '0'; |
||
570 | } |
||
571 | |||
1116 | daniel-mar | 572 | /** |
1131 | daniel-mar | 573 | * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_1 |
1125 | daniel-mar | 574 | * @param int $step |
575 | * @param bool $do_edits |
||
576 | * @param bool $errors_happened |
||
1116 | daniel-mar | 577 | * @return void |
578 | * @throws OIDplusConfigInitializationException |
||
579 | * @throws OIDplusException |
||
580 | */ |
||
1125 | daniel-mar | 581 | public function oobeEntry(int $step, bool $do_edits, bool &$errors_happened)/*: void*/ { |
1055 | daniel-mar | 582 | echo '<h2>'._L('Step %1: System registration and automatic publishing (optional)',$step).'</h2>'; |
635 | daniel-mar | 583 | |
584 | if (file_exists(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html')) { |
||
585 | $info = file_get_contents(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html'); |
||
586 | } else { |
||
587 | $info = file_get_contents(__DIR__ . '/info.html'); |
||
588 | } |
||
589 | |||
590 | // make sure the program works even if the user provided HTML is not UTF-8 |
||
721 | daniel-mar | 591 | $info = convert_to_utf8_no_bom($info); |
635 | daniel-mar | 592 | |
593 | echo $info; |
||
594 | |||
1181 | daniel-mar | 595 | if (!url_post_contents_available(true, $reason)) { |
635 | daniel-mar | 596 | echo '<p><font color="red">'; |
1181 | daniel-mar | 597 | echo _L('OIDplus cannot connect to the Internet (%1). Therefore, you <b>cannot</b> register your OIDplus instance now.', $reason); |
635 | daniel-mar | 598 | echo '</font></p>'; |
599 | if ($do_edits) { |
||
600 | OIDplus::config()->setValue('oobe_registration_done', '1'); |
||
601 | } |
||
602 | return; |
||
603 | } |
||
604 | |||
605 | $pki_status = OIDplus::getPkiStatus(); |
||
606 | |||
607 | if (!$pki_status) { |
||
608 | echo '<p><font color="red">'; |
||
609 | echo _L('Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system).').' '; |
||
610 | echo _L('Therefore, you <b>cannot</b> register your OIDplus instance now.'); |
||
611 | echo '</font></p>'; |
||
612 | if ($do_edits) { |
||
613 | OIDplus::config()->setValue('oobe_registration_done', '1'); |
||
614 | } |
||
615 | return; |
||
616 | } |
||
617 | |||
618 | echo '<p>'._L('Privacy level').':</p><select name="reg_privacy" id="reg_privacy">'; |
||
619 | |||
620 | # --- |
||
621 | |||
622 | echo '<option value="0"'; |
||
1033 | daniel-mar | 623 | if (isset($_POST['sent'])) { |
624 | if (isset($_POST['reg_privacy']) && ($_POST['reg_privacy'] == 0)) echo ' selected'; |
||
635 | daniel-mar | 625 | } else { |
626 | if ((OIDplus::config()->getValue('reg_privacy') == 0) || !OIDplus::config()->getValue('oobe_registration_done')) { |
||
627 | echo ' selected'; |
||
628 | } else { |
||
629 | echo ''; |
||
630 | } |
||
631 | } |
||
632 | echo '>'._L('0 = Register to directory service and automatically publish RA/OID data at oid-info.com').'</option>'; |
||
633 | |||
634 | # --- |
||
635 | |||
636 | echo '<option value="1"'; |
||
1033 | daniel-mar | 637 | if (isset($_POST['sent'])) { |
638 | if (isset($_POST['reg_privacy']) && ($_POST['reg_privacy'] == 1)) echo ' selected'; |
||
635 | daniel-mar | 639 | } else { |
640 | if ((OIDplus::config()->getValue('reg_privacy') == 1)) { |
||
641 | echo ' selected'; |
||
642 | } else { |
||
643 | echo ''; |
||
644 | } |
||
645 | } |
||
646 | echo '>'._L('1 = Only register to directory service').'</option>'; |
||
647 | |||
648 | # --- |
||
649 | |||
650 | echo '<option value="2"'; |
||
1033 | daniel-mar | 651 | if (isset($_POST['sent'])) { |
652 | if (isset($_POST['reg_privacy']) && ($_POST['reg_privacy'] == 2)) echo ' selected'; |
||
635 | daniel-mar | 653 | } else { |
654 | if ((OIDplus::config()->getValue('reg_privacy') == 2)) { |
||
655 | echo ' selected'; |
||
656 | } else { |
||
657 | echo ''; |
||
658 | } |
||
659 | } |
||
660 | echo '>'._L('2 = Hide system').'</option>'; |
||
661 | |||
662 | # --- |
||
663 | |||
664 | echo '</select>'; |
||
665 | |||
1201 | daniel-mar | 666 | $htmlmsg = ''; |
635 | daniel-mar | 667 | if ($do_edits) { |
668 | try { |
||
1130 | daniel-mar | 669 | OIDplus::config()->setValue('reg_privacy', $_POST['reg_privacy'] ?? 1); |
635 | daniel-mar | 670 | OIDplus::config()->setValue('oobe_registration_done', '1'); |
1050 | daniel-mar | 671 | } catch (\Exception $e) { |
1201 | daniel-mar | 672 | $htmlmsg = $e instanceof OIDplusException ? $e->getHtmlMessage() : htmlentities($e->getMessage()); |
635 | daniel-mar | 673 | $errors_happened = true; |
674 | } |
||
675 | } |
||
1201 | daniel-mar | 676 | if (!empty($htmlmsg)) echo ' <font color="red"><b>'.$htmlmsg.'</b></font>'; |
635 | daniel-mar | 677 | |
678 | echo '<p>'._L('<i>Privacy information:</i> This setting can always be changed in the administrator login / control panel.').'<br>'; |
||
679 | echo _L('<a %1>Click here</a> for more information about privacy related topics.','href="../../../../res/OIDplus/privacy_documentation.html" target="_blank"'); |
||
680 | echo '</p>'; |
||
681 | } |
||
682 | |||
1116 | daniel-mar | 683 | /** |
1131 | daniel-mar | 684 | * Implements interface INTF_OID_1_3_6_1_4_1_37476_2_5_2_3_8 |
1125 | daniel-mar | 685 | * @param string|null $user |
1116 | daniel-mar | 686 | * @return array |
687 | * @throws OIDplusException |
||
688 | */ |
||
1125 | daniel-mar | 689 | public function getNotifications(string $user=null): array { |
1000 | daniel-mar | 690 | $notifications = array(); |
691 | if ((!$user || ($user == 'admin')) && OIDplus::authUtils()->isAdminLoggedIn()) { |
||
1181 | daniel-mar | 692 | if (!url_post_contents_available(true, $reason)) { |
1000 | daniel-mar | 693 | $title = _L('System registration'); |
1189 | daniel-mar | 694 | $notifications[] = new OIDplusNotification('ERR', _L('OIDplus plugin "%1" is enabled, but OIDplus cannot connect to the Internet.', '<a '.OIDplus::gui()->link('oidplus:srv_registration').'>'.htmlentities($title).'</a>').' '.$reason); |
1000 | daniel-mar | 695 | } |
696 | } |
||
697 | return $notifications; |
||
698 | } |
||
699 | |||
635 | daniel-mar | 700 | } |