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 2018/06/01 20:37:33 UTC
[1/4] qpid-dispatch git commit: DISPATCH-1011: Describe user name
substitution changes in doc
Repository: qpid-dispatch
Updated Branches:
refs/heads/master 561f210f4 -> c38f99e2a
DISPATCH-1011: Describe user name substitution changes in doc
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/2ccb9e7e
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/2ccb9e7e
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/2ccb9e7e
Branch: refs/heads/master
Commit: 2ccb9e7e0095e92ef09540577c4bf1a5fb7c4622
Parents: 3803dc8
Author: Chuck Rolke <cr...@redhat.com>
Authored: Thu May 31 14:02:18 2018 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Fri Jun 1 15:44:07 2018 -0400
----------------------------------------------------------------------
doc/book/policy.adoc | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/2ccb9e7e/doc/book/policy.adoc
----------------------------------------------------------------------
diff --git a/doc/book/policy.adoc b/doc/book/policy.adoc
index 888611c..a4eb99b 100644
--- a/doc/book/policy.adoc
+++ b/doc/book/policy.adoc
@@ -279,12 +279,19 @@ a * character, a # character, or a sequence of characters that do not
include /, *, or #. The * token matches any single token. The # token
matches zero or more tokens.
+The user name substitution token may be used in a sourcePattern or in a
+targetPattern subject to the following restrictions:
+
+* The user name substitution token must be the first or last token in the rule clause.
+* The user name substitution token must stand alone within its delimited field.
+ It may not be concatenated with literal text prefixes or suffixes.
+
For each rule definition multiple patterns may be specified in a comma
separated list.
[options="nowrap"]
----
- sourcePattern: tmp_${user}, temp/#, ${user}-home/*
+ sourcePattern: tmp.${user}, temp/#, ${user}.home/*
----
[NOTE]
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[4/4] qpid-dispatch git commit: DISPATCH-1011: Fix merge errors found
by tox; delete usused defs
Posted by ch...@apache.org.
DISPATCH-1011: Fix merge errors found by tox; delete usused defs
This closes #311
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/c38f99e2
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/c38f99e2
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/c38f99e2
Branch: refs/heads/master
Commit: c38f99e2aa9836b326cc8d1e66048281e0ef0829
Parents: 729ada0
Author: Chuck Rolke <cr...@redhat.com>
Authored: Fri Jun 1 16:35:20 2018 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Fri Jun 1 16:35:20 2018 -0400
----------------------------------------------------------------------
src/policy.c | 5 ++---
tests/system_tests_policy.py | 10 ++++++----
2 files changed, 8 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/c38f99e2/src/policy.c
----------------------------------------------------------------------
diff --git a/src/policy.c b/src/policy.c
index 43891da..33bd709 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -581,11 +581,10 @@ bool is_token_sep(char testc)
//
// Size of 'easy' temporary copy of allowed input string
#define QPALN_SIZE 1024
-// Wildcard character
+// Wildcard character at end of source/target name strings
#define QPALN_WILDCARD '*'
-#define QPALN_USERBUFSIZE 300
-#define MIN(a,b) (((a)<(b))?(a):(b))\
+#define MIN(a,b) (((a)<(b))?(a):(b))
/**
* Given a username and a list of allowed link names
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/c38f99e2/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index ab02e6e..07ed91e 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -812,9 +812,10 @@ class PolicyLinkNamePatternTest(TestCase):
exception = False
try:
qdm_out = self.run_qdmanage('create --type=vhost --name=DISPATCH-1993-3 --stdin', input=self.disallowed_source_pattern1())
- except Exception, e:
+ except Exception as e:
exception = True
- self.assertTrue("InternalServerErrorStatus: PolicyError: \"Policy 'DISPATCH-1993-3' is invalid:" in e.message)
+ self.assertTrue("InternalServerErrorStatus: PolicyError:" in e.message)
+ self.assertTrue("Policy 'DISPATCH-1993-3' is invalid:" in e.message)
self.assertTrue(exception)
# attempt another create that should be rejected - name subst must be prefix or suffix
@@ -822,9 +823,10 @@ class PolicyLinkNamePatternTest(TestCase):
exception = False
try:
qdm_out = self.run_qdmanage('create --type=vhost --name=DISPATCH-1993-3 --stdin', input=self.disallowed_source_pattern2())
- except Exception, e:
+ except Exception as e:
exception = True
- self.assertTrue("InternalServerErrorStatus: PolicyError: \"Policy 'DISPATCH-1993-3' is invalid:" in e.message)
+ self.assertTrue("InternalServerErrorStatus: PolicyError:" in e.message)
+ self.assertTrue("Policy 'DISPATCH-1993-3' is invalid:" in e.message)
self.assertTrue(exception)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[3/4] qpid-dispatch git commit: DISPATCH-1011: Parse tree exports
separators. Improve self tests.
Posted by ch...@apache.org.
DISPATCH-1011: Parse tree exports separators. Improve self tests.
Test sourcePattern suffixes found latent paste error in code.
More through test cases to hit more conditional code paths.
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/729ada00
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/729ada00
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/729ada00
Branch: refs/heads/master
Commit: 729ada00b00de840935ffd35efa55e61f11b4a39
Parents: 2ccb9e7
Author: Chuck Rolke <cr...@redhat.com>
Authored: Thu May 31 15:52:39 2018 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Fri Jun 1 15:47:01 2018 -0400
----------------------------------------------------------------------
.../policy/policy_local.py | 2 -
src/parse_tree.c | 5 ++
src/parse_tree.h | 3 +-
tests/policy_test.c | 33 +++++++--
tests/system_tests_policy.py | 74 ++++++++++++++++++++
5 files changed, 109 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/729ada00/python/qpid_dispatch_internal/policy/policy_local.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_local.py b/python/qpid_dispatch_internal/policy/policy_local.py
index eaf25cb..d3d35f4 100644
--- a/python/qpid_dispatch_internal/policy/policy_local.py
+++ b/python/qpid_dispatch_internal/policy/policy_local.py
@@ -355,8 +355,6 @@ class PolicyCompiler(object):
eVal.append(v)
eVal.append('')
policy_out[key] = ','.join(eVal)
- print "Val: ", val # hack alert
- print "eVal:", eVal # hack alert
if key == PolicyKeys.KW_SOURCES:
user_sources = True
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/729ada00/src/parse_tree.c
----------------------------------------------------------------------
diff --git a/src/parse_tree.c b/src/parse_tree.c
index c02b74a..189f316 100644
--- a/src/parse_tree.c
+++ b/src/parse_tree.c
@@ -91,6 +91,11 @@ static void token_iterator_next(token_iterator_t *t)
}
+const char address_token_sep[] = "./";
+const char *qd_parse_address_token_sep() {
+ return address_token_sep;
+}
+
static bool token_iterator_done(const token_iterator_t *t)
{
return t->token.begin == t->terminator;
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/729ada00/src/parse_tree.h
----------------------------------------------------------------------
diff --git a/src/parse_tree.h b/src/parse_tree.h
index 8a06fc9..26613a3 100644
--- a/src/parse_tree.h
+++ b/src/parse_tree.h
@@ -28,8 +28,6 @@
typedef struct qd_parse_node qd_parse_tree_t;
-//extern const char * const QD_PARSE_TREE_TOKEN_SEP;
-
// Pattern matching algorithms
// ADDRESS - configured address prefix/pattern matching
// token separators: '.' or '/'
@@ -54,6 +52,7 @@ typedef enum {
qd_parse_tree_t *qd_parse_tree_new(qd_parse_tree_type_t type);
void qd_parse_tree_free(qd_parse_tree_t *tree);
qd_parse_tree_type_t qd_parse_tree_type(const qd_parse_tree_t *tree);
+const char *qd_parse_address_token_sep();
// verify the pattern is in a legal format for the given tree's match algorithm
bool qd_parse_tree_validate_pattern(const qd_parse_tree_t *tree,
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/729ada00/tests/policy_test.c
----------------------------------------------------------------------
diff --git a/tests/policy_test.c b/tests/policy_test.c
index 377e474..3dbd478 100644
--- a/tests/policy_test.c
+++ b/tests/policy_test.c
@@ -98,19 +98,44 @@ static char *test_link_name_tree_lookup(void *context)
qd_parse_tree_add_pattern_str(node, "${user}.xyz", payload);
if (!_qd_policy_approve_link_name_tree("chuck", "p,,.xyz", "chuck.xyz", node))
- return "proposed link 'chuck.xyz' should tree-match allowed links with ${user} but does not";
+ return "proposed link 'chuck.xyz' should tree-match allow links with ${user} but does not";
if (_qd_policy_approve_link_name_tree("chuck", "p,,.xyz", "chuck.xyz.ynot", node))
- return "proposed link 'chuck.xyz.ynot' should not tree-match allowed links with ${user} but does";
+ return "proposed link 'chuck.xyz.ynot' should not tree-match allow links with ${user} but does";
qd_parse_tree_add_pattern_str(node, "${user}.#", payload);
if (!_qd_policy_approve_link_name_tree("motronic", "p,,.#", "motronic", node))
- return "proposed link 'motronic' should tree-match allowed links with ${user} but does not";
+ return "proposed link 'motronic' should tree-match allow links with ${user} but does not";
if (!_qd_policy_approve_link_name_tree("motronic", "p,,.#", "motronic.stubs.wobbler", node))
- return "proposed link 'motronic.stubs.wobbler' should tree-match allowed links with ${user} but does not";
+ return "proposed link 'motronic.stubs.wobbler' should tree-match allow links with ${user} but does not";
+ qd_parse_tree_t *node2 = qd_parse_tree_new(QD_PARSE_TREE_ADDRESS);
+ qd_parse_tree_add_pattern_str(node2, "abc.${user}", payload);
+
+ if (!_qd_policy_approve_link_name_tree("chuck", "s,abc.,", "abc.chuck", node2))
+ return "proposed link 'abc.chuck' should tree-match allow links with ${user} but does not";
+
+ if (_qd_policy_approve_link_name_tree("chuck", "s,abc.,", "abc.ynot.chuck", node2))
+ return "proposed link 'abc.ynot.chuck' should not tree-match allow links with ${user} but does";
+
+ if (_qd_policy_approve_link_name_tree("chuck", "s,abc.,", "abc.achuck", node2))
+ return "proposed link 'abc.achuck' should not tree-match allow links with ${user} but does";
+
+ if (_qd_policy_approve_link_name_tree("chuckginormous", "s,abc.,", "abc.chuck", node2))
+ return "proposed link 'abc.chuck' should not tree-match allow links with ${user} but does";
+
+ qd_parse_tree_t *node3 = qd_parse_tree_new(QD_PARSE_TREE_ADDRESS);
+ qd_parse_tree_add_pattern_str(node3, "${user}", payload);
+
+ if (!_qd_policy_approve_link_name_tree("chuck", "p,,", "chuck", node3))
+ return "proposed link 'chuck' should tree-match allow links with ${user} but does not";
+
+ qd_parse_tree_free(node);
+ qd_parse_tree_free(node2);
+ qd_parse_tree_free(node3);
+
return 0;
}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/729ada00/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index 5ab99d5..ab02e6e 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -724,6 +724,60 @@ class PolicyLinkNamePatternTest(TestCase):
}
"""
+ def disallowed_source_pattern1(self):
+ return """
+{
+ "id": "DISPATCH-1993-3",
+ "maxConnections": 3,
+ "maxConnectionsPerHost": 3,
+ "maxConnectionsPerUser": 3,
+ "allowUnknownUser": true,
+ "groups": {
+ "$default": {
+ "allowAnonymousSender": true,
+ "maxReceivers": 99,
+ "users": "*",
+ "maxSessionWindow": 1000000,
+ "maxFrameSize": 222222,
+ "sourcePattern": "public, private, $management, abc-${user}.xyz",
+ "maxMessageSize": 222222,
+ "allowDynamicSource": true,
+ "remoteHosts": "*",
+ "maxSessions": 2,
+ "targetPattern": "public, private, $management",
+ "maxSenders": 22
+ }
+ }
+}
+"""
+
+ def disallowed_source_pattern2(self):
+ return """
+{
+ "id": "DISPATCH-1993-3",
+ "maxConnections": 3,
+ "maxConnectionsPerHost": 3,
+ "maxConnectionsPerUser": 3,
+ "allowUnknownUser": true,
+ "groups": {
+ "$default": {
+ "allowAnonymousSender": true,
+ "maxReceivers": 99,
+ "users": "*",
+ "maxSessionWindow": 1000000,
+ "maxFrameSize": 222222,
+ "sourcePattern": "public, private, $management, abc/${user}.xyz",
+ "maxMessageSize": 222222,
+ "allowDynamicSource": true,
+ "remoteHosts": "*",
+ "maxSessions": 2,
+ "targetPattern": "public, private, $management",
+ "maxSenders": 22
+ }
+ }
+}
+"""
+
def test_link_name_parse_tree_patterns(self):
# update to replace source/target match patterns
qdm_out = "<not written>"
@@ -753,6 +807,26 @@ class PolicyLinkNamePatternTest(TestCase):
self.assertTrue("InternalServerErrorStatus: PolicyError: Policy 'DISPATCH-1993-3' is invalid:" in str(e))
self.assertTrue(exception)
+ # attempt another create that should be rejected - name subst must whole token
+ qdm_out = "<not written>"
+ exception = False
+ try:
+ qdm_out = self.run_qdmanage('create --type=vhost --name=DISPATCH-1993-3 --stdin', input=self.disallowed_source_pattern1())
+ except Exception, e:
+ exception = True
+ self.assertTrue("InternalServerErrorStatus: PolicyError: \"Policy 'DISPATCH-1993-3' is invalid:" in e.message)
+ self.assertTrue(exception)
+
+ # attempt another create that should be rejected - name subst must be prefix or suffix
+ qdm_out = "<not written>"
+ exception = False
+ try:
+ qdm_out = self.run_qdmanage('create --type=vhost --name=DISPATCH-1993-3 --stdin', input=self.disallowed_source_pattern2())
+ except Exception, e:
+ exception = True
+ self.assertTrue("InternalServerErrorStatus: PolicyError: \"Policy 'DISPATCH-1993-3' is invalid:" in e.message)
+ self.assertTrue(exception)
+
class PolicyHostamePatternTest(TestCase):
"""
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[2/4] qpid-dispatch git commit: DISPATCH-1011: Improve user name
substitution token logic and code
Posted by ch...@apache.org.
DISPATCH-1011: Improve user name substitution token logic and code
Remove code flagged by Coverity.
Add scheme that specifies precisely where user name substitution goes.
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/3803dc8c
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/3803dc8c
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/3803dc8c
Branch: refs/heads/master
Commit: 3803dc8cbd722847bbfd7238cd0dcd5d2728cb0b
Parents: 561f210
Author: Chuck Rolke <cr...@redhat.com>
Authored: Thu May 31 13:35:49 2018 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Fri Jun 1 15:44:07 2018 -0400
----------------------------------------------------------------------
.../policy/policy_local.py | 66 ++-
src/policy.c | 486 +++++++++++++++----
src/policy.h | 11 +
src/policy_internal.h | 3 +-
src/remote_sasl.c | 4 +-
tests/policy_test.c | 90 +++-
tests/router_policy_test.py | 8 +-
7 files changed, 543 insertions(+), 125 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3803dc8c/python/qpid_dispatch_internal/policy/policy_local.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_local.py b/python/qpid_dispatch_internal/policy/policy_local.py
index b55e86e..eaf25cb 100644
--- a/python/qpid_dispatch_internal/policy/policy_local.py
+++ b/python/qpid_dispatch_internal/policy/policy_local.py
@@ -98,6 +98,16 @@ class PolicyKeys(object):
# policy stats controlled by C code but referenced by settings
KW_CSTATS = "denialCounts"
+ # Username subsitituion token in link source and target names and patterns
+ KC_TOKEN_USER = "${user}"
+
+ # Link target/source name wildcard tuple keys
+ KC_TUPLE_ABSENT = 'a'
+ KC_TUPLE_PREFIX = 'p'
+ KC_TUPLE_SUFFIX = 's'
+ KC_TUPLE_EMBED = 'e'
+ KC_TUPLE_WILDCARD = '*'
+
#
#
class PolicyCompiler(object):
@@ -293,8 +303,60 @@ class PolicyCompiler(object):
(vhostname, usergroup, key, val, type(val)))
# deduplicate address lists
val = list(set(val))
- # output result is CSV string with no white space between values: 'abc,def,mytarget'
- policy_out[key] = ','.join(val)
+ # val is CSV string with no white space between values: 'abc,def,mytarget,tmp-${user}'
+ if key == PolicyKeys.KW_USERS:
+ # user name list items are literal strings and need no special handling
+ policy_out[key] = ','.join(val)
+ else:
+ # source and target names get special handling for the '${user}' substitution token
+ # The literal string is translated to a (key, prefix, suffix) set of three strings.
+ # C code does not have to search for the username token and knows with authority
+ # how to construct match strings.
+ # A wildcard is also signaled.
+ utoken = PolicyKeys.KC_TOKEN_USER
+ eVal = []
+ for v in val:
+ vcount = v.count(utoken)
+ if vcount > 1:
+ errors.append("Policy vhost '%s' user group '%s' policy key '%s' item '%s' contains multiple user subtitution tokens" %
+ (vhostname, usergroup, key, v))
+ return False
+ elif vcount == 1:
+ # a single token is present as a prefix, suffix, or embedded
+ # construct cChar, S1, S2 encodings to be added to eVal description
+ if v.startswith(utoken):
+ # prefix
+ eVal.append(PolicyKeys.KC_TUPLE_PREFIX)
+ eVal.append('')
+ eVal.append(v)
+ elif v.endswith(utoken):
+ # suffix
+ eVal.append(PolicyKeys.KC_TUPLE_SUFFIX)
+ eVal.append(v)
+ eVal.append('')
+ else:
+ # embedded
+ if key in [PolicyKeys.KW_SOURCE_PATTERN,
+ PolicyKeys.KW_TARGET_PATTERN]:
+ errors.append("Policy vhost '%s' user group '%s' policy key '%s' item '%s' may contain match pattern '%s' as a prefix or a suffix only." %
+ (vhostname, usergroup, key, v, utoken))
+ return False
+ eVal.append(PolicyKeys.KC_TUPLE_EMBED)
+ eVal.append(v[0:v.find(utoken)])
+ eVal.append(v[v.find(utoken) + len(utoken):])
+ else:
+ # ${user} token is absent
+ if v == PolicyKeys.KC_TUPLE_WILDCARD:
+ eVal.append(PolicyKeys.KC_TUPLE_WILDCARD)
+ eVal.append('')
+ eVal.append('')
+ else:
+ eVal.append(PolicyKeys.KC_TUPLE_ABSENT)
+ eVal.append(v)
+ eVal.append('')
+ policy_out[key] = ','.join(eVal)
+ print "Val: ", val # hack alert
+ print "eVal:", eVal # hack alert
if key == PolicyKeys.KW_SOURCES:
user_sources = True
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3803dc8c/src/policy.c
----------------------------------------------------------------------
diff --git a/src/policy.c b/src/policy.c
index 31d31da..43891da 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -55,6 +55,17 @@ static char* SESSION_DISALLOWED = "session disallowed by local policy
static char* LINK_DISALLOWED = "link disallowed by local policy";
//
+// username substitution key shared with configuration files and python code
+// substitution triplet keys shared with python code
+//
+static const char * const user_subst_key = "${user}";
+static const char * const user_subst_i_absent = "a";
+static const char * const user_subst_i_prefix = "p";
+static const char * const user_subst_i_embed = "e";
+static const char * const user_subst_i_suffix = "s";
+static const char * const user_subst_i_wildcard = "*";
+
+//
// Policy configuration/statistics management interface
//
struct qd_policy_t {
@@ -258,6 +269,8 @@ static const char* QPALN_COMMA_SEP =",";
// receiver links, return a parse_tree
//
// @param config_spec CSV string with link name match patterns
+// The patterns consist of ('key', 'prefix', 'suffix') triplets describing
+// the match pattern.
// @return pointer to parse tree
//
qd_parse_tree_t * qd_policy_parse_tree(const char *config_spec)
@@ -270,18 +283,53 @@ qd_parse_tree_t * qd_policy_parse_tree(const char *config_spec)
if (!tree)
return NULL;
- // Add CSV's values to the tree.
- // Note that tree's pattern is unused. This code uses a dummy '1'.
+ // make a writable, disposable copy of the csv string
char * dup = strdup(config_spec);
+ if (!dup)
+ return NULL;
char * dupend = dup + strlen(dup);
+
char * pch = dup;
while (pch < dupend) {
- size_t vsize = strcspn(pch, QPALN_COMMA_SEP);
- if (vsize > 0) {
- pch[vsize] = '\0';
- qd_parse_tree_add_pattern_str(tree, pch, (void *)1);
- }
- pch += vsize + 1;
+ // the tuple strings
+ char *pChar, *pS1, *pS2;
+ size_t sChar, sS1, sS2;
+
+ // extract control field
+ sChar = strcspn(pch, QPALN_COMMA_SEP);
+ if (sChar != 1) { assert(false); break;}
+ pChar = pch;
+ pChar[sChar] = '\0';
+ pch += sChar + 1;
+ if (pch >= dupend) { assert(false); break; }
+
+ // extract prefix field S1
+ sS1 = strcspn(pch, QPALN_COMMA_SEP);
+ pS1 = pch;
+ pS1[sS1] = '\0';
+ pch += sS1 + 1;
+ if (pch > dupend) { assert(false); break; }
+
+ // extract suffix field S2
+ sS2 = strcspn(pch, QPALN_COMMA_SEP);
+ pS2 = pch;
+ pch += sS2 + 1;
+ pS2[sS2] = '\0';
+
+ size_t sName = sS1 + strlen(user_subst_key) + sS2 + 1; // large enough to handle any case
+ char *pName = (char *)malloc(sName);
+
+ if (!strcmp(pChar, user_subst_i_absent))
+ snprintf(pName, sName, "%s", pS1);
+ else if (!strcmp(pChar, user_subst_i_prefix))
+ snprintf(pName, sName, "%s%s", user_subst_key, pS2);
+ else if (!strcmp(pChar, user_subst_i_embed))
+ snprintf(pName, sName, "%s%s%s", pS1, user_subst_key, pS2);
+ else
+ snprintf(pName, sName, "%s%s", pS1, user_subst_key);
+ qd_parse_tree_add_pattern_str(tree, pName, (void *)1);
+
+ free(pName);
}
free(dup);
return tree;
@@ -516,45 +564,16 @@ void _qd_policy_deny_amqp_receiver_link(pn_link_t *pn_link, qd_connection_t *qd_
}
-//
-//
-#define MIN(a,b) (((a)<(b))?(a):(b))
-
-// substitute "${user}" in place of uname in proposed
-char * _qd_policy_link_user_name_subst(const char *uname, const char *proposed, char *obuf, int osize)
+/**
+ * Given a char return true if it is a parse_tree token separater
+ */
+bool is_token_sep(char testc)
{
- if (strlen(uname) == 0)
- return NULL;
-
- const char duser[] = "${user}";
- char *retptr = obuf;
- const char *wiptr = proposed;
- const char *findptr = strstr(proposed, uname);
- if (findptr == NULL) {
- return NULL;
+ for (const char *ptr = qd_parse_address_token_sep(); *ptr != '\0'; ptr++) {
+ if (*ptr == testc)
+ return true;
}
-
- // Copy leading before match
- int segsize = findptr - wiptr;
- int copysize = MIN(osize, segsize);
- if (copysize)
- strncpy(obuf, wiptr, copysize);
- wiptr += copysize;
- osize -= copysize;
- obuf += copysize;
-
- // Copy the substitution string
- segsize = sizeof(duser) - 1;
- copysize = MIN(osize, segsize);
- if (copysize)
- strncpy(obuf, duser, copysize);
- wiptr += strlen(uname);
- osize -= copysize;
- obuf += copysize;
-
- // Copy trailing after match
- strncpy(obuf, wiptr, osize);
- return retptr;
+ return false;
}
@@ -562,17 +581,30 @@ char * _qd_policy_link_user_name_subst(const char *uname, const char *proposed,
//
// Size of 'easy' temporary copy of allowed input string
#define QPALN_SIZE 1024
-// Size of user-name-substituted proposed string.
-#define QPALN_USERBUFSIZE 300
// Wildcard character
#define QPALN_WILDCARD '*'
+#define QPALN_USERBUFSIZE 300
+#define MIN(a,b) (((a)<(b))?(a):(b))\
+
+/**
+ * Given a username and a list of allowed link names
+ * decide if the proposed link name is approved.
+ * @param[in] username the user name
+ * @param[in] allowed csv of (key, prefix, suffix) tuples
+ * @param[in] proposed the link source/target name to be approved
+ * @return true if the user is allowed to open this link source/target name
+ *
+ * Concrete example
+ * user: 'bob', allowed (from spec): 'A,B,tmp-${user},C', proposed: 'tmp-bob'
+ * note that allowed above is now a tuple and not simple string fron the spec.
+ */
bool _qd_policy_approve_link_name(const char *username, const char *allowed, const char *proposed)
{
// Verify string sizes are usable
size_t p_len = strlen(proposed);
if (p_len == 0) {
- // degenerate case of blank name being opened. will never match anything.
+ // degenerate case of blank proposed name being opened. will never match anything.
return false;
}
size_t a_len = strlen(allowed);
@@ -581,72 +613,252 @@ bool _qd_policy_approve_link_name(const char *username, const char *allowed, con
return false;
}
- // Create a temporary writable copy of incoming allowed list
- char t_allow[QPALN_SIZE + 1]; // temporary buffer for normal allow lists
- int buflen = sizeof(t_allow);
- char * pa = t_allow;
- if (a_len >= buflen) {
- buflen = a_len + 1;
- pa = (char *)malloc(buflen); // malloc a buffer for larger allow lists
- if (!pa)
- return false;
+ size_t username_len = strlen(username);
+
+ // make a writable, disposable copy of the csv string
+ char * dup = strdup(allowed);
+ if (!dup) {
+ return false;
+ }
+ char * dupend = dup + strlen(dup);
+ char * pch = dup;
+
+ // get a scratch buffer for writing temporary match strings
+ char * pName = (char *)malloc(QPALN_SIZE);
+ if (!pName) {
+ free(dup);
+ return false;
}
- strcpy(pa, allowed); /* We know we have allocated enoough space */
- pa[a_len] = 0;
- // Do reverse user substitution into proposed
- char substbuf[QPALN_USERBUFSIZE];
- char * prop2 = _qd_policy_link_user_name_subst(username, proposed, substbuf, QPALN_USERBUFSIZE);
- char *toknext = 0;
- char *tok = strtok_r(pa, QPALN_COMMA_SEP, &toknext);
- assert (tok);
+ size_t pName_sz = QPALN_SIZE;
+
bool result = false;
- while (tok != NULL) {
- if (*tok == QPALN_WILDCARD) {
- result = true;
- break;
- }
- int matchlen = p_len;
- int len = strlen(tok);
- if (tok[len-1] == QPALN_WILDCARD) {
- matchlen = len - 1;
- assert(len > 0);
+
+ while (pch < dupend) {
+ // the tuple strings
+ char *pChar, *pS1, *pS2;
+ size_t sChar, sS1, sS2;
+
+ // extract control field
+ sChar = strcspn(pch, QPALN_COMMA_SEP);
+ if (sChar != 1) { assert(false); break;}
+ pChar = pch;
+ pChar[sChar] = '\0';
+ pch += sChar + 1;
+ if (pch >= dupend) { assert(false); break; }
+
+ // extract prefix field S1
+ sS1 = strcspn(pch, QPALN_COMMA_SEP);
+ pS1 = pch;
+ pS1[sS1] = '\0';
+ pch += sS1 + 1;
+ if (pch > dupend) { assert(false); break; }
+
+ // extract suffix field S2
+ sS2 = strcspn(pch, QPALN_COMMA_SEP);
+ pS2 = pch;
+ pch += sS2 + 1;
+ pS2[sS2] = '\0';
+
+ // compute size of generated string and make sure
+ // temporary buffer is big enough to hold it.
+ size_t sName = sS1 + username_len + sS2 + 1;
+ if (sName > pName_sz) {
+ size_t newSize = sName + QPALN_SIZE;
+ char * newPtr = (char *)realloc(pName, newSize);
+ if (!newPtr) {
+ break;
+ }
+ pName = newPtr;
+ pName_sz = newSize;
}
- if (strncmp(tok, proposed, matchlen) == 0) {
+
+ // if wildcard then check no more
+ if (*pChar == *user_subst_i_wildcard) {
result = true;
break;
}
- if (prop2 && strncmp(tok, prop2, matchlen) == 0) {
- result = true;
+ // From the rule clause construct what the rule is allowing
+ // given the user name associated with this request.
+ int snpN;
+ if (*pChar == *user_subst_i_absent)
+ snpN = snprintf(pName, sName, "%s", pS1);
+ else if (*pChar == *user_subst_i_prefix)
+ snpN = snprintf(pName, sName, "%s%s", username, pS2);
+ else if (*pChar == *user_subst_i_embed)
+ snpN = snprintf(pName, sName, "%s%s%s", pS1, username, pS2);
+ else if (*pChar == *user_subst_i_suffix)
+ snpN = snprintf(pName, sName, "%s%s", pS1, username);
+ else {
+ assert(false);
break;
}
- tok = strtok_r(NULL, QPALN_COMMA_SEP, &toknext);
- }
- if (pa != t_allow) {
- free(pa);
+
+ size_t rule_len = MIN(snpN, sName);
+ if (pName[rule_len-1] != QPALN_WILDCARD) {
+ // Rule clauses that do not end with wildcard
+ // must match entire proposed name string.
+ // pName=tmp-bob-5, proposed can be only 'tmp-bob-5'
+ result = strcmp(proposed, pName) == 0;
+ } else {
+ // Rule clauses that end with wildcard
+ // must match only as many characters as the cluase without the '*'.
+ // pName=tmp*, will match proposed 'tmp', 'tmp-xxx', 'tmp-bob', ...
+ result = strncmp(proposed, pName, rule_len - 1) == 0;
+ }
+ if (result)
+ break;
}
+ free(pName);
+ free(dup);
+
return result;
}
-bool _qd_policy_approve_link_name_tree(const char *username, qd_parse_tree_t *tree, const char *proposed)
+bool _qd_policy_approve_link_name_tree(const char *username, const char *allowed, const char *proposed,
+ qd_parse_tree_t *tree)
{
// Verify string sizes are usable
- size_t p_len = strlen(proposed);
- if (p_len == 0) {
- // degenerate case of blank name being opened. will never match anything.
+ size_t proposed_len = strlen(proposed);
+ if (proposed_len == 0) {
+ // degenerate case of blank proposed name being opened. will never match anything.
+ return false;
+ }
+ size_t a_len = strlen(allowed);
+ if (a_len == 0) {
+ // no names in 'allowed'.
return false;
}
- void * unused_payload = 0;
- if (qd_parse_tree_retrieve_match_str(tree, proposed, &unused_payload))
- return true;
+ // Regardless of how many rule clauses are specified only three match
+ // patterns must be checked: no user subst, prefix subst, and suffix subst.
+ bool need_check_nosubst = true;
+ bool need_check_prefix = true;
+ bool need_check_suffix = true;
- // Do reverse user substitution into proposed
- char substbuf[QPALN_USERBUFSIZE];
- char * prop2 = _qd_policy_link_user_name_subst(username, proposed, substbuf, QPALN_USERBUFSIZE);
- if (prop2 && qd_parse_tree_retrieve_match_str(tree, prop2, &unused_payload))
- return true;
- return false;
+ size_t username_len = strlen(username);
+ size_t usersubst_len = strlen(user_subst_key);
+
+ // make a writable, disposable copy of the csv string
+ char * dup = strdup(allowed);
+ if (!dup) {
+ return false;
+ }
+ char * dupend = dup + strlen(dup);
+ char * pch = dup;
+
+ // get a scratch buffer for writing temporary match strings
+ char * pName = (char *)malloc(QPALN_SIZE);
+ if (!pName) {
+ free(dup);
+ return false;
+ }
+ size_t pName_sz = QPALN_SIZE;
+
+ bool result = false;
+
+ while (pch < dupend) {
+ // the tuple strings
+ char *pChar, *pS1, *pS2;
+ size_t sChar, sS1, sS2;
+
+ // extract control field
+ sChar = strcspn(pch, QPALN_COMMA_SEP);
+ if (sChar != 1) { assert(false); break;}
+ pChar = pch;
+ pChar[sChar] = '\0';
+ pch += sChar + 1;
+ if (pch >= dupend) { assert(false); break; }
+
+ // extract prefix field S1
+ sS1 = strcspn(pch, QPALN_COMMA_SEP);
+ pS1 = pch;
+ pS1[sS1] = '\0';
+ pch += sS1 + 1;
+ if (pch > dupend) { assert(false); break; }
+
+ // extract suffix field S2
+ sS2 = strcspn(pch, QPALN_COMMA_SEP);
+ pS2 = pch;
+ pch += sS2 + 1;
+ pS2[sS2] = '\0';
+
+ // compute size of generated string and make sure
+ // temporary buffer is big enough to hold it.
+ size_t sName = proposed_len + usersubst_len + 1;
+ if (sName > pName_sz) {
+ size_t newSize = sName + QPALN_SIZE;
+ char * newPtr = (char *)realloc(pName, newSize);
+ if (!newPtr) {
+ break;
+ }
+ pName = newPtr;
+ pName_sz = newSize;
+ }
+
+ // From the rule clause construct what the rule is allowing
+ // given the user name associated with this request.
+ if (*pChar == *user_subst_i_absent && need_check_nosubst) {
+ need_check_nosubst = false;
+ // Substitution spec is absent. The search string is the literal
+ // S1 in the rule.
+ snprintf(pName, sName, "%s", proposed);
+ }
+ else if (*pChar == *user_subst_i_prefix && need_check_prefix) {
+ need_check_prefix = false;
+ // Substitution spec is prefix.
+ if (strncmp(proposed, username, username_len) != 0)
+ continue; // Denied. Proposed does not have username prefix.
+ // Check that username is not part of a larger token.
+ if (username_len == proposed_len) {
+ // If username is the whole link name then allow if lookup is ok
+ } else {
+ // Proposed is longer than username. Make sure that proposed
+ // is delimited after user name.
+ if (!is_token_sep(proposed[username_len])) {
+ continue; // denied. proposed has username prefix it it not a delimited user name
+ }
+ }
+ snprintf(pName, sName, "%s%s", user_subst_key, proposed + username_len);
+ }
+ else if (*pChar == *user_subst_i_embed) {
+ assert(false); // not supported
+ }
+ else if (*pChar == *user_subst_i_suffix && need_check_suffix) {
+ need_check_suffix = false;
+ // Check that link name has username suffix
+ if (username_len > proposed_len) {
+ continue; // denied. proposed name is too short to hold username
+ } else {
+ //---
+ // if (username_len == proposed_len) { ... }
+ // unreachable code. substitution-only rule clause is handled by prefix
+ //---
+ if (!is_token_sep(proposed[proposed_len - username_len - 1])) {
+ continue; // denied. proposed suffix it it not a delimited user name
+ }
+ if (strncmp(&proposed[proposed_len - username_len], username, username_len) != 0) {
+ continue; // denied. username is not the suffix
+ }
+ }
+ pName[0] = '\0';
+ strncat(pName, proposed, proposed_len - username_len);
+ strcat(pName, user_subst_key);
+ }
+ else {
+ assert(false);
+ break;
+ }
+
+ void * unused_payload = 0;
+ result = qd_parse_tree_retrieve_match_str(tree, pName, &unused_payload);
+ if (result)
+ break;
+ }
+ free(pName);
+ free(dup);
+
+ return result;
}
@@ -828,13 +1040,13 @@ bool qd_policy_approve_link_name(const char *username,
{
if (isReceiver) {
if (settings->sourceParseTree) {
- return _qd_policy_approve_link_name_tree(username, settings->sourceParseTree, proposed);
+ return _qd_policy_approve_link_name_tree(username, settings->sourcePattern, proposed, settings->sourceParseTree);
} else if (settings->sources) {
return _qd_policy_approve_link_name(username, settings->sources, proposed);
}
} else {
if (settings->targetParseTree) {
- return _qd_policy_approve_link_name_tree(username, settings->targetParseTree, proposed);
+ return _qd_policy_approve_link_name_tree(username, settings->targetPattern, proposed, settings->targetParseTree);
} else if (settings->targets) {
return _qd_policy_approve_link_name(username, settings->targets, proposed);
}
@@ -889,3 +1101,83 @@ char * qd_policy_host_pattern_lookup(qd_policy_t *policy, char *hostPattern)
hostPattern, (payload ? (char *)payload : "null"));
return payload;
}
+
+
+// Convert naked CSV allow list into parsed settings 3-tuple
+// Note that this logic is also present in python compile_app_settings.
+char * qd_policy_compile_allowed_csv(char * csv)
+{
+ size_t csv_len = strlen(csv);
+ size_t usersubst_len = strlen(user_subst_key);
+
+ size_t n_commas = 0;
+ char * pch = strchr(csv, *QPALN_COMMA_SEP);
+ while (pch != NULL) {
+ n_commas++;
+ pch = strchr(pch + 1, *QPALN_COMMA_SEP);
+ }
+
+ size_t result_size = csv_len + 3 * (n_commas + 1) + 1; // each token gets ctrl char and 2 commas
+ char * result = (char *)malloc(result_size);
+ if (!result)
+ return NULL;
+ result[0] = '\0';
+
+ char * dup = strdup(csv);
+ if (!dup) {
+ free(result);
+ return NULL;
+ }
+ char * dupend = dup + csv_len;
+
+ size_t tok_size = 0;
+ char * sep = "";
+ for (pch = dup; pch < dupend; pch += tok_size + 1) {
+ // isolate token
+ char * pcomma = strchr(pch, *QPALN_COMMA_SEP);
+ if (!pcomma) pcomma = dupend;
+ *pcomma = '\0';
+ tok_size = pcomma - pch;
+
+ strcat(result, sep);
+ sep = ",";
+ char * psubst = strstr(pch, user_subst_key);
+ if (psubst) {
+ // substitute token is present
+ if (psubst == pch) {
+ // token is a prefix
+ strcat(result, user_subst_i_prefix);
+ strcat(result, ",,");
+ strcat(result, pch + usersubst_len);
+ } else if (psubst == pch + tok_size - usersubst_len) {
+ // token is a suffix
+ strcat(result, user_subst_i_suffix);
+ strcat(result, ",");
+ strncat(result, pch, tok_size - usersubst_len);
+ strcat(result, ",");
+ } else {
+ // token is embedded
+ strcat(result, user_subst_i_embed);
+ strcat(result, ",");
+ strncat(result, pch, psubst - pch);
+ strcat(result, ",");
+ strncat(result, psubst + usersubst_len, tok_size - (psubst - pch) - usersubst_len);
+ }
+ } else {
+ // substitute token is absent
+ if (strcmp(pch, user_subst_i_wildcard) == 0) {
+ // token is wildcard
+ strcat(result, user_subst_i_wildcard);
+ strcat(result, ",,");
+ } else {
+ // token is ordinary string
+ strcat(result, user_subst_i_absent);
+ strcat(result, ",");
+ strcat(result, pch);
+ strcat(result, ",");
+ }
+ }
+ }
+ free(dup);
+ return result;
+}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3803dc8c/src/policy.h
----------------------------------------------------------------------
diff --git a/src/policy.h b/src/policy.h
index 98500ec..c24ad6b 100644
--- a/src/policy.h
+++ b/src/policy.h
@@ -202,4 +202,15 @@ void qd_policy_host_pattern_remove(qd_policy_t *policy, char *hostPattern);
* @return the name of the ruleset whose hostname pattern matched this actual hostname
*/
char * qd_policy_host_pattern_lookup(qd_policy_t *policy, char *hostPattern);
+
+/**
+ * Compile raw CSV spec of allowed sources/targets and return
+ * the string of tuples used by policy runtime.
+ * The returned string is allocated here and freed by the caller.
+ * This function does no error checking or logging.
+ *
+ * @param[in] csv the CSV allowed list
+ * @return the ruleset string to be used in policy settings.
+ */
+char * qd_policy_compile_allowed_csv(char * csv);
#endif
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3803dc8c/src/policy_internal.h
----------------------------------------------------------------------
diff --git a/src/policy_internal.h b/src/policy_internal.h
index 100338f..c075a75 100644
--- a/src/policy_internal.h
+++ b/src/policy_internal.h
@@ -110,6 +110,7 @@ bool _qd_policy_approve_link_name(const char *username, const char *allowed, con
* @param[in] username authenticated user name
* @param[in] allowed policy settings source/target string in packed CSV form.
* @param[in] proposed the link target name to be approved
+ * @param[in] tree the parse tree for this source/target names
*/
-bool _qd_policy_approve_link_name_tree(const char *username, qd_parse_tree_t *tree, const char *proposed);
+bool _qd_policy_approve_link_name_tree(const char *username, const char *allowed, const char *proposed, qd_parse_tree_t *tree);
#endif
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3803dc8c/src/remote_sasl.c
----------------------------------------------------------------------
diff --git a/src/remote_sasl.c b/src/remote_sasl.c
index fd9da26..239891c 100644
--- a/src/remote_sasl.c
+++ b/src/remote_sasl.c
@@ -249,10 +249,10 @@ static void set_policy_settings(pn_connection_t* conn, permissions_t* permission
ZERO(qd_conn->policy_settings->denialCounts);
if (permissions->targets.start && permissions->targets.capacity) {
- qd_conn->policy_settings->targets = strdup(permissions->targets.start);
+ qd_conn->policy_settings->targets = qd_policy_compile_allowed_csv(permissions->targets.start);
}
if (permissions->sources.start && permissions->sources.capacity) {
- qd_conn->policy_settings->sources = strdup(permissions->sources.start);
+ qd_conn->policy_settings->sources = qd_policy_compile_allowed_csv(permissions->sources.start);
}
qd_conn->policy_settings->allowDynamicSource = true;
qd_conn->policy_settings->allowAnonymousSender = true;
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3803dc8c/tests/policy_test.c
----------------------------------------------------------------------
diff --git a/tests/policy_test.c b/tests/policy_test.c
index ca73f32..377e474 100644
--- a/tests/policy_test.c
+++ b/tests/policy_test.c
@@ -26,6 +26,11 @@
static char *test_link_name_lookup(void *context)
{
+ // DISPATCH-1011: approval specifications are now CSV concatenated 3-tuples:
+ // (user-subst-code, prefix, suffix)
+ // codes are 'a'bsent, 'p'refix, 's'uffix, 'e'mbedded, '*'wildcard
+ // OLD: 'joe', NEW: 'a,joe,'
+
// Degenerate blank names
if (_qd_policy_approve_link_name("a", "a", ""))
return "blank proposed name not rejected";
@@ -33,31 +38,34 @@ static char *test_link_name_lookup(void *context)
return "blank allowed list not rejected";
// Easy matches
- if (!_qd_policy_approve_link_name("", "joe", "joe"))
+ if (!_qd_policy_approve_link_name("", "a,joe,", "joe"))
return "proposed link 'joe' should match allowed links 'joe' but does not";
- if (_qd_policy_approve_link_name("", "joe", "joey"))
+ if (_qd_policy_approve_link_name("", "a,joe,", "joey"))
return "proposed link 'joey' should not match allowed links 'joe' but does";
// Wildcard matches
- if (!_qd_policy_approve_link_name("", "joe*", "joey"))
+ if (!_qd_policy_approve_link_name("", "a,joe*,", "joey"))
return "proposed link 'joey' should match allowed links 'joe*' but does not";
- if (!_qd_policy_approve_link_name("", "joe*", "joezzzZZZ"))
+ if (!_qd_policy_approve_link_name("", "a,joe*,", "joezzzZZZ"))
return "proposed link 'joezzzZZZ' should match allowed links 'joe*' but does not";
- if (!_qd_policy_approve_link_name("", "joe,*", "joey"))
+ if (!_qd_policy_approve_link_name("", "a,joe,,*,,", "joey"))
return "proposed link 'joey' should match allowed links 'joe,*' but does not";
// Deeper match
- if (!_qd_policy_approve_link_name("", "no1,no2,no3,yes,no4", "yes"))
+ if (!_qd_policy_approve_link_name("", "a,no1,,a,no2,,a,no3,,a,yes,,a,no4,", "yes"))
return "proposed link 'yes' should match allowed links 'no1,no2,no3,yes,no4' but does not";
// Deeeper match - triggers malloc/free internal handler
- char * bufp = (char *)malloc(512 * 5 + 6);
+#define BIG_N 512
+ char * bufp = (char *)malloc(BIG_N * 8 + 6);
+ if (!bufp)
+ return "failed to allocate buffer for large link name test";
char * wp = bufp;
int i;
- for (i=0; i<512; i++) {
- wp += sprintf(wp, "n%03d,", i);
+ for (i=0; i<BIG_N; i++) {
+ wp += sprintf(wp, "a,n%03d,,", i);
}
- sprintf(wp, "yes");
+ sprintf(wp, "a,yes,");
if (!_qd_policy_approve_link_name("", bufp, "yes")) {
free(bufp);
return "proposed link 'yes' should match allowed large list but does not";
@@ -65,15 +73,17 @@ static char *test_link_name_lookup(void *context)
free(bufp);
// Substitute a user name
- if (!_qd_policy_approve_link_name("chuck", "ab${user}xyz", "abchuckxyz"))
+ if (!_qd_policy_approve_link_name("chuck", "e,ab,xyz", "abchuckxyz"))
return "proposed link 'abchuckxyz' should match allowed links with ${user} but does not";
- if (!_qd_policy_approve_link_name("chuck", "${user}xyz", "chuckxyz"))
+ if (!_qd_policy_approve_link_name("chuck", "p,,xyz", "chuckxyz"))
return "proposed link 'chuckxyz' should match allowed links with ${user} but does not";
- if (!_qd_policy_approve_link_name("chuck", "ab${user}", "abchuck"))
+ if (!_qd_policy_approve_link_name("chuck", "s,ab,", "abchuck"))
return "proposed link 'abchuck' should match allowed links with ${user} but does not";
+// if (!_qd_policy_approve_link_name("em", "temp-${user}", "temp-em"))
+// return "proposed link 'temp-em' should match allowed links with ${user} but does not";
// Combine user name and wildcard
- if (!_qd_policy_approve_link_name("chuck", "ab${user}*", "abchuckzyxw"))
+ if (!_qd_policy_approve_link_name("chuck", "e,ab,*", "abchuckzyxw"))
return "proposed link 'abchuckzyxw' should match allowed links with ${user}* but does not";
return 0;
@@ -85,23 +95,64 @@ static char *test_link_name_tree_lookup(void *context)
qd_parse_tree_t *node = qd_parse_tree_new(QD_PARSE_TREE_ADDRESS);
void *payload = (void*)1;
- qd_parse_tree_add_pattern_str(node, "ab${user}xyz", payload);
+ qd_parse_tree_add_pattern_str(node, "${user}.xyz", payload);
+
+ if (!_qd_policy_approve_link_name_tree("chuck", "p,,.xyz", "chuck.xyz", node))
+ return "proposed link 'chuck.xyz' should tree-match allowed links with ${user} but does not";
- if (!_qd_policy_approve_link_name_tree("chuck", node, "abchuckxyz"))
- return "proposed link 'abchuckxyz' should tree-match allowed links with ${user} but does not";
+ if (_qd_policy_approve_link_name_tree("chuck", "p,,.xyz", "chuck.xyz.ynot", node))
+ return "proposed link 'chuck.xyz.ynot' should not tree-match allowed links with ${user} but does";
qd_parse_tree_add_pattern_str(node, "${user}.#", payload);
- if (!_qd_policy_approve_link_name_tree("motronic", node, "motronic"))
+ if (!_qd_policy_approve_link_name_tree("motronic", "p,,.#", "motronic", node))
return "proposed link 'motronic' should tree-match allowed links with ${user} but does not";
- if (!_qd_policy_approve_link_name_tree("motronic", node, "motronic.stubs.wobbler"))
+ if (!_qd_policy_approve_link_name_tree("motronic", "p,,.#", "motronic.stubs.wobbler", node))
return "proposed link 'motronic.stubs.wobbler' should tree-match allowed links with ${user} but does not";
return 0;
}
+static char *test_link_name_csv_parser(void *context)
+{
+ char * result;
+
+ result = qd_policy_compile_allowed_csv("ttt");
+ if (!!strcmp(result, "a,ttt,"))
+ return "simple csv with no subst failed";
+ free(result);
+
+ result = qd_policy_compile_allowed_csv("ttt,uuu,vvvv");
+ if (!!strcmp(result, "a,ttt,,a,uuu,,a,vvvv,"))
+ return "moderate csv with no subst failed";
+ free(result);
+
+ result = qd_policy_compile_allowed_csv("*");
+ if (!!strcmp(result, "*,,"))
+ return "wildcard csv failed";
+ free(result);
+
+ result = qd_policy_compile_allowed_csv("${user}-temp");
+ if (!!strcmp(result, "p,,-temp"))
+ return "csv with prefix subst failed";
+ free(result);
+
+ result = qd_policy_compile_allowed_csv("temp-${user}");
+ if (!!strcmp(result, "s,temp-,"))
+ return "csv with suffix subst failed";
+ free(result);
+
+ result = qd_policy_compile_allowed_csv("temp-${user}-home");
+ if (!!strcmp(result, "e,temp-,-home"))
+ return "csv with embedded subst failed";
+ free(result);
+
+ return 0;
+}
+
+
int policy_tests(void)
{
int result = 0;
@@ -109,6 +160,7 @@ int policy_tests(void)
TEST_CASE(test_link_name_lookup, 0);
TEST_CASE(test_link_name_tree_lookup, 0);
+ TEST_CASE(test_link_name_csv_parser, 0);
return result;
}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/3803dc8c/tests/router_policy_test.py
----------------------------------------------------------------------
diff --git a/tests/router_policy_test.py b/tests/router_policy_test.py
index a437668..a8331a0 100644
--- a/tests/router_policy_test.py
+++ b/tests/router_policy_test.py
@@ -165,8 +165,8 @@ class PolicyFile(TestCase):
self.assertTrue(upolicy['maxReceivers'] == 44)
self.assertTrue(upolicy['allowAnonymousSender'])
self.assertTrue(upolicy['allowDynamicSource'])
- self.assertTrue(upolicy['targets'] == 'private')
- self.assertTrue(upolicy['sources'] == 'private')
+ self.assertTrue(upolicy['targets'] == 'a,private,')
+ self.assertTrue(upolicy['sources'] == 'a,private,')
def test_policy1_test_zeke_bad_IP(self):
self.assertTrue(
@@ -225,8 +225,8 @@ class PolicyFileApplicationFallback(TestCase):
self.assertTrue(upolicy['maxReceivers'] == 44)
self.assertTrue(upolicy['allowAnonymousSender'])
self.assertTrue(upolicy['allowDynamicSource'])
- self.assertTrue(upolicy['targets'] == 'private')
- self.assertTrue(upolicy['sources'] == 'private')
+ self.assertTrue(upolicy['targets'] == 'a,private,')
+ self.assertTrue(upolicy['sources'] == 'a,private,')
# Disable fallback and show failure again
self.policy.set_default_vhost('')
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org