Annotation of embedaddon/libnet/src/libnet_asn1.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *  $Id: libnet_asn1.c,v 1.5 2004/01/03 20:31:01 mike Exp $
        !             3:  *
        !             4:  *  libnet 1.1
        !             5:  *  libnet_asn1.c -  Abstract Syntax Notation One routines
        !             6:  *
        !             7:  *  Abstract Syntax Notation One, ASN.1
        !             8:  *  As defined in ISO/IS 8824 and ISO/IS 8825
        !             9:  *  This implements a subset of the above International Standards that
        !            10:  *  is sufficient to implement SNMP.
        !            11:  *
        !            12:  *  Encodes abstract data types into a machine independent stream of bytes.
        !            13:  *
        !            14:  *  Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
        !            15:  *  All rights reserved.
        !            16:  *
        !            17:  *  Permission to use, copy, modify, and distribute this software and its
        !            18:  *  documentation for any purpose and without fee is hereby granted,
        !            19:  *  provided that the above copyright notice appear in all copies and that
        !            20:  *  both that copyright notice and this permission notice appear in
        !            21:  *  supporting documentation, and that the name of CMU not be
        !            22:  *  used in advertising or publicity pertaining to distribution of the
        !            23:  *  software without specific, written prior permission.
        !            24:  *
        !            25:  *  CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            26:  *  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            27:  *  CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            28:  *  ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            29:  *  WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            30:  *  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            31:  *  SOFTWARE.
        !            32:  *
        !            33:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
        !            34:  *  All rights reserved.
        !            35:  *
        !            36:  * Copyright (c) 1993, 1994, 1995, 1996, 1998
        !            37:  *     The Regents of the University of California.  All rights reserved.
        !            38:  *
        !            39:  * Redistribution and use in source and binary forms, with or without
        !            40:  * modification, are permitted provided that: (1) source code distributions
        !            41:  * retain the above copyright notice and this paragraph in its entirety, (2)
        !            42:  * distributions including binary code include the above copyright notice and
        !            43:  * this paragraph in its entirety in the documentation or other materials
        !            44:  * provided with the distribution, and (3) all advertising materials mentioning
        !            45:  * features or use of this software display the following acknowledgement:
        !            46:  * ``This product includes software developed by the University of California,
        !            47:  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
        !            48:  * the University nor the names of its contributors may be used to endorse
        !            49:  * or promote products derived from this software without specific prior
        !            50:  * written permission.
        !            51:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            52:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            53:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            54:  */
        !            55: 
        !            56: #if (HAVE_CONFIG_H)
        !            57: #include "../include/config.h"
        !            58: #endif
        !            59: #if (!(_WIN32) || (__CYGWIN__)) 
        !            60: #include "../include/libnet.h"
        !            61: #else
        !            62: #include "../include/win32/libnet.h"
        !            63: #endif
        !            64: 
        !            65: u_int8_t *
        !            66: libnet_build_asn1_int(u_int8_t *data, int *datalen, u_int8_t type, int32_t *int_p,
        !            67:             int int_s)
        !            68: {
        !            69:     /*
        !            70:      *  ASN.1 integer ::= 0x02 asnlength byte {byte}*
        !            71:      */
        !            72:      register int32_t integer;
        !            73:      register u_int32_t mask;
        !            74: 
        !            75:     if (int_s != sizeof (int32_t))
        !            76:     {
        !            77:         return (NULL);
        !            78:     }
        !            79:     integer = *int_p;
        !            80: 
        !            81:     /*
        !            82:      *  Truncate "unnecessary" bytes off of the most significant end of this
        !            83:      *  2's complement integer.  There should be no sequence of 9 consecutive
        !            84:      *  1's or 0's at the most significant end of the integer.
        !            85:      */
        !            86:     mask = ((u_int32_t) 0x1FF) << ((8 * (sizeof (int32_t) - 1)) - 1);
        !            87:     /* mask is 0xFF800000 on a big-endian machine */
        !            88: 
        !            89:     while ((((integer & mask) == 0) || ((integer & mask) == mask)) && int_s > 1)
        !            90:     {
        !            91:         int_s--;
        !            92:         integer <<= 8;
        !            93:     }
        !            94: 
        !            95:     data = libnet_build_asn1_header(data, datalen, type, int_s);
        !            96: 
        !            97:     if (data == NULL || *datalen < int_s)
        !            98:     {
        !            99:         return (NULL);
        !           100:     }
        !           101: 
        !           102:     *datalen -= int_s;
        !           103: 
        !           104:     mask = ((u_int32_t) 0xFF) << (8 * (sizeof(int32_t) - 1));
        !           105:     /* mask is 0xFF000000 on a big-endian machine */
        !           106: 
        !           107:     while (int_s--)
        !           108:     {
        !           109:         *data++ = (u_int8_t)((integer & mask) >> (8 * (sizeof (int32_t) - 1)));
        !           110:         integer <<= 8;
        !           111:     }
        !           112:     return (data);
        !           113: }
        !           114: 
        !           115: 
        !           116: u_int8_t *
        !           117: libnet_build_asn1_uint(u_int8_t *data, int *datalen, u_int8_t type, u_int32_t *int_p,
        !           118:             int int_s)
        !           119: {
        !           120:     /*
        !           121:      *  ASN.1 integer ::= 0x02 asnlength byte {byte}*
        !           122:      */
        !           123:     register u_int32_t integer;
        !           124:     register u_int32_t mask;
        !           125:     int add_null_byte = 0;
        !           126: 
        !           127:     if (int_s != sizeof (int32_t))
        !           128:     {
        !           129:         return (NULL);
        !           130:     }
        !           131:     integer = *int_p;
        !           132: 
        !           133:     mask = ((u_int32_t) 0xFF) << (8 * (sizeof (int32_t) - 1));
        !           134:     /* mask is 0xFF000000 on a big-endian machine */
        !           135: 
        !           136:     if ((u_int8_t)((integer & mask) >> (8 * (sizeof (int32_t) - 1))) & 0x80)
        !           137:     {
        !           138:         /* if MSB is set */
        !           139:         add_null_byte = 1;
        !           140:         int_s++;
        !           141:     }
        !           142:     else
        !           143:     {
        !           144:         /*
        !           145:          * Truncate "unnecessary" bytes off of the most significant end of this
        !           146:          * 2's complement integer.  There should be no sequence of 9
        !           147:          * consecutive 1's or 0's at the most significant end of the
        !           148:          * integer.
        !           149:          */
        !           150:         mask = ((u_int32_t) 0x1FF) << ((8 * (sizeof(int32_t) - 1)) - 1);
        !           151:         /* mask is 0xFF800000 on a big-endian machine */
        !           152: 
        !           153:         while (((integer & mask) == 0) && int_s > 1)
        !           154:         {
        !           155:             int_s--;
        !           156:             integer <<= 8;
        !           157:         }
        !           158:     }
        !           159: 
        !           160:     data = libnet_build_asn1_header(data, datalen, type, int_s);
        !           161: 
        !           162:     if (data == NULL || *datalen < int_s)
        !           163:     {
        !           164:         return (NULL);
        !           165:     }
        !           166: 
        !           167:     *datalen -= int_s;
        !           168: 
        !           169:     if (add_null_byte == 1)
        !           170:     {
        !           171:         *data++ = '\0';
        !           172:         int_s--;
        !           173:     }
        !           174: 
        !           175:     mask = ((u_int32_t) 0xFF) << (8 * (sizeof(int32_t) - 1));
        !           176:     /* mask is 0xFF000000 on a big-endian machine */
        !           177: 
        !           178:     while (int_s--)
        !           179:     {
        !           180:         *data++ = (u_int8_t)((integer & mask) >> (8 * (sizeof (int32_t) - 1)));
        !           181:         integer <<= 8;
        !           182:     }
        !           183:     return (data);
        !           184: }
        !           185: 
        !           186: 
        !           187: u_int8_t *
        !           188: libnet_build_asn1_string(u_int8_t *data, int *datalen, u_int8_t type,
        !           189:             u_int8_t *string, int str_s)
        !           190: {
        !           191: 
        !           192:     /*
        !           193:      *  ASN.1 octet string ::= primstring | cmpdstring
        !           194:      *  primstring ::= 0x04 asnlength byte {byte}*
        !           195:      *  cmpdstring ::= 0x24 asnlength string {string}*
        !           196:      *  This code will never send a compound string.
        !           197:      */
        !           198:     data = libnet_build_asn1_header(data, datalen, type, str_s);
        !           199: 
        !           200:     if (data == NULL || *datalen < str_s)
        !           201:     {
        !           202:         return (NULL);
        !           203:     }
        !           204:     memmove(data, string, str_s);
        !           205:     *datalen -= str_s;
        !           206: 
        !           207:     return (data + str_s);
        !           208: }
        !           209: 
        !           210: 
        !           211: u_int8_t *
        !           212: libnet_build_asn1_header(u_int8_t *data, int *datalen, u_int8_t type, int len)
        !           213: {
        !           214:     if (*datalen < 1)
        !           215:     {
        !           216:         return (NULL);
        !           217:     }
        !           218:     *data++ = type;
        !           219:     (*datalen)--;
        !           220: 
        !           221:     return (libnet_build_asn1_length(data, datalen, len));
        !           222: }
        !           223: 
        !           224: 
        !           225: u_int8_t *
        !           226: libnet_build_asn1_sequence(u_int8_t *data, int *datalen, u_int8_t type, int len)
        !           227: {
        !           228:     *datalen -= 4;
        !           229:     if (*datalen < 0)
        !           230:     {
        !           231:         *datalen += 4;       /* fix up before punting */
        !           232:         return (NULL);
        !           233:     }
        !           234:     *data++ = type;
        !           235:     *data++ = (u_int8_t)(0x02 | ASN_LONG_LEN);
        !           236:     *data++ = (u_int8_t)((len >> 8) & 0xFF);
        !           237:     *data++ = (u_int8_t)(len & 0xFF);
        !           238:     return (data);
        !           239: }
        !           240: 
        !           241: 
        !           242: u_int8_t *
        !           243: libnet_build_asn1_length(u_int8_t *data, int *datalen, int len)
        !           244: {
        !           245:     u_int8_t *start_data = data;
        !           246: 
        !           247:     /* no indefinite lengths sent */
        !           248:     if (len < 0x80)
        !           249:     {
        !           250:         if (*datalen < 1)
        !           251:         {
        !           252:             return (NULL);
        !           253:         }
        !           254:         *data++ = (u_int8_t)len;
        !           255:     }
        !           256:     else if (len <= 0xFF)
        !           257:     {
        !           258:         if (*datalen < 2)
        !           259:         {
        !           260:             return (NULL);
        !           261:         }
        !           262:         *data++ = (u_int8_t)(0x01 | ASN_LONG_LEN);
        !           263:         *data++ = (u_int8_t)len;
        !           264:     }
        !           265:     else    /* 0xFF < len <= 0xFFFF */
        !           266:     {
        !           267:         if (*datalen < 3)
        !           268:         {
        !           269:             return (NULL);
        !           270:         }
        !           271:         *data++ = (u_int8_t)(0x02 | ASN_LONG_LEN);
        !           272:         *data++ = (u_int8_t)((len >> 8) & 0xFF);
        !           273:         *data++ = (u_int8_t)(len & 0xFF);
        !           274:     }
        !           275:     *datalen -= (data - start_data);
        !           276:     return (data);
        !           277: }
        !           278: 
        !           279: 
        !           280: u_int8_t *
        !           281: libnet_build_asn1_objid(u_int8_t *data, int *datalen, u_int8_t type, oid *objid,
        !           282:             int objidlen)
        !           283: {
        !           284:     /*
        !           285:      *  ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
        !           286:      *  subidentifier ::= {leadingbyte}* lastbyte
        !           287:      *  leadingbyte ::= 1 7bitvalue
        !           288:      *  lastbyte ::= 0 7bitvalue
        !           289:      */
        !           290:     int asnlen;
        !           291:     register oid *op = objid;
        !           292:     u_int8_t objid_size[MAX_OID_LEN];
        !           293:     register u_int32_t objid_val;
        !           294:     u_int32_t first_objid_val;
        !           295:     register int i;
        !           296: 
        !           297:     /* check if there are at least 2 sub-identifiers */
        !           298:     if (objidlen < 2)
        !           299:     {
        !           300:         /* there are not, so make OID have two with value of zero */
        !           301:         objid_val = 0;
        !           302:         objidlen  = 2;
        !           303:     }
        !           304:     else
        !           305:     {
        !           306:         /* combine the first two values */
        !           307:         objid_val = (op[0] * 40) + op[1];
        !           308:         op += 2;
        !           309:     }
        !           310:     first_objid_val = objid_val;
        !           311: 
        !           312:     /* calculate the number of bytes needed to store the encoded value */
        !           313:     for (i = 1, asnlen = 0;;)
        !           314:     {
        !           315:         if (objid_val < (unsigned)0x80)
        !           316:         {
        !           317:             objid_size[i] = 1;
        !           318:             asnlen += 1;
        !           319:         }
        !           320:         else if (objid_val < (unsigned)0x4000)
        !           321:         {
        !           322:             objid_size[i] = 2;
        !           323:             asnlen += 2;
        !           324:         }
        !           325:         else if (objid_val < (unsigned)0x200000)
        !           326:         {
        !           327:             objid_size[i] = 3;
        !           328:             asnlen += 3;
        !           329:         }
        !           330:         else if (objid_val < (unsigned)0x10000000)
        !           331:         {
        !           332:             objid_size[i] = 4;
        !           333:             asnlen += 4;
        !           334:         }
        !           335:         else
        !           336:         {
        !           337:             objid_size[i] = 5;
        !           338:             asnlen += 5;
        !           339:         }
        !           340:         i++;
        !           341:         if (i >= objidlen)
        !           342:         {
        !           343:             break;
        !           344:         }
        !           345:         objid_val = *op++;
        !           346:     }
        !           347: 
        !           348:     /* store the ASN.1 tag and length */
        !           349:     data = libnet_build_asn1_header(data, datalen, type, asnlen);
        !           350:     if (data == NULL || *datalen < asnlen)
        !           351:     {
        !           352:         return (NULL);
        !           353:     }
        !           354: 
        !           355:     /* store the encoded OID value */
        !           356:     for (i = 1, objid_val = first_objid_val, op = objid + 2; i < objidlen; i++)
        !           357:     {
        !           358:         if (i != 1)
        !           359:         {
        !           360:             objid_val = *op++;
        !           361:         }
        !           362:         switch (objid_size[i])
        !           363:         {
        !           364:             case 1:
        !           365:                 *data++ = (u_int8_t)objid_val;
        !           366:                 break;
        !           367: 
        !           368:             case 2:
        !           369:                 *data++ = (u_int8_t)((objid_val >> 7) | 0x80);
        !           370:                 *data++ = (u_int8_t)(objid_val & 0x07f);
        !           371:                 break;
        !           372:             case 3:
        !           373:                 *data++ = (u_int8_t)((objid_val >> 14) | 0x80);
        !           374:                 *data++ = (u_int8_t)((objid_val >> 7 & 0x7f) | 0x80);
        !           375:                 *data++ = (u_int8_t)(objid_val & 0x07f);
        !           376:                 break;
        !           377: 
        !           378:             case 4:
        !           379:                 *data++ = (u_int8_t)((objid_val >> 21) | 0x80);
        !           380:                 *data++ = (u_int8_t)((objid_val >> 14 & 0x7f) | 0x80);
        !           381:                 *data++ = (u_int8_t)((objid_val >> 7 & 0x7f) | 0x80);
        !           382:                 *data++ = (u_int8_t)(objid_val & 0x07f);
        !           383:                 break;
        !           384: 
        !           385:             case 5:
        !           386:                 *data++ = (u_int8_t)((objid_val >> 28) | 0x80);
        !           387:                 *data++ = (u_int8_t)((objid_val >> 21 & 0x7f) | 0x80);
        !           388:                 *data++ = (u_int8_t)((objid_val >> 14 & 0x7f) | 0x80);
        !           389:                 *data++ = (u_int8_t)((objid_val >> 7 & 0x7f) | 0x80);
        !           390:                 *data++ = (u_int8_t)(objid_val & 0x07f);
        !           391:                 break;
        !           392:         }
        !           393:     }
        !           394: 
        !           395:     /* return the length and data ptagr */
        !           396:     *datalen -= asnlen;
        !           397:     return (data);
        !           398: }
        !           399: 
        !           400: 
        !           401: u_int8_t *
        !           402: libnet_build_asn1_null(u_int8_t *data, int *datalen, u_int8_t type)
        !           403: {
        !           404:     /*
        !           405:      *  ASN.1 null ::= 0x05 0x00
        !           406:      */       
        !           407:     return (libnet_build_asn1_header(data, datalen, type, 0));
        !           408: }
        !           409: 
        !           410: 
        !           411: u_int8_t *
        !           412: libnet_build_asn1_bitstring(u_int8_t *data, int *datalen, u_int8_t type,
        !           413:             u_int8_t *string, int str_s)
        !           414: {
        !           415: 
        !           416:     /*
        !           417:      *  ASN.1 bit string ::= 0x03 asnlength unused {byte}*
        !           418:      */
        !           419:     if (str_s < 1 || *string > 7)
        !           420:     {
        !           421:         return (NULL);
        !           422:     }
        !           423:     data = libnet_build_asn1_header(data, datalen, type, str_s);
        !           424: 
        !           425:     if (data == NULL || *datalen < str_s)
        !           426:     {
        !           427:         return (NULL);
        !           428:     }
        !           429: 
        !           430:     memmove(data, string, str_s);
        !           431:     *datalen -= str_s;
        !           432: 
        !           433:     return (data + str_s);
        !           434: }
        !           435: 
        !           436: /* EOF */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>