Squid Web Cache master
Loading...
Searching...
No Matches
asn1.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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 {
679 if (length-- <= 0) {
681 return (NULL);
682 }
683 // shift and add in low order 7 bits
684 subidentifier = (subidentifier << 7)
685 | (*bufp & ~ASN_BIT8);
686 } while (*bufp++ & ASN_BIT8);
687
688 /* while last byte has high bit clear */
689 if (subidentifier > (u_int) MAX_SUBID) {
691 return (NULL);
692 }
693 *oidp++ = (oid) subidentifier;
694 }
695
696 /*
697 * The first two subidentifiers are encoded into the first component
698 * with the value (X * 40) + Y, where:
699 * X is the value of the first subidentifier.
700 * Y is the value of the second subidentifier.
701 */
702 subidentifier = (u_int) objid[1];
703 if (subidentifier == 0x2B) {
704 objid[0] = 1;
705 objid[1] = 3;
706 } else {
707 objid[1] = (u_char) (subidentifier % 40);
708 objid[0] = (u_char) ((subidentifier - objid[1]) / 40);
709 }
710
711 *objidlength = (int) (oidp - objid);
712 return (bufp);
713}
714
715/*
716 * asn_build_objid - Builds an ASN object identifier object containing the
717 * input string.
718 * On entry, datalength is input as the number of valid bytes following
719 * "data". On exit, it is returned as the number of valid bytes
720 * following the beginning of the next object.
721 *
722 * Returns a pointer to the first byte past the end
723 * of this object (i.e. the start of the next object).
724 * Returns NULL on any error.
725 */
726u_char *
727asn_build_objid(u_char * data, int *datalength,
728 u_char type, oid * objid, int objidlength)
729/* u_char *data; IN - pointer to start of object */
730/* int *datalength; IN/OUT - # of valid bytes left in buf */
731/* u_char type; IN - ASN type of object */
732/* oid *objid; IN - pointer to start of input buffer */
733/* int objidlength; IN - number of sub-id's in objid */
734{
735 /*
736 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
737 * subidentifier ::= {leadingbyte}* lastbyte
738 * leadingbyte ::= 1 7bitvalue
739 * lastbyte ::= 0 7bitvalue
740 */
741 u_char buf[MAX_OID_LEN];
742 u_char *bufEnd = buf + sizeof(buf);
743 u_char *bp = buf;
744 oid *op = objid;
745 int asnlength;
746 u_int subid, mask, testmask;
747 int bits, testbits;
748
749 if (objidlength < 2) {
750 *bp++ = 0;
751 objidlength = 0;
752 } else {
753 *bp++ = op[1] + (op[0] * 40);
754 objidlength -= 2;
755 op += 2;
756 }
757
758 while (objidlength-- > 0) {
759 subid = *op++;
760 if (subid < 127) { /* off by one? */
761 if (bp >= bufEnd) {
763 return (NULL);
764 }
765 *bp++ = subid;
766 } else {
767 mask = 0x7F; /* handle subid == 0 case */
768 bits = 0;
769 /* testmask *MUST* !!!! be of an unsigned type */
770 for (testmask = 0x7F, testbits = 0; testmask != 0;
771 testmask <<= 7, testbits += 7) {
772 if (subid & testmask) { /* if any bits set */
773 mask = testmask;
774 bits = testbits;
775 }
776 }
777 /* mask can't be zero here */
778 for (; mask != 0x7F; mask >>= 7, bits -= 7) {
779 /* fix a mask that got truncated above */
780 if (mask == 0x1E00000)
781 mask = 0xFE00000;
782 if (bp >= bufEnd) {
784 return (NULL);
785 }
786 *bp++ = (u_char) (((subid & mask) >> bits) | ASN_BIT8);
787 }
788 if (bp >= bufEnd) {
790 return (NULL);
791 }
792 *bp++ = (u_char) (subid & mask);
793 }
794 }
795
796 asnlength = bp - buf;
797 data = asn_build_header_with_truth(data, datalength, type, asnlength, 1);
798 if (data == NULL)
799 return (NULL);
800 if (*datalength < asnlength) {
802 return (NULL);
803 }
804 memcpy((char *) data, (char *) buf, asnlength);
805 *datalength -= asnlength;
806 return (data + asnlength);
807}
808
809/*
810 * asn_build_null - Builds an ASN null object.
811 * On entry, datalength is input as the number of valid bytes following
812 * "data". On exit, it is returned as the number of valid bytes
813 * following the beginning of the next object.
814 *
815 * Returns a pointer to the first byte past the end
816 * of this object (i.e. the start of the next object).
817 * Returns NULL on any error.
818 */
819u_char *
820asn_build_null(u_char * data, int *datalength, u_char type)
821/* u_char *data; IN - pointer to start of object */
822/* int *datalength; IN/OUT - # of valid bytes left in buf */
823/* u_char type; IN - ASN type of object */
824{
825 /*
826 * ASN.1 null ::= 0x05 0x00
827 */
828 return (asn_build_header_with_truth(data, datalength, type, 0, 1));
829}
830
831/*
832 * To do: Write an asn_parse_exception function to go with the new
833 * asn_build_exception function below so that the exceptional values can
834 * be handled in input packets as well as output ones.
835 */
836
837/*
838 * asn_build_exception - Builds an ASN exception object.
839 * On entry, datalength is input as the number of valid bytes following
840 * "data". On exit, it is returned as the number of valid bytes
841 * following the beginning of the next object.
842 *
843 * Returns a pointer to the first byte past the end
844 * of this object (i.e. the start of the next object).
845 * Returns NULL on any error.
846 *
847 * ASN.1 variable exception ::= 0x8i 0x00, where 'i' is one of these
848 * exception identifiers:
849 * 0 -- noSuchObject
850 * 1 -- noSuchInstance
851 * 2 -- endOfMibView
852 */
853u_char *
854asn_build_exception(u_char * data, int *datalength, u_char type)
855/* u_char *data; IN - pointer to start of object */
856/* int *datalength; IN/OUT - # of valid bytes left in buf */
857/* u_char type; IN - ASN type of object */
858{
859 return (asn_build_header_with_truth(data, datalength, type, 0, 1));
860}
861
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:727
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:854
u_char * asn_build_null(u_char *data, int *datalength, u_char type)
Definition asn1.c:820
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