Пример #1
0
/**
 * Creates a new JSON-RPC listener on the specified port.
 *
 * @param node The host the listener should be bound to.
 * @param service The port to listen on.
 */
bool ApiListener::AddListener(const String& node, const String& service)
{
	ObjectLock olock(this);

	boost::shared_ptr<SSL_CTX> sslContext = m_SSLContext;

	if (!sslContext) {
		Log(LogCritical, "ApiListener", "SSL context is required for AddListener()");
		return false;
	}

	Log(LogInformation, "ApiListener")
	    << "Adding new listener on port '" << service << "'";

	TcpSocket::Ptr server = new TcpSocket();

	try {
		server->Bind(node, service, AF_UNSPEC);
	} catch (const std::exception&) {
		Log(LogCritical, "ApiListener")
		    << "Cannot bind TCP socket for host '" << node << "' on port '" << service << "'.";
		return false;
	}

	boost::thread thread(boost::bind(&ApiListener::ListenerThreadProc, this, server));
	thread.detach();

	m_Servers.insert(server);

	return true;
}
Пример #2
0
void HttpClientConnection::Reconnect()
{
	if (m_Stream)
		m_Stream->Close();

	m_Context.~StreamReadContext();
	new (&m_Context) StreamReadContext();

	m_Requests.clear();
	m_CurrentResponse.reset();

	TcpSocket::Ptr socket = new TcpSocket();
	socket->Connect(m_Host, m_Port);

	if (m_Tls)
		m_Stream = new TlsStream(socket, m_Host, RoleClient);
	else
		ASSERT(!"Non-TLS HTTP connections not supported.");
		/* m_Stream = new NetworkStream(socket);
		 * -- does not currently work because the NetworkStream class doesn't support async I/O
		 */

	/* the stream holds an owning reference to this object through the callback we're registering here */
	m_Stream->RegisterDataHandler(std::bind(&HttpClientConnection::DataAvailableHandler, HttpClientConnection::Ptr(this), _1));
	if (m_Stream->IsDataAvailable())
		DataAvailableHandler(m_Stream);
}
Пример #3
0
int PkiUtility::SaveCert(const String& host, const String& port, const String& keyfile, const String& certfile, const String& trustedfile)
{
	TcpSocket::Ptr client = new TcpSocket();

	client->Connect(host, port);

	boost::shared_ptr<SSL_CTX> sslContext = MakeSSLContext(certfile, keyfile);

	TlsStream::Ptr stream = new TlsStream(client, RoleClient, sslContext);

	try {
		stream->Handshake();
	} catch (...) {

	}

	boost::shared_ptr<X509> cert = stream->GetPeerCertificate();

	std::ofstream fpcert;
	fpcert.open(trustedfile.CStr());
	fpcert << CertificateToString(cert);
	fpcert.close();

	if (fpcert.fail()) {
		Log(LogCritical, "cli")
		    << "Could not write certificate to file '" << trustedfile << "'.";
		return 1;
	}

	Log(LogInformation, "cli")
	    << "Writing trusted certificate to file '" << trustedfile << "'.";

	return 0;
}
Пример #4
0
void HttpClientConnection::Reconnect(void)
{
	if (m_Stream)
		m_Stream->Close();

	m_Context.~StreamReadContext();
	new (&m_Context) StreamReadContext();

	m_Requests.clear();
	m_CurrentResponse.reset();

	TcpSocket::Ptr socket = new TcpSocket();
	socket->Connect(m_Host, m_Port);

	if (m_Tls)
		m_Stream = new TlsStream(socket, m_Host, RoleClient);
	else
		ASSERT(!"Non-TLS HTTP connections not supported.");
		/* m_Stream = new NetworkStream(socket);
		   -- does not currently work because the NetworkStream class doesn't support async I/O */

	m_Stream->RegisterDataHandler(boost::bind(&HttpClientConnection::DataAvailableHandler, this, _1));
	if (m_Stream->IsDataAvailable())
		DataAvailableHandler(m_Stream);
}
Пример #5
0
int PkiUtility::SaveCert(const String& host, const String& port, const String& keyfile, const String& certfile, const String& trustedfile)
{
	TcpSocket::Ptr client = new TcpSocket();

	try {
		client->Connect(host, port);
	} catch (const std::exception& ex) {
		Log(LogCritical, "cli")
		    << "Cannot connect to host '" << host << "' on port '" << port << "'";
		Log(LogDebug, "cli")
		    << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
		return 1;
	}

	boost::shared_ptr<SSL_CTX> sslContext;

	try {
		sslContext = MakeSSLContext(certfile, keyfile);
	} catch (const std::exception& ex) {
		Log(LogCritical, "cli")
		    << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "'.";
		Log(LogDebug, "cli")
		    << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "':\n"  << DiagnosticInformation(ex);
		return 1;
	}

	TlsStream::Ptr stream = new TlsStream(client, String(), RoleClient, sslContext);

	try {
		stream->Handshake();
	} catch (...) {

	}

	boost::shared_ptr<X509> cert = stream->GetPeerCertificate();

	if (!cert) {
		Log(LogCritical, "cli", "Peer did not present a valid certificate.");
		return 1;
	}

	std::ofstream fpcert;
	fpcert.open(trustedfile.CStr());
	fpcert << CertificateToString(cert);
	fpcert.close();

	if (fpcert.fail()) {
		Log(LogCritical, "cli")
		    << "Could not write certificate to file '" << trustedfile << "'.";
		return 1;
	}

	Log(LogInformation, "cli")
	    << "Writing trusted certificate to file '" << trustedfile << "'.";

	return 0;
}
Пример #6
0
ListenerES::ListenerES(TcpSocket::Ptr p_tcpSocket, int p_port)
  : SocketES(p_tcpSocket)
{
  m_eventTypes.insert(Epoll::EventType::Error);
  m_eventTypes.insert(Epoll::EventType::In);
  m_eventTypes.insert(Epoll::EventType::Hup);
  m_eventTypes.insert(Epoll::EventType::RdHup);

  p_tcpSocket->setNonBlocking();
  p_tcpSocket->bind(p_port);
  p_tcpSocket->listen();
}
Пример #7
0
/**
 * Creates a new JSON-RPC client and connects to the specified endpoint.
 *
 * @param endpoint The endpoint.
 */
