Improved web interface for getting started.

This commit is contained in:
Ylian Saint-Hilaire 2017-10-02 14:12:29 -07:00
parent 72a4740f72
commit 5474f1d386
9 changed files with 263 additions and 127 deletions

View File

@ -71,7 +71,6 @@
<Content Include="public\images-isdu\info.gif" />
<Content Include="public\images-isdu\warning.gif" />
<Content Include="public\images-isdu\isdu.ico" />
<Content Include="public\styles\font-awesome\css\font-awesome.css" />
<Content Include="public\styles\font-awesome\css\font-awesome.min.css" />
<Content Include="public\styles\font-awesome\fonts\fontawesome-webfont.eot" />
<Content Include="public\styles\font-awesome\fonts\fontawesome-webfont.svg" />
@ -120,8 +119,6 @@
<Folder Include="public\images-isdu" />
<Folder Include="public\scripts\" />
<Folder Include="public\styles\" />
<Folder Include="public\styles\font-awesome\" />
<Folder Include="public\styles\font-awesome\css\" />
<Folder Include="public\styles\font-awesome\fonts\" />
<Folder Include="public\styles\font-awesome\less\" />
<Folder Include="public\styles\font-awesome\scss\" />

View File

@ -277,9 +277,9 @@ function createMeshCore(agent) {
else if (data.type == 'tunnel') { // Process a new tunnel connection request
if (data.value && data.sessionid) {
// Create a new tunnel object
//sendConsoleText(data.value);
sendConsoleText(data.value);
var xurl = getServerTargetUrlEx(data.value);
//sendConsoleText(xurl);
sendConsoleText(xurl);
if (xurl != null) {
var tunnel = http.request(http.parseUri(xurl));
tunnel.upgrade = onTunnelUpgrade;

View File

@ -38,24 +38,23 @@ module.exports.CertificateOperations = function () {
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 30);
if (addThumbPrintToName == true) { commonName += '-' + obj.pki.getPublicKeyFingerprint(cert.publicKey, { encoding: 'hex' }).substring(0, 6); }
var attrs = [ { name: 'commonName', value: commonName } ];
if (country != undefined) attrs.push({ name: 'countryName', value: country });
if (organization != undefined) attrs.push({ name: 'organizationName', value: organization });
if (country == undefined) { country = 'unknown'; }
if (organization == undefined) { organization = 'unknown'; }
var attrs = [{ name: 'commonName', value: commonName }, { name: 'organizationName', value: organization }, { name: 'countryName', value: country }];
cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.setExtensions([
{ name: 'basicConstraints', cA: true },
{
// Create a root certificate
cert.setExtensions([{
name: 'basicConstraints',
cA: true
}, {
name: 'nsCertType',
client: false,
server: false,
email: false,
objsign: false,
sslCA: true,
emailCA: false,
emailCA: true,
objCA: true
}
]);
}, {
name: 'subjectKeyIdentifier'
}]);
cert.sign(keys.privateKey, obj.forge.md.sha256.create());
return { cert: cert, key: keys.privateKey };
@ -136,7 +135,8 @@ module.exports.CertificateOperations = function () {
}
// Returns the web server TLS certificate and private key, if not present, create demonstration ones.
obj.GetMeshServerCertificate = function (directory, certargs, func) {
obj.GetMeshServerCertificate = function (directory, args, func) {
var certargs = args.cert;
// commonName, country, organization
// If the certificates directory does not exist, create it.
@ -152,15 +152,24 @@ module.exports.CertificateOperations = function () {
rcount++;
}
// If the web certificate already exist, load it
if (args.tlsoffload == true) {
// If the web certificate already exist, load it. Load just the certificate since we are in TLS offload situation
if (obj.fileExists(directory + '/webserver-cert-public.crt')) {
var webCertificate = obj.fs.readFileSync(directory + '/webserver-cert-public.crt', 'utf8');
r.web = { cert: webCertificate };
rcount++;
}
} else {
// If the web certificate already exist, load it. Load both certificate and private key
if (obj.fileExists(directory + '/webserver-cert-public.crt') && obj.fileExists(directory + '/webserver-cert-private.key')) {
var webCertificate = obj.fs.readFileSync(directory + '/webserver-cert-public.crt', 'utf8');
var webPrivateKey = obj.fs.readFileSync(directory + '/webserver-cert-private.key', 'utf8');
r.web = { cert: webCertificate, key: webPrivateKey };
rcount++;
}
}
// If the bin certificate already exist, load it
// If the mps certificate already exist, load it
if (obj.fileExists(directory + '/mpsserver-cert-public.crt') && obj.fileExists(directory + '/mpsserver-cert-private.key')) {
var mpsCertificate = obj.fs.readFileSync(directory + '/mpsserver-cert-public.crt', 'utf8');
var mpsPrivateKey = obj.fs.readFileSync(directory + '/mpsserver-cert-private.key', 'utf8');
@ -168,7 +177,7 @@ module.exports.CertificateOperations = function () {
rcount++;
}
// If the bin certificate already exist, load it
// If the agent certificate already exist, load it
if (obj.fileExists(directory + '/agentserver-cert-public.crt') && obj.fileExists(directory + '/agentserver-cert-private.key')) {
var agentCertificate = obj.fs.readFileSync(directory + '/agentserver-cert-public.crt', 'utf8');
var agentPrivateKey = obj.fs.readFileSync(directory + '/agentserver-cert-private.key', 'utf8');
@ -176,7 +185,7 @@ module.exports.CertificateOperations = function () {
rcount++;
}
// If the bin certificate already exist, load it
// If the console certificate already exist, load it
if (obj.fileExists(directory + '/amtconsole-cert-public.crt') && obj.fileExists(directory + '/agentserver-cert-private.key')) {
var amtConsoleCertificate = obj.fs.readFileSync(directory + '/amtconsole-cert-public.crt', 'utf8');
var amtConsolePrivateKey = obj.fs.readFileSync(directory + '/amtconsole-cert-private.key', 'utf8');
@ -198,7 +207,7 @@ module.exports.CertificateOperations = function () {
r.calist = calist;
// Decode certificate arguments
var commonName = 'un-configured', country, organization;
var commonName = 'un-configured', country, organization, forceWebCertGen = 0;
if (certargs != undefined) {
var args = certargs.split(',');
if (args.length > 0) commonName = args[0];
@ -220,7 +229,7 @@ module.exports.CertificateOperations = function () {
if (xcountryField != null) { xcountry = xcountryField.value; }
var xorganization, xorganizationField = webCertificate.subject.getField('O');
if (xorganizationField != null) { xorganization = xorganizationField.value; }
if ((r.CommonName == commonName) && (xcountry == country) && (xorganization == organization)) { if (func != undefined) { func(r); } return r; } // If the certificate matches what we want, keep it.
if ((r.CommonName == commonName) && (xcountry == country) && (xorganization == organization)) { if (func != undefined) { func(r); } return r; } else { forceWebCertGen = 1; } // If the certificate matches what we want, keep it.
}
console.log('Generating certificates...');
@ -242,7 +251,7 @@ module.exports.CertificateOperations = function () {
// If the web certificate does not exist, create one
var webCertAndKey, webCertificate, webPrivateKey;
if (r.web == undefined) {
if ((r.web == undefined) || (forceWebCertGen == 1)) {
webCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, commonName, country, organization);
webCertificate = obj.pki.certificateToPem(webCertAndKey.cert);
webPrivateKey = obj.pki.privateKeyToPem(webCertAndKey.key);

View File

@ -201,7 +201,11 @@ function CreateMeshCentralServer() {
var xdomains = {}; for (var i in obj.config.domains) { if (!obj.config.domains[i].title) { obj.config.domains[i].title = 'MeshCentral'; } if (!obj.config.domains[i].title2) { obj.config.domains[i].title2 = '2.0 Beta 1'; } xdomains[i.toLowerCase()] = obj.config.domains[i]; } obj.config.domains = xdomains;
var bannedDomains = ['public', 'private', 'images', 'scripts', 'styles', 'views']; // List of banned domains
for (var i in obj.config.domains) { for (var j in bannedDomains) { if (i == bannedDomains[j]) { console.log("ERROR: Domain '" + i + "' is not allowed domain name in ./data/config.json."); return; } } }
for (var i in obj.config.domains) { obj.config.domains[i].url = (i == '')?'/':('/' + i + '/'); obj.config.domains[i].id = i; }
for (var i in obj.config.domains) {
for (var j in obj.config.domains[i]) { obj.config.domains[i][j.toLocaleLowerCase()] = obj.config.domains[i][j]; } // LowerCase all domain keys
obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); obj.config.domains[i].id = i;
if (typeof obj.config.domains[i].userallowedip == 'string') { obj.config.domains[i].userallowedip = null; if (obj.config.domains[i].userallowedip != "") { obj.config.domains[i].userallowedip = obj.config.domains[i].userallowedip.split(','); } }
}
// Log passed arguments into Windows Service Log
//if (obj.servicelog != null) { var s = ''; for (var i in obj.args) { if (i != '_') { if (s.length > 0) { s += ', '; } s += i + "=" + obj.args[i]; } } logInfoEvent('MeshServer started with arguments: ' + s); }
@ -283,7 +287,7 @@ function CreateMeshCentralServer() {
obj.updateMeshCore();
// Load server certificates
obj.certificateOperations.GetMeshServerCertificate(obj.datapath, obj.args.cert, function (certs) {
obj.certificateOperations.GetMeshServerCertificate(obj.datapath, obj.args, function (certs) {
obj.certificates = certs;
// If the certificate is un-configured, force LAN-only mode

View File

@ -189,3 +189,97 @@ TypeError: Cannot read property 'SSL_OP_NO_SSLv2' of undefined
at Immediate._onImmediate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:498:34)
-------- 10/1/2017, 10:21:38 AM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:91
console.log(obj.servers4.keys());
^
TypeError: obj.servers4.keys is not a function
at setupServers (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:91:34)
at Object.obj.start (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:136:9)
at InternalFieldObject.ondone (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshcentral.js:328:98)
-------- 10/1/2017, 10:21:40 AM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:91
console.log(obj.servers4.keys());
^
TypeError: obj.servers4.keys is not a function
at setupServers (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:91:34)
at Object.obj.start (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:136:9)
at InternalFieldObject.ondone (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshcentral.js:328:98)
-------- 10/1/2017, 10:54:43 AM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:96
performScan(server6);
^
ReferenceError: performScan is not defined
at Socket.<anonymous> (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:96:21)
at Socket.g (events.js:286:16)
at emitNone (events.js:86:13)
at Socket.emit (events.js:185:7)
at startListening (dgram.js:121:10)
at dgram.js:228:7
at _combinedTickCallback (internal/process/next_tick.js:77:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
-------- 10/1/2017, 10:54:45 AM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:96
performScan(server6);
^
ReferenceError: performScan is not defined
at Socket.<anonymous> (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:96:21)
at Socket.g (events.js:286:16)
at emitNone (events.js:86:13)
at Socket.emit (events.js:185:7)
at startListening (dgram.js:121:10)
at dgram.js:228:7
at _combinedTickCallback (internal/process/next_tick.js:77:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
-------- 10/1/2017, 10:54:47 AM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:96
performScan(server6);
^
ReferenceError: performScan is not defined
at Socket.<anonymous> (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshscanner.js:96:21)
at Socket.g (events.js:286:16)
at emitNone (events.js:86:13)
at Socket.emit (events.js:185:7)
at startListening (dgram.js:121:10)
at dgram.js:228:7
at _combinedTickCallback (internal/process/next_tick.js:77:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
-------- 10/1/2017, 11:49:12 AM --------
C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\node-forge\js\x509.js:2052
throw error;
^
Error: Attribute value not specified.
at _fillMissingFields (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\node-forge\js\x509.js:2050:19)
at Object.cert.setSubject (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\node-forge\js\x509.js:948:5)
at Object.obj.GenerateRootCertificate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\certoperations.js:44:14)
at Object.obj.GetMeshServerCertificate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\certoperations.js:230:34)
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\meshcentral.js:286:43
at newArguments.(anonymous function) (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\executor.js:29:17)
at Cursor.execFn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:484:12)
at callback (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:126:19)
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:193:12
at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:329:14

View File

@ -22,8 +22,7 @@ module.exports.CreateMeshScanner = function (parent) {
// Get a list of IPv4 and IPv6 interface addresses
function getInterfaceList() {
var ipv4 = [];
var ipv6 = [];
var ipv4 = ['*'], ipv6 = ['*'];
var interfaces = require('os').networkInterfaces();
for (var i in interfaces) {
var interface = interfaces[i];
@ -50,25 +49,32 @@ module.exports.CreateMeshScanner = function (parent) {
obj.servers4[localAddress].xxclear = false;
} else {
// Create a new IPv4 server
try {
var server4 = obj.dgram.createSocket("udp4");
server4.xxclear = false;
server4.xxtype = 4;
server4.xxlocal = localAddress;
server4.on('error', function (err) { console.log("ERROR: Server port " + server4.xxlocal + ":16989 not available, check if server is running twice."); server4.close(); server4 = null; });
server4.bind({ address: server4.xxlocal, port: 16989, exclusive: false }, function () {
var bindOptions = { port: 16989, exclusive: false };
if (server4.xxlocal != '*') { bindOptions.address = server4.xxlocal; }
server4.bind(bindOptions, function () {
try {
server4.setBroadcast(true);
server4.setMulticastTTL(128);
server4.addMembership(membershipIPv4);
this.setBroadcast(true);
this.setMulticastTTL(128);
this.addMembership(membershipIPv4);
server4.on('error', function (error) { console.log('Error: ' + error); });
server4.on('message', function (msg, info) { onUdpPacket(msg, info, server4); });
obj.performScan(server4);
obj.performScan(server4);
obj.performScan(this);
obj.performScan(this);
} catch (e) { }
});
obj.servers4[localAddress] = server4;
} catch (e) {
console.log(e);
}
}
}
for (var i in addresses.ipv6) {
var localAddress = addresses.ipv6[i];
if (obj.servers6[localAddress] != null) {
@ -81,15 +87,17 @@ module.exports.CreateMeshScanner = function (parent) {
server6.xxtype = 6;
server6.xxlocal = localAddress;
server6.on('error', function (err) { console.log("ERROR: Server port [" + server6.xxlocal + "]:16989 not available, check if server is running twice."); server6.close(); obj.server6 = null; });
server6.bind({ address: server6.xxlocal, port: 16989, exclusive: false }, function () {
var bindOptions = { port: 16989, exclusive: false };
if (server6.xxlocal != '*') { bindOptions.address = server6.xxlocal; }
server6.bind(bindOptions, function () {
try {
server6.setBroadcast(true);
server6.setMulticastTTL(128);
server6.addMembership(membershipIPv6);
server6.on('error', function (error) { console.log('Error: ' + error); });
server6.on('message', function (msg, info) { onUdpPacket(msg, info, server6); });
performScan(server6);
performScan(server6);
this.setBroadcast(true);
this.setMulticastTTL(128);
this.addMembership(membershipIPv6);
this.on('error', function (error) { console.log('Error: ' + error); });
this.on('message', function (msg, info) { onUdpPacket(msg, info, this); });
obj.performScan(this);
obj.performScan(this);
} catch (e) { }
});
obj.servers6[localAddress] = server6;
@ -128,6 +136,8 @@ module.exports.CreateMeshScanner = function (parent) {
if (server != null) {
if (server.xxtype == 4) { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); }
if (server.xxtype == 6) { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); }
if ((server.xxtype == 4) && (server.xxlocal == '*')) { server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, '127.0.0.1'); server.send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, '255.255.255.255'); }
if ((server.xxtype == 6) && (server.xxlocal == '*')) { server.send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, '::1'); }
} else {
for (var i in obj.servers4) { obj.servers4[i].send(obj.multicastPacket4, 0, obj.multicastPacket4.length, 16990, membershipIPv4); }
for (var i in obj.servers6) { obj.servers6[i].send(obj.multicastPacket6, 0, obj.multicastPacket6.length, 16990, membershipIPv6); }

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.0.8-g",
"version": "0.0.8-j",
"keywords": [
"Remote Management",
"Intel AMT",

View File

@ -119,7 +119,7 @@
<div class="auto-style1" style="height: 100%; float: right">
<div style="height:100%;width:4px;float:right;background-color:#ffffff"></div>
<div class=h2 style="height:100%;float:right">&nbsp;</div>
<div style=float:right>
<div style=float:right id=devListToolbarView>
View
<select id=viewselect onchange=onDeviceViewChange()>
<option value=1>3 wide</option>
@ -138,18 +138,17 @@
</div>
</div>
</div>
<div id=NoNodesPanel style=display:none>
<table style="width: 100%">
<div id=NoMeshesPanel style=display:none>
<table style="width:100%;padding:20px">
<tr>
<td valign="top" style="width: 50px">
<img src="images/info.png" height="48" width="47" />
</td>
<td>
No nodes found with this search criteria. To create a mesh network and add devices, start at the <a onclick=go(2) style="cursor:pointer">My Account</a> page.
To get started managing devices, <a onclick=account_createMesh() style=cursor:pointer><strong>click here to create a new group of devices called a Mesh</strong></a>.
</td>
</tr>
</table>
<p></p>
</div>
<div id="xdevices" style="max-height:calc(100vh - 228px);overflow-y:auto;-webkit-overflow-scrolling:touch"></div>
<div id="xdevicesmap" style="height:500px;width:100%;overflow:hidden;position:relative">
@ -184,7 +183,7 @@
( <a onclick=account_createMesh() style=cursor:pointer><img height=12 src="images/icon-addnew.png" width=12 border=0 /> New</a> )
<br /><br />
<div id=p2meshes></div>
<div id=p2noMeshFound style=margin-left:40px;display:none>No meshes found. <a onclick=account_createMesh() style=cursor:pointer><strong>Get started here!</strong></a><br /><br /></div>
<div id=p2noMeshFound style=margin-left:40px;display:none>No meshes. <a onclick=account_createMesh() style=cursor:pointer><strong>Get started here!</strong></a><br /><br /></div>
</div>
<div id=p3 style=display:none>
<h1>My Events</h1>
@ -406,13 +405,13 @@
<td style="width:100%;background-color:#d3d9d6;text-align:left;padding:4px" valign=bottom>
<div id="p13rightOfButtons" style="float:right;margin-top:3px"></div>
<div>
<input type=button id="p13FolderUp" disabled="disabled" onclick="p13folderup()" value="Up" />&nbsp;
<input type=button id="p13SelectAllButton" disabled="disabled" onclick="p13selectallfile()" value="Select All" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id="p13RenameFileButton" disabled="disabled" value="Rename" onclick="p13renamefile()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id="p13DeleteFileButton" disabled="disabled" value="Delete" onclick="p13deletefile()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id="p13NewFolderButton" disabled="disabled" value="New Folder" onclick="p13createfolder()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id="p13UploadButton" disabled="disabled" value="Upload" onclick="p13uploadFile()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id="p13RefreshButton" disabled="disabled" value="Refresh" onclick="p13folderup(9999)" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id=p13FolderUp disabled="disabled" onclick="p13folderup()" value="Up" />&nbsp;
<input type=button id=p13SelectAllButton disabled="disabled" onclick="p13selectallfile()" value="Select All" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id=p13RenameFileButton disabled="disabled" value="Rename" onclick="p13renamefile()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id=p13DeleteFileButton disabled="disabled" value="Delete" onclick="p13deletefile()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id=p13NewFolderButton disabled="disabled" value="New Folder" onclick="p13createfolder()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id=p13UploadButton disabled="disabled" value="Upload" onclick="p13uploadFile()" onkeypress="return false" onkeydown="return false" />&nbsp;
<input type=button id=p13RefreshButton disabled="disabled" value="Refresh" onclick="p13folderup(9999)" onkeypress="return false" onkeydown="return false" />&nbsp;
</div>
</td>
</tr>
@ -602,6 +601,7 @@
var showHostnames = false;
var meshserver = null;
var meshes = {};
var meshcount = 0;
var nodes = [];
var filetree = {};
var userinfo = null;
@ -1195,8 +1195,11 @@
QV('devListToolbar', view < 3);
QV('devMapToolbar', view == 3);
QV('devListToolbarSort', view < 3);
QV('NoMeshesPanel', meshcount == 0);
QV('devListToolbarView', (meshcount != 0) && (nodes.length > 0));
QV('devListToolbarSort', (meshcount != 0) && (nodes.length > 0));
if ((meshcount == 0) || (nodes.length == 0)) { view = 1; }
if (view == 3) {
QV('NoNodesPanel',false); //Hide NoNodesPanel user views Map
setTimeout( function() { if (xxmap.map != null) { xxmap.map.updateSize(); } }, 200);
// TODO
} else {
@ -1300,9 +1303,12 @@
}
r += '</tr></table><div style=height:1px></div>'; // This height of 1 div fixes a problem in Linux firefox browsers
// Add a "Add Mesh" option
if (view == 1) { r += '<div style=border-top-style:solid;border-top-width:1px;border-top-color:#DDDDDD;cursor:pointer;font-size:10px title="Create a new group of computers."><a onclick=account_createMesh() style=cursor:pointer>Add Mesh</a></div>'; }
QH('xdevices', r);
deviceHeaderSet();
QV('NoNodesPanel', count == 0);
//QV('NoMeshesPanel', count == 0);
// Re-check nodeid's
var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
@ -1671,7 +1677,6 @@
markersLayer: null,
mapLayer: null, // Create a tile and use OSM source
mapView: null, // Sets the initial view
selectedNodes: {} // Save details of Node that was selected from 'Put a node' option from contextmenu
}
// Add a feature for every Node and change style if connection status changes
@ -3642,6 +3647,7 @@
}
r += '</tr></table>';
meshcount = count;
QH('p2meshes', r);
QV('p2noMeshFound', count == 0);
}

View File

@ -138,7 +138,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
for (var i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; }
for (var i in parent.config.domains) {
if (domainUserCount[i] == 0) {
if (parent.config.domains[i].newAccounts == 0) { parent.config.domains[i].newAccounts = 2; }
if (parent.config.domains[i].newaccounts == 0) { parent.config.domains[i].newaccounts = 2; }
console.log('Server ' + ((i == '') ? '' : (i + ' ')) + 'has no users, next new account will be site administrator.');
}
}
@ -178,22 +178,35 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
}
*/
// Check if the source IP address is allowed, return false if not
function checkUserIpAddress(req, res) {
if (obj.userAllowedIp == null) { return true; }
// Check if the source IP address is allowed for a given allowed list, return false if not
function checkUserIpAddressEx(req, res, allowedIpList) {
if (allowedIpList == null) { return true; }
try {
if (typeof obj.userAllowedIp == 'string') { if (obj.userAllowedIp == "") { obj.userAllowedIp = null; return true; } else { obj.userAllowedIp = obj.userAllowedIp.split(','); } }
var ip = null, type = 0;
if (req.connection) { ip = req.connection.remoteAddress; type = 1; } // HTTP(S) request
else if (req._socket) { ip = req._socket.remoteAddress; type = 2; } // WebSocket request
if (ip.startsWith('::ffff:')) { ip = ip.substring(7); } // Fix IPv4 IP's encoded in IPv6 form
if ((ip != null) && (obj.userAllowedIp.indexOf(ip) >= 0)) { return true; }
if ((ip != null) && (allowedIpList.indexOf(ip) >= 0)) { return true; }
if (type == 1) { res.sendStatus(401); }
else if (type == 2) { try { req.close(); } catch (e) { } }
} catch (e) { console.log(e); }
return false;
}
// Check if the source IP address is allowed, return domain if allowed
function checkUserIpAddress(req, res, rootonly) {
if (obj.userAllowedIp != null) {
if (typeof obj.userAllowedIp == 'string') { if (obj.userAllowedIp == "") { obj.userAllowedIp = null; return true; } else { obj.userAllowedIp = obj.userAllowedIp.split(','); } }
if (checkUserIpAddressEx(req, res, obj.userAllowedIp) == false) return null;
}
if (rootonly == true) return;
var domain;
if (req.url) { domain = getDomain(req); } else { domain = getDomain(res); }
if (domain.userallowedip == null) return domain;
if (checkUserIpAddressEx(req, res, domain.userallowedip) == false) return null;
return domain;
}
// Return the current domain of the request
function getDomain(req) {
var x = req.url.split('/');
@ -203,8 +216,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
}
function handleLogoutRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
// Destroy the user's session to log them out will be re-created next request
if (req.session.userid) {
@ -217,8 +230,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
}
function handleLoginRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
obj.authenticate(req.body.username, req.body.password, domain, function (err, userid, passhint) {
if (userid) {
var user = obj.users[userid];
@ -269,16 +282,16 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
}
function handleCreateAccountRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
if (domain.newAccounts == 0) { res.sendStatus(401); return; }
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
if (domain.newaccounts == 0) { res.sendStatus(401); return; }
if (!req.body.username || !req.body.email || !req.body.password1 || !req.body.password2 || (req.body.password1 != req.body.password2) || req.body.username == '~') {
req.session.loginmode = 2;
req.session.error = '<b style=color:#8C001A>Unable to create account.</b>';;
res.redirect(domain.url);
} else {
// Check if there is domain.newAccountToken, check if supplied token is valid
if ((domain.newAccountsPass != null) && (domain.newAccountsPass != '') && (req.body.anewaccountpass != domain.newAccountsPass)) {
if ((domain.newaccountspass != null) && (domain.newaccountspass != '') && (req.body.anewaccountpass != domain.newaccountspass)) {
req.session.loginmode = 2;
req.session.error = '<b style=color:#8C001A>Invalid account creation token.</b>';
res.redirect(domain.url);
@ -294,7 +307,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
var user = { type: 'user', _id: 'user/' + domain.id + '/' + req.body.username.toLowerCase(), name: req.body.username, email: req.body.email, creation: Date.now(), login: Date.now(), domain: domain.id, passhint: hint };
var usercount = 0;
for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
if (usercount == 0) { user.siteadmin = 0xFFFFFFFF; if (domain.newAccounts == 2) { domain.newAccounts = 0; } } // If this is the first user, give the account site admin.
if (usercount == 0) { user.siteadmin = 0xFFFFFFFF; if (domain.newaccounts == 2) { domain.newaccounts = 0; } } // If this is the first user, give the account site admin.
obj.users[user._id] = user;
req.session.userid = user._id;
req.session.domainid = domain.id;
@ -312,8 +325,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
}
function handleDeleteAccountRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
// Check if the user is logged and we have all required parameters
if (!req.session || !req.session.userid || !req.body.apassword1 || (req.body.apassword1 != req.body.apassword2) || (req.session.domainid != domain.id)) { res.redirect(domain.url); return; }
var user = obj.users[req.session.userid];
@ -335,8 +348,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle password changes
function handlePasswordChangeRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
// Check if the user is logged and we have all required parameters
if (!req.session || !req.session.userid || !req.body.apassword1 || (req.body.apassword1 != req.body.apassword2) || (req.session.domainid != domain.id)) { res.redirect(domain.url); return; }
@ -359,7 +372,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Indicates that any request to "/" should render "default" or "login" depending on login state
function handleRootRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
if (!obj.args) { res.sendStatus(500); return; }
var domain = getDomain(req);
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
@ -412,7 +426,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
res.render(obj.path.join(__dirname, 'views/default'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.certificates.CommonName, serverPublicPort: args.port, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, mpspass: args.mpspass });
} else {
// Send back the login application
res.render(obj.path.join(__dirname, 'views/login'), { loginmode: req.session.loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newAccounts, newAccountPass: (((domain.newAccountsPass == null) || (domain.newAccountsPass == ''))?0:1), serverDnsName: obj.certificates.CommonName, serverPublicPort: obj.args.port });
res.render(obj.path.join(__dirname, 'views/login'), { loginmode: req.session.loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == ''))?0:1), serverDnsName: obj.certificates.CommonName, serverPublicPort: obj.args.port });
}
}
@ -425,8 +439,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Renter the terms of service.
function handleTermsRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
if (req.session && req.session.userid) {
if (req.session.domainid != domain.id) { req.session.destroy(function () { res.redirect(domain.url); }); return; } // Check is the session is for the correct domain
@ -449,14 +463,14 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Returns the mesh server root certificate
function handleRootCertRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
if (checkUserIpAddress(req, res, true) == false) { return; }
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + certificates.RootName + '.cer' });
res.send(new Buffer(getRootCertBase64(), 'base64'));
}
// Returns an mescript for Intel AMT configuration
function handleMeScriptRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
if (checkUserIpAddress(req, res, true) == false) { return; }
if (req.query.type == 1) {
var filename = 'cira_setup.mescript';
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + filename });
@ -527,8 +541,9 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle user public file downloads
function handleDownloadUserFiles(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req), domainname = 'domain', spliturl = decodeURIComponent(req.path).split('/'), filename = '';
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
var domainname = 'domain', spliturl = decodeURIComponent(req.path).split('/'), filename = '';
if ((spliturl.length < 3) || (obj.common.IsFilenameValid(spliturl[2]) == false) || (domain.userQuota == -1)) { res.sendStatus(404); return; }
if (domain.id != '') { domainname = 'domain-' + domain.id; }
var path = obj.path.join(obj.filespath, domainname + "/user-" + spliturl[2] + "/Public");
@ -550,8 +565,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Download a file from the server
function handleDownloadFile(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
if ((req.query.link == null) || (req.session == null) || (req.session.userid == null) || (domain == null) || (domain.userQuota == -1)) { res.sendStatus(404); return; }
var user = obj.users[req.session.userid];
if (user == null) { res.sendStatus(404); return; }
@ -563,8 +578,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Upload a MeshCore.js file to the server
function handleUploadMeshCoreFile(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; }
var user = obj.users[req.session.userid];
if (user.siteadmin != 0xFFFFFFFF) { res.sendStatus(401); return; } // Check if we have mesh core upload rights (Full admin only)
@ -588,8 +603,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Upload a file to the server
function handleUploadFile(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid) || (domain.userQuota == -1)) { res.sendStatus(401); return; }
var user = obj.users[req.session.userid];
if ((user.siteadmin & 8) == 0) { res.sendStatus(401); return; } // Check if we have file rights
@ -650,8 +665,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle a web socket relay request
function handleRelayWebSocket(ws, req) {
if (checkUserIpAddress(ws, req) == false) { return; }
var node, domain = getDomain(req);
var domain = checkUserIpAddress(ws, req);
if (domain == null) return;
// Check if this is a logged in user
var user, peering = true;
if (req.query.auth == null) {
@ -677,7 +692,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Fetch information about the target
obj.db.Get(req.query.host, function (err, docs) {
if (docs.length == 0) { console.log('ERR: Node not found'); return; }
node = docs[0];
var node = docs[0];
if (!node.intelamt) { console.log('ERR: Not AMT node'); return; }
// Check if this user has permission to manage this computer
@ -915,7 +930,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle the web socket echo request, just echo back the data sent
function handleEchoWebSocket(ws, req) {
if (checkUserIpAddress(ws, req) == false) { return; }
var domain = checkUserIpAddress(ws, req);
if (domain == null) return;
// When data is received from the web socket, echo it back
ws.on('message', function (data) {
@ -968,8 +984,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Indicates we want to handle websocket requests on "/control.ashx".
function handleControlRequest(ws, req) {
if (checkUserIpAddress(ws, req) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(ws, req);
if (domain == null) return;
try {
// Check if the user is logged in
if ((!req.session) || (!req.session.userid) || (req.session.domainid != domain.id)) { try { ws.close(); } catch (e) { } return; }
@ -1840,8 +1856,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle a server backup request
function handleBackupRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid) || (obj.parent.args.noserverbackup == 1)) { res.sendStatus(401); return; }
var user = obj.users[req.session.userid];
if ((user.siteadmin & 1) == 0) { res.sendStatus(401); return; } // Check if we have server backup rights
@ -1873,8 +1889,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle a server restore request
function handleRestoreRequest(req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid) || (obj.parent.args.noserverbackup == 1)) { res.sendStatus(401); return; }
var user = obj.users[req.session.userid];
if ((user.siteadmin & 4) == 0) { res.sendStatus(401); return; } // Check if we have server restore rights
@ -1918,8 +1934,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
// Handle a request to download a mesh settings
obj.handleMeshSettingsRequest = function (req, res) {
if (checkUserIpAddress(req, res) == false) { return; }
var domain = getDomain(req);
var domain = checkUserIpAddress(req, res);
if (domain == null) return;
//if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; }
// Delete a mesh and all computers within it