VfsPosix::Directory::Directory (const char *dirname) throw (InternalException) { dir = opendir (dirname); if (dir == NULL) throw InternalException (errnoToString (errno)); }
bool KLUPD::NtlmImplementation::loadSecurityLibrary() { if(m_securityDll && m_funcionTable) return true; if(!m_securityDll) { m_securityDll = LoadLibrary(_T("secur32.dll")); if(!m_securityDll) { // on some platforms (e.g. Windows NT) there is no secur32.dll m_securityDll = LoadLibrary(_T("security.dll")); if(!m_securityDll) { const int lastError = GetLastError(); TRACE_MESSAGE2("Failed to load both 'secur32.dll' and 'security.dll' libraries, last error '%S'", errnoToString(lastError, windowsStyle).toWideChar()); return false; } } } PSecurityFunctionTable (*getFuncTable)(); getFuncTable = (PSecurityFunctionTable (*)(VOID))GetProcAddress(m_securityDll, tStringToAscii(SECURITY_ENTRYPOINT).c_str()); if(!getFuncTable) { const int lastError = GetLastError(); TRACE_MESSAGE3("Initialization NTLM functionality: failed to get function '%s' address, last error '%S'", tStringToAscii(SECURITY_ENTRYPOINT).c_str(), KLUPD::errnoToString(lastError, KLUPD::windowsStyle).toWideChar()); return false; } m_funcionTable = getFuncTable(); if(!m_funcionTable) { const int lastError = GetLastError(); TRACE_MESSAGE3("Initialization NTLM functionality: '%s' call failed, last error '%S'", tStringToAscii(SECURITY_ENTRYPOINT).c_str(), errnoToString(lastError, windowsStyle).toWideChar()); return false; } return true; }
Ref<Vfs::StatData> VfsPosix::stat (const char *_name) throw (InternalException) { Ref<String> name = String::forPrintTask ((Pr (root_path)) (Pr ("/")) (Pr (_name))); struct stat stat_buf; int rv = ::stat (name->getData (), &stat_buf); if (rv == -1) { throw InternalException (errnoToString (errno)); } else if (rv != 0) throw InternalException (); Ref<StatData> stat_data = grab (new StatData); if (S_ISBLK (stat_buf.st_mode)) stat_data->file_type = FileType_BlockDevice; else if (S_ISCHR (stat_buf.st_mode)) stat_data->file_type = FileType_CharacterDevice; else if (S_ISDIR (stat_buf.st_mode)) stat_data->file_type = FileType_Directory; else if (S_ISFIFO (stat_buf.st_mode)) stat_data->file_type = FileType_Fifo; else if (S_ISREG (stat_buf.st_mode)) stat_data->file_type = FileType_RegularFile; else if (S_ISLNK (stat_buf.st_mode)) stat_data->file_type = FileType_SymbolicLink; else if (S_ISSOCK (stat_buf.st_mode)) stat_data->file_type = FileType_Socket; else throw InternalException (); stat_data->size = (unsigned long long) stat_buf.st_size; return stat_data; }
Ref<String> VfsPosix::Directory::getNextEntry () throw (InternalException) { ArrayHolder<unsigned char> dirent_array (sizeof (struct dirent) + NAME_MAX + 1); struct dirent * const dirent = (struct dirent*) &dirent_array [0]; struct dirent *retp; int rv = readdir_r (dir, dirent, &retp); if (rv != 0) throw InternalException (errnoToString (rv)); if (retp == NULL) return NULL; if (retp != dirent) throw InternalException (); return grab (new String (dirent->d_name)); }
VfsPosix::Directory::~Directory () { for (;;) { int rv = closedir (dir); if (rv == -1) { if (errno == EINTR) continue; errf->print ("MyCpp.VfsPosix.Directory~: closedir() failed: ") .print (errnoToString (errno)) .pendl (); } else if (rv != 0) { errf->print ("MyCpp.VfsPosix.Directory~: unexpected return value from closedir(): ") .print ((long) rv) .pendl (); } break; } }
bool KLUPD::NtlmImplementation::makeChallenge(std::vector<char> &challenge, const std::string &domain, const std::string &user, const std::string &password) { #ifdef WIN32 // no implementation for non-Windows platforms if(!loadSecurityLibrary()) return false; TimeStamp expiration; if(needAquireCredentials(domain, user, password)) { _SEC_WINNT_AUTH_IDENTITY *authorizationIdentityPointer = 0; _SEC_WINNT_AUTH_IDENTITY authorizationIdentity; if(getAuthorizationIdentity(authorizationIdentity, domain, user, password)) authorizationIdentityPointer = &authorizationIdentity; releasePreviousCredentialsIfNeeded(); SECURITY_STATUS result = m_funcionTable->AcquireCredentialsHandle(0, _T("NTLM"), SECPKG_CRED_OUTBOUND, 0, authorizationIdentityPointer, 0, 0, &m_credentials, &expiration); if(result != SEC_E_OK) { const int lastError = GetLastError(); TRACE_MESSAGE3("Failed to make NTLM challenge: failed to acquire credentials, result 0x%x, last error '%S'", result, errnoToString(lastError, windowsStyle).toWideChar()); return false; } m_credentialsObtained = true; } SecBuffer secBuffer; // the ISC_REQ_ALLOCATE_MEMORY content requirement does not // work on Windows 98, that is why buffer is allocated on stack char buffer[2048]; secBuffer.cbBuffer = 2048; secBuffer.pvBuffer = buffer; secBuffer.BufferType = SECBUFFER_TOKEN; SecBufferDesc messageType1; messageType1.cBuffers = 1; messageType1.pBuffers = &secBuffer; messageType1.ulVersion = SECBUFFER_VERSION; unsigned long attr = 0; const SECURITY_STATUS result = m_funcionTable->InitializeSecurityContext( &m_credentials, // handle to credentials 0, // handle to partial context (should be 0 on first call) 0, // target (optional) 0, // context requirements 0, // reserved SECURITY_NETWORK_DREP, // data representation 0, // security buffer description 0, // reserved &m_context, // handle of new context &messageType1, // security buffer description &attr, // dst context attributes &expiration); // expiration time (local) if(result != SEC_I_CONTINUE_NEEDED // SEC_I_CONTINUE_NEEDED is not error code - reply from server is expected to perform NTLM authorization protocol && result != SEC_E_OK) { const int lastError = GetLastError(); TRACE_MESSAGE3("Failed to make NTLM challenge: failed to initialize security context, result 0x%x, last error '%S'", result, errnoToString(lastError, windowsStyle).toWideChar()); return false; } m_securityContextObtained = true; challenge = CBase64::encodeBuffer(reinterpret_cast<unsigned char *>(secBuffer.pvBuffer), secBuffer.cbBuffer); return true; #else // WIN32 TRACE_MESSAGE("Ntlm authorization is not implemented on this platform"); return false; #endif // WIN32 }
bool KLUPD::NtlmImplementation::makeResponse(const char *challenge, std::vector<char> &response) { #ifdef WIN32 // no implementation for non-Windows platforms if(!challenge) { TRACE_MESSAGE("Failed to make NTLM response: invalid input parameter challenge"); return false; } std::vector<unsigned char> decodedChallenge = CBase64::decodeBuffer(challenge); if(decodedChallenge.empty()) { TRACE_MESSAGE("Failed to make NTLM response: empty decoded string obtained"); return false; } SecBuffer challengeBuffer; challengeBuffer.BufferType = SECBUFFER_TOKEN; challengeBuffer.cbBuffer = decodedChallenge.size(); challengeBuffer.pvBuffer = &decodedChallenge[0]; SecBufferDesc messageType2; messageType2.cBuffers = 1; messageType2.pBuffers = &challengeBuffer; messageType2.ulVersion = SECBUFFER_VERSION; SecBuffer responseBuffer; // the ISC_REQ_ALLOCATE_MEMORY content requirement does not // work on Windows 98, that is why buffer is allocated on stack char buffer[2048]; responseBuffer.cbBuffer = 2048; responseBuffer.pvBuffer = buffer; responseBuffer.BufferType = SECBUFFER_TOKEN; SecBufferDesc messageType3; messageType3.cBuffers = 1; messageType3.pBuffers = &responseBuffer; messageType3.ulVersion = SECBUFFER_VERSION; unsigned long attr = 0; TimeStamp expiration; const SECURITY_STATUS result = m_funcionTable->InitializeSecurityContext( &m_credentials, // handle to credentials &m_context, // handle to partial context 0, // target (ignored on second call) 0, // context requirements 0, // reserved SECURITY_NETWORK_DREP, // data representation &messageType2, // security buffer description 0, // reserved &m_context, // handle of new context &messageType3, // security buffer description &attr, // dst context attributes &expiration); // expiration time (local) if(result != SEC_I_CONTINUE_NEEDED // SEC_I_CONTINUE_NEEDED is not error code - the data exchange may be continued && result != SEC_E_OK) { const int lastError = GetLastError(); TRACE_MESSAGE3("Failed to make NTLM response: failed to initialize security context, result 0x%x, last error '%S'", result, errnoToString(lastError, windowsStyle).toWideChar()); return false; } response = CBase64::encodeBuffer(reinterpret_cast<unsigned char *>(responseBuffer.pvBuffer), responseBuffer.cbBuffer); return true; #else // WIN32 TRACE_MESSAGE("Ntlm authorization is not implemented on this platform"); return false; #endif // WIN32 }
int Server::main(const std::vector<std::string> & /*args*/) { Logger * log = &logger(); UseSSL use_ssl; ThreadStatus thread_status; registerFunctions(); registerAggregateFunctions(); registerTableFunctions(); registerStorages(); registerDictionaries(); CurrentMetrics::set(CurrentMetrics::Revision, ClickHouseRevision::get()); CurrentMetrics::set(CurrentMetrics::VersionInteger, ClickHouseRevision::getVersionInteger()); /** Context contains all that query execution is dependent: * settings, available functions, data types, aggregate functions, databases... */ global_context = std::make_unique<Context>(Context::createGlobal()); global_context->setGlobalContext(*global_context); global_context->setApplicationType(Context::ApplicationType::SERVER); bool has_zookeeper = config().has("zookeeper"); zkutil::ZooKeeperNodeCache main_config_zk_node_cache([&] { return global_context->getZooKeeper(); }); zkutil::EventPtr main_config_zk_changed_event = std::make_shared<Poco::Event>(); if (loaded_config.has_zk_includes) { auto old_configuration = loaded_config.configuration; ConfigProcessor config_processor(config_path); loaded_config = config_processor.loadConfigWithZooKeeperIncludes( main_config_zk_node_cache, main_config_zk_changed_event, /* fallback_to_preprocessed = */ true); config_processor.savePreprocessedConfig(loaded_config, config().getString("path", DBMS_DEFAULT_PATH)); config().removeConfiguration(old_configuration.get()); config().add(loaded_config.configuration.duplicate(), PRIO_DEFAULT, false); } const auto memory_amount = getMemoryAmount(); #if defined(__linux__) /// After full config loaded { if (config().getBool("mlock_executable", false)) { if (hasLinuxCapability(CAP_IPC_LOCK)) { LOG_TRACE(log, "Will mlockall to prevent executable memory from being paged out. It may take a few seconds."); if (0 != mlockall(MCL_CURRENT)) LOG_WARNING(log, "Failed mlockall: " + errnoToString(ErrorCodes::SYSTEM_ERROR)); else LOG_TRACE(log, "The memory map of clickhouse executable has been mlock'ed"); } else { LOG_INFO(log, "It looks like the process has no CAP_IPC_LOCK capability, binary mlock will be disabled." " It could happen due to incorrect ClickHouse package installation." " You could resolve the problem manually with 'sudo setcap cap_ipc_lock=+ep /usr/bin/clickhouse'." " Note that it will not work on 'nosuid' mounted filesystems."); } } } #endif std::string path = getCanonicalPath(config().getString("path", DBMS_DEFAULT_PATH)); std::string default_database = config().getString("default_database", "default"); /// Check that the process' user id matches the owner of the data. const auto effective_user_id = geteuid(); struct stat statbuf; if (stat(path.c_str(), &statbuf) == 0 && effective_user_id != statbuf.st_uid) { const auto effective_user = getUserName(effective_user_id); const auto data_owner = getUserName(statbuf.st_uid); std::string message = "Effective user of the process (" + effective_user + ") does not match the owner of the data (" + data_owner + ")."; if (effective_user_id == 0) { message += " Run under 'sudo -u " + data_owner + "'."; throw Exception(message, ErrorCodes::MISMATCHING_USERS_FOR_PROCESS_AND_DATA); } else { LOG_WARNING(log, message); } } global_context->setPath(path); /// Create directories for 'path' and for default database, if not exist. Poco::File(path + "data/" + default_database).createDirectories(); Poco::File(path + "metadata/" + default_database).createDirectories(); StatusFile status{path + "status"}; SCOPE_EXIT({ /** Ask to cancel background jobs all table engines, * and also query_log. * It is important to do early, not in destructor of Context, because * table engines could use Context on destroy. */ LOG_INFO(log, "Shutting down storages."); global_context->shutdown(); LOG_DEBUG(log, "Shutted down storages."); /** Explicitly destroy Context. It is more convenient than in destructor of Server, because logger is still available. * At this moment, no one could own shared part of Context. */ global_context.reset(); LOG_DEBUG(log, "Destroyed global context."); });