grst_asn1.c

Go to the documentation of this file.
00001 
00002 #ifndef _GNU_SOURCE
00003 #define _GNU_SOURCE
00004 #endif
00005 
00006 #include <stdio.h>
00007 #include <string.h>
00008 
00009 #ifndef GRST_NO_OPENSSL
00010 #include <openssl/x509_vfy.h>
00011 #include <openssl/err.h>
00012 #include <openssl/pem.h>
00013 
00014 #include <openssl/buffer.h>
00015 #include <openssl/objects.h>
00016 #include <openssl/asn1.h>
00017 #endif
00018 
00019 #ifdef SUNCC
00020 time_t timegm (struct tm *tm) {
00021   time_t ret;
00022   char *tz;
00023 
00024   tz = getenv("TZ");
00025   setenv("TZ", "", 1);
00026   tzset();
00027   ret = mktime(tm);
00028   if (tz)
00029     setenv("TZ", tz, 1);
00030   else
00031     unsetenv("TZ");
00032   tzset();
00033   return ret;
00034 }
00035 #endif
00036 
00037 #include "gridsite.h"
00038 
00039 #ifdef R__SSL_GE_098
00040 #define SSLARG const unsigned char**
00041 #else
00042 #define SSLARG unsigned char**
00043 #endif
00044 
00045 /// ASN1 time string (in a char *) to time_t
00046 /**
00047  *  (Use ASN1_STRING_data() to convert ASN1_GENERALIZEDTIME to char * if
00048  *   necessary)
00049  */
00050                                                                                 
00051 time_t GRSTasn1TimeToTimeT(unsigned char *asn1time, size_t len)
00052 {
00053    char   zone;
00054    struct tm time_tm;
00055    
00056    if (len == 0) len = strlen((char*)asn1time);
00057                                                                                 
00058    if ((len != 13) && (len != 15)) return 0; /* dont understand */
00059                                                                                 
00060    if ((len == 13) &&
00061        ((sscanf((char*)asn1time, "%02d%02d%02d%02d%02d%02d%c",
00062          &(time_tm.tm_year),
00063          &(time_tm.tm_mon),
00064          &(time_tm.tm_mday),
00065          &(time_tm.tm_hour),
00066          &(time_tm.tm_min),
00067          &(time_tm.tm_sec),
00068          &zone) != 7) || (zone != 'Z'))) return 0; /* dont understand */
00069                                                                                 
00070    if ((len == 15) &&
00071        ((sscanf((char*)asn1time, "20%02d%02d%02d%02d%02d%02d%c",
00072          &(time_tm.tm_year),
00073          &(time_tm.tm_mon),
00074          &(time_tm.tm_mday),
00075          &(time_tm.tm_hour),
00076          &(time_tm.tm_min),
00077          &(time_tm.tm_sec),
00078          &zone) != 7) || (zone != 'Z'))) return 0; /* dont understand */
00079                                                                                 
00080    /* time format fixups */
00081                                                                                 
00082    if (time_tm.tm_year < 90) time_tm.tm_year += 100;
00083    --(time_tm.tm_mon);
00084                                                                                 
00085    return timegm(&time_tm);
00086 }
00087 
00088 /* this function is taken from OpenSSL without modification */
00089 
00090 static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
00091              int indent)
00092         {
00093         static const char fmt[]="%-18s";
00094         static const char fmt2[]="%2d %-15s";
00095         char str[128];
00096         const char *p,*p2=NULL;
00097 
00098         if (constructed & V_ASN1_CONSTRUCTED)
00099                 p="cons: ";
00100         else
00101                 p="prim: ";
00102         if (BIO_write(bp,p,6) < 6) goto err;
00103 #if OPENSSL_VERSION_NUMBER >= 0x0090701fL
00104         BIO_indent(bp,indent,128);
00105 #endif
00106 
00107         p=str;
00108         if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
00109                         sprintf(str,"priv [ %d ] ",tag);
00110         else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
00111                 sprintf(str,"cont [ %d ]",tag);
00112         else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
00113                 sprintf(str,"appl [ %d ]",tag);
00114         else p = ASN1_tag2str(tag);
00115 
00116         if (p2 != NULL)
00117                 {
00118                 if (BIO_printf(bp,fmt2,tag,p2) <= 0) goto err;
00119                 }
00120         else
00121                 {
00122                 if (BIO_printf(bp,fmt,p) <= 0) goto err;
00123                 }
00124         return(1);
00125 err:
00126         return(0);
00127         }
00128 
00129 static void GRSTasn1AddToTaglist(struct GRSTasn1TagList taglist[], 
00130                            int maxtag, int *lasttag,
00131                            char *treecoords, int start, int headerlength,
00132                            int length, int tag)
00133 {
00134    if ((strlen(treecoords) > GRST_ASN1_MAXCOORDLEN) ||
00135        (*lasttag + 1 > maxtag)) return;
00136    
00137    ++(*lasttag);
00138    
00139    strncpy(taglist[*lasttag].treecoords, treecoords, GRST_ASN1_MAXCOORDLEN+1);
00140    taglist[*lasttag].start = start;
00141    taglist[*lasttag].headerlength = headerlength;
00142    taglist[*lasttag].length = length;
00143    taglist[*lasttag].tag = tag;
00144 }
00145 
00146 int GRSTasn1SearchTaglist(struct GRSTasn1TagList taglist[], 
00147                                  int lasttag, char *treecoords)
00148 {
00149    int i;
00150    
00151    for (i=0; i <= lasttag; ++i)
00152       {
00153         if (strcmp(treecoords, taglist[i].treecoords) == 0) return i;
00154       }
00155       
00156    return -1;
00157 }
00158 
00159 static int GRSTasn1PrintPrintable(BIO *bp, char *str, int length)
00160 {
00161    int   ret = 0;
00162    char *dup, *p;
00163    
00164    dup = (char*)malloc(length);
00165    strncpy(dup,str,length);
00166 
00167    for (p=dup; *p != '\0'; ++p) if ((*p < ' ') || (*p > '~')) *p = '.';
00168 
00169    if (bp != NULL) ret = BIO_write(bp, dup, strlen(dup));
00170 
00171    free(dup);
00172    
00173    return ret;
00174 }
00175 
00176 static int GRSTasn1Parse2(BIO *bp, unsigned char **pp, long length, int offset,
00177              int depth, int indent, int dump, char *treecoords,
00178              struct GRSTasn1TagList taglist[], int maxtag, int *lasttag)
00179         {
00180         int sibling = 0;
00181         char sibtreecoords[512];
00182 
00183         unsigned char *p,*ep,*tot,*op,*opp;
00184         long len;
00185         int tag,xclass,ret=0;
00186         int nl,hl,j,r;
00187         ASN1_OBJECT *o=NULL;
00188         ASN1_OCTET_STRING *os=NULL;
00189         int dump_indent;
00190 
00191 
00192         dump_indent = 6;        /* Because we know BIO_dump_indent() */
00193         p= *pp;
00194         tot=p+length;
00195         op=p-1;
00196         while ((p < tot) && (op < p))
00197                 {
00198                 op=p;
00199                 j=ASN1_get_object((SSLARG)&p,&len,&tag,&xclass,length);
00200 
00201                 if (j & 0x80)
00202                         {
00203                         if ((bp != NULL) && 
00204                             (BIO_write(bp,"Error in encoding\n",18) <= 0))
00205                                 goto end;
00206                         ret=0;
00207                         goto end;
00208                         }
00209                 hl=(p-op);
00210                 length-=hl;
00211 
00212                 ++sibling;
00213                 sprintf(sibtreecoords, "%s-%d", treecoords, sibling);
00214 
00215                 GRSTasn1AddToTaglist(taglist, maxtag, lasttag, sibtreecoords,
00216                                (int)offset+(int)(op - *pp),
00217                                (int) hl, len, tag);
00218                                
00219                 if (bp != NULL)
00220                   {
00221                     BIO_printf(bp, "  %s %ld %d %ld %d ", sibtreecoords,
00222                            (long)offset+(long)(op - *pp), hl, len, tag);
00223 
00224                     GRSTasn1PrintPrintable(bp, (char*)p,
00225 //                                 &((*pp)[(long)offset+(long)(op - *pp)+hl]),
00226                                            (len > 30) ? 30 : len);
00227 
00228                     BIO_printf(bp, "\n");
00229                  }
00230 
00231 
00232                 /* if j == 0x21 it is a constructed indefinite length object */
00233                 if ((bp != NULL) &&
00234                     (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp))
00235                         <= 0)) goto end;
00236 
00237                 if (j != (V_ASN1_CONSTRUCTED | 1))
00238                         {
00239                         if ((bp != NULL) && 
00240                             (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ",
00241                                 depth,(long)hl,len) <= 0))
00242                                 goto end;
00243                         }
00244                 else
00245                         {
00246                         if ((bp != NULL) &&
00247                             (BIO_printf(bp,"d=%-2d hl=%ld l=inf  ",
00248                                 depth,(long)hl) <= 0))
00249                                 goto end;
00250                         }
00251                 if ((bp != NULL) && 
00252                     !asn1_print_info(bp,tag,xclass,j,(indent)?depth:0))
00253                         goto end;
00254                 if (j & V_ASN1_CONSTRUCTED)
00255                         {
00256                         ep=p+len;
00257                         if ((bp != NULL) &&
00258                             (BIO_write(bp,"\n",1) <= 0)) goto end;
00259                         if (len > length)
00260                                 {
00261                                 if (bp != NULL) BIO_printf(bp,
00262                                         "length is greater than %ld\n",length);
00263                                 ret=0;
00264                                 goto end;
00265                                 }
00266                         if ((j == 0x21) && (len == 0))
00267                                 {
00268                                 for (;;)
00269                                         {
00270                                         r=GRSTasn1Parse2(bp,&p,(long)(tot-p),
00271                                                 offset+(p - *pp),depth+1,
00272                                                 indent,dump,sibtreecoords,
00273                                                 taglist, maxtag, lasttag);
00274                                         if (r == 0) { ret=0; goto end; }
00275                                         if ((r == 2) || (p >= tot)) break;
00276                                         }
00277                                 }
00278                         else
00279                                 while (p < ep)
00280                                         {
00281                                         r=GRSTasn1Parse2(bp,&p,(long)len,
00282                                                 offset+(p - *pp),depth+1,
00283                                                 indent,dump,sibtreecoords,
00284                                                 taglist, maxtag, lasttag);
00285                                         if (r == 0) { ret=0; goto end; }
00286                                         }
00287                         }
00288                 else if (xclass != 0)
00289                         {
00290                         p+=len;
00291                         if ((bp != NULL) && 
00292                             (BIO_write(bp,"\n",1) <= 0)) goto end;
00293                         }
00294                 else
00295                         {
00296                         nl=0;
00297                         if (    (tag == V_ASN1_PRINTABLESTRING) ||
00298                                 (tag == V_ASN1_T61STRING) ||
00299                                 (tag == V_ASN1_IA5STRING) ||
00300                                 (tag == V_ASN1_VISIBLESTRING) ||
00301                                 (tag == V_ASN1_UTCTIME) ||
00302                                 (tag == V_ASN1_GENERALIZEDTIME))
00303                                 {
00304                                 if ((bp != NULL) &&
00305                                     (BIO_write(bp,":",1) <= 0)) goto end;
00306                                 if ((len > 0) && (bp != NULL) &&
00307                                         BIO_write(bp,(char *)p,(int)len)
00308                                         != (int)len)
00309                                         goto end;
00310                                 }
00311                         else if (tag == V_ASN1_OBJECT)
00312                                 {
00313                                 opp=op;
00314                                 if (d2i_ASN1_OBJECT(&o,(SSLARG)&opp,len+hl) != NULL)
00315                                         {
00316                                         if (bp != NULL)
00317                                           {
00318                                             if (BIO_write(bp,":",1) <= 0) goto end;
00319                                             i2a_ASN1_OBJECT(bp,o);
00320                                           }
00321                                         }
00322                                 else
00323                                         {
00324                                         if ((bp != NULL) && 
00325                                             (BIO_write(bp,":BAD OBJECT",11) <= 0))
00326                                                 goto end;
00327                                         }
00328                                 }
00329                         else if (tag == V_ASN1_BOOLEAN)
00330                                 {
00331                                 int ii;
00332 
00333                                 opp=op;
00334                                 ii=d2i_ASN1_BOOLEAN(NULL,(SSLARG)&opp,len+hl);
00335                                 if (ii < 0)
00336                                 {
00337                                   if ((bp != NULL) &&
00338                                       (BIO_write(bp,"Bad boolean\n",12)))
00339                                                 goto end;
00340                                 }
00341                                 if (bp != NULL) BIO_printf(bp,":%d",ii);
00342                                 }
00343                         else if (tag == V_ASN1_BMPSTRING)
00344                                 {
00345                                 /* do the BMP thang */
00346                                 }
00347                         else if (tag == V_ASN1_OCTET_STRING)
00348                                 {
00349                                 opp=op;
00350                                 os=d2i_ASN1_OCTET_STRING(NULL,(SSLARG) &opp,len+hl);
00351                                 if (os != NULL)
00352                                         {
00353                                         opp=os->data;
00354 
00355                                         if (os->length > 0)
00356                                           {
00357                                             if ((bp != NULL) &&
00358                                                     (BIO_write(bp,":",1) <= 0))
00359                                                         goto end;
00360                                             if ((bp != NULL) &&
00361                                                 (GRSTasn1PrintPrintable(bp,
00362                                                         (char*)opp,
00363                                                         os->length) <= 0))
00364                                                         goto end;
00365                                           }
00366 
00367                                         M_ASN1_OCTET_STRING_free(os);
00368                                         os=NULL;
00369                                         }
00370                                 }
00371                         else if (tag == V_ASN1_INTEGER)
00372                                 {
00373                                 ASN1_INTEGER *bs;
00374                                 int i;
00375 
00376                                 opp=op;
00377                                 bs=d2i_ASN1_INTEGER(NULL,(SSLARG)&opp,len+hl);
00378                                 if (bs != NULL)
00379                                         {
00380                                         if ((bp != NULL) &&
00381                                             (BIO_write(bp,":",1) <= 0)) goto end;
00382                                         if (bs->type == V_ASN1_NEG_INTEGER)
00383                                                 if ((bp != NULL) &&
00384                                                     (BIO_write(bp,"-",1) <= 0))
00385                                                         goto end;
00386                                         for (i=0; i<bs->length; i++)
00387                                                 {
00388                                                 if ((bp != NULL) &&
00389                                                     (BIO_printf(bp,"%02X",
00390                                                         bs->data[i]) <= 0))
00391                                                         goto end;
00392                                                 }
00393                                         if (bs->length == 0)
00394                                                 {
00395                                                 if ((bp != NULL) && 
00396                                                     (BIO_write(bp,"00",2) <= 0))
00397                                                         goto end;
00398                                                 }
00399                                         }
00400                                 else
00401                                         {
00402                                         if ((bp != NULL) && 
00403                                             (BIO_write(bp,"BAD INTEGER",11) <= 0))
00404                                                 goto end;
00405                                         }
00406                                 M_ASN1_INTEGER_free(bs);
00407                                 }
00408                         else if (tag == V_ASN1_ENUMERATED)
00409                                 {
00410                                 ASN1_ENUMERATED *bs;
00411                                 int i;
00412 
00413                                 opp=op;
00414                                 bs=d2i_ASN1_ENUMERATED(NULL,(SSLARG) &opp,len+hl);
00415                                 if (bs != NULL)
00416                                         {
00417                                         if ((bp != NULL) &&
00418                                             (BIO_write(bp,":",1) <= 0)) goto end;
00419                                         if (bs->type == V_ASN1_NEG_ENUMERATED)
00420                                                 if ((bp != NULL) &&
00421                                                     (BIO_write(bp,"-",1) <= 0))
00422                                                         goto end;
00423                                         for (i=0; i<bs->length; i++)
00424                                                 {
00425                                                 if ((bp != NULL) &&
00426                                                     (BIO_printf(bp,"%02X",
00427                                                         bs->data[i]) <= 0))
00428                                                         goto end;
00429                                                 }
00430                                         if (bs->length == 0)
00431                                                 {
00432                                                 if ((bp != NULL) &&
00433                                                     (BIO_write(bp,"00",2) <= 0))
00434                                                         goto end;
00435                                                 }
00436                                         }
00437                                 else
00438                                         {
00439                                         if ((bp != NULL) &&
00440                                             (BIO_write(bp,"BAD ENUMERATED",11) <= 0))
00441                                                 goto end;
00442                                         }
00443                                 M_ASN1_ENUMERATED_free(bs);
00444                                 }
00445                         else if (len > 0 && dump)
00446                                 {
00447                                 if (!nl) 
00448                                         {
00449                                         if ((bp != NULL) &&
00450                                             (BIO_write(bp,"\n",1) <= 0))
00451                                                 goto end;
00452                                         }
00453                                 if ((bp != NULL) &&
00454                                     (BIO_dump_indent(bp,(char *)p,
00455                                         ((dump == -1 || dump > len)?len:dump),
00456                                         dump_indent) <= 0))
00457                                         goto end;
00458                                 nl=1;
00459                                 }
00460 
00461                         if (!nl) 
00462                                 {
00463                                 if ((bp != NULL) &&
00464                                     (BIO_write(bp,"\n",1) <= 0)) goto end;
00465                                 }
00466                         p+=len;
00467                         if ((tag == V_ASN1_EOC) && (xclass == 0))
00468                                 {
00469                                 ret=2; /* End of sequence */
00470                                 goto end;
00471                                 }
00472                         }
00473 
00474                 length-=len;
00475                 }
00476         ret=1;
00477 end:
00478         if (o != NULL) ASN1_OBJECT_free(o);
00479         if (os != NULL) M_ASN1_OCTET_STRING_free(os);
00480         *pp=p;
00481         return(ret);
00482         }
00483 
00484 int GRSTasn1ParseDump(BIO *bp, unsigned char *pp, long len,
00485                       struct GRSTasn1TagList taglist[], 
00486                       int maxtag, int *lasttag)
00487         {
00488            return(GRSTasn1Parse2(bp,&pp,len,0,0,0,0,"",
00489                                  taglist, maxtag, lasttag));
00490         }                        
00491 
00492 int GRSTasn1GetX509Name(char *x509name, int maxlength, char *coords,
00493                         char *asn1string,
00494                         struct GRSTasn1TagList taglist[], int lasttag)                        
00495 {
00496    int i, iobj, istr, n, len = 0;
00497    ASN1_OBJECT *obj = NULL;
00498    unsigned char coordstmp[81], *q;
00499    const unsigned char *shortname;
00500 
00501    for (i=1; ; ++i)
00502       {
00503         snprintf((char*)coordstmp, sizeof(coordstmp), coords, i, 1);
00504         iobj = GRSTasn1SearchTaglist(taglist, lasttag, (char*)coordstmp);
00505         if (iobj < 0) break;
00506         
00507         snprintf((char*)coordstmp, sizeof(coordstmp), coords, i, 2);
00508         istr = GRSTasn1SearchTaglist(taglist, lasttag, (char*)coordstmp);
00509         if (istr < 0) break;
00510         
00511         q = (unsigned char*) &asn1string[taglist[iobj].start];
00512         d2i_ASN1_OBJECT(&obj, (SSLARG) &q, taglist[iobj].length +
00513                                   taglist[iobj].headerlength);
00514 
00515         n = OBJ_obj2nid(obj);
00516 // free obj now?
00517 //      if (obj) free (obj);
00518         shortname = (const unsigned char*) OBJ_nid2sn(n);
00519         
00520         if (len + 2 + strlen((char*)shortname) + taglist[istr].length >= maxlength)
00521           {
00522             x509name[0] = '\0';
00523             return GRST_RET_FAILED;          
00524           }
00525         
00526         sprintf(&x509name[len], "/%s=%.*s", shortname, 
00527                                 taglist[istr].length, 
00528                &asn1string[taglist[istr].start+taglist[istr].headerlength]);
00529         len += 2 + strlen((char*)shortname) + taglist[istr].length;
00530       }
00531       
00532    x509name[len] = '\0';
00533    
00534    return (x509name[0] != '\0') ? GRST_RET_OK : GRST_RET_FAILED;
00535 }

Generated on Tue Jul 5 14:47:00 2011 for ROOT_528-00b_version by  doxygen 1.5.1