summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-07-06 01:28:12 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:56:52 -0500
commitb359f5d89301882bbec657084b99c8d3e93dc3f2 (patch)
tree2a4e2edd394fe2462e682bc6a86348924528bc30
parent3b7872f69ffa0b1cde8d14ab9122a91ee8aab7a6 (diff)
downloadsamba-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.c59
-rw-r--r--source4/libcli/util/asn1.c22
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)
{