void ApiListener::ConfigGlobHandler(Dictionary::Ptr& config, const String& path, const String& file) { CONTEXT("Creating config update for file '" + file + "'"); Log(LogNotice, "ApiListener") << "Creating config update for file '" << file << "'"; std::ifstream fp(file.CStr(), std::ifstream::binary); if (!fp) return; String content((std::istreambuf_iterator<char>(fp)), std::istreambuf_iterator<char>()); config->Set(file.SubStr(path.GetLength()), content); }
/** * The entry point for the "object list" CLI command. * * @returns An exit status. */ int ObjectListCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const { String objectfile = Application::GetObjectsPath(); if (!Utility::PathExists(objectfile)) { Log(LogCritical, "cli") << "Cannot open objects file '" << Application::GetObjectsPath() << "'."; Log(LogCritical, "cli", "Run 'icinga2 daemon -C' to validate config and generate the cache file."); return 1; } std::fstream fp; fp.open(objectfile.CStr(), std::ios_base::in); StdioStream::Ptr sfp = new StdioStream(&fp, false); unsigned long objects_count = 0; std::map<String, int> type_count; String message; String name_filter, type_filter; if (vm.count("name")) name_filter = vm["name"].as<std::string>(); if (vm.count("type")) type_filter = vm["type"].as<std::string>(); bool first = true; while (NetString::ReadStringFromStream(sfp, &message)) { PrintObject(std::cout, first, message, type_count, name_filter, type_filter); objects_count++; } sfp->Close(); fp.close(); if (vm.count("count")) { if (!first) std::cout << "\n"; PrintTypeCounts(std::cout, type_count); std::cout << "\n"; } Log(LogNotice, "cli") << "Parsed " << objects_count << " objects."; return 0; }
/** * Retrieves the full path of the executable. * * @param argv0 The first command-line argument. * @returns The path. */ String Application::GetExePath(const String& argv0) { String executablePath; #ifndef _WIN32 char buffer[MAXPATHLEN]; if (getcwd(buffer, sizeof(buffer)) == NULL) { BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("getcwd") << boost::errinfo_errno(errno)); } String workingDirectory = buffer; if (argv0[0] != '/') executablePath = workingDirectory + "/" + argv0; else executablePath = argv0; bool foundSlash = false; for (size_t i = 0; i < argv0.GetLength(); i++) { if (argv0[i] == '/') { foundSlash = true; break; } } if (!foundSlash) { const char *pathEnv = getenv("PATH"); if (pathEnv != NULL) { std::vector<String> paths; boost::algorithm::split(paths, pathEnv, boost::is_any_of(":")); bool foundPath = false; BOOST_FOREACH(String& path, paths) { String pathTest = path + "/" + argv0; if (access(pathTest.CStr(), X_OK) == 0) { executablePath = pathTest; foundPath = true; break; } } if (!foundPath) { executablePath.Clear(); BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine executable path.")); } }
void PerfdataWriter::RotateFile(std::ofstream& output, const String& temp_path, const String& perfdata_path) { ObjectLock olock(this); if (output.good()) { output.close(); if (Utility::PathExists(temp_path)) { String finalFile = perfdata_path + "." + Convert::ToString((long)Utility::GetTime()); if (rename(temp_path.CStr(), finalFile.CStr()) < 0) { BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("rename") << boost::errinfo_errno(errno) << boost::errinfo_file_name(temp_path)); } } } output.open(temp_path.CStr()); if (!output.good()) Log(LogWarning, "PerfdataWriter") << "Could not open perfdata file '" << temp_path << "' for writing. Perfdata will be lost."; }
void ConfigPackageUtility::CollectPaths(const String& path, std::vector<std::pair<String, bool> >& paths) { #ifndef _WIN32 struct stat statbuf; int rc = lstat(path.CStr(), &statbuf); if (rc < 0) BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("lstat") << boost::errinfo_errno(errno) << boost::errinfo_file_name(path)); paths.push_back(std::make_pair(path, S_ISDIR(statbuf.st_mode))); #else /* _WIN32 */ struct _stat statbuf; int rc = _stat(path.CStr(), &statbuf); if (rc < 0) BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("_stat") << boost::errinfo_errno(errno) << boost::errinfo_file_name(path)); paths.push_back(std::make_pair(path, ((statbuf.st_mode & S_IFMT) == S_IFDIR))); #endif /* _WIN32 */ }
HMODULE #else /* _WIN32 */ void * #endif /* _WIN32 */ Utility::LoadExtensionLibrary(const String& library) { String path; #if defined(_WIN32) path = library + ".dll"; #elif defined(__APPLE__) path = "lib" + library + ".dylib"; #else /* __APPLE__ */ path = "lib" + library + ".so"; #endif /* _WIN32 */ Log(LogInformation, "base", "Loading library '" + path + "'"); #ifdef _WIN32 HMODULE hModule = LoadLibrary(path.CStr()); if (hModule == NULL) { BOOST_THROW_EXCEPTION(win32_error() << boost::errinfo_api_function("LoadLibrary") << errinfo_win32_error(GetLastError()) << boost::errinfo_file_name(path)); } #else /* _WIN32 */ void *hModule = dlopen(path.CStr(), RTLD_NOW); if (hModule == NULL) { BOOST_THROW_EXCEPTION(std::runtime_error("Could not load library '" + path + "': " + dlerror())); } #endif /* _WIN32 */ return hModule; }
int PkiUtility::SignCsr(const String& csrfile, const String& certfile) { std::stringstream msgbuf; char errbuf[120]; InitializeOpenSSL(); BIO *csrbio = BIO_new_file(csrfile.CStr(), "r"); X509_REQ *req = PEM_read_bio_X509_REQ(csrbio, NULL, NULL, NULL); if (!req) { Log(LogCritical, "SSL") << "Could not read X509 certificate request from '" << csrfile << "': " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; return 1; } BIO_free(csrbio); boost::shared_ptr<X509> cert = CreateCertIcingaCA(X509_REQ_get_pubkey(req), X509_REQ_get_subject_name(req)); X509_REQ_free(req); std::ofstream fpcert; fpcert.open(certfile.CStr()); if (!fpcert) { Log(LogCritical, "cli") << "Failed to open certificate file '" << certfile << "' for output"; return 1; } fpcert << CertificateToString(cert); fpcert.close(); return 0; }
FileStream::FileStream(const String& path, AccessMode accessMode) : handle(nullptr), canRead(false), canWrite(false) { BBAssert(path.Contains('\\') == false); if (path.IsEmpty()) return; char mode[3] = { 'r', 'b', '\0' }; if (accessMode == ReadOnly) mode[0] = 'r'; else if (accessMode == WriteOnly) mode[0] = 'w'; String absPath; if (Path::IsAbsolutePath(path) == false) { BBAssert(path.CStr()[0] != '/'); absPath = Environment::GetWorkingDirectory() + path; } else absPath = path; handle = std::fopen(absPath.CStr(), mode); if (handle == nullptr) { canRead = false; canWrite = false; return; } canRead = (accessMode == FileStream::ReadOnly); canWrite = (accessMode == FileStream::WriteOnly); }
/* must hold m_LogLock */ void ApiListener::OpenLogFile(void) { String path = GetApiDir() + "log/current"; std::fstream *fp = new std::fstream(path.CStr(), std::fstream::out | std::ofstream::app); if (!fp->good()) { Log(LogWarning, "ApiListener") << "Could not open spool file: " << path; return; } m_LogFile = new StdioStream(fp, true); m_LogMessageCount = 0; SetLogMessageTimestamp(Utility::GetTime()); }
/** * Returns a human-readable type name of a type_info object. * * @param ti A type_info object. * @returns The type name of the object. */ String Utility::GetTypeName(const type_info& ti) { String klass = ti.name(); #ifdef HAVE_GCC_ABI_DEMANGLE int status; char *realname = abi::__cxa_demangle(klass.CStr(), 0, 0, &status); if (realname != NULL) { klass = String(realname); free(realname); } #endif /* HAVE_GCC_ABI_DEMANGLE */ return klass; }
IdoPgsqlResult IdoPgsqlConnection::Query(const String& query) { AssertOnWorkQueue(); Log(LogDebug, "IdoPgsqlConnection") << "Query: " << query; IncreaseQueryCount(); PGresult *result = PQexec(m_Connection, query.CStr()); if (!result) { String message = PQerrorMessage(m_Connection); Log(LogCritical, "IdoPgsqlConnection") << "Error \"" << message << "\" when executing query \"" << query << "\""; BOOST_THROW_EXCEPTION( database_error() << errinfo_message(message) << errinfo_database_query(query) ); } char *rowCount = PQcmdTuples(result); m_AffectedRows = atoi(rowCount); if (PQresultStatus(result) == PGRES_COMMAND_OK) { PQclear(result); return IdoPgsqlResult(); } if (PQresultStatus(result) != PGRES_TUPLES_OK) { String message = PQresultErrorMessage(result); PQclear(result); Log(LogCritical, "IdoPgsqlConnection") << "Error \"" << message << "\" when executing query \"" << query << "\""; BOOST_THROW_EXCEPTION( database_error() << errinfo_message(message) << errinfo_database_query(query) ); } return IdoPgsqlResult(result, std::ptr_fun(PQclear)); }
String ConfigPackageUtility::GetActiveStage(const String& packageName) { String path = GetPackageDir() + "/" + packageName + "/active-stage"; std::ifstream fp; fp.open(path.CStr()); String stage; std::getline(fp, stage.GetData()); fp.close(); if (fp.fail()) return ""; return stage.Trim(); }
/** * Converts a dictionary to a JSON object. * * @param dictionary The dictionary. * @returns A JSON object that is equivalent to the dictionary. Values that * cannot be represented in JSON are omitted. */ cJSON *Dictionary::ToJson(void) const { cJSON *json = cJSON_CreateObject(); try { String key; Value value; BOOST_FOREACH(tie(key, value), m_Data) { cJSON_AddItemToObject(json, key.CStr(), value.ToJson()); } } catch (...) { cJSON_Delete(json); throw; } return json; }
String Base64::Encode(const String& input) { BIO *biomem = BIO_new(BIO_s_mem()); BIO *bio64 = BIO_new(BIO_f_base64()); BIO_push(bio64, biomem); BIO_set_flags(bio64, BIO_FLAGS_BASE64_NO_NL); BIO_write(bio64, input.CStr(), input.GetLength()); (void) BIO_flush(bio64); char *outbuf; long len = BIO_get_mem_data(biomem, &outbuf); String ret = String(outbuf, outbuf + len); BIO_free_all(bio64); return ret; }
String ConfigPackageUtility::CreateStage(const String& packageName, const Dictionary::Ptr& files) { String stageName = Utility::NewUniqueID(); String path = GetPackageDir() + "/" + packageName; if (!Utility::PathExists(path)) BOOST_THROW_EXCEPTION(std::invalid_argument("Package does not exist.")); path += "/" + stageName; Utility::MkDirP(path, 0700); Utility::MkDirP(path + "/conf.d", 0700); Utility::MkDirP(path + "/zones.d", 0700); WriteStageConfig(packageName, stageName); bool foundDotDot = false; if (files) { ObjectLock olock(files); BOOST_FOREACH(const Dictionary::Pair& kv, files) { if (ContainsDotDot(kv.first)) { foundDotDot = true; break; } String filePath = path + "/" + kv.first; Log(LogInformation, "ConfigPackageUtility") << "Updating configuration file: " << filePath; //pass the directory and generate a dir tree, if not existing already Utility::MkDirP(Utility::DirName(filePath), 0750); std::ofstream fp(filePath.CStr(), std::ofstream::out | std::ostream::binary | std::ostream::trunc); fp << kv.second; fp.close(); } } if (foundDotDot) { Utility::RemoveDirRecursive(path); BOOST_THROW_EXCEPTION(std::invalid_argument("Path must not contain '..'.")); } return stageName; }
/** * Returns the file component of a path. See basename(3) for details. * * @param path The full path. * @returns The filename. */ String Utility::BaseName(const String& path) { char *dir = strdup(path.CStr()); String result; if (dir == NULL) throw_exception(bad_alloc()); #ifndef _WIN32 result = basename(dir); #else /* _WIN32 */ result = PathFindFileName(dir); #endif /* _WIN32 */ free(dir); return result; }
void FileLogger::ReopenLogFile() { auto *stream = new std::ofstream(); String path = GetPath(); try { stream->open(path.CStr(), std::fstream::app | std::fstream::out); if (!stream->good()) BOOST_THROW_EXCEPTION(std::runtime_error("Could not open logfile '" + path + "'")); } catch (...) { delete stream; throw; } BindStream(stream, true); }
InfoLog(const String& path, const bool cons) { m_Console = cons; m_ConsoleType = Console_Dumb; if (m_Console) { m_Stream = new std::ostream(std::cout.rdbuf()); #ifndef _WIN32 m_ConsoleType = Console_VT100; #else /*_WIN32*/ m_ConsoleType = Console_Windows; #endif /*_WIN32*/ } else { auto *ofs = new std::ofstream(); ofs->open(path.CStr(), std::ios::out | std::ios::trunc); m_Stream = ofs; } }
int PkiUtility::WriteCert(const boost::shared_ptr<X509>& cert, const String& trustedfile) { std::ofstream fpcert; fpcert.open(trustedfile.CStr()); fpcert << CertificateToString(cert); fpcert.close(); if (fpcert.fail()) { Log(LogCritical, "pki") << "Could not write certificate to file '" << trustedfile << "'."; return 1; } Log(LogInformation, "pki") << "Writing trusted certificate to file '" << trustedfile << "'."; return 0; }
/** * Returns the file component of a path. See basename(3) for details. * * @param path The full path. * @returns The filename. */ String Utility::BaseName(const String& path) { char *dir = strdup(path.CStr()); String result; if (dir == NULL) BOOST_THROW_EXCEPTION(std::bad_alloc()); #ifndef _WIN32 result = basename(dir); #else /* _WIN32 */ result = PathFindFileName(dir); #endif /* _WIN32 */ free(dir); return result; }
/** * Retrieves an X509 certificate from the specified file. * * @param pemfile The filename. * @returns An X509 certificate. */ shared_ptr<X509> Utility::GetX509Certificate(String pemfile) { X509 *cert; BIO *fpcert = BIO_new(BIO_s_file()); if (fpcert == NULL) throw_exception(OpenSSLException("BIO_new failed", ERR_get_error())); if (BIO_read_filename(fpcert, pemfile.CStr()) < 0) throw_exception(OpenSSLException("BIO_read_filename failed", ERR_get_error())); cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL); if (cert == NULL) throw_exception(OpenSSLException("PEM_read_bio_X509_AUX failed", ERR_get_error())); BIO_free(fpcert); return shared_ptr<X509>(cert, X509_free); }
/** * Constructor for the TlsStream class. * * @param role The role of the client. * @param sslContext The SSL context for the client. */ TlsStream::TlsStream(const Socket::Ptr& socket, const String& hostname, ConnectionRole role, const boost::shared_ptr<SSL_CTX>& sslContext) : SocketEvents(socket, this), m_Eof(false), m_HandshakeOK(false), m_VerifyOK(true), m_ErrorCode(0), m_ErrorOccurred(false), m_Socket(socket), m_Role(role), m_SendQ(new FIFO()), m_RecvQ(new FIFO()), m_CurrentAction(TlsActionNone), m_Retry(false), m_Shutdown(false) { std::ostringstream msgbuf; char errbuf[120]; m_SSL = boost::shared_ptr<SSL>(SSL_new(sslContext.get()), SSL_free); if (!m_SSL) { msgbuf << "SSL_new() failed with code " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\""; Log(LogCritical, "TlsStream", msgbuf.str()); BOOST_THROW_EXCEPTION(openssl_error() << boost::errinfo_api_function("SSL_new") << errinfo_openssl_error(ERR_peek_error())); } if (!m_SSLIndexInitialized) { m_SSLIndex = SSL_get_ex_new_index(0, const_cast<char *>("TlsStream"), NULL, NULL, NULL); m_SSLIndexInitialized = true; } SSL_set_ex_data(m_SSL.get(), m_SSLIndex, this); SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, &TlsStream::ValidateCertificate); socket->MakeNonBlocking(); SSL_set_fd(m_SSL.get(), socket->GetFD()); if (m_Role == RoleServer) SSL_set_accept_state(m_SSL.get()); else { #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (!hostname.IsEmpty()) SSL_set_tlsext_host_name(m_SSL.get(), hostname.CStr()); #endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */ SSL_set_connect_state(m_SSL.get()); } }
int FeatureUtility::DisableFeatures(const std::vector<std::string>& features) { String features_enabled_dir = GetFeaturesEnabledPath(); if (!Utility::PathExists(features_enabled_dir) ) { Log(LogCritical, "cli") << "Cannot disable features. Path '" << features_enabled_dir << "' does not exist."; return 0; } std::vector<std::string> errors; for (const String& feature : features) { String target = features_enabled_dir + "/" + feature + ".conf"; if (!Utility::PathExists(target) ) { Log(LogCritical, "cli") << "Cannot disable feature '" << feature << "'. Target file '" << target << "' does not exist."; errors.push_back(feature); continue; } if (unlink(target.CStr()) < 0) { Log(LogCritical, "cli") << "Cannot disable feature '" << feature << "'. Unlinking target file '" << target << "' failed with error code " << errno << ", \"" + Utility::FormatErrorNumber(errno) << "\"."; errors.push_back(feature); continue; } std::cout << "Disabling feature " << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << feature << ConsoleColorTag(Console_Normal) << ". Make sure to restart Icinga 2 for these changes to take effect.\n"; } if (!errors.empty()) { Log(LogCritical, "cli") << "Cannot disable feature(s): " << boost::algorithm::join(errors, " "); errors.clear(); return 1; } return 0; }
void HttpRequest::FinishHeaders(void) { if (m_State == HttpRequestStart) { String rqline = RequestMethod + " " + RequestUrl->Format() + " HTTP/1." + (ProtocolVersion == HttpVersion10 ? "0" : "1") + "\n"; m_Stream->Write(rqline.CStr(), rqline.GetLength()); m_State = HttpRequestHeaders; } if (m_State == HttpRequestHeaders) { AddHeader("User-Agent", "Icinga/" + Application::GetVersion()); if (ProtocolVersion == HttpVersion11) AddHeader("Transfer-Encoding", "chunked"); ObjectLock olock(Headers); BOOST_FOREACH(const Dictionary::Pair& kv, Headers) { String header = kv.first + ": " + kv.second + "\n"; m_Stream->Write(header.CStr(), header.GetLength()); }
static bool SetDaemonIO(const String& stderrFile) { #ifndef _WIN32 int fdnull = open("/dev/null", O_RDWR); if (fdnull >= 0) { if (fdnull != 0) dup2(fdnull, 0); if (fdnull != 1) dup2(fdnull, 1); if (fdnull > 1) close(fdnull); } const char *errPath = "/dev/null"; if (!stderrFile.IsEmpty()) errPath = stderrFile.CStr(); int fderr = open(errPath, O_WRONLY | O_APPEND); if (fderr < 0 && errno == ENOENT) fderr = open(errPath, O_CREAT | O_WRONLY | O_APPEND, 0600); if (fderr >= 0) { if (fderr != 2) dup2(fderr, 2); if (fderr > 2) close(fderr); } pid_t sid = setsid(); if (sid == -1) { return false; } #endif return true; }
void Clipboard::SetText(const String& value) { if (::OpenClipboard(nullptr)) { ::EmptyClipboard(); HGLOBAL dataHandle = ::GlobalAlloc(GMEM_DDESHARE, value.GetLength() + 1); char* destination = static_cast<char*>(::GlobalLock(dataHandle)); String::CopyChars(destination, value.CStr(), value.GetLength()); destination[value.GetLength()] = '\0'; ::GlobalUnlock(dataHandle); ::SetClipboardData(CF_TEXT, dataHandle); ::CloseClipboard(); } }
void ApiListener::ConfigGlobHandler(ConfigDirInformation& config, const String& path, const String& file) { CONTEXT("Creating config update for file '" + file + "'"); Log(LogNotice, "ApiListener") << "Creating config update for file '" << file << "'."; std::ifstream fp(file.CStr(), std::ifstream::binary); if (!fp) return; String content((std::istreambuf_iterator<char>(fp)), std::istreambuf_iterator<char>()); Dictionary::Ptr update; if (Utility::Match("*.conf", file)) update = config.UpdateV1; else update = config.UpdateV2; update->Set(file.SubStr(path.GetLength()), content); }
static bool GlobHelper(const String& pathSpec, int type, std::vector<String>& files, std::vector<String>& dirs) { HANDLE handle; WIN32_FIND_DATA wfd; handle = FindFirstFile(pathSpec.CStr(), &wfd); if (handle == INVALID_HANDLE_VALUE) { DWORD errorCode = GetLastError(); if (errorCode == ERROR_FILE_NOT_FOUND) return false; BOOST_THROW_EXCEPTION(win32_error() << boost::errinfo_api_function("FindFirstFile") << errinfo_win32_error(errorCode) << boost::errinfo_file_name(pathSpec)); } do { if (strcmp(wfd.cFileName, ".") == 0 || strcmp(wfd.cFileName, "..") == 0) continue; String path = Utility::DirName(pathSpec) + "/" + wfd.cFileName; if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (type & GlobDirectory)) dirs.push_back(path); else if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (type & GlobFile)) files.push_back(path); } while (FindNextFile(handle, &wfd)); if (!FindClose(handle)) { BOOST_THROW_EXCEPTION(win32_error() << boost::errinfo_api_function("FindClose") << errinfo_win32_error(GetLastError())); } return true; }
/** * Returns the directory component of a path. See dirname(3) for details. * * @param path The full path. * @returns The directory. */ String Utility::DirName(const String& path) { char *dir = strdup(path.CStr()); String result; if (dir == NULL) throw_exception(bad_alloc()); #ifndef _WIN32 result = dirname(dir); #else /* _WIN32 */ if (!PathRemoveFileSpec(dir)) { free(dir); throw_exception(Win32Exception("PathRemoveFileSpec() failed", GetLastError())); } result = dir; #endif /* _WIN32 */ free(dir); return result; }
void HttpResponse::SetStatus(int code, const String& message) { ASSERT(code >= 100 && code <= 599); ASSERT(!message.IsEmpty()); if (m_State != HttpResponseStart) { Log(LogWarning, "HttpResponse", "Tried to set Http response status after headers had already been sent."); return; } String status = "HTTP/"; if (m_Request->ProtocolVersion == HttpVersion10) status += "1.0"; else status += "1.1"; status += " " + Convert::ToString(code) + " " + message + "\r\n"; m_Stream->Write(status.CStr(), status.GetLength()); m_State = HttpResponseHeaders; }