Subversion Repositories oidplus

Rev

Rev 974 | Rev 1020 | Go to most recent revision | 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
2 daniel-mar 109
                        '<br>' +
261 daniel-mar 110
                        'OIDplus::baseConfig()->setValue(\'CONFIG_VERSION\',    2.1);<br>' +
2 daniel-mar 111
                        '<br>' +
150 daniel-mar 112
                        // Passwords are Base64 encoded to avoid that passwords can be read upon first sight,
294 daniel-mar 113
                        // e.g. if collegues are looking over your shoulder while you accidently open (and quickly close) userdata/baseconfig/config.inc.php
456 daniel-mar 114
                        'OIDplus::baseConfig()->setValue(\'ADMIN_PASSWORD\',    \'' + admPwdHash + '\'); // '+pwComment+'<br>' +
2 daniel-mar 115
                        '<br>' +
702 daniel-mar 116
                        'OIDplus::baseConfig()->setValue(\'DATABASE_PLUGIN\',   \''+strDatabasePlugin+'\');<br>';
150 daniel-mar 117
                for (var i = 0; i < rebuild_config_callbacks.length; i++) {
118
                        var f = rebuild_config_callbacks[i];
119
                        var cont = f();
120
                        if (cont) {
561 daniel-mar 121
                                $("#config")[0].innerHTML = $("#config")[0].innerHTML + cont;
150 daniel-mar 122
                        }
123
                }
561 daniel-mar 124
                $("#config")[0].innerHTML = $("#config")[0].innerHTML +
2 daniel-mar 125
                        '<br>' +
561 daniel-mar 126
                        'OIDplus::baseConfig()->setValue(\'TABLENAME_PREFIX\',  \''+$("#tablename_prefix")[0].value+'\');<br>' +
2 daniel-mar 127
                        '<br>' +
261 daniel-mar 128
                        'OIDplus::baseConfig()->setValue(\'SERVER_SECRET\',     \''+generateRandomString(32)+'\');<br>' +
2 daniel-mar 129
                        '<br>' +
702 daniel-mar 130
                        'OIDplus::baseConfig()->setValue(\'CAPTCHA_PLUGIN\',    \''+strCaptchaPlugin+'\');<br>';
131
                for (var i = 0; i < captcha_rebuild_config_callbacks.length; i++) {
132
                        var f = captcha_rebuild_config_callbacks[i];
133
                        var cont = f();
134
                        if (cont) {
135
                                $("#config")[0].innerHTML = $("#config")[0].innerHTML + cont;
136
                        }
137
                }
138
 
139
                $("#config")[0].innerHTML = $("#config")[0].innerHTML +
80 daniel-mar 140
                        '<br>' +
561 daniel-mar 141
                        'OIDplus::baseConfig()->setValue(\'ENFORCE_SSL\',       '+$("#enforce_ssl")[0].value+');<br>';
2 daniel-mar 142
 
561 daniel-mar 143
                $("#config")[0].innerHTML = $("#config")[0].innerHTML.replaceAll(' ', '&nbsp;');
2 daniel-mar 144
        }
145
 
146
        // In case something is not good, do not allow the user to continue with the other configuration steps:
147
        if (error) {
561 daniel-mar 148
                $("#step2")[0].style.display = "None";
149
                $("#step3")[0].style.display = "None";
150
                $("#step4")[0].style.display = "None";
2 daniel-mar 151
        } else {
561 daniel-mar 152
                $("#step2")[0].style.display = "Block";
153
                $("#step3")[0].style.display = "Block";
154
                $("#step4")[0].style.display = "Block";
2 daniel-mar 155
        }
156
}
362 daniel-mar 157
 
