#include #include #include #include #include #include #include "ber.h" #include "compat.h" /* berOid - the encoding of an object identifier. * the encoding of this is a real hassel. First of all you have the same * anoying problem with length as you do with the strings and sequence. Then * you have to take the first two oids multiply the first one by 40 and add the * second one. Then you can go through the rest of the oids and encode them * however they are not encoded as simple integers or anything they are big * endian two's compliment stuffed into as few bytes as possible. The way that * you stuff them into as few bytes as possible and deal with the fact that * that you don't know how many bytes each suboid is going to be is to use * the MSB to indicate if there are more bits to follow. Thus you can only * use the 7 LSB to represent the data. So a normal long can end up being * up to 5 bytes long. */ BerOid::BerOid(unsigned char *str): BerBase(str){ assert(str[0]==OID_TAG); unsigned char headerlen; unpack_len(str,headerlen); assert(eoid=new unsigned char[oidbytes=edatacache->Length()-headerlen]); memcpy(eoid,str+headerlen,oidbytes); } BerEncodedData *BerOid::encode(){ unsigned char headerlen; unsigned char *retval=start_data(OID_TAG,oidbytes,headerlen); memcpy(retval+headerlen,eoid,oidbytes); return new BerEncodedData(retval,headerlen+oidbytes); } int unpack_suboid(unsigned char* buf, unsigned int &len){ for(len=0;len=0;i--) buf[i]=(suboid>>7*i)&0x7f; // mark the bits for(i=sizeof(long)-1;i>=0;i--) if(buf[i]>0) { for(char j=i;j>0;j--) buf[j]|=0x80; len=i+1; break; } if(len==0) len=1; unsigned char j=0; for(i=len-1;i>=0;i--) outbuf[j++]=buf[i]; return len; } BerOid::BerOid(CONST char *oidstr,unsigned int len){ assert(oidstr!=NULL); // should be big enough. I can't think of a case where an oid would expand // when encoded. assert(eoid=new unsigned char[len]); const char *end=oidstr+len; char *curstr; long val=strtol(oidstr,&curstr,10); assert(val!=LONG_MAX && errno!=ERANGE); if(*curstr==0){ assert(curstr==end); // only one suboid oidbytes=pack_suboid(val*40,eoid)+2; assert(oidbytes<=len); eoid=(unsigned char*)realloc(eoid,oidbytes); return; } assert(*curstr=='.'); oidstr=curstr+1; long val2=strtol(oidstr,&curstr,10); assert(val2!=LONG_MAX && errno!=ERANGE); oidbytes=pack_suboid(val*40+val2,eoid); assert(oidbytes<=len); if(*curstr==0){ assert(curstr==end); // only two suboids eoid=(unsigned char*)realloc(eoid,oidbytes); return; } assert(*curstr=='.'); oidstr=curstr+1; while(oidstrother.oidbytes?other.oidbytes:oidbytes; return !memcmp(eoid,other.eoid,len); }