diff --git a/Debug/AMT.js b/Debug/AMT.js
new file mode 100644
index 0000000..e1b3027
--- /dev/null
+++ b/Debug/AMT.js
@@ -0,0 +1,205 @@
+var http = require('http');
+var digest = require('http-digest').create("admin", "P@ssw0rd");
+console.log("Starting AMT Test");
+
+
+digest.http = require('http');
+
+
+
+//console.log("First Test: HTTP/GET on '/'");
+//var req = digest.request({ protocol: "http:", method: "GET", host: "172.16.2.249", path: "/", port: 16992 }, OnGet1);
+//req.end();
+
+//console.log('First Test: POST /wsman');
+//WSManTest();
+
+console.log('First Test: POST /wsman, [immediate]');
+WSManTest_Immediate();
+
+function OnGet1(imsg)
+{
+ if(imsg.statusCode == 303)
+ {
+ console.log("...SUCCESS!");
+ console.log("Next Test: Redirect to '" + imsg.header['Location'] + "'");
+ req = digest.request({ protocol: "http:", method: "GET", host: "172.16.2.249", path: imsg.header['Location'], port: 16992 }, OnGet2);
+ req.end();
+ }
+ else
+ {
+ console.log("...FAILED!");
+ }
+}
+
+function OnGet2(imsg)
+{
+ if (imsg.statusCode == 200)
+ {
+ console.log("...SUCCESS!");
+ console.log("...Reading body of message");
+ imsg.on('end', function ()
+ {
+ console.log("...Finished");
+ console.log("Next Test: '/index.htm'");
+ req = digest.request({ protocol: "http:", method: "GET", host: "172.16.2.249", path: "/index.htm", port: 16992 }, OnGet3);
+ req.end();
+ });
+ }
+ else
+ {
+ console.log("...FAILED, status code was: " + imsg.statusCode);
+ }
+}
+function OnGet3(imsg)
+{
+ if (imsg.statusCode == 200)
+ {
+ console.log("...SUCCESS!");
+ console.log("Next Test: 'POST /wsman'");
+ WSManTest();
+ }
+}
+
+function WSManTest()
+{
+ req = digest.request({ protocol: "http:", method: "POST", host: "172.16.2.249", path: "/wsman", port: 16992, headers: { Expect: '100-Continue' }, timeout: 2000 });
+ req.on('continue', WSManTest_Continue);
+ req.on('timeout', WSManTest_Timeout);
+ req.on('response', WSManTest_Response);
+}
+
+function WSManTest_Immediate()
+{
+ req = digest.request({ protocol: "http:", method: "POST", host: "172.16.2.249", path: "/wsman", port: 16992 });
+ req.on('response', WSManTest_Response);
+
+ var xml = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48RW52ZWxvcGUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeG1sbnM6eHNkPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6YT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOC9hZGRyZXNzaW5nIiB4bWxuczp3PSJodHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzbWFuLzEvd3NtYW4ueHNkIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMy8wNS9zb2FwLWVudmVsb3BlIiA+PEhlYWRlcj48YTpBY3Rpb24+aHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOS90cmFuc2Zlci9HZXQ8L2E6QWN0aW9uPjxhOlRvPi93c21hbjwvYTpUbz48dzpSZXNvdXJjZVVSST5odHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzY2ltLzEvY2ltLXNjaGVtYS8yL0NJTV9Db21wdXRlclN5c3RlbVBhY2thZ2U8L3c6UmVzb3VyY2VVUkk+PGE6TWVzc2FnZUlEPjQ8L2E6TWVzc2FnZUlEPjxhOlJlcGx5VG8+PGE6QWRkcmVzcz5odHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA0LzA4L2FkZHJlc3Npbmcvcm9sZS9hbm9ueW1vdXM8L2E6QWRkcmVzcz48L2E6UmVwbHlUbz48dzpPcGVyYXRpb25UaW1lb3V0PlBUNjBTPC93Ok9wZXJhdGlvblRpbWVvdXQ+PC9IZWFkZXI+PEJvZHkgLz48L0VudmVsb3BlPg==';
+ var b = Buffer.from(xml, 'base64');
+ req.write(b);
+ req.end();
+}
+
+function WSManTest_Continue()
+{
+ console.log("Got Continue!");
+}
+function WSManTest_Timeout()
+{
+ console.log("Timeout waiting for 100 Continue... Sending body anyways...");
+ var xml = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48RW52ZWxvcGUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeG1sbnM6eHNkPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6YT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOC9hZGRyZXNzaW5nIiB4bWxuczp3PSJodHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzbWFuLzEvd3NtYW4ueHNkIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMy8wNS9zb2FwLWVudmVsb3BlIiA+PEhlYWRlcj48YTpBY3Rpb24+aHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNC8wOS90cmFuc2Zlci9HZXQ8L2E6QWN0aW9uPjxhOlRvPi93c21hbjwvYTpUbz48dzpSZXNvdXJjZVVSST5odHRwOi8vc2NoZW1hcy5kbXRmLm9yZy93YmVtL3dzY2ltLzEvY2ltLXNjaGVtYS8yL0NJTV9Db21wdXRlclN5c3RlbVBhY2thZ2U8L3c6UmVzb3VyY2VVUkk+PGE6TWVzc2FnZUlEPjQ8L2E6TWVzc2FnZUlEPjxhOlJlcGx5VG8+PGE6QWRkcmVzcz5odHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA0LzA4L2FkZHJlc3Npbmcvcm9sZS9hbm9ueW1vdXM8L2E6QWRkcmVzcz48L2E6UmVwbHlUbz48dzpPcGVyYXRpb25UaW1lb3V0PlBUNjBTPC93Ok9wZXJhdGlvblRpbWVvdXQ+PC9IZWFkZXI+PEJvZHkgLz48L0VudmVsb3BlPg==';
+ var b = Buffer.from(xml, 'base64');
+ this.write(b);
+ this.end();
+}
+function WSManTest_Response(imsg)
+{
+ imsg.on('data', function (chunk) { console.log(chunk); });
+}
+
+
+//var req = digest.request({ protocol: "ws:", method: "GET", host: "127.0.0.1", path: "/", port: 9093 }, function (imsg) { console.log(imsg.statusCode == 200 ? "SUCCESS!" : "FAIL!"); });
+//var req = http.request({ protocol: "http:", method: "POST", host: "127.0.0.1", path: "/", port: 9093, headers: { Expect: '100-Continue' } }, function (imsg) { console.log(imsg.statusCode == 200 ? "SUCCESS!" : "FAIL!"); });
+//var req = digest.request({ protocol: "http:", method: "POST", host: "127.0.0.1", path: "/", port: 9093, headers: { Expect: '100-Continue' } }, function (imsg) { console.log(imsg.statusCode == 200 ? "SUCCESS!" : "FAIL!"); });
+
+//req.on('upgrade', function (res, sk, h) { console.log("Upgraded to WebSocket!"); });
+//req.on('error', function () { console.log("Error occured"); });
+//req.on('continue', function () { console.log("Received Continue"); this.write("test"); this.end(); });
+
+//function OnCheckContinue(imsg, resp)
+//{
+// console.log("Recevied: Expect-100 Continue");
+// if (imsg.Digest_IsAuthenticated('www.meshcentral.com') == 1)
+// {
+// var uname = imsg.Digest_GetUsername();
+// console.log("Digest Username was: " + uname);
+// if (uname == 'bryan' && imsg.Digest_ValidatePassword('roe') == 1)
+// {
+// console.log("Validated");
+// imsg.on('data', function (chunk) { console.log('Received: ' + chunk.toString()); });
+// imsg.on('end', function () { console.log('Received Complete'); });
+// resp.writeContinue();
+// }
+// else
+// {
+// console.log("Bad Username/Password");
+// resp.statusCode = "500";
+// resp.statusMessage = "Error";
+// resp.end();
+// }
+// }
+// else
+// {
+// console.log("Sending Unauthorized");
+// imsg.Digest_SendUnauthorized('www.meshcentral.com', 'oops');
+// }
+//}
+//function OnCheckContinue_NoDigest(imsg, resp)
+//{
+// console.log("Recevied: Expect-100 Continue");
+
+// imsg.on('data', function (chunk) { console.log('Received: ' + chunk.toString()); });
+// imsg.on('end', function () { console.log('Received Complete'); });
+// resp.writeContinue();
+//}
+//function OnServerUpgrade(imsg, sck, head)
+//{
+// if(imsg.Digest_IsAuthenticated('www.meshcentral.com')==1)
+// {
+// var uname = imsg.Digest_GetUsername();
+// console.log("Digest Username was: " + uname);
+// if(uname == 'bryan' && imsg.Digest_ValidatePassword('roe')==1)
+// {
+// console.log("Upgrading to WebSocket");
+// sck.upgradeWebSocket();
+// }
+// else
+// {
+// console.log("Bad Username/Password");
+// sck.end();
+// }
+// }
+// else
+// {
+// console.log("Sending Unauthorized");
+// imsg.Digest_SendUnauthorized('www.meshcentral.com', 'oops');
+// }
+//}
+
+
+//function onVerifyServer(clientName, certs) {
+// console.log("Server Name = " + clientName + "\n");
+
+// for (var i = 0; i < certs.length; ++i) {
+// console.log(" Fingerprint = " + certs[i].fingerprint + "\n");
+// }
+// //throw ("Not Valid");
+//}
+//function onVerifyClient(clientName, certs)
+//{
+// console.log("Client Name = " + clientName + "\n");
+
+// for (var i = 0; i < certs.length; ++i) {
+// console.log(" Fingerprint = " + certs[i].fingerprint + "\n");
+// }
+// //throw ("Not Valid");
+//}
+//function onVerify(serverName, certs)
+//{
+// console.log("ServerName = " + serverName + "\n");
+
+// for (var i = 0; i < certs.length;++i)
+// {
+// console.log(" Fingerprint = " + certs[i].fingerprint + "\n");
+// }
+// //throw ("Not Valid");
+//}
+
+//function OnRequest(req, res)
+//{
+// console.log("Received Request for: " + req.url);
+
+//}
+
+
+
diff --git a/Debug/ChildProcessTest.js b/Debug/ChildProcessTest.js
new file mode 100644
index 0000000..81cf49e
--- /dev/null
+++ b/Debug/ChildProcessTest.js
@@ -0,0 +1,27 @@
+var child = require('child_process');
+var childProcess = null;
+
+if (process.platform == 'win32')
+{
+ childProcess = child.execFile(process.env['windir'] + '\\system32\\cmd.exe', ['/c', 'dir'], OnChild);
+}
+else if (process.platform == 'linux')
+{
+ childProcess = child.execFile('/bin/sh', ['sh', '-c', 'ls'], OnChild);
+}
+
+if (childProcess != null)
+{
+ console.log('PID = ' + childProcess.pid);
+ childProcess.stdout.on('data', function (chunk) { console.log(chunk.toString()); });
+ childProcess.on('exit', function (code, sig) { console.log("Process Exited with code: " + code.toString()); });
+}
+//for (var envkey in process.env)
+//{
+// console.log("Environment Variable: [" + envkey + "] = " + process.env[envkey]);
+//}
+
+function OnChild(err, stdErr, stdOut)
+{
+
+}
\ No newline at end of file
diff --git a/Debug/PostDigest.js b/Debug/PostDigest.js
index bd50123..b577167 100644
--- a/Debug/PostDigest.js
+++ b/Debug/PostDigest.js
@@ -4,11 +4,15 @@ var req = "";
var gtunnel = "";
var digest = require('http-digest').create("bryan", "roe");
+console.log("Process.execPath = " + process.execPath);
console.log("Starting POST Digest Test");
server = http.createServer(OnRequest);
server.listen(9093);
+
+console.log("Server Address", server._address());
+
server.on('upgrade', OnServerUpgrade);
server.on('checkContinue', OnCheckContinue);
//server.on('checkContinue', OnCheckContinue_NoDigest);
diff --git a/makefile b/makefile
index c260e8f..f772324 100644
--- a/makefile
+++ b/makefile
@@ -39,6 +39,7 @@ SOURCES += microscript/ILibWebServer_Duktape.c microscript/ILibDuktape_SimpleDat
SOURCES += microscript/ILibDuktape_ProcessPipe.c microscript/ILibDuktape_fs.c microscript/ILibDuktape_SHA256.c microscript/ILibduktape_EventEmitter.c
SOURCES += microscript/ILibDuktape_EncryptionStream.c microscript/ILibDuktape_Polyfills.c microscript/ILibDuktape_Dgram.c
SOURCES += microscript/ILibDuktape_ScriptContainer.c microscript/ILibDuktape_MemoryStream.c microscript/ILibDuktape_NetworkMonitor.c
+SOURCES += microscript/ILibDuktape_ChildProcess.c
# Mesh Agent core
SOURCES += meshcore/agentcore.c meshconsole/main.c meshcore/meshinfo.c
diff --git a/meshconsole/MeshConsole.vcxproj b/meshconsole/MeshConsole.vcxproj
index bf81d22..11da617 100644
--- a/meshconsole/MeshConsole.vcxproj
+++ b/meshconsole/MeshConsole.vcxproj
@@ -31,6 +31,7 @@
+
@@ -91,6 +92,7 @@
+
diff --git a/meshconsole/MeshConsole.vcxproj.filters b/meshconsole/MeshConsole.vcxproj.filters
index cfd2e02..3bafde8 100644
--- a/meshconsole/MeshConsole.vcxproj.filters
+++ b/meshconsole/MeshConsole.vcxproj.filters
@@ -187,6 +187,9 @@
Microscript
+
+ Microscript
+
@@ -337,6 +340,9 @@
Microscript
+
+ Microscript
+
diff --git a/meshconsole/main.c b/meshconsole/main.c
index c074852..abd90c7 100644
--- a/meshconsole/main.c
+++ b/meshconsole/main.c
@@ -29,6 +29,8 @@ limitations under the License.
#include
#endif
+#include "microscript/ILibDuktape_ScriptContainer.h"
+
MeshAgentHostContainer *agentHost = NULL;
#ifdef WIN32
@@ -64,45 +66,12 @@ void BreakSink(int s)
int main(int argc, char **argv)
{
// Check if .JS file is integrated with executable
- FILE *tmpFile;
char *integratedJavaScript = NULL;
int integratedJavaScriptLen = 0;
-#ifdef WIN32
- if (ILibString_EndsWith(argv[0], -1, ".exe", 4) == 0)
- {
- sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", argv[0]);
- tmpFile = fopen(ILibScratchPad, "rb");
- }
- else
- {
- tmpFile = fopen(argv[0], "rb");
- }
-#else
- tmpFile = fopen(argv[0], "rb");
-#endif
-
- if (tmpFile != NULL)
- {
- fseek(tmpFile, 0, SEEK_END);
- fseek(tmpFile, ftell(tmpFile) - 4, SEEK_SET);
- ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
- fseek(tmpFile, 0, SEEK_END);
- if (ftell(tmpFile) == ntohl(((int*)ILibScratchPad)[0]))
- {
- fseek(tmpFile, ftell(tmpFile) - 8, SEEK_SET);
- ignore_result(fread(ILibScratchPad, 1, 4, tmpFile));
- integratedJavaScriptLen = ntohl(((int*)ILibScratchPad)[0]);
- integratedJavaScript = ILibMemory_Allocate(1+integratedJavaScriptLen, 0, NULL, NULL);
- fseek(tmpFile, 0, SEEK_END);
- fseek(tmpFile, ftell(tmpFile) - 8 - integratedJavaScriptLen, SEEK_SET);
- ignore_result(fread(integratedJavaScript, 1, integratedJavaScriptLen, tmpFile));
- integratedJavaScript[integratedJavaScriptLen] = 0;
- }
- fclose(tmpFile);
- }
-
int retCode = 0;
+ ILibDuktape_ScriptContainer_CheckEmbedded(argv, &integratedJavaScript, &integratedJavaScriptLen);
+
if (argc > 2 && memcmp(argv[1], "-faddr", 6) == 0)
{
uint64_t addrOffset;
diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c
index da62b8b..a2540c3 100644
--- a/meshcore/agentcore.c
+++ b/meshcore/agentcore.c
@@ -111,6 +111,11 @@ typedef struct ScriptContainerSettings
}ScriptContainerSettings;
#pragma pack(push, 1)
+typedef struct MeshCommand_BinaryPacket_ServerId
+{
+ unsigned short command;
+ char serverId[UTIL_HASHSIZE];
+}MeshCommand_BinaryPacket_ServerId;
typedef struct MeshCommand_BinaryPacket_AuthRequest
{
unsigned short command;
@@ -1087,12 +1092,10 @@ int agent_GenerateCertificates(MeshAgentHostContainer *agent, char* certfile)
{
// Generate a new random node certificate
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost, ILibRemoteLogging_Flags_VerbosityLevel_1, "...Generating new Node Certificate");
-
do
{
if (util_mkCert(NULL, &(agent->selfcert), 3072, 10000, "MeshNodeCertificate", CERTIFICATE_ROOT, NULL) == 0) return -1;
util_keyhash(agent->selfcert, agent->g_selfid);
-
} while (((int*)agent->g_selfid)[0] == 0); // This removes any chance that the self_id starts with 32 bits of zeros.
ILibRemoteLogging_printf(ILibChainGetLogger(agent->chain), ILibRemoteLogging_Modules_Agent_GuardPost, ILibRemoteLogging_Flags_VerbosityLevel_1, "...g_selfid = %s", ILibRemoteLogging_ConvertToHex(agent->g_selfid, (int)sizeof(agent->g_selfid)));
}
@@ -1361,7 +1364,6 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Hash the server's web certificate and check if it matches the one in the auth request
util_keyhash2(peer, ILibScratchPad2); // Hash the server certificate public key and place it
-
if (memcmp(ILibScratchPad2, AuthRequest->serverHash, sizeof(AuthRequest->serverHash)) != 0) { printf("Bad server certificate hash\r\n"); break; } // TODO: Disconnect
memcpy_s(agent->serverNonce, sizeof(agent->serverNonce), AuthRequest->serverNonce, sizeof(AuthRequest->serverNonce));
@@ -1418,8 +1420,13 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
if (!d2i_X509(&serverCert, (const unsigned char**)&AuthVerify->cert, AuthVerify->certLen)) { printf("Invalid server certificate\r\n"); break; } // TODO: Disconnect
// Check if this certificate public key hash matches what we want
- X509_pubkey_digest(serverCert, EVP_sha384(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1
- if (memcmp(ILibScratchPad, agent->serverHash, UTIL_HASHSIZE) != 0) { printf("Server certificate mismatch\r\n"); break; } // TODO: Disconnect
+ X509_pubkey_digest(serverCert, EVP_sha384(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1, SHA384
+ if (memcmp(ILibScratchPad, agent->serverHash, UTIL_HASHSIZE) != 0) {
+ X509_pubkey_digest(serverCert, EVP_sha256(), (unsigned char*)ILibScratchPad, (unsigned int*)&hashlen); // OpenSSL 1.1, SHA256 (For older .mshx policy file)
+ if (memcmp(ILibScratchPad, agent->serverHash, 32) != 0) {
+ printf("Server certificate mismatch\r\n"); break; // TODO: Disconnect
+ }
+ }
// Compute the authentication hash
SHA384_Init(&c);
@@ -1440,6 +1447,7 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge
// Send to the server information about this agent (TODO: Replace this with a struct)
MeshCommand_BinaryPacket_AuthInfo *info = (MeshCommand_BinaryPacket_AuthInfo*)ILibScratchPad2;
+ memset(info, 0, sizeof(MeshCommand_BinaryPacket_AuthInfo)); // Required because if hash are SHA256, they will not fully fill the struct.
info->command = htons(MeshCommand_AuthInfo);
info->infoVersion = htonl(1);
info->agentId = htonl(MESH_AGENTID);
@@ -1777,6 +1785,12 @@ void MeshServer_OnResponse(ILibWebClient_StateObject WebStateObject, int Interru
agent->serverAuthState = 0; // We are not authenticated. Bitmask: 1 = Server Auth, 2 = Agent Auth.
agent->serverConnectionState = 2;
+ // Send the ServerID to the server, this is useful for the server to use the correct certificate to authenticate.
+ MeshCommand_BinaryPacket_ServerId *serveridcmd = (MeshCommand_BinaryPacket_ServerId*)ILibScratchPad2;
+ serveridcmd->command = htons(MeshCommand_ServerId);
+ memcpy_s(serveridcmd->serverId, sizeof(serveridcmd->serverId), agent->serverHash, sizeof(agent->serverHash)); // Place our mesh agent nonce
+ ILibWebClient_WebSocket_Send(WebStateObject, ILibWebClient_WebSocket_DataType_BINARY, (char*)serveridcmd, sizeof(MeshCommand_BinaryPacket_ServerId), ILibAsyncSocket_MemoryOwnership_USER, ILibWebClient_WebSocket_FragmentFlag_Complete);
+
// Start authentication by sending a auth nonce & server TLS cert hash.
// Send 384 bits SHA384 hash of TLS cert public key + 384 bits nonce
util_random(sizeof(agent->agentNonce), agent->agentNonce); // Generate a new mesh agent connection nonce
@@ -1977,11 +1991,14 @@ void MeshServer_ConnectEx(MeshAgentHostContainer *agent)
return;
}
+ memset(agent->serverHash, 0, sizeof(agent->serverHash));
util_hexToBuf(f->data, f->datalength, agent->serverHash);
ILibDestructParserResults(rs);
-
- if (ILibSimpleDataStore_Get(agent->masterDb, "MeshID", ILibScratchPad, sizeof(ILibScratchPad)) == 0) { printf("MeshID entry not found in Db!\n"); return; }
- memcpy_s(agent->meshId, sizeof(agent->meshId), ILibScratchPad, UTIL_HASHSIZE);
+
+ len = ILibSimpleDataStore_Get(agent->masterDb, "MeshID", ILibScratchPad, sizeof(ILibScratchPad));
+ if ((len != 32) && (len != 48)) { printf("MeshID entry not found in db or bad size.\n"); return; } // Make sure MeshID is both present and SHA256 or SHA384.
+ memset(agent->meshId, 0, sizeof(agent->meshId)); // Clear the meshid first in case we copy SHA256
+ memcpy_s(agent->meshId, sizeof(agent->meshId), ILibScratchPad, len); // Copy the correct length
#ifndef MICROSTACK_NOTLS
util_keyhash(agent->selfcert, agent->g_selfid); // Compute our own identifier using our certificate
@@ -2393,6 +2410,7 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
#endif
// Check to see if we need to import a settings file
+ importSettings(agentHost, MeshAgent_MakeAbsolutePath(agentHost->exePath, ".mshx"));
importSettings(agentHost, MeshAgent_MakeAbsolutePath(agentHost->exePath, ".msh"));
#ifdef WIN32
diff --git a/meshcore/agentcore.h b/meshcore/agentcore.h
index 2b1d401..2fd9cd0 100644
--- a/meshcore/agentcore.h
+++ b/meshcore/agentcore.h
@@ -92,6 +92,7 @@ typedef enum MeshCommands_Binary
MeshCommand_AuthVerify = 2, // Agent or server signature
MeshCommand_AuthInfo = 3, // Agent information
MeshCommand_AuthConfirm = 4, // Server confirm to the agent that is it authenticated
+ MeshCommand_ServerId = 5, // Optional, agent sends the expected serverid to the server. Useful if the server has many server certificates.
MeshCommand_CoreModule = 10, // New core modules to be used instead of the old one, if empty, remove the core module
MeshCommand_CoreModuleHash = 11, // Request/return the SHA384 hash of the core module
MeshCommand_AgentHash = 12, // Request/return the SHA384 hash of the agent executable
diff --git a/meshservice/MeshService.vcxproj b/meshservice/MeshService.vcxproj
index 5e8143e..cca3471 100644
--- a/meshservice/MeshService.vcxproj
+++ b/meshservice/MeshService.vcxproj
@@ -259,6 +259,7 @@
+
@@ -321,6 +322,7 @@
+
diff --git a/meshservice/MeshService.vcxproj.filters b/meshservice/MeshService.vcxproj.filters
index 3105250..3f7f925 100644
--- a/meshservice/MeshService.vcxproj.filters
+++ b/meshservice/MeshService.vcxproj.filters
@@ -184,6 +184,9 @@
Microstack
+
+ Microscript
+
@@ -358,5 +361,8 @@
Microstack
+
+ Microscript
+
\ No newline at end of file
diff --git a/meshservice/ServiceMain.c b/meshservice/ServiceMain.c
index 2995c94..8422c35 100644
--- a/meshservice/ServiceMain.c
+++ b/meshservice/ServiceMain.c
@@ -35,6 +35,8 @@ limitations under the License.
#include "microstack/ILibCrypto.h"
#include "meshcore/agentcore.h"
+#include "microscript/ILibDuktape_ScriptContainer.h"
+
#ifndef _MINCORE
// #include "../kvm/kvm.h"
int SetupWindowsFirewall(wchar_t* processname);
@@ -702,6 +704,10 @@ int main(int argc, char* argv[])
return(0);
}
+ char *integratedJavaScript;
+ int integragedJavaScriptLen;
+ ILibDuktape_ScriptContainer_CheckEmbedded(argv, &integratedJavaScript, &integragedJavaScriptLen);
+
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Process extra switches
@@ -759,7 +765,7 @@ int main(int argc, char* argv[])
return 0;
}
#else
- else if (argc > 1 && ((strcasecmp(argv[1], "run") == 0) || (strcasecmp(argv[1], "--slave") == 0)))
+ else if (integratedJavaScript != NULL || (argc > 1 && ((strcasecmp(argv[1], "run") == 0) || (strcasecmp(argv[1], "--slave") == 0))))
{
// Run the mesh agent in console mode, since the agent is compiled for windows service, the KVM will not work right. This is only good for testing.
SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); // Set SIGNAL on windows to listen for Ctrl-C
@@ -767,6 +773,8 @@ int main(int argc, char* argv[])
__try
{
agent = MeshAgent_Create();
+ agent->meshCoreCtx_embeddedScript = integratedJavaScript;
+ agent->meshCoreCtx_embeddedScriptLen = integragedJavaScriptLen;
MeshAgent_Start(agent, argc, argv);
retCode = agent->exitCode;
MeshAgent_Destroy(agent);
diff --git a/microlms/service/ServiceMain.c b/microlms/service/ServiceMain.c
index 62ad927..2f69390 100644
--- a/microlms/service/ServiceMain.c
+++ b/microlms/service/ServiceMain.c
@@ -136,7 +136,7 @@ void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
// Run the MicroLMS Service
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
Chain = ILibCreateChain();
- MicroLMS = ILibLMS_Create(Chain, selfexe);
+ MicroLMS = ILibLMS_Create(Chain, selfexe, NULL);
if (MicroLMS != NULL)
{
printf("Starting MicroLMS.\r\n");
@@ -580,7 +580,7 @@ int main(int argc, char* argv[])
{
// Run as an command line application
Chain = ILibCreateChain();
- MicroLMS = ILibLMS_Create(Chain, selfexe);
+ MicroLMS = ILibLMS_Create(Chain, selfexe, NULL);
if (MicroLMS != NULL)
{
#ifdef NOCOMMANDER
diff --git a/microscript/ILibDuktape_ChildProcess.c b/microscript/ILibDuktape_ChildProcess.c
new file mode 100644
index 0000000..f1955b9
--- /dev/null
+++ b/microscript/ILibDuktape_ChildProcess.c
@@ -0,0 +1,285 @@
+#include "ILibDuktape_ChildProcess.h"
+
+#include "ILibDuktapeModSearch.h"
+#include "../microstack/ILibParsers.h"
+#include "../microstack/ILibProcessPipe.h"
+
+#include "ILibDuktape_Helpers.h"
+#include "ILibDuktape_ReadableStream.h"
+#include "ILibDuktape_WritableStream.h"
+#include "ILibDuktape_EventEmitter.h"
+
+#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
+#define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process"
+#define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf"
+
+typedef struct ILibDuktape_ChildProcess_SubProcess
+{
+ duk_context *ctx;
+ void *subProcess;
+ void *chain;
+ ILibProcessPipe_Process childProcess;
+
+ ILibDuktape_readableStream *stdOut;
+ ILibDuktape_readableStream *stdErr;
+ ILibDuktape_WritableStream *stdIn;
+
+ int exitCode;
+}ILibDuktape_ChildProcess_SubProcess;
+
+void ILibDuktape_ChildProcess_SubProcess_StdOut_OnPause(ILibDuktape_readableStream *sender, void *user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdOut(p->childProcess));
+}
+void ILibDuktape_ChildProcess_SubProcess_StdOut_OnResume(ILibDuktape_readableStream *sender, void *user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdOut(p->childProcess));
+}
+void ILibDuktape_ChildProcess_SubProcess_StdErr_OnPause(ILibDuktape_readableStream *sender, void *user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Process_GetStdErr(p->childProcess));
+}
+void ILibDuktape_ChildProcess_SubProcess_StdErr_OnResume(ILibDuktape_readableStream *sender, void *user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Process_GetStdErr(p->childProcess));
+}
+ILibTransport_DoneState ILibDuktape_ChildProcess_SubProcess_StdIn_WriteHandler(ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ return(ILibProcessPipe_Process_WriteStdIn(p->childProcess, buffer, bufferLen, ILibTransport_MemoryOwnership_USER));
+}
+void ILibDuktape_ChildProcess_SubProcess_StdIn_EndHandler(ILibDuktape_WritableStream *sender, void *user)
+{
+}
+
+void ILibDuktape_ChildProcess_SubProcess_ExitHandler(ILibProcessPipe_Process sender, int exitCode, void* user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ p->exitCode = exitCode;
+
+ duk_push_heapptr(p->ctx, p->subProcess); // [childProcess]
+ duk_get_prop_string(p->ctx, -1, "emit"); // [childProcess][emit]
+ duk_swap_top(p->ctx, -2); // [emit][this]
+ duk_push_string(p->ctx, "exit"); // [emit][this][exit]
+ duk_push_int(p->ctx, p->exitCode); // [emit][this][exit][exitCode]
+ duk_push_null(p->ctx); // [emit][this][exit][exitCode][sig]
+ if (duk_pcall_method(p->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(p->ctx, "child_process.subProcess.exit(): "); }
+ duk_pop(p->ctx);
+
+}
+void ILibDuktape_ChildProcess_SubProcess_StdOutHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ ILibDuktape_readableStream_WriteData(p->stdOut, buffer, bufferLen);
+ *bytesConsumed = bufferLen;
+}
+void ILibDuktape_ChildProcess_SubProcess_StdErrHandler(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ ILibDuktape_readableStream_WriteData(p->stdErr, buffer, bufferLen);
+ *bytesConsumed = bufferLen;
+}
+void ILibDuktape_ChildProcess_SubProcess_SendOK(ILibProcessPipe_Process sender, void* user)
+{
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)user;
+ ILibDuktape_WritableStream_Ready(p->stdIn);
+}
+duk_ret_t ILibDuktape_ChildProcess_Kill(duk_context *ctx)
+{
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_MemBuf);
+ ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBuffer(ctx, -1, NULL);
+
+ ILibProcessPipe_Process_SoftKill(p->childProcess);
+
+ return(0);
+}
+ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUSH(duk_context *ctx, ILibProcessPipe_Process mProcess, void *callback)
+{
+ duk_push_object(ctx); // [ChildProcess]
+ duk_push_pointer(ctx, mProcess); // [ChildProcess][ptr]
+ duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Process); // [ChildProcess]
+ duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_ChildProcess_SubProcess)); // [ChildProcess][buffer]
+ ILibDuktape_ChildProcess_SubProcess *retVal = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBuffer(ctx, -1, NULL);
+ duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_MemBuf); // [ChildProcess]
+
+ memset(retVal, 0, sizeof(ILibDuktape_ChildProcess_SubProcess));
+ retVal->ctx = ctx;
+ retVal->subProcess = duk_get_heapptr(ctx, -1);
+ retVal->childProcess = mProcess;
+ retVal->chain = Duktape_GetChain(ctx);
+
+ ILibDuktape_CreateReadonlyProperty_int(ctx, "pid", ILibProcessPipe_Process_GetPID(mProcess));
+ ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_Create(ctx);
+
+ ILibDuktape_EventEmitter_CreateEventEx(emitter, "exit");
+ ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
+
+ ILibDuktape_CreateInstanceMethod(ctx, "kill", ILibDuktape_ChildProcess_Kill, 0);
+
+ duk_push_object(ctx);
+ retVal->stdOut = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdOut_OnPause, ILibDuktape_ChildProcess_SubProcess_StdOut_OnResume, retVal);
+ ILibDuktape_CreateReadonlyProperty(ctx, "stdout");
+
+ duk_push_object(ctx);
+ retVal->stdErr = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdErr_OnPause, ILibDuktape_ChildProcess_SubProcess_StdErr_OnResume, retVal);
+ ILibDuktape_CreateReadonlyProperty(ctx, "stderr");
+
+ duk_push_object(ctx);
+ retVal->stdIn = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdIn_WriteHandler, ILibDuktape_ChildProcess_SubProcess_StdIn_EndHandler, retVal);
+ ILibDuktape_CreateReadonlyProperty(ctx, "stdin");
+
+ if (callback != NULL) { ILibDuktape_EventEmitter_AddOnce(emitter, "exit", callback); }
+
+ ILibProcessPipe_Process_AddHandlers(mProcess, 4096, ILibDuktape_ChildProcess_SubProcess_ExitHandler,
+ ILibDuktape_ChildProcess_SubProcess_StdOutHandler,
+ ILibDuktape_ChildProcess_SubProcess_StdErrHandler,
+ ILibDuktape_ChildProcess_SubProcess_SendOK, retVal);
+
+ return(retVal);
+}
+
+duk_ret_t ILibDuktape_ChildProcess_Manager_Finalizer(duk_context *ctx)
+{
+ duk_get_prop_string(ctx, 0, ILibDuktape_ChildProcess_Manager);
+ ILibProcessPipe_Manager manager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
+
+ ILibChain_SafeRemove(((ILibChain_Link*)manager)->ParentChain, manager);
+ return(0);
+}
+duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
+{
+ int nargs = duk_get_top(ctx);
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager);
+ ILibProcessPipe_Manager manager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1);
+ duk_size_t targetLen;
+ char *target = (char*)duk_get_lstring(ctx, 0, &targetLen);
+ char **args = NULL;
+ int i, x;
+ void *callback = NULL;
+ ILibProcessPipe_Process p = NULL;
+
+ for (i = 0; i < nargs; ++i)
+ {
+ if (duk_is_array(ctx, i) != 0)
+ {
+ int arrLen = duk_get_length(ctx, i);
+#ifdef WIN32
+ args = (char**)_alloca((arrLen + 1) * sizeof(char*));
+#else
+ args = (char**)alloca((arrLen + 1) * sizeof(char*));
+#endif
+ for (x = 0; x < arrLen; ++x)
+ {
+ duk_get_prop_index(ctx, i, x);
+ args[x] = (char*)duk_get_string(ctx, -1);
+ }
+ args[x] = NULL;
+ }
+ else if (duk_is_function(ctx, i))
+ {
+ callback = duk_get_heapptr(ctx, i);
+ }
+ }
+
+#ifdef WIN32
+ if (target[0] == '%')
+ {
+ size_t evsize;
+ int pctx = ILibString_IndexOf(target + 1, (int)targetLen - 1, "%", 1);
+ if (pctx > 0)
+ {
+ memcpy_s(ILibScratchPad, sizeof(ILibScratchPad), target + 1, pctx);
+ ILibScratchPad[pctx] = 0;
+ getenv_s(&evsize, ILibScratchPad2, sizeof(ILibScratchPad2), ILibScratchPad);
+ if (evsize > 0)
+ {
+ strncpy_s(ILibScratchPad2 + evsize - 1, sizeof(ILibScratchPad2) - evsize, target + pctx + 2, targetLen - pctx - 2);
+ target = ILibScratchPad2;
+ }
+ }
+ }
+#endif
+
+ p = ILibProcessPipe_Manager_SpawnProcess(manager, target, args);
+ if (p == NULL)
+ {
+ return(ILibDuktape_Error(ctx, "child_process.execFile(): Could not exec [%s]", target));
+ }
+ ILibDuktape_ChildProcess_SpawnedProcess_PUSH(ctx, p, callback);
+ return(1);
+}
+void ILibDuktape_ChildProcess_PUSH(duk_context *ctx, void *chain)
+{
+ duk_push_object(ctx);
+ duk_push_pointer(ctx, (void*)ILibProcessPipe_Manager_Create(chain));
+ duk_put_prop_string(ctx, -2, ILibDuktape_ChildProcess_Manager);
+ ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ChildProcess_Manager_Finalizer);
+
+ ILibDuktape_CreateInstanceMethod(ctx, "execFile", ILibDuktape_ChildProcess_execFile, DUK_VARARGS);
+}
+void ILibDuktape_ChildProcess_Init(duk_context *ctx)
+{
+ ILibDuktape_ModSearch_AddHandler(ctx, "child_process", ILibDuktape_ChildProcess_PUSH);
+}
+
+#ifdef __DOXY__
+/*!
+\implements EventEmitter
+\brief The child_process module provides the ability to spawn child processes. Note: To use, must require('child_process')
+*/
+class ChildProcess
+{
+public:
+ /*!
+ \brief The specified file is spawned as a child process
+ \param file \ Required. The name or path of the executable file to run
+ \param args \ Optional. List of string arguments
+ \param options