Subversion Repositories oidplus

Rev

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