r2749: add asn1_read_implicit_Integer()
[bbaumbach/samba-autobuild/.git] / source / libcli / util / asn1.c
1 /* 
2    Unix SMB/CIFS implementation.
3    simple SPNEGO 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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /* free an asn1 structure */
24 void asn1_free(ASN1_DATA *data)
25 {
26         talloc_free(data->data);
27 }
28
29 /* write to the ASN1 buffer, advancing the buffer pointer */
30 BOOL asn1_write(ASN1_DATA *data, const void *p, int len)
31 {
32         if (data->has_error) return False;
33         if (data->length < data->ofs+len) {
34                 uint8_t *newp;
35                 newp = talloc_realloc(NULL, data->data, data->ofs+len);
36                 if (!newp) {
37                         asn1_free(data);
38                         data->has_error = True;
39                         return False;
40                 }
41                 data->data = newp;
42                 data->length = data->ofs+len;
43         }
44         memcpy(data->data + data->ofs, p, len);
45         data->ofs += len;
46         return True;
47 }
48
49 /* useful fn for writing a uint8_t */
50 BOOL asn1_write_uint8(ASN1_DATA *data, uint8_t v)
51 {
52         return asn1_write(data, &v, 1);
53 }
54
55 /* push a tag onto the asn1 data buffer. Used for nested structures */
56 BOOL asn1_push_tag(ASN1_DATA *data, uint8_t tag)
57 {
58         struct nesting *nesting;
59
60         asn1_write_uint8(data, tag);
61         nesting = talloc_p(NULL, struct nesting);
62         if (!nesting) {
63                 data->has_error = True;
64                 return False;
65         }
66
67         nesting->start = data->ofs;
68         nesting->next = data->nesting;
69         data->nesting = nesting;
70         return asn1_write_uint8(data, 0xff);
71 }
72
73 /* pop a tag */
74 BOOL asn1_pop_tag(ASN1_DATA *data)
75 {
76         struct nesting *nesting;
77         size_t len;
78
79         nesting = data->nesting;
80
81         if (!nesting) {
82                 data->has_error = True;
83                 return False;
84         }
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 */
89         if (len > 255) {
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;
101         } else {
102                 data->data[nesting->start] = len;
103         }
104
105         data->nesting = nesting->next;
106         talloc_free(nesting);
107         return True;
108 }
109
110 /* "i" is the one's complement representation, as is the normal result of an
111  * implicit signed->unsigned conversion */
112
113 static BOOL push_int_bigendian(ASN1_DATA *data, unsigned int i, BOOL negative)
114 {
115         uint8_t lowest = i & 0xFF;
116
117         i = i >> 8;
118         if (i != 0)
119                 if (!push_int_bigendian(data, i, negative))
120                         return False;
121
122         if (data->nesting->start+1 == data->ofs) {
123
124                 /* We did not write anything yet, looking at the highest
125                  * valued byte */
126
127                 if (negative) {
128                         /* Don't write leading 0xff's */
129                         if (lowest == 0xFF)
130                                 return True;
131
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))
137                                         return False;
138                         }
139                 } else {
140                         if (lowest & 0x80) {
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))
145                                         return False;
146                         }
147                 }
148         }
149
150         return asn1_write_uint8(data, lowest);
151 }
152
153 /* write an Integer without the tag framing. Needed for example for the LDAP
154  * Abandon Operation */
155
156 BOOL asn1_write_implicit_Integer(ASN1_DATA *data, int i)
157 {
158         if (i == -1) {
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);
164         } else {
165                 return push_int_bigendian(data, i, i<0);
166         }
167 }
168
169
170 /* write an integer */
171 BOOL asn1_write_Integer(ASN1_DATA *data, int i)
172 {
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);
176 }
177
178 /* write an object ID to a ASN1 buffer */
179 BOOL asn1_write_OID(ASN1_DATA *data, const char *OID)
180 {
181         uint_t v, v2;
182         const char *p = (const char *)OID;
183         char *newp;
184
185         if (!asn1_push_tag(data, ASN1_OID))
186                 return False;
187         v = strtol(p, &newp, 10);
188         p = newp;
189         v2 = strtol(p, &newp, 10);
190         p = newp;
191         if (!asn1_write_uint8(data, 40*v + v2))
192                 return False;
193
194         while (*p) {
195                 v = strtol(p, &newp, 10);
196                 p = newp;
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))
202                         return False;
203         }
204         return asn1_pop_tag(data);
205 }
206
207 /* write an octet string */
208 BOOL asn1_write_OctetString(ASN1_DATA *data, const void *p, size_t length)
209 {
210         asn1_push_tag(data, ASN1_OCTET_STRING);
211         asn1_write(data, p, length);
212         asn1_pop_tag(data);
213         return !data->has_error;
214 }
215
216 /* write a general string */
217 BOOL asn1_write_GeneralString(ASN1_DATA *data, const char *s)
218 {
219         asn1_push_tag(data, ASN1_GENERAL_STRING);
220         asn1_write(data, s, strlen(s));
221         asn1_pop_tag(data);
222         return !data->has_error;
223 }
224
225 BOOL asn1_write_ContextSimple(ASN1_DATA *data, uint8_t num, DATA_BLOB *blob)
226 {
227         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num));
228         asn1_write(data, blob->data, blob->length);
229         asn1_pop_tag(data);
230         return !data->has_error;
231 }
232
233 /* write a BOOLEAN */
234 BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
235 {
236         asn1_push_tag(data, ASN1_BOOLEAN);
237         asn1_write_uint8(data, v ? 0xFF : 0);
238         asn1_pop_tag(data);
239         return !data->has_error;
240 }
241
242 BOOL asn1_read_BOOLEAN(ASN1_DATA *data, BOOL *v)
243 {
244         asn1_start_tag(data, ASN1_BOOLEAN);
245         asn1_read_uint8(data, (uint8 *)v);
246         asn1_end_tag(data);
247         return !data->has_error;
248 }
249
250 /* check a BOOLEAN */
251 BOOL asn1_check_BOOLEAN(ASN1_DATA *data, BOOL v)
252 {
253         uint8_t b = 0;
254
255         asn1_read_uint8(data, &b);
256         if (b != ASN1_BOOLEAN) {
257                 data->has_error = True;
258                 return False;
259         }
260         asn1_read_uint8(data, &b);
261         if (b != v) {
262                 data->has_error = True;
263                 return False;
264         }
265         return !data->has_error;
266 }
267
268
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)
271 {
272         ZERO_STRUCTP(data);
273         data->data = talloc_memdup(NULL, blob.data, blob.length);
274         if (!data->data) {
275                 data->has_error = True;
276                 return False;
277         }
278         data->length = blob.length;
279         return True;
280 }
281
282 /* Peek into an ASN1 buffer, not advancing the pointer */
283 BOOL asn1_peek(ASN1_DATA *data, void *p, int len)
284 {
285         if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)
286                 return False;
287
288         if (data->ofs + len > data->length)
289                 return False;
290
291         memcpy(p, data->data + data->ofs, len);
292         return True;
293 }
294
295 /* read from a ASN1 buffer, advancing the buffer pointer */
296 BOOL asn1_read(ASN1_DATA *data, void *p, int len)
297 {
298         if (!asn1_peek(data, p, len)) {
299                 data->has_error = True;
300                 return False;
301         }
302
303         data->ofs += len;
304         return True;
305 }
306
307 /* read a uint8_t from a ASN1 buffer */
308 BOOL asn1_read_uint8(ASN1_DATA *data, uint8_t *v)
309 {
310         return asn1_read(data, v, 1);
311 }
312
313 BOOL asn1_peek_uint8(ASN1_DATA *data, uint8_t *v)
314 {
315         return asn1_peek(data, v, 1);
316 }
317
318 BOOL asn1_peek_tag(ASN1_DATA *data, uint8_t tag)
319 {
320         uint8_t b;
321
322         if (asn1_tag_remaining(data) <= 0) {
323                 return False;
324         }
325
326         if (!asn1_peek(data, &b, sizeof(b)))
327                 return False;
328
329         return (b == tag);
330 }
331
332 /* start reading a nested asn1 structure */
333 BOOL asn1_start_tag(ASN1_DATA *data, uint8_t tag)
334 {
335         uint8_t b;
336         struct nesting *nesting;
337         
338         if (!asn1_read_uint8(data, &b))
339                 return False;
340
341         if (b != tag) {
342                 data->has_error = True;
343                 return False;
344         }
345         nesting = talloc_p(NULL, struct nesting);
346         if (!nesting) {
347                 data->has_error = True;
348                 return False;
349         }
350
351         if (!asn1_read_uint8(data, &b)) {
352                 return False;
353         }
354
355         if (b & 0x80) {
356                 int n = b & 0x7f;
357                 if (!asn1_read_uint8(data, &b))
358                         return False;
359                 nesting->taglen = b;
360                 while (n > 1) {
361                         if (!asn1_read_uint8(data, &b)) 
362                                 return False;
363                         nesting->taglen = (nesting->taglen << 8) | b;
364                         n--;
365                 }
366         } else {
367                 nesting->taglen = b;
368         }
369         nesting->start = data->ofs;
370         nesting->next = data->nesting;
371         data->nesting = nesting;
372         return !data->has_error;
373 }
374
375 static BOOL read_one_uint8(int sock, uint8_t *result, ASN1_DATA *data,
376                            const struct timeval *endtime)
377 {
378         if (read_data_until(sock, result, 1, endtime) != 1)
379                 return False;
380
381         return asn1_write(data, result, 1);
382 }
383
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)
387 {
388         uint8_t b;
389         size_t len;
390         char *buf;
391
392         ZERO_STRUCTP(data);
393
394         if (!read_one_uint8(sock, &b, data, endtime))
395                 return False;
396
397         if (b != 0x30) {
398                 data->has_error = True;
399                 return False;
400         }
401
402         if (!read_one_uint8(sock, &b, data, endtime))
403                 return False;
404
405         if (b & 0x80) {
406                 int n = b & 0x7f;
407                 if (!read_one_uint8(sock, &b, data, endtime))
408                         return False;
409                 len = b;
410                 while (n > 1) {
411                         if (!read_one_uint8(sock, &b, data, endtime))
412                                 return False;
413                         len = (len<<8) | b;
414                         n--;
415                 }
416         } else {
417                 len = b;
418         }
419
420         buf = talloc(NULL, len);
421         if (buf == NULL)
422                 return False;
423
424         if (read_data_until(sock, buf, len, endtime) != len)
425                 return False;
426
427         if (!asn1_write(data, buf, len))
428                 return False;
429
430         talloc_free(buf);
431
432         data->ofs = 0;
433         
434         return True;
435 }
436
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)
440 {
441         ASN1_DATA data;
442
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 */
445         ZERO_STRUCT(data);
446         data.data = buf;
447         data.length = buf_length;
448         if (!asn1_start_tag(&data, tag))
449                 return False;
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);
454         return True;
455 }
456
457 /* stop reading a tag */
458 BOOL asn1_end_tag(ASN1_DATA *data)
459 {
460         struct nesting *nesting;
461
462         /* make sure we read it all */
463         if (asn1_tag_remaining(data) != 0) {
464                 data->has_error = True;
465                 return False;
466         }
467
468         nesting = data->nesting;
469
470         if (!nesting) {
471                 data->has_error = True;
472                 return False;
473         }
474
475         data->nesting = nesting->next;
476         talloc_free(nesting);
477         return True;
478 }
479
480 /* work out how many bytes are left in this nested tag */
481 int asn1_tag_remaining(ASN1_DATA *data)
482 {
483         if (!data->nesting) {
484                 data->has_error = True;
485                 return -1;
486         }
487         return data->nesting->taglen - (data->ofs - data->nesting->start);
488 }
489
490 /* read an object ID from a ASN1 buffer */
491 BOOL asn1_read_OID(ASN1_DATA *data, char **OID)
492 {
493         uint8_t b;
494         char *tmp_oid = NULL;
495
496         if (!asn1_start_tag(data, ASN1_OID)) return False;
497         asn1_read_uint8(data, &b);
498
499         tmp_oid = talloc_asprintf(NULL, "%u",  b/40);
500         tmp_oid = talloc_asprintf_append(tmp_oid, " %u",  b%40);
501
502         while (!data->has_error && asn1_tag_remaining(data) > 0) {
503                 uint_t v = 0;
504                 do {
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);
509         }
510
511         asn1_end_tag(data);
512
513         *OID = talloc_strdup(NULL, tmp_oid);
514         talloc_free(tmp_oid);
515
516         return (*OID && !data->has_error);
517 }
518
519 /* check that the next object ID is correct */
520 BOOL asn1_check_OID(ASN1_DATA *data, const char *OID)
521 {
522         char *id;
523
524         if (!asn1_read_OID(data, &id)) return False;
525
526         if (strcmp(id, OID) != 0) {
527                 data->has_error = True;
528                 return False;
529         }
530         talloc_free(id);
531         return True;
532 }
533
534 /* read a GeneralString from a ASN1 buffer */
535 BOOL asn1_read_GeneralString(ASN1_DATA *data, char **s)
536 {
537         int len;
538         if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return False;
539         len = asn1_tag_remaining(data);
540         if (len < 0) {
541                 data->has_error = True;
542                 return False;
543         }
544         *s = talloc(NULL, len+1);
545         if (! *s) {
546                 data->has_error = True;
547                 return False;
548         }
549         asn1_read(data, *s, len);
550         (*s)[len] = 0;
551         asn1_end_tag(data);
552         return !data->has_error;
553 }
554
555 /* read a octet string blob */
556 BOOL asn1_read_OctetString(ASN1_DATA *data, DATA_BLOB *blob)
557 {
558         int len;
559         ZERO_STRUCTP(blob);
560         if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return False;
561         len = asn1_tag_remaining(data);
562         if (len < 0) {
563                 data->has_error = True;
564                 return False;
565         }
566         *blob = data_blob(NULL, len);
567         asn1_read(data, blob->data, len);
568         asn1_end_tag(data);
569         
570         if (data->has_error) {
571                 data_blob_free(blob);
572                 *blob = data_blob(NULL, 0);
573                 return False;
574         }
575         return True;
576 }
577
578 BOOL asn1_read_ContextSimple(ASN1_DATA *data, uint8_t num, DATA_BLOB *blob)
579 {
580         int len;
581         ZERO_STRUCTP(blob);
582         if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return False;
583         len = asn1_tag_remaining(data);
584         if (len < 0) {
585                 data->has_error = True;
586                 return False;
587         }
588         *blob = data_blob(NULL, len);
589         asn1_read(data, blob->data, len);
590         asn1_end_tag(data);
591         return !data->has_error;
592 }
593
594 /* read an interger without tag*/
595 BOOL asn1_read_implicit_Integer(ASN1_DATA *data, int *i)
596 {
597         uint8_t b;
598         *i = 0;
599
600         while (asn1_tag_remaining(data)>0) {
601                 if (!asn1_read_uint8(data, &b)) return False;
602                 *i = (*i << 8) + b;
603         }
604         return !data->has_error;        
605         
606 }
607
608 /* read an interger */
609 BOOL asn1_read_Integer(ASN1_DATA *data, int *i)
610 {
611         *i = 0;
612
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);      
616         
617 }
618
619 /* read an interger */
620 BOOL asn1_read_enumerated(ASN1_DATA *data, int *v)
621 {
622         *v = 0;
623         
624         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return False;
625         while (asn1_tag_remaining(data)>0) {
626                 uint8_t b;
627                 asn1_read_uint8(data, &b);
628                 *v = (*v << 8) + b;
629         }
630         return asn1_end_tag(data);      
631 }
632
633 /* check a enumarted value is correct */
634 BOOL asn1_check_enumerated(ASN1_DATA *data, int v)
635 {
636         uint8_t b;
637         if (!asn1_start_tag(data, ASN1_ENUMERATED)) return False;
638         asn1_read_uint8(data, &b);
639         asn1_end_tag(data);
640
641         if (v != b)
642                 data->has_error = False;
643
644         return !data->has_error;
645 }
646
647 /* write an enumarted value to the stream */
648 BOOL asn1_write_enumerated(ASN1_DATA *data, uint8_t v)
649 {
650         if (!asn1_push_tag(data, ASN1_ENUMERATED)) return False;
651         asn1_write_uint8(data, v);
652         asn1_pop_tag(data);
653         return !data->has_error;
654 }