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