cliexplorer.cpp

来自「PGP8.0源码 请认真阅读您的文件包然后写出其具体功能」· C++ 代码 · 共 909 行 · 第 1/2 页

CPP
909
字号
//////////////// START OF INTERPROCESS COMMUNICATION //////////

static char sEnvCSP[] = "CSP";
static char sEnvDataName[] = "KEY_CONTS_OUT_NAME";

static char sGetKeyConts[] = "-getIEKeyContainers";
#define CL_IE_TIMEOUT 45	/* In seconds */

/* Remove command options, if any */
static void sGetCurrArgv0( char *out, int size )  {
	LPCSTR s = GetCommandLine();
	char *firstQ=NULL, *secondQ=NULL;

	*out = '\0';

	/* remove leading spaces */
	while( *s == ' ' || *s == '\t' )
		s ++;	

	strncpy( out, s, size-1 );
	out[size-1] = '\0';

	/* Make sure we get the first qoute for the executable, 
	   not its argument */
	firstQ = ( *out == '"' ? out : NULL );

	if( firstQ )  {
		secondQ = strchr( firstQ+1, '"' );
		pgpAssert( secondQ ); /* How Windows allowed unterminated quotes? */ 
	}

	if( firstQ && secondQ )  {		/* Quotes were used */
		/* Remove quotes */
		secondQ[0] = '\0';
		memmove(out, firstQ+1, strlen(firstQ)/* including '\0' */ );
	}
	else if( firstQ == NULL )  {	/* No qoutes used */
		secondQ = strchr( out, ' ' );
		if( secondQ )
			*secondQ = '\0';
	}

#if PGP_DEBUG && defined(PGP_IE_TRACE_CONT_REMOTE)
	{
		char s[MAX_PATH+32];
		sprintf( s, "sGetCurrArgv0 returns %s\n", out );
		OutputDebugString( s );
	}
#endif
}

HANDLE static sGetRemoteProcess( const char *CSP, const char *dataName )  
{
	STARTUPINFO startupInfo;
	PROCESS_INFORMATION processInformation = {0};
	char path[MAX_PATH + sizeof(sGetKeyConts)];
	char cmdline[MAX_PATH + sizeof(sGetKeyConts)];
	char *env;
	BOOL r;
	int i=0;
	int CSP_len = 
		strlen(CSP) + sizeof(sEnvCSP)-1 + 1/*for'='*/ + 1/*for\0*/ +
		strlen(dataName) + sizeof(sEnvDataName)-1 + 1/*for'='*/ + 1/*for\0*/ +
		1 /*for\0*/;

	/* estimate the size of present environment block */

	env = GetEnvironmentStrings();

	for( i=0; env[i] != '\0'; i+=strlen(env+i)+1 ) {}
	
	CSP_len += i+1/*for\0*/;

	env = (char *)calloc( 1, CSP_len );
	if( !env )
		return NULL;

	memcpy( env, GetEnvironmentStrings(), i );

	sprintf( env+i, "%s=%s", sEnvCSP, CSP );
	i += strlen( env+i )+1;
		
	sprintf( env+i, "%s=%s", sEnvDataName, dataName );
	i += strlen( env+i ) +1;
	env[i] = '\0';

	memset( &startupInfo, 0, sizeof(startupInfo) );
	startupInfo.cb = sizeof(startupInfo);

	/* Determine the process to run */
	sGetCurrArgv0( path, sizeof(path) );

	/* Quote unquoted path and add option */
	strcpy( cmdline, "\"" );
	strcat( cmdline, path );
	strcat( cmdline, "\" " );
	strcat( cmdline, sGetKeyConts );

#if PGP_DEBUG
	{
		char u[MAX_PATH];
		strcpy( u, path );
		strupr( u );
		pgpAssert( strstr( u, "PGPKEYS" ) );	/* So far it is the case */
	}
#endif

	r = CreateProcess( 
		path,					// name of executable module
		cmdline,				// command line string
		NULL,					// SD
		NULL,					// SD
		FALSE,					// handle inheritance option
		0,						// creation flags
		env,					// new environment block
		NULL,					// current directory name
		&startupInfo,           // startup information
		&processInformation		// process information
	);

#if PGP_DEBUG
	DWORD err = GetLastError();
#endif

	free(env);

	return processInformation.hProcess;
}

