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