void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
{
	{
		ObjectLock olock(this);

		std::shared_ptr<SSL_CTX> sslContext = m_SSLContext;

		if (!sslContext) {
			Log(LogCritical, "ApiListener", "SSL context is required for AddConnection()");
			return;
		}
	}

	String host = endpoint->GetHost();
	String port = endpoint->GetPort();

	Log(LogInformation, "ApiListener")
		<< "Reconnecting to endpoint '" << endpoint->GetName() << "' via host '" << host << "' and port '" << port << "'";

	TcpSocket::Ptr client = new TcpSocket();

	String serverName = endpoint->GetName();

	String env = ScriptGlobal::Get("Environment", &Empty);
	if (env != "" && env != "production")
		serverName += ":" + env;

	try {
		endpoint->SetConnecting(true);
		client->Connect(host, port);
		NewClientHandler(client, serverName, RoleClient);
		endpoint->SetConnecting(false);
	} catch (const std::exception& ex) {
		endpoint->SetConnecting(false);
		client->Close();

		std::ostringstream info;
		info << "Cannot connect to host '" << host << "' on port '" << port << "'";
		Log(LogCritical, "ApiListener", info.str());
		Log(LogDebug, "ApiListener")
			<< info.str() << "\n" << DiagnosticInformation(ex);
	}

	Log(LogInformation, "ApiListener")
		<< "Finished reconnecting to endpoint '" << endpoint->GetName() << "' via host '" << host << "' and port '" << port << "'";
}
Пример #8
0
void GraphiteWriter::ReconnectTimerHandler(void)
{
	try {
		if (m_Stream) {
			m_Stream->Write("\n", 1);
			Log(LogWarning, "perfdata", "GraphiteWriter already connected on socket on host '" + GetHost() + "' port '" + GetPort() + "'.");
			return;
		}
	} catch (const std::exception& ex) {
		Log(LogWarning, "perfdata", "GraphiteWriter socket on host '" + GetHost() + "' port '" + GetPort() + "' gone. Attempting to reconnect.");	
	}

	TcpSocket::Ptr socket = make_shared<TcpSocket>();

	Log(LogDebug, "perfdata", "GraphiteWriter: Reconnect to tcp socket on host '" + GetHost() + "' port '" + GetPort() + "'.");
	socket->Connect(GetHost(), GetPort());

	NetworkStream::Ptr net_stream = make_shared<NetworkStream>(socket);
	m_Stream = make_shared<BufferedStream>(net_stream);
}
Пример #9
0
void GelfWriter::ReconnectTimerHandler(void)
{
    if (m_Stream)
        return;

    TcpSocket::Ptr socket = new TcpSocket();

    Log(LogNotice, "GelfWriter")
            << "Reconnecting to GELF endpoint '" << GetHost() << "' port '" << GetPort() << "'.";

    try {
        socket->Connect(GetHost(), GetPort());
    } catch (std::exception&) {
        Log(LogCritical, "GelfWriter")
                << "Can't connect to GELF endpoint '" << GetHost() << "' port '" << GetPort() << "'.";
        return;
    }

    m_Stream = new NetworkStream(socket);
}
Пример #10
0
void OpenTsdbWriter::ReconnectTimerHandler()
{
	if (m_Stream)
		return;

	TcpSocket::Ptr socket = new TcpSocket();

	Log(LogNotice, "OpenTsdbWriter")
		<< "Reconnect to OpenTSDB TSD on host '" << GetHost() << "' port '" << GetPort() << "'.";

	try {
		socket->Connect(GetHost(), GetPort());
	} catch (std::exception&) {
		Log(LogCritical, "OpenTsdbWriter")
			<< "Can't connect to OpenTSDB TSD on host '" << GetHost() << "' port '" << GetPort() << "'.";
		return;
	}

	m_Stream = new NetworkStream(socket);
}
Пример #11
0
Stream::Ptr InfluxdbWriter::Connect(void)
{
	TcpSocket::Ptr socket = new TcpSocket();

	Log(LogNotice, "InfluxdbWriter")
	    << "Reconnecting to InfluxDB on host '" << GetHost() << "' port '" << GetPort() << "'.";

	try {
		socket->Connect(GetHost(), GetPort());
	} catch (std::exception&) {
		Log(LogWarning, "InfluxdbWriter")
		    << "Can't connect to InfluxDB on host '" << GetHost() << "' port '" << GetPort() << "'.";
		return Stream::Ptr();
	}

	if (GetSslEnable()) {
		boost::shared_ptr<SSL_CTX> ssl_context;
		try {
			ssl_context = MakeSSLContext(GetSslCert(), GetSslKey(), GetSslCaCert());
		} catch (std::exception&) {
			Log(LogWarning, "InfluxdbWriter")
			    << "Unable to create SSL context.";
			return Stream::Ptr();
		}

		TlsStream::Ptr tls_stream = new TlsStream(socket, GetHost(), RoleClient, ssl_context);
		try {
			tls_stream->Handshake();
		} catch (std::exception&) {
			Log(LogWarning, "InfluxdbWriter")
			    << "TLS handshake with host '" << GetHost() << "' failed.";
			return Stream::Ptr();
		}

		return tls_stream;
	} else {
		return new NetworkStream(socket);
	}
}
Пример #12
0
/**
 * Creates a new JSON-RPC client and connects to the specified endpoint.
 *
 * @param endpoint The endpoint.
 */
