Subversion Repositories oidplus

Rev

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