summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasey Marshall <csm@gnu.org>2006-06-06 01:01:19 +0000
committerCasey Marshall <csm@gnu.org>2006-06-06 01:01:19 +0000
commit61dcae3967de896a92e7e61754738b1c80ed5482 (patch)
tree7463efff3f3fe4d2265219abc6275c3ebbd68f86
parent6ed1dcd5f536296e20cf30c98e96067f6bf0148b (diff)
downloadclasspath-61dcae3967de896a92e7e61754738b1c80ed5482.tar.gz
2006-06-05 Casey Marshall <csm@gnu.org>
* gnu/javax/net/ssl/provider/Extension.java: add Javadoc. (length): return the length of the extension value. (setLength, setType, setValue, setValue): new methods. * gnu/javax/net/ssl/provider/ExtensionList.java: new file. * jessie-tests/run-tests.sh: add testExtensionList. * jessie-tests/testExtensionList.java: new file.
-rw-r--r--ChangeLog-ssl-nio12
-rw-r--r--gnu/javax/net/ssl/provider/Extension.java37
-rw-r--r--gnu/javax/net/ssl/provider/ExtensionList.java270
-rw-r--r--jessie-tests/run-tests.sh2
4 files changed, 317 insertions, 4 deletions
diff --git a/ChangeLog-ssl-nio b/ChangeLog-ssl-nio
index b1fa00f70..ffca8bdac 100644
--- a/ChangeLog-ssl-nio
+++ b/ChangeLog-ssl-nio
@@ -1,4 +1,13 @@
-2006-06-05 Casey Marshall <csm@gnu.org>
+2006-06-05 Casey Marshall <csm@gnu.org>
+
+ * gnu/javax/net/ssl/provider/Extension.java: add Javadoc.
+ (length): return the length of the extension value.
+ (setLength, setType, setValue, setValue): new methods.
+ * gnu/javax/net/ssl/provider/ExtensionList.java: new file.
+ * jessie-tests/run-tests.sh: add testExtensionList.
+ * jessie-tests/testExtensionList.java: new file.
+
+2006-06-05 Casey Marshall <csm@gnu.org>
* gnu/javax/net/ssl/provider/CipherSuiteList.java: implement
Iterable<CipherSuite>.
@@ -20,4 +29,3 @@
* gnu/javax/net/ssl/provider/ServerHelloDone.java: made public.
* jessie-tests/run-tests.sh: add `testServerHelloDone.'
* jessie-tests/testServerHelloDone.java: new test.
-
diff --git a/gnu/javax/net/ssl/provider/Extension.java b/gnu/javax/net/ssl/provider/Extension.java
index fda5e11bd..9e2b69e3b 100644
--- a/gnu/javax/net/ssl/provider/Extension.java
+++ b/gnu/javax/net/ssl/provider/Extension.java
@@ -43,6 +43,17 @@ import java.io.StringWriter;
import java.nio.ByteBuffer;
+/**
+ * An SSL hello extension.
+ *
+ * <pre>
+ * struct {
+ * ExtensionType extension_type;
+ * opaque extension_data<0..2^16-1>;
+ * } Extension;</pre>
+ *
+ * @author csm@gnu.org
+ */
public final class Extension implements Constructed
{
@@ -64,7 +75,7 @@ public final class Extension implements Constructed
public int length ()
{
- return (buffer.getShort (2) & 0xFFFF) + 4;
+ return (buffer.getShort (2) & 0xFFFF);
}
public Type type()
@@ -79,7 +90,31 @@ public final class Extension implements Constructed
((ByteBuffer) buffer.duplicate ().position (4)).get (value);
return value;
}
+
+ public void setLength (final int newLength)
+ {
+ if (newLength < 0 || newLength > 65535)
+ throw new IllegalArgumentException ("length is out of bounds");
+ buffer.putShort (2, (short) newLength);
+ }
+
+ public void setType (final Type type)
+ {
+ buffer.putShort(0, (short) type.getValue());
+ }
+ public void setValue (byte[] value)
+ {
+ setValue (value, 0, value.length);
+ }
+
+ public void setValue (final byte[] value, final int offset, final int length)
+ {
+ if (length != length ())
+ throw new IllegalArgumentException ("length is different than claimed length");
+ ((ByteBuffer) buffer.duplicate().position(4)).put(value, offset, length);
+ }
+
public String toString()
{
return toString(null);
diff --git a/gnu/javax/net/ssl/provider/ExtensionList.java b/gnu/javax/net/ssl/provider/ExtensionList.java
new file mode 100644
index 000000000..ddb104491
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ExtensionList.java
@@ -0,0 +1,270 @@
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A list of extensions, that may appear in either the {@link ClientHello} or
+ * {@link ServerHello}. The form of the extensions list is:
+ *
+ * <tt> Extension extensions_list&lt;1..2^16-1&gt;</tt>
+ *
+ * @author csm
+ */
+public class ExtensionList implements Iterable<Extension>
+{
+ private final ByteBuffer buffer;
+ private int modCount;
+
+ public ExtensionList (ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ modCount = 0;
+ }
+
+ public Extension get (final int index)
+ {
+ int length = length ();
+ int i;
+ int n = 0;
+ for (i = 2; i < length && n < index; )
+ {
+ int l = buffer.getShort (i+2) & 0xFFFF;
+ i += l + 4;
+ n++;
+ }
+ if (n < index)
+ throw new IndexOutOfBoundsException ("no elemenet at " + index);
+ int el = buffer.getShort (i+2) & 0xFFFF;
+ return new Extension (((ByteBuffer) buffer.duplicate().position(i).limit(i+el+4)).slice());
+ }
+
+ /**
+ * Returns the number of extensions this list contains.
+ *
+ * @return The number of extensions.
+ */
+ public int size ()
+ {
+ int length = length ();
+ if (length == 0)
+ return 0;
+ int n = 0;
+ for (int i = 2; i < length; )
+ {
+ int len = buffer.getShort (i+2) & 0xFFFF;
+ i += len + 4;
+ n++;
+ }
+ return n;
+ }
+
+ /**
+ * Returns the length of this extension list, in bytes.
+ *
+ * @return The length of this extension list, in bytes.
+ */
+ public int length ()
+ {
+ return buffer.getShort (0) & 0xFFFF;
+ }
+
+ /**
+ * Sets the extension at index <i>i</i> to <i>e</i>. Note that setting an
+ * element at an index <b>may</b> invalidate any other elements that come
+ * after element at index <i>i</i>. In other words, no attempt is made to
+ * move existing elements in this list, and since extensions are variable
+ * length, you can <em>not</em> guarantee that extensions later in the list
+ * will still be valid.
+ *
+ * <p>Thus, elements of this list <b>must</b> be set in order of increasing
+ * index.
+ *
+ * @param index The index to set the extension at.
+ * @param e The extension.
+ * @throws java.nio.BufferOverflowException If setting the extension overflows
+ * the buffer.
+ * @throws IllegalArgumentException If it isn't possible to find the given index
+ * in the current list (say, if no element index - 1 is set), or if setting
+ * the extension will overflow the current list length (given by {@link
+ * #length()}).
+ */
+ public void set (final int index, Extension e)
+ {
+ int length = length();
+ int n = 0;
+ int i;
+ for (i = 2; i < length && n < index; )
+ {
+ int len = buffer.getShort(i+2) & 0xFFFF;
+ i += len + 4;
+ n++;
+ }
+ if (n < index)
+ throw new IllegalArgumentException("nothing set at index " + (index-1)
+ + " or insufficient space");
+ if (i + e.length() + 2 > length)
+ throw new IllegalArgumentException("adding this element will exceed the "
+ + "list length");
+ buffer.putShort(i, (short) e.type().getValue());
+ buffer.putShort(i+2, (short) e.length());
+ ((ByteBuffer) buffer.duplicate().position(i+4)).put (e.value());
+ modCount++;
+ }
+
+ /**
+ * Reserve space for an extension at index <i>i</i> in the list. In other
+ * words, this does the job of {@link #set(int, Extension)}, but does not
+ * copy the extension value to the underlying buffer.
+ *
+ * @param index The index of the extension to reserve space for.
+ * @param t The type of the extension.
+ * @param eLength The number of bytes to reserve for this extension. The total
+ * number of bytes used by this method is this length, plus four.
+ */
+ public void set (final int index, Extension.Type t, final int eLength)
+ {
+ int length = length ();
+ int n = 0;
+ int i;
+ for (i = 2; i < length && n < index; )
+ {
+ int len = buffer.getShort (i+2) & 0xFFFF;
+ i += len + 4;
+ n++;
+ }
+ if (n < index)
+ throw new IllegalArgumentException ("nothing set at index " + (index-1)
+ + " or insufficient space");
+ if (i + eLength + 2 > length)
+ throw new IllegalArgumentException ("adding this element will exceed the "
+ + "list length");
+ buffer.putShort(i, (short) t.getValue());
+ buffer.putShort(i+2, (short) eLength);
+ modCount++;
+ }
+
+ /**
+ * Set the total length of this list, in bytes.
+ *
+ * @param newLength The new list length.
+ */
+ public void setLength (final int newLength)
+ {
+ if (newLength < 0 || newLength > 65535)
+ throw new IllegalArgumentException ("invalid length");
+ buffer.putShort (0, (short) newLength);
+ modCount++;
+ }
+
+ public Iterator<Extension> iterator()
+ {
+ return new ExtensionsIterator ();
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
+ out.println ("ExtensionList {");
+ if (prefix != null) out.print (prefix);
+ out.print (" length = ");
+ out.print (length ());
+ out.println (";");
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix = prefix + subprefix;
+ for (Extension e : this)
+ out.println (e.toString(subprefix));
+ if (prefix != null) out.print (prefix);
+ out.println ("};");
+ return str.toString();
+ }
+
+ /**
+ * List iterator interface to an extensions list.
+ *
+ * @author csm@gnu.org
+ */
+ public final class ExtensionsIterator implements ListIterator<Extension>
+ {
+ private final int modCount;
+ private int index;
+ private final int size;
+
+ public ExtensionsIterator ()
+ {
+ this.modCount = ExtensionList.this.modCount;
+ index = 0;
+ size = size ();
+ }
+
+ public boolean hasNext()
+ {
+ return index < size;
+ }
+
+ public boolean hasPrevious()
+ {
+ return index > 0;
+ }
+
+ public Extension next() throws NoSuchElementException
+ {
+ if (modCount != ExtensionList.this.modCount)
+ throw new ConcurrentModificationException ();
+ if (!hasNext ())
+ throw new NoSuchElementException ();
+ return get (index++);
+ }
+
+ public Extension previous() throws NoSuchElementException
+ {
+ if (modCount != ExtensionList.this.modCount)
+ throw new ConcurrentModificationException ();
+ if (!hasPrevious ())
+ throw new NoSuchElementException ();
+ return get (--index);
+ }
+
+ public int nextIndex()
+ {
+ if (hasNext ())
+ return index + 1;
+ return index;
+ }
+
+ public int previousIndex()
+ {
+ if (hasPrevious ())
+ return index - 1;
+ return -1;
+ }
+
+ public void add(Extension e)
+ {
+ throw new UnsupportedOperationException ("cannot add items to this iterator");
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException ("cannot remove items from this iterator");
+ }
+
+ public void set(Extension e)
+ {
+ ExtensionList.this.set (index, e);
+ }
+ }
+}
diff --git a/jessie-tests/run-tests.sh b/jessie-tests/run-tests.sh
index c61e06fa9..d4a3dd499 100644
--- a/jessie-tests/run-tests.sh
+++ b/jessie-tests/run-tests.sh
@@ -7,7 +7,7 @@ test -z "$CLASSPATH" && export CLASSPATH=.
tests="testAlert testCertificate testCertificateRequest \
testCipherSuiteList testClientHello testCompressionMethodList \
- testHelloRequest testRecord testServerDHParams \
+ testExtensionList testHelloRequest testRecord testServerDHParams \
testServerHello testServerHelloDone testServerKeyExchange \
testServerRSAParams testSignature"