From 52455cb9224bc7358f6700c8e3a233ff8c9a0f2a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 20 Dec 2006 15:51:02 +0000 Subject: r20284: Simplify OID primitive BER parsing. Do not require an artificial ASN.1 context to be setup. Simo. (This used to be commit 14b3b9861ae47498c74a6643e6979b3d85260a61) --- source4/libcli/util/asn1.c | 146 ++++++++++++++++++++++----------------- source4/librpc/ndr/ndr_drsuapi.c | 45 +++++------- 2 files changed, 100 insertions(+), 91 deletions(-) (limited to 'source4') diff --git a/source4/libcli/util/asn1.c b/source4/libcli/util/asn1.c index c82269fd60..d139996bd0 100644 --- a/source4/libcli/util/asn1.c +++ b/source4/libcli/util/asn1.c @@ -187,27 +187,28 @@ BOOL asn1_write_Integer(struct asn1_data *data, int i) return asn1_pop_tag(data); } -BOOL asn1_write_OID_String(struct asn1_data *data, const char *OID) +BOOL ber_write_OID_String(DATA_BLOB *blob, const char *OID) { uint_t v, v2; const char *p = (const char *)OID; char *newp; + int i; v = strtoul(p, &newp, 10); - if (newp[0] != '.') { - data->has_error = True; - return False; - } + if (newp[0] != '.') return False; p = newp + 1; + v2 = strtoul(p, &newp, 10); - if (newp[0] != '.') { - data->has_error = True; - return False; - } + if (newp[0] != '.') return False; p = newp + 1; - if (!asn1_write_uint8(data, 40*v + v2)) - return False; + /*the ber representation can't use more space then the string one */ + *blob = data_blob(NULL, strlen(OID)); + if (!blob->data) return False; + + blob->data[0] = 40*v + v2; + + i = 1; while (*p) { v = strtoul(p, &newp, 10); if (newp[0] == '.') { @@ -215,25 +216,38 @@ BOOL asn1_write_OID_String(struct asn1_data *data, const char *OID) } else if (newp[0] == '\0') { p = newp; } else { - data->has_error = True; + data_blob_free(blob); return False; } - if (v >= (1<<28)) asn1_write_uint8(data, 0x80 | ((v>>28)&0xff)); - if (v >= (1<<21)) asn1_write_uint8(data, 0x80 | ((v>>21)&0xff)); - if (v >= (1<<14)) asn1_write_uint8(data, 0x80 | ((v>>14)&0xff)); - if (v >= (1<<7)) asn1_write_uint8(data, 0x80 | ((v>>7)&0xff)); - if (!asn1_write_uint8(data, v&0x7f)) - return False; + if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f)); + if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f)); + if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f)); + if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f)); + blob->data[i++] = (v&0x7f); } - return !data->has_error; + blob->length = i; + + return True; } /* write an object ID to a ASN1 buffer */ BOOL asn1_write_OID(struct asn1_data *data, const char *OID) { + DATA_BLOB blob; + if (!asn1_push_tag(data, ASN1_OID)) return False; - if (!asn1_write_OID_String(data, OID)) return False; + + if (!ber_write_OID_String(&blob, OID)) { + data->has_error = True; + return False; + } + + if (!asn1_write(data, blob.data, blob.length)) { + data->has_error = True; + return False; + } + data_blob_free(&blob); return asn1_pop_tag(data); } @@ -425,26 +439,6 @@ BOOL asn1_start_tag(struct asn1_data *data, uint8_t tag) return !data->has_error; } -BOOL asn1_start_fake_tag(struct asn1_data *data) -{ - struct nesting *nesting; - - nesting = talloc(NULL, struct nesting); - if (!nesting) { - data->has_error = True; - return False; - } - - nesting->start = data->ofs; - nesting->taglen = data->length - data->ofs; - nesting->next = data->nesting; - data->nesting = nesting; - if (asn1_tag_remaining(data) == -1) { - return False; - } - return !data->has_error; -} - /* stop reading a tag */ BOOL asn1_end_tag(struct asn1_data *data) { @@ -488,52 +482,78 @@ int asn1_tag_remaining(struct asn1_data *data) return remaining; } -/* read an object ID from a ASN1 buffer */ -BOOL asn1_read_OID_String(struct asn1_data *data, const char **OID) +/* read an object ID from a data blob */ +BOOL ber_read_OID_String(DATA_BLOB blob, const char **OID) { - uint8_t b; + int i; + uint8_t *b; + uint_t v; char *tmp_oid = NULL; - if (!asn1_read_uint8(data, &b)) return False; + if (blob.length < 2) return False; + + b = blob.data; - tmp_oid = talloc_asprintf(NULL, "%u", b/40); + tmp_oid = talloc_asprintf(NULL, "%u", b[0]/40); if (!tmp_oid) goto nomem; - tmp_oid = talloc_asprintf_append(tmp_oid, ".%u", b%40); + tmp_oid = talloc_asprintf_append(tmp_oid, ".%u", b[0]%40); if (!tmp_oid) goto nomem; - while (!data->has_error && asn1_tag_remaining(data) > 0) { - uint_t v = 0; - do { - asn1_read_uint8(data, &b); - v = (v<<7) | (b&0x7f); - } while (!data->has_error && (b & 0x80)); - tmp_oid = talloc_asprintf_append(tmp_oid, ".%u", v); + for(i = 1, v = 0; i < blob.length; i++) { + v = (v<<7) | (b[i]&0x7f); + if ( ! (b[i] & 0x80)) { + tmp_oid = talloc_asprintf_append(tmp_oid, ".%u", v); + v = 0; + } if (!tmp_oid) goto nomem; } - if (!data->has_error) { - *OID = tmp_oid; - } else { + if (v != 0) { talloc_free(tmp_oid); + return False; } - return !data->has_error; + *OID = tmp_oid; + return True; + nomem: - talloc_free(tmp_oid); - data->has_error = True; return False; } /* read an object ID from a ASN1 buffer */ BOOL asn1_read_OID(struct asn1_data *data, const char **OID) { + DATA_BLOB blob; + int len; + if (!asn1_start_tag(data, ASN1_OID)) return False; - if (!asn1_read_OID_String(data, OID)) return False; - if (!asn1_end_tag(data)) { - talloc_free(discard_const(*OID)); - *OID = NULL; + + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = True; + return False; + } + + blob = data_blob(NULL, len); + if (!blob.data) { + data->has_error = True; + return False; + } + + asn1_read(data, blob.data, len); + asn1_end_tag(data); + if (data->has_error) { + data_blob_free(&blob); return False; } + + if (!ber_read_OID_String(blob, OID)) { + data->has_error = True; + data_blob_free(&blob); + return False; + } + + data_blob_free(&blob); return True; } diff --git a/source4/librpc/ndr/ndr_drsuapi.c b/source4/librpc/ndr/ndr_drsuapi.c index 5bbb5714e8..dbbdd842f2 100644 --- a/source4/librpc/ndr/ndr_drsuapi.c +++ b/source4/librpc/ndr/ndr_drsuapi.c @@ -64,19 +64,19 @@ void ndr_print_drsuapi_DsReplicaObjectListItemEx(struct ndr_print *ndr, const ch } } -#define _ASN1_PUSH_CHECK(call) do { \ +#define _OID_PUSH_CHECK(call) do { \ BOOL _status; \ _status = call; \ if (_status != True) { \ - return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "ASN.1 Error: %s\n", __location__); \ + return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "OID Conversion Error: %s\n", __location__); \ } \ } while (0) -#define _ASN1_PULL_CHECK(call) do { \ +#define _OID_PULL_CHECK(call) do { \ BOOL _status; \ _status = call; \ if (_status != True) { \ - return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "ASN.1 Error: %s\n", __location__); \ + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "OID Conversion Error: %s\n", __location__); \ } \ } while (0) @@ -89,15 +89,13 @@ NTSTATUS ndr_push_drsuapi_DsReplicaOID(struct ndr_push *ndr, int ndr_flags, cons } if (ndr_flags & NDR_BUFFERS) { if (r->oid) { - struct asn1_data _asn1; + DATA_BLOB blob; - ZERO_STRUCT(_asn1); - _ASN1_PUSH_CHECK(asn1_write_OID_String(&_asn1, r->oid)); - talloc_steal(ndr, _asn1.data); + _OID_PUSH_CHECK(ber_write_OID_String(&blob, r->oid)); + talloc_steal(ndr, blob.data); - NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, _asn1.ofs)); - NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, _asn1.data, _asn1.ofs)); - asn1_free(&_asn1); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length)); + NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, blob.data, blob.length)); } } return NT_STATUS_OK; @@ -136,22 +134,14 @@ NTSTATUS ndr_pull_drsuapi_DsReplicaOID(struct ndr_pull *ndr, int ndr_flags, stru if (_oid_array.length && _oid_array.data[0] == 0xFF) { _oid = data_blob_hex_string(ndr, &_oid_array); NT_STATUS_HAVE_NO_MEMORY(_oid); - data_blob_free(&_oid_array); - talloc_steal(r->oid, _oid); - r->oid = _oid; } else { - struct asn1_data _asn1; - ZERO_STRUCT(_asn1); - _ASN1_PULL_CHECK(asn1_load(&_asn1, _oid_array)); - talloc_steal(ndr, _asn1.data); - data_blob_free(&_oid_array); - _ASN1_PULL_CHECK(asn1_start_fake_tag(&_asn1)); - _ASN1_PULL_CHECK(asn1_read_OID_String(&_asn1, &_oid)); + _OID_PULL_CHECK(ber_read_OID_String(_oid_array, &_oid)); talloc_steal(r->oid, _oid); r->oid = _oid; - _ASN1_PULL_CHECK(asn1_end_tag(&_asn1)); - asn1_free(&_asn1); } + data_blob_free(&_oid_array); + talloc_steal(r->oid, _oid); + r->oid = _oid; } if (r->oid) { NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->oid, r->__ndr_size)); @@ -162,16 +152,15 @@ NTSTATUS ndr_pull_drsuapi_DsReplicaOID(struct ndr_pull *ndr, int ndr_flags, stru size_t ndr_size_drsuapi_DsReplicaOID_oid(const char *oid, int flags) { - struct asn1_data _asn1; + DATA_BLOB _blob; size_t ret = 0; if (!oid) return 0; - ZERO_STRUCT(_asn1); - if (asn1_write_OID_String(&_asn1, oid)) { - ret = _asn1.ofs; + if (ber_write_OID_String(&_blob, oid)) { + ret = _blob.length; } - asn1_free(&_asn1); + data_blob_free(&_blob); return ret; } -- cgit