From 182a69c5be7706fbb542694c7be51d499b61c98d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 23 Sep 2010 18:10:28 +0200 Subject: lib/util/asn1: add asn1_peek_tag_needed_size() and asn1_peek_full_tag() We need a way to ask for the length of a tag without having the full buffer yet. metze --- lib/util/asn1.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/util/asn1.h | 2 ++ 2 files changed, 85 insertions(+) (limited to 'lib/util') diff --git a/lib/util/asn1.c b/lib/util/asn1.c index 8f30cfe2c6..c4923343e2 100644 --- a/lib/util/asn1.c +++ b/lib/util/asn1.c @@ -489,6 +489,65 @@ bool asn1_peek_tag(struct asn1_data *data, uint8_t tag) return (b == tag); } +/* + * just get the needed size the tag would consume + */ +bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, size_t *size) +{ + off_t start_ofs = data->ofs; + uint8_t b; + size_t taglen = 0; + + if (data->has_error) { + return false; + } + + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + + if (b != tag) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + + if (b & 0x80) { + int n = b & 0x7f; + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + taglen = b; + while (n > 1) { + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + taglen = (taglen << 8) | b; + n--; + } + } else { + taglen = b; + } + + *size = (data->ofs - start_ofs) + taglen; + + data->ofs = start_ofs; + data->has_error = false; + return true; +} + /* start reading a nested asn1 structure */ bool asn1_start_tag(struct asn1_data *data, uint8_t tag) { @@ -943,6 +1002,30 @@ NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size) if (size > blob.length) { return STATUS_MORE_ENTRIES; + } + + *packet_size = size; + return NT_STATUS_OK; +} + +NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size) +{ + struct asn1_data asn1; + uint32_t size; + bool ok; + + ZERO_STRUCT(asn1); + asn1.data = blob.data; + asn1.length = blob.length; + + ok = asn1_peek_tag_needed_size(&asn1, tag, &size); + if (!ok) { + return STATUS_MORE_ENTRIES; + } + + if (size > blob.length) { + *packet_size = size; + return STATUS_MORE_ENTRIES; } *packet_size = size; diff --git a/lib/util/asn1.h b/lib/util/asn1.h index ded3244bed..266a9a386b 100644 --- a/lib/util/asn1.h +++ b/lib/util/asn1.h @@ -79,6 +79,7 @@ bool asn1_peek(struct asn1_data *data, void *p, int len); bool asn1_read(struct asn1_data *data, void *p, int len); bool asn1_read_uint8(struct asn1_data *data, uint8_t *v); bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v); +bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, size_t *size); bool asn1_peek_tag(struct asn1_data *data, uint8_t tag); bool asn1_start_tag(struct asn1_data *data, uint8_t tag); bool asn1_end_tag(struct asn1_data *data); @@ -100,5 +101,6 @@ bool asn1_write_enumerated(struct asn1_data *data, uint8_t v); bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob); void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len); NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size); +NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size); #endif /* _ASN_1_H */ -- cgit