📄 unber.c
字号:
/*- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: unber.c,v 1.14 2005/03/10 09:33:13 vlm Exp $ */#include "sys-common.h"#include <asn1parser.h> /* For static string tables */#include <asn_application.h>#include <constraints.c>#include <ber_tlv_tag.c>#include <ber_tlv_length.c>#include <OBJECT_IDENTIFIER.c>#include <RELATIVE-OID.c>#include <asn_codecs_prim.c>#undef COPYRIGHT#define COPYRIGHT \ "Copyright (c) 2004 Lev Walkin <vlm@lionet.info>\n"static void usage(const char *av0); /* Print the Usage screen and exit */static int process(const char *fname); /* Perform the BER decoding */static int decode_tlv_from_string(const char *datastring);static int single_type_decoding = 0; /* -1 enables that */static int pretty_printing = 1; /* -p disables that */static char *indent_buffer = " "; /* -i controls that */intmain(int ac, char **av) { int ch; /* Command line character */ int i; /* Index in some loops */ /* * Process command-line options. */ while((ch = getopt(ac, av, "1hi:pt:v")) != -1) switch(ch) { case '1': single_type_decoding = 1; break; case 't': if(decode_tlv_from_string(optarg)) exit(EX_DATAERR); exit(0); case 'p': pretty_printing = 0; break; case 'i': i = atoi(optarg); if(i >= 0 && i < 16) { indent_buffer = alloca(i + 1); memset(indent_buffer, ' ', i); indent_buffer[i] = '\0'; } else { fprintf(stderr, "-i %s: Invalid indent value\n",optarg); exit(EX_USAGE); } break; case 'v': fprintf(stderr, "ASN.1 BER Decoder, v" VERSION "\n" COPYRIGHT); exit(0); break; case 'h': default: usage(av[0]); } /* * Ensure that there are some input files present. */ if(ac > optind) { ac -= optind; av += optind; } else { fprintf(stderr, "%s: No input files specified\n", av[0]); exit(1); } setvbuf(stdout, 0, _IOLBF, 0); /* * Iterate over input files and parse each. * All syntax trees from all files will be bundled together. */ for(i = 0; i < ac; i++) { if(process(av[i])) exit(EX_DATAERR); } return 0;}/* * Print the usage screen and exit(EX_USAGE). */static voidusage(const char *av0) { fprintf(stderr,"ASN.1 BER Decoder, v" VERSION "\n" COPYRIGHT"Usage: %s [options] [-] [file ...]\n""Options:\n"" -1 Decode only the first BER structure (otherwise, until EOF)\n"" -i <indent> Amount of spaces for output indentation (default is 4)\n"" -p Do not attempt pretty-printing of known ASN.1 types\n"" -t <data-string> Decode the given tag[/length] sequence (e.g. -t \"bf20\")\n""\n""The XML opening tag format is as follows:\n"" <tform T=\"tag\" TL=\"tl_len\" V=\"{Indefinite|v_len}\" [A=\"type\"] [F]>\n""Where:\n"" tform Which form the value is in: constructed (\"C\", \"I\") or primitive (\"P\")\n"" tag The tag class and value\n"" tl_len The length of the TL (BER Tag and Length) encoding\n"" v_len The length of the value (V, encoded by the L), may be \"Indefinite\"\n"" type Likely name of the underlying ASN.1 type (for [UNIVERSAL n] tags)\n"" [F] Indicates that the value was reformatted (pretty-printed)\n""See the manual page for details\n" , av0); exit(EX_USAGE);}typedef enum pd_code { PD_FAILED = -1, PD_FINISHED = 0, PD_EOF = 1,} pd_code_e;static pd_code_e process_deeper(const char *fname, FILE *fp, int level, ssize_t limit, ssize_t *decoded, int expect_eoc);static void print_TL(int fin, int level, int constr, ssize_t tlen, ber_tlv_tag_t, ber_tlv_len_t);static int print_V(const char *fname, FILE *fp, ber_tlv_tag_t, ber_tlv_len_t);/* * Open the file and initiate recursive processing. */static intprocess(const char *fname) { FILE *fp; pd_code_e pdc; ssize_t decoded = 0; if(strcmp(fname, "-")) { fp = fopen(fname, "r"); if(!fp) { perror(fname); return -1; } } else { fp = stdin; } /* * Fetch out BER-encoded data until EOF or error. */ do { pdc = process_deeper(fname, fp, 0, -1, &decoded, 0); } while(pdc == PD_FINISHED && !single_type_decoding); if(fp != stdin) fclose(fp); if(pdc == PD_FAILED) return -1; return 0;}/* * Process the TLV recursively. */static pd_code_e process_deeper(const char *fname, FILE *fp, int level, ssize_t limit, ssize_t *decoded, int expect_eoc) { unsigned char tagbuf[32]; ssize_t tblen = 0; pd_code_e pdc = PD_FINISHED; ber_tlv_tag_t tlv_tag; ber_tlv_len_t tlv_len; ssize_t t_len; ssize_t l_len; do { int constr; int ch; if(limit == 0) return PD_FINISHED; if(limit >= 0 && tblen >= limit) { fprintf(stderr, "%s: Too long TL sequence (%ld >= %ld). " "Dangerous file\n", fname, (long)tblen, (long)limit); return PD_FAILED; } ch = fgetc(fp); if(ch == -1) { if(tblen) { fprintf(stderr, "%s: Unexpected end of file (TL)\n", fname); return PD_FAILED; } else { return PD_EOF; } } tagbuf[tblen++] = ch; /* * Decode the TLV tag. */ t_len = ber_fetch_tag(tagbuf, tblen, &tlv_tag); switch(t_len) { case -1: fprintf(stderr, "%s: Fatal error deciphering tag\n", fname); return PD_FAILED; case 0: /* More data expected */ continue; } /* * Decode the TLV length. */ constr = BER_TLV_CONSTRUCTED(tagbuf); l_len = ber_fetch_length(constr, tagbuf + t_len, tblen - t_len, &tlv_len); switch(l_len) { case -1: fprintf(stderr, "%s: Fatal error deciphering length\n", fname); return PD_FAILED; case 0: /* More data expected */ continue; } /* Make sure the T & L decoders took exactly the whole buffer */ assert((t_len + l_len) == tblen); if(!expect_eoc || tagbuf[0] || tagbuf[1]) print_TL(0, level, constr, tblen, tlv_tag, tlv_len); if(limit != -1) { /* If limit is set, account for the TL sequence */ limit -= (t_len + l_len); assert(limit >= 0); if(tlv_len > limit) { fprintf(stderr, "%s: Structure advertizes length (%ld) " "greater than of a parent container (%ld)\n", fname, (long)tlv_len, (long)limit); return PD_FAILED; } } *decoded += t_len + l_len; if(expect_eoc && tagbuf[0] == '\0' && tagbuf[1] == '\0') { /* End of content octets */ print_TL(1, level - 1, 1, 2, 0, -1); return PD_FINISHED; } if(constr) { ssize_t dec = 0; /* * This is a constructed type. Process recursively. */ printf(">\n"); /* Close the opening tag */ if(tlv_len != -1 && limit != -1) { assert(limit >= tlv_len); } pdc = process_deeper(fname, fp, level + 1, tlv_len == -1 ? limit : tlv_len, &dec, tlv_len == -1); if(pdc == PD_FAILED) return pdc; if(limit != -1) { assert(limit >= dec); limit -= dec; } *decoded += dec; if(tlv_len == -1) { tblen = 0; continue; } } else { assert(tlv_len >= 0); if(print_V(fname, fp, tlv_tag, tlv_len)) return PD_FAILED; if(limit != -1) { assert(limit >= tlv_len); limit -= tlv_len; } *decoded += tlv_len; } print_TL(1, level, constr, tblen, tlv_tag, tlv_len); tblen = 0; } while(1); return pdc;}static voidprint_TL(int fin, int level, int constr, ssize_t tlen, ber_tlv_tag_t tlv_tag, ber_tlv_len_t tlv_len) { if(fin && !constr) { printf("</P>\n"); return; } while(level-- > 0) printf(indent_buffer); /* Print indent */ printf(fin ? "</" : "<"); printf(constr ? ((tlv_len == -1) ? "I" : "C") : "P"); printf(" T=\""); ber_tlv_tag_fwrite(tlv_tag, stdout); printf("\""); if(!fin || tlv_len == -1) printf(" TL=\"%ld\"", (long)tlen); if(!fin) { if(tlv_len == -1) printf(" V=\"Indefinite\""); else printf(" V=\"%ld\"", (long)tlv_len); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -