Subversion Repositories oidplus

Rev

Rev 1020 | Rev 1055 | 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
1020 daniel-mar 109
                        '<i>// List of possible values: doc/config_values.txt</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
456 daniel-mar 117
                        'OIDplus::baseConfig()->setValue(\'ADMIN_PASSWORD\',    \'' + admPwdHash + '\'); // '+pwComment+'<br>' +
2 daniel-mar 118
                        '<br>' +
702 daniel-mar 119
                        'OIDplus::baseConfig()->setValue(\'DATABASE_PLUGIN\',   \''+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>' +
561 daniel-mar 129
                        'OIDplus::baseConfig()->setValue(\'TABLENAME_PREFIX\',  \''+$("#tablename_prefix")[0].value+'\');<br>' +
2 daniel-mar 130
                        '<br>' +
261 daniel-mar 131
                        'OIDplus::baseConfig()->setValue(\'SERVER_SECRET\',     \''+generateRandomString(32)+'\');<br>' +
2 daniel-mar 132
                        '<br>' +
702 daniel-mar 133
                        'OIDplus::baseConfig()->setValue(\'CAPTCHA_PLUGIN\',    \''+strCaptchaPlugin+'\');<br>';
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>' +
561 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>' +
149
                                'OIDplus::baseConfig()->setValue(\'CANONICAL_SYSTEM_URL\', \''+$("#canonical_url")[0].value.trim()+'\');<br>';
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";
2 daniel-mar 160
        } else {
561 daniel-mar 161
                $("#step2")[0].style.display = "Block";
162
                $("#step3")[0].style.display = "Block";
163
                $("#step4")[0].style.display = "Block";
2 daniel-mar 164
        }
165
}
362 daniel-mar 166
 
167
function checkAccess(dir) {
706 daniel-mar 168
        if (!dir.toLowerCase().startsWith('https:') && !dir.toLowerCase().startsWith('http:')) {
169
                var url = '../' + dir;
170
                var visibleUrl = RemoveLastDirectoryPartOf(window.location.href) + '/' + dir; // xhr.responseURL not available in IE
171
        } else {
172
                var url = dir;
173
                var visibleUrl = dir; // xhr.responseURL not available in IE
174
        }
362 daniel-mar 175
 
176
        var xhr = new XMLHttpRequest();
177
        xhr.onreadystatechange = function() {
178
                if (xhr.readyState === 4) {
179
                        if (xhr.status === 200) {
561 daniel-mar 180
                                $("#systemCheckCaption")[0].style.display = 'block';
861 daniel-mar 181
                                // 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
182
                                //       THERE MUST BE NO CACHE!!!
561 daniel-mar 183
                                $("#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 184
                        }
185
                }
186
        };
187
 
188
        xhr.open('GET', url);
189
        xhr.send();
190
}
191
 
192
function dbplugin_changed() {
561 daniel-mar 193
        var e = $("#db_plugin")[0];
702 daniel-mar 194
        var strDatabasePlugin = e.options[e.selectedIndex].value;
362 daniel-mar 195
 
196
        for (var i = 0; i < plugin_combobox_change_callbacks.length; i++) {
197
                var f = plugin_combobox_change_callbacks[i];
702 daniel-mar 198
                f(strDatabasePlugin);
362 daniel-mar 199
        }
200
 
201
        rebuild();
202
}
203
 
702 daniel-mar 204
function captchaplugin_changed() {
205
        var e = $("#captcha_plugin")[0];
206
        var strCaptchaPlugin = e.options[e.selectedIndex].value;
207
 
208
        for (var i = 0; i < captcha_plugin_combobox_change_callbacks.length; i++) {
209
                var f = captcha_plugin_combobox_change_callbacks[i];
210
                f(strCaptchaPlugin);
211
        }
212
 
213
        rebuild();
214
}
215
 
362 daniel-mar 216
function performAccessCheck() {
561 daniel-mar 217
        $("#dirAccessWarning")[0].innerHTML = "";
362 daniel-mar 218
        checkAccess("userdata/index.html");
476 daniel-mar 219
        checkAccess("res/ATTENTION.TXT");
362 daniel-mar 220
        checkAccess("dev/index.html");
221
        checkAccess("includes/index.html");
448 daniel-mar 222
        checkAccess("setup/includes/index.html");
635 daniel-mar 223
        //checkAccess("plugins/viathinksoft/publicPages/100_whois/whois/cli/index.html");
974 daniel-mar 224
 
706 daniel-mar 225
        if (window.location.href.toLowerCase().startsWith('https://')) {
974 daniel-mar 226
                $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_YES'); // enforce SSL (because we are already SSL)
706 daniel-mar 227
        } else {
228
                // Do a SSL detection now.
229
                // This is important because on XAMPP the SSL cert is invalid (self signed) and the user might
974 daniel-mar 230
                // 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 231
                // big warning page of the browser!
232
                var xhr = new XMLHttpRequest();
233
                xhr.onreadystatechange = function() {
234
                        if (xhr.readyState === 4) {
235
                                if (xhr.status === 200) {
974 daniel-mar 236
                                        $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_YES'); // enforce SSL (we checked that it loads correctly)
706 daniel-mar 237
                                } else {
238
                                        console.log("JS SSL detection result: "+xhr.status);
974 daniel-mar 239
                                        $("#enforce_ssl").val('OIDplus::ENFORCE_SSL_NO'); // disable SSL (because it failed, e.g. because of invalid cert or closed port)
706 daniel-mar 240
                                }
241
                        }
242
                };
243
                var https_url = window.location.href.replace(/^http:/i, "https:");
244
                xhr.open('GET', https_url);
245
                xhr.send();
246
        }
362 daniel-mar 247
}
248
 
249
function setupOnLoad() {
250
        rebuild();
251
        dbplugin_changed();
702 daniel-mar 252
        captchaplugin_changed();
362 daniel-mar 253
        performAccessCheck();
254
}
255
 
256
window.onload = setupOnLoad;