Refactor meshuser - serverconsome cmd handlers
Noah Zalev committed
Jul 7, 2021 at 20:44 UTC
2addeb78a9644c135f74bf31c2d9ef8eddebc81d
1 file changed
+691
-545
meshuser.js
+691
-545
@@ -544,6 +544,690 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
544
});
545
} catch (e) { console.log(e); }
546
547
+
548
+ var consoleCommands = {};
549
+ consoleCommands['help'] = helpConsoleCommand;
550
+ consoleCommands['certexpire'] = certexpireConsoleCommand;
551
+ consoleCommands['webpush'] = webpushConsoleCommand;
552
+ consoleCommands['amtmanager'] = amtmanagerConsoleCommand;
553
+ consoleCommands['certhashes'] = certhashesConsoleCommand;
554
+ consoleCommands['amtacm'] = amtacmConsoleCommand;
555
+ consoleCommands['heapdump'] = heapdumpConsoleCommand;
556
+ consoleCommands['heapdump2'] = heapdump2ConsoleCommand;
557
+ consoleCommands['sms'] = smsConsoleCommand;
558
+ consoleCommands['email'] = emailConsoleCommand;
559
+ consoleCommands['le'] = leConsoleCommand;
560
+ consoleCommands['lecheck'] = lecheckConsoleCommand;
561
+ consoleCommands['leevents'] = leeventsConsoleCommand;
562
+ consoleCommands['badlogins'] = badloginsConsoleCommand;
563
+ consoleCommands['dispatchtable'] = dispatchtableConsoleCommand;
564
+ consoleCommands['dupagents'] = dupagentsConsoleCommand;
565
+ consoleCommands['agentstats'] = agentstatsConsoleCommand;
566
+ consoleCommands['agentissues'] = agentissuesConsoleCommand;
567
+ consoleCommands['webstats'] = webstatsConsoleCommand;
568
+ consoleCommands['trafficstats'] = trafficstatsConsoleCommand;
569
+ consoleCommands['trafficdelta'] = trafficdeltaConsoleCommand;
570
+ consoleCommands['watchdog'] = watchdogConsoleCommand;
571
+ consoleCommands['acceleratorsstats'] = acceleratorsstatsConsoleCommand;
572
+ consoleCommands['mpsstats'] = mpsstatsConsoleCommand;
573
+ consoleCommands['mps'] = mpsConsoleCommand;
574
+ consoleCommands['dbstats'] = dbstatsConsoleCommand;
575
+ consoleCommands['dbcounters'] = dbcountersConsoleCommand;
576
+ consoleCommands['serverupdate'] = serverupdateConsoleCommand;
577
+ consoleCommands['print'] = printConsoleCommand;
578
+ consoleCommands['amtpasswords'] = amtpasswordsConsoleCommand;
579
+ consoleCommands['updatecheck'] = updatecheckConsoleCommand;
580
+ consoleCommands['maintenance'] = maintenanceConsoleCommand;
581
+ consoleCommands['info'] = infoConsoleCommand;
582
+ consoleCommands['nodeconfig'] = nodeconfigConsoleCommand;
583
+ consoleCommands['versions'] = versionsConsoleCommand;
584
+ consoleCommands['args'] = argsConsoleCommand;
585
+ consoleCommands['usersessions'] = usersessionsConsoleCommand;
586
+ consoleCommands['closeusersessions'] = closeusersessionsConsoleCommand;
587
+ consoleCommands['resetserver'] = resetserverConsoleCommand;
588
+ consoleCommands['tasklimiter'] = tasklimiterConsoleCommand;
589
+ consoleCommands['setmaxtasks'] = setmaxtasksConsoleCommand;
590
+ consoleCommands['cores'] = coresConsoleCommand;
591
+ consoleCommands['showpaths'] = showpathsConsoleCommand;
592
+ consoleCommands['migrationagents'] = migrationagentsConsoleCommand;
593
+ consoleCommands['swarmstats'] = swarmstatsConsoleCommand;
594
+ consoleCommands['relays'] = relaysConsoleCommand;
595
+ consoleCommands['autobackup'] = autobackupConsoleCommand;
596
+ consoleCommands['backupconfig'] = backupconfigConsoleCommand;
597
+ consoleCommands['firebase'] = firebaseConsoleCommand;
598
+
599
+
600
+ function helpConsoleCommand(cmdargs) {
601
+ var r = '', fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,trafficstats,trafficdelta,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager,amtpasswords,certexpire,email';
602
+ if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; }
603
+ availcommands = availcommands.split(',').sort();
604
+ while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); }
605
+ if (f != '') { fin += f; }
606
+ if (cmdargs['_'].length == 0) {
607
+ r = 'Available commands: \r\n' + fin + '\r\nType help <command> for details.';
608
+ } else {
609
+ var cmd2 = cmdargs['_'][0].toLowerCase();
610
+ switch (cmd2) {
611
+ case 'info': { r = "info: Returns the most immidiatly useful information about this server, including MeshCentral and NodeJS versions. This is often information required to file a bug."; break; }
612
+ case 'versions': { r = "versions: Returns all internal versions for NodeJS running this server."; break; }
613
+ case 'resetserver': { r = "resetserver: Causes the server to reset, this is sometimes useful is the config.json file was changed."; break; }
614
+ case 'usersessions': { r = "usersessions: Returns a list of active sessions grouped by user."; break; }
615
+ case 'closeusersessions': { r = "closeusersessions: Disconnects all sessions for a specified user."; break; }
616
+ case 'tasklimiter': { r = "tasklimiter: Returns the internal status of the tasklimiter. This is a system used to smooth out work done by the server. It's used by, for example, agent updates so that not all agents are updated at the same time."; break; }
617
+ case 'serverupdate': { r = "serverupdate: Updates server to latest version. Optional version argument to install specific version. Example: serverupdate 0.8.49"; break; }
618
+ default: { r = 'No help information about this command.'; break; }
619
+ }
620
+ }
621
+ return r;
622
+ }
623
+
624
+ function certexpireConsoleCommand(command, cmdargs) {
625
+ var r = '';
626
+ const now = Date.now();
627
+ for (var i in parent.webCertificateExpire) {
628
+ const domainName = (i == '') ? '[Default]' : i;
629
+ r += domainName + ', expires in ' + Math.floor((parent.webCertificateExpire[i] - now) / 86400000) + ' day(s)\r\n';
630
+ }
631
+ return r;
632
+ }
633
+
634
+ function webpushConsoleCommand(command, cmdargs) {
635
+ var r = '';
636
+ if (parent.parent.webpush == null) {
637
+ r = "Web push not supported.";
638
+ } else {
639
+ if (cmdargs['_'].length != 1) {
640
+ r = "Usage: WebPush \"Message\"";
641
+ } else {
642
+ const pushSubscription = { "endpoint": "https://updates.push.services.mozilla.com/wpush/v2/gAAAAABgIkO9hjXHWhMPiuk-ppNRw7r_pUZitddwCEK4ykdzeIxOIjFnYhIt_nr-qUca2mpZziwQsSEhYTUCiuYrhWnVDRweMtiUj16yJJq8V5jneaEaUYjEIe5jp3DOMNpoTm1aHgX74gCR8uTXSITcM97bNi-hRxcQ4f6Ie4WSAmoXpd89B_g", "keys": { "auth": "UB2sbLVK7ALnSHw5P1dahg", "p256dh": "BIoRbcNSxBuTjN39CCCUCHo1f4NxBJ1YDdu_k4MbPW_q3NK1_RufnydUzLPDp8ibBVItSI72-s48QJvOjQ_S8Ok" } }
643
+ parent.parent.webpush.sendNotification(pushSubscription, cmdargs['_'][0]).then(
644
+ function (value) { try { ws.send(JSON.stringify({ action: 'OK', value: r, tag: command.tag })); } catch (ex) { } },
645
+ function (error) { try { ws.send(JSON.stringify({ action: 'Error', value: r, tag: command.tag })); } catch (ex) { } }
646
+ );
647
+ }
648
+ }
649
+ return r;
650
+ }
651
+
652
+ function amtmanagerConsoleCommand(command, cmdargs) {
653
+ var r = '';
654
+ if (parent.parent.amtManager == null) {
655
+ r = 'Intel AMT Manager not active.';
656
+ } else {
657
+ r = parent.parent.amtManager.getStatusString();
658
+ }
659
+ return r;
660
+ }
661
+
662
+ function certhashesConsoleCommand(command, cmdargs) {
663
+ var r = '';
664
+ r += 'AgentCertHash: ' + parent.agentCertificateHashHex;
665
+ for (var i in parent.webCertificateHashs) { r += '\r\nwebCertificateHash (' + i + '): ' + common.rstr2hex(parent.webCertificateHashs[i]); }
666
+ for (var i in parent.webCertificateFullHashs) { r += '\r\nwebCertificateFullHash (' + i + '): ' + common.rstr2hex(parent.webCertificateFullHashs[i]); }
667
+ r += '\r\ndefaultWebCertificateHash: ' + common.rstr2hex(parent.defaultWebCertificateHash);
668
+ r += '\r\ndefaultWebCertificateFullHash: ' + common.rstr2hex(parent.defaultWebCertificateFullHash);
669
+ return r;
670
+ }
671
+
672
+ function amtacmConsoleCommand(command, cmdargs) {
673
+ var r = '';
674
+ if ((domain.amtacmactivation == null) || (domain.amtacmactivation.acmmatch == null) || (domain.amtacmactivation.acmmatch.length == 0)) {
675
+ r = 'No Intel AMT activation certificates.';
676
+ } else {
677
+ if (domain.amtacmactivation.log != null) { r += '--- Activation Log ---\r\nFile : ' + domain.amtacmactivation.log + '\r\n'; }
678
+ for (var i in domain.amtacmactivation.acmmatch) {
679
+ var acmcert = domain.amtacmactivation.acmmatch[i];
680
+ r += '--- Activation Certificate ' + (parseInt(i) + 1) + ' ---\r\nName : ' + acmcert.cn + '\r\nSHA1 : ' + acmcert.sha1 + '\r\nSHA256: ' + acmcert.sha256 + '\r\n';
681
+ }
682
+ }
683
+ return r;
684
+ }
685
+
686
+ function heapdumpConsoleCommand(command, cmdargs) {
687
+ var r = '';
688
+ // Heapdump support, see example at:
689
+ // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/
690
+ if (parent.parent.config.settings.heapdump === true) {
691
+ var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`);
692
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { }
693
+ require('heapdump').writeSnapshot(dumpFileName, (err, filename) => {
694
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { }
695
+ });
696
+ } else {
697
+ r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json.";
698
+ }
699
+ return r;
700
+ }
701
+
702
+ function heapdump2ConsoleCommand(command, cmdargs) {
703
+ var r = '';
704
+ var heapdump = null;
705
+ try { heapdump = require('heapdump'); } catch (ex) { }
706
+ if (heapdump == null) {
707
+ r = 'Heapdump module not installed, run "npm install heapdump".';
708
+ } else {
709
+ heapdump.writeSnapshot(function (err, filename) {
710
+ if (err != null) {
711
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Unable to write heapdump: ' + err })); } catch (ex) { }
712
+ } else {
713
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Wrote heapdump at ' + filename })); } catch (ex) { }
714
+ }
715
+ });
716
+ }
717
+ return r;
718
+ }
719
+
720
+ function smsConsoleCommand(command, cmdargs) {
721
+ var r = '';
722
+ if (parent.parent.smsserver == null) {
723
+ r = "No SMS gateway in use.";
724
+ } else {
725
+ if (cmdargs['_'].length != 2) {
726
+ r = "Usage: SMS \"PhoneNumber\" \"Message\".";
727
+ } else {
728
+ parent.parent.smsserver.sendSMS(cmdargs['_'][0], cmdargs['_'][1], function (status, msg) {
729
+ if (typeof msg == 'string') {
730
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? ('Success: ' + msg) : ('Failed: ' + msg), tag: command.tag })); } catch (ex) { }
731
+ } else {
732
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? 'Success' : 'Failed', tag: command.tag })); } catch (ex) { }
733
+ }
734
+ });
735
+ }
736
+ }
737
+ return r;
738
+ }
739
+
740
+ function emailConsoleCommand(command, cmdargs) {
741
+ var r = '';
742
+ if (domain.mailserver == null) {
743
+ r = "No email service enabled.";
744
+ } else {
745
+ if (cmdargs['_'].length != 3) {
746
+ r = "Usage: email \"user@sample.com\" \"Subject\" \"Message\".";
747
+ } else {
748
+ domain.mailserver.sendMail(cmdargs['_'][0], cmdargs['_'][1], cmdargs['_'][2]);
749
+ r = "Done.";
750
+ }
751
+ }
752
+ return r;
753
+ }
754
+
755
+ function leConsoleCommand(command, cmdargs) {
756
+ var r = '';
757
+ if (parent.parent.letsencrypt == null) {
758
+ r = "Let's Encrypt not in use.";
759
+ } else {
760
+ r = JSON.stringify(parent.parent.letsencrypt.getStats(), null, 4);
761
+ }
762
+ return r;
763
+ }
764
+
765
+ function lecheckConsoleCommand(command, cmdargs) {
766
+ var r = '';
767
+ if (parent.parent.letsencrypt == null) {
768
+ r = "Let's Encrypt not in use.";
769
+ } else {
770
+ r = ["CertOK", "Request:NoCert", "Request:Expire", "Request:MissingNames"][parent.parent.letsencrypt.checkRkenewCertificate()];
771
+ }
772
+ return r;
773
+ }
774
+
775
+ function leeventsConsoleCommand(command, cmdargs) {
776
+ var r = '';
777
+ if (parent.parent.letsencrypt == null) {
778
+ r = "Let's Encrypt not in use.";
779
+ } else {
780
+ r = parent.parent.letsencrypt.events.join('\r\n');
781
+ }
782
+ return r;
783
+ }
784
+
785
+ function badloginsConsoleCommand(command, cmdargs) {
786
+ var r = '';
787
+ if (parent.parent.config.settings.maxinvalidlogin == false) {
788
+ r = 'Bad login filter is disabled.';
789
+ } else {
790
+ if (cmdargs['_'] == 'reset') {
791
+ // Reset bad login table
792
+ parent.badLoginTable = {};
793
+ parent.badLoginTableLastClean = 0;
794
+ r = 'Done.'
795
+ } else if (cmdargs['_'] == '') {
796
+ // Show current bad login table
797
+ if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') {
798
+ r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n";
799
+ } else {
800
+ r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n";
801
+ }
802
+ var badLoginCount = 0;
803
+ parent.cleanBadLoginTable();
804
+ for (var i in parent.badLoginTable) {
805
+ badLoginCount++;
806
+ if (typeof parent.badLoginTable[i] == 'number') {
807
+ r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n";
808
+ } else {
809
+ if (parent.badLoginTable[i].length > 1) {
810
+ r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n");
811
+ } else {
812
+ r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n");
813
+ }
814
+ }
815
+ }
816
+ if (badLoginCount == 0) { r += 'No bad logins.'; }
817
+ } else {
818
+ r = 'Usage: badlogin [reset]';
819
+ }
820
+ }
821
+ return r;
822
+ }
823
+
824
+ function dispatchtableConsoleCommand(command, cmdargs) {
825
+ var r = '';
826
+ for (var i in parent.parent.eventsDispatch) {
827
+ r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n');
828
+ }
829
+ return r;
830
+ }
831
+
832
+ function dupagentsConsoleCommand(command, cmdargs) {
833
+ var r = '';
834
+ for (var i in parent.duplicateAgentsLog) {
835
+ r += JSON.stringify(parent.duplicateAgentsLog[i]) + '\r\n';
836
+ }
837
+ if (r == '') { r = 'No duplicate agents in log.'; }
838
+ return r;
839
+ }
840
+
841
+ function agentstatsConsoleCommand(command, cmdargs) {
842
+ var r = '';
843
+ var stats = parent.getAgentStats();
844
+ for (var i in stats) {
845
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
846
+ }
847
+ return r;
848
+ }
849
+
850
+ function agentissuesConsoleCommand(command, cmdargs) {
851
+ var r = '';
852
+ var stats = parent.getAgentIssues();
853
+ if (stats.length == 0) {
854
+ r = "No agent issues.";
855
+ } else {
856
+ for (var i in stats) { r += stats[i].join(', ') + '\r\n'; }
857
+ }
858
+ return r;
859
+ }
860
+
861
+ function webstatsConsoleCommand(command, cmdargs) {
862
+ var r = '';
863
+ var stats = parent.getStats();
864
+ for (var i in stats) {
865
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
866
+ }
867
+ return r;
868
+ }
869
+
870
+ function trafficstatsConsoleCommand(command, cmdargs) {
871
+ var r = '';
872
+ var stats = parent.getTrafficStats();
873
+ for (var i in stats) {
874
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
875
+ }
876
+ return r;
877
+ }
878
+
879
+ function trafficdeltaConsoleCommand(command, cmdargs) {
880
+ var r = '';
881
+ const stats = parent.getTrafficDelta(obj.trafficStats);
882
+ obj.trafficStats = stats.current;
883
+ for (var i in stats.delta) {
884
+ if (typeof stats.delta[i] == 'object') { r += (i + ': ' + JSON.stringify(stats.delta[i]) + '\r\n'); } else { r += (i + ': ' + stats.delta[i] + '\r\n'); }
885
+ }
886
+ return r;
887
+ }
888
+
889
+ function watchdogConsoleCommand(command, cmdargs) {
890
+ var r = '';
891
+ if (parent.parent.watchdog == null) {
892
+ r = 'Server watchdog not active.';
893
+ } else {
894
+ r = 'Server watchdog active.\r\n';
895
+ if (parent.parent.watchdogmaxtime != null) { r += 'Largest timeout was ' + parent.parent.watchdogmax + 'ms on ' + parent.parent.watchdogmaxtime + '\r\n'; }
896
+ for (var i in parent.parent.watchdogtable) { r += parent.parent.watchdogtable[i] + '\r\n'; }
897
+ }
898
+ return r;
899
+ }
900
+
901
+ function acceleratorsstatsConsoleCommand(command, cmdargs) {
902
+ var r = '';
903
+ var stats = parent.parent.certificateOperations.getAcceleratorStats();
904
+ for (var i in stats) {
905
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
906
+ }
907
+ return r;
908
+ }
909
+
910
+ function mpsstatsConsoleCommand(command, cmdargs) {
911
+ var r = '';
912
+ if (parent.parent.mpsserver == null) {
913
+ r = 'MPS not enabled.';
914
+ } else {
915
+ var stats = parent.parent.mpsserver.getStats();
916
+ for (var i in stats) {
917
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
918
+ }
919
+ }
920
+ return r;
921
+ }
922
+
923
+ function mpsConsoleCommand(command, cmdargs) {
924
+ var r = '';
925
+ if (parent.parent.mpsserver == null) {
926
+ r = 'MPS not enabled.';
927
+ } else {
928
+ const connectionTypes = ['CIRA', 'Relay', 'LMS'];
929
+ for (var nodeid in parent.parent.mpsserver.ciraConnections) {
930
+ r += nodeid;
931
+ var connections = parent.parent.mpsserver.ciraConnections[nodeid];
932
+ for (var i in connections) { r += ', ' + connectionTypes[connections[i].tag.connType]; }
933
+ r += '\r\n';
934
+ }
935
+ if (r == '') { r = 'MPS has not connections.'; }
936
+ }
937
+ return r;
938
+ }
939
+
940
+ function dbstatsConsoleCommand(command, cmdargs) {
941
+ parent.parent.db.getStats(function (stats) {
942
+ var r2 = '';
943
+ for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); }
944
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
945
+ });
946
+ }
947
+
948
+ function dbcountersConsoleCommand(command, cmdargs) {
949
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: JSON.stringify(parent.parent.db.dbCounters, null, 2), tag: command.tag })); } catch (ex) { }
950
+ }
951
+
952
+ function serverupdateConsoleCommand(command, cmdargs) {
953
+ var r = '';
954
+ r = 'Performing server update...';
955
+ var version = null;
956
+
957
+ if (cmdargs['_'].length > 0) {
958
+ version = cmdargs['_'][0];
959
+
960
+ // This call is SLOW. We only want to validate version if we have to
961
+ if (version != 'stable' && version != 'latest') {
962
+ parent.parent.getServerVersions((data) => {
963
+ var versions = JSON.parse(data);
964
+
965
+ if (versions.includes(version)) {
966
+ if (parent.parent.performServerUpdate(version) == false) {
967
+ try {
968
+ ws.send(JSON.stringify({ action: 'serverconsole',
969
+ value: 'Server self-update not possible.'}));
970
+ } catch (ex) { }
971
+ }
972
+ } else {
973
+ try {
974
+ ws.send(JSON.stringify({ action: 'serverconsole',
975
+ value: 'Invalid version. Aborting update'}));
976
+ } catch (ex) { }
977
+ }
978
+ });
979
+ } else {
980
+ if (parent.parent.performServerUpdate(version) == false) {
981
+ r = 'Server self-update not possible.';
982
+ }
983
+ }
984
+ } else {
985
+ if (parent.parent.performServerUpdate(version) == false) {
986
+ r = 'Server self-update not possible.';
987
+ }
988
+ }
989
+ return r;
990
+ }
991
+
992
+ function printConsoleCommand(command, cmdargs) {
993
+ console.log(cmdargs['_'][0]);
994
+ }
995
+
996
+ function amtpasswordsConsoleCommand(command, cmdargs) {
997
+ var r = '';
998
+ if (parent.parent.amtPasswords == null) {
999
+ r = "No Intel AMT password table."
1000
+ } else {
1001
+ for (var i in parent.parent.amtPasswords) { r += (i + ' - ' + parent.parent.amtPasswords[i].join(', ') + '\r\n'); }
1002
+ }
1003
+ return r;
1004
+ }
1005
+
1006
+ function updatecheckConsoleCommand(command, cmdargs) {
1007
+ var r = '';
1008
+ parent.parent.getServerTags(function (tags, error) {
1009
+ var r2 = '';
1010
+ if (error != null) { r2 += 'Exception: ' + error + '\r\n'; }
1011
+ else { for (var i in tags) { r2 += i + ': ' + tags[i] + '\r\n'; } }
1012
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
1013
+ });
1014
+ r = "Checking server update...";
1015
+ return r;
1016
+ }
1017
+
1018
+ function maintenanceConsoleCommand(command, cmdargs) {
1019
+ var r = '';
1020
+ var arg = null, changed = false;
1021
+ if ((cmdargs['_'] != null) && (cmdargs['_'][0] != null)) { arg = cmdargs['_'][0].toLowerCase(); }
1022
+ if (arg == 'enabled') { parent.parent.config.settings.maintenancemode = 1; changed = true; }
1023
+ else if (arg == 'disabled') { delete parent.parent.config.settings.maintenancemode; changed = true; }
1024
+ r = 'Maintenance mode: ' + ((parent.parent.config.settings.maintenancemode == null) ? 'Disabled' : 'Enabled');
1025
+ if (changed == false) { r += '\r\nTo change type: maintenance [enabled|disabled]'; }
1026
+ return r;
1027
+ }
1028
+
1029
+ function infoConsoleCommand(command, cmdargs) {
1030
+ var r = '';
1031
+ var info = process.memoryUsage();
1032
+ info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType];
1033
+ try { if (parent.parent.multiServer != null) { info.serverId = parent.parent.multiServer.serverid; } } catch (ex) { }
1034
+ if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; }
1035
+ if (parent.parent.pluginHandler != null) { info.plugins = []; for (var i in parent.parent.pluginHandler.plugins) { info.plugins.push(i); } }
1036
+ try { info.nodeVersion = process.version; } catch (ex) { }
1037
+ try { info.meshVersion = parent.parent.currentVer; } catch (ex) { }
1038
+ try { info.platform = process.platform; } catch (ex) { }
1039
+ try { info.arch = process.arch; } catch (ex) { }
1040
+ try { info.pid = process.pid; } catch (ex) { }
1041
+ try { info.uptime = process.uptime(); } catch (ex) { }
1042
+ try { info.cpuUsage = process.cpuUsage(); } catch (ex) { }
1043
+ try { info.warnings = parent.parent.getServerWarnings(); } catch (ex) { }
1044
+ try { info.database = ["Unknown", "NeDB", "MongoJS", "MongoDB", "MariaDB", "MySQL"][parent.parent.db.databaseType]; } catch (ex) { }
1045
+ try { info.productionMode = ((process.env.NODE_ENV != null) && (process.env.NODE_ENV == 'production')); } catch (ex) { }
1046
+ try { info.allDevGroupManagers = parent.parent.config.settings.managealldevicegroups; } catch (ex) { }
1047
+ r = JSON.stringify(info, null, 4);
1048
+ return r;
1049
+ }
1050
+
1051
+ function nodeconfigConsoleCommand(command, cmdargs) {
1052
+ return JSON.stringify(process.config, null, 4);
1053
+ }
1054
+
1055
+ function versionsConsoleCommand(command, cmdargs) {
1056
+ return JSON.stringify(process.versions, null, 4);
1057
+ }
1058
+
1059
+ function argsConsoleCommand(command, cmdargs) {
1060
+ return 'args: ' + JSON.stringify(cmdargs);
1061
+ }
1062
+
1063
+ function usersessionsConsoleCommand(command, cmdargs) {
1064
+ var r = '';
1065
+ var userSessionCount = 0;
1066
+ var filter = null;
1067
+ var arg = cmdargs['_'][0];
1068
+ if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
1069
+ for (var i in parent.wssessions) {
1070
+ if ((filter == null) || (filter == i)) {
1071
+ userSessionCount++;
1072
+ r += (i + ', ' + parent.wssessions[i].length + ' session' + ((parent.wssessions[i].length > 1) ? 's' : '') + '.\r\n');
1073
+ for (var j in parent.wssessions[i]) {
1074
+ r += ' ' + parent.wssessions[i][j].clientIp + ' --> ' + parent.wssessions[i][j].sessionId + '\r\n';
1075
+ }
1076
+ }
1077
+ }
1078
+ if (userSessionCount == 0) { r = 'None.'; }
1079
+ return r;
1080
+ }
1081
+
1082
+ function closeusersessionsConsoleCommand(command, cmdargs) {
1083
+ var r = '';
1084
+ var userSessionCount = 0;
1085
+ var filter = null;
1086
+ var arg = cmdargs['_'][0];
1087
+ if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
1088
+ if (filter == null) {
1089
+ r += "Usage: closeusersessions <username>";
1090
+ } else {
1091
+ r += "Closing user sessions for: " + filter + '\r\n';
1092
+ for (var i in parent.wssessions) {
1093
+ if (filter == i) {
1094
+ userSessionCount++;
1095
+ for (var j in parent.wssessions[i]) {
1096
+ parent.wssessions[i][j].send(JSON.stringify({ action: 'stopped', msg: "Administrator forced disconnection" }));
1097
+ parent.wssessions[i][j].close();
1098
+ }
1099
+ }
1100
+ }
1101
+ if (userSessionCount < 2) { r += 'Disconnected ' + userSessionCount + ' session.'; } else { r += 'Disconnected ' + userSessionCount + ' sessions.'; };
1102
+ }
1103
+ return r;
1104
+ }
1105
+
1106
+ function resetserverConsoleCommand(command, cmdargs) {
1107
+ console.log("Server restart...");
1108
+ process.exit(0);
1109
+ }
1110
+
1111
+ function tasklimiterConsoleCommand(command, cmdargs) {
1112
+ var r = '';
1113
+ if (parent.parent.taskLimiter != null) {
1114
+ //var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null };
1115
+ const tl = parent.parent.taskLimiter;
1116
+ r += 'MaxTasks: ' + tl.maxTasks + ', NextTaskId: ' + tl.nextTaskId + '\r\n';
1117
+ r += 'MaxTaskTime: ' + (tl.maxTaskTime / 1000) + ' seconds, Timer: ' + (tl.timer != null) + '\r\n';
1118
+ var c = [];
1119
+ for (var i in tl.current) { c.push(i); }
1120
+ r += 'Current (' + tl.currentCount + '): [' + c.join(', ') + ']\r\n';
1121
+ r += 'Pending (High/Med/Low): ' + tl.pending[0].length + ', ' + tl.pending[1].length + ', ' + tl.pending[2].length + '\r\n';
1122
+ }
1123
+ return r;
1124
+ }
1125
+
1126
+ function setmaxtasksConsoleCommand(command, cmdargs) {
1127
+ var r = '';
1128
+ if ((cmdargs["_"].length != 1) || (parseInt(cmdargs["_"][0]) < 1) || (parseInt(cmdargs["_"][0]) > 1000)) {
1129
+ r = 'Usage: setmaxtasks [1 to 1000]';
1130
+ } else {
1131
+ parent.parent.taskLimiter.maxTasks = parseInt(cmdargs["_"][0]);
1132
+ r = 'MaxTasks set to ' + parent.parent.taskLimiter.maxTasks + '.';
1133
+ }
1134
+ return r;
1135
+ }
1136
+
1137
+ function coresConsoleCommand(command, cmdargs) {
1138
+ var r = '';
1139
+ if (parent.parent.defaultMeshCores != null) {
1140
+ for (var i in parent.parent.defaultMeshCores) {
1141
+ r += i + ': ' + parent.parent.defaultMeshCores[i].length + ' bytes\r\n';
1142
+ }
1143
+ }
1144
+ return r;
1145
+ }
1146
+
1147
+ function showpathsConsoleCommand(command, cmdargs) {
1148
+ var r = '';
1149
+ r = 'Parent: ' + parent.parent.parentpath + '\r\n';
1150
+ r += 'Data: ' + parent.parent.datapath + '\r\n';
1151
+ r += 'Files: ' + parent.parent.filespath + '\r\n';
1152
+ r += 'Backup: ' + parent.parent.backuppath + '\r\n';
1153
+ r += 'Record: ' + parent.parent.recordpath + '\r\n';
1154
+ r += 'WebPublic: ' + parent.parent.webPublicPath + '\r\n';
1155
+ r += 'WebViews: ' + parent.parent.webViewsPath + '\r\n';
1156
+ if (parent.parent.webViewsOverridePath) { r += 'XWebPublic: ' + parent.parent.webViewsOverridePath + '\r\n'; }
1157
+ if (parent.parent.webViewsOverridePath) { r += 'XWebViews: ' + parent.parent.webPublicOverridePath + '\r\n'; }
1158
+ return r;
1159
+ }
1160
+
1161
+ function migrationagentsConsoleCommand(command, cmdargs) {
1162
+ var r = '';
1163
+ if (parent.parent.swarmserver == null) {
1164
+ r = 'Swarm server not running.';
1165
+ } else {
1166
+ for (var i in parent.parent.swarmserver.migrationAgents) {
1167
+ var arch = parent.parent.swarmserver.migrationAgents[i];
1168
+ for (var j in arch) { var agent = arch[j]; r += 'Arch ' + agent.arch + ', Ver ' + agent.ver + ', Size ' + ((agent.binary == null) ? 0 : agent.binary.length) + '<br />'; }
1169
+ }
1170
+ }
1171
+ return r;
1172
+ }
1173
+
1174
+ function swarmstatsConsoleCommand(command, cmdargs) {
1175
+ var r = '';
1176
+ if (parent.parent.swarmserver == null) {
1177
+ r = 'Swarm server not running.';
1178
+ } else {
1179
+ for (var i in parent.parent.swarmserver.stats) {
1180
+ if (typeof parent.parent.swarmserver.stats[i] == 'object') {
1181
+ r += i + ': ' + JSON.stringify(parent.parent.swarmserver.stats[i]) + '\r\n';
1182
+ } else {
1183
+ r += i + ': ' + parent.parent.swarmserver.stats[i] + '\r\n';
1184
+ }
1185
+ }
1186
+ }
1187
+ return r;
1188
+ }
1189
+
1190
+ function relaysConsoleCommand(command, cmdargs) {
1191
+ var r = '';
1192
+ for (var i in parent.wsrelays) {
1193
+ r += 'id: ' + i + ', ' + ((parent.wsrelays[i].state == 2) ? 'connected' : 'pending');
1194
+ if (parent.wsrelays[i].peer1 != null) {
1195
+ r += ', ' + cleanRemoteAddr(parent.wsrelays[i].peer1.req.clientIp);
1196
+ if (parent.wsrelays[i].peer1.user) { r += ' (User:' + parent.wsrelays[i].peer1.user.name + ')' }
1197
+ }
1198
+ if (parent.wsrelays[i].peer2 != null) {
1199
+ r += ' to ' + cleanRemoteAddr(parent.wsrelays[i].peer2.req.clientIp);
1200
+ if (parent.wsrelays[i].peer2.user) { r += ' (User:' + parent.wsrelays[i].peer2.user.name + ')' }
1201
+ }
1202
+ r += '\r\n';
1203
+ }
1204
+ if (r == '') { r = 'No relays.'; }
1205
+ return r;
1206
+ }
1207
+
1208
+ function autobackupConsoleCommand(command, cmdargs) {
1209
+ var r = '';
1210
+ var backupResult = parent.db.performBackup(function (msg) {
1211
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: msg, tag: command.tag })); } catch (ex) { }
1212
+ });
1213
+ if (backupResult == 0) { r = 'Starting auto-backup...'; } else { r = 'Backup alreay in progress.'; }
1214
+ return r;
1215
+ }
1216
+
1217
+ function backupconfigConsoleCommand(command, cmdargs) {
1218
+ return parent.db.getBackupConfig();
1219
+ }
1220
+
1221
+ function firebaseConsoleCommand(command, cmdargs) {
1222
+ var r = '';
1223
+ if (parent.parent.firebase == null) {
1224
+ r = "Firebase push messaging not supported";
1225
+ } else {
1226
+ r = JSON.stringify(parent.parent.firebase.stats, null, 2);
1227
+ }
1228
+ return r;
1229
+ }
1230
+
1231
// Process incoming web socket data from the browser
1232
function processWebSocketData(msg) {
1233
var command, i = 0, mesh = null, meshid = null, nodeid = null, meshlinks = null, change = 0;
@@ -911,554 +1595,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1595
const cmd = cmdargs[0].toLowerCase();
1596
cmdargs = parseArgs(cmdargs);
1597
914
- switch (cmd) {
915
- case 'help': {
916
- var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,trafficstats,trafficdelta,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager,amtpasswords,certexpire,email';
917
- if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; }
918
- availcommands = availcommands.split(',').sort();
919
- while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); }
920
- if (f != '') { fin += f; }
921
- if (cmdargs['_'].length == 0) {
922
- r = 'Available commands: \r\n' + fin + '\r\nType help <command> for details.';
923
- } else {
924
- var cmd2 = cmdargs['_'][0].toLowerCase();
925
- switch (cmd2) {
926
- case 'info': { r = "info: Returns the most immidiatly useful information about this server, including MeshCentral and NodeJS versions. This is often information required to file a bug."; break; }
927
- case 'versions': { r = "versions: Returns all internal versions for NodeJS running this server."; break; }
928
- case 'resetserver': { r = "resetserver: Causes the server to reset, this is sometimes useful is the config.json file was changed."; break; }
929
- case 'usersessions': { r = "usersessions: Returns a list of active sessions grouped by user."; break; }
930
- case 'closeusersessions': { r = "closeusersessions: Disconnects all sessions for a specified user."; break; }
931
- case 'tasklimiter': { r = "tasklimiter: Returns the internal status of the tasklimiter. This is a system used to smooth out work done by the server. It's used by, for example, agent updates so that not all agents are updated at the same time."; break; }
932
- case 'serverupdate': { r = "serverupdate: Updates server to latest version. Optional version argument to install specific version. Example: serverupdate 0.8.49"; break; }
933
- default: { r = 'No help information about this command.'; break; }
934
- }
935
- }
936
- break;
937
- }
938
- case 'certexpire': {
939
- const now = Date.now();
940
- for (var i in parent.webCertificateExpire) {
941
- const domainName = (i == '') ? '[Default]' : i;
942
- r += domainName + ', expires in ' + Math.floor((parent.webCertificateExpire[i] - now) / 86400000) + ' day(s)\r\n';
943
- }
944
- break;
945
- }
946
- case 'webpush': {
947
- if (parent.parent.webpush == null) {
948
- r = "Web push not supported.";
949
- } else {
950
- if (cmdargs['_'].length != 1) {
951
- r = "Usage: WebPush \"Message\"";
952
- } else {
953
- const pushSubscription = { "endpoint": "https://updates.push.services.mozilla.com/wpush/v2/gAAAAABgIkO9hjXHWhMPiuk-ppNRw7r_pUZitddwCEK4ykdzeIxOIjFnYhIt_nr-qUca2mpZziwQsSEhYTUCiuYrhWnVDRweMtiUj16yJJq8V5jneaEaUYjEIe5jp3DOMNpoTm1aHgX74gCR8uTXSITcM97bNi-hRxcQ4f6Ie4WSAmoXpd89B_g", "keys": { "auth": "UB2sbLVK7ALnSHw5P1dahg", "p256dh": "BIoRbcNSxBuTjN39CCCUCHo1f4NxBJ1YDdu_k4MbPW_q3NK1_RufnydUzLPDp8ibBVItSI72-s48QJvOjQ_S8Ok" } }
954
- parent.parent.webpush.sendNotification(pushSubscription, cmdargs['_'][0]).then(
955
- function (value) { try { ws.send(JSON.stringify({ action: 'OK', value: r, tag: command.tag })); } catch (ex) { } },
956
- function (error) { try { ws.send(JSON.stringify({ action: 'Error', value: r, tag: command.tag })); } catch (ex) { } }
957
- );
958
- }
959
- }
960
- break;
961
- }
962
- case 'amtmanager': {
963
- if (parent.parent.amtManager == null) { r = 'Intel AMT Manager not active.'; } else { r = parent.parent.amtManager.getStatusString(); }
964
- break;
965
- }
966
- case 'certhashes': {
967
- r += 'AgentCertHash: ' + parent.agentCertificateHashHex;
968
- for (var i in parent.webCertificateHashs) { r += '\r\nwebCertificateHash (' + i + '): ' + common.rstr2hex(parent.webCertificateHashs[i]); }
969
- for (var i in parent.webCertificateFullHashs) { r += '\r\nwebCertificateFullHash (' + i + '): ' + common.rstr2hex(parent.webCertificateFullHashs[i]); }
970
- r += '\r\ndefaultWebCertificateHash: ' + common.rstr2hex(parent.defaultWebCertificateHash);
971
- r += '\r\ndefaultWebCertificateFullHash: ' + common.rstr2hex(parent.defaultWebCertificateFullHash);
972
- break;
973
- }
974
- case 'amtacm': {
975
- if ((domain.amtacmactivation == null) || (domain.amtacmactivation.acmmatch == null) || (domain.amtacmactivation.acmmatch.length == 0)) {
976
- r = 'No Intel AMT activation certificates.';
977
- } else {
978
- if (domain.amtacmactivation.log != null) { r += '--- Activation Log ---\r\nFile : ' + domain.amtacmactivation.log + '\r\n'; }
979
- for (var i in domain.amtacmactivation.acmmatch) {
980
- var acmcert = domain.amtacmactivation.acmmatch[i];
981
- r += '--- Activation Certificate ' + (parseInt(i) + 1) + ' ---\r\nName : ' + acmcert.cn + '\r\nSHA1 : ' + acmcert.sha1 + '\r\nSHA256: ' + acmcert.sha256 + '\r\n';
982
- }
983
- }
984
- break;
985
- }
986
- case 'heapdump': {
987
- // Heapdump support, see example at:
988
- // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/
989
- if (parent.parent.config.settings.heapdump === true) {
990
- var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`);
991
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { }
992
- require('heapdump').writeSnapshot(dumpFileName, (err, filename) => {
993
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { }
994
- });
995
- } else {
996
- r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json.";
997
- }
998
- break;
999
- }
1000
- case 'sms': {
1001
- if (parent.parent.smsserver == null) {
1002
- r = "No SMS gateway in use.";
1003
- } else {
1004
- if (cmdargs['_'].length != 2) {
1005
- r = "Usage: SMS \"PhoneNumber\" \"Message\".";
1006
- } else {
1007
- parent.parent.smsserver.sendSMS(cmdargs['_'][0], cmdargs['_'][1], function (status, msg) {
1008
- if (typeof msg == 'string') {
1009
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? ('Success: ' + msg) : ('Failed: ' + msg), tag: command.tag })); } catch (ex) { }
1010
- } else {
1011
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? 'Success' : 'Failed', tag: command.tag })); } catch (ex) { }
1012
- }
1013
- });
1014
- }
1015
- }
1016
- break;
1017
- }
1018
- case 'email': {
1019
- if (domain.mailserver == null) {
1020
- r = "No email service enabled.";
1021
- } else {
1022
- if (cmdargs['_'].length != 3) {
1023
- r = "Usage: email \"user@sample.com\" \"Subject\" \"Message\".";
1024
- } else {
1025
- domain.mailserver.sendMail(cmdargs['_'][0], cmdargs['_'][1], cmdargs['_'][2]);
1026
- r = "Done.";
1027
- }
1028
- }
1029
- break;
1030
- }
1031
- case 'le': {
1032
- if (parent.parent.letsencrypt == null) {
1033
- r = "Let's Encrypt not in use.";
1034
- } else {
1035
- r = JSON.stringify(parent.parent.letsencrypt.getStats(), null, 4);
1036
- }
1037
- break;
1038
- }
1039
- case 'lecheck': {
1040
- if (parent.parent.letsencrypt == null) {
1041
- r = "Let's Encrypt not in use.";
1042
- } else {
1043
- r = ["CertOK", "Request:NoCert", "Request:Expire", "Request:MissingNames"][parent.parent.letsencrypt.checkRenewCertificate()];
1044
- }
1045
- break;
1046
- }
1047
- case 'leevents': {
1048
- if (parent.parent.letsencrypt == null) {
1049
- r = "Let's Encrypt not in use.";
1050
- } else {
1051
- r = parent.parent.letsencrypt.events.join('\r\n');
1052
- }
1053
- break;
1054
- }
1055
- case 'badlogins': {
1056
- if (parent.parent.config.settings.maxinvalidlogin == false) {
1057
- r = 'Bad login filter is disabled.';
1058
- } else {
1059
- if (cmdargs['_'] == 'reset') {
1060
- // Reset bad login table
1061
- parent.badLoginTable = {};
1062
- parent.badLoginTableLastClean = 0;
1063
- r = 'Done.'
1064
- } else if (cmdargs['_'] == '') {
1065
- // Show current bad login table
1066
- if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') {
1067
- r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n";
1068
- } else {
1069
- r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n";
1070
- }
1071
- var badLoginCount = 0;
1072
- parent.cleanBadLoginTable();
1073
- for (var i in parent.badLoginTable) {
1074
- badLoginCount++;
1075
- if (typeof parent.badLoginTable[i] == 'number') {
1076
- r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n";
1077
- } else {
1078
- if (parent.badLoginTable[i].length > 1) {
1079
- r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n");
1080
- } else {
1081
- r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n");
1082
- }
1083
- }
1084
- }
1085
- if (badLoginCount == 0) { r += 'No bad logins.'; }
1086
- } else {
1087
- r = 'Usage: badlogin [reset]';
1088
- }
1089
- }
1090
- break;
1091
- }
1092
- case 'dispatchtable': {
1093
- r = '';
1094
- for (var i in parent.parent.eventsDispatch) { r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n'); }
1095
- break;
1096
- }
1097
- case 'dupagents': {
1098
- for (var i in parent.duplicateAgentsLog) { r += JSON.stringify(parent.duplicateAgentsLog[i]) + '\r\n'; }
1099
- if (r == '') { r = 'No duplicate agents in log.'; }
1100
- break;
1101
- }
1102
- case 'agentstats': {
1103
- var stats = parent.getAgentStats();
1104
- for (var i in stats) {
1105
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1106
- }
1107
- break;
1108
- }
1109
- case 'agentissues': {
1110
- var stats = parent.getAgentIssues();
1111
- if (stats.length == 0) {
1112
- r = "No agent issues.";
1113
- } else {
1114
- for (var i in stats) { r += stats[i].join(', ') + '\r\n'; }
1115
- }
1116
- break;
1117
- }
1118
- case 'webstats': {
1119
- var stats = parent.getStats();
1120
- for (var i in stats) {
1121
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1122
- }
1123
- break;
1124
- }
1125
- case 'trafficstats': {
1126
- var stats = parent.getTrafficStats();
1127
- for (var i in stats) {
1128
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1129
- }
1130
- break;
1131
- }
1132
- case 'trafficdelta': {
1133
- const stats = parent.getTrafficDelta(obj.trafficStats);
1134
- obj.trafficStats = stats.current;
1135
- for (var i in stats.delta) {
1136
- if (typeof stats.delta[i] == 'object') { r += (i + ': ' + JSON.stringify(stats.delta[i]) + '\r\n'); } else { r += (i + ': ' + stats.delta[i] + '\r\n'); }
1137
- }
1138
- break;
1139
- }
1140
- case 'watchdog': {
1141
- if (parent.parent.watchdog == null) {
1142
- r = 'Server watchdog not active.';
1143
- } else {
1144
- r = 'Server watchdog active.\r\n';
1145
- if (parent.parent.watchdogmaxtime != null) { r += 'Largest timeout was ' + parent.parent.watchdogmax + 'ms on ' + parent.parent.watchdogmaxtime + '\r\n'; }
1146
- for (var i in parent.parent.watchdogtable) { r += parent.parent.watchdogtable[i] + '\r\n'; }
1147
- }
1148
- break;
1149
- }
1150
- case 'acceleratorsstats': {
1151
- var stats = parent.parent.certificateOperations.getAcceleratorStats();
1152
- for (var i in stats) {
1153
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1154
- }
1155
- break;
1156
- }
1157
- case 'mpsstats': {
1158
- if (parent.parent.mpsserver == null) {
1159
- r = 'MPS not enabled.';
1160
- } else {
1161
- var stats = parent.parent.mpsserver.getStats();
1162
- for (var i in stats) {
1163
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1164
- }
1165
- }
1166
- break;
1167
- }
1168
- case 'mps': { // List all MPS connections and types.
1169
- if (parent.parent.mpsserver == null) {
1170
- r = 'MPS not enabled.';
1171
- } else {
1172
- const connectionTypes = ['CIRA', 'Relay', 'LMS'];
1173
- for (var nodeid in parent.parent.mpsserver.ciraConnections) {
1174
- r += nodeid;
1175
- var connections = parent.parent.mpsserver.ciraConnections[nodeid];
1176
- for (var i in connections) { r += ', ' + connectionTypes[connections[i].tag.connType]; }
1177
- r += '\r\n';
1178
- }
1179
- if (r == '') { r = 'MPS has not connections.'; }
1180
- }
1181
- break;
1182
- }
1183
- case 'dbstats': {
1184
- parent.parent.db.getStats(function (stats) {
1185
- var r2 = '';
1186
- for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); }
1187
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
1188
- });
1189
- break;
1190
- }
1191
- case 'dbcounters': {
1192
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: JSON.stringify(parent.parent.db.dbCounters, null, 2), tag: command.tag })); } catch (ex) { }
1193
- break;
1194
- }
1195
- case 'serverupdate': {
1196
- r = 'Performing server update...';
1197
- var version = null;
1198
-
1199
- if (cmdargs['_'].length > 0) {
1200
- version = cmdargs['_'][0];
1201
-
1202
- // This call is SLOW. We only want to validate version if we have to
1203
- if (version != 'stable' && version != 'latest') {
1204
- parent.parent.getServerVersions((data) => {
1205
- var versions = JSON.parse(data);
1206
-
1207
- if (versions.includes(version)) {
1208
- if (parent.parent.performServerUpdate(version) == false) {
1209
- try {
1210
- ws.send(JSON.stringify({ action: 'serverconsole',
1211
- value: 'Server self-update not possible.'}));
1212
- } catch (ex) { }
1213
- }
1214
- } else {
1215
- try {
1216
- ws.send(JSON.stringify({ action: 'serverconsole',
1217
- value: 'Invalid version. Aborting update'}));
1218
- } catch (ex) { }
1219
- }
1220
- });
1221
- } else {
1222
- if (parent.parent.performServerUpdate(version) == false) {
1223
- r = 'Server self-update not possible.';
1224
- }
1225
- }
1226
- } else {
1227
- if (parent.parent.performServerUpdate(version) == false) {
1228
- r = 'Server self-update not possible.';
1229
- }
1230
- }
1231
-
1232
- break;
1233
- }
1234
- case 'print': {
1235
- console.log(cmdargs['_'][0]);
1236
- break;
1237
- }
1238
- case 'amtpasswords': {
1239
- if (parent.parent.amtPasswords == null) {
1240
- r = "No Intel AMT password table."
1241
- } else {
1242
- for (var i in parent.parent.amtPasswords) { r += (i + ' - ' + parent.parent.amtPasswords[i].join(', ') + '\r\n'); }
1243
- }
1244
- break;
1245
- }
1246
- case 'updatecheck': {
1247
- parent.parent.getServerTags(function (tags, error) {
1248
- var r2 = '';
1249
- if (error != null) { r2 += 'Exception: ' + error + '\r\n'; }
1250
- else { for (var i in tags) { r2 += i + ': ' + tags[i] + '\r\n'; } }
1251
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
1252
- });
1253
- r = "Checking server update...";
1254
- break;
1255
- }
1256
- case 'maintenance': {
1257
- var arg = null, changed = false;
1258
- if ((cmdargs['_'] != null) && (cmdargs['_'][0] != null)) { arg = cmdargs['_'][0].toLowerCase(); }
1259
- if (arg == 'enabled') { parent.parent.config.settings.maintenancemode = 1; changed = true; }
1260
- else if (arg == 'disabled') { delete parent.parent.config.settings.maintenancemode; changed = true; }
1261
- r = 'Maintenance mode: ' + ((parent.parent.config.settings.maintenancemode == null) ? 'Disabled' : 'Enabled');
1262
- if (changed == false) { r += '\r\nTo change type: maintenance [enabled|disabled]'; }
1263
- break;
1264
- }
1265
- case 'info': {
1266
- var info = process.memoryUsage();
1267
- info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType];
1268
- try { if (parent.parent.multiServer != null) { info.serverId = parent.parent.multiServer.serverid; } } catch (ex) { }
1269
- if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; }
1270
- if (parent.parent.pluginHandler != null) { info.plugins = []; for (var i in parent.parent.pluginHandler.plugins) { info.plugins.push(i); } }
1271
- try { info.nodeVersion = process.version; } catch (ex) { }
1272
- try { info.meshVersion = parent.parent.currentVer; } catch (ex) { }
1273
- try { info.platform = process.platform; } catch (ex) { }
1274
- try { info.arch = process.arch; } catch (ex) { }
1275
- try { info.pid = process.pid; } catch (ex) { }
1276
- try { info.uptime = process.uptime(); } catch (ex) { }
1277
- try { info.cpuUsage = process.cpuUsage(); } catch (ex) { }
1278
- try { info.warnings = parent.parent.getServerWarnings(); } catch (ex) { }
1279
- try { info.database = ["Unknown", "NeDB", "MongoJS", "MongoDB", "MariaDB", "MySQL"][parent.parent.db.databaseType]; } catch (ex) { }
1280
- try { info.productionMode = ((process.env.NODE_ENV != null) && (process.env.NODE_ENV == 'production')); } catch (ex) { }
1281
- try { info.allDevGroupManagers = parent.parent.config.settings.managealldevicegroups; } catch (ex) { }
1282
- r = JSON.stringify(info, null, 4);
1283
- break;
1284
- }
1285
- case 'nodeconfig': {
1286
- r = JSON.stringify(process.config, null, 4);
1287
- break;
1288
- }
1289
- case 'versions': {
1290
- r = JSON.stringify(process.versions, null, 4);
1291
- break;
1292
- }
1293
- case 'args': {
1294
- r = cmd + ': ' + JSON.stringify(cmdargs);
1295
- break;
1296
- }
1297
- case 'usersessions': {
1298
- var userSessionCount = 0;
1299
- var filter = null;
1300
- var arg = cmdargs['_'][0];
1301
- if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
1302
- for (var i in parent.wssessions) {
1303
- if ((filter == null) || (filter == i)) {
1304
- userSessionCount++;
1305
- r += (i + ', ' + parent.wssessions[i].length + ' session' + ((parent.wssessions[i].length > 1) ? 's' : '') + '.\r\n');
1306
- for (var j in parent.wssessions[i]) {
1307
- r += ' ' + parent.wssessions[i][j].clientIp + ' --> ' + parent.wssessions[i][j].sessionId + '\r\n';
1308
- }
1309
- }
1310
- }
1311
- if (userSessionCount == 0) { r = 'None.'; }
1312
- break;
1313
- }
1314
- case 'closeusersessions': {
1315
- var userSessionCount = 0;
1316
- var filter = null;
1317
- var arg = cmdargs['_'][0];
1318
- if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
1319
- if (filter == null) {
1320
- r += "Usage: closeusersessions <username>";
1321
- } else {
1322
- r += "Closing user sessions for: " + filter + '\r\n';
1323
- for (var i in parent.wssessions) {
1324
- if (filter == i) {
1325
- userSessionCount++;
1326
- for (var j in parent.wssessions[i]) {
1327
- parent.wssessions[i][j].send(JSON.stringify({ action: 'stopped', msg: "Administrator forced disconnection" }));
1328
- parent.wssessions[i][j].close();
1329
- }
1330
- }
1331
- }
1332
- if (userSessionCount < 2) { r += 'Disconnected ' + userSessionCount + ' session.'; } else { r += 'Disconnected ' + userSessionCount + ' sessions.'; };
1333
- }
1334
- break;
1335
- }
1336
- case 'resetserver': {
1337
- console.log("Server restart...");
1338
- process.exit(0);
1339
- break;
1340
- }
1341
- case 'tasklimiter': {
1342
- if (parent.parent.taskLimiter != null) {
1343
- //var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null };
1344
- const tl = parent.parent.taskLimiter;
1345
- r += 'MaxTasks: ' + tl.maxTasks + ', NextTaskId: ' + tl.nextTaskId + '\r\n';
1346
- r += 'MaxTaskTime: ' + (tl.maxTaskTime / 1000) + ' seconds, Timer: ' + (tl.timer != null) + '\r\n';
1347
- var c = [];
1348
- for (var i in tl.current) { c.push(i); }
1349
- r += 'Current (' + tl.currentCount + '): [' + c.join(', ') + ']\r\n';
1350
- r += 'Pending (High/Med/Low): ' + tl.pending[0].length + ', ' + tl.pending[1].length + ', ' + tl.pending[2].length + '\r\n';
1351
- }
1352
- break;
1353
- }
1354
- case 'setmaxtasks': {
1355
- if ((cmdargs["_"].length != 1) || (parseInt(cmdargs["_"][0]) < 1) || (parseInt(cmdargs["_"][0]) > 1000)) {
1356
- r = 'Usage: setmaxtasks [1 to 1000]';
1357
- } else {
1358
- parent.parent.taskLimiter.maxTasks = parseInt(cmdargs["_"][0]);
1359
- r = 'MaxTasks set to ' + parent.parent.taskLimiter.maxTasks + '.';
1360
- }
1361
- break;
1362
- }
1363
- case 'cores': {
1364
- if (parent.parent.defaultMeshCores != null) { for (var i in parent.parent.defaultMeshCores) { r += i + ': ' + parent.parent.defaultMeshCores[i].length + ' bytes\r\n'; } }
1365
- break;
1366
- }
1367
- case 'showpaths': {
1368
- r = 'Parent: ' + parent.parent.parentpath + '\r\n';
1369
- r += 'Data: ' + parent.parent.datapath + '\r\n';
1370
- r += 'Files: ' + parent.parent.filespath + '\r\n';
1371
- r += 'Backup: ' + parent.parent.backuppath + '\r\n';
1372
- r += 'Record: ' + parent.parent.recordpath + '\r\n';
1373
- r += 'WebPublic: ' + parent.parent.webPublicPath + '\r\n';
1374
- r += 'WebViews: ' + parent.parent.webViewsPath + '\r\n';
1375
- if (parent.parent.webViewsOverridePath) { r += 'XWebPublic: ' + parent.parent.webViewsOverridePath + '\r\n'; }
1376
- if (parent.parent.webViewsOverridePath) { r += 'XWebViews: ' + parent.parent.webPublicOverridePath + '\r\n'; }
1377
- break;
1378
- }
1379
- case 'migrationagents': {
1380
- if (parent.parent.swarmserver == null) {
1381
- r = 'Swarm server not running.';
1382
- } else {
1383
- for (var i in parent.parent.swarmserver.migrationAgents) {
1384
- var arch = parent.parent.swarmserver.migrationAgents[i];
1385
- for (var j in arch) { var agent = arch[j]; r += 'Arch ' + agent.arch + ', Ver ' + agent.ver + ', Size ' + ((agent.binary == null) ? 0 : agent.binary.length) + '<br />'; }
1386
- }
1387
- }
1388
- break;
1389
- }
1390
- case 'swarmstats': {
1391
- if (parent.parent.swarmserver == null) {
1392
- r = 'Swarm server not running.';
1393
- } else {
1394
- for (var i in parent.parent.swarmserver.stats) {
1395
- if (typeof parent.parent.swarmserver.stats[i] == 'object') {
1396
- r += i + ': ' + JSON.stringify(parent.parent.swarmserver.stats[i]) + '\r\n';
1397
- } else {
1398
- r += i + ': ' + parent.parent.swarmserver.stats[i] + '\r\n';
1399
- }
1400
- }
1401
- }
1402
- break;
1403
- }
1404
- case 'heapdump': {
1405
- var heapdump = null;
1406
- try { heapdump = require('heapdump'); } catch (ex) { }
1407
- if (heapdump == null) {
1408
- r = 'Heapdump module not installed, run "npm install heapdump".';
1409
- } else {
1410
- heapdump.writeSnapshot(function (err, filename) {
1411
- if (err != null) {
1412
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Unable to write heapdump: ' + err })); } catch (ex) { }
1413
- } else {
1414
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Wrote heapdump at ' + filename })); } catch (ex) { }
1415
- }
1416
- });
1417
- }
1418
- break;
1419
- }
1420
- case 'relays': {
1421
- for (var i in parent.wsrelays) {
1422
- r += 'id: ' + i + ', ' + ((parent.wsrelays[i].state == 2) ? 'connected' : 'pending');
1423
- if (parent.wsrelays[i].peer1 != null) {
1424
- r += ', ' + cleanRemoteAddr(parent.wsrelays[i].peer1.req.clientIp);
1425
- if (parent.wsrelays[i].peer1.user) { r += ' (User:' + parent.wsrelays[i].peer1.user.name + ')' }
1426
- }
1427
- if (parent.wsrelays[i].peer2 != null) {
1428
- r += ' to ' + cleanRemoteAddr(parent.wsrelays[i].peer2.req.clientIp);
1429
- if (parent.wsrelays[i].peer2.user) { r += ' (User:' + parent.wsrelays[i].peer2.user.name + ')' }
1430
- }
1431
- r += '\r\n';
1432
- }
1433
- if (r == '') { r = 'No relays.'; }
1434
- break;
1435
- }
1436
- case 'autobackup': {
1437
- var backupResult = parent.db.performBackup(function (msg) {
1438
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: msg, tag: command.tag })); } catch (ex) { }
1439
- });
1440
- if (backupResult == 0) { r = 'Starting auto-backup...'; } else { r = 'Backup alreay in progress.'; }
1441
- break;
1442
- }
1443
- case 'backupconfig': {
1444
- r = parent.db.getBackupConfig();
1445
- break;
1446
- }
1447
- case 'firebase': {
1448
- if (parent.parent.firebase == null) {
1449
- r = "Firebase push messaging not supported";
1450
- } else {
1451
- r = JSON.stringify(parent.parent.firebase.stats, null, 2);
1452
- }
1453
- break;
1454
- }
1455
- default: { // This is an unknown command, return an error message
1598
+ try {
1599
+ r = consoleCommands[cmd](command, cmdargs);
1600
+ } catch (e) {
1601
+ if (consoleCommands[cmd] == null)
1602
r = 'Unknown command \"' + cmd + '\", type \"help\" for list of available commands.';
1457
- break;
1458
- }
1603
+ else
1604
+ console.log(e);
1605
}
1606
1461
- if (r != '') { try { ws.send(JSON.stringify({ action: 'serverconsole', value: r, tag: command.tag })); } catch (ex) { } }
1607
+ if (r != null && r != '') { try { ws.send(JSON.stringify({ action: 'serverconsole', value: r, tag: command.tag })); } catch (ex) { } }
1608
break;
1609
}
1610
case 'msg':