Revision: 180
Author:
sma...@gmail.com
Date: Thu May 23 16:56:04 2013
Log: Add blacklist feature for specific client identities under a CA
Certificate configuration. Blacklisted clients are added by client
certificate. When configuring blacklisted clients in omapd.conf, this is
set as a directory that contains the blacklisted client certificates. When
blacklisting a client through the management interface, the client
certificate file and the CA certificate file paths are used. TODO:
terminate active sessions for blacklisted clients added through the
management interface.
http://code.google.com/p/omapd/source/detail?r=180
Modified:
/trunk/clientconfiguration.cpp
/trunk/clientconfiguration.h
/trunk/managementserver.cpp
/trunk/mapsessions.cpp
/trunk/mapsessions.h
/trunk/omapd.conf
/trunk/omapdconfig.cpp
=======================================
--- /trunk/clientconfiguration.cpp Sun Feb 24 14:35:44 2013
+++ /trunk/clientconfiguration.cpp Thu May 23 16:56:04 2013
@@ -49,12 +49,13 @@
_metadataPolicy = metadataPolicy;
}
-void ClientConfiguration::createCAAuthClient(QString clientPrefix, QString
issuingCACertFile, QString caCertFile, OmapdConfig::AuthzOptions authz,
QString metadataPolicy)
+void ClientConfiguration::createCAAuthClient(QString clientPrefix, QString
issuingCACertFile, QString caCertFile, OmapdConfig::AuthzOptions authz,
QString metadataPolicy, QString blacklistDir)
{
_authType = MapRequest::AuthCACert;
_authz = authz;
_name = clientPrefix;
_caCertFileName = caCertFile;
+ _blacklistDirectory = blacklistDir;
// In this case, _certFileName and _haveClientCert refer to the
issuingCACertFile
_certFileName = issuingCACertFile;
_haveClientCert = true;
=======================================
--- /trunk/clientconfiguration.h Sun Feb 24 14:35:44 2013
+++ /trunk/clientconfiguration.h Thu May 23 16:56:04 2013
@@ -31,7 +31,7 @@
ClientConfiguration();
void createBasicAuthClient(QString clientName, QString username,
QString password, OmapdConfig::AuthzOptions authz, QString metadataPolicy);
void createCertAuthClient(QString clientName, QString certFile,
QString caCertFile, OmapdConfig::AuthzOptions authz, QString
metadataPolicy);
- void createCAAuthClient(QString clientPrefix, QString
issuingCACertFile, QString caCertFile, OmapdConfig::AuthzOptions authz,
QString metadataPolicy);
+ void createCAAuthClient(QString clientPrefix, QString
issuingCACertFile, QString caCertFile, OmapdConfig::AuthzOptions authz,
QString metadataPolicy, QString blacklistDir = QString());
QString metadataPolicy() { return _metadataPolicy; }
QString name() { return _name; }
@@ -39,6 +39,7 @@
QString password() { return _password; }
QString certFileName() { return _certFileName; }
QString caCertFileName() { return _caCertFileName; }
+ QString blacklistDirectory() { return _blacklistDirectory; }
bool haveClientCert() { return _haveClientCert; }
MapRequest::AuthenticationType authType() { return _authType; }
OmapdConfig::AuthzOptions authz() { return _authz; }
@@ -49,6 +50,7 @@
QString _password;
QString _certFileName;
QString _caCertFileName;
+ QString _blacklistDirectory;
bool _haveClientCert;
MapRequest::AuthenticationType _authType;
OmapdConfig::AuthzOptions _authz;
=======================================
--- /trunk/managementserver.cpp Fri Mar 1 13:17:05 2013
+++ /trunk/managementserver.cpp Thu May 23 16:56:04 2013
@@ -222,6 +222,48 @@
}
}
+
+ } else if (command == "addCertClientToBlacklist") {
+ // Note: Clients blacklisted through mgmt interface but still
defined in omapd.conf
+ // will be re-enabled when omapd restarts.
+ /*
+ { "cmd":"addCertClientToBlacklist",
+ "certPath":"/path/to/clientCert",
+ "caPath":"/path/to/clientCACert" }
+ */
+ if (parsedRequest.contains("certPath") &&
+ parsedRequest.contains("caPath") &&
+ QFile::exists(parsedRequest["certPath"].toString()) &&
+ QFile::exists(parsedRequest["caPath"].toString())) {
+
+ QString certPath = parsedRequest["certPath"].toString();
+ QString certCAPath = parsedRequest["caPath"].toString();
+
+ ClientConfiguration clientConfig;
+ clientConfig.createCertAuthClient("", certPath, certCAPath,
0, "");
+
MapSessions::getInstance()->addBlacklistClientConfiguration(&clientConfig);
+ }
+
+ } else if (command == "removeCertClientFromBlacklist") {
+ // Note: Clients removed from the blacklist through mgmt interface
but still defined
+ // in omapd.conf will be re-added to the blacklist when omapd
restarts.
+ /*
+ { "cmd":"removeCertClientFromBlacklist",
+ "certPath":"/path/to/clientCert",
+ "caPath":"/path/to/clientCACert" }
+ */
+ if (parsedRequest.contains("certPath") &&
+ parsedRequest.contains("caPath") &&
+ QFile::exists(parsedRequest["certPath"].toString()) &&
+ QFile::exists(parsedRequest["caPath"].toString())) {
+
+ QString certPath = parsedRequest["certPath"].toString();
+ QString certCAPath = parsedRequest["caPath"].toString();
+
+ ClientConfiguration clientConfig;
+ clientConfig.createCertAuthClient("", certPath, certCAPath,
0, "");
+
MapSessions::getInstance()->removeBlacklistClientConfiguration(&clientConfig);
+ }
} else {
if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
=======================================
--- /trunk/mapsessions.cpp Fri Mar 1 13:17:05 2013
+++ /trunk/mapsessions.cpp Thu May 23 16:56:04 2013
@@ -143,11 +143,17 @@
if (client->authType() == MapRequest::AuthCACert) {
MapClient mapClient(authToken, client->authType(),
client->authz(), "", client->metadataPolicy());
_mapClientCAs.insert(authToken, mapClient);
+
+ if (!client->blacklistDirectory().isEmpty()) {
+ loadBlacklistedClients(client->blacklistDirectory(),
client->caCertFileName());
+ }
+
if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
qDebug() << __PRETTY_FUNCTION__ << ":" << "Created CA
Authentication MapClient for configuration named:" << client->name()
<< "authToken:" << authToken
<< "authz:" <<
OmapdConfig::authzOptionsString(client->authz())
- << "metadataPolicy" << client->metadataPolicy();
+ << "metadataPolicy" << client->metadataPolicy()
+ << "blacklist directory" <<
client->blacklistDirectory();
}
} else {
QString pubId;
@@ -236,6 +242,92 @@
return clientConfigOk;
}
+
+void MapSessions::loadBlacklistedClients(QString blacklistDirectory,
QString caCertFile)
+{
+ QDir blacklistDir(blacklistDirectory);
+ QStringList files = blacklistDir.entryList();
+
+ QStringListIterator fileIt(files);
+ while (fileIt.hasNext()) {
+ QString file = fileIt.next();
+ ClientConfiguration clientConfig;
+ clientConfig.createCertAuthClient("blacklist", file, caCertFile,
0, "");
+
+ manageClientBlacklist(&clientConfig, MapSessions::AddToBlacklist);
+ }
+}
+
+bool MapSessions::manageClientBlacklist(ClientConfiguration *client,
MapSessions::BlacklistAction action)
+{
+ bool clientConfigOk = false;
+
+ QString authToken;
+
+ if (client->haveClientCert()) {
+ QFile certFile(client->certFileName());
+ if (!certFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Client:" <<
client->name()
+ << "has no certificate file:" << certFile.fileName();
+ } else {
+ QSslCertificate clientCert;
+ // Try PEM format fail over to DER; since they are the only 2
+ // supported by the QSsl Certificate classes
+ clientCert = QSslCertificate(&certFile, QSsl::Pem);
+ if ( clientCert.isNull() )
+ clientCert = QSslCertificate(&certFile, QSsl::Der);
+
+ if (!clientCert.isNull()) clientConfigOk = true;
+
+ authToken = ClientHandler::buildDN(clientCert,
ClientHandler::Subject);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Loaded cert for
client named:" << client->name();
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "-- DN:" <<
authToken;
+ }
+ authToken += "::SEPARATOR::";
+ authToken += ClientHandler::buildDN(clientCert,
ClientHandler::Issuer);
+
+ if (authToken.isEmpty())
+ clientConfigOk = false;
+ }
+ }
+
+ if (clientConfigOk) {
+ if (action == MapSessions::AddToBlacklist) {
+ _blacklistedClients.insert(authToken);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Added
blacklisted MapClient with authToken" << authToken;
+ }
+ } else if (action == MapSessions::RemoveFromBlacklist) {
+ // Note: we will still return true even if client is not
originally in blacklist
+ _blacklistedClients.remove(authToken);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Removed
MapClient from blacklisted with authToken" << authToken;
+ }
+ }
+ } else {
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Error adding
blacklisted MapClient";
+ }
+
+ return clientConfigOk;
+}
+
+bool MapSessions::addBlacklistClientConfiguration(ClientConfiguration
*client)
+{
+ bool addOk = false;
+
+ if (manageClientBlacklist(client, MapSessions::AddToBlacklist)) {
+ // Terminate existing sessions
+ addOk = true;
+ }
+
+ return addOk;
+}
+
+bool MapSessions::removeBlacklistClientConfiguration(ClientConfiguration
*client)
+{
+ return manageClientBlacklist(client, MapSessions::RemoveFromBlacklist);
+}
QString MapSessions::generateSessionId()
{
@@ -272,7 +364,12 @@
bool registered = false;
if (authType != MapRequest::AuthNone && !authToken.isEmpty()) {
- if (_mapClients.contains(authToken)) {
+ if (_blacklistedClients.contains(authToken)) {
+ // This client is blacklisted
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Client is
blacklisted:" << authToken;
+ }
+ } else if (_mapClients.contains(authToken)) {
// Already have a publisher-id for this client
pubId = _mapClients.value(authToken).pubId();
if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
=======================================
--- /trunk/mapsessions.h Fri Mar 1 13:17:05 2013
+++ /trunk/mapsessions.h Thu May 23 16:56:04 2013
@@ -38,6 +38,11 @@
{
Q_OBJECT
public:
+ enum BlacklistAction {
+ AddToBlacklist = 1,
+ RemoveFromBlacklist
+ };
+
static MapSessions* getInstance();
QString registerMapClient(ClientHandler *socket,
MapRequest::AuthenticationType authType, QString authToken);
@@ -79,6 +84,11 @@
bool loadClientConfiguration(ClientConfiguration *client);
bool removeClientConfiguration(ClientConfiguration *client);
+ void loadBlacklistedClients(QString blacklistDirectory, QString
caCertFile);
+ bool manageClientBlacklist(ClientConfiguration *client,
MapSessions::BlacklistAction action);
+ bool addBlacklistClientConfiguration(ClientConfiguration *client);
+ bool removeBlacklistClientConfiguration(ClientConfiguration *client);
+
private:
MapSessions(QObject *parent = 0);
~MapSessions();
@@ -90,6 +100,7 @@
QHash<QString, MapClient> _mapClients; // authToken --> MapClient
QHash<QString, MapClient> _mapClientCAs; // CA AuthToken --> MapClient
+ QSet<QString> _blacklistedClients; // blacklisted client authToken
// Registry for published vendor specific metadata cardinalities
QHash<VSM, Meta::Cardinality> _vsmRegistry;
=======================================
--- /trunk/omapd.conf Fri Mar 1 13:17:05 2013
+++ /trunk/omapd.conf Thu May 23 16:56:04 2013
@@ -69,11 +69,28 @@
"certPath":"/path/to/clientCert",
"caPath":"/path/to/clientCACert"
}
+ * Blacklist a certificate-based client under a CA. Prevent this
client from
+ connecting to omapd. Note that this command only makes sense
for clients
+ connecting under a CA client configuration. This command
returns success as
+ long as the certificates exist and are valid.
+ { "cmd":"addCertClientToBlacklist",
+ "certPath":"/path/to/clientCert",
+ "caPath":"/path/to/clientCACert"
+ }
+ * Remove a client from the blacklist. Note that this command
only makes sense for clients
+ connecting under a CA client configuration. This command
returns success as
+ long as the certificates exist and are valid.
+ { "cmd":"removeCertClientFromBlacklist",
+ "certPath":"/path/to/clientCert",
+ "caPath":"/path/to/clientCACert"
+ }
-->
<!-- Example usages:
echo '{"cmd":"mapdump"}' | nc localhost 8097
echo '{"cmd":"addCertClient","type":"single","name":"clientName","certPath":"/path/to/clientCert","caPath":"/path/to/clientCAChain","authorization":"0x1E","metadataPolicy":"policyName"}'
| nc localhost 8097
echo '{"cmd":"removeCertClient","type":"single","certPath":"/path/to/clientCert","caPath":"/path/to/clientCAChain"}'
| nc localhost 8097
+
echo '{"cmd":"addCertClientToBlacklist","certPath":"/path/to/clientCert","caPath":"/path/to/clientCAChain"}'
| nc localhost 8097
+
echo '{"cmd":"removeCertClientFromBlacklist","certPath":"/path/to/clientCert","caPath":"/path/to/clientCAChain"}'
| nc localhost 8097
-->
</management_configuration>
@@ -204,10 +221,20 @@
the specified authorization. Note that the issuing CA Cert should also
be
included in the CA Certificates file.
-->
+ <!-- In the following example, specific client identities can be
blacklisted
+ from authenticating under the given CA certificate by specifying the
optional
+ blacklist_directory element. Omapd will parse the certificates in this
directory
+ and add them to the list of blacklisted clients. Multiple CA
Certificate client
+ configurations can use the same blacklist directory; the directory
will be processed
+ each time, but only a single blacklist entry will be created for each
certificate
+ in the blacklist directory. Note that this directory will be read
only once upon
+ omapd startup.
+ -->
<!--
<client name="ca-client-" authorization="1F"
authentication="ca-certificate" metadata_policy="policy2">
<issuing_ca_certificate_file
format="pem">issuing-cacert.pem</issuing_ca_certificate_file>
<ca_certificates_file
format="pem">client-cacert.pem</ca_certificates_file>
+ <blacklist_directory>/path/to/blacklisted/certs</blacklist_directory>
</client>
-->
</client_configuration>
=======================================
--- /trunk/omapdconfig.cpp Sun Feb 24 14:35:44 2013
+++ /trunk/omapdconfig.cpp Thu May 23 16:56:04 2013
@@ -563,6 +563,7 @@
bool haveIssuingCACertFile = false,
haveCACertFile = false;
QString issuingCaCertFileName;
QString caCertFileName;
+ QString blacklistDirectory;
for (int i=0; i<2; i++) {
if (xmlReader.name()
== "issuing_ca_certificate_file") {
@@ -573,8 +574,10 @@
// TODO: Deal with certificate
type {pem|der}
caCertFileName =
xmlReader.readElementText(QXmlStreamReader::ErrorOnUnexpectedElement);
haveCACertFile =
QFile::exists(caCertFileName);
+ } else if (xmlReader.name()
== "blacklist_directory") {
+ blacklistDirectory =
xmlReader.readElementText(QXmlStreamReader::ErrorOnUnexpectedElement);
} else {
-
xmlReader.raiseError(QObject::tr("invalid cert auth element"));
+
xmlReader.raiseError(QObject::tr("invalid ca-certificate auth element"));
}
xmlReader.readNextStartElement();
}
@@ -585,7 +588,8 @@
issuingCaCertFileName,
caCertFileName,
OmapdConfig::authzOptions(clientAuthz),
-
metadataPolicy);
+
metadataPolicy,
+
blacklistDirectory);
_clientConfigurations.append(clientConfig);
}