1 #ifndef ASN1_H
2 #define ASN1_H
3 
4 #include <net-snmp/library/oid.h>
5 
6 #ifdef __cplusplus
7 extern          "C" {
8 #endif
9 
10 #define PARSE_PACKET	0
11 #define DUMP_PACKET	1
12 
13     /*
14      * Definitions for Abstract Syntax Notation One, ASN.1
15      * As defined in ISO/IS 8824 and ISO/IS 8825
16      *
17      *
18      */
19 /***********************************************************
20 	Copyright 1988, 1989 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  * Portions of this file are copyrighted by:
42  * Copyright (c) 2016 VMware, Inc. All rights reserved.
43  * Use is subject to license terms specified in the COPYING file
44  */
45 
46 #define MIN_OID_LEN	    2
47 #define MAX_OID_LEN	    128 /* max subid's in an oid */
48 #ifndef MAX_NAME_LEN            /* conflicts with some libraries */
49 #define MAX_NAME_LEN	    MAX_OID_LEN /* obsolete. use MAX_OID_LEN */
50 #endif
51 
52 #define OID_LENGTH(x)  (sizeof(x)/sizeof(oid))
53 
54 
55 #define ASN_BOOLEAN	    0x01U
56 #define ASN_INTEGER	    0x02U
57 #define ASN_BIT_STR	    0x03U
58 #define ASN_OCTET_STR	    0x04U
59 #define ASN_NULL	    0x05U
60 #define ASN_OBJECT_ID	    0x06U
61 #define ASN_SEQUENCE	    0x10U
62 #define ASN_SET		    0x11U
63 
64 #define ASN_UNIVERSAL	    0x00U
65 #define ASN_APPLICATION     0x40U
66 #define ASN_CONTEXT	    0x80U
67 #define ASN_PRIVATE	    0xC0U
68 
69 #define ASN_PRIMITIVE	    0x00U
70 #define ASN_CONSTRUCTOR	    0x20U
71 
72 #define ASN_LONG_LEN	    0x80U
73 #define ASN_EXTENSION_ID    0x1FU
74 #define ASN_BIT8	    0x80U
75 
76 #define IS_CONSTRUCTOR(byte)	((byte) & ASN_CONSTRUCTOR)
77 #define IS_EXTENSION_ID(byte)	(((byte) & ASN_EXTENSION_ID) == ASN_EXTENSION_ID)
78 
79     struct counter64 {
80         u_long          high;
81         u_long          low;
82     };
83 
84 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
85     typedef struct counter64 integer64;
86     typedef struct counter64 unsigned64;
87 
88     /*
89      * The BER inside an OPAQUE is an context specific with a value of 48 (0x30)
90      * plus the "normal" tag. For a Counter64, the tag is 0x46 (i.e., an
91      * applications specific tag with value 6). So the value for a 64 bit
92      * counter is 0x46 + 0x30, or 0x76 (118 base 10). However, values
93      * greater than 30 can not be encoded in one octet. So the first octet
94      * has the class, in this case context specific (ASN_CONTEXT), and
95      * the special value (i.e., 31) to indicate that the real value follows
96      * in one or more octets. The high order bit of each following octet
97      * indicates if the value is encoded in additional octets. A high order
98      * bit of zero, indicates the last. For this "hack", only one octet
99      * will be used for the value.
100      */
101 
102     /*
103      * first octet of the tag
104      */
105 #define ASN_OPAQUE_TAG1 (ASN_CONTEXT | ASN_EXTENSION_ID)
106     /*
107      * base value for the second octet of the tag - the
108      * second octet was the value for the tag
109      */
110 #define ASN_OPAQUE_TAG2 0x30U
111 
112 #define ASN_OPAQUE_TAG2U 0x2fU /* second octet of tag for union */
113 
114     /*
115      * All the ASN.1 types for SNMP "should have been" defined in this file,
116      * but they were not. (They are defined in snmp_impl.h)  Thus, the tag for
117      * Opaque and Counter64 is defined, again, here with a different names.
118      */
119 #define ASN_APP_OPAQUE (ASN_APPLICATION | 4)
120 #define ASN_APP_COUNTER64 (ASN_APPLICATION | 6)
121 #define ASN_APP_FLOAT (ASN_APPLICATION | 8)
122 #define ASN_APP_DOUBLE (ASN_APPLICATION | 9)
123 #define ASN_APP_I64 (ASN_APPLICATION | 10)
124 #define ASN_APP_U64 (ASN_APPLICATION | 11)
125 #define ASN_APP_UNION (ASN_PRIVATE | 1) /* or ASN_PRIV_UNION ? */
126 
127     /*
128      * value for Counter64
129      */
130 #define ASN_OPAQUE_COUNTER64 (ASN_OPAQUE_TAG2 + ASN_APP_COUNTER64)
131     /*
132      * max size of BER encoding of Counter64
133      */
134 #define ASN_OPAQUE_COUNTER64_MX_BER_LEN 12
135 
136     /*
137      * value for Float
138      */
139 #define ASN_OPAQUE_FLOAT (ASN_OPAQUE_TAG2 + ASN_APP_FLOAT)
140     /*
141      * size of BER encoding of Float
142      */
143 #define ASN_OPAQUE_FLOAT_BER_LEN 7
144 
145     /*
146      * value for Double
147      */
148 #define ASN_OPAQUE_DOUBLE (ASN_OPAQUE_TAG2 + ASN_APP_DOUBLE)
149     /*
150      * size of BER encoding of Double
151      */
152 #define ASN_OPAQUE_DOUBLE_BER_LEN 11
153 
154     /*
155      * value for Integer64
156      */
157 #define ASN_OPAQUE_I64 (ASN_OPAQUE_TAG2 + ASN_APP_I64)
158     /*
159      * max size of BER encoding of Integer64
160      */
161 #define ASN_OPAQUE_I64_MX_BER_LEN 11
162 
163     /*
164      * value for Unsigned64
165      */
166 #define ASN_OPAQUE_U64 (ASN_OPAQUE_TAG2 + ASN_APP_U64)
167     /*
168      * max size of BER encoding of Unsigned64
169      */
170 #define ASN_OPAQUE_U64_MX_BER_LEN 12
171 
172 #endif                          /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
173 
174 
175 #define ASN_PRIV_INCL_RANGE (ASN_PRIVATE | 2)
176 #define ASN_PRIV_EXCL_RANGE (ASN_PRIVATE | 3)
177 #define ASN_PRIV_DELEGATED  (ASN_PRIVATE | 5)
178 #define ASN_PRIV_IMPLIED_OCTET_STR  (ASN_PRIVATE | ASN_OCTET_STR)       /* 4 */
179 #define ASN_PRIV_IMPLIED_OBJECT_ID  (ASN_PRIVATE | ASN_OBJECT_ID)       /* 6 */
180 #define ASN_PRIV_RETRY      (ASN_PRIVATE | 7)   /* 199 */
181 #define ASN_PRIV_STOP       (ASN_PRIVATE | 8)   /* 200 */
182 #define IS_DELEGATED(x)   ((x) == ASN_PRIV_DELEGATED)
183 
184 
185     NETSNMP_IMPORT
186     int             asn_check_packet(u_char *, size_t);
187     NETSNMP_IMPORT
188     u_char         *asn_parse_int(u_char *, size_t *, u_char *, long *,
189                                   size_t);
190     NETSNMP_IMPORT
191     u_char         *asn_build_int(u_char *, size_t *, u_char, const long *,
192                                   size_t);
193     NETSNMP_IMPORT
194     u_char         *asn_parse_unsigned_int(u_char *, size_t *, u_char *,
195                                            u_long *, size_t);
196     NETSNMP_IMPORT
197     u_char         *asn_build_unsigned_int(u_char *, size_t *, u_char,
198                                            const u_long *, size_t);
199     NETSNMP_IMPORT
200     u_char         *asn_parse_string(u_char *, size_t *, u_char *,
201                                      u_char *, size_t *);
202     NETSNMP_IMPORT
203     u_char         *asn_build_string(u_char *, size_t *, u_char,
204                                      const u_char *, size_t);
205     NETSNMP_IMPORT
206     u_char         *asn_parse_header(u_char *, size_t *, u_char *);
207     NETSNMP_IMPORT
208     u_char         *asn_parse_sequence(u_char *, size_t *, u_char *, u_char expected_type,      /* must be this type */
209                                        const char *estr);       /* error message prefix */
210     NETSNMP_IMPORT
211     u_char         *asn_build_header(u_char *, size_t *, u_char, size_t);
212     NETSNMP_IMPORT
213     u_char         *asn_build_sequence(u_char *, size_t *, u_char, size_t);
214     NETSNMP_IMPORT
215     u_char         *asn_parse_length(u_char *, u_long *);
216     NETSNMP_IMPORT
217     u_char         *asn_build_length(u_char *, size_t *, size_t);
218     NETSNMP_IMPORT
219     u_char         *asn_parse_objid(u_char *, size_t *, u_char *, oid *,
220                                     size_t *);
221     NETSNMP_IMPORT
222     u_char         *asn_build_objid(u_char *, size_t *, u_char, oid *,
223                                     size_t);
224     NETSNMP_IMPORT
225     u_char         *asn_parse_null(u_char *, size_t *, u_char *);
226     NETSNMP_IMPORT
227     u_char         *asn_build_null(u_char *, size_t *, u_char);
228     NETSNMP_IMPORT
229     u_char         *asn_parse_bitstring(u_char *, size_t *, u_char *,
230                                         u_char *, size_t *);
231     NETSNMP_IMPORT
232     u_char         *asn_build_bitstring(u_char *, size_t *, u_char,
233                                         const u_char *, size_t);
234     NETSNMP_IMPORT
235     u_char         *asn_parse_unsigned_int64(u_char *, size_t *, u_char *,
236                                              struct counter64 *, size_t);
237     NETSNMP_IMPORT
238     u_char         *asn_build_unsigned_int64(u_char *, size_t *, u_char,
239                                              const struct counter64 *, size_t);
240     NETSNMP_IMPORT
241     u_char         *asn_parse_signed_int64(u_char *, size_t *, u_char *,
242                                            struct counter64 *, size_t);
243     NETSNMP_IMPORT
244     u_char         *asn_build_signed_int64(u_char *, size_t *, u_char,
245                                            const struct counter64 *, size_t);
246     NETSNMP_IMPORT
247     u_char         *asn_build_float(u_char *, size_t *, u_char, const float *,
248                                     size_t);
249     NETSNMP_IMPORT
250     u_char         *asn_parse_float(u_char *, size_t *, u_char *, float *,
251                                     size_t);
252     NETSNMP_IMPORT
253     u_char         *asn_build_double(u_char *, size_t *, u_char, const double *,
254                                      size_t);
255     NETSNMP_IMPORT
256     u_char         *asn_parse_double(u_char *, size_t *, u_char *,
257                                      double *, size_t);
258 
259 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
260 
261     /*
262      * Re-allocator function for below.
263      */
264 
265     NETSNMP_IMPORT
266     int             asn_realloc(u_char **, size_t *);
267 
268     /*
269      * Re-allocating reverse ASN.1 encoder functions.  Synopsis:
270      *
271      * u_char *buf = (u_char*)malloc(100);
272      * u_char type = (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
273      * size_t buf_len = 100, offset = 0;
274      * long data = 12345;
275      * int allow_realloc = 1;
276      *
277      * if (asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
278      * type, &data, sizeof(long)) == 0) {
279      * error;
280      * }
281      *
282      * NOTE WELL: after calling one of these functions with allow_realloc
283      * non-zero, buf might have moved, buf_len might have grown and
284      * offset will have increased by the size of the encoded data.
285      * You should **NEVER** do something like this:
286      *
287      * u_char *buf = (u_char *)malloc(100), *ptr;
288      * u_char type = (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
289      * size_t buf_len = 100, offset = 0;
290      * long data1 = 1234, data2 = 5678;
291      * int rc = 0, allow_realloc = 1;
292      *
293      * rc  = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
294      * type, &data1, sizeof(long));
295      * ptr = buf[buf_len - offset];   / * points at encoding of data1 * /
296      * if (rc == 0) {
297      * error;
298      * }
299      * rc  = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
300      * type, &data2, sizeof(long));
301      * make use of ptr here;
302      *
303      *
304      * ptr is **INVALID** at this point.  In general, you should store the
305      * offset value and compute pointers when you need them:
306      *
307      *
308      *
309      * u_char *buf = (u_char *)malloc(100), *ptr;
310      * u_char type = (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
311      * size_t buf_len = 100, offset = 0, ptr_offset;
312      * long data1 = 1234, data2 = 5678;
313      * int rc = 0, allow_realloc = 1;
314      *
315      * rc  = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
316      * type, &data1, sizeof(long));
317      * ptr_offset = offset;
318      * if (rc == 0) {
319      * error;
320      * }
321      * rc  = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
322      * type, &data2, sizeof(long));
323      * ptr = buf + buf_len - ptr_offset
324      * make use of ptr here;
325      *
326      *
327      *
328      * Here, you can see that ptr will be a valid pointer even if the block of
329      * memory has been moved, as it may well have been.  Plenty of examples of
330      * usage all over asn1.c, snmp_api.c, snmpusm.c.
331      *
332      * The other thing you should **NEVER** do is to pass a pointer to a buffer
333      * on the stack as the first argument when allow_realloc is non-zero, unless
334      * you really know what you are doing and your machine/compiler allows you to
335      * free non-heap memory.  There are rumours that such things exist, but many
336      * consider them no more than the wild tales of a fool.
337      *
338      * Of course, you can pass allow_realloc as zero, to indicate that you do not
339      * wish the packet buffer to be reallocated for some reason; perhaps because
340      * it is on the stack.  This may be useful to emulate the functionality of
341      * the old API:
342      *
343      * u_char my_static_buffer[100], *cp = NULL;
344      * size_t my_static_buffer_len = 100;
345      * float my_pi = (float)22/(float)7;
346      *
347      * cp = asn_rbuild_float(my_static_buffer, &my_static_buffer_len,
348      * ASN_OPAQUE_FLOAT, &my_pi, sizeof(float));
349      * if (cp == NULL) {
350      * error;
351      * }
352      *
353      *
354      * IS EQUIVALENT TO:
355      *
356      *
357      * u_char my_static_buffer[100];
358      * size_t my_static_buffer_len = 100, my_offset = 0;
359      * float my_pi = (float)22/(float)7;
360      * int rc = 0;
361      *
362      * rc = asn_realloc_rbuild_float(&my_static_buffer, &my_static_buffer_len,
363      * &my_offset, 0,
364      * ASN_OPAQUE_FLOAT, &my_pi, sizeof(float));
365      * if (rc == 0) {
366      * error;
367      * }
368      *
369      *
370      */
371 
372 
373     NETSNMP_IMPORT
374     int             asn_realloc_rbuild_int(u_char ** pkt, size_t * pkt_len,
375                                            size_t * offset,
376                                            int allow_realloc, u_char type,
377                                            const long *data, size_t data_size);
378 
379     NETSNMP_IMPORT
380     int             asn_realloc_rbuild_string(u_char ** pkt,
381                                               size_t * pkt_len,
382                                               size_t * offset,
383                                               int allow_realloc,
384                                               u_char type,
385                                               const u_char * data,
386                                               size_t data_size);
387 
388     NETSNMP_IMPORT
389     int             asn_realloc_rbuild_unsigned_int(u_char ** pkt,
390                                                     size_t * pkt_len,
391                                                     size_t * offset,
392                                                     int allow_realloc,
393                                                     u_char type,
394                                                     const u_long * data,
395                                                     size_t data_size);
396 
397     NETSNMP_IMPORT
398     int             asn_realloc_rbuild_header(u_char ** pkt,
399                                               size_t * pkt_len,
400                                               size_t * offset,
401                                               int allow_realloc,
402                                               u_char type,
403                                               size_t data_size);
404 
405     NETSNMP_IMPORT
406     int             asn_realloc_rbuild_sequence(u_char ** pkt,
407                                                 size_t * pkt_len,
408                                                 size_t * offset,
409                                                 int allow_realloc,
410                                                 u_char type,
411                                                 size_t data_size);
412 
413     NETSNMP_IMPORT
414     int             asn_realloc_rbuild_length(u_char ** pkt,
415                                               size_t * pkt_len,
416                                               size_t * offset,
417                                               int allow_realloc,
418                                               size_t data_size);
419 
420     NETSNMP_IMPORT
421     int             asn_realloc_rbuild_objid(u_char ** pkt,
422                                              size_t * pkt_len,
423                                              size_t * offset,
424                                              int allow_realloc,
425                                              u_char type, const oid *,
426                                              size_t);
427 
428     NETSNMP_IMPORT
429     int             asn_realloc_rbuild_null(u_char ** pkt,
430                                             size_t * pkt_len,
431                                             size_t * offset,
432                                             int allow_realloc,
433                                             u_char type);
434 
435     NETSNMP_IMPORT
436     int             asn_realloc_rbuild_bitstring(u_char ** pkt,
437                                                  size_t * pkt_len,
438                                                  size_t * offset,
439                                                  int allow_realloc,
440                                                  u_char type,
441                                                  const u_char * data,
442                                                  size_t data_size);
443 
444     NETSNMP_IMPORT
445     int             asn_realloc_rbuild_unsigned_int64(u_char ** pkt,
446                                                       size_t * pkt_len,
447                                                       size_t * offset,
448                                                       int allow_realloc,
449                                                       u_char type,
450                                                       struct counter64
451                                                       const *data, size_t);
452 
453     NETSNMP_IMPORT
454     int             asn_realloc_rbuild_signed_int64(u_char ** pkt,
455                                                     size_t * pkt_len,
456                                                     size_t * offset,
457                                                     int allow_realloc,
458                                                     u_char type,
459                                                     const struct counter64 *data,
460                                                     size_t);
461 
462     NETSNMP_IMPORT
463     int             asn_realloc_rbuild_float(u_char ** pkt,
464                                              size_t * pkt_len,
465                                              size_t * offset,
466                                              int allow_realloc,
467                                              u_char type, const float *data,
468                                              size_t data_size);
469 
470     NETSNMP_IMPORT
471     int             asn_realloc_rbuild_double(u_char ** pkt,
472                                               size_t * pkt_len,
473                                               size_t * offset,
474                                               int allow_realloc,
475                                               u_char type, const double *data,
476                                               size_t data_size);
477 #endif
478 
479 #ifdef __cplusplus
480 }
481 #endif
482 #endif                          /* ASN1_H */
483