diff options
Diffstat (limited to 'lib/util')
-rw-r--r-- | lib/util/asn1.c | 102 | ||||
-rw-r--r-- | lib/util/asn1.h | 4 | ||||
-rw-r--r-- | lib/util/talloc_stack.h | 2 | ||||
-rw-r--r-- | lib/util/tests/asn1_tests.c | 260 | ||||
-rw-r--r-- | lib/util/tests/data_blob.c | 2 | ||||
-rw-r--r-- | lib/util/util.c | 18 | ||||
-rw-r--r-- | lib/util/util_tdb.c | 2 |
7 files changed, 368 insertions, 22 deletions
diff --git a/lib/util/asn1.c b/lib/util/asn1.c index 70c2c57450..946f71359c 100644 --- a/lib/util/asn1.c +++ b/lib/util/asn1.c @@ -214,7 +214,7 @@ bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, return asn1_pop_tag(data); } -bool ber_write_OID_String(DATA_BLOB *blob, const char *OID) +bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID) { uint_t v, v2; const char *p = (const char *)OID; @@ -230,7 +230,7 @@ bool ber_write_OID_String(DATA_BLOB *blob, const char *OID) p = newp + 1; /*the ber representation can't use more space then the string one */ - *blob = data_blob(NULL, strlen(OID)); + *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID)); if (!blob->data) return false; blob->data[0] = 40*v + v2; @@ -258,6 +258,41 @@ bool ber_write_OID_String(DATA_BLOB *blob, const char *OID) return true; } +/** + * Serialize partial OID string. + * Partial OIDs are in the form: + * 1:2.5.6:0x81 + * 1:2.5.6:0x8182 + */ +bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid) +{ + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + char *oid = talloc_strdup(tmp_ctx, partial_oid); + char *p; + + /* truncate partial part so ber_write_OID_String() works */ + p = strchr(oid, ':'); + if (p) { + *p = '\0'; + p++; + } + + if (!ber_write_OID_String(mem_ctx, blob, oid)) { + talloc_free(tmp_ctx); + return false; + } + + /* Add partially endcoded subidentifier */ + if (p) { + DATA_BLOB tmp_blob = strhex_to_data_blob(tmp_ctx, p); + data_blob_append(mem_ctx, blob, tmp_blob.data, tmp_blob.length); + } + + talloc_free(tmp_ctx); + + return true; +} + /* write an object ID to a ASN1 buffer */ bool asn1_write_OID(struct asn1_data *data, const char *OID) { @@ -265,7 +300,7 @@ bool asn1_write_OID(struct asn1_data *data, const char *OID) if (!asn1_push_tag(data, ASN1_OID)) return false; - if (!ber_write_OID_String(&blob, OID)) { + if (!ber_write_OID_String(NULL, &blob, OID)) { data->has_error = true; return false; } @@ -543,8 +578,13 @@ int asn1_tag_remaining(struct asn1_data *data) return remaining; } -/* read an object ID from a data blob */ -bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID) +/** + * Internal implementation for reading binary OIDs + * Reading is done as far in the buffer as valid OID + * till buffer ends or not valid sub-identifier is found. + */ +static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob, + const char **OID, size_t *bytes_eaten) { int i; uint8_t *b; @@ -565,19 +605,63 @@ bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID) if ( ! (b[i] & 0x80)) { tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", v); v = 0; + if (bytes_eaten) + *bytes_eaten = i+1; } if (!tmp_oid) goto nomem; } - if (v != 0) { - talloc_free(tmp_oid); + *OID = tmp_oid; + return true; + +nomem: + return false; +} + +/* read an object ID from a data blob */ +bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID) +{ + size_t bytes_eaten; + + if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten)) + return false; + + return (bytes_eaten == blob.length); +} + +/** + * Deserialize partial OID string. + * Partial OIDs are in the form: + * 1:2.5.6:0x81 + * 1:2.5.6:0x8182 + */ +bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **partial_oid) +{ + size_t bytes_left; + size_t bytes_eaten; + char *identifier = NULL; + char *tmp_oid = NULL; + + if (!_ber_read_OID_String_impl(mem_ctx, blob, (const char **)&tmp_oid, &bytes_eaten)) return false; + + if (bytes_eaten < blob.length) { + bytes_left = blob.length - bytes_eaten; + identifier = hex_encode_talloc(mem_ctx, &blob.data[bytes_eaten], bytes_left); + if (!identifier) goto nomem; + + *partial_oid = talloc_asprintf_append_buffer(tmp_oid, ":0x%s", identifier); + if (!*partial_oid) goto nomem; + TALLOC_FREE(identifier); + } else { + *partial_oid = tmp_oid; } - *OID = tmp_oid; return true; -nomem: +nomem: + TALLOC_FREE(identifier); + TALLOC_FREE(tmp_oid); return false; } diff --git a/lib/util/asn1.h b/lib/util/asn1.h index 9abae50d64..ded3244bed 100644 --- a/lib/util/asn1.h +++ b/lib/util/asn1.h @@ -61,7 +61,8 @@ bool asn1_pop_tag(struct asn1_data *data); bool asn1_write_implicit_Integer(struct asn1_data *data, int i); bool asn1_write_Integer(struct asn1_data *data, int i); bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding); -bool ber_write_OID_String(DATA_BLOB *blob, const char *OID); +bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID); +bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid); bool asn1_write_OID(struct asn1_data *data, const char *OID); bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length); bool asn1_write_LDAPString(struct asn1_data *data, const char *s); @@ -83,6 +84,7 @@ bool asn1_start_tag(struct asn1_data *data, uint8_t tag); bool asn1_end_tag(struct asn1_data *data); int asn1_tag_remaining(struct asn1_data *data); bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID); +bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **partial_oid); bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID); bool asn1_check_OID(struct asn1_data *data, const char *OID); bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s); diff --git a/lib/util/talloc_stack.h b/lib/util/talloc_stack.h index bb22b8a029..777671164d 100644 --- a/lib/util/talloc_stack.h +++ b/lib/util/talloc_stack.h @@ -35,7 +35,7 @@ #ifndef _TALLOC_STACK_H #define _TALLOC_STACK_H -#include "../talloc/talloc.h" +#include "talloc.h" /* * Create a new talloc stack frame. diff --git a/lib/util/tests/asn1_tests.c b/lib/util/tests/asn1_tests.c new file mode 100644 index 0000000000..25c82227ae --- /dev/null +++ b/lib/util/tests/asn1_tests.c @@ -0,0 +1,260 @@ +/* + Unix SMB/CIFS implementation. + + util_asn1 testing + + Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "../asn1.h" + +struct oid_data { + const char *oid; /* String OID */ + const char *bin_oid; /* Binary OID represented as string */ +}; + +/* Data for successful OIDs conversions */ +struct oid_data oid_data_ok[] = { + { + .oid = "2.5.4.0", + .bin_oid = "550400" + }, + { + .oid = "2.5.4.1", + .bin_oid = "550401" + }, + { + .oid = "2.5.4.130", + .bin_oid = "55048102" + }, + { + .oid = "2.5.130.4", + .bin_oid = "55810204" + }, + { + .oid = "2.5.4.16387", + .bin_oid = "5504818003" + }, + { + .oid = "2.5.16387.4", + .bin_oid = "5581800304" + }, + { + .oid = "2.5.2097155.4", + .bin_oid = "558180800304" + }, + { + .oid = "2.5.4.130.16387.2097155.268435459", + .bin_oid = "55048102818003818080038180808003" + }, +}; + +/* Data for successful Partial OIDs conversions */ +struct oid_data partial_oid_data_ok[] = { + { + .oid = "2.5.4.130:0x81", + .bin_oid = "5504810281" + }, + { + .oid = "2.5.4.16387:0x8180", + .bin_oid = "55048180038180" + }, + { + .oid = "2.5.4.16387:0x81", + .bin_oid = "550481800381" + }, + { + .oid = "2.5.2097155.4:0x818080", + .bin_oid = "558180800304818080" + }, + { + .oid = "2.5.2097155.4:0x8180", + .bin_oid = "5581808003048180" + }, + { + .oid = "2.5.2097155.4:0x81", + .bin_oid = "55818080030481" + }, +}; + + +/* Testing ber_write_OID_String() function */ +static bool test_ber_write_OID_String(struct torture_context *tctx) +{ + int i; + char *hex_str; + DATA_BLOB blob; + TALLOC_CTX *mem_ctx; + struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + torture_assert(tctx, ber_write_OID_String(mem_ctx, &blob, data[i].oid), + "ber_write_OID_String failed"); + + hex_str = hex_encode_talloc(mem_ctx, blob.data, blob.length); + torture_assert(tctx, hex_str, "No memory!"); + + torture_assert(tctx, strequal(data[i].bin_oid, hex_str), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + talloc_free(mem_ctx); + + return true; +} + +/* Testing ber_read_OID_String() function */ +static bool test_ber_read_OID_String(struct torture_context *tctx) +{ + int i; + const char *oid; + DATA_BLOB oid_blob; + TALLOC_CTX *mem_ctx; + struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + oid_blob = strhex_to_data_blob(mem_ctx, data[i].bin_oid); + + torture_assert(tctx, ber_read_OID_String(mem_ctx, oid_blob, &oid), + "ber_read_OID_String failed"); + + torture_assert(tctx, strequal(data[i].oid, oid), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + talloc_free(mem_ctx); + + return true; +} + +/* Testing ber_write_partial_OID_String() function */ +static bool test_ber_write_partial_OID_String(struct torture_context *tctx) +{ + int i; + char *hex_str; + DATA_BLOB blob; + TALLOC_CTX *mem_ctx; + struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + /* ber_write_partial_OID_String() should work with not partial OIDs also */ + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + torture_assert(tctx, ber_write_partial_OID_String(mem_ctx, &blob, data[i].oid), + "ber_write_partial_OID_String failed"); + + hex_str = hex_encode_talloc(mem_ctx, blob.data, blob.length); + torture_assert(tctx, hex_str, "No memory!"); + + torture_assert(tctx, strequal(data[i].bin_oid, hex_str), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + /* ber_write_partial_OID_String() test with partial OIDs */ + data = partial_oid_data_ok; + for (i = 0; i < ARRAY_SIZE(partial_oid_data_ok); i++) { + torture_assert(tctx, ber_write_partial_OID_String(mem_ctx, &blob, data[i].oid), + "ber_write_partial_OID_String failed"); + + hex_str = hex_encode_talloc(mem_ctx, blob.data, blob.length); + torture_assert(tctx, hex_str, "No memory!"); + + torture_assert(tctx, strequal(data[i].bin_oid, hex_str), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + talloc_free(mem_ctx); + + return true; +} + +/* Testing ber_read_partial_OID_String() function */ +static bool test_ber_read_partial_OID_String(struct torture_context *tctx) +{ + int i; + const char *oid; + DATA_BLOB oid_blob; + TALLOC_CTX *mem_ctx; + struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + /* ber_read_partial_OID_String() should work with not partial OIDs also */ + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + oid_blob = strhex_to_data_blob(mem_ctx, data[i].bin_oid); + + torture_assert(tctx, ber_read_partial_OID_String(mem_ctx, oid_blob, &oid), + "ber_read_partial_OID_String failed"); + + torture_assert(tctx, strequal(data[i].oid, oid), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + /* ber_read_partial_OID_String() test with partial OIDs */ + data = partial_oid_data_ok; + for (i = 0; i < ARRAY_SIZE(partial_oid_data_ok); i++) { + oid_blob = strhex_to_data_blob(mem_ctx, data[i].bin_oid); + + torture_assert(tctx, ber_read_partial_OID_String(mem_ctx, oid_blob, &oid), + "ber_read_partial_OID_String failed"); + + torture_assert(tctx, strequal(data[i].oid, oid), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + talloc_free(mem_ctx); + + return true; +} + + +/* LOCAL-ASN1 test suite creation */ +struct torture_suite *torture_local_util_asn1(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "ASN1"); + + torture_suite_add_simple_test(suite, "ber_write_OID_String", + test_ber_write_OID_String); + + torture_suite_add_simple_test(suite, "ber_read_OID_String", + test_ber_read_OID_String); + + torture_suite_add_simple_test(suite, "ber_write_partial_OID_String", + test_ber_write_partial_OID_String); + + torture_suite_add_simple_test(suite, "ber_read_partial_OID_String", + test_ber_read_partial_OID_String); + + return suite; +} diff --git a/lib/util/tests/data_blob.c b/lib/util/tests/data_blob.c index 875e5fdef8..f0b02b8d17 100644 --- a/lib/util/tests/data_blob.c +++ b/lib/util/tests/data_blob.c @@ -78,7 +78,7 @@ static bool test_cmp(struct torture_context *tctx) static bool test_hex_string(struct torture_context *tctx) { DATA_BLOB a = data_blob_string_const("\xC\xA\xF\xE"); - torture_assert_str_equal(tctx, data_blob_hex_string(tctx, &a), "0C0A0F0E", "hex string"); + torture_assert_str_equal(tctx, data_blob_hex_string(tctx, &a), "0c0a0f0e", "hex string"); return true; } diff --git a/lib/util/util.c b/lib/util/util.c index 2a809d3ccb..fd0e6b8d79 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -579,18 +579,18 @@ _PUBLIC_ _PURE_ size_t count_chars(const char *s, char c) **/ _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len) { - size_t i; + size_t i = 0; size_t num_chars = 0; uint8_t lonybble, hinybble; const char *hexchars = "0123456789ABCDEF"; char *p1 = NULL, *p2 = NULL; - for (i = 0; i < strhex_len && strhex[i] != 0; i++) { - if (strncasecmp(hexchars, "0x", 2) == 0) { - i++; /* skip two chars */ - continue; - } + /* skip leading 0x prefix */ + if (strncasecmp(strhex, "0x", 2) == 0) { + i += 2; /* skip two chars */ + } + for (; i < strhex_len && strhex[i] != 0; i++) { if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i])))) break; @@ -804,8 +804,8 @@ static bool next_token_internal_talloc(TALLOC_CTX *ctx, const char *sep, bool ltrim) { - char *s; - char *saved_s; + const char *s; + const char *saved_s; char *pbuf; bool quoted; size_t len=1; @@ -815,7 +815,7 @@ static bool next_token_internal_talloc(TALLOC_CTX *ctx, return(false); } - s = (char *)*ptr; + s = *ptr; /* default to simple separators */ if (!sep) { diff --git a/lib/util/util_tdb.c b/lib/util/util_tdb.c index e107cbdc4a..cda8dc75b2 100644 --- a/lib/util/util_tdb.c +++ b/lib/util/util_tdb.c @@ -20,7 +20,7 @@ */ #include "includes.h" -#include "../tdb/include/tdb.h" +#include "tdb.h" #include "../lib/util/util_tdb.h" /* these are little tdb utility functions that are meant to make |