Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

asn1.c

Go to the documentation of this file.
00001 /**
00002 **  @file       asn1.c
00003 **
00004 **  @author     Daniel Roelker <droelker@sourcefire.com>
00005 **
00006 **  @brief      ASN.1 Decoding API for BER and DER encodings.
00007 **
00008 **  Copyright (C) 2004, Daniel Roelker and Sourcefire, Inc.
00009 **
00010 **  ASN.1 decoding functions that incorporate an internal stack for
00011 **  processing.  That way we don't have to worry about attackers trying
00012 **  to overload the machine stack.
00013 **
00014 **  Handles both DER and BER encodings, and also the indefinite encoding 
00015 **  that BER supports.  Lots of functionality can be added on top of
00016 **  this library.  SNMP will probably be the first.
00017 **
00018 **  NOTES:
00019 **    - Stop using global variables so we can have multiple instances,
00020 **      but we don't need that functionality right now.
00021 */  
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <ctype.h>
00027 #include <sys/types.h>
00028 
00029 #ifdef WIN32
00030 #include <winsock.h>
00031 #endif
00032 
00033 #include "asn1.h"
00034 
00035 /*
00036 **  Macros
00037 */
00038 #define SF_ASN1_CLASS(c)   (((u_char)c) & SF_ASN1_CLASS_MASK)
00039 #define SF_ASN1_FLAG(c)    (((u_char)c) & SF_ASN1_FLAG_MASK)
00040 #define SF_ASN1_TAG(c)     (((u_char)c) & SF_ASN1_TAG_MASK)
00041 #define SF_ASN1_LEN_EXT(c) (((u_char)c) & SF_BER_LEN_MASK)
00042 
00043 #define ASN1_OOB(s,e,d)      (!(((s) <= (d)) && ((d) < (e))))
00044 #define ASN1_FATAL_ERR(e)    ((e) < 0)
00045 #define ASN1_NONFATAL_ERR(e) ((e) > 0)
00046 
00047 #define ASN1_MAX_STACK 128
00048 
00049 static ASN1_TYPE *g_asn1_mem        = NULL;
00050 static int        g_asn1_max_nodes  = 0;
00051 static int        g_asn1_node_index = 0;
00052 
00053 /*
00054 **  NAME
00055 **    asn1_init_node_index::
00056 */
00057 /**
00058 **  This function should get called whenever we decode a new ASN.1
00059 **  string to initialize the memory.
00060 **
00061 **  @return void
00062 */
00063 static void asn1_init_node_index(void)
00064 {
00065     g_asn1_node_index = 0;
00066 
00067     return;
00068 }
00069 
00070 /*
00071 **  NAME
00072 **    asn1_node_alloc::
00073 */
00074 /**
00075 **  Allocate an ASN1_NODE.
00076 **
00077 **  @return ASN1_TYPE *
00078 **
00079 **  @retval NULL memory allocation failed
00080 **  @retval !NULL function successful
00081 */
00082 static ASN1_TYPE *asn1_node_alloc(void)
00083 {
00084     if(!g_asn1_mem || (g_asn1_max_nodes <= g_asn1_node_index))
00085         return NULL;
00086 
00087     return &g_asn1_mem[g_asn1_node_index++];
00088 }
00089 
00090 /*
00091 **  NAME
00092 **    asn1_init_mem::
00093 */
00094 /**
00095 **  This function initializes the number of nodes that we want to track in
00096 **  an ASN.1 decode.  Pass in the max number of nodes for an ASN.1 decode and
00097 **  we will track that many.
00098 **
00099 **  @return integer
00100 **
00101 **  @retval ASN1_OK function successful
00102 **  @retval ASN1_ERR_MEM_ALLOC memory allocation failed
00103 **  @retval ASN1_ERR_INVALID_ARG invalid argument
00104 */
00105 int asn1_init_mem(int iNodes)
00106 {
00107     if(iNodes <= 0)
00108         return ASN1_ERR_INVALID_ARG;
00109 
00110     /*
00111     **  This makes sure that we don't initialize multiple times.
00112     */
00113     if(g_asn1_mem && g_asn1_max_nodes > 0)
00114         return ASN1_OK;
00115         
00116     g_asn1_mem = (ASN1_TYPE *)malloc(sizeof(ASN1_TYPE)*iNodes);
00117     if(!g_asn1_mem)
00118         return ASN1_ERR_MEM_ALLOC;
00119 
00120     g_asn1_max_nodes = iNodes;
00121 
00122     return ASN1_OK;
00123 }
00124 
00125 /*
00126 **  NAME
00127 **    asn1_decode_tag_num_ext::
00128 */
00129 /**
00130 **  This routine decodes extended tag numbers and checks for overlong
00131 **  tag numbers, etc.
00132 **
00133 **  @param ASN1_DATA ptr to data
00134 **  @param u_int ptr to tag num
00135 **
00136 **  @return integer
00137 **
00138 **  @retval ASN1_OK function successful
00139 **  @retval ASN1_ERR_OVERLONG_LEN tag number too large
00140 **  @retval ASN1_ERR_OOB encoding goes out of bounds
00141 **  @retval ASN1_ERR_NULL_MEM function arguments are NULL
00142 */
00143 static int asn1_decode_tag_num_ext(ASN1_DATA *asn1_data, u_int *tag_num)
00144 {
00145     int   iExtension = 0;
00146     u_int new_tag_num;
00147 
00148     if(!asn1_data || !tag_num)
00149         return ASN1_ERR_NULL_MEM;
00150 
00151     *tag_num = 0;
00152 
00153     /*
00154     **  Loop through the tag type while extension bit is set
00155     */
00156     do
00157     {
00158         /*
00159         **  Is this an extension byte?
00160         */
00161         iExtension = SF_ASN1_LEN_EXT(*asn1_data->data);
00162 
00163         new_tag_num = ((*tag_num << 7) | (*asn1_data->data & 0x7f));
00164         if(*tag_num != 0 && new_tag_num <= *tag_num)
00165         {
00166             return ASN1_ERR_OVERLONG_LEN;
00167         }
00168 
00169         *tag_num = new_tag_num;
00170 
00171         asn1_data->data++;
00172         if(ASN1_OOB(asn1_data->start, asn1_data->end, asn1_data->data))
00173         {
00174             return ASN1_ERR_OOB;
00175         }
00176         
00177     } while(iExtension);
00178 
00179     return ASN1_OK;
00180 }
00181 
00182 /*
00183 **  NAME
00184 **    asn1_decode_ident::
00185 */
00186 /**
00187 **  This function decodes the identifier byte(s) of an ASN.1 structure.
00188 **  We handle long tag numbers and check for overflows in the extended
00189 **  tag numbers.
00190 **
00191 **  @return integer
00192 **
00193 **  @retval ASN1_ERR_NULL_MEM function arguments are NULL
00194 **  @retval ASN1_ERR_OOB buffer out of bounds
00195 **  @retval ASN1_ERR_INVALID_BER_TAG_LEN tag num too large or bad encoding
00196 **  @retval ASN1_OK function ok
00197 */
00198 static int asn1_decode_ident(ASN1_TYPE *asn1_type, ASN1_DATA *asn1_data)
00199 {
00200     ASN1_IDENT *ident;
00201     int iRet;
00202 
00203     if(!asn1_type || !asn1_data)
00204         return ASN1_ERR_NULL_MEM;
00205 
00206     ident = &asn1_type->ident;
00207 
00208     ident->class = SF_ASN1_CLASS(*asn1_data->data);
00209     ident->flag  = SF_ASN1_FLAG(*asn1_data->data);
00210     ident->tag   = SF_ASN1_TAG(*asn1_data->data);
00211 
00212     asn1_data->data++;
00213     if(ASN1_OOB(asn1_data->start, asn1_data->end, asn1_data->data))
00214     {
00215         //printf("** decode_ident:  oob\n");
00216         return ASN1_ERR_OOB;
00217     }
00218 
00219     /*
00220     **  Is tag extended?
00221     */
00222     if(ident->tag == SF_ASN1_TAG_EXTENSION)
00223     {
00224         ident->tag_type = SF_ASN1_TAG_EXTENSION;
00225 
00226         iRet = asn1_decode_tag_num_ext(asn1_data, &ident->tag);
00227         if(iRet)
00228         {
00229             //printf("** decode_ident: ext_len error\n");
00230             return ASN1_ERR_INVALID_BER_TAG_LEN;
00231         }
00232     }
00233 
00234     return ASN1_OK;
00235 }
00236 
00237 /*
00238 **  NAME
00239 **    asn1_decode_len_type::
00240 */
00241 /**
00242 **  Determine the type of len encoding.  Could be short, long or
00243 **  indeterminate.
00244 **
00245 **  @return integer
00246 **
00247 **  @retval SF_BER_LEN_DEF_LONG extended length
00248 **  @retval SF_BER_LEN_DEF_SHORT one byte length < 127
00249 **  @retval SF_BER_LEN_INDEF indeterminate length
00250 */
00251 static int asn1_decode_len_type(u_char *data)
00252 {
00253     int iExt;
00254 
00255     iExt = SF_ASN1_LEN_EXT(*data);
00256     if(iExt)
00257     {
00258         if(*data & 0x7f)
00259         {
00260             return SF_BER_LEN_DEF_LONG;
00261         }
00262         else
00263         {
00264             return SF_BER_LEN_INDEF;
00265         }
00266     }
00267 
00268     return SF_BER_LEN_DEF_SHORT;
00269 }
00270 
00271 /*
00272 **  NAME
00273 **    asn1_decode_len_ext::
00274 */
00275 /**
00276 **  Decode the extended length version.  Basically we read the first
00277 **  byte for the number of bytes in the extended length.  We then read
00278 **  that number of bytes to determine the length.  If the number of bytes
00279 **  in the length is greater than our variable, then we return 
00280 **  ASN1_ERR_OVERLONG_LEN, and exit decoding.
00281 **
00282 **  @return integer
00283 **
00284 **  @retval ASN1_ERR_NULL_MEM function arguments NULL
00285 **  @retval ASN1_ERR_OVERLONG_LEN length to long for us to decode
00286 **  @retval ASN1_ERR_OOB out of bounds condition
00287 **  @retval ASN1_OK function successful
00288 */
00289 static int asn1_decode_len_ext(ASN1_DATA *asn1_data, u_int *size)
00290 {
00291     int iBytes;
00292     int iCtr;
00293     u_int new_size;
00294 
00295     if(!asn1_data || !size)
00296         return ASN1_ERR_NULL_MEM;
00297 
00298     *size = 0;
00299 
00300     iBytes = (*asn1_data->data & 0x7f);
00301     
00302     asn1_data->data++;
00303     if(ASN1_OOB(asn1_data->start, asn1_data->end, asn1_data->data))
00304     {
00305         return ASN1_ERR_OOB;
00306     }
00307 
00308     for(iCtr = 0; iCtr < iBytes; iCtr++)
00309     {
00310         new_size = ((*size << 8) | (*asn1_data->data));
00311 
00312         /*
00313         **  If we've just added some data to the size, and
00314         **  we are still the same or less than the previous
00315         **  size, we've just overflowed our variable
00316         */
00317         if(*size != 0 && new_size <= *size)
00318         {
00319             return ASN1_ERR_OVERLONG_LEN;
00320         }
00321 
00322         *size = new_size;
00323 
00324         asn1_data->data++;
00325         if(ASN1_OOB(asn1_data->start, asn1_data->end, asn1_data->data))
00326         {
00327             /*
00328             **  Check to see if this was just an extended length that was zero at 
00329             **  the end of the buffer.  If it was, then return normal.
00330             */
00331             if(*size == 0 && (iCtr+1) == iBytes)
00332                 break;
00333 
00334             return ASN1_ERR_OOB;
00335         }
00336     }
00337 
00338     return ASN1_OK;
00339 }
00340 
00341 /*
00342 **  NAME
00343 **    asn1_decode_len::
00344 */
00345 /**
00346 **  This function decodes the ASN.1 type length.  Determines what type of
00347 **  BER encoding is used for the length and decodes that length.
00348 **
00349 **  @return integer
00350 **
00351 **  @retval ASN1_ERR_NULL_MEM function arguments NULL
00352 **  @retval ASN1_ERR_FATAL should never get this
00353 **  @retval ASN1_ERR_OOB out of bounds condition
00354 **  @retval ASN1_OK function successful
00355 */
00356 static int asn1_decode_len(ASN1_TYPE *asn1_type, ASN1_DATA *asn1_data)
00357 {
00358     ASN1_LEN *len;
00359     int iRet;
00360 
00361     if(!asn1_type || !asn1_data)
00362         return ASN1_ERR_NULL_MEM;
00363 
00364     len = &asn1_type->len;
00365 
00366     len->type = asn1_decode_len_type(asn1_data->data);
00367 
00368     switch(len->type)
00369     {
00370         case SF_BER_LEN_DEF_SHORT:
00371             len->size = *asn1_data->data;
00372             
00373             (asn1_data->data)++;
00374             if(ASN1_OOB(asn1_data->start, asn1_data->end, asn1_data->data))
00375             {
00376                 /*
00377                 **  Only return OOB if the short length wasn't zero.  Otherwise,
00378                 **  it's a valid encoding.
00379                 */
00380                 if(len->size != 0)
00381                     return ASN1_ERR_OOB;
00382             }
00383 
00384             break;
00385 
00386         case SF_BER_LEN_DEF_LONG:
00387             iRet = asn1_decode_len_ext(asn1_data, &len->size);
00388             if(iRet)
00389                 return iRet;
00390 
00391             break;
00392 
00393         case SF_BER_LEN_INDEF:
00394             /*
00395             **  Not sure what to do here, so we'll just set the length
00396             **  to 0 and proceed for now.
00397             */
00398             len->size = 0;
00399 
00400             asn1_data->data++;
00401             if(ASN1_OOB(asn1_data->start, asn1_data->end, asn1_data->data))
00402                 return ASN1_ERR_OOB;
00403 
00404             break;
00405             
00406         default:
00407             /*
00408             **  This should be one of the three values.  So we are in
00409             **  error condition.
00410             */
00411             return ASN1_ERR_FATAL;
00412     }
00413 
00414     return ASN1_OK;
00415 }
00416 
00417 /*
00418 **  NAME
00419 **    asn1_is_eoc::
00420 */
00421 /**
00422 **  This function checks and ASN1_TYPE for end-of-content encoding.  This
00423 **  doesn't determine that this is what it is, but what it could be.
00424 **
00425 **  @return int
00426 **
00427 **  @retval 0 not EOC
00428 **  @retval 1 is EOC
00429 */
00430 static int asn1_is_eoc(ASN1_TYPE *asn1)
00431 {
00432     if(!asn1)
00433         return 0;
00434 
00435     if(asn1->ident.class == 0x00 && asn1->ident.flag == 0x00 && 
00436        asn1->ident.tag == 0x00 && asn1->len.type == SF_BER_LEN_DEF_SHORT &&
00437        asn1->len.size == 0)
00438     {
00439         return 1;
00440     }
00441 
00442     return 0;
00443 }
00444 
00445 /*
00446 **  NAME
00447 **    asn1_decode_type::
00448 */
00449 /**
00450 **  This function decodes an ASN1_TYPE structure.  It processes the type in
00451 **  three parts.
00452 **
00453 **  1) Identifier
00454 **  2) Length
00455 **  3) Data
00456 **
00457 **  The data processing skips over primitive data (if it can) and processes
00458 **  construct data (if it can).
00459 **
00460 **  This function also updates the data and len ptrs so we continue moving
00461 **  through the data.
00462 **
00463 **  @return integer
00464 **
00465 **  @retval ASN1_OK function successful
00466 **  @retval ASN1_ERR_MEM_ALLOC memory allocation failed
00467 **  @retval ASN1_ERR_INVALID_INDEF_LEN invalid indefinite encoding
00468 **  @retval ASN1_ERR_INVALID_ARG invalid argument
00469 **  @retval ASN1_ERR_OOB out of bounds
00470 */
00471 static int asn1_decode_type(u_char **data, u_int *len, ASN1_TYPE **asn1_type)
00472 {
00473     ASN1_DATA asn1data;
00474     u_int uiRawLen;
00475     int iRet;
00476 
00477     if(!*data)
00478         return ASN1_ERR_INVALID_ARG;
00479 
00480     *asn1_type = NULL;
00481 
00482     /*
00483     **  Check len first, because if it's 0, then we already decoded a valid
00484     **  construct.  We let the caller know this, by returning OK, but setting
00485     **  the asn1_type ptr to NULL.
00486     */
00487     if(*len == 0)
00488         return ASN1_OK;
00489 
00490     if(ASN1_OOB(*data, (*data) + *len, *data))
00491         return ASN1_ERR_OOB;
00492 
00493     *asn1_type = asn1_node_alloc();
00494     if(*asn1_type == NULL)
00495     {
00496         return ASN1_ERR_MEM_ALLOC;
00497     }
00498     memset(*asn1_type, 0x00, sizeof(ASN1_TYPE));
00499     
00500     asn1data.start = *data;
00501     asn1data.end   = (*data) + *len;
00502     asn1data.data  = *data;
00503 
00504     iRet = asn1_decode_ident(*asn1_type, &asn1data);
00505     if(iRet)
00506     {
00507         return iRet;
00508     }
00509 
00510     iRet = asn1_decode_len(*asn1_type, &asn1data);
00511     if(iRet)
00512     {
00513         return iRet;
00514     }
00515 
00516     /*
00517     **  Set this varible here, so we can set the data_len for
00518     **  indeterminate constructs.
00519     */
00520     uiRawLen = asn1data.end - asn1data.data;
00521 
00522     /*
00523     **  This is an important check.  If the length is zero, it means that
00524     **  we've either hit a zero length type or we've hit a BER indefinite
00525     **  encoding (hate those).
00526     **
00527     **  Standard says that only constructs can have the indefinite length
00528     **  encoding, but we still need to "prove" that.  Thanks M$.
00529     */
00530     if(!(*asn1_type)->len.size)
00531     {
00532         if((*asn1_type)->len.type != SF_BER_LEN_INDEF ||
00533            (*asn1_type)->ident.flag == SF_ASN1_FLAG_CONSTRUCT)
00534         {
00535             (*asn1_type)->data = asn1data.data;
00536 
00537             if((*asn1_type)->len.type == SF_BER_LEN_INDEF)
00538             {
00539                 (*asn1_type)->data_len = uiRawLen;
00540             }
00541             else
00542             {
00543                 /*
00544                 **  If we're not an indefinite type, then we check to
00545                 **  see if we are an eoc, so we don't have to check again.
00546                 */
00547                 (*asn1_type)->data_len = 0;
00548             
00549                 if(asn1_is_eoc(*asn1_type))
00550                     (*asn1_type)->eoc = 1;
00551             }
00552 
00553             goto valid;
00554         }
00555 
00556         return ASN1_ERR_INVALID_INDEF_LEN;
00557     }
00558 
00559     /*
00560     **  Set data ptr for asn1 types that have data.
00561     */
00562     (*asn1_type)->data = asn1data.data;
00563 
00564     /*
00565     **  Check for the ASN.1 type being larger than we have room for.
00566     */
00567     if(uiRawLen < (*asn1_type)->len.size)
00568     {
00569         (*asn1_type)->data_len = uiRawLen;
00570 
00571         /*
00572         **  If we're a construct, then don't skip over the data because
00573         **  we have to process it.
00574         */
00575         if((*asn1_type)->ident.flag == SF_ASN1_FLAG_CONSTRUCT)
00576             goto valid;
00577 
00578         return ASN1_ERR_OOB;
00579     }
00580 
00581     /*
00582     **  We got enough data in the buffer for the true identifier size, so
00583     **  we set it.
00584     */
00585     (*asn1_type)->data_len = (*asn1_type)->len.size;
00586 
00587     /*
00588     **  Only jump data that's not going to be decoded.  That means jump
00589     **  over primitive data and decode construct data.
00590     */
00591     if(!((*asn1_type)->ident.flag == SF_ASN1_FLAG_CONSTRUCT))
00592     {
00593         asn1data.data += (*asn1_type)->len.size;
00594     }
00595 
00596 valid:
00597     /*
00598     **  Update data buffer, before we return.  Depending on if we just decoded
00599     **  a zero length identifier and are on the last data byte, we could be at
00600     **  the end of our buffer.  Otherwise, we're still in the buffer.
00601     */
00602     *len  = asn1data.end - asn1data.data;
00603     *data = asn1data.data;
00604 
00605     return ASN1_OK;
00606 }
00607 
00608 /*
00609 **  NAME
00610 **    asn1_decode::
00611 */
00612 /**
00613 **  This function decodes an ASN.1 string and returns the decoded
00614 **  structures.  We BER encoding, which means we handle both
00615 **  definite and indefinite length encodings (that was a B).
00616 **
00617 **  @return integer
00618 **
00619 **  @retval  ASN1_OK function successful
00620 **  @retval !ASN1_OK lots of error conditions, figure it out
00621 */
00622 int asn1_decode(u_char *data, u_int len, ASN1_TYPE **asn1_type)
00623 {
00624     ASN1_TYPE *cur;
00625     ASN1_TYPE *child = NULL;
00626     ASN1_TYPE *indef;
00627     ASN1_TYPE *asnstack[ASN1_MAX_STACK];
00628 
00629     u_char *end;
00630     u_int con_len;
00631     int index = 0;
00632     int iRet;
00633 
00634     if(!data || !len)
00635         return ASN1_ERR_NULL_MEM;
00636 
00637     asn1_init_node_index();
00638 
00639     /*
00640     **  Keep track of where the end of the data buffer is so we can continue
00641     **  processing if there is a construct.
00642     */
00643     end = data + len;
00644 
00645     iRet = asn1_decode_type(&data,&len,asn1_type);
00646     if(iRet || !(*asn1_type))
00647     {
00648         //printf("** initial bad decode\n");
00649         return iRet;
00650     }
00651 
00652     cur  = *asn1_type;
00653 
00654     while(cur)
00655     {
00656         /*
00657         **  This is where we decode the ASN.1 constructs.  We do while()
00658         **  because we may have back to back constructs.  We bail on the
00659         **  first indentifier that isn't a construct.
00660         */
00661         while(cur && cur->ident.flag == SF_ASN1_FLAG_CONSTRUCT)
00662         {
00663             if(index < ASN1_MAX_STACK)
00664                 asnstack[index++] = cur;
00665             else
00666                 return ASN1_ERR_STACK;
00667 
00668             /*
00669             **  We now set the current len for this constructs true length,
00670             **  or raw length if true length is past buffer.
00671             */
00672             if(cur->len.type != SF_BER_LEN_INDEF)
00673             {
00674                 if(len < cur->data_len)
00675                     return ASN1_ERR_OVERLONG_LEN;
00676 
00677                 len = cur->data_len;
00678             }
00679 
00680             iRet = asn1_decode_type(&data, &len, &cur->cnext);
00681             if(iRet)
00682             {
00683                 return iRet;
00684             }
00685             
00686             /*
00687             **  Check next child for ending of indefinite encodings.
00688             */
00689             if(cur->cnext && cur->cnext->eoc)
00690             {
00691                 if(index && (indef = asnstack[--index]))
00692                 {
00693                     if(indef->len.type == SF_BER_LEN_INDEF)
00694                     {
00695                         indef->len.size = data - indef->data - 2;
00696                         indef->data_len = indef->len.size;
00697 
00698                         cur->cnext = NULL;
00699                         cur = indef;
00700                         break;
00701                     }
00702                     else
00703                     {
00704                         /*
00705                         **  Not an EOC type, so it's just a strange child
00706                         **  encoding.  Put the construct back on the stack.
00707                         */
00708                         asnstack[index++] = indef;
00709                     }
00710                 }
00711             }
00712 
00713             cur = cur->cnext;
00714         }
00715 
00716         /*
00717         **  If there is a node, then process any peers that this node has.
00718         */
00719         if(cur)
00720         {
00721             iRet = asn1_decode_type(&data, &len, &cur->next);
00722             if(iRet)
00723                 return iRet;
00724 
00725             /*
00726             **  Cycle through any eoc that might be back to back
00727             */
00728             while(cur->next && cur->next->eoc)
00729             {
00730                 if(index && (indef = asnstack[--index]))
00731                 {
00732                     if(indef->len.type == SF_BER_LEN_INDEF)
00733                     {
00734                         indef->len.size = data - indef->data - 2;
00735                         indef->data_len = indef->len.size;
00736                         cur->next = NULL;
00737                         cur = indef;
00738 
00739                         iRet = asn1_decode_type(&data, &len, &cur->next);
00740                         if(iRet)
00741                         {
00742                             return iRet;
00743                         }
00744 
00745                         continue;
00746                     }
00747 
00748                     asnstack[index++] = indef;
00749                 }
00750 
00751                 break;
00752             }
00753 
00754             cur = cur->next;
00755             if(cur) continue;
00756         }
00757 
00758         /*
00759         **  We only get here if the peer decode fails.
00760         **
00761         **  Traverse the stack and close off any constructs that we
00762         **  are done with.  This gets a little trickier, because we have to
00763         **  check for additional peers for each construct, depending on the
00764         **  length of the parent construct.
00765         */
00766         while(index && (cur = asnstack[--index]))
00767         {
00768             /*
00769             **  Get the construct length and set the length appropriately
00770             **  if there is more data in this construct.
00771             */
00772             con_len = data - cur->data;
00773             if(cur->data_len > con_len)
00774             {
00775                 len = cur->data_len - con_len;
00776             }
00777 
00778             /*
00779             **  If this construct has no more data left, then save it off as
00780             **  the last child of the previous construct.
00781             */
00782             if(len == 0)
00783             {
00784                 child = cur;
00785             }
00786             else if(child)
00787             {
00788                 /*
00789                 **  Means this construct has more data left, so if the child is set
00790                 **  then we set it's next ptr.  Otherwise, this means we are in
00791                 **  an indeterminate construct, and need to check for eoc before we
00792                 **  continue processing.
00793                 */
00794                 asnstack[index++] = cur;
00795                 cur   = child;
00796                 child = NULL;
00797             }
00798 
00799             iRet = asn1_decode_type(&data, &len, &cur->next);
00800             if(iRet)
00801             {
00802                 return iRet;
00803             }
00804 
00805             if(cur->next && cur->next->eoc)
00806             {
00807                 if(index && (indef = asnstack[--index]))
00808                 {
00809                     if(indef->len.type == SF_BER_LEN_INDEF)
00810                     {
00811                         indef->len.size = data - indef->data - 2;
00812                         indef->data_len = indef->len.size;
00813                         cur->next = NULL;
00814                         cur = indef;
00815                     }
00816                     else
00817                     {
00818                         asnstack[index++] = indef;
00819                     }
00820                 }
00821             }
00822 
00823             /*
00824             **  This logic tell us that we are on the root construct, but there
00825             **  are additional peers because there is more data.  We recalculate
00826             **  the length and continue on.
00827             **
00828             **  NOTE:
00829             **    We may not want this because research may only be able to point
00830             **    us at the first sequence and it's anyone's guess after that.
00831             */
00832             if(!index && !(cur->next) && (data < end))
00833             {
00834                 len = (end - data);
00835                 
00836                 iRet = asn1_decode_type(&data, &len, &cur->next);
00837                 if(iRet)
00838                     return iRet;
00839             }
00840 
00841             cur = cur->next;
00842             if(cur)
00843                 break;
00844         }
00845 
00846         /*
00847         **  The loop logic bails us out if there is no cur.
00848         */
00849     }
00850 
00851     return ASN1_OK;
00852 }
00853 
00854 /*
00855 **  NAME
00856 **    asn1_traverse::
00857 */
00858 /**
00859 **  This function traverses a decoded ASN1 structure, applying a detection
00860 **  function for the different types.  This is just to make this user stack
00861 **  generic AND easy.
00862 **
00863 **  @return integer
00864 **
00865 **  @retval 1 detection function successful
00866 **  @retval 0 detection function unsuccessful
00867 */
00868 int asn1_traverse(ASN1_TYPE *asn1, void *user, 
00869                   int (*DetectFunc)(ASN1_TYPE *, void *))
00870 {
00871     ASN1_TYPE *asnstack[ASN1_MAX_STACK];
00872     int index = 0;
00873     ASN1_TYPE *cur;
00874     int iRet;
00875 
00876     if(!asn1)
00877         return 0;
00878 
00879     cur = asn1;
00880 
00881     while(cur)
00882     {
00883         while(cur && cur->ident.flag == SF_ASN1_FLAG_CONSTRUCT)
00884         {
00885             if(index < ASN1_MAX_STACK)
00886                 asnstack[index++] = cur;
00887             else
00888                 return 0;
00889 
00890             iRet = DetectFunc(cur, user);
00891             if(iRet)
00892                 return 1;
00893 
00894             cur = cur->cnext;
00895         }
00896 
00897         if(cur)
00898         {
00899             iRet = DetectFunc(cur, user);
00900             if(iRet)
00901                 return 1;
00902 
00903             cur = cur->next;
00904             if(cur) continue;
00905         }
00906 
00907         while(index && (cur = asnstack[--index]))
00908         {
00909             cur = cur->next;
00910             if(cur)
00911                 break;
00912         }
00913     }
00914 
00915     return 0;
00916 }
00917 
00918 /*
00919 **  NAME
00920 **    asn1_print_types::
00921 */
00922 /**
00923 **  Print out the ASN.1 type.
00924 **
00925 **  @return integer
00926 **
00927 **  @retval 0 printed
00928 */
00929 int asn1_print_types(ASN1_TYPE *asn1_type, void *user)
00930 {
00931     unsigned int iTabs = 0;
00932     unsigned int iCtr;
00933 
00934     if(user)
00935         iTabs = *((int *)user);
00936 
00937     for(iCtr = 0; iCtr < iTabs; iCtr++)
00938         printf("    ");
00939 
00940     printf("## PRINT ASN1_TYPE STRUCTURE ##\n");
00941 
00942     for(iCtr = 0; iCtr < iTabs; iCtr++)
00943         printf("    ");
00944 
00945     printf("IDENT - class: %.2x | flag: %.2x | tag_type: %.2x | "
00946            "tag_num: %d\n", asn1_type->ident.class, asn1_type->ident.flag,
00947            asn1_type->ident.tag_type, asn1_type->ident.tag);
00948 
00949     for(iCtr = 0; iCtr < iTabs; iCtr++)
00950         printf("    ");
00951     
00952     printf("LEN - type: %d | size: %u\n", asn1_type->len.type, 
00953            asn1_type->len.size);
00954 
00955     for(iCtr = 0; iCtr < iTabs; iCtr++)
00956         printf("    ");
00957 
00958     printf("DATA | data_len: %d | ", asn1_type->data_len);
00959     if(asn1_type->data)
00960     {
00961         for(iCtr = 0; iCtr < asn1_type->data_len; iCtr++)
00962             printf(" %.2x", asn1_type->data[iCtr]);
00963     }
00964     else
00965     {
00966         printf(" NULL");
00967     }
00968 
00969     printf("\n\n");
00970 
00971     /*
00972 
00973     printf("\n");
00974     //if(BitStringOverflow(asn1_type))
00975     //{
00976     //    printf("!! BITSTRING OVERFLOW\n");
00977     //}
00978     printf("\n");
00979     
00980     if(asn1_type->cnext)
00981         asn1_print_types(asn1_type->cnext, iTabs+1);
00982 
00983     if(asn1_type->next)
00984         asn1_print_types(asn1_type->next, iTabs);
00985     */
00986 
00987     return 0;
00988 }
00989 
00990 #ifdef I_WANT_MAIN_DAMMIT
00991 static int BitStringOverflow(ASN1_TYPE *asn1_type)
00992 {
00993     if(!asn1_type)
00994         return 0;
00995 
00996     if(asn1_type->ident.tag == SF_ASN1_TAG_BIT_STR && !asn1_type->ident.flag)
00997     {
00998         if(((asn1_type->len.size - 1)*8) < (u_int)asn1_type->data[0])
00999         {
01000                 return 1;
01001         }
01002     }
01003 
01004     return 0;
01005 }
01006 
01007 
01008 /*
01009 **  Program reads from stdin and decodes the hexadecimal ASN.1 stream
01010 **  into identifier,len,data.
01011 */
01012 int main(int argc, char **argv)
01013 {
01014     ASN1_TYPE *asn1_type;
01015     char line[10000];
01016     u_int ctmp;
01017     char *buf;
01018     int buf_size;
01019     int iCtr;
01020     int iRet;
01021 
01022     fgets(line, sizeof(line), stdin);
01023     buf_size = strlen(line);
01024 
01025     while(buf_size && line[buf_size-1] <= 0x20)
01026     {
01027         buf_size--;
01028         line[buf_size] = 0x00;
01029     }
01030 
01031     if(!buf_size)
01032     {
01033         printf("** No valid characters in data string.\n");
01034         return 1;
01035     }
01036     
01037     if(buf_size % 2)
01038     {
01039         printf("** Data must be represent in hex, meaning that there is an "
01040                "odd number of characters in the data string.\n");
01041         return 1;
01042     }
01043 
01044     buf_size >>= 1;
01045 
01046     buf = (char *)malloc(buf_size + 1);
01047     if(!buf)
01048     {
01049         printf("** Bad malloc\n");
01050         return 1;
01051     }
01052 
01053     for(iCtr = 0; iCtr < buf_size; iCtr++)
01054     {
01055         if(!(isxdigit(line[iCtr*2]) && isxdigit(line[(iCtr*2)+1])))
01056         {
01057             printf("** Data stream is not all hex digits.\n");
01058             return 1;
01059         }
01060 
01061         sscanf(&line[iCtr*2], "%2x", &ctmp);
01062         buf[iCtr] = (char)ctmp;
01063     }
01064 
01065     buf[iCtr] = 0x00;
01066 
01067     if(asn1_init_mem(256))
01068     {
01069         printf("** asn1_init_mem() failed\n");
01070         return 1;
01071     }
01072 
01073     iRet = asn1_decode(buf, buf_size, &asn1_type);
01074     if(iRet && !asn1_type)
01075     {
01076         printf("** FAILED\n");
01077         return 1;
01078     }
01079 
01080     printf("** iRet = %d\n", iRet);
01081 
01082     asn1_print_types(asn1_type, 0);
01083 
01084     free(buf);
01085 
01086     return 0;
01087 }
01088 #endif

Generated on Sun May 14 14:51:18 2006 by  doxygen 1.4.2