~RpmEnvironmentManager() { // If we had set the environment, clean it up afterward. if (!config_.is_initialized()) { unsetEnvVar("RPM_CONFIGDIR"); } if (callback_ != nullptr) { rpmlogSetCallback(callback_, nullptr); callback_ = nullptr; } }
TEST_F(ProcessTests, test_envVar) { auto val = getEnvVar("GTEST_OSQUERY"); EXPECT_FALSE(val); EXPECT_FALSE(val.is_initialized()); EXPECT_TRUE(setEnvVar("GTEST_OSQUERY", "true")); val = getEnvVar("GTEST_OSQUERY"); EXPECT_FALSE(!val); EXPECT_TRUE(val.is_initialized()); EXPECT_EQ(*val, "true"); EXPECT_TRUE(unsetEnvVar("GTEST_OSQUERY")); val = getEnvVar("GTEST_OSQUERY"); EXPECT_FALSE(val); EXPECT_FALSE(val.is_initialized()); }
/* Takes the command struct and takes approproate action. * Will either execute a shell command, program, or output an error message. * @params: command - a struct representing the command * @return: false is the command was note found, true otherwise. */ bool processCommand(command_t* command, char* pEnv[]){ char* defaultDir = getenv("HOME"); if( strcmp(command->name, "cd") == CMP_OK) { if( command->argc == 1 ) { changeDirectory(defaultDir); } else { changeDirectory(command->argv[1]); } } else if( strcmp(command->name,"help") == CMP_OK) { help(); } else if( strcmp(command->name, "senv") == CMP_OK) { char* envName = NULL; char* envVal = NULL; if( command->argc > 1) { envName = command->argv[1]; } if( command->argc > 2) { envVal = command->argv[2]; } setEnvVar(envName,envVal); } else if( strcmp(command->name, "usenv") == CMP_OK) { char* envName = NULL; if( command->argc > 1) { envName = command->argv[1]; } unsetEnvVar(envName); } else if( strcmp(command->name, "genv") == CMP_OK) { char* envName = NULL; if( command-> argc > 1) { envName = command->argv[1]; } getEnvVar(envName); } else { char* filePath = getFilePath(command->name); if(filePath != NULL) { pid_t pid_command = fork(); if(pid_command < CHILD) { // ERROR fprintf(stderr, "Fork failure!\n"); } else if ( pid_command == CHILD) { if(command->isBg) { freopen("/dev/null","w",stdout); freopen("/dev/null","w",stderr); } execve(filePath, command->argv, pEnv); } else { if(!command->isBg) { int stat; waitpid(pid_command, &stat, 0); } else { printf("Process ID: %d\n", pid_command); } } } else if(strcmp(command->name, "quit") == CMP_OK || strcmp(command->name, "exit") == CMP_OK || strcmp(command->name, "q") == CMP_OK ) { return false; } else { printf("%s: Command not found\n", command->name); return false; } } return true; }
std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension( const std::string &exec_path, const std::string &extension, const std::string &extensions_socket, const std::string &extensions_timeout, const std::string &extensions_interval, const std::string &verbose) { ::STARTUPINFOA si = {0}; ::PROCESS_INFORMATION pi = {0}; si.cb = sizeof(si); // To prevent errant double quotes from altering the intended arguments for // argv, we strip them out completely. std::stringstream argv_stream; argv_stream << "\"osquery extension: " << boost::replace_all_copy(extension, "\"", "") << "\" "; argv_stream << "--socket \"" << extensions_socket << "\" "; argv_stream << "--timeout " << extensions_timeout << " "; argv_stream << "--interval " << extensions_interval << " "; if (verbose == "true") { argv_stream << "--verbose"; } // We don't directly use argv.c_str() as the value for lpCommandLine in // CreateProcess since that argument requires a modifiable buffer. So, // instead, we off-load the contents of argv into a vector which will have its // backing memory as modifiable. std::string argv = argv_stream.str(); std::vector<char> mutable_argv(argv.begin(), argv.end()); mutable_argv.push_back('\0'); // In POSIX, this environment variable is set to the child's process ID. But // that is not easily accomplishable on Windows and provides no value since // this is never used elsewhere in the core. if (!setEnvVar("OSQUERY_EXTENSION", "1")) { return std::shared_ptr<PlatformProcess>(); } BOOL status = ::CreateProcessA(exec_path.c_str(), &mutable_argv[0], NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); unsetEnvVar("OSQUERY_EXTENSION"); if (!status) { return std::shared_ptr<PlatformProcess>(); } auto process = std::make_shared<PlatformProcess>(pi.hProcess); ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); return process; }
std::shared_ptr<PlatformProcess> PlatformProcess::launchWorker( const std::string &exec_path, int argc, char **argv) { ::STARTUPINFOA si = {0}; ::PROCESS_INFORMATION pi = {0}; si.cb = sizeof(si); std::stringstream argv_stream; std::stringstream handle_stream; // The HANDLE exposed to the child process is currently limited to only having // SYNCHRONIZE and PROCESS_QUERY_LIMITED_INFORMATION capabilities. The // SYNCHRONIZE permissions allows for WaitForSingleObject. // PROCESS_QUERY_LIMITED_INFORMATION allows for the ability to use the // GetProcessId and GetExitCodeProcess API functions. HANDLE hLauncherProcess = ::OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, TRUE, GetCurrentProcessId()); if (hLauncherProcess == NULL) { return std::shared_ptr<PlatformProcess>(); } handle_stream << hLauncherProcess; std::string handle = handle_stream.str(); // In the POSIX version, the environment variable OSQUERY_WORKER is set to the // string form of the child process' process ID. However, this is not easily // doable on Windows. Since the value does not appear to be used by the rest // of osquery, we currently just set it to '1'. // // For the worker case, we also set another environment variable, // OSQUERY_LAUNCHER. OSQUERY_LAUNCHER stores the string form of a HANDLE to // the current process. This is mostly used for detecting the death of the // launcher process in WatcherWatcherRunner::start if (!setEnvVar("OSQUERY_WORKER", "1") || !setEnvVar("OSQUERY_LAUNCHER", handle.c_str())) { ::CloseHandle(hLauncherProcess); return std::shared_ptr<PlatformProcess>(); } // Since Windows does not accept a char * array for arguments, we have to // build one as a string. Therefore, we need to make sure that special // characters are not present that would obstruct the parsing of arguments. // For now, we strip out all double quotes. If the an entry in argv has // spaces, we will put double-quotes around the entry. // // NOTE: This is extremely naive and will break the moment complexities are // involved... Windows command line argument parsing is extremely // nitpicky and is different in behavior than POSIX argv parsing. // // We don't directly use argv.c_str() as the value for lpCommandLine in // CreateProcess since that argument requires a modifiable buffer. So, // instead, we off-load the contents of argv into a vector which will have its // backing memory as modifiable. for (size_t i = 0; i < argc; i++) { std::string component(argv[i]); if (component.find(" ") != std::string::npos) { boost::replace_all(component, "\"", "\\\""); argv_stream << "\"" << component << "\" "; } else { argv_stream << component << " "; } } std::string cmdline = argv_stream.str(); std::vector<char> mutable_argv(cmdline.begin(), cmdline.end()); mutable_argv.push_back('\0'); BOOL status = ::CreateProcessA(exec_path.c_str(), &mutable_argv[0], NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); unsetEnvVar("OSQUERY_WORKER"); unsetEnvVar("OSQUERY_LAUNCHER"); ::CloseHandle(hLauncherProcess); if (!status) { return std::shared_ptr<PlatformProcess>(); } auto process = std::make_shared<PlatformProcess>(pi.hProcess); ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); return process; }