nwrap: Fix resolving hostnames with a trailing dot.
[sfrench/samba-autobuild/.git] / lib / util / asn1.c
1 /* 
2    Unix SMB/CIFS implementation.
3    simple ASN1 routines
4    Copyright (C) Andrew Tridgell 2001
5    
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.
10    
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.
15    
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/>.
18 */
19
20 #include "includes.h"
21 #include "../lib/util/asn1.h"
22
23 /* allocate an asn1 structure */
24 struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx)
25 {
26         struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data);
27         if (ret == NULL) {
28                 DEBUG(0,("asn1_init failed! out of memory\n"));
29         }
30         return ret;
31 }
32
33 /* free an asn1 structure */
34 void asn1_free(struct asn1_data *data)
35 {
36         talloc_free(data);
37 }
38
39 /* write to the ASN1 buffer, advancing the buffer pointer */
40 bool asn1_write(struct asn1_data *data, const void *p, int len)
41 {
42         if (data->has_error) return false;
43         if (data->length < data->ofs+len) {
44                 uint8_t *newp;
45                 newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len);
46                 if (!newp) {
47                         data->has_error = true;
48                         return false;
49                 }
50                 data->data = newp;
51                 data->length = data->ofs+len;
52         }
53         memcpy(data->data + data->ofs, p, len);
54         data->ofs += len;
55         return true;
56 }
57
58 /* useful fn for writing a uint8_t */
59 bool asn1_write_uint8(struct asn1_data *data, uint8_t v)
60 {
61         return asn1_write(data, &v, 1);
62 }
63
64 /* push a tag onto the asn1 data buffer. Used for nested structures */
65 bool asn1_push_tag(struct asn1_data *data, uint8_t tag)
66 {
67         struct nesting *nesting;
68
69         asn1_write_uint8(data, tag);
70         nesting = talloc(data, struct nesting);
71         if (!nesting) {
72                 data->has_error = true;
73                 return false;
74         }
75
76         nesting->start = data->ofs;
77         nesting->next = data->nesting;
78         data->nesting = nesting;
79         return asn1_write_uint8(data, 0xff);
80 }
81
82 /* pop a tag */
83 bool asn1_pop_tag(struct asn1_data *data)
84 {
85         struct nesting *nesting;
86         size_t len;
87
88         nesting = data->nesting;
89
90         if (!nesting) {
91                 data->has_error = true;
92                 return false;
93         }
94         len = data->ofs - (nesting->start+1);
95         /* yes, this is ugly. We don't know in advance how many bytes the length
96            of a tag will take, so we assumed 1 byte. If we were wrong then we 
97            need to correct our mistake */
98         if (len > 0xFFFFFF) {
99                 data->data[nesting->start] = 0x84;
100                 if (!asn1_write_uint8(data, 0)) return false;
101                 if (!asn1_write_uint8(data, 0)) return false;
102                 if (!asn1_write_uint8(data, 0)) return false;
103                 if (!asn1_write_uint8(data, 0)) return false;
104                 memmove(data->data+nesting->start+5, data->data+nesting->start+1, len);
105                 data->data[nesting->start+1] = (len>>24) & 0xFF;
106                 data->data[nesting->start+2] = (len>>16) & 0xFF;
107                 data->data[nesting->start+3] = (len>>8) & 0xFF;
108                 data->data[nesting->start+4] = len&0xff;
109         } else if (len > 0xFFFF) {
110                 data->data[nesting->start] = 0x83;
111                 if (!asn1_write_uint8(data, 0)) return false;
112                 if (!asn1_write_uint8(data, 0)) return false;
113                 if (!asn1_write_uint8(data, 0)) return false;
114                 memmove(data->data+nesting->start+4, data->data+nesting->start+1, len);
115                 data->data[nesting->start+1] = (len>>16) & 0xFF;
116                 data->data[nesting->start+2] = (len>>8) & 0xFF;
117                 data->data[nesting->start+3] = len&0xff;
118         } else if (len > 255) {
119                 data->data[nesting->start] = 0x82;
120                 if (!asn1_write_uint8(data, 0)) return false;
121                 if (!asn1_write_uint8(data, 0)) return false;
122                 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
123                 data->data[nesting->start+1] = len>>8;
124                 data->data[nesting->start+2] = len&0xff;
125         } else if (len > 127) {
126                 data->data[nesting->start] = 0x81;
127                 if (!asn1_write_uint8(data, 0)) return false;
128                 memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);
129                 data->data[nesting->start+1] = len;
130         } else {
131                 data->data[nesting->start] = len;
132         }
133
134         data->nesting = nesting->next;
135         talloc_free(nesting);
136         return true;
137 }
138
139 /* "i" is the one's complement representation, as is the normal result of an
140  * implicit signed->unsigned conversion */
141
142 static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative)
143 {
144         uint8_t lowest = i & 0xFF;
145
146         i = i >> 8;
147         if (i != 0)
148                 if (!push_int_bigendian(data, i, negative))
149                         return false;
150
151         if (data->nesting->start+1 == data->ofs) {
152
153                 /* We did not write anything yet, looking at the highest
154                  * valued byte */
155
156                 if (negative) {
157                         /* Don't write leading 0xff's */
158                         if (lowest == 0xFF)
159                                 return true;
160
161                         if ((lowest & 0x80) == 0) {
162                                 /* The only exception for a leading 0xff is if
163                                  * the highest bit is 0, which would indicate
164                                  * a positive value */
165                                 if (!asn1_write_uint8(data, 0xff))
166                                         return false;
167                         }
168                 } else {
169                         if (lowest & 0x80) {
170                                 /* The highest bit of a positive integer is 1,
171                                  * this would indicate a negative number. Push
172                                  * a 0 to indicate a positive one */
173                                 if (!asn1_write_uint8(data, 0))
174                                         return false;
175                         }
176                 }
177         }
178
179         return asn1_write_uint8(data, lowest);
180 }
181
182 /* write an Integer without the tag framing. Needed for example for the LDAP
183  * Abandon Operation */
184
185 bool asn1_write_implicit_Integer(struct asn1_data *data, int i)
186 {
187         if (i == -1) {
188                 /* -1 is special as it consists of all-0xff bytes. In
189                     push_int_bigendian this is the only case that is not
190                     properly handled, as all 0xff bytes would be handled as
191                     leading ones to be ignored. */
192                 return asn1_write_uint8(data, 0xff);
193         } else {
194                 return push_int_bigendian(data, i, i<0);
195         }
196 }
197
198
199 /* write an integer */
200 bool asn1_write_Integer(struct asn1_data *data, int i)
201 {
202         if (!asn1_push_tag(data, ASN1_INTEGER)) return false;
203         if (!asn1_write_implicit_Integer(data, i)) return false;
204         return asn1_pop_tag(data);
205 }
206
207 /* write a BIT STRING */
208 bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding)
209 {
210         if (!asn1_push_tag(data, ASN1_BIT_STRING)) return false;
211         if (!asn1_write_uint8(data, padding)) return false;
212         if (!asn1_write(data, p, length)) return false;
213         return asn1_pop_tag(data);
214 }
215
216 bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID)
217 {
218         unsigned int v, v2;
219         const char *p = (const char *)OID;
220         char *newp;
221         int i;
222
223         if (!isdigit(*p)) return false;
224         v = strtoul(p, &newp, 10);
225         if (newp[0] != '.') return false;
226         p = newp + 1;
227
228         if (!isdigit(*p)) return false;
229         v2 = strtoul(p, &newp, 10);
230         if (newp[0] != '.') return false;
231         p = newp + 1;
232
233         /*the ber representation can't use more space then the string one */
234         *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID));
235         if (!blob->data) return false;
236
237         blob->data[0] = 40*v + v2;
238
239         i = 1;
240         while (*p) {
241                 if (!isdigit(*p)) return false;
242                 v = strtoul(p, &newp, 10);
243                 if (newp[0] == '.') {
244                         p = newp + 1;
245                         /* check for empty last component */
246                         if (!*p) return false;
247                 } else if (newp[0] == '\0') {
248                         p = newp;
249                 } else {
250                         data_blob_free(blob);
251                         return false;
252                 }
253                 if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f));
254                 if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f));
255                 if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f));
256                 if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f));
257                 blob->data[i++] = (v&0x7f);
258         }
259
260         blob->length = i;
261
262         return true;
263 }
264
265 /**
266  * Serialize partial OID string.
267  * Partial OIDs are in the form:
268  *   1:2.5.6:0x81
269  *   1:2.5.6:0x8182
270  */
271 bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid)
272 {
273         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
274         char *oid = talloc_strdup(tmp_ctx, partial_oid);
275         char *p;
276
277         /* truncate partial part so ber_write_OID_String() works */
278         p = strchr(oid, ':');
279         if (p) {
280                 *p = '\0';
281                 p++;
282         }
283
284         if (!ber_write_OID_String(mem_ctx, blob, oid)) {
285                 talloc_free(tmp_ctx);
286                 return false;
287         }
288
289         /* Add partially encoded sub-identifier */
290         if (p) {
291                 DATA_BLOB tmp_blob = strhex_to_data_blob(tmp_ctx, p);
292                 if (!data_blob_append(mem_ctx, blob, tmp_blob.data,
293                                       tmp_blob.length)) {
294                         talloc_free(tmp_ctx);
295                         return false;
296                 }
297         }
298
299         talloc_free(tmp_ctx);
300
301         return true;
302 }
303
304 /* write an object ID to a ASN1 buffer */
305 bool asn1_write_OID(struct asn1_data *data, const char *OID)
306 {
307         DATA_BLOB blob;
308
309         if (!asn1_push_tag(data, ASN1_OID)) return false;
310
311         if (!ber_write_OID_String(NULL, &blob, OID)) {
312                 data->has_error = true;
313                 return false;
314         }
315
316         if (!asn1_write(data, blob.data, blob.length)) {
317                 data_blob_free(&blob);
318                 data->has_error = true;
319                 return false;
320         }
321         data_blob_free(&blob);
322         return asn1_pop_tag(data);
323 }
324
325 /* write an octet string */
326 bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length)
327 {
328         if (!asn1_push_tag(data, ASN1_OCTET_STRING)) return false;
329         if (!asn1_write(data, p, length)) return false;
330         return asn1_pop_tag(data);
331 }
332
333 /* write a LDAP string */
334 bool asn1_write_LDAPString(struct asn1_data *data, const char *s)
335 {
336         return asn1_write(data, s, strlen(s));
337 }
338
339 /* write a LDAP string from a DATA_BLOB */
340 bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s)
341 {
342         return asn1_write(data, s->data, s->length);
343 }
344
345 /* write a general string */
346 bool asn1_write_GeneralString(struct asn1_data *data, const char *s)
347 {
348         if (!asn1_push_tag(data, ASN1_GENERAL_STRING)) return false;
349         if (!asn1_write_LDAPString(data, s)) return false;
350         return asn1_pop_tag(data);
351 }
352
353 bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
354 {
355         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
356         if (!asn1_write(data, blob->data, blob->length)) return false;
357         return asn1_pop_tag(data);
358 }
359
360 /* write a BOOLEAN */
361 bool asn1_write_BOOLEAN(struct asn1_data *data, bool v)
362 {
363         if (!asn1_push_tag(data, ASN1_BOOLEAN)) return false;
364         if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false;
365         return asn1_pop_tag(data);
366 }
367
368 bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v)
369 {
370         uint8_t tmp = 0;
371         if (!asn1_start_tag(data, ASN1_BOOLEAN)) return false;
372         *v = false;
373         if (!asn1_read_uint8(data, &tmp)) return false;
374         if (tmp == 0xFF) {
375                 *v = true;
376         }
377         return asn1_end_tag(data);
378 }
379
380 /* write a BOOLEAN in a simple context */
381 bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context)
382 {
383         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false;
384         if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false;
385         return asn1_pop_tag(data);
386 }
387
388 bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context)
389 {
390         uint8_t tmp = 0;
391         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false;
392         *v = false;
393         if (!asn1_read_uint8(data, &tmp)) return false;
394         if (tmp == 0xFF) {
395                 *v = true;
396         }
397         return asn1_end_tag(data);
398 }
399
400 /* check a BOOLEAN */
401 bool asn1_check_BOOLEAN(struct asn1_data *data, bool v)
402 {
403         uint8_t b = 0;
404
405         if (!asn1_read_uint8(data, &b)) return false;
406         if (b != ASN1_BOOLEAN) {
407                 data->has_error = true;
408                 return false;
409         }
410         if (!asn1_read_uint8(data, &b)) return false;
411         if (b != v) {
412                 data->has_error = true;
413                 return false;
414         }
415         return !data->has_error;
416 }
417
418
419 /* load a struct asn1_data structure with a lump of data, ready to be parsed */
420 bool asn1_load(struct asn1_data *data, DATA_BLOB blob)
421 {
422         ZERO_STRUCTP(data);
423         data->data = (uint8_t *)talloc_memdup(data, blob.data, blob.length);
424         if (!data->data) {
425                 data->has_error = true;
426                 return false;
427         }
428         data->length = blob.length;
429         return true;
430 }
431
432 /* Peek into an ASN1 buffer, not advancing the pointer */
433 bool asn1_peek(struct asn1_data *data, void *p, int len)
434 {
435         if (data->has_error)
436                 return false;
437
438         if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
439                 return false;
440
441         if (data->ofs + len > data->length) {
442                 /* we need to mark the buffer as consumed, so the caller knows
443                    this was an out of data error, and not a decode error */
444                 data->ofs = data->length;
445                 return false;
446         }
447
448         memcpy(p, data->data + data->ofs, len);
449         return true;
450 }
451
452 /* read from a ASN1 buffer, advancing the buffer pointer */
453 bool asn1_read(struct asn1_data *data, void *p, int len)
454 {
455         if (!asn1_peek(data, p, len)) {
456                 data->has_error = true;
457                 return false;
458         }
459
460         data->ofs += len;
461         return true;
462 }
463
464 /* read a uint8_t from a ASN1 buffer */
465 bool asn1_read_uint8(struct asn1_data *data, uint8_t *v)
466 {
467         return asn1_read(data, v, 1);
468 }
469
470 bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v)
471 {
472         return asn1_peek(data, v, 1);
473 }
474
475 bool asn1_peek_tag(struct asn1_data *data, uint8_t tag)
476 {
477         uint8_t b;
478
479         if (asn1_tag_remaining(data) <= 0) {
480                 return false;
481         }
482
483         if (!asn1_peek_uint8(data, &b))
484                 return false;
485
486         return (b == tag);
487 }
488
489 /*
490  * just get the needed size the tag would consume
491  */
492 bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, size_t *size)
493 {
494         off_t start_ofs = data->ofs;
495         uint8_t b;
496         size_t taglen = 0;
497
498         if (data->has_error) {
499                 return false;
500         }
501
502         if (!asn1_read_uint8(data, &b)) {
503                 data->ofs = start_ofs;
504                 data->has_error = false;
505                 return false;
506         }
507
508         if (b != tag) {
509                 data->ofs = start_ofs;
510                 data->has_error = false;
511                 return false;
512         }
513
514         if (!asn1_read_uint8(data, &b)) {
515                 data->ofs = start_ofs;
516                 data->has_error = false;
517                 return false;
518         }
519
520         if (b & 0x80) {
521                 int n = b & 0x7f;
522                 if (!asn1_read_uint8(data, &b)) {
523                         data->ofs = start_ofs;
524                         data->has_error = false;
525                         return false;
526                 }
527                 if (n > 4) {
528                         /*
529                          * We should not allow more than 4 bytes
530                          * for the encoding of the tag length.
531                          *
532                          * Otherwise we'd overflow the taglen
533                          * variable on 32 bit systems.
534                          */
535                         data->ofs = start_ofs;
536                         data->has_error = false;
537                         return false;
538                 }
539                 taglen = b;
540                 while (n > 1) {
541                         if (!asn1_read_uint8(data, &b)) {
542                                 data->ofs = start_ofs;
543                                 data->has_error = false;
544                                 return false;
545                         }
546                         taglen = (taglen << 8) | b;
547                         n--;
548                 }
549         } else {
550                 taglen = b;
551         }
552
553         *size = (data->ofs - start_ofs) + taglen;
554
555         data->ofs = start_ofs;
556         data->has_error = false;
557         return true;
558 }
559
560 /* start reading a nested asn1 structure */
561 bool asn1_start_tag(struct asn1_data *data, uint8_t tag)
562 {
563         uint8_t b;
564         struct nesting *nesting;
565         
566         if (!asn1_read_uint8(data, &b))
567                 return false;
568
569         if (b != tag) {
570                 data->has_error = true;
571                 return false;
572         }
573         nesting = talloc(data, struct nesting);
574         if (!nesting) {
575                 data->has_error = true;
576                 return false;
577         }
578
579         if (!asn1_read_uint8(data, &b)) {
580                 return false;
581         }
582
583         if (b & 0x80) {
584                 int n = b & 0x7f;
585                 if (!asn1_read_uint8(data, &b))
586                         return false;
587                 nesting->taglen = b;
588                 while (n > 1) {
589                         if (!asn1_read_uint8(data, &b)) 
590                                 return false;
591                         nesting->taglen = (nesting->taglen << 8) | b;
592                         n--;
593                 }
594         } else {
595                 nesting->taglen = b;
596         }
597         nesting->start = data->ofs;
598         nesting->next = data->nesting;
599         data->nesting = nesting;
600         if (asn1_tag_remaining(data) == -1) {
601                 return false;
602         }
603         return !data->has_error;
604 }
605
606 /* stop reading a tag */
607 bool asn1_end_tag(struct asn1_data *data)
608 {
609         struct nesting *nesting;
610
611         /* make sure we read it all */
612         if (asn1_tag_remaining(data) != 0) {
613                 data->has_error = true;
614                 return false;
615         }
616
617         nesting = data->nesting;
618
619         if (!nesting) {
620                 data->has_error = true;
621                 return false;
622         }
623
624         data->nesting = nesting->next;
625         talloc_free(nesting);
626         return true;
627 }
628
629 /* work out how many bytes are left in this nested tag */
630 int asn1_tag_remaining(struct asn1_data *data)
631 {
632         int remaining;
633         if (data->has_error) {
634                 return -1;
635         }
636
637         if (!data->nesting) {
638                 data->has_error = true;
639                 return -1;
640         }
641         remaining = data->nesting->taglen - (data->ofs - data->nesting->start);
642         if (remaining > (data->length - data->ofs)) {
643                 data->has_error = true;
644                 return -1;
645         }
646         return remaining;
647 }
648
649 /**
650  * Internal implementation for reading binary OIDs
651  * Reading is done as far in the buffer as valid OID
652  * till buffer ends or not valid sub-identifier is found.
653  */
654 static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
655                                       char **OID, size_t *bytes_eaten)
656 {
657         int i;
658         uint8_t *b;
659         unsigned int v;
660         char *tmp_oid = NULL;
661
662         if (blob.length < 2) return false;
663
664         b = blob.data;
665
666         tmp_oid = talloc_asprintf(mem_ctx, "%u",  b[0]/40);
667         if (!tmp_oid) goto nomem;
668         tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  b[0]%40);
669         if (!tmp_oid) goto nomem;
670
671         if (bytes_eaten != NULL) {
672                 *bytes_eaten = 0;
673         }
674
675         for(i = 1, v = 0; i < blob.length; i++) {
676                 v = (v<<7) | (b[i]&0x7f);
677                 if ( ! (b[i] & 0x80)) {
678                         tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u",  v);
679                         v = 0;
680                         if (bytes_eaten)
681                                 *bytes_eaten = i+1;
682                 }
683                 if (!tmp_oid) goto nomem;
684         }
685
686         *OID = tmp_oid;
687         return true;
688
689 nomem:
690         return false;
691 }
692
693 /* read an object ID from a data blob */
694 bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID)
695 {
696         size_t bytes_eaten;
697
698         if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten))
699                 return false;
700
701         return (bytes_eaten == blob.length);
702 }
703
704 /**
705  * Deserialize partial OID string.
706  * Partial OIDs are in the form:
707  *   1:2.5.6:0x81
708  *   1:2.5.6:0x8182
709  */
710 bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob,
711                                  char **partial_oid)
712 {
713         size_t bytes_left;
714         size_t bytes_eaten;
715         char *identifier = NULL;
716         char *tmp_oid = NULL;
717
718         if (!_ber_read_OID_String_impl(mem_ctx, blob, &tmp_oid, &bytes_eaten))
719                 return false;
720
721         if (bytes_eaten < blob.length) {
722                 bytes_left = blob.length - bytes_eaten;
723                 identifier = hex_encode_talloc(mem_ctx, &blob.data[bytes_eaten], bytes_left);
724                 if (!identifier)        goto nomem;
725
726                 *partial_oid = talloc_asprintf_append_buffer(tmp_oid, ":0x%s", identifier);
727                 if (!*partial_oid)      goto nomem;
728                 TALLOC_FREE(identifier);
729         } else {
730                 *partial_oid = tmp_oid;
731         }
732
733         return true;
734
735 nomem:
736         TALLOC_FREE(identifier);
737         TALLOC_FREE(tmp_oid);
738         return false;
739 }
740
741 /* read an object ID from a ASN1 buffer */
742 bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID)
743 {
744         DATA_BLOB blob;
745         int len;
746
747         if (!asn1_start_tag(data, ASN1_OID)) return false;
748
749         len = asn1_tag_remaining(data);
750         if (len < 0) {
751                 data->has_error = true;
752                 return false;
753         }
754
755         blob = data_blob(NULL, len);
756         if (!blob.data) {
757                 data->has_error = true;
758                 return false;
759         }
760
761         if (!asn1_read(data, blob.data, len)) return false;
762         if (!asn1_end_tag(data)) {
763                 data_blob_free(&blob);
764                 return false;
765         }
766
767         if (!ber_read_OID_String(mem_ctx, blob, OID)) {
768                 data->has_error = true;
769                 data_blob_free(&blob);
770                 return false;
771         }
772
773         data_blob_free(&blob);
774         return true;
775 }
776
777 /* check that the next object ID is correct */
778 bool asn1_check_OID(struct asn1_data *data, const char *OID)
779 {
780         char *id;
781
782         if (!asn1_read_OID(data, data, &id)) return false;
783
784         if (strcmp(id, OID) != 0) {
785                 talloc_free(id);
786                 data->has_error = true;
787                 return false;
788         }
789         talloc_free(id);
790         return true;
791 }
792
793 /* read a LDAPString from a ASN1 buffer */
794 bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
795 {
796         int len;
797         len = asn1_tag_remaining(data);
798         if (len < 0) {
799                 data->has_error = true;
800                 return false;
801         }
802         *s = talloc_array(mem_ctx, char, len+1);
803         if (! *s) {
804                 data->has_error = true;
805                 return false;
806         }
807         (*s)[len] = 0;
808         return asn1_read(data, *s, len);
809 }
810
811
812 /* read a GeneralString from a ASN1 buffer */
813 bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s)
814 {
815         if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false;
816         if (!asn1_read_LDAPString(data, mem_ctx, s)) return false;
817         return asn1_end_tag(data);
818 }
819
820
821 /* read a octet string blob */
822 bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
823 {
824         int len;
825         ZERO_STRUCTP(blob);
826         if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false;
827         len = asn1_tag_remaining(data);
828         if (len < 0) {
829                 data->has_error = true;
830                 return false;
831         }
832         *blob = data_blob_talloc(mem_ctx, NULL, len+1);
833         if (!blob->data || blob->length < len) {
834                 data->has_error = true;
835                 return false;
836         }
837         if (!asn1_read(data, blob->data, len)) goto err;
838         if (!asn1_end_tag(data)) goto err;
839         blob->length--;
840         blob->data[len] = 0;
841         return true;
842
843   err:
844
845         data_blob_free(blob);
846         *blob = data_blob_null;
847         return false;
848 }
849
850 bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob)
851 {
852         int len;
853         ZERO_STRUCTP(blob);
854         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false;
855         len = asn1_tag_remaining(data);
856         if (len < 0) {
857                 data->has_error = true;
858                 return false;
859         }
860         *blob = data_blob(NULL, len);
861         if ((len != 0) && (!blob->data)) {
862                 data->has_error = true;
863                 return false;
864         }
865         if (!asn1_read(data, blob->data, len)) return false;
866         return asn1_end_tag(data);
867 }
868
869 /* read an integer without tag*/
870 bool asn1_read_implicit_Integer(struct asn1_data *data, int *i)
871 {
872         uint8_t b;
873         bool first_byte = true;
874         *i = 0;
875
876         while (!data->has_error && asn1_tag_remaining(data)>0) {
877                 if (!asn1_read_uint8(data, &b)) return false;
878                 if (first_byte) {
879                         if (b & 0x80) {
880                                 /* Number is negative.
881                                    Set i to -1 for sign extend. */
882                                 *i = -1;
883                         }
884                         first_byte = false;
885                 }
886                 *i = (*i << 8) + b;
887         }
888         return !data->has_error;        
889         
890 }
891
892 /* read an integer */
893 bool asn1_read_Integer(struct asn1_data *data, int *i)
894 {
895         *i = 0;
896
897         if (!asn1_start_tag(data, ASN1_INTEGER)) return false;
898         if (!asn1_read_implicit_Integer(data, i)) return false;
899         return asn1_end_tag(data);      
900 }
901
902 /* read a BIT STRING */
903 bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding)
904 {
905         int len;
906         ZERO_STRUCTP(blob);
907         if (!asn1_start_tag(data, ASN1_BIT_STRING)) return false;
908         len = asn1_tag_remaining(data);
909         if (len < 0) {
910                 data->has_error = true;
911                 return false;
912         }
913         if (!asn1_read_uint8(data, padding)) return false;
914
915         *blob = data_blob_talloc(mem_ctx, NULL, len+1);
916         if (!blob->data || blob->length < len) {
917                 data->has_error = true;
918                 return false;
919         }
920         if (asn1_read(data, blob->data, len - 1)) {
921                 blob->length--;
922                 blob->data[len] = 0;
923                 asn1_end_tag(data);
924         }
925
926         if (data->has_error) {
927                 data_blob_free(blob);
928                 *blob = data_blob_null;
929                 *padding = 0;
930                 return false;
931         }
932         return true;
933 }
934
935 /* read an integer */
936 bool asn1_read_enumerated(struct asn1_data *data, int *v)
937 {
938         *v = 0;
939         
940         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
941         while (!data->has_error && asn1_tag_remaining(data)>0) {
942                 uint8_t b;
943                 asn1_read_uint8(data, &b);
944                 *v = (*v << 8) + b;
945         }
946         return asn1_end_tag(data);      
947 }
948
949 /* check a enumerated value is correct */
950 bool asn1_check_enumerated(struct asn1_data *data, int v)
951 {
952         uint8_t b;
953         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false;
954         if (!asn1_read_uint8(data, &b)) return false;
955         if (!asn1_end_tag(data)) return false;
956
957         if (v != b)
958                 data->has_error = false;
959
960         return !data->has_error;
961 }
962
963 /* write an enumerated value to the stream */
964 bool asn1_write_enumerated(struct asn1_data *data, uint8_t v)
965 {
966         if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false;
967         if (!asn1_write_uint8(data, v)) return false;
968         return asn1_pop_tag(data);
969 }
970
971 /*
972   Get us the data just written without copying
973 */
974 bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob)
975 {
976         if (asn1->has_error) {
977                 return false;
978         }
979         if (asn1->nesting != NULL) {
980                 return false;
981         }
982         blob->data = asn1->data;
983         blob->length = asn1->length;
984         return true;
985 }
986
987 /*
988   Fill in an asn1 struct without making a copy
989 */
990 void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len)
991 {
992         ZERO_STRUCTP(data);
993         data->data = buf;
994         data->length = len;
995 }
996
997 /*
998   check if a ASN.1 blob is a full tag
999 */
1000 NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
1001 {
1002         struct asn1_data *asn1 = asn1_init(NULL);
1003         int size;
1004
1005         NT_STATUS_HAVE_NO_MEMORY(asn1);
1006
1007         asn1->data = blob.data;
1008         asn1->length = blob.length;
1009         if (!asn1_start_tag(asn1, tag)) {
1010                 talloc_free(asn1);
1011                 return STATUS_MORE_ENTRIES;
1012         }
1013         size = asn1_tag_remaining(asn1) + asn1->ofs;
1014
1015         talloc_free(asn1);
1016
1017         if (size > blob.length) {
1018                 return STATUS_MORE_ENTRIES;
1019         }
1020
1021         *packet_size = size;
1022         return NT_STATUS_OK;
1023 }
1024
1025 NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
1026 {
1027         struct asn1_data asn1;
1028         size_t size;
1029         bool ok;
1030
1031         ZERO_STRUCT(asn1);
1032         asn1.data = blob.data;
1033         asn1.length = blob.length;
1034
1035         ok = asn1_peek_tag_needed_size(&asn1, tag, &size);
1036         if (!ok) {
1037                 return NT_STATUS_INVALID_BUFFER_SIZE;
1038         }
1039
1040         if (size > blob.length) {
1041                 *packet_size = size;
1042                 return STATUS_MORE_ENTRIES;
1043         }               
1044
1045         *packet_size = size;
1046         return NT_STATUS_OK;
1047 }