From 429b645a54fce6e935d5f128d0acc227f3a01806 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Tue, 12 Mar 2019 22:23:30 -0700 Subject: [PATCH] 1. Added ability to modify environment variables on ScriptContainers 2. Fixed bug, where child ScriptContainer would exit if return value had a JSON parse error --- microscript/ILibDuktape_ScriptContainer.c | 100 ++++++++++++++++++++-- microstack/ILibProcessPipe.c | 11 ++- microstack/ILibProcessPipe.h | 3 +- 3 files changed, 102 insertions(+), 12 deletions(-) diff --git a/microscript/ILibDuktape_ScriptContainer.c b/microscript/ILibDuktape_ScriptContainer.c index 2072c18..c894bf1 100644 --- a/microscript/ILibDuktape_ScriptContainer.c +++ b/microscript/ILibDuktape_ScriptContainer.c @@ -910,7 +910,26 @@ void ILibDuktape_ScriptContainer_Process_SIGTERM_Hook(ILibDuktape_EventEmitter * } } +duk_ret_t ILibDuktape_Process_setenv(duk_context *ctx) +{ + char *name = (char*)duk_require_string(ctx, 0); + char *value = Duktape_GetBuffer(ctx, 1, NULL); +#ifdef WIN32 + SetEnvironmentVariableA((LPCSTR)name, (LPCTSTR)value); +#else + if (value != NULL) + { + setenv(name, value, 1); + } + else + { + unsetenv(name); + } +#endif + + return(0); +} void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList) { int i = 0; @@ -921,8 +940,8 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList) ILibDuktape_WriteID(ctx, "process"); ILibDuktape_CreateEventWithGetter(ctx, "env", ILibDuktape_ScriptContainer_Process_env); ILibDuktape_CreateInstanceMethod(ctx, "cwd", ILibDuktape_Process_cwd, 0); - - + ILibDuktape_CreateInstanceMethod(ctx, "setenv", ILibDuktape_Process_setenv, 2); + #if defined(WIN32) // [g][process][platform] duk_push_string(ctx, "win32"); #elif defined(__APPLE__) @@ -2240,13 +2259,27 @@ void ILibDuktape_ScriptContainer_Slave_ProcessCommands(ILibDuktape_ScriptContain } if (!duk_is_undefined(slave->ctx, -2)) { - duk_dup(slave->ctx, -2); // [json][retJSON][retVal] - duk_json_encode(slave->ctx, -1); // [json][retJSON][retValJSON] - duk_put_prop_string(slave->ctx, -2, "result"); // [json][retJSON] + if (duk_peval_string(slave->ctx, "JSON.stringify") == 0) // [json][retJSON][stringify] + { + duk_dup(slave->ctx, -3); // [json][retJSON][stringify][retVal] + if (duk_pcall(slave->ctx, 1) == 0) // [json][retJSON][retValJSON] + { + duk_put_prop_string(slave->ctx, -2, "result"); // [json][retJSON] + } + else + { + duk_pop(slave->ctx); // [json][retJSON] + } + } + else + { + duk_pop(slave->ctx); // [json][retJSON] + } } } else { + // Failure // [json][error] char *errMsg = (char*)duk_safe_to_string(slave->ctx, -1); duk_push_string(slave->ctx, errMsg); // [json][error][errMsg] @@ -2402,6 +2435,10 @@ int ILibDuktape_ScriptContainer_StartSlave(void *chain, ILibProcessPipe_Manager ILibChainSetLogger(chain, logger); #endif +#if defined(_POSIX) && !defined(__APPLE__) + ILibCriticalLogFilename = "/var/tmp/agentSlave"; +#endif + #ifndef MICROSTACK_NOTLS util_openssl_init(); #endif @@ -3097,14 +3134,61 @@ duk_ret_t ILibDuktape_ScriptContainer_Create(duk_context *ctx) unsigned int executionTimeout = duk_is_object(ctx, 0)?Duktape_GetIntPropertyValue(ctx, 0, "executionTimeout", 0): (unsigned int)duk_require_int(ctx, 0); master->ChildSecurityFlags = (duk_is_object(ctx, 0) ? Duktape_GetIntPropertyValue(ctx, 0, "childSecurityFlags", 0): (unsigned int)duk_require_int(ctx, 1)) | SCRIPT_ENGINE_NO_MESH_AGENT_ACCESS; - if (sessionIdSpecified != 0) + if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, "env")) { - master->child = ILibProcessPipe_Manager_SpawnProcessEx3(manager, exePath, (char * const*)param, ILibProcessPipe_SpawnTypes_SPECIFIED_USER, sessionId, 2 * sizeof(void*)); + char tmp[32768]; + size_t v = 0; +#ifdef WIN32 + char *key, *value; + duk_size_t keyLen, valueLen; +#else + char **envvars = (char**)tmp; +#endif + + + duk_get_prop_string(ctx, 0, "env"); // [env] + duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);// [env][enum] + while (duk_next(ctx, -1, 1)) // [env][enum][key][val] + { +#ifdef WIN32 + key = (char*)duk_to_lstring(ctx, -2, &keyLen); + value = (char*)duk_to_lstring(ctx, -1, &valueLen); + if (keyLen + valueLen + 3 + v > sizeof(tmp)) { return(ILibDuktape_Error(ctx, "Environment Variables too Large")); } + v += sprintf_s(tmp + v, sizeof(tmp) - v, "%s=%s", key, value); + (tmp + v)[0] = 0; ++v; +#else + v += (2 * sizeof(char*)); + if (v < sizeof(tmp)) + { + envvars[0] = (char*)duk_to_string(ctx, -2); + envvars[1] = (char*)duk_to_string(ctx, -1); + envvars = (char**)((char*)envvars + 2 * sizeof(char*)); + } +#endif + duk_pop_2(ctx); // [env][enum] + } + duk_pop_2(ctx); // ... +#ifdef WIN32 + (tmp + v)[0] = 0; ++v; +#else + v += sizeof(char*); + if (v < sizeof(tmp)) + { + envvars[0] = NULL; + } + else + { + return(ILibDuktape_Error(ctx, "Environment Variables are too large")); + } +#endif + master->child = ILibProcessPipe_Manager_SpawnProcessEx4(manager, exePath, (char * const*)param, sessionIdSpecified!=0?ILibProcessPipe_SpawnTypes_SPECIFIED_USER:spawnType, sessionId, (void*)tmp, 2 * sizeof(void*)); } else { - master->child = ILibProcessPipe_Manager_SpawnProcessEx2(manager, exePath, (char * const*)param, spawnType, 2 * sizeof(void*)); + master->child = ILibProcessPipe_Manager_SpawnProcessEx3(manager, exePath, (char * const*)param, sessionIdSpecified!=0?ILibProcessPipe_SpawnTypes_SPECIFIED_USER:spawnType, sessionId, 2 * sizeof(void*)); } + + if (master->child == NULL) { return(ILibDuktape_Error(ctx, "ScriptContainer.Create(): Error spawning child process, using [%s]", exePath)); } duk_push_true(ctx); diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index 85d8b27..ae68561 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -703,7 +703,7 @@ void ILibProcessPipe_Process_SoftKill(ILibProcessPipe_Process p) #endif } -ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx3(ILibProcessPipe_Manager pipeManager, char* target, char* const* parameters, ILibProcessPipe_SpawnTypes spawnType, void *sid, int extraMemorySize) +ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx4(ILibProcessPipe_Manager pipeManager, char* target, char* const* parameters, ILibProcessPipe_SpawnTypes spawnType, void *sid, void *envvars, int extraMemorySize) { ILibProcessPipe_Process_Object* retVal = NULL; @@ -790,8 +790,8 @@ ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx3(ILibProcessPipe_ info.dwFlags |= STARTF_USESTDHANDLES; } - if ((spawnType == ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessA(target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo)) || - (spawnType != ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessAsUserA(userToken, target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &info, &processInfo))) + if ((spawnType == ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessA(target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW, envvars, NULL, &info, &processInfo)) || + (spawnType != ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessAsUserA(userToken, target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW, envvars, NULL, &info, &processInfo))) { if (spawnType != ILibProcessPipe_SpawnTypes_DETACHED) { @@ -897,6 +897,11 @@ ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx3(ILibProcessPipe_ { ignore_result(setuid((uid_t)UID)); } + while (envvars != NULL && ((char**)envvars)[0] != NULL) + { + setenv(((char**)envvars)[0], ((char**)envvars)[1], 1); + envvars = (void*)((char*)envvars + 2 * sizeof(char*)); + } execv(target, parameters); _exit(1); } diff --git a/microstack/ILibProcessPipe.h b/microstack/ILibProcessPipe.h index 660c377..7710f72 100644 --- a/microstack/ILibProcessPipe.h +++ b/microstack/ILibProcessPipe.h @@ -66,10 +66,11 @@ void ILibProcessPipe_Pipe_SetBrokenPipeHandler(ILibProcessPipe_Pipe targetPipe, ILibProcessPipe_Manager ILibProcessPipe_Manager_Create(void *chain); int ILibProcessPipe_Process_IsDetached(ILibProcessPipe_Process p); -ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx3(ILibProcessPipe_Manager pipeManager, char* target, char* const* parameters, ILibProcessPipe_SpawnTypes spawnType, void *sessionId, int extraMemorySize); +ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx4(ILibProcessPipe_Manager pipeManager, char* target, char* const* parameters, ILibProcessPipe_SpawnTypes spawnType, void *sessionId, void *envvars, int extraMemorySize); #define ILibProcessPipe_Manager_SpawnProcess(pipeManager, target, parameters) ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, ILibProcessPipe_SpawnTypes_DEFAULT, 0) #define ILibProcessPipe_Manager_SpawnProcessEx(pipeManager, target, parameters, spawnType) ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, spawnType, 0) #define ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, spawnType, extraMemorySize) ILibProcessPipe_Manager_SpawnProcessEx3(pipeManager, target, parameters, spawnType, NULL, extraMemorySize) +#define ILibProcessPipe_Manager_SpawnProcessEx3(pipeManager, target, parameters, spawnType, sessionId, extraMemorySize) ILibProcessPipe_Manager_SpawnProcessEx4(pipeManager, target, parameters, spawnType, sessionId, NULL, extraMemorySize) #define ILibProcessPipe_Manager_SpawnProcessWithExtraPipeMemory(pipeManager, target, parameters, memorySize) ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, ILibProcessPipe_SpawnTypes_DEFAULT, memorySize) void ILibProcessPipe_Process_SoftKill(ILibProcessPipe_Process p); void ILibProcessPipe_Process_AddHandlers(ILibProcessPipe_Process module, int bufferSize, ILibProcessPipe_Process_ExitHandler exitHandler, ILibProcessPipe_Process_OutputHandler stdOut, ILibProcessPipe_Process_OutputHandler stdErr, ILibProcessPipe_Process_SendOKHandler sendOk, void *user);