Repository: accumulo
Updated Branches:
refs/heads/master 125557476 -> dee8d7aba
ACCUMULO-3734 unescape auths when using AuthsContainer
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/e581d5b6
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/e581d5b6
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/e581d5b6
Branch: refs/heads/master
Commit: e581d5b6919ae3b6ac5691bc059e763b262844c6
Parents: e1e4100
Author: Keith Turner <kturner@apache.org>
Authored: Thu Dec 31 10:23:45 2015 -0500
Committer: Keith Turner <kturner@apache.org>
Committed: Mon Jan 4 13:42:03 2016 -0500
----------------------------------------------------------------------
.../core/security/VisibilityEvaluator.java | 62 +++++++++++++++++++-
.../core/security/VisibilityEvaluatorTest.java | 42 ++++++++++++-
2 files changed, 101 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/accumulo/blob/e581d5b6/core/src/main/java/org/apache/accumulo/core/security/VisibilityEvaluator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/security/VisibilityEvaluator.java
b/core/src/main/java/org/apache/accumulo/core/security/VisibilityEvaluator.java
index 8535731..2338ed9 100644
--- a/core/src/main/java/org/apache/accumulo/core/security/VisibilityEvaluator.java
+++ b/core/src/main/java/org/apache/accumulo/core/security/VisibilityEvaluator.java
@@ -19,6 +19,8 @@ package org.apache.accumulo.core.security;
import java.util.ArrayList;
import org.apache.accumulo.core.constraints.Constraint.Environment;
+import org.apache.accumulo.core.data.ArrayByteSequence;
+import org.apache.accumulo.core.data.ByteSequence;
import org.apache.accumulo.core.security.ColumnVisibility.Node;
/**
@@ -28,6 +30,62 @@ public class VisibilityEvaluator {
private AuthorizationContainer auths;
/**
+ * Authorizations in column visibility expression are in escaped form. Column visibility
parsing does not unescape. This class wraps an AuthorizationContainer
+ * and unescapes auths before checking the wrapped container.
+ */
+ private static class UnescapingAuthorizationContainer implements AuthorizationContainer
{
+
+ private AuthorizationContainer wrapped;
+
+ UnescapingAuthorizationContainer(AuthorizationContainer wrapee) {
+ this.wrapped = wrapee;
+ }
+
+ @Override
+ public boolean contains(ByteSequence auth) {
+ return wrapped.contains(unescape(auth));
+ }
+ }
+
+ static ByteSequence unescape(ByteSequence auth) {
+ int escapeCharCount = 0;
+ for (int i = 0; i < auth.length(); i++) {
+ byte b = auth.byteAt(i);
+ if (b == '"' || b == '\\') {
+ escapeCharCount++;
+ }
+ }
+
+ if (escapeCharCount > 0) {
+ if (escapeCharCount % 2 == 1) {
+ throw new IllegalArgumentException("Illegal escape sequence in auth : " + auth);
+ }
+
+ byte[] unescapedCopy = new byte[auth.length() - escapeCharCount / 2];
+ int pos = 0;
+ for (int i = 0; i < auth.length(); i++) {
+ byte b = auth.byteAt(i);
+ if (b == '\\') {
+ i++;
+ b = auth.byteAt(i);
+ if (b != '"' && b != '\\') {
+ throw new IllegalArgumentException("Illegal escape sequence in auth : " + auth);
+ }
+ } else if (b == '"') {
+ // should only see quote after a slash
+ throw new IllegalArgumentException("Illegal escape sequence in auth : " + auth);
+ }
+
+ unescapedCopy[pos++] = b;
+ }
+
+ return new ArrayByteSequence(unescapedCopy);
+ } else {
+ return auth;
+ }
+ }
+
+ /**
* Creates a new {@link Authorizations} object with escaped forms of the authorizations
in the given object.
*
* @param auths
@@ -86,7 +144,7 @@ public class VisibilityEvaluator {
* environment containing authorizations
*/
VisibilityEvaluator(Environment env) {
- this.auths = env.getAuthorizationsContainer();
+ this.auths = new UnescapingAuthorizationContainer(env.getAuthorizationsContainer());
}
/**
@@ -97,7 +155,7 @@ public class VisibilityEvaluator {
* authorizations object
*/
public VisibilityEvaluator(Authorizations authorizations) {
- this.auths = escape((Authorizations) authorizations);
+ this.auths = escape(authorizations);
}
/**
http://git-wip-us.apache.org/repos/asf/accumulo/blob/e581d5b6/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java
b/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java
index 2996970..ed90c81 100644
--- a/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java
@@ -22,8 +22,12 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import org.apache.accumulo.core.constraints.Constraint;
+import org.apache.accumulo.core.constraints.Constraint.Environment;
+import org.apache.accumulo.core.data.ArrayByteSequence;
import org.apache.accumulo.core.util.BadArgumentException;
import org.apache.accumulo.core.util.ByteArraySet;
+import org.easymock.EasyMock;
import org.junit.Test;
public class VisibilityEvaluatorTest {
@@ -88,8 +92,19 @@ public class VisibilityEvaluatorTest {
@Test
public void testQuotedExpressions() throws VisibilityParseException {
- VisibilityEvaluator ct = new VisibilityEvaluator(new Authorizations("A#C", "A\"C", "A\\C",
"AC"));
+ Authorizations auths = new Authorizations("A#C", "A\"C", "A\\C", "AC");
+ VisibilityEvaluator ct = new VisibilityEvaluator(auths);
+ runQuoteTest(ct);
+
+ Environment env = EasyMock.createNiceMock(Constraint.Environment.class);
+ EasyMock.expect(env.getAuthorizationsContainer()).andReturn(auths);
+ EasyMock.replay(env);
+ ct = new VisibilityEvaluator(env);
+ runQuoteTest(ct);
+ }
+
+ private void runQuoteTest(VisibilityEvaluator ct) throws VisibilityParseException {
assertTrue(ct.evaluate(new ColumnVisibility(quote("A#C") + "|" + quote("A?C"))));
assertTrue(ct.evaluate(new ColumnVisibility(new ColumnVisibility(quote("A#C") + "|" +
quote("A?C")).flatten())));
assertTrue(ct.evaluate(new ColumnVisibility(quote("A\"C") + "&" + quote("A\\C"))));
@@ -113,6 +128,31 @@ public class VisibilityEvaluatorTest {
}
@Test
+ public void testUnescape() {
+ assertEquals("a\"b", VisibilityEvaluator.unescape(new ArrayByteSequence("a\\\"b")).toString());
+ assertEquals("a\\b", VisibilityEvaluator.unescape(new ArrayByteSequence("a\\\\b")).toString());
+ assertEquals("a\\\"b", VisibilityEvaluator.unescape(new ArrayByteSequence("a\\\\\\\"b")).toString());
+ assertEquals("\\\"", VisibilityEvaluator.unescape(new ArrayByteSequence("\\\\\\\"")).toString());
+ assertEquals("a\\b\\c\\d", VisibilityEvaluator.unescape(new ArrayByteSequence("a\\\\b\\\\c\\\\d")).toString());
+
+ try {
+ VisibilityEvaluator.unescape(new ArrayByteSequence("a\\b"));
+ fail("Expected failure to unescape invalid escape sequence");
+ } catch (IllegalArgumentException e) {}
+
+ try {
+ VisibilityEvaluator.unescape(new ArrayByteSequence("a\\b\\c"));
+ fail("Expected failure to unescape invalid escape sequence");
+ } catch (IllegalArgumentException e) {}
+
+ try {
+ VisibilityEvaluator.unescape(new ArrayByteSequence("a\"b\\"));
+ fail("Expected failure to unescape invalid escape sequence");
+ } catch (IllegalArgumentException e) {}
+
+ }
+
+ @Test
public void testNonAscii() throws VisibilityParseException {
VisibilityEvaluator ct = new VisibilityEvaluator(new Authorizations("五", "六", "八",
"九", "五十"));
|