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
00046
00047
00048
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;
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;
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;
00079
00080
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
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;
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
00226 (len > 30) ? 30 : len);
00227
00228 BIO_printf(bp, "\n");
00229 }
00230
00231
00232
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
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;
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
00517
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 }