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
92u_char *
93asn_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 */
113u_char *
114asn_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 */
178u_char *
179asn_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 */
244u_char *
245asn_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 */
310u_char *
311asn_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 */
386u_char *
387asn_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 */
432u_char *
433asn_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 */
469u_char *
470asn_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
512u_char *
513asn_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 */
538u_char *
539asn_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
569u_char *
570asn_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 */
637u_char *
638asn_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 */
722u_char *
723asn_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 */
802u_char *
803asn_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 */
836u_char *
837asn_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_parse_objid(u_char *data, int *datalength, u_char *type, oid *objid, int *objidlength)
Definition: asn1.c:638
u_char * asn_parse_int(u_char *data, int *datalength, u_char *type, int *intp, int intsize)
Definition: asn1.c:114
u_char * asn_parse_length(u_char *data, u_int *length)
Definition: asn1.c:539
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_string(u_char *data, int *datalength, u_char type, u_char *string, int strlength)
Definition: asn1.c:433
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_parse_header(u_char *data, int *datalength, u_char *type)
Definition: asn1.c:470
u_char * asn_build_length(u_char *data, int *datalength, int length, int truth)
Definition: asn1.c:570
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_build_objid(u_char *data, int *datalength, u_char type, oid *objid, int objidlength)
Definition: asn1.c:723
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(u_char *data, int *datalength, u_char type, int length)
Definition: asn1.c:93
u_char * asn_build_exception(u_char *data, int *datalength, u_char type)
Definition: asn1.c:837
u_char * asn_build_null(u_char *data, int *datalength, u_char type)
Definition: asn1.c:803
u_char * asn_parse_unsigned_int(u_char *data, int *datalength, u_char *type, u_int *intp, int intsize)
Definition: asn1.c:179
u_int oid
Definition: asn1.h:42
#define MAX_SUBID
Definition: asn1.h:43
#define ASN_LONG_LEN
Definition: asn1.h:68
#define MAX_OID_LEN
Definition: asn1.h:49
#define ASN_BIT8
Definition: asn1.h:70
#define IS_EXTENSION_ID(byte)
Definition: asn1.h:73
#define SNMPERR_ASN_ENCODE
void snmp_set_api_error(int)
#define SNMPERR_ASN_DECODE
Definition: parse.c:96
int unsigned int
Definition: stub_fd.cc:19
#define NULL
Definition: types.h:145

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors