summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--ext/openssl/ossl_asn1.c22
-rw-r--r--test/openssl/test_asn1.rb25
3 files changed, 44 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 7ee8dcaa7e..16e54a4b1b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon May 23 10:01:02 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
+
+ * ext/openssl/ossl_asn1.c: Do not parse zero-tagged values as EOC. Do
+ not let current length become negative for infinite length constructed
+ values. Support constructed values of length zero. Added tests.
+
Mon May 23 09:19:53 2011 Eric Hodel <drbrain@segment7.net>
* lib/net/smtp.rb: Document Net::SMTP::Response. Patch by J.R. Garcia.
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index cd65195796..354009ddce 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -838,9 +838,9 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, int hlen, int tag,
}
static VALUE
-int_ossl_asn1_decode0_cons(unsigned char **pp, long length, long *offset,
- int depth, int yield, int j, int tag, VALUE tc,
- long *num_read)
+int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
+ long *offset, int depth, int yield, int j,
+ int tag, VALUE tc, long *num_read)
{
VALUE value, asn1data, ary;
int infinite;
@@ -851,13 +851,18 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long length, long *offset,
while (length > 0 || infinite) {
long inner_read = 0;
- value = ossl_asn1_decode0(pp, length, &off, depth + 1, yield, &inner_read);
+ value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read);
*num_read += inner_read;
+ max_len -= inner_read;
rb_ary_push(ary, value);
- length -= inner_read;
+ if (length > 0)
+ length -= inner_read;
- if (infinite && NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC)
+ if (infinite &&
+ NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC &&
+ SYM2ID(ossl_asn1_get_tag_class(value)) == sUNIVERSAL) {
break;
+ }
}
if (tc == sUNIVERSAL && (tag == V_ASN1_SEQUENCE || V_ASN1_SET)) {
@@ -899,7 +904,7 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
{
unsigned char *start, *p;
const unsigned char *p0;
- long len, inner_read = 0, off = *offset;
+ long len = 0, inner_read = 0, off = *offset;
int hlen, tag, tc, j;
VALUE asn1data, tag_class;
@@ -934,10 +939,9 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
}
if(j & V_ASN1_CONSTRUCTED) {
- long max_len = len == 0 ? length : len;
*pp += hlen;
off += hlen;
- asn1data = int_ossl_asn1_decode0_cons(pp, max_len, &off, depth, yield, j, tag, tag_class, &inner_read);
+ asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read);
inner_read += hlen;
}
else {
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 0122e0fdcb..31fd2c3251 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -266,6 +266,31 @@ class OpenSSL::TestASN1 < Test::Unit::TestCase
end
end
+ def test_parse_empty_sequence
+ expected = %w{ A0 07 30 02 30 00 02 01 00 }
+ raw = [expected.join('')].pack('H*')
+ asn1 = OpenSSL::ASN1.decode(raw)
+ assert_equal(raw, asn1.to_der)
+ assert_equal(2, asn1.value.size)
+ seq = asn1.value[0]
+ assert_equal(1, seq.value.size)
+ inner_seq = seq.value[0]
+ assert_equal(0, inner_seq.value.size)
+ end
+
+ def test_parse_tagged_0_infinite
+ expected = %w{ 30 80 02 01 01 80 01 02 00 00 }
+ raw = [expected.join('')].pack('H*')
+ asn1 = OpenSSL::ASN1.decode(raw)
+ assert_equal(3, asn1.value.size)
+ int = asn1.value[0]
+ assert_universal(OpenSSL::ASN1::INTEGER, int)
+ tagged = asn1.value[1]
+ assert_equal(0, tagged.tag)
+ assert_universal(OpenSSL::ASN1::EOC, asn1.value[2])
+ assert_equal(raw, asn1.to_der)
+ end
+
def test_seq_infinite_length
begin
content = [ OpenSSL::ASN1::Null.new(nil),