* @param sslContext The SSL context for the client.
*/
TlsStream::TlsStream(const Socket::Ptr& socket, ConnectionRole role, const shared_ptr<SSL_CTX>& sslContext)
- : m_Eof(false), m_Socket(socket), m_Role(role)
+ : m_Eof(false), m_Socket(socket), m_Role(role), m_VerifyOK(false)
{
std::ostringstream msgbuf;
char errbuf[120];
SSL_set_ex_data(m_SSL.get(), m_SSLIndex, this);
- SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+ SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, &TlsStream::ValidateCertificate);
socket->MakeNonBlocking();
SSL_set_connect_state(m_SSL.get());
}
+int TlsStream::ValidateCertificate(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ SSL *ssl = static_cast<SSL *>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
+ TlsStream *stream = static_cast<TlsStream *>(SSL_get_ex_data(ssl, m_SSLIndex));
+ stream->m_VerifyOK = preverify_ok;
+ return 1;
+}
+
+bool TlsStream::IsVerifyOK(void) const
+{
+ return m_VerifyOK;
+}
+
/**
* Retrieves the X509 certficate for this client.
*
virtual bool IsEof(void) const;
+ bool IsVerifyOK(void) const;
+
private:
shared_ptr<SSL> m_SSL;
bool m_Eof;
mutable boost::mutex m_SSLLock;
mutable boost::mutex m_IOActionLock;
+ bool m_VerifyOK;
Socket::Ptr m_Socket;
ConnectionRole m_Role;
static int m_SSLIndex;
static bool m_SSLIndexInitialized;
+ static int ValidateCertificate(int preverify_ok, X509_STORE_CTX *ctx);
static void NullCertificateDeleter(X509 *certificate);
};
static Value SetLogPositionHandler(const MessageOrigin& origin, const Dictionary::Ptr& params);
REGISTER_APIFUNCTION(SetLogPosition, log, &SetLogPositionHandler);
-ApiClient::ApiClient(const String& identity, const Stream::Ptr& stream, ConnectionRole role)
- : m_Identity(identity), m_Stream(stream), m_Role(role), m_Seen(Utility::GetTime())
+ApiClient::ApiClient(const String& identity, bool authenticated, const Stream::Ptr& stream, ConnectionRole role)
+ : m_Identity(identity), m_Authenticated(authenticated), m_Stream(stream), m_Role(role), m_Seen(Utility::GetTime())
{
- m_Endpoint = Endpoint::GetByName(identity);
+ if (authenticated)
+ m_Endpoint = Endpoint::GetByName(identity);
}
void ApiClient::Start(void)
return m_Identity;
}
+bool ApiClient::IsAuthenticated(void) const
+{
+ return m_Authenticated;
+}
+
Endpoint::Ptr ApiClient::GetEndpoint(void) const
{
return m_Endpoint;
public:
DECLARE_PTR_TYPEDEFS(ApiClient);
- ApiClient(const String& identity, const Stream::Ptr& stream, ConnectionRole role);
+ ApiClient(const String& identity, bool authenticated, const Stream::Ptr& stream, ConnectionRole role);
void Start(void);
String GetIdentity(void) const;
+ bool IsAuthenticated(void) const;
Endpoint::Ptr GetEndpoint(void) const;
Stream::Ptr GetStream(void) const;
ConnectionRole GetRole(void) const;
private:
String m_Identity;
+ bool m_Authenticated;
Endpoint::Ptr m_Endpoint;
Stream::Ptr m_Stream;
ConnectionRole m_Role;
return;
}
- Log(LogInformation, "ApiListener", "New client connection for identity '" + identity + "'");
+ bool verify_ok = tlsStream->IsVerifyOK();
- Endpoint::Ptr endpoint = Endpoint::GetByName(identity);
+ std::ostringstream msgbuf;
+ msgbuf << "New client connection for identity '" << identity << "'";
+
+ if (!verify_ok)
+ msgbuf << " (unauthenticated)";
+
+ Log(LogInformation, "ApiListener", msgbuf.str());
+
+ Endpoint::Ptr endpoint;
+
+ if (verify_ok)
+ endpoint = Endpoint::GetByName(identity);
bool need_sync = false;
if (endpoint)
need_sync = !endpoint->IsConnected();
- ApiClient::Ptr aclient = make_shared<ApiClient>(identity, tlsStream, role);
+ ApiClient::Ptr aclient = make_shared<ApiClient>(identity, verify_ok, tlsStream, role);
aclient->Start();
if (endpoint) {
void NewClientHandler(const Socket::Ptr& client, ConnectionRole role);
void ListenerThreadProc(const Socket::Ptr& server);
- void MessageHandler(const TlsStream::Ptr& sender, const String& identity, const Dictionary::Ptr& message);
-
WorkQueue m_RelayQueue;
boost::mutex m_LogLock;