Subversion Repositories oidplus

Rev

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
}