Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/directory-kerby
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java
index 456d6ea..a0e27ca 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Container.java
@@ -22,6 +22,7 @@
import org.apache.kerby.asn1.Asn1Dumpable;
import org.apache.kerby.asn1.Asn1Dumper;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
@@ -33,12 +34,8 @@
private List<Asn1ParseResult> children = new ArrayList<>();
- public Asn1Container(Asn1Header header) {
- super(header);
- }
-
- public Asn1Container(Asn1ParseResult parseResult) {
- super(parseResult.header);
+ public Asn1Container(Asn1Header header, int bodyStart, ByteBuffer buffer) {
+ super(header, bodyStart, buffer);
}
public List<Asn1ParseResult> getChildren() {
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1DerivedItem.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1DerivedItem.java
new file mode 100644
index 0000000..41db80e
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1DerivedItem.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.asn1.parse;
+
+import org.apache.kerby.asn1.Tag;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Combine multiple parts in a container into a single item, for primitive types
+ * that use constructed encoding.
+ */
+public class Asn1DerivedItem extends Asn1Item {
+
+ private final Asn1Container container;
+ private final Tag newTag;
+ private int newBodyLength;
+ private ByteBuffer newBodyBuffer;
+
+ public Asn1DerivedItem(Tag newTag, Asn1Container container) {
+ super(container.getHeader(), container.getBodyStart(),
+ container.getBuffer());
+
+ this.newTag = newTag;
+ this.container = container;
+ this.newBodyLength = -1;
+ }
+
+ @Override
+ public Tag tag() {
+ return newTag;
+ }
+
+ private int computeBodyLength() {
+ int totalLen = 0;
+ for (Asn1ParseResult parseItem : container.getChildren()) {
+ totalLen += parseItem.getBodyLength();
+ }
+
+ return totalLen;
+ }
+
+ private ByteBuffer makeBodyBuffer() {
+ ByteBuffer tmpBuffer = ByteBuffer.allocate(getBodyLength());
+ for (Asn1ParseResult parseItem : container.getChildren()) {
+ tmpBuffer.put(parseItem.getBodyBuffer());
+ }
+ tmpBuffer.flip();
+
+ return tmpBuffer;
+ }
+
+ @Override
+ public ByteBuffer getBodyBuffer() {
+ if (newBodyBuffer == null) {
+ newBodyBuffer = makeBodyBuffer();
+ }
+ return newBodyBuffer;
+ }
+
+ @Override
+ public int getBodyLength() {
+ if (newBodyLength == -1) {
+ newBodyLength = computeBodyLength();
+ }
+
+ return newBodyLength;
+ }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.java
index bf3177b..8d90ac1 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Header.java
@@ -21,70 +21,23 @@
import org.apache.kerby.asn1.Tag;
-import java.nio.ByteBuffer;
-
public class Asn1Header {
private Tag tag;
private int length;
- private int bodyStart;
- private int bodyEnd;
- private ByteBuffer buffer;
- public Asn1Header(Tag tag, int length,
- int bodyStart, ByteBuffer buffer) {
+ public Asn1Header(Tag tag, int length) {
this.tag = tag;
this.length = length;
- this.bodyStart = bodyStart;
- this.buffer = buffer;
-
- this.bodyEnd = isDefinitiveLength() ? bodyStart + length : -1;
}
public Tag getTag() {
return tag;
}
- public int getActualBodyLength() {
- if (isDefinitiveLength()) {
- return getLength();
- } else if (getBodyEnd() != -1) {
- return getBodyEnd() - getBodyStart();
- }
- return -1;
- }
-
public int getLength() {
return length;
}
- public int getBodyStart() {
- return bodyStart;
- }
-
- public int getBodyEnd() {
- return bodyEnd;
- }
-
- public void setBodyEnd(int bodyEnd) {
- this.bodyEnd = bodyEnd;
- }
-
- public ByteBuffer getBuffer() {
- return buffer;
- }
-
- public ByteBuffer getBodyBuffer() {
- ByteBuffer result = buffer.duplicate();
- result.position(bodyStart);
-
- int end = getBodyEnd();
- if (end >= bodyStart) {
- result.limit(end);
- }
-
- return result;
- }
-
public boolean isEOC() {
return length == 0 && tag.isEOC();
}
@@ -92,8 +45,4 @@
public boolean isDefinitiveLength() {
return length != -1;
}
-
- public boolean checkBodyFinished(int pos) {
- return getBodyEnd() != -1 && pos >= getBodyEnd();
- }
}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java
index 2e2722d..7548629 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Item.java
@@ -19,10 +19,19 @@
*/
package org.apache.kerby.asn1.parse;
+import java.nio.ByteBuffer;
+
public class Asn1Item extends Asn1ParseResult {
- public Asn1Item(Asn1Header header) {
- super(header);
+ public Asn1Item(Asn1Header header, int bodyStart, ByteBuffer buffer) {
+ super(header, bodyStart, buffer);
+ }
+
+ public byte[] readBodyBytes() {
+ ByteBuffer bodyBuffer = getBodyBuffer();
+ byte[] result = new byte[bodyBuffer.remaining()];
+ bodyBuffer.get(result);
+ return result;
}
@Override
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java
index be549ff..6aebeae 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1ParseResult.java
@@ -25,22 +25,58 @@
import java.nio.ByteBuffer;
public abstract class Asn1ParseResult extends Asn1Object {
- protected Asn1Header header;
+ private Asn1Header header;
+ private int bodyStart;
+ private int bodyEnd;
+ private ByteBuffer buffer;
- public Asn1ParseResult(Asn1Header header) {
+ public Asn1ParseResult(Asn1Header header,
+ int bodyStart, ByteBuffer buffer) {
super(header.getTag());
this.header = header;
+ this.bodyStart = bodyStart;
+ this.buffer = buffer;
+
+ this.bodyEnd = isDefinitiveLength() ? bodyStart + header.getLength() : -1;
}
public Asn1Header getHeader() {
return header;
}
+ public int getBodyStart() {
+ return bodyStart;
+ }
+
+ public int getBodyEnd() {
+ return bodyEnd;
+ }
+
+ public void setBodyEnd(int bodyEnd) {
+ this.bodyEnd = bodyEnd;
+ }
+
+ public ByteBuffer getBuffer() {
+ return buffer;
+ }
+
+ public ByteBuffer getBodyBuffer() {
+ ByteBuffer result = buffer.duplicate();
+ result.position(bodyStart);
+
+ int end = getBodyEnd();
+ if (end >= bodyStart) {
+ result.limit(end);
+ }
+
+ return result;
+ }
+
public boolean isDefinitiveLength() {
return header.isDefinitiveLength();
}
- public int getAllLength() {
+ public int getEncodingLength() {
return getHeaderLength() + getBodyLength();
}
@@ -52,18 +88,21 @@
return headerLen;
}
- public int getBodyLength() {
- return header.getActualBodyLength();
- }
-
protected int getOffset() {
- return header.getBodyStart() - getHeaderLength();
+ return getBodyStart() - getHeaderLength();
}
- public byte[] readBodyBytes() {
- ByteBuffer bodyBuffer = header.getBodyBuffer();
- byte[] result = new byte[bodyBuffer.remaining()];
- bodyBuffer.get(result);
- return result;
+ public int getBodyLength() {
+ if (isDefinitiveLength()) {
+ return header.getLength();
+ } else if (getBodyEnd() != -1) {
+ return getBodyEnd() - getBodyStart();
+ }
+ return -1;
+ }
+
+
+ public boolean checkBodyFinished(int pos) {
+ return getBodyEnd() != -1 && pos >= getBodyEnd();
}
}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java
index c81c8c1..8e07131 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Parser.java
@@ -30,13 +30,8 @@
public class Asn1Parser {
public static void parse(Asn1Container container) throws IOException {
- parse(container.header, container);
- }
-
- public static void parse(Asn1Header header,
- Asn1Container parent) throws IOException {
- Asn1Reader reader = new Asn1Reader(header.getBuffer());
- int pos = header.getBodyStart();
+ Asn1Reader reader = new Asn1Reader(container.getBuffer());
+ int pos = container.getBodyStart();
while (true) {
reader.setPosition(pos);
Asn1ParseResult asn1Obj = parse(reader);
@@ -44,21 +39,19 @@
break;
}
- if (parent != null) {
- parent.addItem(asn1Obj);
- }
+ container.addItem(asn1Obj);
- pos += asn1Obj.getAllLength();
+ pos += asn1Obj.getEncodingLength();
if (asn1Obj.isEOC()) {
break;
}
- if (header.checkBodyFinished(pos)) {
+ if (container.checkBodyFinished(pos)) {
break;
}
}
- header.setBodyEnd(pos);
+ container.setBodyEnd(pos);
}
public static Asn1ParseResult parse(ByteBuffer content) throws IOException {
@@ -73,12 +66,14 @@
Asn1Header header = reader.readHeader();
Tag tmpTag = header.getTag();
+ int bodyStart = reader.getPosition();
Asn1ParseResult parseResult;
if (tmpTag.isPrimitive()) {
- parseResult = new Asn1Item(header);
+ parseResult = new Asn1Item(header, bodyStart, reader.getBuffer());
} else {
- Asn1Container container = new Asn1Container(header);
+ Asn1Container container = new Asn1Container(header,
+ bodyStart, reader.getBuffer());
parse(container);
parseResult = container;
}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java
index 555d7a8..89994f8 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/parse/Asn1Reader.java
@@ -38,9 +38,7 @@
public Asn1Header readHeader() throws IOException {
Tag tag = readTag();
int valueLength = readLength();
- int bodyStart = getPosition();
- Asn1Header header = new Asn1Header(tag, valueLength,
- bodyStart, getValueBuffer(valueLength));
+ Asn1Header header = new Asn1Header(tag, valueLength);
return header;
}
@@ -61,10 +59,6 @@
return position < buffer.limit();
}
- public ByteBuffer getValueBuffer(int valueLength) {
- return buffer;
- }
-
protected byte readByte() throws IOException {
return buffer.get(position++);
}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
index 07ec4c9..ea85d95 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
@@ -23,6 +23,7 @@
import org.apache.kerby.asn1.TaggingOption;
import org.apache.kerby.asn1.UniversalTag;
import org.apache.kerby.asn1.parse.Asn1Container;
+import org.apache.kerby.asn1.parse.Asn1DerivedItem;
import org.apache.kerby.asn1.parse.Asn1ParseResult;
import org.apache.kerby.asn1.parse.Asn1Parser;
import org.apache.kerby.asn1.util.Asn1Util;
@@ -179,8 +180,14 @@
public void decode(Asn1ParseResult parseResult) throws IOException {
if (!tag().equals(parseResult.tag())) {
- throw new IOException("Unexpected tag " + parseResult.tag()
- + ", expecting " + tag());
+ // Primitive but using constructed encoding
+ if (isPrimitive() && !parseResult.isPrimitive()) {
+ Asn1Container container = (Asn1Container) parseResult;
+ parseResult = new Asn1DerivedItem(tag(), container);
+ } else {
+ throw new IOException("Unexpected tag " + parseResult.tag()
+ + ", expecting " + tag());
+ }
}
decodeBody(parseResult);
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
index 78cb1ff..a1348f8 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
@@ -20,6 +20,7 @@
package org.apache.kerby.asn1.type;
import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1Item;
import org.apache.kerby.asn1.parse.Asn1ParseResult;
import java.io.IOException;
@@ -45,7 +46,8 @@
@Override
protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
- setValue(parseResult.readBodyBytes());
+ Asn1Item item = (Asn1Item) parseResult;
+ setValue(item.readBodyBytes());
}
@Override
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
index d75f0a3..45165a8 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
@@ -21,6 +21,7 @@
import org.apache.kerby.asn1.Tag;
import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1Item;
import org.apache.kerby.asn1.parse.Asn1ParseResult;
import org.apache.kerby.asn1.util.Asn1Util;
@@ -94,7 +95,8 @@
@Override
protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
- byte[] leftBytes = parseResult.readBodyBytes();
+ Asn1Item item = (Asn1Item) parseResult;
+ byte[] leftBytes = item.readBodyBytes();
if (leftBytes.length > 0) {
setBytes(leftBytes);
toValue();
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ConstructedOctetString.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ConstructedOctetString.java
index 3d66cb8..e7b40be 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ConstructedOctetString.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ConstructedOctetString.java
@@ -20,12 +20,13 @@
package org.apache.kerby.asn1;
import org.apache.kerby.asn1.type.Asn1OctetString;
+import org.junit.Test;
import java.io.IOException;
public class TestAsn1ConstructedOctetString {
- //@Test
+ @Test
public void testDecoding() throws IOException {
byte[] data = TestUtil.readBytesFromTxtFile("/constructed-octet-string.txt");
Asn1OctetString octetString = new Asn1OctetString();