Subversion Repositories oidplus

Rev

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