Пример #1
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);
}
Пример #2
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;
}
Пример #3
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);
}
Пример #4
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;
}
Пример #5
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 << "'";
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
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);
}
Пример #9
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);
	}
}
Пример #10
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);
	}
}
Пример #11
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();
}
Пример #12
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;
}
Пример #13
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;
}