158
function checkAccess(dir) {
706 daniel-mar 159
        if (!dir.toLowerCase().startsWith('https:') && !dir.toLowerCase().startsWith('http:')) {
160
                var url = '../' + dir;
161
                var visibleUrl = RemoveLastDirectoryPartOf(window.location.href) + '/' + dir; // xhr.responseURL not available in IE
162
        } else {
163
                var url = dir;
164
                var visibleUrl = dir; // xhr.responseURL not available in IE
165
        }
362 daniel-mar 166
 
167
        var xhr = new XMLHttpRequest();
168
        xhr.onreadystatechange = function() {
169
                if (xhr.readyState === 4) {
170
                        if (xhr.status === 200) {
561 daniel-mar 171
                                $("#systemCheckCaption")[0].style.display = 'block';
861 daniel-mar 172
                                // 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
173
                                //       THERE MUST BE NO CACHE!!!
561 daniel-mar 174
                                $("#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 175
                        }
176
                }
177
        };
178
 
179
        xhr.open('GET', url);
180
        xhr.send();
181
}
182
 
183
function dbplugin_changed() {
561 daniel-mar 184
        var e = $("#db_plugin")[0];
702 daniel-mar 185
        var strDatabasePlugin = e.options[e.selectedIndex].value;
362 daniel-mar 186
 
187
        for (var i = 0; i < plugin_combobox_change_callbacks.length; i++) {
188
                var f = plugin_combobox_change_callbacks[i];
702 daniel-mar 189
                f(strDatabasePlugin);
362 daniel-mar 190
        }
191
 
192
        rebuild();
193
}
194
 
702 daniel-mar 195
function captchaplugin_changed() {
196
        var e = $("#captcha_plugin")[0];
197
        var strCaptchaPlugin = e.options[e.selectedIndex].value;
198
 
199
        for (var i = 0; i < captcha_plugin_combobox_change_callbacks.length; i++) {
200
                var f = captcha_plugin_combobox_change_callbacks[i];
201
                f(strCaptchaPlugin);
202
        }
203
 
204
        rebuild();
205
}
206
 
362 daniel-mar 207
function performAccessCheck() {
561 daniel-mar 208
        $("#dirAccessWarning")[0].innerHTML = "";
362 daniel-mar 209
        checkAccess("userdata/index.html");
476 daniel-mar 210
        checkAccess("res/ATTENTION.TXT");
362 daniel-mar 211
        checkAccess("dev/index.html");
212
        checkAccess("includes/index.html");
448 daniel-mar 213
        checkAccess("setup/includes/index.html");
635 daniel-mar 214
        //checkAccess("plugins/viathinksoft/publicPages/100_whois/whois/cli/index.html");
974 daniel-mar 215
 
706 daniel-mar 216
        if (window.location.href.toLowerCase().startsWith('https://')) {
974 daniel-mar 217
                $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_YES'); // enforce SSL (because we are already SSL)
706 daniel-mar 218
        } else {
219
                // Do a SSL detection now.
220
                // This is important because on XAMPP the SSL cert is invalid (self signed) and the user might
974 daniel-mar 221
                // 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 222
                // big warning page of the browser!
223
                var xhr = new XMLHttpRequest();
224
                xhr.onreadystatechange = function() {
225
                        if (xhr.readyState === 4) {
226
                                if (xhr.status === 200) {
974 daniel-mar 227
                                        $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_YES'); // enforce SSL (we checked that it loads correctly)
706 daniel-mar 228
                                } else {
229
                                        console.log("JS SSL detection result: "+xhr.status);
974 daniel-mar 230
                                        $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_NO'); // disable SSL (because it failed, e.g. because of invalid cert or closed port)
706 daniel-mar 231
                                }
232
                        }
233
                };
234
                var https_url = window.location.href.replace(/^http:/i, "https:");
235
                xhr.open('GET', https_url);
236
                xhr.send();
237
        }
362 daniel-mar 238
}
239
 
240
function setupOnLoad() {
241
        rebuild();
242
        dbplugin_changed();
702 daniel-mar 243
        captchaplugin_changed();
362 daniel-mar 244
        performAccessCheck();
245
}
246
 
247
window.onload = setupOnLoad;