#pragma once
-#include <map>
#include <string>
+#include "iohook.h"
/** ssl_cert is a class which abstracts SSL certificate
* and key information.
}
};
-/** Get certificate from a socket (only useful with an SSL module) */
-struct SocketCertificateRequest : public Request
+class SSLIOHook : public IOHook
{
- StreamSocket* const sock;
- ssl_cert* cert;
+ protected:
+ /** Peer SSL certificate, set by the SSL module
+ */
+ reference<ssl_cert> certificate;
- SocketCertificateRequest(StreamSocket* ss, Module* Me)
- : Request(Me, ss->GetIOHook(), "GET_SSL_CERT"), sock(ss), cert(NULL)
+ public:
+ SSLIOHook(IOHookProvider* hookprov)
+ : IOHook(hookprov)
{
- Send();
}
- std::string GetFingerprint()
+ /**
+ * Get the certificate sent by this peer
+ * @return The SSL certificate sent by the peer, NULL if no cert was sent
+ */
+ ssl_cert* GetCertificate() const
{
+ return certificate;
+ }
+
+ /**
+ * Get the fingerprint of the peer's certificate
+ * @return The fingerprint of the SSL client certificate sent by the peer,
+ * empty if no cert was sent
+ */
+ std::string GetFingerprint() const
+ {
+ ssl_cert* cert = GetCertificate();
if (cert)
return cert->GetFingerprint();
return "";
}
};
-/** Get certificate from a user (requires m_sslinfo) */
-struct UserCertificateRequest : public Request
+/** Helper functions for obtaining SSL client certificates and key fingerprints
+ * from StreamSockets
+ */
+class SSLClientCert
{
- User* const user;
- ssl_cert* cert;
+ public:
+ /**
+ * Get the client certificate from a socket
+ * @param sock The socket to get the certificate from, the socket does not have to use SSL
+ * @return The SSL client certificate information, NULL if the peer is not using SSL
+ */
+ static ssl_cert* GetCertificate(StreamSocket* sock)
+ {
+ IOHook* iohook = sock->GetIOHook();
+ if ((!iohook) || (iohook->prov->type != IOHookProvider::IOH_SSL))
+ return NULL;
+
+ SSLIOHook* ssliohook = static_cast<SSLIOHook*>(iohook);
+ return ssliohook->GetCertificate();
+ }
- UserCertificateRequest(User* u, Module* Me, Module* info = ServerInstance->Modules->Find("m_sslinfo.so"))
- : Request(Me, info, "GET_USER_CERT"), user(u), cert(NULL)
+ /**
+ * Get the fingerprint of a client certificate from a socket
+ * @param sock The socket to get the certificate fingerprint from, the
+ * socket does not have to use SSL
+ * @return The key fingerprint from the SSL certificate sent by the peer,
+ * empty if no cert was sent or the peer is not using SSL
+ */
+ static std::string GetFingerprint(StreamSocket* sock)
{
- Send();
+ ssl_cert* cert = SSLClientCert::GetCertificate(sock);
+ if (cert)
+ return cert->GetFingerprint();
+ return "";
}
+};
+
+class UserCertificateAPIBase : public DataProvider
+{
+ public:
+ UserCertificateAPIBase(Module* parent)
+ : DataProvider(parent, "m_sslinfo_api")
+ {
+ }
+
+ /** Get the SSL certificate of a user
+ * @param user The user whose certificate to get, user may be remote
+ * @return The SSL certificate of the user or NULL if the user is not using SSL
+ */
+ virtual ssl_cert* GetCertificate(User* user) = 0;
- std::string GetFingerprint()
+ /** Get the key fingerprint from a user's certificate
+ * @param user The user whose key fingerprint to get, user may be remote
+ * @return The key fingerprint from the user's SSL certificate or an empty string
+ * if the user is not using SSL or did not provide a client certificate
+ */
+ std::string GetFingerprint(User* user)
{
+ ssl_cert* cert = GetCertificate(user);
if (cert)
return cert->GetFingerprint();
return "";
}
};
+
+/** API implemented by m_sslinfo that allows modules to retrive the SSL certificate
+ * information of local and remote users. It can also be used to find out whether a
+ * user is using SSL or not.
+ */
+class UserCertificateAPI : public dynamic_reference<UserCertificateAPIBase>
+{
+ public:
+ UserCertificateAPI(Module* parent)
+ : dynamic_reference<UserCertificateAPIBase>(parent, "m_sslinfo_api")
+ {
+ }
+};