The branch, master has been updated via 95b56aa libcli/ldap: let ldap_full_packet() use asn1_peek_tag_needed_size() via 182a69c lib/util/asn1: add asn1_peek_tag_needed_size() and asn1_peek_full_tag() via e628bf1 libcli/util: let tstream_read_pdu_blob_* cope with variable length headers from 0b5a556 s4-kerberos Don't segfault if the password isn't specified in keytab generation
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 95b56aabcbfe2754a34eac627a6bc7226cbd3f17 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Sep 24 05:09:15 2010 +0200 libcli/ldap: let ldap_full_packet() use asn1_peek_tag_needed_size() This allows us to read a full packet without read byte after byte or possible read to much. metze commit 182a69c5be7706fbb542694c7be51d499b61c98d Author: Stefan Metzmacher <me...@samba.org> Date: Thu Sep 23 18:10:28 2010 +0200 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 commit e628bf1081929684d888353101296cc17d9f3ae4 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 22 20:31:06 2010 +0200 libcli/util: let tstream_read_pdu_blob_* cope with variable length headers metze ----------------------------------------------------------------------- Summary of changes: lib/util/asn1.c | 83 ++++++++++++++++++++++++++++++++++++++++++++ lib/util/asn1.h | 2 + libcli/ldap/ldap_message.c | 2 +- libcli/util/tstream.c | 18 +++++++--- 4 files changed, 99 insertions(+), 6 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/util/asn1.c b/lib/util/asn1.c index 8f30cfe..c492334 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 ded3244..266a9a3 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 */ diff --git a/libcli/ldap/ldap_message.c b/libcli/ldap/ldap_message.c index 1e44214..3941518 100644 --- a/libcli/ldap/ldap_message.c +++ b/libcli/ldap/ldap_message.c @@ -1609,5 +1609,5 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, */ NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size) { - return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size); + return asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size); } diff --git a/libcli/util/tstream.c b/libcli/util/tstream.c index 5d0e561..b287597 100644 --- a/libcli/util/tstream.c +++ b/libcli/util/tstream.c @@ -97,7 +97,9 @@ static void tstream_read_pdu_blob_done(struct tevent_req *subreq) struct tstream_read_pdu_blob_state); ssize_t ret; int sys_errno; - size_t pdu_size; + size_t old_buf_size = state->pdu_blob.length; + size_t new_buf_size = 0; + size_t pdu_size = 0; NTSTATUS status; uint8_t *buf; @@ -116,20 +118,26 @@ static void tstream_read_pdu_blob_done(struct tevent_req *subreq) return; } else if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { /* more to get */ + if (pdu_size > 0) { + new_buf_size = pdu_size; + } else { + /* we don't know the size yet, so get one more byte */ + new_buf_size = old_buf_size + 1; + } } else if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - buf = talloc_realloc(state, state->pdu_blob.data, uint8_t, pdu_size); + buf = talloc_realloc(state, state->pdu_blob.data, uint8_t, new_buf_size); if (tevent_req_nomem(buf, req)) { return; } state->pdu_blob.data = buf; - state->pdu_blob.length = pdu_size; + state->pdu_blob.length = new_buf_size; - state->tmp_vector.iov_base = (char *) (buf + state->tmp_vector.iov_len); - state->tmp_vector.iov_len = pdu_size - state->tmp_vector.iov_len; + state->tmp_vector.iov_base = (char *) (buf + old_buf_size); + state->tmp_vector.iov_len = new_buf_size - old_buf_size; subreq = tstream_readv_send(state, state->caller.ev, -- Samba Shared Repository