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

📄 dumpasn1.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:

				/* If there's a warning associated with this OID, remember
				   that there was a problem */
				if( oidInfo->warn )
					noWarnings++;

				break;
				}

			/* Pick apart the OID */
			x = ( unsigned char ) buffer[ 0 ] / 40;
			y = ( unsigned char ) buffer[ 0 ] % 40;
			if( x > 2 )
				{
				/* Handle special case for large y if x = 2 */
				y += ( x - 2 ) * 40;
				x = 2;
				}
			fprintf( output, " '%d %d", x, y );
			value = 0;
			for( x = 1; x < item->length; x++ )
				{
				value = ( value << 7 ) | ( buffer[ x ] & 0x7F );
				if( !( buffer[ x ] & 0x80 ) )
					{
					fprintf( output, " %ld", value );
					value = 0;
					}
				}
			fprintf( output, "'\n" );
			break;

		case EOC:
		case NULLTAG:
			fputc( '\n', output );
			break;

		case OBJDESCRIPTOR:
		case GRAPHICSTRING:
		case VISIBLESTRING:
		case GENERALSTRING:
		case UNIVERSALSTRING:
		case NUMERICSTRING:
		case T61STRING:
		case VIDEOTEXSTRING:
		case UTF8STRING:
			displayString( inFile, item->length, level, STR_NONE );
			break;
		case PRINTABLESTRING:
			displayString( inFile, item->length, level, STR_PRINTABLE );
			break;
		case BMPSTRING:
			displayString( inFile, item->length, level, STR_BMP );
			break;
		case UTCTIME:
			displayString( inFile, item->length, level, STR_UTCTIME );
			break;
		case GENERALIZEDTIME:
			displayString( inFile, item->length, level, STR_GENERALIZED );
			break;
		case IA5STRING:
			displayString( inFile, item->length, level, STR_IA5 );
			break;

		default:
			fputc( '\n', output );
			if( !doPure )
				fprintf( output, "            : " );
			doIndent( level + 1 );
			fprintf( output, "Unrecognised primitive, hex value is:");
			dumpHex( inFile, item->length, level, FALSE );
			noErrors++;		/* Treat it as an error */
		}
	}

/* Print a complex ASN.1 object */

int printAsn1( FILE *inFile, const int level, long length,
			   const int isIndefinite )
	{
	ASN1_ITEM item;
	long lastPos = fPos;
	int seenEOC = FALSE, status;

	/* Special-case for zero-length objects */
	if( !length && !isIndefinite )
		return( 0 );

	while( ( status = getItem( inFile, &item ) ) > 0 )
		{
		/* Perform various special checks the first time we're called */
		if( length == LENGTH_MAGIC )
			{
			/* If the length isn't known and the item has a definite length,
			   set the length to the item's length */
			if( !item.indefinite )
				length = item.headerSize + item.length;

			/* If the input isn't seekable, turn off some options which
			   require the use of fseek().  This check isn't perfect (some
			   streams are slightly seekable due to buffering) but it's
			   better than nothing */
			if( fseek( inFile, -item.headerSize, SEEK_CUR ) )
				{
				useStdin = TRUE;
				checkEncaps = FALSE;
				puts( "Warning: Input is non-seekable, some functionality "
					  "has been disabled." );
				}
			else
				fseek( inFile, item.headerSize, SEEK_CUR );
			}

		/* Dump the header as hex data if requested */
		if( doDumpHeader )
			dumpHeader( inFile, &item );

		/* Print offset into buffer, tag, and length */
		if( !doPure )
			if( item.indefinite )
				fprintf( output, ( doHexValues ) ? "%04lX %02X NDEF: " :
						 "%4ld %02X NDEF: ", lastPos, item.id | item.tag );
			else
				if( ( item.id | item.tag ) == EOC )
					seenEOC = TRUE;
				else
					fprintf( output, ( doHexValues ) ? "%04lX %02X %4lX: " :
							 "%4ld %02X %4ld: ", lastPos, item.id | item.tag,
							 item.length );

		/* Print details on the item */
		if( !seenEOC )
			{
			doIndent( level );
			printASN1object( inFile, &item, level );
			}

		/* If it was an indefinite-length object (no length was ever set) and
		   we've come back to the top level, exit */
		if( length == LENGTH_MAGIC )
			return( 0 );

		length -= fPos - lastPos;
		lastPos = fPos;
		if( isIndefinite )
			{
			if( seenEOC )
				return( 0 );
			}
		else
			if( length <= 0 )
				{
				if( length < 0 )
					return( ( int ) -length );
				return( 0 );
				}
			else
				if( length == 1 )
					{
					const int ch = fgetc( inFile );

					/* No object can be one byte long, try and recover.  This
					   only works sometimes because it can be caused by
					   spurious data in an OCTET STRING hole or an incorrect
					   length encoding.  The following workaround tries to
					   recover from spurious data by skipping the byte if
					   it's zero or a non-basic-ASN.1 tag, but keeping it if
					   it could be valid ASN.1 */
					if( ch && ch <= 0x31 )
						ungetc( ch, inFile );
					else
						{
						fPos++;
						return( 1 );
						}
					}
		}
	if( status == -1 )
		{
		fprintf( stderr, "\nError: Invalid data encountered at position "
				 "%d.\n", fPos );
		exit( EXIT_FAILURE );
		}

	/* If we see an EOF and there's supposed to be more data present,
	   complain */
	if( length && length != LENGTH_MAGIC )
		{
		fprintf( output, "Error: Inconsistent object length, %ld byte%s "
				 "difference.\n", length, ( length > 1 ) ? "s" : "" );
		noErrors++;
		}
	return( 0 );
	}

