"Fossies" - the Fresh Open Source Software Archive

Member "npadmin-0.14/beroid.C" (19 Apr 2001, 5127 Bytes) of package /linux/misc/old/npadmin-0.14.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* Copyright (c) 2000 Ben Woodard
    2  * All rights reserved.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public Licence
    6  * as published by the Free Software Foundation; either version 2
    7  * of the Licence, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRENTY; without even the implied warrenty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   12  * GNU General Public Licence in the COPYING file for more
   13  * details.
   14  *
   15  * You should have received a copy of the GNU Library General 
   16  * Public License along with the GNU C Library; see the file 
   17  * COPYING.LIB.  If not, write to the Free Software Foundation, 
   18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
   19  */
   20 
   21 #include <stdio.h>
   22 #include <stdlib.h>
   23 #include <assert.h>
   24 #include <string.h>
   25 #include <limits.h>
   26 #include <errno.h>
   27 
   28 #include "ber.h"
   29 #include "compat.h"
   30 
   31 /* berOid - the encoding of an object identifier.
   32  * the encoding of this is a real hassel. First of all you have the same 
   33  * anoying problem with length as you do with the strings and sequence. Then
   34  * you have to take the first two oids multiply the first one by 40 and add the
   35  * second one. Then you can go through the rest of the oids and encode them
   36  * however they are not encoded as simple integers or anything they are big
   37  * endian two's compliment stuffed into as few bytes as possible. The way that 
   38  * you stuff them into as few bytes as possible and deal with the fact that 
   39  * that you don't know how many bytes each suboid is going to be is to use
   40  * the MSB to indicate if there are more bits to follow. Thus you can only 
   41  * use the 7 LSB to represent the data. So a normal long can end up being 
   42  * up to 5 bytes long.
   43  */
   44 
   45 BerOid::BerOid(unsigned char *str): BerBase(str){
   46   assert(str[0]==OID_TAG);
   47   unsigned char headerlen;
   48   unpack_len(str,headerlen);
   49   eoid=new unsigned char[oidbytes=edatacache->Length()-headerlen];
   50   memcpy(eoid,str+headerlen,oidbytes);
   51 }
   52 
   53 BerEncodedData *BerOid::encode(){
   54   unsigned char headerlen;
   55   unsigned char *retval=start_data(OID_TAG,oidbytes,headerlen);
   56   
   57   memcpy(retval+headerlen,eoid,oidbytes);
   58   return new BerEncodedData(retval,headerlen+oidbytes);
   59 }
   60 
   61 int unpack_suboid(unsigned char* buf, unsigned int &len){
   62   for(len=0;len<sizeof(long)+1;len++)
   63     if(buf[len]<128)
   64       break;
   65   long val=0;
   66   switch(len){
   67   case 4:
   68     val|=(buf[0]&0x7f)<<28;
   69     buf++;
   70   case 3:
   71     val|=(buf[0]&0x7f)<<21;
   72     buf++;
   73   case 2:
   74     val|=(buf[0]&0x7f)<<14;
   75     buf++;
   76   case 1:
   77     val|=(buf[0]&0x7f)<<7;
   78     buf++;
   79   default:
   80     val|=buf[0];
   81   }
   82   len++;
   83   return val;
   84 
   85 }
   86 
   87 int pack_suboid(long suboid, unsigned char *outbuf){
   88   unsigned char buf[sizeof(long)+1];
   89   unsigned char len=0;
   90   // spread out the bits
   91   signed char i;
   92   for(i=sizeof(long);i>=0;i--)
   93     buf[i]=(suboid>>7*i)&0x7f;
   94 
   95   // mark the bits
   96   for(i=sizeof(long)-1;i>=0;i--)
   97     if(buf[i]>0) {
   98       for(char j=i;j>0;j--)
   99     buf[j]|=0x80;
  100       len=i+1;
  101       break;
  102     }
  103 
  104   if(len==0)
  105     len=1;
  106 
  107   unsigned char j=0;
  108   for(i=len-1;i>=0;i--)
  109     outbuf[j++]=buf[i];
  110 
  111   return len;
  112 }         
  113 
  114 BerOid::BerOid(CONST char *oidstr,unsigned int len){
  115   assert(oidstr!=NULL);
  116   // should be big enough. I can't think of a case where an oid would expand
  117   // when encoded.
  118   eoid=new unsigned char[len];
  119   
  120   const char *end=oidstr+len;
  121   char *curstr;
  122   long val=strtol(oidstr,&curstr,10);
  123   assert(val!=LONG_MAX && errno!=ERANGE);
  124   if(*curstr==0){
  125     assert(curstr==end);
  126     // only one suboid
  127     oidbytes=pack_suboid(val*40,eoid)+2;
  128     assert(oidbytes<=len);
  129     eoid=(unsigned char*)realloc(eoid,oidbytes);
  130     return;
  131   } 
  132   assert(*curstr=='.');
  133   oidstr=curstr+1;
  134 
  135   long val2=strtol(oidstr,&curstr,10);
  136   assert(val2!=LONG_MAX && errno!=ERANGE);
  137   oidbytes=pack_suboid(val*40+val2,eoid);
  138   assert(oidbytes<=len);
  139 
  140   if(*curstr==0){
  141     assert(curstr==end);
  142     // only two suboids
  143     eoid=(unsigned char*)realloc(eoid,oidbytes);
  144     return;
  145   }
  146   assert(*curstr=='.');
  147   oidstr=curstr+1;
  148 
  149   while(oidstr<end){
  150     val=strtol(oidstr,&curstr,10);    
  151     assert(val!=LONG_MAX && errno!=ERANGE);
  152     assert(!(*curstr==0 && curstr!=end)); // string too short
  153     assert(!(*curstr!='.' && curstr!=end));
  154     oidstr=curstr+1;
  155     oidbytes+=pack_suboid(val,eoid+oidbytes);
  156     assert(oidbytes<=len);
  157   }
  158   eoid=(unsigned char*)realloc(eoid,oidbytes);
  159 }
  160 
  161 int BerOid::print(char *buf, unsigned int len){
  162   unsigned char *cur=eoid;
  163   unsigned int elen=0,totlen=0;
  164   int slen;
  165   int val=unpack_suboid(cur,elen);
  166   cur+=elen;
  167   slen=snprintf(buf,len,"%d.%d",val/40,val%40);
  168   if(slen==-1) return -1;
  169   buf+=slen;
  170   totlen=slen;
  171   len-=slen;
  172   while(cur<eoid+oidbytes){
  173     val=unpack_suboid(cur,elen);
  174     cur+=elen;
  175     slen=snprintf(buf,len,".%d",val);
  176     if(slen==-1) return -1;
  177     buf+=slen;
  178     len-=slen;
  179     totlen+=slen;
  180   }
  181   return totlen;
  182 }
  183 
  184 int BerOid::operator==(BerOid &other){
  185   unsigned int len=oidbytes>other.oidbytes?other.oidbytes:oidbytes;
  186   return !memcmp(eoid,other.eoid,len);
  187 }