HANDLE static sCreateTempFile()  {
	char s[MAX_PATH] = "";
	HANDLE h;

	GetTempPath (sizeof(s), s);
	GetTempFileName (s, "PGP", 0, s);

	h = CreateFile(
		s,								// file name
		GENERIC_READ|GENERIC_WRITE,     // access mode
		FILE_SHARE_WRITE,               // share mode
		NULL,							// SD
		CREATE_ALWAYS,					// how to create
		FILE_FLAG_DELETE_ON_CLOSE|FILE_ATTRIBUTE_TEMPORARY,  // file attributes
		NULL							// handle to template file
	);

	return h;
}

static int sCreateNamedData( HANDLE *hFile, HANDLE *hMapFile, const char *mapName, 
	const void *p, int size )  
{
	HANDLE hf, hm;
	DWORD n;

	*hFile = NULL;
	*hMapFile = NULL;

	hf = sCreateTempFile();
	if( hf == NULL )  {
		return -1;
	}

	WriteFile( hf, &size, sizeof(size), &n, NULL );
	if( p )
		WriteFile( hf, p, size, &n, NULL );

	hm = CreateFileMapping(
		hf,					// Current file handle. 
		NULL,                   // Default security. 
		PAGE_READWRITE,         // Read/write permission. 
		0,                      // Max. object size. 
		0,                      // Size of hFile. 
		mapName);			// Name of mapping object. 
 
	if (hm == NULL) 
	{ 
		pgpDebugMsg("Could not create file-mapping object."); 
		CloseHandle(hf);
		return -1;
	}

	*hFile = hf;
	*hMapFile = hm;

	return 0;
}

static sReadNamedData( const char *dataName, char **out )  {
	HANDLE hMapFileOut = NULL;
	void *lpMapAddress=NULL;
	int ret;
	int retries = CL_IE_TIMEOUT;

	*out = NULL;

	/* Now read reply */
	while( retries-- > 0 && hMapFileOut == NULL )  {
		Sleep(1000);
		hMapFileOut = OpenFileMapping(
			FILE_MAP_ALL_ACCESS,	// Read/write permission. 
			FALSE,                  // Do not inherit the name
			dataName);        
#if PGP_DEBUG
		if( retries < CL_IE_TIMEOUT - 10 )  
			OutputDebugString( "sReadNamedData: host process is not ready within 10 sec!\n" );
#endif
	
	}

	if( hMapFileOut == NULL )  {
		ret = -1;
		goto error;
	}

	lpMapAddress = MapViewOfFile(
		hMapFileOut,						// Handle to mapping object. 
		FILE_MAP_ALL_ACCESS,               // Read/write permission. 
		0,                                 // Max. object size. 
		0,                                 // Size of hFile. 
		0);                                // Map entire file. 

	if (lpMapAddress == NULL) 	{ 
		ret = -1;
		goto error;
	} 

	{
		DWORD l;
		char *c;

		l = *(DWORD*)lpMapAddress;

		if( l == 0 || l == -1 )
			goto error;

		c = (char *)malloc(l);
		if( c == NULL )  {
			ret = -1;
			goto error;
		}

		memcpy( c, (BYTE*)lpMapAddress + sizeof(l), l );
		*out = c;
	}

error:
	if( lpMapAddress )
		UnmapViewOfFile( lpMapAddress );
	CloseHandle(hMapFileOut);
	return ret;
}

/* This runs in another process */
extern "C" int PGPclExport
PGPclIEInit(const char *cmdLine)
{
	const char *CSP;
	const char *mapFileNameOut;

	HANDLE hFile, hMapFile;

	char *conts = NULL;
	int conts_n = 0;
	int l=0;

	if( cmdLine == NULL )
		cmdLine = GetCommandLine();

	/* Check for the magic */
	if( strstr( cmdLine, sGetKeyConts ) == NULL )  
		return 0;

	CSP = getenv( sEnvCSP );
	mapFileNameOut = getenv( sEnvDataName );

	if( !CSP )
		return -1;

	sGetExistingKeyContainers( CSP, &conts, &conts_n );
	if( conts_n )  {
		char *c = conts;
		while( conts_n > 0 )  {
			const size1 = strlen( c ) + 1;
			l += size1;
			c += size1;
			conts_n--;
		}
		l++;	/* For the last terminating symbol */
		pgpAssert( *c == '\0' );
	}

	/* Always create "reply" data, so the caller will not wait */
	sCreateNamedData( &hFile, 
		&hMapFile, mapFileNameOut, conts, l );

	free( conts );

	Sleep( CL_IE_TIMEOUT * 1000 );

	CloseHandle( hFile );
	CloseHandle( hMapFile );

	pgpAssert(0 /* Why this process wasn't killed? */);

	ExitProcess(-1);

	return 0;
}

/* Query for key containers using invocation of new process with 
   the same name as this one. 
   Remote process must call PGPclIEInit at the beginning. 
*/
extern "C" int PGPclExport
PGPclIEGetExistingKeyContainersRemote( const char *CSP, char **conts, int *n )  
{
	HANDLE hProc;
	int retries = 10;
	int ret = -1;
	char *dataNameValue=NULL;

	*conts = NULL;
	*n = 0;

	if( *CSP == '\0' )
		return 0;

	/* Generate data name to make it robust. 
	   (There is no much need to make this name random)
	*/
	if( CLIEGenerateNewUUID( &dataNameValue ) != 0 )
		return -1;

#if PGP_DEBUG
	/* make it easy-identifiable */
	{
		const char suffix[] = "dataNameValue";

		dataNameValue = (char*)realloc( dataNameValue, strlen(dataNameValue)+sizeof(suffix) );
		strcat( dataNameValue, suffix );
	}
#endif
	
	hProc = sGetRemoteProcess(CSP, dataNameValue);
	if( hProc == NULL  )
		goto error;

	{
		char *c, *p;
		int i=0;

		sReadNamedData( dataNameValue, &c );

		if( c == NULL )
			goto error;

		for( p=c; p && *p; p+=strlen(p)+1 )  {
			i++;
		}

		if( i )  {
			*n = i;
			*conts = c;
		}
	}

	ret = 0; // OK

error:
	free(dataNameValue);

	if( hProc != NULL )  {
		BOOL r = TerminateProcess( hProc, 0 );
		pgpAssert( r == TRUE );
		CloseHandle(hProc);
	}

	return ret;
}

extern "C" void PGPclExport PGPclIEFreeMem( void *cont )  {
	if( cont )
		free(cont);
}

/* 
	This class allows us to call PGPclIEInit implicitly; otherwize it needs to be called 
	somewhere close to WinMain
*/
static class A {
public:
	A()  {
		PGPclIEInit(NULL);
	}
} theInst;

//////////////// END OF INTERPROCESS COMMUNICATION //////////

#ifdef TEST
void main()  {
    char *cont;
    int n=0;
    char *p;
    char *diff;

    /* test container diff function */
    CLIEDiffKeyContainers( "3\0" "2\0" "1\0" "\0", "1\0" "2\0" "3\0" "4\0" "\0", &diff );
    printf( "diff=%s\n", diff );
    free(diff);

    printf( "Aladdin >>>\n" );
    sGetExistingKeyContainers( "eToken Base Cryptographic Provider", &cont, &n );
    p = cont;
    while( p && *p )  {
        printf( "Aladdin: %s\n", p );
        p += strlen( p ) + 1;
    }
    free( cont );
    cont = NULL;

    printf( "Schlumberger >>>\n" );    
    sGetExistingKeyContainers( "Schlumberger Cryptographic Service Provider", &cont, &n );
    p = cont;
    while( p && *p )  {
        printf( "Schlumberger: %s\n", p );
        p += strlen( p ) + 1;
    }
    free( cont );
    cont = NULL;

    printf( "iKey >>>\n" );
    sGetExistingKeyContainers( "Datakey RSA CSP", &cont, &n );
    p = cont;
    while( p && *p )  {
        printf( "Rainbow: %s\n", p );
        p += strlen( p ) + 1;
    }
    free( cont );
    cont = NULL;

    printf( "Gemsafe >>>\n" );
    sGetExistingKeyContainers( "Gemplus GemSAFE Card CSP", &cont, &n );
    p = cont;
    while( p && *p )  {
        printf( "GemSafe: %s\n", p );
        p += strlen( p ) + 1;
    }
    free( cont );
    cont = NULL;

}
#endif

⌨️ 快捷键说明

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