summaryrefslogtreecommitdiff
path: root/source3/libsmb/asn1.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-10-11 13:13:06 +0000
committerAndrew Tridgell <tridge@samba.org>2001-10-11 13:13:06 +0000
commit7cd9c611e2a1e0028081863a3678c47bc8af7b55 (patch)
tree2ce652229e5647535c8eaedf1654cfc86636a2cb /source3/libsmb/asn1.c
parent49307c26789b3061780d160f4c6fa4863853eddd (diff)
downloadsamba-7cd9c611e2a1e0028081863a3678c47bc8af7b55.tar.gz
samba-7cd9c611e2a1e0028081863a3678c47bc8af7b55.tar.bz2
samba-7cd9c611e2a1e0028081863a3678c47bc8af7b55.zip
added a ASN.1 parser, so now I can properly parse the negTokenInit
packet which means I can extract the service and realm, so we should now work with realms other than the local realm. it also means we now check the list of OIDs given by the server just in case it says that it doesn't support kerberos. In that case we should fall back to NTLMSSP but that isn't written yet. (This used to be commit 395cfeea94febb5280ea57027e8a8a3c7c3f9291)
Diffstat (limited to 'source3/libsmb/asn1.c')
-rw-r--r--source3/libsmb/asn1.c186
1 files changed, 168 insertions, 18 deletions
diff --git a/source3/libsmb/asn1.c b/source3/libsmb/asn1.c
index e4c2d3af80..17b1ee1089 100644
--- a/source3/libsmb/asn1.c
+++ b/source3/libsmb/asn1.c
@@ -30,9 +30,13 @@ void asn1_free(ASN1_DATA *data)
/* write to the ASN1 buffer, advancing the buffer pointer */
BOOL asn1_write(ASN1_DATA *data, const void *p, int len)
{
+ if (data->has_error) return False;
if (data->length < data->ofs+len) {
data->data = Realloc(data->data, data->ofs+len);
- if (!data->data) return False;
+ if (!data->data) {
+ data->has_error = True;
+ return False;
+ }
data->length = data->ofs+len;
}
memcpy(data->data + data->ofs, p, len);
@@ -53,13 +57,15 @@ BOOL asn1_push_tag(ASN1_DATA *data, uint8 tag)
asn1_write_uint8(data, tag);
nesting = (struct nesting *)malloc(sizeof(struct nesting));
- if (!nesting) return False;
+ if (!nesting) {
+ data->has_error = True;
+ return False;
+ }
nesting->start = data->ofs;
nesting->next = data->nesting;
data->nesting = nesting;
- asn1_write_uint8(data, 0xff);
- return True;
+ return asn1_write_uint8(data, 0xff);
}
/* pop a tag */
@@ -71,6 +77,7 @@ BOOL asn1_pop_tag(ASN1_DATA *data)
nesting = data->nesting;
if (!nesting) {
+ data->has_error = True;
return False;
}
len = data->ofs - (nesting->start+1);
@@ -79,8 +86,8 @@ BOOL asn1_pop_tag(ASN1_DATA *data)
need to correct our mistake */
if (len > 127) {
data->data[nesting->start] = 0x82;
- asn1_write_uint8(data, 0);
- asn1_write_uint8(data, 0);
+ if (!asn1_write_uint8(data, 0)) return False;
+ if (!asn1_write_uint8(data, 0)) return False;
memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
data->data[nesting->start+1] = len>>8;
data->data[nesting->start+2] = len&0xff;
@@ -99,10 +106,10 @@ BOOL asn1_write_OID(ASN1_DATA *data, const char *OID)
unsigned v, v2;
char *p = (char *)OID;
- asn1_push_tag(data, ASN1_OID);
+ if (!asn1_push_tag(data, ASN1_OID)) return False;
v = strtol(p, &p, 10);
v2 = strtol(p, &p, 10);
- asn1_write_uint8(data, 40*v + v2);
+ if (!asn1_write_uint8(data, 40*v + v2)) return False;
while (*p) {
v = strtol(p, &p, 10);
@@ -110,10 +117,9 @@ BOOL asn1_write_OID(ASN1_DATA *data, const char *OID)
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));
- asn1_write_uint8(data, v&0x7f);
+ if (!asn1_write_uint8(data, v&0x7f)) return False;
}
- asn1_pop_tag(data);
- return True;
+ return asn1_pop_tag(data);
}
/* write an octet string */
@@ -122,7 +128,7 @@ BOOL asn1_write_OctetString(ASN1_DATA *data, const void *p, size_t length)
asn1_push_tag(data, ASN1_OCTET_STRING);
asn1_write(data, p, length);
asn1_pop_tag(data);
- return True;
+ return !data->has_error;
}
/* write a general string */
@@ -131,7 +137,7 @@ BOOL asn1_write_GeneralString(ASN1_DATA *data, const char *s)
asn1_push_tag(data, ASN1_GENERAL_STRING);
asn1_write(data, s, strlen(s));
asn1_pop_tag(data);
- return True;
+ return !data->has_error;
}
/* write a BOOLEAN */
@@ -139,17 +145,20 @@ BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
{
asn1_write_uint8(data, ASN1_BOOLEAN);
asn1_write_uint8(data, v);
- return True;
+ return !data->has_error;
}
/* load a ASN1_DATA structure with a lump of data, ready to be parsed */
-BOOL asn1_load(ASN1_DATA *data, void *p, size_t length)
+BOOL asn1_load(ASN1_DATA *data, DATA_BLOB blob)
{
ZERO_STRUCTP(data);
- data->data = memdup(p, length);
- if (!data->data) return False;
- data->length = length;
+ data->data = memdup(blob.data, blob.length);
+ if (!data->data) {
+ data->has_error = True;
+ return False;
+ }
+ data->length = blob.length;
return True;
}
@@ -157,6 +166,7 @@ BOOL asn1_load(ASN1_DATA *data, void *p, size_t length)
BOOL asn1_read(ASN1_DATA *data, void *p, int len)
{
if (data->ofs + len > data->length) {
+ data->has_error = True;
return False;
}
memcpy(p, data->data + data->ofs, len);
@@ -164,4 +174,144 @@ BOOL asn1_read(ASN1_DATA *data, void *p, int len)
return True;
}
+/* read a uint8 from a ASN1 buffer */
+BOOL asn1_read_uint8(ASN1_DATA *data, uint8 *v)
+{
+ return asn1_read(data, v, 1);
+}
+/* start reading a nested asn1 structure */
+BOOL asn1_start_tag(ASN1_DATA *data, uint8 tag)
+{
+ uint8 b;
+ struct nesting *nesting;
+
+ asn1_read_uint8(data, &b);
+ if (b != tag) {
+ data->has_error = True;
+ return False;
+ }
+ nesting = (struct nesting *)malloc(sizeof(struct nesting));
+ if (!nesting) {
+ data->has_error = True;
+ return False;
+ }
+
+ asn1_read_uint8(data, &b);
+ if (b & 0x80) {
+ int n = b & 0x7f;
+ if (n != 2) {
+ data->has_error = True;
+ return False;
+ }
+ asn1_read_uint8(data, &b);
+ nesting->taglen = b<<8;
+ asn1_read_uint8(data, &b);
+ nesting->taglen |= b;
+ } else {
+ nesting->taglen = b;
+ }
+ nesting->start = data->ofs;
+ nesting->next = data->nesting;
+ data->nesting = nesting;
+ return !data->has_error;
+}
+
+
+/* stop reading a tag */
+BOOL asn1_end_tag(ASN1_DATA *data)
+{
+ struct nesting *nesting;
+
+ /* make sure we read it all */
+ if (asn1_tag_remaining(data) != 0) {
+ data->has_error = True;
+ return False;
+ }
+
+ nesting = data->nesting;
+
+ if (!nesting) {
+ data->has_error = True;
+ return False;
+ }
+
+ data->nesting = nesting->next;
+ free(nesting);
+ return True;
+}
+
+/* work out how many bytes are left in this nested tag */
+int asn1_tag_remaining(ASN1_DATA *data)
+{
+ if (!data->nesting) {
+ data->has_error = True;
+ return -1;
+ }
+ return data->nesting->taglen - (data->ofs - data->nesting->start);
+}
+
+/* read an object ID from a ASN1 buffer */
+BOOL asn1_read_OID(ASN1_DATA *data, char **OID)
+{
+ uint8 b;
+ pstring oid;
+ fstring el;
+
+ if (!asn1_start_tag(data, ASN1_OID)) return False;
+ asn1_read_uint8(data, &b);
+
+ oid[0] = 0;
+ snprintf(el, sizeof(el), "%u", b/40);
+ pstrcat(oid, el);
+ snprintf(el, sizeof(el), " %u", b%40);
+ pstrcat(oid, el);
+
+ while (asn1_tag_remaining(data) > 0) {
+ unsigned v = 0;
+ do {
+ asn1_read_uint8(data, &b);
+ v = (v<<7) | (b&0x7f);
+ } while (!data->has_error && b & 0x80);
+ snprintf(el, sizeof(el), " %u", v);
+ pstrcat(oid, el);
+ }
+
+ asn1_end_tag(data);
+
+ *OID = strdup(oid);
+
+ return !data->has_error;
+}
+
+/* check that the next object ID is correct */
+BOOL asn1_check_OID(ASN1_DATA *data, char *OID)
+{
+ char *id;
+
+ if (!asn1_read_OID(data, &id)) return False;
+
+ if (strcmp(id, OID) != 0) {
+ data->has_error = True;
+ return False;
+ }
+ free(id);
+ return True;
+}
+
+/* read a GeneralString from a ASN1 buffer */
+BOOL asn1_read_GeneralString(ASN1_DATA *data, char **s)
+{
+ int len;
+ if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return False;
+ len = asn1_tag_remaining(data);
+ *s = malloc(len+1);
+ if (! *s) {
+ data->has_error = True;
+ return False;
+ }
+ asn1_read(data, *s, len);
+ (*s)[len] = 0;
+ asn1_end_tag(data);
+ return !data->has_error;
+}