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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* free an asn1 structure */
24 void asn1_free(ASN1_DATA *data)
26 talloc_free(data->data);
29 /* write to the ASN1 buffer, advancing the buffer pointer */
30 BOOL asn1_write(ASN1_DATA *data, const void *p, int len)
32 if (data->has_error) return False;
33 if (data->length < data->ofs+len) {
35 newp = talloc_realloc(NULL, data->data, data->ofs+len);
38 data->has_error = True;
42 data->length = data->ofs+len;
44 memcpy(data->data + data->ofs, p, len);
49 /* useful fn for writing a uint8_t */
50 BOOL asn1_write_uint8(ASN1_DATA *data, uint8_t v)
52 return asn1_write(data, &v, 1);
55 /* push a tag onto the asn1 data buffer. Used for nested structures */
56 BOOL asn1_push_tag(ASN1_DATA *data, uint8_t tag)
58 struct nesting *nesting;
60 asn1_write_uint8(data, tag);
61 nesting = talloc_p(NULL, struct nesting);
63 data->has_error = True;
67 nesting->start = data->ofs;
68 nesting->next = data->nesting;
69 data->nesting = nesting;
70 return asn1_write_uint8(data, 0xff);
74 BOOL asn1_pop_tag(ASN1_DATA *data)
76 struct nesting *nesting;
79 nesting = data->nesting;
82 data->has_error = True;
85 len = data->ofs - (nesting->start+1);
86 /* yes, this is ugly. We don't know in advance how many bytes the length
87 of a tag will take, so we assumed 1 byte. If we were wrong then we
88 need to correct our mistake */
90 data->data[nesting->start] = 0x82;
91 if (!asn1_write_uint8(data, 0)) return False;
92 if (!asn1_write_uint8(data, 0)) return False;
93 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
94 data->data[nesting->start+1] = len>>8;
95 data->data[nesting->start+2] = len&0xff;
96 } else if (len > 127) {
97 data->data[nesting->start] = 0x81;
98 if (!asn1_write_uint8(data, 0)) return False;
99 memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
100 data->data[nesting->start+1] = len;
102 data->data[nesting->start] = len;
105 data->nesting = nesting->next;
106 talloc_free(nesting);
110 /* "i" is the one's complement representation, as is the normal result of an
111 * implicit signed->unsigned conversion */
113 static BOOL push_int_bigendian(ASN1_DATA *data, unsigned int i, BOOL negative)
115 uint8_t lowest = i & 0xFF;
119 if (!push_int_bigendian(data, i, negative))
122 if (data->nesting->start+1 == data->ofs) {
124 /* We did not write anything yet, looking at the highest
128 /* Don't write leading 0xff's */
132 if ((lowest & 0x80) == 0) {
133 /* The only exception for a leading 0xff is if
134 * the highest bit is 0, which would indicate
135 * a positive value */
136 if (!asn1_write_uint8(data, 0xff))
141 /* The highest bit of a positive integer is 1,
142 * this would indicate a negative number. Push
143 * a 0 to indicate a positive one */
144 if (!asn1_write_uint8(data, 0))
150 return asn1_write_uint8(data, lowest);
153 /* write an Integer without the tag framing. Needed for example for the LDAP
154 * Abandon Operation */
156 BOOL asn1_write_implicit_Integer(ASN1_DATA *data, int i)
159 /* -1 is special as it consists of all-0xff bytes. In
160 push_int_bigendian this is the only case that is not
161 properly handled, as all 0xff bytes would be handled as
162 leading ones to be ignored. */
163 return asn1_write_uint8(data, 0xff);
165 return push_int_bigendian(data, i, i<0);
170 /* write an integer */
171 BOOL asn1_write_Integer(ASN1_DATA *data, int i)
173 if (!asn1_push_tag(data, ASN1_INTEGER)) return False;
174 if (!asn1_write_implicit_Integer(data, i)) return False;
175 return asn1_pop_tag(data);
178 /* write an object ID to a ASN1 buffer */
179 BOOL asn1_write_OID(ASN1_DATA *data, const char *OID)
182 const char *p = (const char *)OID;
185 if (!asn1_push_tag(data, ASN1_OID))
187 v = strtol(p, &newp, 10);
189 v2 = strtol(p, &newp, 10);
191 if (!asn1_write_uint8(data, 40*v + v2))
195 v = strtol(p, &newp, 10);
197 if (v >= (1<<28)) asn1_write_uint8(data, 0x80 | ((v>>28)&0xff));
198 if (v >= (1<<21)) asn1_write_uint8(data, 0x80 | ((v>>21)&0xff));
199 if (v >= (1<<14)) asn1_write_uint8(data, 0x80 | ((v>>14)&0xff));
200 if (v >= (1<<7)) asn1_write_uint8(data, 0x80 | ((v>>7)&0xff));
201 if (!asn1_write_uint8(data, v&0x7f))
204 return asn1_pop_tag(data);
207 /* write an octet string */
208 BOOL asn1_write_OctetString(ASN1_DATA *data, const void *p, size_t length)
210 asn1_push_tag(data, ASN1_OCTET_STRING);
211 asn1_write(data, p, length);
213 return !data->has_error;
216 /* write a general string */
217 BOOL asn1_write_GeneralString(ASN1_DATA *data, const char *s)
219 asn1_push_tag(data, ASN1_GENERAL_STRING);
220 asn1_write(data, s, strlen(s));
222 return !data->has_error;
225 BOOL asn1_write_ContextSimple(ASN1_DATA *data, uint8_t num, DATA_BLOB *blob)
227 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num));
228 asn1_write(data, blob->data, blob->length);
230 return !data->has_error;
233 /* write a BOOLEAN */
234 BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
236 asn1_push_tag(data, ASN1_BOOLEAN);
237 asn1_write_uint8(data, v ? 0xFF : 0);
239 return !data->has_error;
242 BOOL asn1_read_BOOLEAN(ASN1_DATA *data, BOOL *v)
244 asn1_start_tag(data, ASN1_BOOLEAN);
245 asn1_read_uint8(data, (uint8 *)v);
247 return !data->has_error;
250 /* check a BOOLEAN */
251 BOOL asn1_check_BOOLEAN(ASN1_DATA *data, BOOL v)
255 asn1_read_uint8(data, &b);
256 if (b != ASN1_BOOLEAN) {
257 data->has_error = True;
260 asn1_read_uint8(data, &b);
262 data->has_error = True;
265 return !data->has_error;
269 /* load a ASN1_DATA structure with a lump of data, ready to be parsed */
270 BOOL asn1_load(ASN1_DATA *data, DATA_BLOB blob)
273 data->data = talloc_memdup(NULL, blob.data, blob.length);
275 data->has_error = True;
278 data->length = blob.length;
282 /* Peek into an ASN1 buffer, not advancing the pointer */
283 BOOL asn1_peek(ASN1_DATA *data, void *p, int len)
285 if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
288 if (data->ofs + len > data->length)
291 memcpy(p, data->data + data->ofs, len);
295 /* read from a ASN1 buffer, advancing the buffer pointer */
296 BOOL asn1_read(ASN1_DATA *data, void *p, int len)
298 if (!asn1_peek(data, p, len)) {
299 data->has_error = True;
307 /* read a uint8_t from a ASN1 buffer */
308 BOOL asn1_read_uint8(ASN1_DATA *data, uint8_t *v)
310 return asn1_read(data, v, 1);
313 BOOL asn1_peek_uint8(ASN1_DATA *data, uint8_t *v)
315 return asn1_peek(data, v, 1);
318 BOOL asn1_peek_tag(ASN1_DATA *data, uint8_t tag)
322 if (asn1_tag_remaining(data) <= 0) {
326 if (!asn1_peek(data, &b, sizeof(b)))
332 /* start reading a nested asn1 structure */
333 BOOL asn1_start_tag(ASN1_DATA *data, uint8_t tag)
336 struct nesting *nesting;
338 if (!asn1_read_uint8(data, &b))
342 data->has_error = True;
345 nesting = talloc_p(NULL, struct nesting);
347 data->has_error = True;
351 if (!asn1_read_uint8(data, &b)) {
357 if (!asn1_read_uint8(data, &b))
361 if (!asn1_read_uint8(data, &b))
363 nesting->taglen = (nesting->taglen << 8) | b;
369 nesting->start = data->ofs;
370 nesting->next = data->nesting;
371 data->nesting = nesting;
372 return !data->has_error;
375 static BOOL read_one_uint8(int sock, uint8_t *result, ASN1_DATA *data,
376 const struct timeval *endtime)
378 if (read_data_until(sock, result, 1, endtime) != 1)
381 return asn1_write(data, result, 1);
384 /* Read a complete ASN sequence (ie LDAP result) from a socket */
385 BOOL asn1_read_sequence_until(int sock, ASN1_DATA *data,
386 const struct timeval *endtime)
394 if (!read_one_uint8(sock, &b, data, endtime))
398 data->has_error = True;
402 if (!read_one_uint8(sock, &b, data, endtime))
407 if (!read_one_uint8(sock, &b, data, endtime))
411 if (!read_one_uint8(sock, &b, data, endtime))
420 buf = talloc(NULL, len);
424 if (read_data_until(sock, buf, len, endtime) != len)
427 if (!asn1_write(data, buf, len))
437 /* Get the length to be expected in buf */
438 BOOL asn1_object_length(uint8_t *buf, size_t buf_length,
439 uint8_t tag, size_t *result)
443 /* Fake the asn1_load to avoid the memdup, this is just to be able to
444 * re-use the length-reading in asn1_start_tag */
447 data.length = buf_length;
448 if (!asn1_start_tag(&data, tag))
450 *result = asn1_tag_remaining(&data)+data.ofs;
451 /* We can't use asn1_end_tag here, as we did not consume the complete
452 * tag, so asn1_end_tag would flag an error and not free nesting */
453 talloc_free(data.nesting);
457 /* stop reading a tag */
458 BOOL asn1_end_tag(ASN1_DATA *data)
460 struct nesting *nesting;
462 /* make sure we read it all */
463 if (asn1_tag_remaining(data) != 0) {
464 data->has_error = True;
468 nesting = data->nesting;
471 data->has_error = True;
475 data->nesting = nesting->next;
476 talloc_free(nesting);
480 /* work out how many bytes are left in this nested tag */
481 int asn1_tag_remaining(ASN1_DATA *data)
483 if (!data->nesting) {
484 data->has_error = True;
487 return data->nesting->taglen - (data->ofs - data->nesting->start);
490 /* read an object ID from a ASN1 buffer */
491 BOOL asn1_read_OID(ASN1_DATA *data, char **OID)
494 char *tmp_oid = NULL;
496 if (!asn1_start_tag(data, ASN1_OID)) return False;
497 asn1_read_uint8(data, &b);
499 tmp_oid = talloc_asprintf(NULL, "%u", b/40);
500 tmp_oid = talloc_asprintf_append(tmp_oid, " %u", b%40);
502 while (!data->has_error && asn1_tag_remaining(data) > 0) {
505 asn1_read_uint8(data, &b);
506 v = (v<<7) | (b&0x7f);
507 } while (!data->has_error && b & 0x80);
508 tmp_oid = talloc_asprintf_append(tmp_oid, " %u", v);
513 *OID = talloc_strdup(NULL, tmp_oid);
514 talloc_free(tmp_oid);
516 return (*OID && !data->has_error);
519 /* check that the next object ID is correct */
520 BOOL asn1_check_OID(ASN1_DATA *data, const char *OID)
524 if (!asn1_read_OID(data, &id)) return False;
526 if (strcmp(id, OID) != 0) {
527 data->has_error = True;
534 /* read a GeneralString from a ASN1 buffer */
535 BOOL asn1_read_GeneralString(ASN1_DATA *data, char **s)
538 if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return False;
539 len = asn1_tag_remaining(data);
541 data->has_error = True;
544 *s = talloc(NULL, len+1);
546 data->has_error = True;
549 asn1_read(data, *s, len);
552 return !data->has_error;
555 /* read a octet string blob */
556 BOOL asn1_read_OctetString(ASN1_DATA *data, DATA_BLOB *blob)
560 if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return False;
561 len = asn1_tag_remaining(data);
563 data->has_error = True;
566 *blob = data_blob(NULL, len);
567 asn1_read(data, blob->data, len);
570 if (data->has_error) {
571 data_blob_free(blob);
572 *blob = data_blob(NULL, 0);
578 BOOL asn1_read_ContextSimple(ASN1_DATA *data, uint8_t num, DATA_BLOB *blob)
582 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return False;
583 len = asn1_tag_remaining(data);
585 data->has_error = True;
588 *blob = data_blob(NULL, len);
589 asn1_read(data, blob->data, len);
591 return !data->has_error;
594 /* read an interger without tag*/
595 BOOL asn1_read_implicit_Integer(ASN1_DATA *data, int *i)
600 while (asn1_tag_remaining(data)>0) {
601 if (!asn1_read_uint8(data, &b)) return False;
604 return !data->has_error;
608 /* read an interger */
609 BOOL asn1_read_Integer(ASN1_DATA *data, int *i)
613 if (!asn1_start_tag(data, ASN1_INTEGER)) return False;
614 if (!asn1_read_implicit_Integer(data, i)) return False;
615 return asn1_end_tag(data);
619 /* read an interger */
620 BOOL asn1_read_enumerated(ASN1_DATA *data, int *v)
624 if (!asn1_start_tag(data, ASN1_ENUMERATED)) return False;
625 while (asn1_tag_remaining(data)>0) {
627 asn1_read_uint8(data, &b);
630 return asn1_end_tag(data);
633 /* check a enumarted value is correct */
634 BOOL asn1_check_enumerated(ASN1_DATA *data, int v)
637 if (!asn1_start_tag(data, ASN1_ENUMERATED)) return False;
638 asn1_read_uint8(data, &b);
642 data->has_error = False;
644 return !data->has_error;
647 /* write an enumarted value to the stream */
648 BOOL asn1_write_enumerated(ASN1_DATA *data, uint8_t v)
650 if (!asn1_push_tag(data, ASN1_ENUMERATED)) return False;
651 asn1_write_uint8(data, v);
653 return !data->has_error;