You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
9.5 KiB
351 lines
9.5 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
main.cpp
|
|
|
|
Abstract:
|
|
This file contains the client program for dealing with script signature.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 04/11/2000
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
#include <iostream>
|
|
|
|
#include <string>
|
|
#include <list>
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
static void Usage( int argc ,
|
|
LPCWSTR argv[] )
|
|
{
|
|
wprintf( L"Usage: %s <command> <parameters>\n\n", argv[0] );
|
|
wprintf( L"Available commands:\n\n" );
|
|
wprintf( L" CREATE <private key file> <public key file>\n" );
|
|
wprintf( L" SIGN <private key file> <file to sign> <signature file>\n" );
|
|
wprintf( L" VERIFY <public key file> <signed file> <signature file>\n" );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT LoadFile( /*[in ]*/ LPCWSTR szFile ,
|
|
/*[out]*/ HGLOBAL& hg )
|
|
{
|
|
__HCP_FUNC_ENTRY( "LoadFile" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<IStream> streamMem;
|
|
CComPtr<MPC::FileStream> streamFile;
|
|
|
|
|
|
//
|
|
// Create a stream for a file.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &streamFile ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamFile->InitForRead( szFile ));
|
|
|
|
|
|
//
|
|
// Create a memory stream.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal( NULL, FALSE, &streamMem ));
|
|
|
|
//
|
|
// Load the contents in memory.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( streamFile, streamMem ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::GetHGlobalFromStream( streamMem, &hg ));
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT SaveFile( /*[in]*/ LPCWSTR szFile ,
|
|
/*[in]*/ HGLOBAL hg )
|
|
{
|
|
__HCP_FUNC_ENTRY( "SaveFile" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<IStream> streamMem;
|
|
CComPtr<MPC::FileStream> streamFile;
|
|
|
|
|
|
//
|
|
// Create a stream for a file.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &streamFile ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamFile->InitForWrite( szFile ));
|
|
|
|
|
|
//
|
|
// Create a memory stream.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal( hg, FALSE, &streamMem ));
|
|
|
|
//
|
|
// Load the contents in memory.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( streamMem, streamFile ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT LoadFileAsString( /*[in ]*/ LPCWSTR szFile ,
|
|
/*[out]*/ CComBSTR& bstrData )
|
|
{
|
|
__HCP_FUNC_ENTRY( "LoadFileAsString" );
|
|
|
|
HRESULT hr;
|
|
HGLOBAL hg = NULL;
|
|
DWORD dwLen;
|
|
LPWSTR str;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFile( szFile, hg ));
|
|
|
|
dwLen = ::GlobalSize( hg );
|
|
|
|
bstrData.Attach( ::SysAllocStringLen( NULL, dwLen ) );
|
|
|
|
::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)::GlobalLock( hg ), dwLen, bstrData, (dwLen+1)*sizeof(WCHAR) ); bstrData[dwLen] = 0;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(hg) ::GlobalFree( hg );
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT SaveFileAsString( /*[in]*/ LPCWSTR szFile ,
|
|
/*[in]*/ const CComBSTR& bstrData )
|
|
{
|
|
__HCP_FUNC_ENTRY( "SaveFileAsString" );
|
|
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr;
|
|
DWORD dwLen = ::SysStringLen( bstrData );
|
|
HGLOBAL hg = NULL;
|
|
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (hg = ::GlobalAlloc( GMEM_FIXED, dwLen )));
|
|
|
|
::CopyMemory( hg, W2A(bstrData), dwLen );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveFile( szFile, hg ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(hg) ::GlobalFree( hg );
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT Create( /*[in]*/ LPCWSTR szPrivateFile ,
|
|
/*[in]*/ LPCWSTR szPublicFile )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Create" );
|
|
|
|
HRESULT hr;
|
|
CPCHCryptKeys key;
|
|
CComBSTR bstrPrivate;
|
|
CComBSTR bstrPublic;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, key.CreatePair());
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, key.ExportPair( bstrPrivate, bstrPublic ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveFileAsString( szPrivateFile, bstrPrivate ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveFileAsString( szPublicFile , bstrPublic ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT Sign( /*[in]*/ LPCWSTR szPrivateFile ,
|
|
/*[in]*/ LPCWSTR szDataFile ,
|
|
/*[in]*/ LPCWSTR szSignatureFile )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Sign" );
|
|
|
|
HRESULT hr;
|
|
CPCHCryptKeys key;
|
|
CComBSTR bstrPrivate;
|
|
CComBSTR bstrSignature;
|
|
HGLOBAL hg = NULL;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFileAsString( szPrivateFile, bstrPrivate ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFile ( szDataFile , hg ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, key.ImportPrivate( bstrPrivate ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, key.SignData( bstrSignature, (BYTE*)::GlobalLock( hg ), ::GlobalSize( hg ) ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveFileAsString( szSignatureFile, bstrSignature ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(hg) ::GlobalFree( hg );
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT Verify( /*[in]*/ LPCWSTR szPublicFile ,
|
|
/*[in]*/ LPCWSTR szDataFile ,
|
|
/*[in]*/ LPCWSTR szSignatureFile )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Sign" );
|
|
|
|
HRESULT hr;
|
|
CPCHCryptKeys key;
|
|
CComBSTR bstrPublic;
|
|
CComBSTR bstrSignature;
|
|
HGLOBAL hg = NULL;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFileAsString( szPublicFile , bstrPublic ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFileAsString( szSignatureFile, bstrSignature ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFile ( szDataFile , hg ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, key.ImportPublic( bstrPublic ));
|
|
|
|
|
|
hr = key.VerifyData( bstrSignature, (BYTE*)::GlobalLock( hg ), ::GlobalSize( hg ) );
|
|
if(FAILED(hr))
|
|
{
|
|
wprintf( L"Verification failure: 0x%08x\n", hr );
|
|
}
|
|
else
|
|
{
|
|
wprintf( L"Verification successful: 0x%08x\n", hr );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(hg) ::GlobalFree( hg );
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT ProcessArguments( int argc ,
|
|
LPCWSTR argv[] )
|
|
{
|
|
__HCP_FUNC_ENTRY( "ProcessArguments" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
if(argc < 2) { Usage( argc, argv ); __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL); }
|
|
|
|
if(!_wcsicmp( argv[1], L"CREATE" ))
|
|
{
|
|
if(argc < 4) { Usage( argc, argv ); __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL); }
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Create( argv[2], argv[3] ));
|
|
}
|
|
|
|
if(!_wcsicmp( argv[1], L"SIGN" ))
|
|
{
|
|
if(argc < 5) { Usage( argc, argv ); __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL); }
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Sign( argv[2], argv[3], argv[4] ));
|
|
}
|
|
|
|
if(!_wcsicmp( argv[1], L"VERIFY" ))
|
|
{
|
|
if(argc < 5) { Usage( argc, argv ); __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL); }
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Verify( argv[2], argv[3], argv[4] ));
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int __cdecl wmain( int argc ,
|
|
LPCWSTR argv[] )
|
|
{
|
|
HRESULT hr;
|
|
|
|
//DebugBreak();
|
|
|
|
//
|
|
// We need to be a single-threaded application, because we are hosting script engines and
|
|
// script engines don't like to be called from different threads...
|
|
//
|
|
if(SUCCEEDED(hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED )))
|
|
{
|
|
if(SUCCEEDED(hr = ::CoInitializeSecurity( NULL ,
|
|
-1 , // We don't care which authentication service we use.
|
|
NULL ,
|
|
NULL ,
|
|
RPC_C_AUTHN_LEVEL_CONNECT, // We want to identify the callers.
|
|
RPC_C_IMP_LEVEL_DELEGATE , // We want to be able to forward the caller's identity.
|
|
NULL ,
|
|
EOAC_DYNAMIC_CLOAKING , // Let's use the thread token for outbound calls.
|
|
NULL )))
|
|
{
|
|
__MPC_TRACE_INIT();
|
|
|
|
//
|
|
// Process arguments.
|
|
//
|
|
hr = ProcessArguments( argc, argv );
|
|
|
|
__MPC_TRACE_TERM();
|
|
}
|
|
|
|
::CoUninitialize();
|
|
}
|
|
|
|
return FAILED(hr) ? 10 : 0;
|
|
}
|