/*
- Unix SMB/Netbios implementation.
- Version 3.0
+ Unix SMB/CIFS implementation.
simple SPNEGO routines
Copyright (C) Andrew Tridgell 2001
{
if (data->has_error) return False;
if (data->length < data->ofs+len) {
- data->data = Realloc(data->data, data->ofs+len);
- if (!data->data) {
+ uint8 *newp;
+ newp = Realloc(data->data, data->ofs+len);
+ if (!newp) {
+ SAFE_FREE(data->data);
data->has_error = True;
return False;
}
+ data->data = newp;
data->length = data->ofs+len;
}
memcpy(data->data + data->ofs, p, len);
/* yes, this is ugly. We don't know in advance how many bytes the length
of a tag will take, so we assumed 1 byte. If we were wrong then we
need to correct our mistake */
- if (len > 127) {
+ if (len > 255) {
data->data[nesting->start] = 0x82;
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;
+ } else if (len > 127) {
+ data->data[nesting->start] = 0x81;
+ if (!asn1_write_uint8(data, 0)) return False;
+ memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
+ data->data[nesting->start+1] = len;
} else {
data->data[nesting->start] = len;
}
return True;
}
+
+/* write an integer */
+BOOL asn1_write_Integer(ASN1_DATA *data, int i)
+{
+ if (!asn1_push_tag(data, ASN1_INTEGER)) return False;
+ do {
+ asn1_write_uint8(data, i);
+ i = i >> 8;
+ } while (i);
+ return asn1_pop_tag(data);
+}
+
/* write an object ID to a ASN1 buffer */
BOOL asn1_write_OID(ASN1_DATA *data, const char *OID)
{
unsigned v, v2;
- char *p = (char *)OID;
+ const char *p = (const char *)OID;
+ char *newp;
- if (!asn1_push_tag(data, ASN1_OID)) return False;
- v = strtol(p, &p, 10);
- v2 = strtol(p, &p, 10);
- if (!asn1_write_uint8(data, 40*v + v2)) return False;
+ if (!asn1_push_tag(data, ASN1_OID))
+ return False;
+ v = strtol(p, &newp, 10);
+ p = newp;
+ v2 = strtol(p, &newp, 10);
+ p = newp;
+ if (!asn1_write_uint8(data, 40*v + v2))
+ return False;
while (*p) {
- v = strtol(p, &p, 10);
+ v = strtol(p, &newp, 10);
+ p = newp;
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 (!asn1_write_uint8(data, v&0x7f))
+ return False;
}
return asn1_pop_tag(data);
}
return !data->has_error;
}
+/* write a BOOLEAN - hmm, I suspect this one is the correct one, and the
+ above boolean is bogus. Need to check */
+BOOL asn1_write_BOOLEAN2(ASN1_DATA *data, BOOL v)
+{
+ asn1_push_tag(data, ASN1_BOOLEAN);
+ asn1_write_uint8(data, v);
+ asn1_pop_tag(data);
+ return !data->has_error;
+}
+
+/* check a BOOLEAN */
+BOOL asn1_check_BOOLEAN(ASN1_DATA *data, BOOL v)
+{
+ uint8 b = 0;
+
+ asn1_read_uint8(data, &b);
+ if (b != ASN1_BOOLEAN) {
+ data->has_error = True;
+ return False;
+ }
+ asn1_read_uint8(data, &b);
+ if (b != v) {
+ data->has_error = True;
+ return False;
+ }
+ return !data->has_error;
+}
+
/* load a ASN1_DATA structure with a lump of data, ready to be parsed */
BOOL asn1_load(ASN1_DATA *data, DATA_BLOB blob)
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;
+ nesting->taglen = b;
+ while (n > 1) {
+ asn1_read_uint8(data, &b);
+ nesting->taglen = (nesting->taglen << 8) | b;
+ n--;
+ }
} else {
nesting->taglen = b;
}
}
/* check that the next object ID is correct */
-BOOL asn1_check_OID(ASN1_DATA *data, char *OID)
+BOOL asn1_check_OID(ASN1_DATA *data, const char *OID)
{
char *id;
asn1_end_tag(data);
return !data->has_error;
}
+
+/* read a octet string blob */
+BOOL asn1_read_OctetString(ASN1_DATA *data, DATA_BLOB *blob)
+{
+ int len;
+ ZERO_STRUCTP(blob);
+ if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return False;
+ len = asn1_tag_remaining(data);
+ *blob = data_blob(NULL, len);
+ asn1_read(data, blob->data, len);
+ asn1_end_tag(data);
+ return !data->has_error;
+}
+
+/* read an interger */
+BOOL asn1_read_Integer(ASN1_DATA *data, int *i)
+{
+ uint8 b;
+ *i = 0;
+
+ if (!asn1_start_tag(data, ASN1_INTEGER)) return False;
+ while (asn1_tag_remaining(data)>0) {
+ asn1_read_uint8(data, &b);
+ *i = (*i << 8) + b;
+ }
+ return asn1_end_tag(data);
+
+}
+
+/* check a enumarted value is correct */
+BOOL asn1_check_enumerated(ASN1_DATA *data, int v)
+{
+ uint8 b;
+ if (!asn1_start_tag(data, ASN1_ENUMERATED)) return False;
+ asn1_read_uint8(data, &b);
+ asn1_end_tag(data);
+ return !data->has_error && (v == b);
+}
+
+/* check a enumarted value is correct */
+BOOL asn1_write_enumerated(ASN1_DATA *data, uint8 v)
+{
+ if (!asn1_push_tag(data, ASN1_ENUMERATED)) return False;
+ asn1_write_uint8(data, v);
+ asn1_pop_tag(data);
+ return !data->has_error;
+}