Repository: accumulo
Updated Branches:
  refs/heads/1.7 01cdd0205 -> ff0833643


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/1.7
Commit: e581d5b6919ae3b6ac5691bc059e763b262844c6
Parents: e1e4100
Author: Keith Turner <ktur...@apache.org>
Authored: Thu Dec 31 10:23:45 2015 -0500
Committer: Keith Turner <ktur...@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("五", 
"六", "八", "九", "五十"));
 

Reply via email to