00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include <stdio.h>
00064 #include <stdlib.h>
00065 #include <string.h>
00066 #include "apps.h"
00067 #include <openssl/err.h>
00068 #include <openssl/evp.h>
00069 #include <openssl/x509.h>
00070 #include <openssl/pem.h>
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #undef PROG
00081 #define PROG asn1parse_main
00082
00083 int MAIN(int, char **);
00084
00085 static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf);
00086
00087 int MAIN(int argc, char **argv)
00088 {
00089 int i,badops=0,offset=0,ret=1,j;
00090 unsigned int length=0;
00091 long num,tmplen;
00092 BIO *in=NULL,*out=NULL,*b64=NULL, *derout = NULL;
00093 int informat,indent=0, noout = 0, dump = 0;
00094 char *infile=NULL,*str=NULL,*prog,*oidfile=NULL, *derfile=NULL;
00095 char *genstr=NULL, *genconf=NULL;
00096 unsigned char *tmpbuf;
00097 const unsigned char *ctmpbuf;
00098 BUF_MEM *buf=NULL;
00099 STACK *osk=NULL;
00100 ASN1_TYPE *at=NULL;
00101
00102 informat=FORMAT_PEM;
00103
00104 apps_startup();
00105
00106 if (bio_err == NULL)
00107 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
00108 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
00109
00110 if (!load_config(bio_err, NULL))
00111 goto end;
00112
00113 prog=argv[0];
00114 argc--;
00115 argv++;
00116 if ((osk=sk_new_null()) == NULL)
00117 {
00118 BIO_printf(bio_err,"Memory allocation failure\n");
00119 goto end;
00120 }
00121 while (argc >= 1)
00122 {
00123 if (strcmp(*argv,"-inform") == 0)
00124 {
00125 if (--argc < 1) goto bad;
00126 informat=str2fmt(*(++argv));
00127 }
00128 else if (strcmp(*argv,"-in") == 0)
00129 {
00130 if (--argc < 1) goto bad;
00131 infile= *(++argv);
00132 }
00133 else if (strcmp(*argv,"-out") == 0)
00134 {
00135 if (--argc < 1) goto bad;
00136 derfile= *(++argv);
00137 }
00138 else if (strcmp(*argv,"-i") == 0)
00139 {
00140 indent=1;
00141 }
00142 else if (strcmp(*argv,"-noout") == 0) noout = 1;
00143 else if (strcmp(*argv,"-oid") == 0)
00144 {
00145 if (--argc < 1) goto bad;
00146 oidfile= *(++argv);
00147 }
00148 else if (strcmp(*argv,"-offset") == 0)
00149 {
00150 if (--argc < 1) goto bad;
00151 offset= atoi(*(++argv));
00152 }
00153 else if (strcmp(*argv,"-length") == 0)
00154 {
00155 if (--argc < 1) goto bad;
00156 length= atoi(*(++argv));
00157 if (length == 0) goto bad;
00158 }
00159 else if (strcmp(*argv,"-dump") == 0)
00160 {
00161 dump= -1;
00162 }
00163 else if (strcmp(*argv,"-dlimit") == 0)
00164 {
00165 if (--argc < 1) goto bad;
00166 dump= atoi(*(++argv));
00167 if (dump <= 0) goto bad;
00168 }
00169 else if (strcmp(*argv,"-strparse") == 0)
00170 {
00171 if (--argc < 1) goto bad;
00172 sk_push(osk,*(++argv));
00173 }
00174 else if (strcmp(*argv,"-genstr") == 0)
00175 {
00176 if (--argc < 1) goto bad;
00177 genstr= *(++argv);
00178 }
00179 else if (strcmp(*argv,"-genconf") == 0)
00180 {
00181 if (--argc < 1) goto bad;
00182 genconf= *(++argv);
00183 }
00184 else
00185 {
00186 BIO_printf(bio_err,"unknown option %s\n",*argv);
00187 badops=1;
00188 break;
00189 }
00190 argc--;
00191 argv++;
00192 }
00193
00194 if (badops)
00195 {
00196 bad:
00197 BIO_printf(bio_err,"%s [options] <infile\n",prog);
00198 BIO_printf(bio_err,"where options are\n");
00199 BIO_printf(bio_err," -inform arg input format - one of DER PEM\n");
00200 BIO_printf(bio_err," -in arg input file\n");
00201 BIO_printf(bio_err," -out arg output file (output format is always DER\n");
00202 BIO_printf(bio_err," -noout arg don't produce any output\n");
00203 BIO_printf(bio_err," -offset arg offset into file\n");
00204 BIO_printf(bio_err," -length arg length of section in file\n");
00205 BIO_printf(bio_err," -i indent entries\n");
00206 BIO_printf(bio_err," -dump dump unknown data in hex form\n");
00207 BIO_printf(bio_err," -dlimit arg dump the first arg bytes of unknown data in hex form\n");
00208 BIO_printf(bio_err," -oid file file of extra oid definitions\n");
00209 BIO_printf(bio_err," -strparse offset\n");
00210 BIO_printf(bio_err," a series of these can be used to 'dig' into multiple\n");
00211 BIO_printf(bio_err," ASN1 blob wrappings\n");
00212 BIO_printf(bio_err," -genstr str string to generate ASN1 structure from\n");
00213 BIO_printf(bio_err," -genconf file file to generate ASN1 structure from\n");
00214 goto end;
00215 }
00216
00217 ERR_load_crypto_strings();
00218
00219 in=BIO_new(BIO_s_file());
00220 out=BIO_new(BIO_s_file());
00221 if ((in == NULL) || (out == NULL))
00222 {
00223 ERR_print_errors(bio_err);
00224 goto end;
00225 }
00226 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
00227 #ifdef OPENSSL_SYS_VMS
00228 {
00229 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
00230 out = BIO_push(tmpbio, out);
00231 }
00232 #endif
00233
00234 if (oidfile != NULL)
00235 {
00236 if (BIO_read_filename(in,oidfile) <= 0)
00237 {
00238 BIO_printf(bio_err,"problems opening %s\n",oidfile);
00239 ERR_print_errors(bio_err);
00240 goto end;
00241 }
00242 OBJ_create_objects(in);
00243 }
00244
00245 if (infile == NULL)
00246 BIO_set_fp(in,stdin,BIO_NOCLOSE);
00247 else
00248 {
00249 if (BIO_read_filename(in,infile) <= 0)
00250 {
00251 perror(infile);
00252 goto end;
00253 }
00254 }
00255
00256 if (derfile) {
00257 if(!(derout = BIO_new_file(derfile, "wb"))) {
00258 BIO_printf(bio_err,"problems opening %s\n",derfile);
00259 ERR_print_errors(bio_err);
00260 goto end;
00261 }
00262 }
00263
00264 if ((buf=BUF_MEM_new()) == NULL) goto end;
00265 if (!BUF_MEM_grow(buf,BUFSIZ*8)) goto end;
00266
00267 if (genstr || genconf)
00268 {
00269 num = do_generate(bio_err, genstr, genconf, buf);
00270 if (num < 0)
00271 {
00272 ERR_print_errors(bio_err);
00273 goto end;
00274 }
00275 }
00276
00277 else
00278 {
00279
00280 if (informat == FORMAT_PEM)
00281 {
00282 BIO *tmp;
00283
00284 if ((b64=BIO_new(BIO_f_base64())) == NULL)
00285 goto end;
00286 BIO_push(b64,in);
00287 tmp=in;
00288 in=b64;
00289 b64=tmp;
00290 }
00291
00292 num=0;
00293 for (;;)
00294 {
00295 if (!BUF_MEM_grow(buf,(int)num+BUFSIZ)) goto end;
00296 i=BIO_read(in,&(buf->data[num]),BUFSIZ);
00297 if (i <= 0) break;
00298 num+=i;
00299 }
00300 }
00301 str=buf->data;
00302
00303
00304
00305 if (sk_num(osk))
00306 {
00307 tmpbuf=(unsigned char *)str;
00308 tmplen=num;
00309 for (i=0; i<sk_num(osk); i++)
00310 {
00311 ASN1_TYPE *atmp;
00312 int typ;
00313 j=atoi(sk_value(osk,i));
00314 if (j == 0)
00315 {
00316 BIO_printf(bio_err,"'%s' is an invalid number\n",sk_value(osk,i));
00317 continue;
00318 }
00319 tmpbuf+=j;
00320 tmplen-=j;
00321 atmp = at;
00322 ctmpbuf = tmpbuf;
00323 at = d2i_ASN1_TYPE(NULL,&ctmpbuf,tmplen);
00324 ASN1_TYPE_free(atmp);
00325 if(!at)
00326 {
00327 BIO_printf(bio_err,"Error parsing structure\n");
00328 ERR_print_errors(bio_err);
00329 goto end;
00330 }
00331 typ = ASN1_TYPE_get(at);
00332 if ((typ == V_ASN1_OBJECT)
00333 || (typ == V_ASN1_NULL))
00334 {
00335 BIO_printf(bio_err, "Can't parse %s type\n",
00336 typ == V_ASN1_NULL ? "NULL" : "OBJECT");
00337 ERR_print_errors(bio_err);
00338 goto end;
00339 }
00340
00341 tmpbuf=at->value.asn1_string->data;
00342 tmplen=at->value.asn1_string->length;
00343 }
00344 str=(char *)tmpbuf;
00345 num=tmplen;
00346 }
00347
00348 if (offset >= num)
00349 {
00350 BIO_printf(bio_err, "Error: offset too large\n");
00351 goto end;
00352 }
00353
00354 num -= offset;
00355
00356 if ((length == 0) || ((long)length > num)) length=(unsigned int)num;
00357 if(derout) {
00358 if(BIO_write(derout, str + offset, length) != (int)length) {
00359 BIO_printf(bio_err, "Error writing output\n");
00360 ERR_print_errors(bio_err);
00361 goto end;
00362 }
00363 }
00364 if (!noout &&
00365 !ASN1_parse_dump(out,(unsigned char *)&(str[offset]),length,
00366 indent,dump))
00367 {
00368 ERR_print_errors(bio_err);
00369 goto end;
00370 }
00371 ret=0;
00372 end:
00373 BIO_free(derout);
00374 if (in != NULL) BIO_free(in);
00375 if (out != NULL) BIO_free_all(out);
00376 if (b64 != NULL) BIO_free(b64);
00377 if (ret != 0)
00378 ERR_print_errors(bio_err);
00379 if (buf != NULL) BUF_MEM_free(buf);
00380 if (at != NULL) ASN1_TYPE_free(at);
00381 if (osk != NULL) sk_free(osk);
00382 OBJ_cleanup();
00383 apps_shutdown();
00384 OPENSSL_EXIT(ret);
00385 }
00386
00387 static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf)
00388 {
00389 CONF *cnf = NULL;
00390 int len;
00391 long errline;
00392 unsigned char *p;
00393 ASN1_TYPE *atyp = NULL;
00394
00395 if (genconf)
00396 {
00397 cnf = NCONF_new(NULL);
00398 if (!NCONF_load(cnf, genconf, &errline))
00399 goto conferr;
00400 if (!genstr)
00401 genstr = NCONF_get_string(cnf, "default", "asn1");
00402 if (!genstr)
00403 {
00404 BIO_printf(bio, "Can't find 'asn1' in '%s'\n", genconf);
00405 goto err;
00406 }
00407 }
00408
00409 atyp = ASN1_generate_nconf(genstr, cnf);
00410 NCONF_free(cnf);
00411
00412 if (!atyp)
00413 return -1;
00414
00415 len = i2d_ASN1_TYPE(atyp, NULL);
00416
00417 if (len <= 0)
00418 goto err;
00419
00420 if (!BUF_MEM_grow(buf,len))
00421 goto err;
00422
00423 p=(unsigned char *)buf->data;
00424
00425 i2d_ASN1_TYPE(atyp, &p);
00426
00427 ASN1_TYPE_free(atyp);
00428 return len;
00429
00430 conferr:
00431
00432 if (errline > 0)
00433 BIO_printf(bio, "Error on line %ld of config file '%s'\n",
00434 errline, genconf);
00435 else
00436 BIO_printf(bio, "Error loading config file '%s'\n", genconf);
00437
00438 err:
00439 NCONF_free(cnf);
00440 ASN1_TYPE_free(atyp);
00441
00442 return -1;
00443
00444 }