Beispiel #1
0
VfsPosix::Directory::Directory (const char *dirname)
    throw (InternalException)
{
    dir = opendir (dirname);
    if (dir == NULL)
	throw InternalException (errnoToString (errno));
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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));
}
Beispiel #5
0
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;
    }
}
Beispiel #6
0
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
}
Beispiel #7
0
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
}
Beispiel #8
0
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.");
    });