/* Show usage and exit */

void usageExit( void )
	{
	puts( "DumpASN1 - ASN.1 object dump/syntax check program." );
	puts( "Copyright Peter Gutmann 1997 - 2001.  Last updated " UPDATE_STRING "." );
	puts( "" );
	puts( "Usage: dumpasn1 [-acdefhlprstxz] <file>" );
	puts( "       - = Take input from stdin (some options may not work properly)" );
	puts( "       -<number> = Start <number> bytes into the file" );
	puts( "       -- = End of arg list" );
	puts( "       -a = Print all data in long data blocks, not just the first 128 bytes" );
	puts( "       -c<file> = Read Object Identifier info from alternate config file" );
	puts( "            (values will override equivalents in global config file)" );
	puts( "       -d = Print dots to show column alignment" );
	puts( "       -e = Don't print encapsulated data inside OCTET/BIT STRINGs" );
	puts( "       -f<file> = Dump object at offset -<number> to file (allows data to be" );
	puts( "            extracted from encapsulating objects)" );
	puts( "       -h = Hex dump object header (tag+length) before the decoded output" );
	puts( "       -hh = Same as -h but display more of the object as hex data" );
	puts( "       -l = Long format, display extra info about Object Identifiers" );
	puts( "       -p = Pure ASN.1 output without encoding information" );
	puts( "       -r = Print bits in BIT STRING as encoded in reverse order" );
	puts( "       -s = Syntax check only, don't dump ASN.1 structures" );
	puts( "       -t = Display text values next to hex dump of data" );
	puts( "       -x = Display size and offset in hex not decimal" );
	puts( "       -z = Allow zero-length items" );
	puts( "" );
	puts( "Warnings generated by deprecated OIDs require the use of '-l' to be displayed." );
	puts( "Program return code is the number of errors found or EXIT_SUCCESS." );
	exit( EXIT_FAILURE );
	}

