Added CAPTCHA option when creating new accounts on login screen.
This commit is contained in:
parent
4382899468
commit
04fb1f2bf0
|
@ -1235,7 +1235,7 @@ function createAuthenticodeHandler(path) {
|
||||||
if (args.hash == 'sha512') { hashOid = forge.pki.oids.sha512; fileHash = obj.getHash('sha512'); }
|
if (args.hash == 'sha512') { hashOid = forge.pki.oids.sha512; fileHash = obj.getHash('sha512'); }
|
||||||
if (args.hash == 'sha224') { hashOid = forge.pki.oids.sha224; fileHash = obj.getHash('sha224'); }
|
if (args.hash == 'sha224') { hashOid = forge.pki.oids.sha224; fileHash = obj.getHash('sha224'); }
|
||||||
if (args.hash == 'md5') { hashOid = forge.pki.oids.md5; fileHash = obj.getHash('md5'); }
|
if (args.hash == 'md5') { hashOid = forge.pki.oids.md5; fileHash = obj.getHash('md5'); }
|
||||||
if (hashOid == null) { func(false); return; };
|
if (hashOid == null) { func('Invalid signing hash: ' + args.hash); return; };
|
||||||
|
|
||||||
// Create the signature block
|
// Create the signature block
|
||||||
var xp7 = forge.pkcs7.createSignedData();
|
var xp7 = forge.pkcs7.createSignedData();
|
||||||
|
@ -1453,7 +1453,7 @@ function createAuthenticodeHandler(path) {
|
||||||
// Open the output file
|
// Open the output file
|
||||||
var output = null;
|
var output = null;
|
||||||
try { output = fs.openSync(args.out, 'w+'); } catch (ex) { }
|
try { output = fs.openSync(args.out, 'w+'); } catch (ex) { }
|
||||||
if (output == null) { func(false); return; }
|
if (output == null) { func('Unable to open output file: ' + args.out); return; }
|
||||||
var tmp, written = 0, executableSize = obj.header.sigpos ? obj.header.sigpos : filesize;
|
var tmp, written = 0, executableSize = obj.header.sigpos ? obj.header.sigpos : filesize;
|
||||||
|
|
||||||
// Compute pre-header length and copy that to the new file
|
// Compute pre-header length and copy that to the new file
|
||||||
|
|
|
@ -343,6 +343,7 @@
|
||||||
"ipkvm": { "type": "boolean", "default": false, "description": "Set to true to enable IP KVM device support in this domain." },
|
"ipkvm": { "type": "boolean", "default": false, "description": "Set to true to enable IP KVM device support in this domain." },
|
||||||
"minify": { "type": "boolean", "default": false, "description": "When enabled, the server will send reduced sided web pages." },
|
"minify": { "type": "boolean", "default": false, "description": "When enabled, the server will send reduced sided web pages." },
|
||||||
"newAccounts": { "type": "boolean", "default": false, "description": "When set to true, allow new user accounts to be created from the login page." },
|
"newAccounts": { "type": "boolean", "default": false, "description": "When set to true, allow new user accounts to be created from the login page." },
|
||||||
|
"newAccountsPass": { "type": "string", "default": null, "description": "When set this password will be required in order to create a new account from the login screen." },
|
||||||
"newAccountsUserGroups": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
"newAccountsUserGroups": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
||||||
"userNameIsEmail": { "type": "boolean", "default": false, "description": "When enabled, the username of each account is also the email address of the account." },
|
"userNameIsEmail": { "type": "boolean", "default": false, "description": "When enabled, the username of each account is also the email address of the account." },
|
||||||
"newAccountEmailDomains": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
"newAccountEmailDomains": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
||||||
|
|
|
@ -3675,6 +3675,7 @@ function mainStart() {
|
||||||
var wildleek = false;
|
var wildleek = false;
|
||||||
var nodemailer = false;
|
var nodemailer = false;
|
||||||
var sendgrid = false;
|
var sendgrid = false;
|
||||||
|
var captcha = false;
|
||||||
if (require('os').platform() == 'win32') { for (var i in config.domains) { domainCount++; if (config.domains[i].auth == 'sspi') { sspi = true; } else { allsspi = false; } } } else { allsspi = false; }
|
if (require('os').platform() == 'win32') { for (var i in config.domains) { domainCount++; if (config.domains[i].auth == 'sspi') { sspi = true; } else { allsspi = false; } } } else { allsspi = false; }
|
||||||
if (domainCount == 0) { allsspi = false; }
|
if (domainCount == 0) { allsspi = false; }
|
||||||
for (var i in config.domains) {
|
for (var i in config.domains) {
|
||||||
|
@ -3697,6 +3698,7 @@ function mainStart() {
|
||||||
}
|
}
|
||||||
if (config.domains[i].sessionrecording != null) { sessionRecording = true; }
|
if (config.domains[i].sessionrecording != null) { sessionRecording = true; }
|
||||||
if ((config.domains[i].passwordrequirements != null) && (config.domains[i].passwordrequirements.bancommonpasswords == true)) { wildleek = true; }
|
if ((config.domains[i].passwordrequirements != null) && (config.domains[i].passwordrequirements.bancommonpasswords == true)) { wildleek = true; }
|
||||||
|
if ((config.domains[i].newaccountscaptcha != null) && (config.domains[i].newaccountscaptcha !== false)) { captcha = true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the list of required modules
|
// Build the list of required modules
|
||||||
|
@ -3705,6 +3707,8 @@ function mainStart() {
|
||||||
if (ldap == true) { modules.push('ldapauth-fork'); }
|
if (ldap == true) { modules.push('ldapauth-fork'); }
|
||||||
if (ssh == true) { if (nodeVersion < 11) { addServerWarning('MeshCentral SSH support requires NodeJS 11 or higher.', 1); } else { modules.push('ssh2'); } }
|
if (ssh == true) { if (nodeVersion < 11) { addServerWarning('MeshCentral SSH support requires NodeJS 11 or higher.', 1); } else { modules.push('ssh2'); } }
|
||||||
if (passport != null) { modules.push(...passport); }
|
if (passport != null) { modules.push(...passport); }
|
||||||
|
if (captcha == true) { modules.push('svg-captcha'); }
|
||||||
|
|
||||||
if (sessionRecording == true) { modules.push('image-size'); } // Need to get the remote desktop JPEG sizes to index the recodring file.
|
if (sessionRecording == true) { modules.push('image-size'); } // Need to get the remote desktop JPEG sizes to index the recodring file.
|
||||||
if (config.letsencrypt != null) { modules.push('acme-client'); } // Add acme-client module
|
if (config.letsencrypt != null) { modules.push('acme-client'); } // Add acme-client module
|
||||||
if (config.settings.mqtt != null) { modules.push('aedes@0.39.0'); } // Add MQTT Modules
|
if (config.settings.mqtt != null) { modules.push('aedes@0.39.0'); } // Add MQTT Modules
|
||||||
|
|
|
@ -58,7 +58,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||||
obj.server.listen(args.mpsport, args.mpsportbind, function () {
|
obj.server.listen(args.mpsport, args.mpsportbind, function () {
|
||||||
console.log("MeshCentral Intel(R) AMT server running on " + certificates.AmtMpsName + ":" + args.mpsport + ((args.mpsaliasport != null) ? (", alias port " + args.mpsaliasport) : "") + ".");
|
console.log("MeshCentral Intel(R) AMT server running on " + certificates.AmtMpsName + ":" + args.mpsport + ((args.mpsaliasport != null) ? (", alias port " + args.mpsaliasport) : "") + ".");
|
||||||
obj.parent.authLog('mps', 'Server listening on ' + ((args.mpsportbind != null) ? args.mpsportbind : '0.0.0.0') + ' port ' + args.mpsport + '.');
|
obj.parent.authLog('mps', 'Server listening on ' + ((args.mpsportbind != null) ? args.mpsportbind : '0.0.0.0') + ' port ' + args.mpsport + '.');
|
||||||
}).on("error", function (err) { console.error("ERROR: MeshCentral Intel(R) AMT server port " + args.mpsport + " is not available."); if (args.exactports) { process.exit(); } });
|
}).on("error", function (err) { console.error("ERROR: MeshCentral Intel(R) AMT server port " + args.mpsport + " is not available. Check if the MeshCentral is already running."); if (args.exactports) { process.exit(); } });
|
||||||
|
|
||||||
obj.server.on('tlsClientError', function (err, tlssocket) { if (args.mpsdebug) { var remoteAddress = tlssocket.remoteAddress; if (tlssocket.remoteFamily == 'IPv6') { remoteAddress = '[' + remoteAddress + ']'; } console.log('MPS:Invalid TLS connection from ' + remoteAddress + ':' + tlssocket.remotePort + '.'); } });
|
obj.server.on('tlsClientError', function (err, tlssocket) { if (args.mpsdebug) { var remoteAddress = tlssocket.remoteAddress; if (tlssocket.remoteFamily == 'IPv6') { remoteAddress = '[' + remoteAddress + ']'; } console.log('MPS:Invalid TLS connection from ' + remoteAddress + ':' + tlssocket.remotePort + '.'); } });
|
||||||
}
|
}
|
||||||
|
|
14
package.json
14
package.json
|
@ -37,6 +37,8 @@
|
||||||
"sample-config-advanced.json"
|
"sample-config-advanced.json"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@crowdsec/express-bouncer": "^0.1.0",
|
||||||
|
"@yetzt/nedb": "^1.8.0",
|
||||||
"archiver": "^5.3.1",
|
"archiver": "^5.3.1",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"cbor": "~5.2.0",
|
"cbor": "~5.2.0",
|
||||||
|
@ -45,13 +47,21 @@
|
||||||
"express": "^4.17.0",
|
"express": "^4.17.0",
|
||||||
"express-handlebars": "^5.3.5",
|
"express-handlebars": "^5.3.5",
|
||||||
"express-ws": "^4.0.0",
|
"express-ws": "^4.0.0",
|
||||||
|
"image-size": "^1.0.1",
|
||||||
"ipcheck": "^0.1.0",
|
"ipcheck": "^0.1.0",
|
||||||
|
"loadavg-windows": "^1.1.1",
|
||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.5",
|
||||||
"multiparty": "^4.2.1",
|
"multiparty": "^4.2.1",
|
||||||
"@yetzt/nedb": "^1.8.0",
|
|
||||||
"node-forge": "^1.0.0",
|
"node-forge": "^1.0.0",
|
||||||
|
"node-windows": "^0.1.4",
|
||||||
|
"otplib": "^10.2.3",
|
||||||
|
"pg": "^8.7.1",
|
||||||
|
"pgtools": "^0.3.2",
|
||||||
|
"ssh2": "^1.11.0",
|
||||||
|
"web-push": "^3.5.0",
|
||||||
"ws": "^5.2.3",
|
"ws": "^5.2.3",
|
||||||
"yauzl": "^2.10.0"
|
"yauzl": "^2.10.0",
|
||||||
|
"yubikeyotp": "^0.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
|
|
|
@ -122,6 +122,14 @@
|
||||||
<td id="nuToken" align=right>Creation Token:</td>
|
<td id="nuToken" align=right>Creation Token:</td>
|
||||||
<td><input id=anewaccountpass type=password name=anewaccountpass {{{autocomplete}}}=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6,event) onkeyup=validateCreate(6,event) /></td>
|
<td><input id=anewaccountpass type=password name=anewaccountpass {{{autocomplete}}}=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6,event) onkeyup=validateCreate(6,event) /></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr id=newAccountCaptchaImg title="CAPTCHA image">
|
||||||
|
<td></td>
|
||||||
|
<td colspan=2><img src="{{{newAccountCaptchaImage}}}" loading="lazy" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr id=newAccountCaptcha title="Security check">
|
||||||
|
<td id="nuCaptcha" align=right>Security Check:</td>
|
||||||
|
<td><input id=anewaccountcaptcha type=text name=anewaccountcaptcha {{{autocomplete}}}=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(7,event) onkeyup=validateCreate(7,event) /></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan=2>
|
<td colspan=2>
|
||||||
<div style=float:right><input id=createButton type=submit value="Create Account" disabled="disabled" /></div>
|
<div style=float:right><input id=createButton type=submit value="Create Account" disabled="disabled" /></div>
|
||||||
|
@ -131,6 +139,7 @@
|
||||||
</table>
|
</table>
|
||||||
<hr /><a onclick="return xgo(1,event);" href="#" style=cursor:pointer>Back to login</a>
|
<hr /><a onclick="return xgo(1,event);" href="#" style=cursor:pointer>Back to login</a>
|
||||||
<input id=createformargs name="urlargs" type="hidden" value="" />
|
<input id=createformargs name="urlargs" type="hidden" value="" />
|
||||||
|
<input id=createformcaptcha name="captchaargs" type="hidden" value="{{{newAccountCaptcha}}}" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id=resetpanel style="display:none">
|
<div id=resetpanel style="display:none">
|
||||||
|
@ -311,6 +320,7 @@
|
||||||
var loginMode = '{{{loginmode}}}';
|
var loginMode = '{{{loginmode}}}';
|
||||||
var newAccount = '{{{newAccount}}}';
|
var newAccount = '{{{newAccount}}}';
|
||||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||||
|
var newAccountCaptcha = '{{{newAccountCaptcha}}}';
|
||||||
var emailCheck = '{{{emailcheck}}}';
|
var emailCheck = '{{{emailcheck}}}';
|
||||||
var passRequirements = '{{{passRequirements}}}';
|
var passRequirements = '{{{passRequirements}}}';
|
||||||
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
||||||
|
@ -335,7 +345,7 @@
|
||||||
var i;
|
var i;
|
||||||
var messageid = parseInt('{{{messageid}}}');
|
var messageid = parseInt('{{{messageid}}}');
|
||||||
var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent."];
|
var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent."];
|
||||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance."];
|
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance.", "Unable to send device notification.", "Invalid security check."];
|
||||||
if (messageid > 0) {
|
if (messageid > 0) {
|
||||||
var msg = '';
|
var msg = '';
|
||||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||||
|
@ -433,6 +443,8 @@
|
||||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||||
if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||||
QV('newAccountPass', (newAccountPass == 1));
|
QV('newAccountPass', (newAccountPass == 1));
|
||||||
|
QV('newAccountCaptcha', (newAccountCaptcha != ''));
|
||||||
|
QV('newAccountCaptchaImg', (newAccountCaptcha != ''));
|
||||||
QV('resetAccountDiv', (emailCheck == 'true'));
|
QV('resetAccountDiv', (emailCheck == 'true'));
|
||||||
QV('hrAccountDiv', (emailCheck == 'true') || (newAccountPass == 1));
|
QV('hrAccountDiv', (emailCheck == 'true') || (newAccountPass == 1));
|
||||||
|
|
||||||
|
@ -627,6 +639,7 @@
|
||||||
var pass1ok = (Q('apassword1').value.length > 0);
|
var pass1ok = (Q('apassword1').value.length > 0);
|
||||||
var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
|
var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
|
||||||
var newAccOk = (newAccountPass == 0) || (Q('anewaccountpass').value.length > 0);
|
var newAccOk = (newAccountPass == 0) || (Q('anewaccountpass').value.length > 0);
|
||||||
|
var newCaptchaOk = (newAccountCaptcha == '') || (Q('anewaccountcaptcha').value.length > 0);
|
||||||
var ok = (userok && emailok && pass1ok && pass2ok && newAccOk);
|
var ok = (userok && emailok && pass1ok && pass2ok && newAccOk);
|
||||||
|
|
||||||
// Color the fields
|
// Color the fields
|
||||||
|
@ -635,6 +648,7 @@
|
||||||
QS('nuPass1').color = pass1ok ? 'black' : '#7b241c';
|
QS('nuPass1').color = pass1ok ? 'black' : '#7b241c';
|
||||||
QS('nuPass2').color = pass2ok ? 'black' : '#7b241c';
|
QS('nuPass2').color = pass2ok ? 'black' : '#7b241c';
|
||||||
QS('nuToken').color = newAccOk ? 'black' : '#7b241c';
|
QS('nuToken').color = newAccOk ? 'black' : '#7b241c';
|
||||||
|
QS('nuCaptcha').color = newCaptchaOk ? 'black' : '#7b241c';
|
||||||
|
|
||||||
if (Q('apassword1').value == '') {
|
if (Q('apassword1').value == '') {
|
||||||
QH('passWarning', '');
|
QH('passWarning', '');
|
||||||
|
@ -663,13 +677,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((e != null) && (e.keyCode == 13)) {
|
if ((e != null) && (e.keyCode == 13)) {
|
||||||
|
|
||||||
if ((box == 1) && userok) { Q('aemail').focus(); }
|
if ((box == 1) && userok) { Q('aemail').focus(); }
|
||||||
if ((box == 2) && emailok) { Q('apassword1').focus(); }
|
if ((box == 2) && emailok) { Q('apassword1').focus(); }
|
||||||
if ((box == 3) && pass1ok) { Q('apassword2').focus(); }
|
if ((box == 3) && pass1ok) { Q('apassword2').focus(); }
|
||||||
if ((box == 4) && pass2ok) { if (passRequirements.hint === true) { Q('apasswordhint').focus(); } else { box = 5; } }
|
if ((box == 4) && pass2ok) { if (passRequirements.hint === true) { Q('apasswordhint').focus(); } else { box = 5; } }
|
||||||
if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { box = 6; } }
|
if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { box = 6; } }
|
||||||
if (box == 6) { Q('createButton').click(); }
|
if (box == 6) { if (newAccountCaptcha != '') { Q('anewaccountcaptcha').focus(); } else { box = 7; } }
|
||||||
|
if (box == 7) { Q('createButton').click(); }
|
||||||
}
|
}
|
||||||
if (e != null) { haltEvent(e); }
|
if (e != null) { haltEvent(e); }
|
||||||
QE('createButton', ok);
|
QE('createButton', ok);
|
||||||
|
|
|
@ -144,6 +144,14 @@
|
||||||
<td id="nuToken" align=right>Creation Token:</td>
|
<td id="nuToken" align=right>Creation Token:</td>
|
||||||
<td><input id=anewaccountpass type=password name=anewaccountpass {{{autocomplete}}}=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6,event) onkeyup=validateCreate(6,event) /></td>
|
<td><input id=anewaccountpass type=password name=anewaccountpass {{{autocomplete}}}=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(6,event) onkeyup=validateCreate(6,event) /></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr id=newAccountCaptchaImg title="CAPTCHA image">
|
||||||
|
<td></td>
|
||||||
|
<td colspan=2><img src="{{{newAccountCaptchaImage}}}" loading="lazy" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr id=newAccountCaptcha title="Security check">
|
||||||
|
<td id="nuCaptcha" align=right>Security Check:</td>
|
||||||
|
<td><input id=anewaccountcaptcha type=text name=anewaccountcaptcha {{{autocomplete}}}=off maxlength=256 onkeydown=haltReturn(event) onchange=validateCreate(7,event) onkeyup=validateCreate(7,event) /></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan=2>
|
<td colspan=2>
|
||||||
<div style=float:right><input id=createButton type="button" onclick="submitButtonClicked('createpanelform')" value="Create Account" disabled="disabled" /></div>
|
<div style=float:right><input id=createButton type="button" onclick="submitButtonClicked('createpanelform')" value="Create Account" disabled="disabled" /></div>
|
||||||
|
@ -153,6 +161,7 @@
|
||||||
</table>
|
</table>
|
||||||
<hr /><a onclick="return xgo(1,event);" href="#" style=cursor:pointer>Back to login</a>
|
<hr /><a onclick="return xgo(1,event);" href="#" style=cursor:pointer>Back to login</a>
|
||||||
<input id=createformargs name="urlargs" type="hidden" value="" />
|
<input id=createformargs name="urlargs" type="hidden" value="" />
|
||||||
|
<input id=createformcaptcha name="captchaargs" type="hidden" value="{{{newAccountCaptcha}}}" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id=resetpanel style="display:none">
|
<div id=resetpanel style="display:none">
|
||||||
|
@ -368,6 +377,7 @@
|
||||||
var loginMode = '{{{loginmode}}}';
|
var loginMode = '{{{loginmode}}}';
|
||||||
var newAccount = '{{{newAccount}}}';
|
var newAccount = '{{{newAccount}}}';
|
||||||
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
var newAccountPass = parseInt('{{{newAccountPass}}}');
|
||||||
|
var newAccountCaptcha = '{{{newAccountCaptcha}}}';
|
||||||
var emailCheck = '{{{emailcheck}}}';
|
var emailCheck = '{{{emailcheck}}}';
|
||||||
var passRequirements = '{{{passRequirements}}}';
|
var passRequirements = '{{{passRequirements}}}';
|
||||||
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
|
||||||
|
@ -405,7 +415,7 @@
|
||||||
var i;
|
var i;
|
||||||
var messageid = parseInt('{{{messageid}}}');
|
var messageid = parseInt('{{{messageid}}}');
|
||||||
var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent.", "Sending notification..."];
|
var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent.", "Sending notification..."];
|
||||||
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance.", "Unable to send device notification."];
|
var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance.", "Unable to send device notification.", "Invalid security check."];
|
||||||
if (messageid > 0) {
|
if (messageid > 0) {
|
||||||
var msg = '';
|
var msg = '';
|
||||||
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; }
|
||||||
|
@ -487,6 +497,8 @@
|
||||||
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
QV('newAccountDiv', (newAccount === '1') || (newAccount === 'true')); // If new accounts are not allowed, don't display the new account link.
|
||||||
if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
if ((passhint != null) && (passhint.length > 0)) { QV('showPassHintLink', true); }
|
||||||
QV('newAccountPass', (newAccountPass == 1));
|
QV('newAccountPass', (newAccountPass == 1));
|
||||||
|
QV('newAccountCaptcha', (newAccountCaptcha != ''));
|
||||||
|
QV('newAccountCaptchaImg', (newAccountCaptcha != ''));
|
||||||
QV('resetAccountDiv', (emailCheck == 'true'));
|
QV('resetAccountDiv', (emailCheck == 'true'));
|
||||||
QV('hrAccountDiv', (emailCheck == 'true') || (newAccountPass == 1));
|
QV('hrAccountDiv', (emailCheck == 'true') || (newAccountPass == 1));
|
||||||
|
|
||||||
|
@ -712,6 +724,7 @@
|
||||||
var pass1ok = (Q('apassword1').value.length > 0);
|
var pass1ok = (Q('apassword1').value.length > 0);
|
||||||
var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
|
var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
|
||||||
var newAccOk = (newAccountPass == 0) || (Q('anewaccountpass').value.length > 0);
|
var newAccOk = (newAccountPass == 0) || (Q('anewaccountpass').value.length > 0);
|
||||||
|
var newCaptchaOk = (newAccountCaptcha == '') || (Q('anewaccountcaptcha').value.length > 0);
|
||||||
var ok = (userok && emailok && pass1ok && pass2ok && newAccOk);
|
var ok = (userok && emailok && pass1ok && pass2ok && newAccOk);
|
||||||
|
|
||||||
// Color the fields
|
// Color the fields
|
||||||
|
@ -720,6 +733,7 @@
|
||||||
QS('nuPass1').color = pass1ok ? 'black' : '#7b241c';
|
QS('nuPass1').color = pass1ok ? 'black' : '#7b241c';
|
||||||
QS('nuPass2').color = pass2ok ? 'black' : '#7b241c';
|
QS('nuPass2').color = pass2ok ? 'black' : '#7b241c';
|
||||||
QS('nuToken').color = newAccOk ? 'black' : '#7b241c';
|
QS('nuToken').color = newAccOk ? 'black' : '#7b241c';
|
||||||
|
QS('nuCaptcha').color = newCaptchaOk ? 'black' : '#7b241c';
|
||||||
|
|
||||||
if (Q('apassword1').value == '') {
|
if (Q('apassword1').value == '') {
|
||||||
QH('passWarning', '');
|
QH('passWarning', '');
|
||||||
|
@ -748,13 +762,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((e != null) && (e.keyCode == 13)) {
|
if ((e != null) && (e.keyCode == 13)) {
|
||||||
|
|
||||||
if ((box == 1) && userok) { Q('aemail').focus(); }
|
if ((box == 1) && userok) { Q('aemail').focus(); }
|
||||||
if ((box == 2) && emailok) { Q('apassword1').focus(); }
|
if ((box == 2) && emailok) { Q('apassword1').focus(); }
|
||||||
if ((box == 3) && pass1ok) { Q('apassword2').focus(); }
|
if ((box == 3) && pass1ok) { Q('apassword2').focus(); }
|
||||||
if ((box == 4) && pass2ok) { if (passRequirements.hint === true) { Q('apasswordhint').focus(); } else { box = 5; } }
|
if ((box == 4) && pass2ok) { if (passRequirements.hint === true) { Q('apasswordhint').focus(); } else { box = 5; } }
|
||||||
if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { box = 6; } }
|
if (box == 5) { if (newAccountPass == 1) { Q('anewaccountpass').focus(); } else { box = 6; } }
|
||||||
if (box == 6) { Q('createButton').click(); }
|
if (box == 6) { if (newAccountCaptcha != '') { Q('anewaccountcaptcha').focus(); } else { box = 7; } }
|
||||||
|
if (box == 7) { Q('createButton').click(); }
|
||||||
}
|
}
|
||||||
if (e != null) { haltEvent(e); }
|
if (e != null) { haltEvent(e); }
|
||||||
QE('createButton', ok);
|
QE('createButton', ok);
|
||||||
|
|
59
webserver.js
59
webserver.js
|
@ -1359,6 +1359,26 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||||
// If the email is the username, set this here.
|
// If the email is the username, set this here.
|
||||||
if (domain.usernameisemail) { req.body.username = req.body.email; }
|
if (domain.usernameisemail) { req.body.username = req.body.email; }
|
||||||
|
|
||||||
|
// Check if there is domain.newAccountToken, check if supplied token is valid
|
||||||
|
if ((domain.newaccountspass != null) && (domain.newaccountspass != '') && (req.body.anewaccountpass != domain.newaccountspass)) {
|
||||||
|
parent.debug('web', 'handleCreateAccountRequest: Invalid account creation token');
|
||||||
|
req.session.loginmode = 2;
|
||||||
|
req.session.messageid = 103; // Invalid account creation token.
|
||||||
|
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If needed, check the new account creation CAPTCHA
|
||||||
|
if ((domain.newaccountscaptcha != null) && (domain.newaccountscaptcha !== false)) {
|
||||||
|
const c = parent.decodeCookie(req.body.captchaargs, parent.loginCookieEncryptionKey, 10); // 10 minute timeout
|
||||||
|
if ((c == null) || (c.type != 'newAccount') || (typeof c.captcha != 'string') || (c.captcha.length < 5) || (c.captcha != req.body.anewaccountcaptcha)) {
|
||||||
|
req.session.loginmode = 2;
|
||||||
|
req.session.messageid = 117; // Invalid security check
|
||||||
|
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Accounts that start with ~ are not allowed
|
// Accounts that start with ~ are not allowed
|
||||||
if ((typeof req.body.username != 'string') || (req.body.username.length < 1) || (req.body.username[0] == '~')) {
|
if ((typeof req.body.username != 'string') || (req.body.username.length < 1) || (req.body.username[0] == '~')) {
|
||||||
parent.debug('web', 'handleCreateAccountRequest: unable to create account (0)');
|
parent.debug('web', 'handleCreateAccountRequest: unable to create account (0)');
|
||||||
|
@ -1423,14 +1443,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||||
req.session.messageid = 102; // Existing account with this email address.
|
req.session.messageid = 102; // Existing account with this email address.
|
||||||
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
||||||
} else {
|
} else {
|
||||||
// Check if there is domain.newAccountToken, check if supplied token is valid
|
|
||||||
if ((domain.newaccountspass != null) && (domain.newaccountspass != '') && (req.body.anewaccountpass != domain.newaccountspass)) {
|
|
||||||
parent.debug('web', 'handleCreateAccountRequest: Invalid account creation token');
|
|
||||||
req.session.loginmode = 2;
|
|
||||||
req.session.messageid = 103; // Invalid account creation token.
|
|
||||||
if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check if user exists
|
// Check if user exists
|
||||||
if (obj.users['user/' + domain.id + '/' + req.body.username.toLowerCase()]) {
|
if (obj.users['user/' + domain.id + '/' + req.body.username.toLowerCase()]) {
|
||||||
parent.debug('web', 'handleCreateAccountRequest: Username already exists');
|
parent.debug('web', 'handleCreateAccountRequest: Username already exists');
|
||||||
|
@ -3054,20 +3066,29 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||||
twoFactorTimeout = domain.passwordrequirements.twofactortimeout * 1000;
|
twoFactorTimeout = domain.passwordrequirements.twofactortimeout * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup CAPTCHA if needed
|
||||||
|
var newAccountCaptcha = '', newAccountCaptchaImage = '';
|
||||||
|
if ((domain.newaccountscaptcha != null) && (domain.newaccountscaptcha !== false)) {
|
||||||
|
newAccountCaptcha = obj.parent.encodeCookie({ type: 'newAccount', captcha: require('svg-captcha').randomText(5) }, obj.parent.loginCookieEncryptionKey);
|
||||||
|
newAccountCaptchaImage = 'newAccountCaptcha.ashx?x=' + newAccountCaptcha;
|
||||||
|
}
|
||||||
|
|
||||||
// Render the login page
|
// Render the login page
|
||||||
render(req, res,
|
render(req, res,
|
||||||
getRenderPage((domain.sitestyle == 2) ? 'login2' : 'login', req, domain),
|
getRenderPage((domain.sitestyle == 2) ? 'login2' : 'login', req, domain),
|
||||||
getRenderArgs({
|
getRenderArgs({
|
||||||
loginmode: loginmode,
|
loginmode: loginmode,
|
||||||
rootCertLink: getRootCertLink(domain),
|
rootCertLink: getRootCertLink(domain),
|
||||||
newAccount: newAccountsAllowed,
|
newAccount: newAccountsAllowed, // True if new accounts are allowed from the login page
|
||||||
newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1),
|
newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), // 1 if new account creation requires password
|
||||||
|
newAccountCaptcha: newAccountCaptcha, // If new account creation requires a CAPTCHA, this string will not be empty
|
||||||
|
newAccountCaptchaImage: newAccountCaptchaImage, // Set to the URL of the CAPTCHA image
|
||||||
serverDnsName: obj.getWebServerName(domain),
|
serverDnsName: obj.getWebServerName(domain),
|
||||||
serverPublicPort: httpsPort,
|
serverPublicPort: httpsPort,
|
||||||
passlogin: (typeof domain.showpasswordlogin == 'boolean') ? domain.showpasswordlogin : true,
|
passlogin: (typeof domain.showpasswordlogin == 'boolean') ? domain.showpasswordlogin : true,
|
||||||
emailcheck: emailcheck,
|
emailcheck: emailcheck,
|
||||||
features: features,
|
features: features,
|
||||||
sessiontime: (args.sessiontime) ? args.sessiontime : 60,
|
sessiontime: (args.sessiontime) ? args.sessiontime : 60, // Session time in minutes, 60 minutes is the default
|
||||||
passRequirements: passRequirements,
|
passRequirements: passRequirements,
|
||||||
customui: customui,
|
customui: customui,
|
||||||
footer: (domain.loginfooter == null) ? '' : domain.loginfooter,
|
footer: (domain.loginfooter == null) ? '' : domain.loginfooter,
|
||||||
|
@ -3195,6 +3216,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle new account Captcha GET
|
||||||
|
function handleNewAccountCaptchaRequest(req, res) {
|
||||||
|
const domain = checkUserIpAddress(req, res);
|
||||||
|
if (domain == null) { return; }
|
||||||
|
if ((domain.newaccountscaptcha == null) || (domain.newaccountscaptcha === false) || (req.query.x == null)) { res.sendStatus(404); return; }
|
||||||
|
const c = obj.parent.decodeCookie(req.query.x, obj.parent.loginCookieEncryptionKey);
|
||||||
|
if ((c == null) || (c.type !== 'newAccount') || (typeof c.captcha != 'string')) { res.sendStatus(404); return; }
|
||||||
|
res.type('svg');
|
||||||
|
res.status(200).end(require('svg-captcha')(c.captcha, {}));
|
||||||
|
}
|
||||||
|
|
||||||
// Handle Captcha GET
|
// Handle Captcha GET
|
||||||
function handleCaptchaGetRequest(req, res) {
|
function handleCaptchaGetRequest(req, res) {
|
||||||
const domain = checkUserIpAddress(req, res);
|
const domain = checkUserIpAddress(req, res);
|
||||||
|
@ -6104,6 +6136,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||||
obj.app.get(url + 'pluginHandler.js', obj.handlePluginJS);
|
obj.app.get(url + 'pluginHandler.js', obj.handlePluginJS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New account CAPTCHA request
|
||||||
|
if ((domain.newaccountscaptcha != null) && (domain.newaccountscaptcha !== false)) {
|
||||||
|
obj.app.get(url + 'newAccountCaptcha.ashx', handleNewAccountCaptchaRequest);
|
||||||
|
}
|
||||||
|
|
||||||
// Check CrowdSec Bounser if configured
|
// Check CrowdSec Bounser if configured
|
||||||
if (parent.crowdSecBounser != null) {
|
if (parent.crowdSecBounser != null) {
|
||||||
obj.app.get(url + 'captcha.ashx', handleCaptchaGetRequest);
|
obj.app.get(url + 'captcha.ashx', handleCaptchaGetRequest);
|
||||||
|
|
Loading…
Reference in New Issue