void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
{
	{
		ObjectLock olock(this);

		boost::shared_ptr<SSL_CTX> sslContext = m_SSLContext;

		if (!sslContext) {
			Log(LogCritical, "ApiListener", "SSL context is required for AddConnection()");
			return;
		}
	}

	String host = endpoint->GetHost();
	String port = endpoint->GetPort();

	Log(LogInformation, "JsonRpcConnection")
	    << "Reconnecting to API endpoint '" << endpoint->GetName() << "' via host '" << host << "' and port '" << port << "'";

	TcpSocket::Ptr client = new TcpSocket();

	try {
		endpoint->SetConnecting(true);
		client->Connect(host, port);
		NewClientHandler(client, endpoint->GetName(), RoleClient);
		endpoint->SetConnecting(false);
	} catch (const std::exception& ex) {
		endpoint->SetConnecting(false);
		client->Close();

		std::ostringstream info;
		info << "Cannot connect to host '" << host << "' on port '" << port << "'";
		Log(LogCritical, "ApiListener", info.str());
		Log(LogDebug, "ApiListener")
		    << info.str() << "\n" << DiagnosticInformation(ex);
	}
}
Пример #13
0
boost::shared_ptr<X509> PkiUtility::FetchCert(const String& host, const String& port)
{
	TcpSocket::Ptr client = new TcpSocket();

	try {
		client->Connect(host, port);
	} catch (const std::exception& ex) {
		Log(LogCritical, "pki")
		    << "Cannot connect to host '" << host << "' on port '" << port << "'";
		Log(LogDebug, "pki")
		    << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
		return boost::shared_ptr<X509>();
	}

	boost::shared_ptr<SSL_CTX> sslContext;

	try {
		sslContext = MakeSSLContext();
	} catch (const std::exception& ex) {
		Log(LogCritical, "pki")
		    << "Cannot make SSL context.";
		Log(LogDebug, "pki")
		    << "Cannot make SSL context:\n"  << DiagnosticInformation(ex);
		return boost::shared_ptr<X509>();
	}

	TlsStream::Ptr stream = new TlsStream(client, host, RoleClient, sslContext);

	try {
		stream->Handshake();
	} catch (...) {

	}

	return stream->GetPeerCertificate();
}
Пример #14
0
int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile,
    const String& certfile, const String& cafile, const boost::shared_ptr<X509>& trustedCert, const String& ticket)
{
	TcpSocket::Ptr client = new TcpSocket();

	try {
		client->Connect(host, port);
	} catch (const std::exception& ex) {
		Log(LogCritical, "cli")
		    << "Cannot connect to host '" << host << "' on port '" << port << "'";
		Log(LogDebug, "cli")
		    << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
		return 1;
	}

	boost::shared_ptr<SSL_CTX> sslContext;

	try {
		sslContext = MakeSSLContext(certfile, keyfile);
	} catch (const std::exception& ex) {
		Log(LogCritical, "cli")
		    << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'.";
		Log(LogDebug, "cli")
		    << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "':\n"  << DiagnosticInformation(ex);
		return 1;
	}

	TlsStream::Ptr stream = new TlsStream(client, host, RoleClient, sslContext);

	try {
		stream->Handshake();
	} catch (const std::exception&) {
		Log(LogCritical, "cli", "Client TLS handshake failed.");
		return 1;
	}

	boost::shared_ptr<X509> peerCert = stream->GetPeerCertificate();

	if (X509_cmp(peerCert.get(), trustedCert.get())) {
		Log(LogCritical, "cli", "Peer certificate does not match trusted certificate.");
		return 1;
	}

	Dictionary::Ptr request = new Dictionary();

	String msgid = Utility::NewUniqueID();

	request->Set("jsonrpc", "2.0");
	request->Set("id", msgid);
	request->Set("method", "pki::RequestCertificate");

	Dictionary::Ptr params = new Dictionary();
	params->Set("ticket", String(ticket));

	request->Set("params", params);

	JsonRpc::SendMessage(stream, request);

	String jsonString;
	Dictionary::Ptr response;
	StreamReadContext src;

	for (;;) {
		StreamReadStatus srs = JsonRpc::ReadMessage(stream, &jsonString, src);

		if (srs == StatusEof)
			break;

		if (srs != StatusNewItem)
			continue;

		response = JsonRpc::DecodeMessage(jsonString);

		if (response && response->Contains("error")) {
			Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log (notice or debug).");
#ifdef I2_DEBUG
			/* we shouldn't expose master errors to the user in production environments */
			Log(LogCritical, "cli", response->Get("error"));
#endif /* I2_DEBUG */
			return 1;
		}

		if (response && (response->Get("id") != msgid))
			continue;

		break;
	}

	if (!response) {
		Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log.");
		return 1;
	}

	Dictionary::Ptr result = response->Get("result");

	if (result->Contains("error")) {
		Log(LogCritical, "cli", result->Get("error"));
		return 1;
	}

	std::ofstream fpcert;
	fpcert.open(certfile.CStr());
	fpcert << result->Get("cert");
	fpcert.close();

	if (fpcert.fail()) {
		Log(LogCritical, "cli")
		    << "Could not write certificate to file '" << certfile << "'.";
		return 1;
	}

	Log(LogInformation, "cli")
	    << "Writing signed certificate to file '" << certfile << "'.";

	std::ofstream fpca;
	fpca.open(cafile.CStr());
	fpca << result->Get("ca");
	fpca.close();

	if (fpca.fail()) {
		Log(LogCritical, "cli")
		    << "Could not open CA certificate file '" << cafile << "' for writing.";
		return 1;
	}

	Log(LogInformation, "cli")
	    << "Writing CA certificate to file '" << cafile << "'.";

	return 0;
}
Пример #15
0
int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile,
    const String& certfile, const String& cafile, const String& trustedfile, const String& ticket)
{
	TcpSocket::Ptr client = make_shared<TcpSocket>();

	try {
		client->Connect(host, port);
	} catch (const std::exception& ex) {
		Log(LogCritical, "cli")
		    << "Cannot connect to host '" << host << "' on port '" << port << "'";
		Log(LogDebug, "cli")
		    << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
		return 1;
	}

	shared_ptr<SSL_CTX> sslContext;

	try {
		sslContext = MakeSSLContext(certfile, keyfile);
	} catch (const std::exception& ex) {
		Log(LogCritical, "cli")
                    << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'.";
		return 1;
	}

	TlsStream::Ptr stream = make_shared<TlsStream>(client, RoleClient, sslContext);

	try {
		stream->Handshake();
	} catch (const std::exception&) {
		Log(LogCritical, "cli", "Client TLS handshake failed.");
		return 1;
	}

	shared_ptr<X509> peerCert = stream->GetPeerCertificate();

	shared_ptr<X509> trustedCert;

	try {
		trustedCert = GetX509Certificate(trustedfile);
	} catch (const std::exception&) {
		Log(LogCritical, "cli")
                    << "Cannot get trusted from cert path: '" << trustedfile << "'.";
		return 1;
	}

	if (CertificateToString(peerCert) != CertificateToString(trustedCert)) {
		Log(LogCritical, "cli", "Peer certificate does not match trusted certificate.");
		return 1;
	}

	Dictionary::Ptr request = make_shared<Dictionary>();

	String msgid = Utility::NewUniqueID();

	request->Set("jsonrpc", "2.0");
	request->Set("id", msgid);
	request->Set("method", "pki::RequestCertificate");

	Dictionary::Ptr params = make_shared<Dictionary>();
	params->Set("ticket", String(ticket));

	request->Set("params", params);

	JsonRpc::SendMessage(stream, request);

	Dictionary::Ptr response;

	for (;;) {
		response = JsonRpc::ReadMessage(stream);

		if (response->Get("id") != msgid)
			continue;

		break;
	}

	if (!response->Contains("result")) {
		Log(LogCritical, "cli", "Request certificate did not return a valid result. Check the master log for details!");
		return 1;
	}

	Dictionary::Ptr result = response->Get("result");

	if (result->Contains("error")) {
		Log(LogCritical, "cli", result->Get("error"));
		return 1;
	}

	std::ofstream fpcert;
	fpcert.open(certfile.CStr());
	fpcert << result->Get("cert");
	fpcert.close();

	if (fpcert.fail()) {
		Log(LogCritical, "cli")
		    << "Could not write certificate to file '" << certfile << "'.";
		return 1;
	}

	Log(LogInformation, "cli")
	    << "Writing signed certificate to file '" << certfile << "'.";

	std::ofstream fpca;
	fpca.open(cafile.CStr());
	fpca << result->Get("ca");
	fpca.close();

	if (fpca.fail()) {
		Log(LogCritical, "cli")
		    << "Could not open CA certificate file '" << cafile << "' for writing.";
		return 1;
	}

	Log(LogInformation, "cli")
	    << "Writing CA certificate to file '" << cafile << "'.";

	return 0;
}
Пример #16
0
MessageES::Ptr ListenerES::accept() const
{
  TcpSocket::Ptr tcpSocket = boost::dynamic_pointer_cast<TcpSocket>(m_socket);
  TcpSocket::Ptr accepted = tcpSocket->accept();
  return MessageES::Ptr(new MessageES(accepted));
}
Пример #17
0
    bool TcpService::_addTcpConnection(TcpSocket::Ptr socket,
        const std::vector<AddSocketOption::AddSocketOptionFunc>& optionFuncs)
    {
        struct TcpService::AddSocketOption::Options options;
        for (const auto& v : optionFuncs)
        {
            if (v != nullptr)
            {
                v(options);
            }
        }

        if (options.maxRecvBufferSize <= 0)
        {
            throw std::runtime_error("buffer size is zero");
        }

        EventLoop::Ptr eventLoop;
        if (options.forceSameThreadLoop)
        {
            eventLoop = getSameThreadEventLoop();
        }
        else
        {
            eventLoop = getRandomEventLoop();
        }
        if (eventLoop == nullptr)
        {
            return false;
        }

        auto wrapperEnterCallback = [options](const TcpConnection::Ptr& tcpConnection) {
            for (const auto& callback : options.enterCallback)
            {
                callback(tcpConnection);
            }
        };

        const auto isServerSide = socket->isServerSide();
        auto tcpConnection = TcpConnection::Create(std::move(socket),
            options.maxRecvBufferSize,
            wrapperEnterCallback,
            eventLoop);
        (void)isServerSide;
#ifdef USE_OPENSSL
        if (options.useSSL)
        {
            if (isServerSide)
            {
                if (options.sslHelper == nullptr ||
                    options.sslHelper->getOpenSSLCTX() == nullptr ||
                    !tcpConnection->initAcceptSSL(options.sslHelper->getOpenSSLCTX()))
                {
                    return false;
                }
            }
            else
            {
                if (!tcpConnection->initConnectSSL())
                {
                    return false;
                }
            }
        }
#else
        if (options.useSSL)
        {
            return false;
        }
#endif
        eventLoop->runAsyncFunctor([tcpConnection]() {
            tcpConnection->onEnterEventLoop();
        });

        return true;
    }