asn1.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /*
10  * Abstract Syntax Notation One, ASN.1
11  * As defined in ISO/IS 8824 and ISO/IS 8825
12  * This implements a subset of the above International Standards that
13  * is sufficient to implement SNMP.
14  *
15  * Encodes abstract data types into a machine independent stream of bytes.
16  *
17  */
18 /***************************************************************************
19  *
20  * Copyright 1997 by Carnegie Mellon University
21  *
22  * All Rights Reserved
23  *
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation for any purpose and without fee is hereby granted,
26  * provided that the above copyright notice appear in all copies and that
27  * both that copyright notice and this permission notice appear in
28  * supporting documentation, and that the name of CMU not be
29  * used in advertising or publicity pertaining to distribution of the
30  * software without specific, written prior permission.
31  *
32  * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
33  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
34  * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
35  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
36  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
37  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
38  * SOFTWARE.
39  *
40  ***************************************************************************/
41 
42 #include "squid.h"
43 
44 #if HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 #if HAVE_STDLIB_H
48 #include <stdlib.h>
49 #endif
50 #if HAVE_SYS_TYPES_H
51 #include <sys/types.h>
52 #endif
53 #if HAVE_CTYPE_H
54 #include <ctype.h>
55 #endif
56 #if HAVE_GNUMALLOC_H
57 #include <gnumalloc.h>
58 #elif HAVE_MALLOC_H
59 #include <malloc.h>
60 #endif
61 #if HAVE_MEMORY_H
62 #include <memory.h>
63 #endif
64 #if HAVE_STRING_H
65 #include <string.h>
66 #endif
67 #if HAVE_STRINGS_H
68 #include <strings.h>
69 #endif
70 #if HAVE_BSTRING_H
71 #include <bstring.h>
72 #endif
73 #if HAVE_SYS_SOCKET_H
74 #include <sys/socket.h>
75 #endif
76 #if HAVE_NETINET_IN_H
77 #include <netinet/in.h>
78 #endif
79 #if HAVE_ARPA_INET_H
80 #include <arpa/inet.h>
81 #endif
82 #if HAVE_SYS_TIME_H
83 #include <sys/time.h>
84 #endif
85 #if HAVE_NETDB_H
86 #include <netdb.h>
87 #endif
88 
89 #include "asn1.h"
90 #include "snmp_api_error.h"
91 
92 u_char *
93 asn_build_header(u_char * data, /* IN - ptr to start of object */
94  int *datalength, /* IN/OUT - # of valid bytes */
95  /* left in buffer */
96  u_char type, /* IN - ASN type of object */
97  int length)
98 { /* IN - length of object */
99  /* Truth is 0 'cause we don't know yet */
100  return (asn_build_header_with_truth(data, datalength, type, length, 0));
101 }
102 
103 /*
104  * asn_parse_int - pulls an int out of an ASN int type.
105  * On entry, datalength is input as the number of valid bytes following
106  * "data". On exit, it is returned as the number of valid bytes
107  * following the end of this object.
108  *
109  * Returns a pointer to the first byte past the end
110  * of this object (i.e. the start of the next object).
111  * Returns NULL on any error.
112  */
113 u_char *
114 asn_parse_int(u_char * data, int *datalength,
115  u_char * type, int *intp, int intsize)
116 /* u_char *data; IN - pointer to start of object */
117 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
118 /* u_char *type; OUT - asn type of object */
119 /* int *intp; IN/OUT - pointer to start of output buffer */
120 /* int intsize; IN - size of output buffer */
121 {
122  /*
123  * ASN.1 integer ::= 0x02 asnlength byte {byte}*
124  */
125  u_char *bufp = data;
126  u_int asn_length;
127  int value = 0;
128 
129  /* Room to store int? */
130  if (intsize != sizeof(int)) {
132  return (NULL);
133  }
134  /* Type */
135  *type = *bufp++;
136 
137  /* Extract length */
138  bufp = asn_parse_length(bufp, &asn_length);
139  if (bufp == NULL)
140  return (NULL);
141 
142  /* Make sure the entire int is in the buffer */
143  if (asn_length + (bufp - data) > *datalength) {
145  return (NULL);
146  }
147  /* Can we store this int? */
148  if (asn_length > intsize) {
150  return (NULL);
151  }
152  /* Remaining data */
153  *datalength -= (int) asn_length + (bufp - data);
154 
155  /* Is the int negative? */
156  if (*bufp & 0x80)
157  value = -1; /* integer is negative */
158 
159  /* Extract the bytes */
160  while (asn_length--)
161  value = (value << 8) | *bufp++;
162 
163  /* That's it! */
164  *intp = value;
165  return (bufp);
166 }
167 
168 /*
169  * asn_parse_unsigned_int - pulls an unsigned int out of an ASN int type.
170  * On entry, datalength is input as the number of valid bytes following
171  * "data". On exit, it is returned as the number of valid bytes
172  * following the end of this object.
173  *
174  * Returns a pointer to the first byte past the end
175  * of this object (i.e. the start of the next object).
176  * Returns NULL on any error.
177  */
178 u_char *
179 asn_parse_unsigned_int(u_char * data, int *datalength,
180  u_char * type, u_int * intp, int intsize)
181 /* u_char *data; IN - pointer to start of object */
182 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
183 /* u_char *type; OUT - asn type of object */
184 /* u_int *intp; IN/OUT - pointer to start of output buffer */
185 /* int intsize; IN - size of output buffer */
186 {
187  /*
188  * ASN.1 integer ::= 0x02 asnlength byte {byte}*
189  */
190  u_char *bufp = data;
191  u_int asn_length;
192  int value = 0;
193 
194  /* Room to store int? */
195  if (intsize != sizeof(int)) {
197  return (NULL);
198  }
199  /* Type */
200  *type = *bufp++;
201 
202  /* Extract length */
203  bufp = asn_parse_length(bufp, &asn_length);
204  if (bufp == NULL)
205  return (NULL);
206 
207  /* Make sure the entire int is in the buffer */
208  if (asn_length + (bufp - data) > *datalength) {
210  return (NULL);
211  }
212  /* Can we store this int? */
213  if ((asn_length > (intsize + 1)) ||
214  ((asn_length == intsize + 1) && *bufp != 0x00)) {
216  return (NULL);
217  }
218  /* Remaining data */
219  *datalength -= (int) asn_length + (bufp - data);
220 
221  /* Is the int negative? */
222  if (*bufp & 0x80)
223  value = -1; /* integer is negative */
224 
225  /* Extract the bytes */
226  while (asn_length--)
227  value = (value << 8) | *bufp++;
228 
229  /* That's it! */
230  *intp = value;
231  return (bufp);
232 }
233 
234 /*
235  * asn_build_int - builds an ASN object containing an integer.
236  * On entry, datalength is input as the number of valid bytes following
237  * "data". On exit, it is returned as the number of valid bytes
238  * following the end of this object.
239  *
240  * Returns a pointer to the first byte past the end
241  * of this object (i.e. the start of the next object).
242  * Returns NULL on any error.
243  */
244 u_char *
245 asn_build_int(u_char * data, int *datalength,
246  u_char type, int *intp, int intsize)
247 /* u_char *data; IN - pointer to start of output buffer */
248 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
249 /* u_char type; IN - asn type of object */
250 /* int *intp; IN - pointer to start of integer */
251 /* int intsize; IN - size of *intp */
252 {
253  /*
254  * ASN.1 integer ::= 0x02 asnlength byte {byte}*
255  */
256  int integer;
257  u_int mask;
258 
259  if (intsize != sizeof(int)) {
261  return (NULL);
262  }
263  integer = *intp;
264 
265  /*
266  * Truncate "unnecessary" bytes off of the most significant end of this
267  * 2's complement integer. There should be no sequence of 9
268  * consecutive 1's or 0's at the most significant end of the
269  * integer.
270  */
271  mask = (u_int) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
272  /* mask is 0xFF800000 on a big-endian machine */
273 
274  while ((((integer & mask) == 0) || ((integer & mask) == mask))
275  && intsize > 1) {
276  intsize--;
277  integer <<= 8;
278  }
279 
280  data = asn_build_header_with_truth(data, datalength, type, intsize, 1);
281  if (data == NULL)
282  return (NULL);
283 
284  /* Enough room for what we just encoded? */
285  if (*datalength < intsize) {
287  return (NULL);
288  }
289  /* Insert it */
290  *datalength -= intsize;
291  mask = (u_int) 0xFF << (8 * (sizeof(int) - 1));
292  /* mask is 0xFF000000 on a big-endian machine */
293  while (intsize--) {
294  *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(int) - 1)));
295  integer <<= 8;
296  }
297  return (data);
298 }
299 
300 /*
301  * asn_build_unsigned_int - builds an ASN object containing an integer.
302  * On entry, datalength is input as the number of valid bytes following
303  * "data". On exit, it is returned as the number of valid bytes
304  * following the end of this object.
305  *
306  * Returns a pointer to the first byte past the end
307  * of this object (i.e. the start of the next object).
308  * Returns NULL on any error.
309  */
310 u_char *
311 asn_build_unsigned_int(u_char * data, int *datalength,
312  u_char type, u_int * intp, int intsize)
313 /* u_char *data; IN - pointer to start of output buffer */
314 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
315 /* u_char type; IN - asn type of object */
316 /* u_int *intp; IN - pointer to start of integer */
317 /* int intsize; IN - size of *intp */
318 {
319  /*
320  * ASN.1 integer ::= 0x02 asnlength byte {byte}*
321  */
322  u_int integer;
323  u_int mask;
324  int add_null_byte = 0;
325 
326  if (intsize != sizeof(int)) {
328  return (NULL);
329  }
330  integer = *intp;
331  mask = (u_int) 0x80 << (8 * (sizeof(int) - 1));
332  /* mask is 0x80000000 on a big-endian machine */
333  if ((integer & mask) != 0) {
334  /* add a null byte if MSB is set, to prevent sign extension */
335  add_null_byte = 1;
336  intsize++;
337  }
338  /*
339  * Truncate "unnecessary" bytes off of the most significant end of
340  * this 2's complement integer.
341  * There should be no sequence of 9 consecutive 1's or 0's at the
342  * most significant end of the integer.
343  * The 1's case is taken care of above by adding a null byte.
344  */
345  mask = (u_int) 0x1FF << ((8 * (sizeof(int) - 1)) - 1);
346  /* mask is 0xFF800000 on a big-endian machine */
347  while (((integer & mask) == 0) && intsize > 1) {
348  intsize--;
349  integer <<= 8;
350  }
351 
352  data = asn_build_header_with_truth(data, datalength, type, intsize, 1);
353  if (data == NULL)
354  return (NULL);
355 
356  if (*datalength < intsize) {
358  return (NULL);
359  }
360  *datalength -= intsize;
361  if (add_null_byte == 1) {
362  *data++ = '\0';
363  intsize--;
364  }
365  mask = (u_int) 0xFF << (8 * (sizeof(int) - 1));
366  /* mask is 0xFF000000 on a big-endian machine */
367  while (intsize--) {
368  *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(int) - 1)));
369  integer <<= 8;
370  }
371  return (data);
372 }
373 
374 /*
375  * asn_parse_string - pulls an octet string out of an ASN octet string type.
376  * On entry, datalength is input as the number of valid bytes following
377  * "data". On exit, it is returned as the number of valid bytes
378  * following the beginning of the next object.
379  *
380  * "string" is filled with the octet string.
381  *
382  * Returns a pointer to the first byte past the end
383  * of this object (i.e. the start of the next object).
384  * Returns NULL on any error.
385  */
386 u_char *
387 asn_parse_string(u_char * data, int *datalength,
388  u_char * type, u_char * string, int *strlength)
389 /* u_char *data; IN - pointer to start of object */
390 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
391 /* u_char *type; OUT - asn type of object */
392 /* u_char *string; IN/OUT - pointer to start of output buffer */
393 /* int *strlength; IN/OUT - size of output buffer */
394 {
395  /*
396  * ASN.1 octet string ::= primstring | cmpdstring
397  * primstring ::= 0x04 asnlength byte {byte}*
398  * cmpdstring ::= 0x24 asnlength string {string}*
399  */
400  u_char *bufp = data;
401  u_int asn_length;
402 
403  *type = *bufp++;
404  bufp = asn_parse_length(bufp, &asn_length);
405  if (bufp == NULL)
406  return (NULL);
407 
408  if (asn_length + (bufp - data) > *datalength) {
410  return (NULL);
411  }
412  if (asn_length > *strlength) {
414  return (NULL);
415  }
416  memcpy((char *) string, (char *) bufp, (int) asn_length);
417  *strlength = (int) asn_length;
418  *datalength -= (int) asn_length + (bufp - data);
419  return (bufp + asn_length);
420 }
421 
422 /*
423  * asn_build_string - Builds an ASN octet string object containing the input
424  * string. On entry, datalength is input as the number of valid bytes
425  * following "data". On exit, it is returned as the number of valid bytes
426  * following the beginning of the next object.
427  *
428  * Returns a pointer to the first byte past the end
429  * of this object (i.e. the start of the next object).
430  * Returns NULL on any error.
431  */
432 u_char *
433 asn_build_string(u_char * data, int *datalength,
434  u_char type, u_char * string, int strlength)
435 /* u_char *data; IN - pointer to start of object */
436 /* int *datalength; IN/OUT - # of valid bytes left in buf */
437 /* u_char type; IN - ASN type of string */
438 /* u_char *string; IN - pointer to start of input buffer */
439 /* int strlength; IN - size of input buffer */
440 {
441  /*
442  * ASN.1 octet string ::= primstring | cmpdstring
443  * primstring ::= 0x04 asnlength byte {byte}*
444  * cmpdstring ::= 0x24 asnlength string {string}*
445  * This code will never send a compound string.
446  */
447  data = asn_build_header_with_truth(data, datalength, type, strlength, 1);
448  if (data == NULL)
449  return (NULL);
450 
451  if (*datalength < strlength) {
453  return (NULL);
454  }
455  memcpy((char *) data, (char *) string, strlength);
456  *datalength -= strlength;
457  return (data + strlength);
458 }
459 
460 /*
461  * asn_parse_header - interprets the ID and length of the current object.
462  * On entry, datalength is input as the number of valid bytes following
463  * "data". On exit, it is returned as the number of valid bytes
464  * in this object following the id and length.
465  *
466  * Returns a pointer to the first byte of the contents of this object.
467  * Returns NULL on any error.
468  */
469 u_char *
470 asn_parse_header(u_char * data, int *datalength, u_char * type)
471 /* u_char *data; IN - pointer to start of object */
472 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
473 /* u_char *type; OUT - ASN type of object */
474 {
475  u_char *bufp = data;
476  int header_len;
477  u_int asn_length;
478 
479  /* this only works on data types < 30, i.e. no extension octets */
480  if (IS_EXTENSION_ID(*bufp)) {
482  return (NULL);
483  }
484  *type = *bufp;
485  bufp = asn_parse_length(bufp + 1, &asn_length);
486  if (bufp == NULL)
487  return (NULL);
488 
489  header_len = bufp - data;
490  if (header_len + asn_length > *datalength || asn_length > (u_int)(2 << 18) ) {
492  return (NULL);
493  }
494  *datalength = (int) asn_length;
495  return (bufp);
496 }
497 
498 /*
499  * asn_build_header - builds an ASN header for an object with the ID and
500  * length specified.
501  * On entry, datalength is input as the number of valid bytes following
502  * "data". On exit, it is returned as the number of valid bytes
503  * in this object following the id and length.
504  *
505  * This only works on data types < 30, i.e. no extension octets.
506  * The maximum length is 0xFFFF;
507  *
508  * Returns a pointer to the first byte of the contents of this object.
509  * Returns NULL on any error.
510  */
511 
512 u_char *
513 asn_build_header_with_truth(u_char * data, int *datalength,
514  u_char type, int length, int truth)
515 /* u_char *data; IN - pointer to start of object */
516 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
517 /* u_char type; IN - ASN type of object */
518 /* int length; IN - length of object */
519 /* int truth; IN - Whether length is truth */
520 {
521  if (*datalength < 1) {
523  return (NULL);
524  }
525  *data++ = type;
526  (*datalength)--;
527  return (asn_build_length(data, datalength, length, truth));
528 }
529 
530 #if 0
531 /*
532  * asn_build_sequence - builds an ASN header for a sequence with the ID and
533  * length specified.
534  * On entry, datalength is input as the number of valid bytes following
535  * "data". On exit, it is returned as the number of valid bytes
536  * in this object following the id and length.
537  *
538  * This only works on data types < 30, i.e. no extension octets.
539  * The maximum length is 0xFFFF;
540  *
541  * Returns a pointer to the first byte of the contents of this object.
542  * Returns NULL on any error.
543  */
544 u_char *
545 asn_build_sequence(u_char * data, int *datalength,
546  u_char type, int length)
547 /* u_char *data; IN - pointer to start of object */
548 /* int *datalength; IN/OUT - # of valid bytes left in buffer */
549 /* u_char type; IN - ASN type of object */
550 /* int length; IN - length of object */
551 {
552  *datalength -= 4;
553  if (*datalength < 0) {
554  *datalength += 4; /* fix up before punting */
556  return (NULL);
557  }
558  *data++ = type;
559  *data++ = (u_char) (0x02 | ASN_LONG_LEN);
560  *data++ = (u_char) ((length >> 8) & 0xFF);
561  *data++ = (u_char) (length & 0xFF);
562  return (data);
563 }
564 #endif
565 
566 /*
567  * asn_parse_length - interprets the length of the current object.
568  * On exit, length contains the value of this length field.
569  *
570  * Returns a pointer to the first byte after this length
571  * field (aka: the start of the data field).
572  * Returns NULL on any error.
573  */
574 u_char *
575 asn_parse_length(u_char * data, u_int * length)
576 /* u_char *data; IN - pointer to start of length field */
577 /* u_int *length; OUT - value of length field */
578 {
579  u_char lengthbyte = *data;
580 
581  if (lengthbyte & ASN_LONG_LEN) {
582  lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
583 
584  if (lengthbyte == 0) {
586  return (NULL);
587  }
588  if (lengthbyte > sizeof(int)) {
590  return (NULL);
591  }
592  *length = (u_int) 0;
593  memcpy((char *) (length), (char *) data + 1, (int) lengthbyte);
594  *length = ntohl(*length);
595  *length >>= (8 * ((sizeof *length) - lengthbyte));
596  return (data + lengthbyte + 1);
597 
598  }
599  /* short asnlength */
600 
601  *length = (int) lengthbyte;
602  return (data + 1);
603 }
604 
605 u_char *
606 asn_build_length(u_char * data, int *datalength,
607  int length, int truth)
608 /* u_char *data; IN - pointer to start of object */
609 /* int *datalength; IN/OUT - # of valid bytes left in buf */
610 /* int length; IN - length of object */
611 /* int truth; IN - If 1, this is the true len. */
612 {
613  u_char *start_data = data;
614 
615  if (truth) {
616 
617  /* no indefinite lengths sent */
618  if (length < 0x80) {
619  if (*datalength < 1) {
621  return (NULL);
622  }
623  *data++ = (u_char) length;
624 
625  } else if (length <= 0xFF) {
626  if (*datalength < 2) {
628  return (NULL);
629  }
630  *data++ = (u_char) (0x01 | ASN_LONG_LEN);
631  *data++ = (u_char) length;
632  } else { /* 0xFF < length <= 0xFFFF */
633  if (*datalength < 3) {
635  return (NULL);
636  }
637  *data++ = (u_char) (0x02 | ASN_LONG_LEN);
638  *data++ = (u_char) ((length >> 8) & 0xFF);
639  *data++ = (u_char) (length & 0xFF);
640  }
641 
642  } else {
643 
644  /* Don't know if this is the true length. Make sure it's large
645  * enough for later.
646  */
647  if (*datalength < 3) {
649  return (NULL);
650  }
651  *data++ = (u_char) (0x02 | ASN_LONG_LEN);
652  *data++ = (u_char) ((length >> 8) & 0xFF);
653  *data++ = (u_char) (length & 0xFF);
654  }
655 
656  *datalength -= (data - start_data);
657  return (data);
658 }
659 
660 /*
661  * asn_parse_objid - pulls an object indentifier out of an ASN object
662  * identifier type.
663  * On entry, datalength is input as the number of valid bytes following
664  * "data". On exit, it is returned as the number of valid bytes
665  * following the beginning of the next object.
666  *
667  * "objid" is filled with the object identifier.
668  *
669  * Returns a pointer to the first byte past the end
670  * of this object (i.e. the start of the next object).
671  * Returns NULL on any error.
672  */
673 u_char *
674 asn_parse_objid(u_char * data, int *datalength,
675  u_char * type, oid * objid, int *objidlength)
676 /* u_char *data; IN - pointer to start of object */
677 /* int *datalength; IN/OUT - # of valid bytes left in buf */
678 /* u_char *type; OUT - ASN type of object */
679 /* oid *objid; IN/OUT - pointer to start of output buffer */
680 /* int *objidlength; IN/OUT - number of sub-id's in objid */
681 {
682  /*
683  * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
684  * subidentifier ::= {leadingbyte}* lastbyte
685  * leadingbyte ::= 1 7bitvalue
686  * lastbyte ::= 0 7bitvalue
687  */
688  u_char *bufp = data;
689  oid *oidp = objid + 1;
690  u_int subidentifier;
691  int length;
692  u_int asn_length;
693 
694  *type = *bufp++;
695  bufp = asn_parse_length(bufp, &asn_length);
696  if (bufp == NULL)
697  return (NULL);
698 
699  if (asn_length + (bufp - data) > *datalength) {
701  return (NULL);
702  }
703  *datalength -= (int) asn_length + (bufp - data);
704 
705  /* Handle invalid object identifier encodings of the form 06 00 robustly */
706  if (asn_length == 0)
707  objid[0] = objid[1] = 0;
708 
709  length = asn_length;
710  (*objidlength)--; /* account for expansion of first byte */
711  while (length > 0 && (*objidlength)-- > 0) {
712  subidentifier = 0;
713 
714  do { /* shift and add in low order 7 bits */
715  subidentifier = (subidentifier << 7)
716  + (*(u_char *) bufp & ~ASN_BIT8);
717  length--;
718  } while (*(u_char *) bufp++ & ASN_BIT8);
719 
720  /* while last byte has high bit clear */
721  if (subidentifier > (u_int) MAX_SUBID) {
723  return (NULL);
724  }
725  *oidp++ = (oid) subidentifier;
726  }
727 
728  /*
729  * The first two subidentifiers are encoded into the first component
730  * with the value (X * 40) + Y, where:
731  * X is the value of the first subidentifier.
732  * Y is the value of the second subidentifier.
733  */
734  subidentifier = (u_int) objid[1];
735  if (subidentifier == 0x2B) {
736  objid[0] = 1;
737  objid[1] = 3;
738  } else {
739  objid[1] = (u_char) (subidentifier % 40);
740  objid[0] = (u_char) ((subidentifier - objid[1]) / 40);
741  }
742 
743  *objidlength = (int) (oidp - objid);
744  return (bufp);
745 }
746 
747 /*
748  * asn_build_objid - Builds an ASN object identifier object containing the
749  * input string.
750  * On entry, datalength is input as the number of valid bytes following
751  * "data". On exit, it is returned as the number of valid bytes
752  * following the beginning of the next object.
753  *
754  * Returns a pointer to the first byte past the end
755  * of this object (i.e. the start of the next object).
756  * Returns NULL on any error.
757  */
758 u_char *
759 asn_build_objid(u_char * data, int *datalength,
760  u_char type, oid * objid, int objidlength)
761 /* u_char *data; IN - pointer to start of object */
762 /* int *datalength; IN/OUT - # of valid bytes left in buf */
763 /* u_char type; IN - ASN type of object */
764 /* oid *objid; IN - pointer to start of input buffer */
765 /* int objidlength; IN - number of sub-id's in objid */
766 {
767  /*
768  * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
769  * subidentifier ::= {leadingbyte}* lastbyte
770  * leadingbyte ::= 1 7bitvalue
771  * lastbyte ::= 0 7bitvalue
772  */
773  u_char buf[MAX_OID_LEN];
774  u_char *bp = buf;
775  oid *op = objid;
776  int asnlength;
777  u_int subid, mask, testmask;
778  int bits, testbits;
779 
780  if (objidlength < 2) {
781  *bp++ = 0;
782  objidlength = 0;
783  } else {
784  *bp++ = op[1] + (op[0] * 40);
785  objidlength -= 2;
786  op += 2;
787  }
788 
789  while (objidlength-- > 0) {
790  subid = *op++;
791  if (subid < 127) { /* off by one? */
792  *bp++ = subid;
793  } else {
794  mask = 0x7F; /* handle subid == 0 case */
795  bits = 0;
796  /* testmask *MUST* !!!! be of an unsigned type */
797  for (testmask = 0x7F, testbits = 0; testmask != 0;
798  testmask <<= 7, testbits += 7) {
799  if (subid & testmask) { /* if any bits set */
800  mask = testmask;
801  bits = testbits;
802  }
803  }
804  /* mask can't be zero here */
805  for (; mask != 0x7F; mask >>= 7, bits -= 7) {
806  /* fix a mask that got truncated above */
807  if (mask == 0x1E00000)
808  mask = 0xFE00000;
809  *bp++ = (u_char) (((subid & mask) >> bits) | ASN_BIT8);
810  }
811  *bp++ = (u_char) (subid & mask);
812  }
813  }
814 
815  asnlength = bp - buf;
816  data = asn_build_header_with_truth(data, datalength, type, asnlength, 1);
817  if (data == NULL)
818  return (NULL);
819  if (*datalength < asnlength) {
821  return (NULL);
822  }
823  memcpy((char *) data, (char *) buf, asnlength);
824  *datalength -= asnlength;
825  return (data + asnlength);
826 }
827 
828 #if 0
829 /*
830  * asn_parse_null - Interprets an ASN null type.
831  * On entry, datalength is input as the number of valid bytes following
832  * "data". On exit, it is returned as the number of valid bytes
833  * following the beginning of the next object.
834  *
835  * Returns a pointer to the first byte past the end
836  * of this object (i.e. the start of the next object).
837  * Returns NULL on any error.
838  */
839 u_char *
840 asn_parse_null(u_char * data, int *datalength, u_char * type)
841 /* u_char *data; IN - pointer to start of object */
842 /* int *datalength; IN/OUT - # of valid bytes left in buf */
843 /* u_char *type; OUT - ASN type of object */
844 {
845  /*
846  * ASN.1 null ::= 0x05 0x00
847  */
848  u_char *bufp = data;
849  u_int asn_length;
850 
851  *type = *bufp++;
852  bufp = asn_parse_length(bufp, &asn_length);
853  if (bufp == NULL)
854  return (NULL);
855 
856  if (asn_length != 0) {
858  return (NULL);
859  }
860  *datalength -= (bufp - data);
861  return (bufp + asn_length);
862 }
863 #endif
864 
865 /*
866  * asn_build_null - Builds an ASN null object.
867  * On entry, datalength is input as the number of valid bytes following
868  * "data". On exit, it is returned as the number of valid bytes
869  * following the beginning of the next object.
870  *
871  * Returns a pointer to the first byte past the end
872  * of this object (i.e. the start of the next object).
873  * Returns NULL on any error.
874  */
875 u_char *
876 asn_build_null(u_char * data, int *datalength, u_char type)
877 /* u_char *data; IN - pointer to start of object */
878 /* int *datalength; IN/OUT - # of valid bytes left in buf */
879 /* u_char type; IN - ASN type of object */
880 {
881  /*
882  * ASN.1 null ::= 0x05 0x00
883  */
884  return (asn_build_header_with_truth(data, datalength, type, 0, 1));
885 }
886 
887 #if 0
888 
889 /*
890  * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type.
891  * On entry, datalength is input as the number of valid bytes following
892  * "data". On exit, it is returned as the number of valid bytes
893  * following the beginning of the next object.
894  *
895  * "string" is filled with the bit string.
896  *
897  * Returns a pointer to the first byte past the end
898  * of this object (i.e. the start of the next object).
899  * Returns NULL on any error.
900  */
901 u_char *
902 asn_parse_bitstring(u_char * data, int *datalength,
903  u_char * type, u_char * string, int *strlength)
904 /* u_char *data; IN - pointer to start of object */
905 /* int *datalength; IN/OUT - # of valid bytes left in buf */
906 /* u_char *type; OUT - asn type of object */
907 /* u_char *string; IN/OUT - pointer to start of output buf */
908 /* int *strlength; IN/OUT - size of output buffer */
909 {
910  /*
911  * bitstring ::= 0x03 asnlength unused {byte}*
912  */
913  u_char *bufp = data;
914  u_int asn_length;
915 
916  *type = *bufp++;
917  bufp = asn_parse_length(bufp, &asn_length);
918  if (bufp == NULL)
919  return (NULL);
920 
921  if (asn_length + (bufp - data) > *datalength) {
923  return (NULL);
924  }
925  if (asn_length > *strlength) {
927  return (NULL);
928  }
929  if (asn_length < 1) {
931  return (NULL);
932  }
933  if ((int) (*(char *) bufp) < 0 || (int) (*bufp) > 7) {
935  return (NULL);
936  }
937  memcpy((char *) string, (char *) bufp, (int) asn_length);
938  *strlength = (int) asn_length;
939  *datalength -= (int) asn_length + (bufp - data);
940  return (bufp + asn_length);
941 }
942 
943 /*
944  * asn_build_bitstring - Builds an ASN bit string object containing the
945  * input string.
946  * On entry, datalength is input as the number of valid bytes following
947  * "data". On exit, it is returned as the number of valid bytes
948  * following the beginning of the next object.
949  *
950  * Returns a pointer to the first byte past the end
951  * of this object (i.e. the start of the next object).
952  * Returns NULL on any error.
953  */
954 u_char *
955 asn_build_bitstring(u_char * data, int *datalength,
956  u_char type, u_char * string, int strlength)
957 /* u_char *data; IN - pointer to start of object */
958 /* int *datalength; IN/OUT - # of valid bytes left in buf */
959 /* u_char type; IN - ASN type of string */
960 /* u_char *string; IN - pointer to start of input buffer */
961 /* int strlength; IN - size of input buffer */
962 {
963  /*
964  * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
965  */
966  if ((strlength < 1) || ((*(char *) string) < 0) || ((*string) > 7)) {
968  return (NULL);
969  }
970  data = asn_build_header_with_truth(data, datalength, type, strlength, 1);
971  if (data == NULL)
972  return (NULL);
973 
974  if (*datalength < strlength) {
976  return (NULL);
977  }
978  memcpy((char *) data, (char *) string, strlength);
979  *datalength -= strlength;
980  return (data + strlength);
981 }
982 
983 #endif
984 
985 /*
986  * To do: Write an asn_parse_exception function to go with the new
987  * asn_build_exception function below so that the exceptional values can
988  * be handled in input packets aswell as output ones.
989  */
990 
991 /*
992  * asn_build_exception - Builds an ASN exception object.
993  * On entry, datalength is input as the number of valid bytes following
994  * "data". On exit, it is returned as the number of valid bytes
995  * following the beginning of the next object.
996  *
997  * Returns a pointer to the first byte past the end
998  * of this object (i.e. the start of the next object).
999  * Returns NULL on any error.
1000  *
1001  * ASN.1 variable exception ::= 0x8i 0x00, where 'i' is one of these
1002  * exception identifiers:
1003  * 0 -- noSuchObject
1004  * 1 -- noSuchInstance
1005  * 2 -- endOfMibView
1006  */
1007 u_char *
1008 asn_build_exception(u_char * data, int *datalength, u_char type)
1009 /* u_char *data; IN - pointer to start of object */
1010 /* int *datalength; IN/OUT - # of valid bytes left in buf */
1011 /* u_char type; IN - ASN type of object */
1012 {
1013  return (asn_build_header_with_truth(data, datalength, type, 0, 1));
1014 }
1015 
u_char * asn_build_length(u_char *data, int *datalength, int length, int truth)
Definition: asn1.c:606
u_char * asn_parse_objid(u_char *data, int *datalength, u_char *type, oid *objid, int *objidlength)
Definition: asn1.c:674
#define MAX_SUBID
Definition: asn1.h:43
u_char * asn_parse_unsigned_int(u_char *data, int *datalength, u_char *type, u_int *intp, int intsize)
Definition: asn1.c:179
u_char * asn_build_exception(u_char *data, int *datalength, u_char type)
Definition: asn1.c:1008
void snmp_set_api_error(int)
int type
Definition: errorpage.cc:79
#define IS_EXTENSION_ID(byte)
Definition: asn1.h:73
#define SNMPERR_ASN_DECODE
u_char * asn_parse_header(u_char *data, int *datalength, u_char *type)
Definition: asn1.c:470
u_char * asn_build_header_with_truth(u_char *data, int *datalength, u_char type, int length, int truth)
Definition: asn1.c:513
u_char * asn_parse_int(u_char *data, int *datalength, u_char *type, int *intp, int intsize)
Definition: asn1.c:114
u_char * asn_build_objid(u_char *data, int *datalength, u_char type, oid *objid, int objidlength)
Definition: asn1.c:759
void const char HLPCB void * data
Definition: stub_helper.cc:16
u_char * asn_build_int(u_char *data, int *datalength, u_char type, int *intp, int intsize)
Definition: asn1.c:245
u_char * asn_build_string(u_char *data, int *datalength, u_char type, u_char *string, int strlength)
Definition: asn1.c:433
u_char * asn_build_header(u_char *data, int *datalength, u_char type, int length)
Definition: asn1.c:93
u_char * asn_build_null(u_char *data, int *datalength, u_char type)
Definition: asn1.c:876
void const char * buf
Definition: stub_helper.cc:16
u_int oid
Definition: asn1.h:42
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
#define ASN_LONG_LEN
Definition: asn1.h:68
u_char * asn_parse_string(u_char *data, int *datalength, u_char *type, u_char *string, int *strlength)
Definition: asn1.c:387
#define SNMPERR_ASN_ENCODE
u_char * asn_build_unsigned_int(u_char *data, int *datalength, u_char type, u_int *intp, int intsize)
Definition: asn1.c:311
Definition: parse.c:96
u_char * asn_parse_length(u_char *data, u_int *length)
Definition: asn1.c:575
#define NULL
Definition: types.h:166
#define ASN_BIT8
Definition: asn1.h:70
u_char * asn_parse_null(u_char *, int *, u_char *)
#define MAX_OID_LEN
Definition: asn1.h:49

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors