⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn1fix.c

📁 ASN.1解析解码工具,可以解析各种ASN.1格式的文件,并对相应的BER文件解码
💻 C
字号:
#include "asn1fix/asn1fix_internal.h"#include "asn1fix/asn1fix.h"/* Print everything to stderr */void _default_error_logger(int _severity, const char *fmt, ...);/* * Internal check functions. */static int asn1f_fix_module__phase_1(arg_t *arg);static int asn1f_fix_module__phase_2(arg_t *arg);static int asn1f_fix_simple(arg_t *arg);	/* For INTEGER/ENUMERATED */static int asn1f_fix_constructed(arg_t *arg);	/* For SEQUENCE/SET/CHOICE */static int asn1f_resolve_constraints(arg_t *arg); /* For subtype constraints */static int asn1f_check_constraints(arg_t *arg);	/* For subtype constraints */static int asn1f_check_duplicate(arg_t *arg);static int asn1f_apply_unique_index(arg_t *arg);static int phase_1_1(arg_t *arg, int prm2);arg_t a1f_replace_me_with_proper_interface_arg;/* * Scan every module defined here in search for inconsistences. */intasn1f_process(asn1p_t *asn, enum asn1f_flags flags,		error_logger_f error_logger) {	arg_t arg;	int fatals = 0;	int warnings = 0;	int ret;	/*	 * Check validity of arguments.	 */	if(asn == NULL) {		errno = EINVAL;		return -1;	}	/*	 * If errors handler is not specified, default to internal one.	 */	if(error_logger == 0) {		error_logger = _default_error_logger;	}	memset(&arg, 0, sizeof(arg));	arg.asn = asn;	arg.eh = error_logger;	if(flags & A1F_DEBUG) {		arg.debug = arg.eh;		arg.debug(-1, "Called %s() with flags %d", __func__, flags);		flags &= ~A1F_DEBUG;	}	/* Allow SIZE() constraint for INTEGER and other types */	if(flags & A1F_EXTENDED_SizeConstraint) {		arg.flags |= A1F_EXTENDED_SizeConstraint;		flags &= ~A1F_EXTENDED_SizeConstraint;		if(arg.debug) {			arg.debug(-1,				"Extended SizeConstraint support enabled");		}	}	a1f_replace_me_with_proper_interface_arg = arg;	/*	 * Check that we haven't missed an unknown flag.	 */	if(flags) {		errno = EINVAL;		return -1;	}	/*	 * Process each module in the list.	 * PHASE I.	 */	TQ_FOR(arg.mod, &(asn->modules), mod_next) {		ret = asn1f_fix_module__phase_1(&arg);		/*		 * These lines are used for illustration purposes.		 * RET2RVAL() is used everywhere else.		 */		if(ret == -1) fatals++;		if(ret == 1) warnings++;	}	/* PHASE II. */	TQ_FOR(arg.mod, &(asn->modules), mod_next) {		ret = asn1f_fix_module__phase_2(&arg);		if(ret == -1) fatals++;		if(ret == 1) warnings++;	}	memset(&a1f_replace_me_with_proper_interface_arg, 0, sizeof(arg_t));	/*	 * Compute a return value.	 */	return fatals?-1:warnings?1:0;}/* * Check the internals of a single module. */static intasn1f_fix_module__phase_1(arg_t *arg) {	asn1p_expr_t *expr;	int rvalue = 0;	int ret;	asn1p_module_t *omod;	/*	 * Check that we don't have a similarly named module.	 */	TQ_FOR(omod, &arg->asn->modules, mod_next) {		int sameNames;		if(omod == arg->mod) break;		sameNames = strcmp(omod->ModuleName, arg->mod->ModuleName)?0:1;		if(omod->module_oid && arg->mod->module_oid) {			/* Compare only the OID. */			if(asn1p_oid_compare(omod->module_oid,					arg->mod->module_oid) == 0) {				FATAL("ASN.1 module %s in %s "					"has the same OBJECT IDENTIFIER"					" as module %s",					omod->ModuleName,					omod->source_file_name,					arg->mod->ModuleName				);				RET2RVAL(-1, rvalue);			} else if(sameNames) {				WARNING("ASN.1 module %s is defined more than once, with different OIDs", omod->ModuleName);				RET2RVAL(1, rvalue);			}		} else if(sameNames) {			FATAL("ASN.1 module %s is defined more than once",				omod->ModuleName);			RET2RVAL(-1, rvalue);		}	}	switch((arg->mod->module_flags & MSF_MASK_TAGS)) {	case MSF_NOFLAGS:	case MSF_EXPLICIT_TAGS:	case MSF_IMPLICIT_TAGS:	case MSF_AUTOMATIC_TAGS:		break;	default:		FATAL("Module %s defined with ambiguous global tagging mode",			arg->mod->ModuleName);		RET2RVAL(-1, rvalue);	}	switch((arg->mod->module_flags & MSF_MASK_INSTRUCTIONS)) {	case MSF_NOFLAGS:		/*		 * arg->mod->module_flags |= MSF_TAG_INSTRUCTIONS;		 */		break;	case MSF_unk_INSTRUCTIONS:		WARNING("Module %s defined with unrecognized "			"encoding reference", arg->mod->ModuleName);		RET2RVAL(1, rvalue);		/* Fall through */	case MSF_TAG_INSTRUCTIONS:	case MSF_XER_INSTRUCTIONS:		break;	default:		FATAL("Module %s defined with ambiguous encoding reference",			arg->mod->ModuleName);		RET2RVAL(-1, rvalue);	}	/*	 * Do various non-recursive transformations.	 */	TQ_FOR(expr, &(arg->mod->members), next) {		arg->expr = expr;		ret = phase_1_1(arg, 0);		RET2RVAL(ret, rvalue);		/*		 * Make sure everybody's behaving well.		 */		assert(arg->expr == expr);	}	TQ_FOR(expr, &(arg->mod->members), next) {		arg->expr = expr;		ret = phase_1_1(arg, 1);		RET2RVAL(ret, rvalue);		assert(arg->expr == expr);	}	/*	 * 5. Automatic tagging	 */	TQ_FOR(expr, &(arg->mod->members), next) {		arg->expr = expr;		ret = asn1f_recurse_expr(arg, asn1f_fix_constr_autotag);		RET2RVAL(ret, rvalue);		assert(arg->expr == expr);	}	/*	 * 8. fix BIT STRING	 * 9. fix spaces in cstrings	 */	TQ_FOR(expr, &(arg->mod->members), next) {		arg->expr = expr;		ret = asn1f_recurse_expr(arg, asn1f_fix_bit_string);		RET2RVAL(ret, rvalue);		ret = asn1f_recurse_expr(arg, asn1f_fix_cstring);		RET2RVAL(ret, rvalue);		assert(arg->expr == expr);	}	/*	 * ... Check for tags distinctness.	 */	TQ_FOR(expr, &(arg->mod->members), next) {		arg->expr = expr;		ret = asn1f_recurse_expr(arg, asn1f_check_constr_tags_distinct);		RET2RVAL(ret, rvalue);		assert(arg->expr == expr);	}	return rvalue;}static intasn1f_fix_module__phase_2(arg_t *arg) {	asn1p_expr_t *expr;	int rvalue = 0;	int ret;	TQ_FOR(expr, &(arg->mod->members), next) {		arg->expr = expr;		/*		 * Dereference DEFAULT values.		 */		ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_defaults);		RET2RVAL(ret, rvalue);		/*		 * Check semantic validity of constraints.		 */		ret = asn1f_recurse_expr(arg, asn1f_check_constraints);		RET2RVAL(ret, rvalue);		/*		 * Uniquely tag each inner type.		 */		asn1f_apply_unique_index(0);		ret = asn1f_recurse_expr(arg, asn1f_apply_unique_index);		RET2RVAL(ret, rvalue);		assert(arg->expr == expr);	}	return rvalue;}static intphase_1_1(arg_t *arg, int prm2) {	asn1p_expr_t *expr = arg->expr;	int rvalue = 0;	int ret;	if(expr->lhs_params && expr->spec_index == -1) {		int i;		if(!prm2)			/* Do not process the parameterized type just yet */			return 0;		for(i = 0; i < expr->specializations.pspecs_count; i++) {			arg->expr = expr->specializations.pspec[i].my_clone;			ret = phase_1_1(arg, 0);			RET2RVAL(ret, rvalue);		}		arg->expr = expr;	/* revert */		return rvalue;	} else if(prm2) {		return 0;	/* Already done! */	}	/* Check whether this type is a duplicate */	if(!expr->lhs_params) {		ret = asn1f_check_duplicate(arg);		RET2RVAL(ret, rvalue);	}	DEBUG("=== Now processing \"%s\" (%d/0x%x) at line %d ===",		expr->Identifier, expr->meta_type, expr->expr_type,		expr->_lineno);	assert(expr->meta_type != AMT_INVALID);	/*	 * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc).	 */	ret = asn1f_recurse_expr(arg, asn1f_fix_simple);	RET2RVAL(ret, rvalue);	/*	 * 2.5.4	 */	ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types);	RET2RVAL(ret, rvalue);	/*	 * Fix tagging of top-level types.	 */	ret = asn1f_fix_constr_tag(arg, 1);	RET2RVAL(ret, rvalue);	/*	 * 2.[234] Process SEQUENCE/SET/CHOICE types.	 */	ret = asn1f_recurse_expr(arg, asn1f_fix_constructed);	RET2RVAL(ret, rvalue);	/*	 * 2.5.5	 */	ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values);	RET2RVAL(ret, rvalue);	/*	 * Parse class objects and fill up the object class with data.	 */	ret = asn1f_parse_class_object(arg);	RET2RVAL(ret, rvalue);	/*	 * Resolve references in constraints.	 */	ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);	RET2RVAL(ret, rvalue);	/*	 * 6. INTEGER value processed at 2.5.4.	 */	return rvalue;}static intasn1f_fix_simple(arg_t *arg) {	int rvalue = 0;	int ret;	ret = asn1f_fix_enum(arg);	RET2RVAL(ret, rvalue);	ret = asn1f_fix_integer(arg);	RET2RVAL(ret, rvalue);	return rvalue;}static intasn1f_fix_constructed(arg_t *arg) {	int rvalue = 0;	int ret;	switch(arg->expr->expr_type) {	case ASN_CONSTR_SEQUENCE:	case ASN_CONSTR_SET:	case ASN_CONSTR_CHOICE:		break;	default:		return 0;	}	/* Check identifier distinctness */	ret = asn1f_check_unique_expr(arg);	RET2RVAL(ret, rvalue);	/* Fix extensibility */	ret = asn1f_fix_constr_ext(arg);	RET2RVAL(ret, rvalue);	/* Fix tagging */	ret = asn1f_fix_constr_tag(arg, 0);	RET2RVAL(ret, rvalue);	/* Import COMPONENTS OF stuff */	ret = asn1f_pull_components_of(arg);	RET2RVAL(ret, rvalue);	return rvalue;}static intasn1f_resolve_constraints(arg_t *arg) {	asn1p_expr_t *top_parent;	asn1p_expr_type_e etype;	int rvalue = 0;	int ret;	top_parent = asn1f_find_terminal_type(arg, arg->expr);	if(top_parent)		etype = top_parent->expr_type;	else	etype = A1TC_INVALID;	DEBUG("(%s)", arg->expr->Identifier);	ret = asn1constraint_resolve(arg, arg->expr->constraints, etype, 0);	RET2RVAL(ret, rvalue);	return rvalue;}static intasn1f_check_constraints(arg_t *arg) {	static enum asn1p_constraint_type_e test_types[] = {		ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };	asn1p_expr_t *top_parent;	asn1cnst_range_t *range;	asn1p_expr_type_e etype;	unsigned int i;	int rvalue = 0;	int ret;	DEBUG("(%s{%d/%d})",		arg->expr->Identifier,		arg->expr->meta_type, arg->expr->expr_type);	top_parent = asn1f_find_terminal_type(arg, arg->expr);	if(!top_parent)		return 0;	etype = top_parent->expr_type;	ret = asn1constraint_pullup(arg);	RET2RVAL(ret, rvalue);	for(i = 0; i < sizeof(test_types)/sizeof(test_types[0]); i++) {		range = asn1constraint_compute_PER_range(				etype,				arg->expr->combined_constraints,				test_types[i], 0, 0,				CPR_noflags /* ignore -fbless-SIZE */);		if(!range && errno == EPERM) {			FATAL("This error happened for \"%s\" (meta %d) "				"at line %d",				arg->expr->Identifier,				arg->expr->meta_type,				arg->expr->_lineno);			return -1;		}		asn1constraint_range_free(range);	}	return rvalue;}static intasn1f_check_duplicate(arg_t *arg) {	arg_t tmparg = *arg;	int rvalue = 0;	/*	 * This is a linear scan in search of a similar type.	 * The linear scan is just fine for the task, no need to over-optimize.	 */	TQ_FOR(tmparg.mod, &arg->asn->modules, mod_next) {		int critical = 1;	/* FATAL */		if((arg->mod->_tags & MT_STANDARD_MODULE)		!= (tmparg.mod->_tags & MT_STANDARD_MODULE)) {			/* Ignore clashes with standard module */			critical = 0;	/* WARNING */		}		TQ_FOR(tmparg.expr, &(tmparg.mod->members), next) {			int diff_files;	/* different files */			assert(tmparg.expr->Identifier);			assert(arg->expr->Identifier);			if(arg->expr->spec_index != -1)				continue;			if(tmparg.expr == arg->expr) break;			if(strcmp(tmparg.expr->Identifier,				  arg->expr->Identifier))				continue;			diff_files = strcmp(arg->mod->source_file_name,					tmparg.mod->source_file_name) ? 1 : 0;			LOG(critical,			"ASN.1 expression \"%s\" at line %d of module %s\n"			"clashes with expression \"%s\" at line %d of module %s"			"%s%s%s.\n"			"Rename or remove either instance "				"to resolve the conflict",				arg->expr->Identifier,				arg->expr->_lineno,				arg->mod->ModuleName,				tmparg.expr->Identifier,				tmparg.expr->_lineno,				tmparg.mod->ModuleName,				diff_files ? " (" : "",				diff_files ? tmparg.mod->source_file_name : "",				diff_files ? ")" : "");			if(critical)				return -1;			RET2RVAL(1, rvalue);		}		if(tmparg.mod == arg->mod) break;	}	return rvalue;}static intasn1f_apply_unique_index(arg_t *arg) {	static int unique_index;	if(!arg) { unique_index = 0; return 0; }	arg->expr->_type_unique_index = ++unique_index;	return 0;}/* * Print everything to stderr */void_default_error_logger(int _severity, const char *fmt, ...) {	va_list ap;	char *pfx = "";	switch(_severity) {	case -1: pfx = "DEBUG: "; break;	case 0: pfx = "WARNING: "; break;	case 1: pfx = "FATAL: "; break;	}		fprintf(stderr, "%s", pfx);	va_start(ap, fmt);	vfprintf(stderr, fmt, ap);	va_end(ap);	fprintf(stderr, "\n");}int asn1p_error_logger(const char *fmt,...){	va_list ap;	va_start(ap, fmt);	vfprintf(stderr, fmt, ap);	va_end(ap);	fprintf(stderr, "\n");	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -