📄 utils.c
字号:
}
#endif /* Win32 */
/****************************************************************************
* *
* Debug Functions *
* *
****************************************************************************/
/* Write an object to a file for debugging purposes */
#if defined( _MSC_VER ) && \
!( defined( _WIN32_WCE ) || defined( __PALMSOURCE__ ) )
#include <direct.h>
#include <io.h>
#endif /* VC++ Win16/Win32 */
void debugDump( const char *fileName, const void *data, const int dataLength )
{
FILE *filePtr;
#ifdef __UNIX__
const char *tmpPath = getenv( "TMPDIR" );
char fileNameBuffer[ FILENAME_BUFFER_SIZE ];
const int tmpPathLen = ( tmpPath != NULL ) ? strlen( tmpPath ) : 0;
#else
char fileNameBuffer[ 128 ];
#endif /* __UNIX__ */
const int length = strlen( fileName );
fileNameBuffer[ 0 ] = '\0';
#if defined( _WIN32_WCE )
/* Under WinCE we don't want to scribble a ton of data into flash every
time we're run so we don't try and do anything */
return;
#elif ( defined( _MSC_VER ) && !defined( __PALMSOURCE__ ) )
/* If the path isn't absolute, deposit it in a temp directory */
if( fileName[ 1 ] != ':' )
{
if( access( "d:/tmp/", 6 ) == 0 )
{
/* There's a data partition available, dump the info there */
if( access( "d:/tmp/", 6 ) == -1 && \
!CreateDirectory( "d:/tmp", NULL ) )
return;
strcpy( fileNameBuffer, "d:/tmp/" );
}
else
{
/* There's no separate data partition, everything's dumped into
the same partition */
if( access( "c:/tmp/", 6 ) == -1 && mkdir( "c:/tmp" ) == -1 )
return;
strcpy( fileNameBuffer, "c:/tmp/" );
}
}
#elif defined( __UNIX__ )
/* If the path isn't absolute, deposit it in a temp directory */
if( fileName[ 0 ] != '/' )
{
if( tmpPathLen > 3 && tmpPathLen < FILENAME_BUFFER_SIZE - 64 )
{
strcpy( fileNameBuffer, tmpPath );
if( fileNameBuffer[ tmpPathLen - 1 ] != '/' )
strcat( fileNameBuffer + tmpPathLen, "/" );
}
else
strcpy( fileNameBuffer, "/tmp/" );
}
#else
fileNameBuffer[ 0 ] = '\0';
#endif /* OS-specific paths */
strcat( fileNameBuffer, fileName );
if( length <= 3 || fileName[ length - 4 ] != '.' )
strcat( fileNameBuffer, ".der" );
#if defined( __VMCMS__ )
{
char formatBuffer[ 32 ];
sprintf( formatBuffer, "wb, recfm=F, lrecl=%d, noseek", dataLength );
filePtr = fopen( fileNameBuffer, formatBuffer );
}
if( filePtr == NULL )
#else
if( ( filePtr = fopen( fileNameBuffer, "wb" ) ) == NULL )
#endif /* __VMCMS__ */
return;
fwrite( data, dataLength, 1, filePtr );
fclose( filePtr );
}
/****************************************************************************
* *
* Session Functions *
* *
****************************************************************************/
/* Print information on the peer that we're talking to */
int printConnectInfo( const CRYPT_SESSION cryptSession )
{
#ifndef UNICODE_STRINGS
time_t theTime;
#endif /* UNICODE_STRINGS */
C_CHR serverName[ 128 ];
int serverNameLength, serverPort, status;
status = cryptGetAttributeString( cryptSession, CRYPT_SESSINFO_CLIENT_NAME,
serverName, &serverNameLength );
if( cryptStatusError( status ) )
return( FALSE );
cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CLIENT_PORT, &serverPort );
#ifdef UNICODE_STRINGS
serverName[ serverNameLength / sizeof( wchar_t ) ] = TEXT( '\0' );
printf( "SVR: Connect attempt from %S, port %d", serverName, serverPort );
#else
serverName[ serverNameLength ] = '\0';
time( &theTime );
printf( "SVR: Connect attempt from %s, port %d, on %s.\n", serverName,
serverPort, getTimeString( theTime, 0 ) );
#endif /* UNICODE_STRINGS */
fflush( stdout );
/* Display all the attributes that we've got */
status = displayAttributes( cryptSession );
fflush( stdout );
return( status );
}
/* Print security info for the session */
int printSecurityInfo( const CRYPT_SESSION cryptSession,
const BOOLEAN isServer,
const BOOLEAN showFingerprint )
{
int cryptAlgo, keySize, version, status;
/* Print general security info */
status = cryptGetAttribute( cryptSession, CRYPT_CTXINFO_ALGO,
&cryptAlgo );
if( cryptStatusOK( status ) )
status = cryptGetAttribute( cryptSession, CRYPT_CTXINFO_KEYSIZE,
&keySize );
if( cryptStatusOK( status ) )
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_VERSION,
&version );
if( cryptStatusError( status ) )
{
printf( "Couldn't get session security parameters, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
printf( "%sSession is protected using algorithm %d with a %d bit key,\n"
" protocol version %d.\n", isServer ? "SVR: " : "",
cryptAlgo, keySize * 8, version );
fflush( stdout );
if( isServer || !showFingerprint )
return( TRUE );
status = printFingerprint( cryptSession, FALSE );
fflush( stdout );
return( status );
}
int printFingerprint( const CRYPT_SESSION cryptSession,
const BOOLEAN isServer )
{
BYTE fingerPrint[ CRYPT_MAX_HASHSIZE ];
int i, length, status;
/* Print the server key fingerprint */
status = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_FINGERPRINT,
fingerPrint, &length );
if( cryptStatusError( status ) )
{
printf( "cryptGetAttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
printf( "%sServer key fingerprint =", isServer ? "SVR: " : "" );
for( i = 0; i < length; i++ )
printf( " %02X", fingerPrint[ i ] );
puts( "." );
fflush( stdout );
return( TRUE );
}
/* Set up a client/server to connect locally. For the client his simply
tells it where to connect, for the server this binds it to the local
address so we don't inadvertently open up outside ports (admittedly
they can't do much except run the hardcoded self-test, but it's better
not to do this at all) */
BOOLEAN setLocalConnect( const CRYPT_SESSION cryptSession, const int port )
{
int status;
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME,
TEXT( "localhost" ),
paramStrlen( TEXT( "localhost" ) ) );
#ifdef __UNIX__
/* If we're running under Unix, set the port to a nonprivileged one so
we don't have to run as root. For anything other than very low-
numbered ports (e.g. SSH), the way we determine the port is to repeat
the first digit, so e.g. TSA on 318 becomes 3318, this seems to be
the method most commonly used */
if( cryptStatusOK( status ) && port < 1024 )
{
if( port < 100 )
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT,
port + 4000 );
else
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT,
( ( port / 100 ) * 1000 ) + port );
}
#endif /* __UNIX__ */
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute/AttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
return( TRUE );
}
/* Run a persistent server session, recycling the connection if the client
kept the link open */
int activatePersistentServerSession( const CRYPT_SESSION cryptSession,
const BOOLEAN showOperationType )
{
BOOLEAN connectionActive = FALSE;
int status;
do
{
/* Activate the connection */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE,
TRUE );
if( status == CRYPT_ERROR_READ && connectionActive )
{
/* The other side closed the connection after a previous
successful transaction, this isn't an error */
return( CRYPT_OK );
}
/* Print connection info and check whether the connection is still
active. If it is, we recycle the session so that we can process
another request */
printConnectInfo( cryptSession );
if( cryptStatusOK( status ) && showOperationType )
{
char userID[ CRYPT_MAX_TEXTSIZE ];
int userIDsize, requestType;
status = cryptGetAttribute( cryptSession,
CRYPT_SESSINFO_CMP_REQUESTTYPE,
&requestType );
if( cryptStatusOK( status ) )
status = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME,
userID, &userIDsize );
if( cryptStatusError( status ) )
printf( "cryptGetAttribute/AttributeString() failed with "
"error code %d, line %d.\n", status, __LINE__ );
else
{
userID[ userIDsize ] = '\0';
printf( "SVR: Operation type was %d, user '%s'.\n",
requestType, userID );
fflush( stdout );
}
}
cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CONNECTIONACTIVE,
&connectionActive );
}
while( cryptStatusOK( status ) && connectionActive );
return( status );
}
/****************************************************************************
* *
* Attribute Dump Routines *
* *
****************************************************************************/
/* Print a list of all attributes present in an object */
int displayAttributes( const CRYPT_HANDLE cryptHandle )
{
int status;
if( cryptStatusError( \
cryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT_GROUP,
CRYPT_CURSOR_FIRST ) ) )
return( TRUE );
puts( "Attributes present (by cryptlib ID) are:" );
do
{
BOOLEAN firstAttr = TRUE;
int value;
status = cryptGetAttribute( cryptHandle,
CRYPT_ATTRIBUTE_CURRENT_GROUP, &value );
if( cryptStatusError( status ) )
{
printf( "\nCurrent attribute group value read failed with "
"error code %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
printf( " Attribute group %d, values =", value );
do
{
status = cryptGetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT,
&value );
if( cryptStatusError( status ) )
{
printf( "\nCurrent attribute value read failed with error "
"code %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
if( !firstAttr )
putchar( ',' );
printf( " %d", value );
firstAttr = FALSE;
}
while( cryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT,
CRYPT_CURSOR_NEXT ) == CRYPT_OK );
puts( "." );
}
while( cryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT_GROUP,
CRYPT_CURSOR_NEXT ) == CRYPT_OK );
/* Reset the cursor to the first attribute. This is useful for things
like envelopes and sessions where the cursor points at the first
attribute that needs to be handled */
cryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT_GROUP,
CRYPT_CURSOR_FIRST );
return( TRUE );
}
/****************************************************************************
* *
* Certificate Dump Routines *
* *
****************************************************************************/
/* Print a hex string */
static void printHex( const BYTE *value, const int length )
{
int i;
for( i = 0; i < length; i++ )
{
if( i )
printf( " " );
printf( "%02X", value[ i ] );
}
puts( "." );
}
/* Print a DN */
static void printDN( const CRYPT_CERTIFICATE certificate )
{
char buffer[ 1024 + 1 ];
int length, status;
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_DN, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " DN string = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_COUNTRYNAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " C = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_STATEORPROVINCENAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " S = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_LOCALITYNAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " L = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_ORGANIZATIONNAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " O = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " OU = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_COMMONNAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " CN = %s.\n", buffer ); }
}
/* Print an altName */
static void printAltName( const CRYPT_CERTIFICATE certificate )
{
char buffer[ 512 ];
int length, status;
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_RFC822NAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " Email = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_DNSNAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " DNSName = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " EDI Nameassigner = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " EDI Partyname = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " URL = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_IPADDRESS, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " IP = %s.\n", buffer ); }
status = cryptGetAttributeString( certificate,
CRYPT_CERTINFO_REGISTEREDID, buffer, &length );
if( cryptStatusOK( status ) )
{ buffer[ length ] = '\0'; printf( " Registered ID = %s.\n", buffer ); }
status = cryptSetAttribute( certificate, CRYPT_CERTINFO_DIRECTORYNAME,
CRYPT_UNUSED );
if( cryptStatusOK( status ) )
{
printf( " altName DN is:\n" );
printDN( certificate );
}
}
/* The following function performs many attribute accesses, rather than using
huge numbers of status checks we use the following macro to check each
attribute access */
#define CHK( function ) \
status = function; \
if( cryptStatusError( status ) ) \
return( certInfoErrorExit( #function, status, __LINE__ ) )
static int certInfoErrorExit( const char *functionCall, const int status,
const int line )
{
printf( "\n%s failed with status %d, line %d.\n", functionCall,
status, line );
return( FALSE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -