You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ch...@apache.org on 2016/09/09 14:17:32 UTC
qpid-dispatch git commit: DISPATCH-468: Use computed x.509 cert
display-name as authenticated id
Repository: qpid-dispatch
Updated Branches:
refs/heads/master bba79f3c6 -> 6e9c24e95
DISPATCH-468: Use computed x.509 cert display-name as authenticated id
Add a DisplayName service interface to be called from C code.
During connection establishment use the translated display name
as the connection authenticated user_id.
This closes #97
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/6e9c24e9
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/6e9c24e9
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/6e9c24e9
Branch: refs/heads/master
Commit: 6e9c24e954e958476fca2b0ceb5a1d9874ef1f73
Parents: bba79f3
Author: Chuck Rolke <cr...@redhat.com>
Authored: Fri Sep 9 10:07:05 2016 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Fri Sep 9 10:07:05 2016 -0400
----------------------------------------------------------------------
include/qpid/dispatch/server.h | 10 +++++
python/qpid_dispatch_internal/dispatch.py | 2 +
.../display_name/display_name.py | 12 +++++-
.../qpid_dispatch_internal/management/config.py | 1 +
src/dispatch.c | 6 +++
src/dispatch_private.h | 5 +++
src/server.c | 42 ++++++++++++++++++++
src/server_private.h | 2 +
tests/displayname_files/profile_names1.json | 4 +-
tests/displayname_files/profile_names2.json | 3 +-
tests/system_tests_user_id.py | 38 ++++++++++++++++--
11 files changed, 119 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/include/qpid/dispatch/server.h
----------------------------------------------------------------------
diff --git a/include/qpid/dispatch/server.h b/include/qpid/dispatch/server.h
index 03d4e4b..a0ee4b5 100644
--- a/include/qpid/dispatch/server.h
+++ b/include/qpid/dispatch/server.h
@@ -659,6 +659,16 @@ qd_connector_t *qd_server_connect(qd_dispatch_t *qd, const qd_server_config_t *c
*/
void qd_server_connector_free(qd_connector_t* ct);
+
+
+/**
+ * Store address of display name service py object for C code use
+ *
+ * @param qd The dispatch handle returned by qd_dispatch.
+ * @param display_name_service address of python object
+ */
+qd_error_t qd_register_display_name_service(qd_dispatch_t *qd, void *display_name_service);
+
/**
* @}
*/
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/python/qpid_dispatch_internal/dispatch.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/dispatch.py b/python/qpid_dispatch_internal/dispatch.py
index 11fe6ed..e397f86 100644
--- a/python/qpid_dispatch_internal/dispatch.py
+++ b/python/qpid_dispatch_internal/dispatch.py
@@ -80,6 +80,8 @@ class QdDll(ctypes.PyDLL):
self._prototype(self.qd_dispatch_policy_c_counts_free, None, [c_long], check=False)
self._prototype(self.qd_dispatch_policy_c_counts_refresh, None, [c_long, py_object])
+ self._prototype(self.qd_dispatch_register_display_name_service, None, [self.qd_dispatch_p, py_object])
+
self._prototype(self.qd_dispatch_set_agent, None, [self.qd_dispatch_p, py_object])
self._prototype(self.qd_router_setup_late, None, [self.qd_dispatch_p])
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/python/qpid_dispatch_internal/display_name/display_name.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/display_name/display_name.py b/python/qpid_dispatch_internal/display_name/display_name.py
index 5ecb867..9cce3a7 100644
--- a/python/qpid_dispatch_internal/display_name/display_name.py
+++ b/python/qpid_dispatch_internal/display_name/display_name.py
@@ -92,7 +92,6 @@ class DisplayNameService(object):
body = {'user_name': user_name if user_name else user_id}
else:
body = {'user_name': user_id}
-
return body
def receive(self, message, unused_link_id, unused_cost):
@@ -123,3 +122,14 @@ class DisplayNameService(object):
self.io_adapter[0].send(response)
+
+def display_name_local_query(displaynameservice, profile_name, user_id):
+ """
+ Local query interface for reading cached name translations from C code
+ @param displaynameservice: DisplayNameService python instance
+ @param profile_name: connection's sslProfile name
+ @param user_id: Name formatted from SSL cert fields
+ @return: Name to be used as connection's authenticated user
+ """
+ body = displaynameservice.query(profile_name, user_id)
+ return body['user_name']
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/python/qpid_dispatch_internal/management/config.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/management/config.py b/python/qpid_dispatch_internal/management/config.py
index a7b82c7..9df1dad 100644
--- a/python/qpid_dispatch_internal/management/config.py
+++ b/python/qpid_dispatch_internal/management/config.py
@@ -155,6 +155,7 @@ def configure_dispatch(dispatch, lib_handle, filename):
from qpid_dispatch_internal.display_name.display_name import DisplayNameService
displayname_service = DisplayNameService("$displayname")
+ qd.qd_dispatch_register_display_name_service(dispatch, displayname_service)
policyDir = config.by_type('policy')[0]['policyDir']
policyDefaultVhost = config.by_type('policy')[0]['defaultVhost']
# Remaining configuration
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/src/dispatch.c
----------------------------------------------------------------------
diff --git a/src/dispatch.c b/src/dispatch.c
index 1b39228..902f097 100644
--- a/src/dispatch.c
+++ b/src/dispatch.c
@@ -190,6 +190,12 @@ qd_error_t qd_dispatch_register_policy_manager(qd_dispatch_t *qd, qd_entity_t *e
}
+qd_error_t qd_dispatch_register_display_name_service(qd_dispatch_t *qd, void *object)
+{
+ return qd_register_display_name_service(qd, object);
+}
+
+
long qd_dispatch_policy_c_counts_alloc()
{
return qd_policy_c_counts_alloc();
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/src/dispatch_private.h
----------------------------------------------------------------------
diff --git a/src/dispatch_private.h b/src/dispatch_private.h
index 27a454f..99c35d7 100644
--- a/src/dispatch_private.h
+++ b/src/dispatch_private.h
@@ -117,6 +117,11 @@ qd_error_t qd_dispatch_configure_policy(qd_dispatch_t *qd, qd_entity_t *entity);
qd_error_t qd_dispatch_register_policy_manager(qd_dispatch_t *qd, qd_entity_t *entity);
/**
+ * Configure display name service, must be called after qd_dispatch_prepare
+ */
+qd_error_t qd_dispatch_register_display_name_service(qd_dispatch_t *qd, void *object);
+
+/**
* \brief Configure the logging module from the
* parsed configuration file. This must be called after the
* call to qd_dispatch_prepare completes.
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/src/server.c
----------------------------------------------------------------------
diff --git a/src/server.c b/src/server.c
index aa08ae6..e78978d 100644
--- a/src/server.c
+++ b/src/server.c
@@ -23,6 +23,7 @@
#include <qpid/dispatch/log.h>
#include <qpid/dispatch/amqp.h>
#include <qpid/dispatch/server.h>
+#include "qpid/dispatch/python_embedded.h"
#include "entity.h"
#include "entity_cache.h"
#include "dispatch_private.h"
@@ -133,6 +134,19 @@ static qd_error_t connection_entity_update_host(qd_entity_t* entity, qd_connecti
return qd_entity_set_string(entity, "host", qdpn_connector_name(conn->pn_cxtr));
}
+
+/**
+ * Save displayNameService object instance and ImportModule address
+ * Called with qd_python_lock held
+ */
+qd_error_t qd_register_display_name_service(qd_dispatch_t *qd, void *displaynameservice)
+{
+ qd->server->py_displayname_obj = displaynameservice;
+ qd->server->py_displayname_module = PyImport_ImportModule("qpid_dispatch_internal.display_name.display_name");
+ return qd->server->py_displayname_module ? QD_ERROR_NONE : qd_error(QD_ERROR_RUNTIME, "Fail importing DisplayNameService module");
+}
+
+
/**
* Returns a char pointer to a user id which is constructed from components specified in the config->ssl_uid_format.
* Parses through each component and builds a semi-colon delimited string which is returned as the user id.
@@ -310,6 +324,32 @@ static const char *qd_transport_get_user(qd_connection_t *conn, pn_transport_t *
}
}
}
+ if (config->ssl_display_name_file) {
+ // Translate extracted id into display name
+ qd_python_lock_state_t lock_state = qd_python_lock();
+ PyObject *module = (PyObject*)conn->server->py_displayname_module;
+ PyObject *query = PyObject_GetAttrString(module, "display_name_local_query");
+ if (query) {
+ PyObject *result = PyObject_CallFunction(query, "(Oss)",
+ (PyObject *)conn->server->py_displayname_obj,
+ config->ssl_profile, user_id);
+ if (result) {
+ const char *res_string = PyString_AsString(result);
+ free(user_id);
+ user_id = malloc(strlen(res_string) + 1);
+ user_id[0] = '\0';
+ strcat(user_id, res_string);
+ Py_XDECREF(result);
+ } else {
+ qd_log(conn->server->log_source, QD_LOG_DEBUG, "Internal: failed to read displaynameservice query result");
+ }
+ Py_XDECREF(query);
+ } else {
+ qd_log(conn->server->log_source, QD_LOG_DEBUG, "Internal: failed to locate query function");
+ }
+ Py_XDECREF(module);
+ qd_python_unlock(lock_state);
+ }
qd_log(conn->server->log_source, QD_LOG_DEBUG, "User id is '%s' ", user_id);
return user_id;
}
@@ -1351,6 +1391,8 @@ qd_server_t *qd_server(qd_dispatch_t *qd, int thread_count, const char *containe
qd_server->signal_handler_running = false;
qd_server->heartbeat_timer = 0;
qd_server->next_connection_id = 1;
+ qd_server->py_displayname_module = 0;
+ qd_server->py_displayname_obj = 0;
qd_log(qd_server->log_source, QD_LOG_INFO, "Container Name: %s", qd_server->container_name);
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/src/server_private.h
----------------------------------------------------------------------
diff --git a/src/server_private.h b/src/server_private.h
index 008ed2b..caa3471 100644
--- a/src/server_private.h
+++ b/src/server_private.h
@@ -180,6 +180,8 @@ struct qd_server_t {
qd_connection_list_t connections;
qd_timer_t *heartbeat_timer;
uint64_t next_connection_id;
+ void *py_displayname_module;
+ void *py_displayname_obj;
};
ALLOC_DECLARE(qd_work_item_t);
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/tests/displayname_files/profile_names1.json
----------------------------------------------------------------------
diff --git a/tests/displayname_files/profile_names1.json b/tests/displayname_files/profile_names1.json
index 21337db..f0f0dd4 100644
--- a/tests/displayname_files/profile_names1.json
+++ b/tests/displayname_files/profile_names1.json
@@ -1,5 +1,7 @@
{
"14845961c5646ee0129536b3a9ef1eea0d8d2f26f8c3ed08ece4f8f3027ba9d5": "gmurthy",
"94745961c5646ee0129536b3acef1eea0d8d2f26f8c3ed08ece4f8f3027bcd47": "janedoe",
- "94745961c5646ee0129536b3acef1eea0d8d2f26f8c3ed08ece4f8f3027bcd48": "johndoe"
+ "94745961c5646ee0129536b3acef1eea0d8d2f26f8c3ed08ece4f8f3027bcd48": "johndoe",
+ "60f5dbd7ed14a5ea243785e81745ac8463494298": "user13",
+ "82244216b6d02ffdfb886c8da3c803e0f7a7b330a7b665dccabd30bd25d0f35e2a4fff5f0a2a01d56eb7dbae085c108e71a32b84bab16c9ec243a1f6d014900d" : "user14"
}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/tests/displayname_files/profile_names2.json
----------------------------------------------------------------------
diff --git a/tests/displayname_files/profile_names2.json b/tests/displayname_files/profile_names2.json
index 497543e..152f705 100644
--- a/tests/displayname_files/profile_names2.json
+++ b/tests/displayname_files/profile_names2.json
@@ -1,5 +1,6 @@
{
"14845961c5646ee0129536b3a9ef1eea0d8d2f26f8c3ed08ece4f5546546": "jerry",
"94745961c5646ee0129536b3acef1eea0d8d2f26f8c353455233027bcd47": "elaine",
- "94745961c5646ee0129536b3acef1eea0d8d2f26f8c3ed08ece3027bcd48": "george"
+ "94745961c5646ee0129536b3acef1eea0d8d2f26f8c3ed08ece3027bcd48": "george",
+ "7c87f0c974f9e1aa5cb98f13fae9675625f240c98034b888753140da28094879": "user12"
}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6e9c24e9/tests/system_tests_user_id.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_user_id.py b/tests/system_tests_user_id.py
index 8b70470..ddd4f67 100644
--- a/tests/system_tests_user_id.py
+++ b/tests/system_tests_user_id.py
@@ -20,7 +20,6 @@
import os
import unittest
-from time import sleep
from system_test import TestCase, Qdrouterd, DIR, main_module
from qpid_dispatch.management.client import Node
from proton import SSLDomain, Message
@@ -138,6 +137,23 @@ class QdSSLUseridTest(TestCase):
'displayNameFile': ssl_profile1_json,
'password': 'server-password'}),
+ # should translate a display name
+ ('sslProfile', {'name': 'server-ssl13',
+ 'certDb': cls.ssl_file('ca-certificate.pem'),
+ 'certFile': cls.ssl_file('server-certificate.pem'),
+ 'keyFile': cls.ssl_file('server-private-key.pem'),
+ 'uidFormat': '2',
+ 'displayNameFile': ssl_profile2_json,
+ 'password': 'server-password'}),
+
+ ('sslProfile', {'name': 'server-ssl14',
+ 'certDb': cls.ssl_file('ca-certificate.pem'),
+ 'certFile': cls.ssl_file('server-certificate.pem'),
+ 'keyFile': cls.ssl_file('server-private-key.pem'),
+ 'uidFormat': '1',
+ 'displayNameFile': ssl_profile1_json,
+ 'password': 'server-password'}),
+
('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl1', 'authenticatePeer': 'yes',
'requireSsl': 'yes', 'saslMechanisms': 'EXTERNAL'}),
@@ -176,6 +192,12 @@ class QdSSLUseridTest(TestCase):
('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl12', 'authenticatePeer': 'no',
'requireSsl': 'yes', 'saslMechanisms': 'ANONYMOUS'}),
+ ('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl13', 'authenticatePeer': 'yes',
+ 'requireSsl': 'yes', 'saslMechanisms': 'EXTERNAL'}),
+
+ ('listener', {'port': cls.tester.get_port(), 'sslProfile': 'server-ssl14', 'authenticatePeer': 'yes',
+ 'requireSsl': 'yes', 'saslMechanisms': 'EXTERNAL'}),
+
('listener', {'port': cls.tester.get_port(), 'authenticatePeer': 'no'})
])
@@ -277,8 +299,18 @@ class QdSSLUseridTest(TestCase):
user = node.query(type='org.apache.qpid.dispatch.connection', attribute_names=['user']).results[11][0]
self.assertEqual("anonymous", user)
+ addr = self.address(12).replace("amqp", "amqps")
+ node = Node.connect(addr, ssl_domain=domain)
+ user = node.query(type='org.apache.qpid.dispatch.connection', attribute_names=['user']).results[12][0]
+ self.assertEqual("user12", str(user))
+
+ addr = self.address(13).replace("amqp", "amqps")
+ node = Node.connect(addr, ssl_domain=domain)
+ user_id = node.query(type='org.apache.qpid.dispatch.connection', attribute_names=['user']).results[13][0]
+ self.assertEqual("user13", user_id)
+
M1 = self.messenger()
- M1.route("amqp:/*", self.address(12)+"/$1")
+ M1.route("amqp:/*", self.address(14)+"/$1")
subscription = M1.subscribe("amqp:/#")
@@ -301,7 +333,7 @@ class QdSSLUseridTest(TestCase):
rm = Message()
tm.address = addr
tm.reply_to = reply_to
- tm.body = {'profilename': 'server-ssl14', 'opcode': 'QUERY', 'userid': '94745961c5646ee0129536b3acef1eea0d8d2f26f8c3ed08ece4f8f3027bcd48'}
+ tm.body = {'profilename': 'server-ssl-unknown', 'opcode': 'QUERY', 'userid': '94745961c5646ee0129536b3acef1eea0d8d2f26f8c3ed08ece4f8f3027bcd48'}
M1.put(tm)
M1.send()
M1.recv(1)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org