Subversion Repositories oidplus

Rev

Rev 1207 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 daniel-mar 1
/*
2
 * OIDplus 2.0
511 daniel-mar 3
 * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
5 daniel-mar 4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
 
362 daniel-mar 18
// DEFAULT_LANGUAGE will be set by setup.js.php
19
// language_messages will be set by setup.js.php
20
// language_tblprefix will be set by setup.js.php
21
 
695 daniel-mar 22
// TODO: Put these settings in a "setup configuration file" (hardcoded)
635 daniel-mar 23
min_password_length = 10; // see also plugins/viathinksoft/publicPages/092_forgot_password_admin/script.js
421 daniel-mar 24
password_salt_length = 10;
695 daniel-mar 25
bcrypt_rounds = 10;
80 daniel-mar 26
 
421 daniel-mar 27
function adminGeneratePassword(password) {
28
        var salt = generateRandomString(password_salt_length);
29
        return salt+'$'+hexToBase64(sha3_512(salt+password));
30
}
31
 
456 daniel-mar 32
var bCryptWorker = null;
33
var g_prevBcryptPw = null;
34
var g_last_admPwdHash = null;
35
var g_last_pwComment = null;
36
 
2 daniel-mar 37
function rebuild() {
561 daniel-mar 38
        var pw = $("#admin_password")[0].value;
456 daniel-mar 39
 
40
        if (pw != g_prevBcryptPw) {
41
                // sync call to calculate SHA3
42
                var admPwdHash = adminGeneratePassword(pw);
43
                var pwComment = 'salted, base64 encoded SHA3-512 hash';
44
                doRebuild(admPwdHash, pwComment);
45
 
46
                // "async" call to calculate bcrypt (via web-worker)
47
                if (bCryptWorker != null) {
48
                        g_prevBcryptPw = null;
49
                        bCryptWorker.terminate();
50
                }
599 daniel-mar 51
                bCryptWorker = new Worker('../bcrypt_worker.js');
695 daniel-mar 52
                bCryptWorker.postMessage([pw, bcrypt_rounds]);
456 daniel-mar 53
                bCryptWorker.onmessage = function (event) {
54
                        var admPwdHash = event.data;
55
                        var pwComment = 'bcrypt encoded hash';
56
                        doRebuild(admPwdHash, pwComment);
57
                        g_prevBcryptPw = pw;
58
                };
59
        } else {
60
                doRebuild(g_last_admPwdHash, g_last_pwComment);
61
        }
62
}
63
 
64
function doRebuild(admPwdHash, pwComment) {
65
        g_last_admPwdHash = admPwdHash;
66
        g_last_pwComment = pwComment;
67
 
2 daniel-mar 68
        var error = false;
69
 
561 daniel-mar 70
        if ($("#config")[0] == null) return;
150 daniel-mar 71
 
81 daniel-mar 72
        // Check 1: Has the password the correct length?
561 daniel-mar 73
        if ($("#admin_password")[0].value.length < min_password_length)
81 daniel-mar 74
        {
561 daniel-mar 75
                $("#password_warn")[0].innerHTML = '<font color="red">'+_L('Password must be at least %1 characters long',min_password_length)+'</font>';
76
                $("#config")[0].innerHTML = '<b>&lt?php</b><br><br><i>// ERROR: Password must be at least '+min_password_length+' characters long</i>'; // do not translate
81 daniel-mar 77
                error = true;
78
        } else {
561 daniel-mar 79
                $("#password_warn")[0].innerHTML = '';
81 daniel-mar 80
        }
81
 
82
        // Check 2: Do the passwords match?
561 daniel-mar 83
        if ($("#admin_password")[0].value != $("#admin_password2")[0].value) {
84
                $("#password_warn2")[0].innerHTML = '<font color="red">'+_L('The passwords do not match!')+'</font>';
2 daniel-mar 85
                error = true;
86
        } else {
561 daniel-mar 87
                $("#password_warn2")[0].innerHTML = '';
2 daniel-mar 88
        }
89
 
702 daniel-mar 90
        // Check 3: Ask the database or captcha plugins for verification of their data
150 daniel-mar 91
        for (var i = 0; i < rebuild_callbacks.length; i++) {
92
                var f = rebuild_callbacks[i];
93
                if (!f()) {
94
                        error = true;
95
                }
2 daniel-mar 96
        }
81 daniel-mar 97
 
149 daniel-mar 98
        // Continue
81 daniel-mar 99
        if (!error)
100
        {
561 daniel-mar 101
                var e = $("#db_plugin")[0];
702 daniel-mar 102
                var strDatabasePlugin = e.options[e.selectedIndex].value;
103
                var e = $("#captcha_plugin")[0];
104
                var strCaptchaPlugin = e.options[e.selectedIndex].value;
150 daniel-mar 105
 
561 daniel-mar 106
                $("#config")[0].innerHTML = '<b>&lt?php</b><br><br>' +
362 daniel-mar 107
                        '<i>// To renew this file, please run setup/ in your browser.</i><br>' + // do not translate
108
                        '<i>// If you don\'t want to run setup again, you can also change most of the settings directly in this file.</i><br>' + // do not translate
1207 daniel-mar 109
                        '<i>// List of possible values: doc/config_values.md</i><br>' + // do not translate
2 daniel-mar 110
                        '<br>' +
1050 daniel-mar 111
                        'use ViaThinkSoft\\OIDplus\\OIDplus;<br>' +
112
                        '<br>' +
261 daniel-mar 113
                        'OIDplus::baseConfig()->setValue(\'CONFIG_VERSION\',    2.1);<br>' +
2 daniel-mar 114
                        '<br>' +
150 daniel-mar 115
                        // Passwords are Base64 encoded to avoid that passwords can be read upon first sight,
294 daniel-mar 116
                        // e.g. if collegues are looking over your shoulder while you accidently open (and quickly close) userdata/baseconfig/config.inc.php
1173 daniel-mar 117
                        'OIDplus::baseConfig()->setValue(\'ADMIN_PASSWORD\',    ' + jsString(admPwdHash) + '); // '+pwComment+'<br>' +
2 daniel-mar 118
                        '<br>' +
1173 daniel-mar 119
                        'OIDplus::baseConfig()->setValue(\'DATABASE_PLUGIN\',   ' + jsString(strDatabasePlugin) + ');<br>';
150 daniel-mar 120
                for (var i = 0; i < rebuild_config_callbacks.length; i++) {
121
                        var f = rebuild_config_callbacks[i];
122
                        var cont = f();
123
                        if (cont) {
561 daniel-mar 124
                                $("#config")[0].innerHTML = $("#config")[0].innerHTML + cont;
150 daniel-mar 125
                        }
126
                }
561 daniel-mar 127
                $("#config")[0].innerHTML = $("#config")[0].innerHTML +
1050 daniel-mar 128
                        //'<br>' +
1173 daniel-mar 129
                        'OIDplus::baseConfig()->setValue(\'TABLENAME_PREFIX\',  ' + jsString($("#tablename_prefix")[0].value) + ');<br>' +
2 daniel-mar 130
                        '<br>' +
1173 daniel-mar 131
                        'OIDplus::baseConfig()->setValue(\'SERVER_SECRET\',     ' + jsString(generateRandomString(32)) + ');<br>' +
2 daniel-mar 132
                        '<br>' +
1173 daniel-mar 133
                        'OIDplus::baseConfig()->setValue(\'CAPTCHA_PLUGIN\',    ' + jsString(strCaptchaPlugin) + ');<br>';
702 daniel-mar 134
                for (var i = 0; i < captcha_rebuild_config_callbacks.length; i++) {
135
                        var f = captcha_rebuild_config_callbacks[i];
136
                        var cont = f();
137
                        if (cont) {
138
                                $("#config")[0].innerHTML = $("#config")[0].innerHTML + cont;
139
                        }
140
                }
141
 
142
                $("#config")[0].innerHTML = $("#config")[0].innerHTML +
80 daniel-mar 143
                        '<br>' +
1173 daniel-mar 144
                        'OIDplus::baseConfig()->setValue(\'ENFORCE_SSL\',       ' + $("#enforce_ssl")[0].value + ');<br>';
2 daniel-mar 145
 
1020 daniel-mar 146
                if ($("#canonical_url")[0].value.trim() != '') {
147
                        $("#config")[0].innerHTML = $("#config")[0].innerHTML +
148
                                '<br>' +
1173 daniel-mar 149
                                'OIDplus::baseConfig()->setValue(\'CANONICAL_SYSTEM_URL\', ' + jsString($("#canonical_url")[0].value.trim()) + ');<br>';
1020 daniel-mar 150
                }
151
 
561 daniel-mar 152
                $("#config")[0].innerHTML = $("#config")[0].innerHTML.replaceAll(' ', '&nbsp;');
2 daniel-mar 153
        }
154
 
155
        // In case something is not good, do not allow the user to continue with the other configuration steps:
156
        if (error) {
561 daniel-mar 157
                $("#step2")[0].style.display = "None";
158
                $("#step3")[0].style.display = "None";
159
                $("#step4")[0].style.display = "None";
1057 daniel-mar 160
                $("#footer_warn")[0].innerHTML = '<font color="red">'+_L('Please correct the errors above (in red) before continuing.')+'</font>';
2 daniel-mar 161
        } else {
561 daniel-mar 162
                $("#step2")[0].style.display = "Block";
163
                $("#step3")[0].style.display = "Block";
164
                $("#step4")[0].style.display = "Block";
1057 daniel-mar 165
                $("#footer_warn")[0].innerHTML = '';
2 daniel-mar 166
        }
167
}
362 daniel-mar 168
 
169
function checkAccess(dir) {
706 daniel-mar 170
        if (!dir.toLowerCase().startsWith('https:') && !dir.toLowerCase().startsWith('http:')) {
171
                var url = '../' + dir;
172
                var visibleUrl = RemoveLastDirectoryPartOf(window.location.href) + '/' + dir; // xhr.responseURL not available in IE
173
        } else {
174
                var url = dir;
175
                var visibleUrl = dir; // xhr.responseURL not available in IE
176
        }
362 daniel-mar 177
 
178
        var xhr = new XMLHttpRequest();
179
        xhr.onreadystatechange = function() {
180
                if (xhr.readyState === 4) {
181
                        if (xhr.status === 200) {
561 daniel-mar 182
                                $("#systemCheckCaption")[0].style.display = 'block';
861 daniel-mar 183
                                // TODO: At my Ubuntu VM, after fixing an issue with Apache2, the messages still appeared. I had to click the links and press F5 for each one
184
                                //       THERE MUST BE NO CACHE!!!
561 daniel-mar 185
                                $("#dirAccessWarning")[0].innerHTML = $("#dirAccessWarning")[0].innerHTML + _L('Attention: The following directory is world-readable: %1 ! You need to configure your web server to restrict access to this directory! (For Apache see <i>.htaccess</i>, for Microsoft IIS see <i>web.config</i>, for Nginx see <i>nginx.conf</i>).','<a target="_blank" href="'+url+'">'+visibleUrl+'</a>') + '<br>';
362 daniel-mar 186
                        }
187
                }
188
        };
189
 
190
        xhr.open('GET', url);
191
        xhr.send();
192
}
193
 
194
function dbplugin_changed() {
561 daniel-mar 195
        var e = $("#db_plugin")[0];
702 daniel-mar 196
        var strDatabasePlugin = e.options[e.selectedIndex].value;
362 daniel-mar 197
 
198
        for (var i = 0; i < plugin_combobox_change_callbacks.length; i++) {
199
                var f = plugin_combobox_change_callbacks[i];
702 daniel-mar 200
                f(strDatabasePlugin);
362 daniel-mar 201
        }
202
 
203
        rebuild();
204
}
205
 
702 daniel-mar 206
function captchaplugin_changed() {
207
        var e = $("#captcha_plugin")[0];
208
        var strCaptchaPlugin = e.options[e.selectedIndex].value;
209
 
210
        for (var i = 0; i < captcha_plugin_combobox_change_callbacks.length; i++) {
211
                var f = captcha_plugin_combobox_change_callbacks[i];
212
                f(strCaptchaPlugin);
213
        }
214
 
215
        rebuild();
216
}
217
 
362 daniel-mar 218
function performAccessCheck() {
561 daniel-mar 219
        $("#dirAccessWarning")[0].innerHTML = "";
362 daniel-mar 220
        checkAccess("userdata/index.html");
476 daniel-mar 221
        checkAccess("res/ATTENTION.TXT");
362 daniel-mar 222
        checkAccess("dev/index.html");
223
        checkAccess("includes/index.html");
448 daniel-mar 224
        checkAccess("setup/includes/index.html");
635 daniel-mar 225
        //checkAccess("plugins/viathinksoft/publicPages/100_whois/whois/cli/index.html");
974 daniel-mar 226
 
706 daniel-mar 227
        if (window.location.href.toLowerCase().startsWith('https://')) {
974 daniel-mar 228
                $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_YES'); // enforce SSL (because we are already SSL)
706 daniel-mar 229
        } else {
230
                // Do a SSL detection now.
231
                // This is important because on XAMPP the SSL cert is invalid (self signed) and the user might
974 daniel-mar 232
                // be very confused if the PHP detection (OIDplus::ENFORCE_SSL_AUTO) notices the open 443 port and redirects the user to a
706 daniel-mar 233
                // big warning page of the browser!
234
                var xhr = new XMLHttpRequest();
235
                xhr.onreadystatechange = function() {
236
                        if (xhr.readyState === 4) {
237
                                if (xhr.status === 200) {
974 daniel-mar 238
                                        $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_YES'); // enforce SSL (we checked that it loads correctly)
706 daniel-mar 239
                                } else {
240
                                        console.log("JS SSL detection result: "+xhr.status);
974 daniel-mar 241
                                        $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_NO'); // disable SSL (because it failed, e.g. because of invalid cert or closed port)
1289 daniel-mar 242
                                        setCookie('SSL_CHECK', 0, 0/*Until browser closes*/, oidplus_webpath_relative); // we must revert the SSL_CHECK=1 the PHP script did set (see explanation in OIDplus.class.php:isSslAvailable)
706 daniel-mar 243
                                }
244
                        }
245
                };
246
                var https_url = window.location.href.replace(/^http:/i, "https:");
247
                xhr.open('GET', https_url);
248
                xhr.send();
249
        }
362 daniel-mar 250
}
251
 
252
function setupOnLoad() {
253
        rebuild();
254
        dbplugin_changed();
702 daniel-mar 255
        captchaplugin_changed();
362 daniel-mar 256
        performAccessCheck();
257
}
258
 
1055 daniel-mar 259
$(document).ready(setupOnLoad);