diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-07-06 01:28:12 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:56:52 -0500 |
commit | b359f5d89301882bbec657084b99c8d3e93dc3f2 (patch) | |
tree | 2a4e2edd394fe2462e682bc6a86348924528bc30 | |
parent | 3b7872f69ffa0b1cde8d14ab9122a91ee8aab7a6 (diff) | |
download | samba-b359f5d89301882bbec657084b99c8d3e93dc3f2.tar.gz samba-b359f5d89301882bbec657084b99c8d3e93dc3f2.tar.bz2 samba-b359f5d89301882bbec657084b99c8d3e93dc3f2.zip |
r1352: Add a 'peek' function to our ASN1 code, so we can safely perform the
various switches without looking one byte past te end of the buffer.
(This used to be commit 5bce188d429b4166f3d0314922ae40204de182a7)
-rw-r--r-- | source4/libcli/auth/spnego_parse.c | 59 | ||||
-rw-r--r-- | source4/libcli/util/asn1.c | 22 |
2 files changed, 63 insertions, 18 deletions
diff --git a/source4/libcli/auth/spnego_parse.c b/source4/libcli/auth/spnego_parse.c index b38226c014..dfaf9cf320 100644 --- a/source4/libcli/auth/spnego_parse.c +++ b/source4/libcli/auth/spnego_parse.c @@ -35,8 +35,13 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, struct spnego_negTokenInit *token while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) { int i; + uint8_t context; + if (!asn1_peek_uint8(asn1, &context)) { + asn1->has_error = True; + break; + } - switch (asn1->data[asn1->ofs]) { + switch (context) { /* Read mechTypes */ case ASN1_CONTEXT(0): asn1_start_tag(asn1, ASN1_CONTEXT(0)); @@ -70,8 +75,14 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, struct spnego_negTokenInit *token break; /* Read mecListMIC */ case ASN1_CONTEXT(3): + { + uint8_t type_peek; asn1_start_tag(asn1, ASN1_CONTEXT(3)); - if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) { + if (!asn1_peek_uint8(asn1, &type_peek)) { + asn1->has_error = True; + break; + } + if (type_peek == ASN1_OCTET_STRING) { asn1_read_OctetString(asn1, &token->mechListMIC); } else { @@ -90,6 +101,7 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, struct spnego_negTokenInit *token } asn1_end_tag(asn1); break; + } default: asn1->has_error = True; break; @@ -173,7 +185,13 @@ static BOOL read_negTokenTarg(ASN1_DATA *asn1, struct spnego_negTokenTarg *token asn1_start_tag(asn1, ASN1_SEQUENCE(0)); while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) { - switch (asn1->data[asn1->ofs]) { + uint8_t context; + if (!asn1_peek_uint8(asn1, &context)) { + asn1->has_error = True; + break; + } + + switch (context) { case ASN1_CONTEXT(0): asn1_start_tag(asn1, ASN1_CONTEXT(0)); asn1_start_tag(asn1, ASN1_ENUMERATED); @@ -257,22 +275,27 @@ ssize_t spnego_read_data(DATA_BLOB data, struct spnego_data *token) asn1_load(&asn1, data); - switch (asn1.data[asn1.ofs]) { - case ASN1_APPLICATION(0): - asn1_start_tag(&asn1, ASN1_APPLICATION(0)); - asn1_check_OID(&asn1, OID_SPNEGO); - if (read_negTokenInit(&asn1, &token->negTokenInit)) { - token->type = SPNEGO_NEG_TOKEN_INIT; - } - asn1_end_tag(&asn1); - break; - case ASN1_CONTEXT(1): - if (read_negTokenTarg(&asn1, &token->negTokenTarg)) { - token->type = SPNEGO_NEG_TOKEN_TARG; + uint8_t context; + if (!asn1_peek_uint8(asn1, &context)) { + asn1->has_error = True; + } else { + switch (context) { + case ASN1_APPLICATION(0): + asn1_start_tag(&asn1, ASN1_APPLICATION(0)); + asn1_check_OID(&asn1, OID_SPNEGO); + if (read_negTokenInit(&asn1, &token->negTokenInit)) { + token->type = SPNEGO_NEG_TOKEN_INIT; + } + asn1_end_tag(&asn1); + break; + case ASN1_CONTEXT(1): + if (read_negTokenTarg(&asn1, &token->negTokenTarg)) { + token->type = SPNEGO_NEG_TOKEN_TARG; + } + break; + default: + break; } - break; - default: - break; } if (!asn1.has_error) ret = asn1.ofs; diff --git a/source4/libcli/util/asn1.c b/source4/libcli/util/asn1.c index 943ce4d1c1..da51340774 100644 --- a/source4/libcli/util/asn1.c +++ b/source4/libcli/util/asn1.c @@ -239,6 +239,28 @@ BOOL asn1_read_uint8(ASN1_DATA *data, uint8_t *v) return asn1_read(data, v, 1); } +/* read from a ASN1 buffer, advancing the buffer pointer */ +BOOL asn1_peek(ASN1_DATA *data, void *p, int len) +{ + if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len) { + data->has_error = True; + return False; + } + + if (data->ofs + len > data->length) { + data->has_error = True; + return False; + } + memcpy(p, data->data + data->ofs, len); + return True; +} + +/* read a uint8_t from a ASN1 buffer */ +BOOL asn1_peek_uint8(ASN1_DATA *data, uint8_t *v) +{ + return asn1_peek(data, v, 1); +} + /* start reading a nested asn1 structure */ BOOL asn1_start_tag(ASN1_DATA *data, uint8_t tag) { |