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.
24 /* free an asn1 structure */
25 void asn1_free(struct asn1_data *data)
27 talloc_free(data->data);
30 /* write to the ASN1 buffer, advancing the buffer pointer */
31 BOOL asn1_write(struct asn1_data *data, const void *p, int len)
33 if (data->has_error) return False;
34 if (data->length < data->ofs+len) {
36 newp = talloc_realloc(NULL, data->data, data->ofs+len);
39 data->has_error = True;
43 data->length = data->ofs+len;
45 memcpy(data->data + data->ofs, p, len);
50 /* useful fn for writing a uint8_t */
51 BOOL asn1_write_uint8(struct asn1_data *data, uint8_t v)
53 return asn1_write(data, &v, 1);
56 /* push a tag onto the asn1 data buffer. Used for nested structures */
57 BOOL asn1_push_tag(struct asn1_data *data, uint8_t tag)
59 struct nesting *nesting;
61 asn1_write_uint8(data, tag);
62 nesting = talloc_p(NULL, struct nesting);
64 data->has_error = True;
68 nesting->start = data->ofs;
69 nesting->next = data->nesting;
70 data->nesting = nesting;
71 return asn1_write_uint8(data, 0xff);
75 BOOL asn1_pop_tag(struct asn1_data *data)
77 struct nesting *nesting;
80 nesting = data->nesting;
83 data->has_error = True;
86 len = data->ofs - (nesting->start+1);
87 /* yes, this is ugly. We don't know in advance how many bytes the length
88 of a tag will take, so we assumed 1 byte. If we were wrong then we
89 need to correct our mistake */
91 data->data[nesting->start] = 0x82;
92 if (!asn1_write_uint8(data, 0)) return False;
93 if (!asn1_write_uint8(data, 0)) return False;
94 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
95 data->data[nesting->start+1] = len>>8;
96 data->data[nesting->start+2] = len&0xff;
97 } else if (len > 127) {
98 data->data[nesting->start] = 0x81;
99 if (!asn1_write_uint8(data, 0)) return False;
100 memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
101 data->data[nesting->start+1] = len;
103 data->data[nesting->start] = len;
106 data->nesting = nesting->next;
107 talloc_free(nesting);
111 /* "i" is the one's complement representation, as is the normal result of an
112 * implicit signed->unsigned conversion */
114 static BOOL push_int_bigendian(struct asn1_data *data, unsigned int i, BOOL negative)
116 uint8_t lowest = i & 0xFF;
120 if (!push_int_bigendian(data, i, negative))
123 if (data->nesting->start+1 == data->ofs) {
125 /* We did not write anything yet, looking at the highest
129 /* Don't write leading 0xff's */
133 if ((lowest & 0x80) == 0) {
134 /* The only exception for a leading 0xff is if
135 * the highest bit is 0, which would indicate
136 * a positive value */
137 if (!asn1_write_uint8(data, 0xff))
142 /* The highest bit of a positive integer is 1,
143 * this would indicate a negative number. Push
144 * a 0 to indicate a positive one */
145 if (!asn1_write_uint8(data, 0))
151 return asn1_write_uint8(data, lowest);
154 /* write an Integer without the tag framing. Needed for example for the LDAP
155 * Abandon Operation */
157 BOOL asn1_write_implicit_Integer(struct asn1_data *data, int i)
160 /* -1 is special as it consists of all-0xff bytes. In
161 push_int_bigendian this is the only case that is not
162 properly handled, as all 0xff bytes would be handled as
163 leading ones to be ignored. */
164 return asn1_write_uint8(data, 0xff);
166 return push_int_bigendian(data, i, i<0);
171 /* write an integer */
172 BOOL asn1_write_Integer(struct asn1_data *data, int i)
174 if (!asn1_push_tag(data, ASN1_INTEGER)) return False;
175 if (!asn1_write_implicit_Integer(data, i)) return False;
176 return asn1_pop_tag(data);
179 /* write an object ID to a ASN1 buffer */
180 BOOL asn1_write_OID(struct asn1_data *data, const char *OID)
183 const char *p = (const char *)OID;
186 if (!asn1_push_tag(data, ASN1_OID))
188 v = strtol(p, &newp, 10);
190 v2 = strtol(p, &newp, 10);
192 if (!asn1_write_uint8(data, 40*v + v2))
196 v = strtol(p, &newp, 10);
198 if (v >= (1<<28)) asn1_write_uint8(data, 0x80 | ((v>>28)&0xff));
199 if (v >= (1<<21)) asn1_write_uint8(data, 0x80 | ((v>>21)&0xff));
200 if (v >= (1<<14)) asn1_write_uint8(data, 0x80 | ((v>>14)&0xff));
201 if (v >= (1<<7)) asn1_write_uint8(data, 0x80 | ((v>>7)&0xff));
202 if (!asn1_write_uint8(data, v&0x7f))
205 return asn1_pop_tag(data);
208 /* write an octet string */
209 BOOL asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length)
211 asn1_push_tag(data, ASN1_OCTET_STRING);
212 asn1_write(data, p, length);
214 return !data->has_error;
217 /* write a general string */
218 BOOL asn1_write_GeneralString(struct asn1_data *data, const char *s)
220 asn1_push_tag(data, ASN1_GENERAL_STRING);
221 asn1_write(data, s, strlen(s));
223 return !data->has_error;
226 BOOL asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
228 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num));
229 asn1_write(data, blob->data, blob->length);
231 return !data->has_error;
234 /* write a BOOLEAN */
235 BOOL asn1_write_BOOLEAN(struct asn1_data *data, BOOL v)
237 asn1_push_tag(data, ASN1_BOOLEAN);
238 asn1_write_uint8(data, v ? 0xFF : 0);
240 return !data->has_error;
243 BOOL asn1_read_BOOLEAN(struct asn1_data *data, BOOL *v)
246 asn1_start_tag(data, ASN1_BOOLEAN);
247 asn1_read_uint8(data, &tmp);
254 return !data->has_error;
257 /* check a BOOLEAN */
258 BOOL asn1_check_BOOLEAN(struct asn1_data *data, BOOL v)
262 asn1_read_uint8(data, &b);
263 if (b != ASN1_BOOLEAN) {
264 data->has_error = True;
267 asn1_read_uint8(data, &b);
269 data->has_error = True;
272 return !data->has_error;
276 /* load a struct asn1_data structure with a lump of data, ready to be parsed */
277 BOOL asn1_load(struct asn1_data *data, DATA_BLOB blob)
280 data->data = talloc_memdup(NULL, blob.data, blob.length);
282 data->has_error = True;
285 data->length = blob.length;
289 /* Peek into an ASN1 buffer, not advancing the pointer */
290 BOOL asn1_peek(struct asn1_data *data, void *p, int len)
292 if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
295 if (data->ofs + len > data->length)
298 memcpy(p, data->data + data->ofs, len);
302 /* read from a ASN1 buffer, advancing the buffer pointer */
303 BOOL asn1_read(struct asn1_data *data, void *p, int len)
305 if (!asn1_peek(data, p, len)) {
306 data->has_error = True;
314 /* read a uint8_t from a ASN1 buffer */
315 BOOL asn1_read_uint8(struct asn1_data *data, uint8_t *v)
317 return asn1_read(data, v, 1);
320 BOOL asn1_peek_uint8(struct asn1_data *data, uint8_t *v)
322 return asn1_peek(data, v, 1);
325 BOOL asn1_peek_tag(struct asn1_data *data, uint8_t tag)
329 if (asn1_tag_remaining(data) <= 0) {
333 if (!asn1_peek(data, &b, sizeof(b)))
339 /* start reading a nested asn1 structure */
340 BOOL asn1_start_tag(struct asn1_data *data, uint8_t tag)
343 struct nesting *nesting;
345 if (!asn1_read_uint8(data, &b))
349 data->has_error = True;
352 nesting = talloc_p(NULL, struct nesting);
354 data->has_error = True;
358 if (!asn1_read_uint8(data, &b)) {
364 if (!asn1_read_uint8(data, &b))
368 if (!asn1_read_uint8(data, &b))
370 nesting->taglen = (nesting->taglen << 8) | b;
376 nesting->start = data->ofs;
377 nesting->next = data->nesting;
378 data->nesting = nesting;
379 return !data->has_error;
382 static BOOL read_one_uint8(int sock, uint8_t *result, struct asn1_data *data,
383 const struct timeval *endtime)
385 if (read_data_until(sock, result, 1, endtime) != 1)
388 return asn1_write(data, result, 1);
391 /* Read a complete ASN sequence (ie LDAP result) from a socket */
392 BOOL asn1_read_sequence_until(int sock, struct asn1_data *data,
393 const struct timeval *endtime)
401 if (!read_one_uint8(sock, &b, data, endtime))
405 data->has_error = True;
409 if (!read_one_uint8(sock, &b, data, endtime))
414 if (!read_one_uint8(sock, &b, data, endtime))
418 if (!read_one_uint8(sock, &b, data, endtime))
427 buf = talloc(NULL, len);
431 if (read_data_until(sock, buf, len, endtime) != len)
434 if (!asn1_write(data, buf, len))
444 /* Get the length to be expected in buf */
445 BOOL asn1_object_length(uint8_t *buf, size_t buf_length,
446 uint8_t tag, size_t *result)
448 struct asn1_data data;
450 /* Fake the asn1_load to avoid the memdup, this is just to be able to
451 * re-use the length-reading in asn1_start_tag */
454 data.length = buf_length;
455 if (!asn1_start_tag(&data, tag))
457 *result = asn1_tag_remaining(&data)+data.ofs;
458 /* We can't use asn1_end_tag here, as we did not consume the complete
459 * tag, so asn1_end_tag would flag an error and not free nesting */
460 talloc_free(data.nesting);
464 /* stop reading a tag */
465 BOOL asn1_end_tag(struct asn1_data *data)
467 struct nesting *nesting;
469 /* make sure we read it all */
470 if (asn1_tag_remaining(data) != 0) {
471 data->has_error = True;
475 nesting = data->nesting;
478 data->has_error = True;
482 data->nesting = nesting->next;
483 talloc_free(nesting);
487 /* work out how many bytes are left in this nested tag */
488 int asn1_tag_remaining(struct asn1_data *data)
490 if (!data->nesting) {
491 data->has_error = True;
494 return data->nesting->taglen - (data->ofs - data->nesting->start);
497 /* read an object ID from a ASN1 buffer */
498 BOOL asn1_read_OID(struct asn1_data *data, const char **OID)
501 char *tmp_oid = NULL;
503 if (!asn1_start_tag(data, ASN1_OID)) return False;
504 asn1_read_uint8(data, &b);
506 tmp_oid = talloc_asprintf(NULL, "%u", b/40);
507 tmp_oid = talloc_asprintf_append(tmp_oid, " %u", b%40);
509 while (!data->has_error && asn1_tag_remaining(data) > 0) {
512 asn1_read_uint8(data, &b);
513 v = (v<<7) | (b&0x7f);
514 } while (!data->has_error && b & 0x80);
515 tmp_oid = talloc_asprintf_append(tmp_oid, " %u", v);
520 *OID = talloc_strdup(NULL, tmp_oid);
521 talloc_free(tmp_oid);
523 return (*OID && !data->has_error);
526 /* check that the next object ID is correct */
527 BOOL asn1_check_OID(struct asn1_data *data, const char *OID)
531 if (!asn1_read_OID(data, &id)) return False;
533 if (strcmp(id, OID) != 0) {
534 data->has_error = True;
537 talloc_free(discard_const(id));
541 /* read a GeneralString from a ASN1 buffer */
542 BOOL asn1_read_GeneralString(struct asn1_data *data, char **s)
545 if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return False;
546 len = asn1_tag_remaining(data);
548 data->has_error = True;
551 *s = talloc(NULL, len+1);
553 data->has_error = True;
556 asn1_read(data, *s, len);
559 return !data->has_error;
562 /* read a octet string blob */
563 BOOL asn1_read_OctetString(struct asn1_data *data, DATA_BLOB *blob)
567 if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return False;
568 len = asn1_tag_remaining(data);
570 data->has_error = True;
573 *blob = data_blob(NULL, len);
574 asn1_read(data, blob->data, len);
577 if (data->has_error) {
578 data_blob_free(blob);
579 *blob = data_blob(NULL, 0);
585 BOOL asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
589 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return False;
590 len = asn1_tag_remaining(data);
592 data->has_error = True;
595 *blob = data_blob(NULL, len);
596 asn1_read(data, blob->data, len);
598 return !data->has_error;
601 /* read an interger without tag*/
602 BOOL asn1_read_implicit_Integer(struct asn1_data *data, int *i)
607 while (asn1_tag_remaining(data)>0) {
608 if (!asn1_read_uint8(data, &b)) return False;
611 return !data->has_error;
615 /* read an interger */
616 BOOL asn1_read_Integer(struct asn1_data *data, int *i)
620 if (!asn1_start_tag(data, ASN1_INTEGER)) return False;
621 if (!asn1_read_implicit_Integer(data, i)) return False;
622 return asn1_end_tag(data);
626 /* read an interger */
627 BOOL asn1_read_enumerated(struct asn1_data *data, int *v)
631 if (!asn1_start_tag(data, ASN1_ENUMERATED)) return False;
632 while (asn1_tag_remaining(data)>0) {
634 asn1_read_uint8(data, &b);
637 return asn1_end_tag(data);
640 /* check a enumarted value is correct */
641 BOOL asn1_check_enumerated(struct asn1_data *data, int v)
644 if (!asn1_start_tag(data, ASN1_ENUMERATED)) return False;
645 asn1_read_uint8(data, &b);
649 data->has_error = False;
651 return !data->has_error;
654 /* write an enumarted value to the stream */
655 BOOL asn1_write_enumerated(struct asn1_data *data, uint8_t v)
657 if (!asn1_push_tag(data, ASN1_ENUMERATED)) return False;
658 asn1_write_uint8(data, v);
660 return !data->has_error;