📄 dumpasn1.c
字号:
{ sprintf( buffer, "%s/%s", pathPtr, CONFIG_NAME ); if( testConfigPath( buffer ) ) return( readConfig( buffer, TRUE ) ); pathPtr = strtok( NULL, ":" ); } while( pathPtr != NULL ); }#endif /* __UNIX__ */ /* Default to just the config name (which should fail as it was the first entry in configPaths[]). readConfig() will display the appropriate warning */ return( readConfig( CONFIG_NAME, TRUE ) ); }/***************************************************************************** ** Output/Formatting Routines ** *****************************************************************************/#ifdef __OS390__static int asciiToEbcdic( const int ch ) { char convBuffer[ 2 ]; convBuffer[ 0 ] = ch; convBuffer[ 1 ] = '\0'; __atoe( convBuffer ); /* Convert ASCII to EBCDIC for 390 */ return( convBuffer[ 0 ] ); }#endif /* __OS390__ *//* Indent a string by the appropriate amount */static void doIndent( const int level ) { int i; for( i = 0; i < level; i++ ) fprintf( output, printDots ? ". " : \ shallowIndent ? " " : " " ); }/* Complain about an error in the ASN.1 object */static void complain( const char *message, const int level ) { if( !doPure ) fprintf( output, INDENT_STRING ); doIndent( level + 1 ); fprintf( output, "Error: %s.\n", message ); noErrors++; }/* Dump data as a string of hex digits up to a maximum of 128 bytes */static void dumpHex( FILE *inFile, long length, int level, int isInteger ) { const int lineLength = ( dumpText ) ? 8 : 16; char printable[ 9 ]; long noBytes = length; int zeroPadded = FALSE, warnPadding = FALSE, warnNegative = isInteger; int singleLine = FALSE; int maxLevel = ( doPure ) ? 15 : 8, i; /* Check if LHS status info + indent + "OCTET STRING" string + data will wrap */ if( ( ( doPure ) ? 0 : INDENT_SIZE ) + ( level * 2 ) + 12 + \ ( length * 3 ) < outputWidth ) singleLine = TRUE; if( noBytes > 128 && !printAllData ) noBytes = 128; /* Only output a maximum of 128 bytes */ if( level > maxLevel ) level = maxLevel; /* Make sure that we don't go off edge of screen */ printable[ 8 ] = printable[ 0 ] = '\0'; for( i = 0; i < noBytes; i++ ) { int ch; if( !( i % lineLength ) ) { if( singleLine ) putchar( ' ' ); else { if( dumpText ) { /* If we're dumping text alongside the hex data, print the accumulated text string */ fputs( " ", output ); fputs( printable, output ); } fputc( '\n', output ); if( !doPure ) fprintf( output, INDENT_STRING ); doIndent( level + 1 ); } } ch = getc( inFile ); fprintf( output, "%s%02X", i % lineLength ? " " : "", ch ); printable[ i % 8 ] = ( ch >= ' ' && ch < 127 ) ? ch : '.'; fPos++; /* If we need to check for negative values and zero padding, check this now */ if( !i ) { if( !ch ) zeroPadded = TRUE; if( !( ch & 0x80 ) ) warnNegative = FALSE; } if( i == 1 && zeroPadded && ch < 0x80 ) warnPadding = TRUE; } if( dumpText ) { /* Print any remaining text */ i %= lineLength; printable[ i ] = '\0'; while( i < lineLength ) { fprintf( output, " " ); i++; } fputs( " ", output ); fputs( printable, output ); } if( length > 128 && !printAllData ) { length -= 128; fputc( '\n', output ); if( !doPure ) fprintf( output, INDENT_STRING ); doIndent( level + 5 ); fprintf( output, "[ Another %ld bytes skipped ]", length ); fPos += length; if( useStdin ) { while( length-- ) getc( inFile ); } else fseek( inFile, length, SEEK_CUR ); } fputs( "\n", output ); if( isInteger ) { if( warnPadding ) complain( "Integer has non-DER encoding", level ); if( warnNegative ) complain( "Integer has a negative value", level ); } }/* Dump a bitstring, reversing the bits into the standard order in the process */static void dumpBitString( FILE *inFile, const int length, const int unused, const int level ) { unsigned int bitString = 0, currentBitMask = 0x80, remainderMask = 0xFF; int bitFlag, value = 0, noBits, bitNo = -1, i; char *errorStr = NULL; if( unused < 0 || unused > 7 ) complain( "Invalid number of unused bits", level ); noBits = ( length * 8 ) - unused; /* ASN.1 bitstrings start at bit 0, so we need to reverse the order of the bits if necessary */ if( length ) { bitString = fgetc( inFile ); fPos++; } for( i = noBits - 8; i > 0; i -= 8 ) { bitString = ( bitString << 8 ) | fgetc( inFile ); currentBitMask <<= 8; remainderMask = ( remainderMask << 8 ) | 0xFF; fPos++; } if( reverseBitString ) { for( i = 0, bitFlag = 1; i < noBits; i++ ) { if( bitString & currentBitMask ) value |= bitFlag; if( !( bitString & remainderMask ) ) { /* The last valid bit should be a one bit */ errorStr = "Spurious zero bits in bitstring"; } bitFlag <<= 1; bitString <<= 1; } if( noBits < sizeof( int ) && \ ( ( remainderMask << noBits ) & value ) ) { /* There shouldn't be any bits set after the last valid one. We have to do the noBits check to avoid a fencepost error when there's exactly 32 bits */ errorStr = "Spurious one bits in bitstring"; } } else value = bitString; /* Now that it's in the right order, dump it. If there's only one bit set (which is often the case for bit flags) we also print the bit number to save users having to count the zeroes to figure out which flag is set */ fputc( '\n', output ); if( !doPure ) fprintf( output, INDENT_STRING ); doIndent( level + 1 ); fputc( '\'', output ); if( reverseBitString ) currentBitMask = 1 << ( noBits - 1 ); for( i = 0; i < noBits; i++ ) { if( value & currentBitMask ) { bitNo = ( bitNo == -1 ) ? ( noBits - 1 ) - i : -2; fputc( '1', output ); } else fputc( '0', output ); currentBitMask >>= 1; } if( bitNo >= 0 ) fprintf( output, "'B (bit %d)\n", bitNo ); else fputs( "'B\n", output ); if( errorStr != NULL ) complain( errorStr, level ); }/* Display data as a text string up to a maximum of 240 characters (8 lines of 48 chars to match the hex limit of 8 lines of 16 bytes) with special treatement for control characters and other odd things that can turn up in BMPString and UniversalString types. If the string is less than 40 chars in length, we try to print it on the same line as the rest of the text (even if it wraps), otherwise we break it up into 48-char chunks in a somewhat less nice text-dump format */static void displayString( FILE *inFile, long length, int level, STR_OPTION strOption ) { char timeStr[ 64 ];#ifdef __OS390__ char convBuffer[ 2 ];#endif /* __OS390__ */ long noBytes = length; int lineLength = 48, maxLevel = ( doPure ) ? 15 : 8, i; int firstTime = TRUE, doTimeStr = FALSE, warnIA5 = FALSE; int warnPrintable = FALSE, warnTime = FALSE, warnBMP = FALSE; if( noBytes > 384 && !printAllData ) noBytes = 384; /* Only output a maximum of 384 bytes */ if( strOption == STR_UTCTIME || strOption == STR_GENERALIZED ) { if( ( strOption == STR_UTCTIME && length != 13 ) || \ ( strOption == STR_GENERALIZED && length != 15 ) ) warnTime = TRUE; else doTimeStr = rawTimeString ? FALSE : TRUE; } if( !doTimeStr && length <= 40 ) fprintf( output, " '" ); /* Print string on same line */ if( level > maxLevel ) level = maxLevel; /* Make sure that we don't go off edge of screen */ for( i = 0; i < noBytes; i++ ) { int ch; /* If the string is longer than 40 chars, break it up into multiple sections */ if( length > 40 && !( i % lineLength ) ) { if( !firstTime ) fputc( '\'', output ); fputc( '\n', output ); if( !doPure ) fprintf( output, INDENT_STRING ); doIndent( level + 1 ); fputc( '\'', output ); firstTime = FALSE; } ch = getc( inFile );#if defined( __WIN32__ ) || defined( __UNIX__ ) || defined( __OS390__ ) if( strOption == STR_BMP ) { if( i == noBytes - 1 && ( noBytes & 1 ) ) /* Odd-length BMP string, complain */ warnBMP = TRUE; else { const wchar_t wCh = ( ch << 8 ) | getc( inFile ); char outBuf[ 8 ];#ifdef __OS390__ char *p;#endif /* OS-specific charset handling */ int outLen; /* Attempting to display Unicode characters is pretty hit and miss, and if it fails nothing is displayed. To try and detect this we use wcstombs() to see if anything can be displayed, if it can't we drop back to trying to display the data as non-Unicode. There's one exception to this case, which is for a wrong-endianness Unicode string, for which the first character looks like a single ASCII char */ outLen = wcstombs( outBuf, &wCh, 1 ); if( outLen < 1 ) { /* Can't be displayed as Unicode, fall back to displaying it as normal text */ ungetc( wCh & 0xFF, inFile ); } else { lineLength++; i++; /* We've read two characters for a wchar_t */#if defined( __WIN32__ ) fputwc( wCh, output );#elif defined( __UNIX__ ) && !( defined( __MACH__ ) || defined( __OpenBSD__ ) ) /* Some Unix environments differentiate between char and wide-oriented stdout (!!!), so it's necessary to manually switch the orientation of stdout to make it wide-oriented before calling a widechar output function or nothing will be output (exactly what level of braindamage it takes to have an implementation function like this is a mystery). In order to safely display widechars, we therefore have to use the fwide() kludge function to change stdout modes around the display of the widechar */ if( fwide( output, 1 ) > 0 ) { fputwc( wCh, output ); fwide( output, -1 ); } else fputc( wCh, output );#else #ifdef __OS390__ /* This could use some improvement */ for( p = outBuf; *p != '\0'; p++ ) *p = asciiToEbcdic( *p ); #endif /* IBM ASCII -> EBCDIC conversion */ fprintf( output, "%s", outBuf );#endif /* OS-specific charset handling */ fPos += 2; continue; } } }#endif /* __WIN32__ || __UNIX__ || __OS390__ */ switch( strOption ) { case STR_PRINTABLE: case STR_IA5: case STR_LATIN1: if( strOption == STR_PRINTABLE && !isPrintable( ch ) ) warnPrintable = TRUE; if( strOption == STR_IA5 && !isIA5( ch ) ) warnIA5 = TRUE; if( strOption == STR_LATIN1 ) { if( !isprint( ch & 0x7F ) ) ch = '.'; /* Convert non-ASCII to placeholders */ } else { if( !isprint( ch ) ) ch = '.'; /* Convert non-ASCII to placeholders */ }#ifdef __OS390__ ch = asciiToEbcdic( ch );#endif /* __OS390__ */ break; case STR_UTCTIME: case STR_GENERALIZED: if( !isdigit( ch ) && ch != 'Z' ) { warnTime = TRUE; if( !isprint( ch ) ) ch = '.'; /* Convert non-ASCII to placeholders */ }#ifdef __OS390__ ch = asciiToEbcdic( ch );#endif /* __OS390__ */ break; case STR_BMP_REVERSED: if( i == noBytes - 1 && ( noBytes & 1 ) ) { /* Odd-length BMP string, complain */ warnBMP = TRUE; } /* Wrong-endianness BMPStrings (Microsoft Unicode) can't be handled through the usual widechar-handling mechanism above since the first widechar looks like an ASCII char followed by a null terminator, so we just treat them as ASCII chars, skipping the following zero byte. This is safe since the code that detects reversed BMPStrings has already checked that every second byte is zero */ getc( inFile ); i++; fPos++; /* Drop through */ default: if( !isprint( ch ) ) ch = '.'; /* Convert control chars to placeholders */#ifdef __OS390__ ch = asciiToEbcdic( ch );#endif /* __OS390__ */ } if( doTimeStr ) timeStr[ i ] = ch; else fputc( ch, output ); fPos++; } if( length > 384 && !printAllData ) { length -= 384; fprintf( output, "'\n" ); if( !doPure ) fprintf( output, INDENT_STRING ); doIndent( level + 5 ); fprintf( output, "[ Another %ld characters skipped ]", length ); fPos += length; while( length-- ) { int ch = getc( inFile ); if( strOption == STR_PRINTABLE && !isPrintable( ch ) ) warnPrintable = TRUE; if( strOption == STR_IA5 && !isIA5( ch ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -