asn1.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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 /*
531  * asn_parse_length - interprets the length of the current object.
532  * On exit, length contains the value of this length field.
533  *
534  * Returns a pointer to the first byte after this length
535  * field (aka: the start of the data field).
536  * Returns NULL on any error.
537  */
538 u_char *
539 asn_parse_length(u_char * data, u_int * length)
540 /* u_char *data; IN - pointer to start of length field */
541 /* u_int *length; OUT - value of length field */
542 {
543  u_char lengthbyte = *data;
544 
545  if (lengthbyte & ASN_LONG_LEN) {
546  lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
547 
548  if (lengthbyte == 0) {
550  return (NULL);
551  }
552  if (lengthbyte > sizeof(int)) {
554  return (NULL);
555  }
556  *length = (u_int) 0;
557  memcpy((char *) (length), (char *) data + 1, (int) lengthbyte);
558  *length = ntohl(*length);
559  *length >>= (8 * ((sizeof *length) - lengthbyte));
560  return (data + lengthbyte + 1);
561 
562  }
563  /* short asnlength */
564 
565  *length = (int) lengthbyte;
566  return (data + 1);
567 }
568 
569 u_char *
570 asn_build_length(u_char * data, int *datalength,
571  int length, int truth)
572 /* u_char *data; IN - pointer to start of object */
573 /* int *datalength; IN/OUT - # of valid bytes left in buf */
574 /* int length; IN - length of object */
575 /* int truth; IN - If 1, this is the true len. */
576 {
577  u_char *start_data = data;
578 
579  if (truth) {
580 
581  /* no indefinite lengths sent */
582  if (length < 0x80) {
583  if (*datalength < 1) {
585  return (NULL);
586  }
587  *data++ = (u_char) length;
588 
589  } else if (length <= 0xFF) {
590  if (*datalength < 2) {
592  return (NULL);
593  }
594  *data++ = (u_char) (0x01 | ASN_LONG_LEN);
595  *data++ = (u_char) length;
596  } else { /* 0xFF < length <= 0xFFFF */
597  if (*datalength < 3) {
599  return (NULL);
600  }
601  *data++ = (u_char) (0x02 | ASN_LONG_LEN);
602  *data++ = (u_char) ((length >> 8) & 0xFF);
603  *data++ = (u_char) (length & 0xFF);
604  }
605 
606  } else {
607 
608  /* Don't know if this is the true length. Make sure it's large
609  * enough for later.
610  */
611  if (*datalength < 3) {
613  return (NULL);
614  }
615  *data++ = (u_char) (0x02 | ASN_LONG_LEN);
616  *data++ = (u_char) ((length >> 8) & 0xFF);
617  *data++ = (u_char) (length & 0xFF);
618  }
619 
620  *datalength -= (data - start_data);
621  return (data);
622 }
623 
624 /*
625  * asn_parse_objid - pulls an object identifier out of an ASN object
626  * identifier type.
627  * On entry, datalength is input as the number of valid bytes following
628  * "data". On exit, it is returned as the number of valid bytes
629  * following the beginning of the next object.
630  *
631  * "objid" is filled with the object identifier.
632  *
633  * Returns a pointer to the first byte past the end
634  * of this object (i.e. the start of the next object).
635  * Returns NULL on any error.
636  */
637 u_char *
638 asn_parse_objid(u_char * data, int *datalength,
639  u_char * type, oid * objid, int *objidlength)
640 /* u_char *data; IN - pointer to start of object */
641 /* int *datalength; IN/OUT - # of valid bytes left in buf */
642 /* u_char *type; OUT - ASN type of object */
643 /* oid *objid; IN/OUT - pointer to start of output buffer */
644 /* int *objidlength; IN/OUT - number of sub-id's in objid */
645 {
646  /*
647  * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
648  * subidentifier ::= {leadingbyte}* lastbyte
649  * leadingbyte ::= 1 7bitvalue
650  * lastbyte ::= 0 7bitvalue
651  */
652  u_char *bufp = data;
653  oid *oidp = objid + 1;
654  u_int subidentifier;
655  int length;
656  u_int asn_length;
657 
658  *type = *bufp++;
659  bufp = asn_parse_length(bufp, &asn_length);
660  if (bufp == NULL)
661  return (NULL);
662 
663  if (asn_length + (bufp - data) > *datalength) {
665  return (NULL);
666  }
667  *datalength -= (int) asn_length + (bufp - data);
668 
669  /* Handle invalid object identifier encodings of the form 06 00 robustly */
670  if (asn_length == 0)
671  objid[0] = objid[1] = 0;
672 
673  length = asn_length;
674  (*objidlength)--; /* account for expansion of first byte */
675  while (length > 0 && (*objidlength)-- > 0) {
676  subidentifier = 0;
677 
678  do { /* shift and add in low order 7 bits */
679  subidentifier = (subidentifier << 7)
680  + (*(u_char *) bufp & ~ASN_BIT8);
681  length--;
682  } while (*(u_char *) bufp++ & ASN_BIT8);
683 
684  /* while last byte has high bit clear */
685  if (subidentifier > (u_int) MAX_SUBID) {
687  return (NULL);
688  }
689  *oidp++ = (oid) subidentifier;
690  }
691 
692  /*
693  * The first two subidentifiers are encoded into the first component
694  * with the value (X * 40) + Y, where:
695  * X is the value of the first subidentifier.
696  * Y is the value of the second subidentifier.
697  */
698  subidentifier = (u_int) objid[1];
699  if (subidentifier == 0x2B) {
700  objid[0] = 1;
701  objid[1] = 3;
702  } else {
703  objid[1] = (u_char) (subidentifier % 40);
704  objid[0] = (u_char) ((subidentifier - objid[1]) / 40);
705  }
706 
707  *objidlength = (int) (oidp - objid);
708  return (bufp);
709 }
710 
711 /*
712  * asn_build_objid - Builds an ASN object identifier object containing the
713  * input string.
714  * On entry, datalength is input as the number of valid bytes following
715  * "data". On exit, it is returned as the number of valid bytes
716  * following the beginning of the next object.
717  *
718  * Returns a pointer to the first byte past the end
719  * of this object (i.e. the start of the next object).
720  * Returns NULL on any error.
721  */
722 u_char *
723 asn_build_objid(u_char * data, int *datalength,
724  u_char type, oid * objid, int objidlength)
725 /* u_char *data; IN - pointer to start of object */
726 /* int *datalength; IN/OUT - # of valid bytes left in buf */
727 /* u_char type; IN - ASN type of object */
728 /* oid *objid; IN - pointer to start of input buffer */
729 /* int objidlength; IN - number of sub-id's in objid */
730 {
731  /*
732  * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
733  * subidentifier ::= {leadingbyte}* lastbyte
734  * leadingbyte ::= 1 7bitvalue
735  * lastbyte ::= 0 7bitvalue
736  */
737  u_char buf[MAX_OID_LEN];
738  u_char *bp = buf;
739  oid *op = objid;
740  int asnlength;
741  u_int subid, mask, testmask;
742  int bits, testbits;
743 
744  if (objidlength < 2) {
745  *bp++ = 0;
746  objidlength = 0;
747  } else {
748  *bp++ = op[1] + (op[0] * 40);
749  objidlength -= 2;
750  op += 2;
751  }
752 
753  while (objidlength-- > 0) {
754  subid = *op++;
755  if (subid < 127) { /* off by one? */
756  *bp++ = subid;
757  } else {
758  mask = 0x7F; /* handle subid == 0 case */
759  bits = 0;
760  /* testmask *MUST* !!!! be of an unsigned type */
761  for (testmask = 0x7F, testbits = 0; testmask != 0;
762  testmask <<= 7, testbits += 7) {
763  if (subid & testmask) { /* if any bits set */
764  mask = testmask;
765  bits = testbits;
766  }
767  }
768  /* mask can't be zero here */
769  for (; mask != 0x7F; mask >>= 7, bits -= 7) {
770  /* fix a mask that got truncated above */
771  if (mask == 0x1E00000)
772  mask = 0xFE00000;
773  *bp++ = (u_char) (((subid & mask) >> bits) | ASN_BIT8);
774  }
775  *bp++ = (u_char) (subid & mask);
776  }
777  }
778 
779  asnlength = bp - buf;
780  data = asn_build_header_with_truth(data, datalength, type, asnlength, 1);
781  if (data == NULL)
782  return (NULL);
783  if (*datalength < asnlength) {
785  return (NULL);
786  }
787  memcpy((char *) data, (char *) buf, asnlength);
788  *datalength -= asnlength;
789  return (data + asnlength);
790 }
791 
792 /*
793  * asn_build_null - Builds an ASN null object.
794  * On entry, datalength is input as the number of valid bytes following
795  * "data". On exit, it is returned as the number of valid bytes
796  * following the beginning of the next object.
797  *
798  * Returns a pointer to the first byte past the end
799  * of this object (i.e. the start of the next object).
800  * Returns NULL on any error.
801  */
802 u_char *
803 asn_build_null(u_char * data, int *datalength, u_char type)
804 /* u_char *data; IN - pointer to start of object */
805 /* int *datalength; IN/OUT - # of valid bytes left in buf */
806 /* u_char type; IN - ASN type of object */
807 {
808  /*
809  * ASN.1 null ::= 0x05 0x00
810  */
811  return (asn_build_header_with_truth(data, datalength, type, 0, 1));
812 }
813 
814 /*
815  * To do: Write an asn_parse_exception function to go with the new
816  * asn_build_exception function below so that the exceptional values can
817  * be handled in input packets as well as output ones.
818  */
819 
820 /*
821  * asn_build_exception - Builds an ASN exception object.
822  * On entry, datalength is input as the number of valid bytes following
823  * "data". On exit, it is returned as the number of valid bytes
824  * following the beginning of the next object.
825  *
826  * Returns a pointer to the first byte past the end
827  * of this object (i.e. the start of the next object).
828  * Returns NULL on any error.
829  *
830  * ASN.1 variable exception ::= 0x8i 0x00, where 'i' is one of these
831  * exception identifiers:
832  * 0 -- noSuchObject
833  * 1 -- noSuchInstance
834  * 2 -- endOfMibView
835  */
836 u_char *
837 asn_build_exception(u_char * data, int *datalength, u_char type)
838 /* u_char *data; IN - pointer to start of object */
839 /* int *datalength; IN/OUT - # of valid bytes left in buf */
840 /* u_char type; IN - ASN type of object */
841 {
842  return (asn_build_header_with_truth(data, datalength, type, 0, 1));
843 }
844 
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_header_with_truth(u_char *data, int *datalength, u_char type, int length, int truth)
Definition: asn1.c:513
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_objid(u_char *data, int *datalength, u_char type, oid *objid, int objidlength)
Definition: asn1.c:723
u_char * asn_build_null(u_char *data, int *datalength, u_char type)
Definition: asn1.c:803
u_char * asn_parse_header(u_char *data, int *datalength, u_char *type)
Definition: asn1.c:470
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_string(u_char *data, int *datalength, u_char type, u_char *string, int strlength)
Definition: asn1.c:433
#define SNMPERR_ASN_DECODE
#define NULL
Definition: types.h:145
u_char * asn_build_exception(u_char *data, int *datalength, u_char type)
Definition: asn1.c:837
char * data
Definition: rfcnb-common.h:44
#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
u_char * asn_build_header(u_char *data, int *datalength, u_char type, int length)
Definition: asn1.c:93
u_int oid
Definition: asn1.h:42
#define SNMPERR_ASN_ENCODE
Definition: parse.c:96
u_char * asn_parse_length(u_char *data, u_int *length)
Definition: asn1.c:539
void snmp_set_api_error(int)
#define MAX_SUBID
Definition: asn1.h:43
#define ASN_BIT8
Definition: asn1.h:70
#define MAX_OID_LEN
Definition: asn1.h:49
u_char * asn_build_unsigned_int(u_char *data, int *datalength, u_char type, u_int *intp, int intsize)
Definition: asn1.c:311
u_char * asn_build_length(u_char *data, int *datalength, int length, int truth)
Definition: asn1.c:570
#define IS_EXTENSION_ID(byte)
Definition: asn1.h:73
u_char * asn_parse_objid(u_char *data, int *datalength, u_char *type, oid *objid, int *objidlength)
Definition: asn1.c:638
int unsigned int
Definition: stub_fd.cc:19

 

Introduction

Documentation

Support

Miscellaneous