int main( int argc, char *argv[] )
	{
	FILE *inFile, *outFile = NULL;
	char *pathPtr = argv[ 0 ];
	long offset = 0;
	int moreArgs = TRUE, doCheckOnly = FALSE;

	/* Skip the program name */
	argv++; argc--;

	/* Display usage if no args given */
	if( argc < 1 )
		usageExit();
	output = stdout;	/* Needs to be assigned at runtime */

	/* Check for arguments */
	while( argc && *argv[ 0 ] == '-' && moreArgs )
		{
		char *argPtr = argv[ 0 ] + 1;

		if( !*argPtr )
			useStdin = TRUE;
		while( *argPtr )
			{
			if( isdigit( *argPtr ) )
				{
				offset = atol( argPtr );
				break;
				}
			switch( toupper( *argPtr ) )
				{
				case '-':
					moreArgs = FALSE;	/* GNU-style end-of-args flag */
					break;

				case 'A':
					printAllData = TRUE;
					break;

				case 'C':
					if( !readConfig( argPtr + 1, FALSE ) )
						exit( EXIT_FAILURE );
					while( argPtr[ 1 ] )
						argPtr++;	/* Skip rest of arg */
					break;

				case 'D':
					printDots = TRUE;
					break;

				case 'E':
					checkEncaps = FALSE;
					break;

				case 'F':
					if( ( outFile = fopen( argPtr + 1, "wb" ) ) == NULL )
						{
						perror( argPtr + 1 );
						exit( EXIT_FAILURE );
						}
					while( argPtr[ 1 ] )
						argPtr++;	/* Skip rest of arg */
					break;

				case 'L':
					extraOIDinfo = TRUE;
					break;

				case 'H':
					doDumpHeader++;
					break;

				case 'P':
					doPure = TRUE;
					break;

				case 'R':
					reverseBitString = FALSE;
					break;

				case 'S':
					doCheckOnly = TRUE;
#if defined( __WIN32__ )
					/* Under Windows we can't fclose( stdout ) because the
					   VC++ runtime reassigns the stdout handle to the next
					   open file (which is valid) but then scribbles stdout
					   garbage all over it for files larger than about 16K
					   (which isn't), so we have to make sure that the
					   stdout handle is pointed to something somewhere */
					freopen( "nul", "w", stdout );
#elif defined( __UNIX__ )
					/* Safety feature in case any Unix libc is as broken
					   as the Win32 version */
					freopen( "/dev/null", "w", stdout );
#else
					fclose( stdout );
#endif /* OS-specific bypassing of stdout */
					break;

				case 'T':
					dumpText = TRUE;
					break;

				case 'X':
					doHexValues = TRUE;
					break;

				case 'Z':
					zeroLengthAllowed = TRUE;
					break;

				default:
					printf( "Unknown argument '%c'.\n", *argPtr );
					return( EXIT_SUCCESS );
				}
			argPtr++;
			}
		argv++;
		argc--;
		}

	/* We can't use options which perform an fseek() if reading from stdin */
	if( useStdin && ( doDumpHeader || outFile != NULL ) )
		{
		puts( "Can't use -f or -h when taking input from stdin" );
		exit( EXIT_FAILURE );
		}

	/* Check args and read the config file.  We don't bother weeding out
	   dups during the read because (a) the linear search would make the
	   process n^2, (b) during the dump process the search will terminate on
	   the first match so dups aren't that serious, and (c) there should be
	   very few dups present */
	if( argc != 1 && !useStdin )
		usageExit();
	if( !readGlobalConfig( pathPtr ) )
		exit( EXIT_FAILURE );

	/* Dump the given file */
	if( useStdin )
		inFile = stdin;
	else
		if( ( inFile = fopen( argv[ 0 ], "rb" ) ) == NULL )
			{
			perror( argv[ 0 ] );
			exit( EXIT_FAILURE );
			}
	if( useStdin )
		{
		while( offset-- )
			getc( inFile );
		}
	else
		fseek( inFile, offset, SEEK_SET );
	if( outFile != NULL )
		{
		ASN1_ITEM item;
		long length;
		int i, status;

		/* Make sure there's something there, and that it has a definite
		   length */
		status = getItem( inFile, &item );
		if( status == -1 )
			{
			puts( "Non-ASN.1 data encountered." );
			exit( EXIT_FAILURE );
			}
		if( status == 0 )
			{
			puts( "Nothing to read." );
			exit( EXIT_FAILURE );
			}
		if( item.indefinite )
			{
			puts( "Cannot process indefinite-length item." );
			exit( EXIT_FAILURE );
			}

		/* Copy the item across, first the header and then the data */
		for( i = 0; i < item.headerSize; i++ )
			putc( item.header[ i ], outFile );
		for( length = 0; length < item.length && !feof( inFile ); length++ )
			putc( getc( inFile ), outFile );
		fclose( outFile );

		fseek( inFile, offset, SEEK_SET );
		}
	printAsn1( inFile, 0, LENGTH_MAGIC, 0 );
	fclose( inFile );

	/* Print a summary of warnings/errors if it's required or appropriate */
	if( !doPure )
		{
		if( !doCheckOnly )
			fputc( '\n', stderr );
		fprintf( stderr, "%d warning%s, %d error%s.\n", noWarnings,
				( noWarnings != 1 ) ? "s" : "", noErrors,
				( noErrors != 1 ) ? "s" : "" );
		}

	return( ( noErrors ) ? noErrors : EXIT_SUCCESS );
	}

⌨️ 快捷键说明

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