2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2001
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "data_blob.h"
28 /* allocate an asn1 structure */
29 struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx)
31 struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data);
35 /* free an asn1 structure */
36 void asn1_free(struct asn1_data *data)
41 /* write to the ASN1 buffer, advancing the buffer pointer */
42 bool asn1_write(struct asn1_data *data, const void *p, int len)
46 if (data->length < (size_t)data->ofs + len) {
48 newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len);
51 data->has_error = true;
55 data->length = data->ofs+len;
57 memcpy(data->data + data->ofs, p, len);
62 /* useful fn for writing a uint8_t */
63 bool asn1_write_uint8(struct asn1_data *data, uint8_t v)
65 return asn1_write(data, &v, 1);
68 /* push a tag onto the asn1 data buffer. Used for nested structures */
69 bool asn1_push_tag(struct asn1_data *data, uint8_t tag)
71 struct nesting *nesting;
73 asn1_write_uint8(data, tag);
74 nesting = talloc(data, struct nesting);
76 data->has_error = true;
80 nesting->start = data->ofs;
81 nesting->next = data->nesting;
82 data->nesting = nesting;
83 return asn1_write_uint8(data, 0xff);
87 bool asn1_pop_tag(struct asn1_data *data)
89 struct nesting *nesting;
92 nesting = data->nesting;
95 data->has_error = true;
98 len = data->ofs - (nesting->start+1);
99 /* yes, this is ugly. We don't know in advance how many bytes the length
100 of a tag will take, so we assumed 1 byte. If we were wrong then we
101 need to correct our mistake */
102 if (len > 0xFFFFFF) {
103 data->data[nesting->start] = 0x84;
104 if (!asn1_write_uint8(data, 0)) return false;
105 if (!asn1_write_uint8(data, 0)) return false;
106 if (!asn1_write_uint8(data, 0)) return false;
107 if (!asn1_write_uint8(data, 0)) return false;
108 memmove(data->data+nesting->start+5, data->data+nesting->start+1, len);
109 data->data[nesting->start+1] = (len>>24) & 0xFF;
110 data->data[nesting->start+2] = (len>>16) & 0xFF;
111 data->data[nesting->start+3] = (len>>8) & 0xFF;
112 data->data[nesting->start+4] = len&0xff;
113 } else if (len > 0xFFFF) {
114 data->data[nesting->start] = 0x83;
115 if (!asn1_write_uint8(data, 0)) return false;
116 if (!asn1_write_uint8(data, 0)) return false;
117 if (!asn1_write_uint8(data, 0)) return false;
118 memmove(data->data+nesting->start+4, data->data+nesting->start+1, len);
119 data->data[nesting->start+1] = (len>>16) & 0xFF;
120 data->data[nesting->start+2] = (len>>8) & 0xFF;
121 data->data[nesting->start+3] = len&0xff;
122 } else if (len > 255) {
123 data->data[nesting->start] = 0x82;
124 if (!asn1_write_uint8(data, 0)) return false;
125 if (!asn1_write_uint8(data, 0)) return false;
126 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
127 data->data[nesting->start+1] = len>>8;
128 data->data[nesting->start+2] = len&0xff;
129 } else if (len > 127) {
130 data->data[nesting->start] = 0x81;
131 if (!asn1_write_uint8(data, 0)) return false;
132 memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
133 data->data[nesting->start+1] = len;
135 data->data[nesting->start] = len;
138 data->nesting = nesting->next;
139 talloc_free(nesting);
143 /* "i" is the one's complement representation, as is the normal result of an
144 * implicit signed->unsigned conversion */
146 static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative)
148 uint8_t lowest = i & 0xFF;
152 if (!push_int_bigendian(data, i, negative))
155 if (data->nesting->start+1 == data->ofs) {
157 /* We did not write anything yet, looking at the highest
161 /* Don't write leading 0xff's */
165 if ((lowest & 0x80) == 0) {
166 /* The only exception for a leading 0xff is if
167 * the highest bit is 0, which would indicate
168 * a positive value */
169 if (!asn1_write_uint8(data, 0xff))
174 /* The highest bit of a positive integer is 1,
175 * this would indicate a negative number. Push
176 * a 0 to indicate a positive one */
177 if (!asn1_write_uint8(data, 0))
183 return asn1_write_uint8(data, lowest);
186 /* write an Integer without the tag framing. Needed for example for the LDAP
187 * Abandon Operation */
189 bool asn1_write_implicit_Integer(struct asn1_data *data, int i)
192 /* -1 is special as it consists of all-0xff bytes. In
193 push_int_bigendian this is the only case that is not
194 properly handled, as all 0xff bytes would be handled as
195 leading ones to be ignored. */
196 return asn1_write_uint8(data, 0xff);
198 return push_int_bigendian(data, i, i<0);
203 /* write an integer */
204 bool asn1_write_Integer(struct asn1_data *data, int i)
206 if (!asn1_push_tag(data, ASN1_INTEGER)) return false;
207 if (!asn1_write_implicit_Integer(data, i)) return false;
208 return asn1_pop_tag(data);
211 /* write a BIT STRING */
212 bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding)
214 if (!asn1_push_tag(data, ASN1_BIT_STRING)) return false;
215 if (!asn1_write_uint8(data, padding)) return false;
216 if (!asn1_write(data, p, length)) return false;
217 return asn1_pop_tag(data);
220 bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID)
223 const char *p = (const char *)OID;
227 v = strtoul(p, &newp, 10);
228 if (newp[0] != '.') return false;
231 v2 = strtoul(p, &newp, 10);
232 if (newp[0] != '.') return false;
235 /*the ber representation can't use more space then the string one */
236 *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID));
237 if (!blob->data) return false;
239 blob->data[0] = 40*v + v2;
243 v = strtoul(p, &newp, 10);
244 if (newp[0] == '.') {
246 } else if (newp[0] == '\0') {
249 data_blob_free(blob);
252 if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f));
253 if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f));
254 if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f));
255 if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f));
256 blob->data[i++] = (v&0x7f);
264 /* write an object ID to a ASN1 buffer */
265 bool asn1_write_OID(struct asn1_data *data, const char *OID)
269 if (!asn1_push_tag(data, ASN1_OID)) return false;
271 if (!ber_write_OID_String(NULL, &blob, OID)) {
272 data->has_error = true;
276 if (!asn1_write(data, blob.data, blob.length)) {
277 data_blob_free(&blob);
278 data->has_error = true;
281 data_blob_free(&blob);
282 return asn1_pop_tag(data);
285 /* write an octet string */
286 bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length)
288 asn1_push_tag(data, ASN1_OCTET_STRING);
289 asn1_write(data, p, length);
291 return !data->has_error;
294 /* write a LDAP string */
295 bool asn1_write_LDAPString(struct asn1_data *data, const char *s)
297 asn1_write(data, s, strlen(s));
298 return !data->has_error;
301 /* write a LDAP string from a DATA_BLOB */
302 bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s)
304 asn1_write(data, s->data, s->length);
305 return !data->has_error;
308 /* write a general string */
309 bool asn1_write_GeneralString(struct asn1_data *data, const char *s)
311 asn1_push_tag(data, ASN1_GENERAL_STRING);
312 asn1_write_LDAPString(data, s);
314 return !data->has_error;
317 bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
319 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num));
320 asn1_write(data, blob->data, blob->length);
322 return !data->has_error;
325 /* write a BOOLEAN */
326 bool asn1_write_BOOLEAN(struct asn1_data *data, bool v)
328 asn1_push_tag(data, ASN1_BOOLEAN);
329 asn1_write_uint8(data, v ? 0xFF : 0);
331 return !data->has_error;
334 bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v)
337 asn1_start_tag(data, ASN1_BOOLEAN);
338 asn1_read_uint8(data, &tmp);
345 return !data->has_error;
348 /* write a BOOLEAN in a simple context */
349 bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context)
351 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context));
352 asn1_write_uint8(data, v ? 0xFF : 0);
354 return !data->has_error;
357 bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context)
360 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context));
361 asn1_read_uint8(data, &tmp);
368 return !data->has_error;
371 /* check a BOOLEAN */
372 bool asn1_check_BOOLEAN(struct asn1_data *data, bool v)
376 asn1_read_uint8(data, &b);
377 if (b != ASN1_BOOLEAN) {
378 data->has_error = true;
381 asn1_read_uint8(data, &b);
383 data->has_error = true;
386 return !data->has_error;
390 /* load a struct asn1_data structure with a lump of data, ready to be parsed */
391 bool asn1_load(struct asn1_data *data, DATA_BLOB blob)
394 data->data = (uint8_t *)talloc_memdup(data, blob.data, blob.length);
396 data->has_error = true;
399 data->length = blob.length;
403 /* Peek into an ASN1 buffer, not advancing the pointer */
404 bool asn1_peek(struct asn1_data *data, void *p, int len)
409 if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
412 if ((size_t)data->ofs + len > data->length) {
413 /* we need to mark the buffer as consumed, so the caller knows
414 this was an out of data error, and not a decode error */
415 data->ofs = data->length;
419 memcpy(p, data->data + data->ofs, len);
423 /* read from a ASN1 buffer, advancing the buffer pointer */
424 bool asn1_read(struct asn1_data *data, void *p, int len)
426 if (!asn1_peek(data, p, len)) {
427 data->has_error = true;
435 /* read a uint8_t from a ASN1 buffer */
436 bool asn1_read_uint8(struct asn1_data *data, uint8_t *v)
438 return asn1_read(data, v, 1);
441 bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v)
443 return asn1_peek(data, v, 1);
446 bool asn1_peek_tag(struct asn1_data *data, uint8_t tag)
450 if (asn1_tag_remaining(data) <= 0) {
454 if (!asn1_peek_uint8(data, &b))
460 /* start reading a nested asn1 structure */
461 bool asn1_start_tag(struct asn1_data *data, uint8_t tag)
464 struct nesting *nesting;
466 if (!asn1_read_uint8(data, &b))
470 data->has_error = true;
473 nesting = talloc(data, struct nesting);
475 data->has_error = true;
479 if (!asn1_read_uint8(data, &b)) {
485 if (!asn1_read_uint8(data, &b))
489 if (!asn1_read_uint8(data, &b))
491 nesting->taglen = (nesting->taglen << 8) | b;
497 nesting->start = data->ofs;
498 nesting->next = data->nesting;
499 data->nesting = nesting;
500 if (asn1_tag_remaining(data) == -1) {
503 return !data->has_error;
506 /* stop reading a tag */
507 bool asn1_end_tag(struct asn1_data *data)
509 struct nesting *nesting;
511 /* make sure we read it all */
512 if (asn1_tag_remaining(data) != 0) {
513 data->has_error = true;
517 nesting = data->nesting;
520 data->has_error = true;
524 data->nesting = nesting->next;
525 talloc_free(nesting);
529 /* work out how many bytes are left in this nested tag */
530 int asn1_tag_remaining(struct asn1_data *data)
533 if (data->has_error) {
537 if (!data->nesting) {
538 data->has_error = true;
541 remaining = data->nesting->taglen - (data->ofs - data->nesting->start);
543 data->has_error = true;
546 if ((size_t)remaining > data->length - data->ofs) {
547 data->has_error = true;
554 * Internal implementation for reading binary OIDs
555 * Reading is done as far in the buffer as valid OID
556 * till buffer ends or not valid sub-identifier is found.
558 static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
559 const char **OID, size_t *bytes_eaten)
564 char *tmp_oid = NULL;
566 if (blob.length < 2) return false;
570 tmp_oid = talloc_asprintf(mem_ctx, "%u", b[0]/40);
571 if (!tmp_oid) goto nomem;
572 tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", b[0]%40);
573 if (!tmp_oid) goto nomem;
575 for(i = 1, v = 0; i < blob.length; i++) {
576 v = (v<<7) | (b[i]&0x7f);
577 if ( ! (b[i] & 0x80)) {
578 tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", v);
583 if (!tmp_oid) goto nomem;
593 /* read an object ID from a data blob */
594 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID)
596 size_t bytes_eaten = 0;
598 if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten))
601 return (bytes_eaten == blob.length);
604 /* read an object ID from a ASN1 buffer */
605 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID)
610 if (!asn1_start_tag(data, ASN1_OID)) return false;
612 len = asn1_tag_remaining(data);
614 data->has_error = true;
618 blob = data_blob(NULL, len);
620 data->has_error = true;
624 asn1_read(data, blob.data, len);
626 if (data->has_error) {
627 data_blob_free(&blob);
631 if (!ber_read_OID_String(mem_ctx, blob, OID)) {
632 data->has_error = true;
633 data_blob_free(&blob);
637 data_blob_free(&blob);
641 /* check that the next object ID is correct */
642 bool asn1_check_OID(struct asn1_data *data, const char *OID)
646 if (!asn1_read_OID(data, data, &id)) return false;
648 if (strcmp(id, OID) != 0) {
649 talloc_free(discard_const(id));
650 data->has_error = true;
653 talloc_free(discard_const(id));
657 /* read a LDAPString from a ASN1 buffer */
658 bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
661 len = asn1_tag_remaining(data);
663 data->has_error = true;
666 *s = talloc_array(mem_ctx, char, len+1);
668 data->has_error = true;
671 asn1_read(data, *s, len);
673 return !data->has_error;
677 /* read a GeneralString from a ASN1 buffer */
678 bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
680 if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false;
681 if (!asn1_read_LDAPString(data, mem_ctx, s)) return false;
682 return asn1_end_tag(data);
686 /* read a octet string blob */
687 bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
691 if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false;
692 len = asn1_tag_remaining(data);
694 data->has_error = true;
697 *blob = data_blob_talloc(mem_ctx, NULL, len+1);
699 data->has_error = true;
702 asn1_read(data, blob->data, len);
707 if (data->has_error) {
708 data_blob_free(blob);
709 *blob = data_blob_null;
715 bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
719 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
720 len = asn1_tag_remaining(data);
722 data->has_error = true;
725 *blob = data_blob(NULL, len);
726 if ((len != 0) && (!blob->data)) {
727 data->has_error = true;
730 asn1_read(data, blob->data, len);
732 return !data->has_error;
735 /* read an integer without tag*/
736 bool asn1_read_implicit_Integer(struct asn1_data *data, int *i)
741 while (!data->has_error && asn1_tag_remaining(data)>0) {
742 if (!asn1_read_uint8(data, &b)) return false;
745 return !data->has_error;
749 /* read an integer */
750 bool asn1_read_Integer(struct asn1_data *data, int *i)
754 if (!asn1_start_tag(data, ASN1_INTEGER)) return false;
755 if (!asn1_read_implicit_Integer(data, i)) return false;
756 return asn1_end_tag(data);
759 /* read a BIT STRING */
760 bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding)
764 if (!asn1_start_tag(data, ASN1_BIT_STRING)) return false;
765 len = asn1_tag_remaining(data);
767 data->has_error = true;
770 if (!asn1_read_uint8(data, padding)) return false;
772 *blob = data_blob_talloc(mem_ctx, NULL, len);
774 data->has_error = true;
777 if (asn1_read(data, blob->data, len - 1)) {
783 if (data->has_error) {
784 data_blob_free(blob);
785 *blob = data_blob_null;
792 /* read an integer */
793 bool asn1_read_enumerated(struct asn1_data *data, int *v)
797 if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
798 while (!data->has_error && asn1_tag_remaining(data)>0) {
800 asn1_read_uint8(data, &b);
803 return asn1_end_tag(data);
806 /* check a enumerated value is correct */
807 bool asn1_check_enumerated(struct asn1_data *data, int v)
810 if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
811 asn1_read_uint8(data, &b);
815 data->has_error = false;
817 return !data->has_error;
820 /* write an enumerated value to the stream */
821 bool asn1_write_enumerated(struct asn1_data *data, uint8_t v)
823 if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false;
824 asn1_write_uint8(data, v);
826 return !data->has_error;
830 Get us the data just written without copying
832 bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob)
834 if (asn1->has_error) {
837 if (asn1->nesting != NULL) {
840 blob->data = asn1->data;
841 blob->length = asn1->length;
846 Fill in an asn1 struct without making a copy
848 void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len)