|
|
//
// file: drctencp.cpp
//
//
//=--------------------------------------------------------------------------=
// Copyright 1997-1999 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
#include <windows.h>
#include <wincrypt.h>
#include <STDIO.H>
#include <mq.h>
//
// Globals.
//
BOOL fEnhEncrypted = FALSE ; QMPROPID propidPK = PROPID_QM_ENCRYPTION_PK; WCHAR wszMachineName[ 128 ] = {0} ;
void Usage(char * pszProgramName) { fprintf(stderr, "...Usage: %s\n", pszProgramName); fprintf(stderr, "\t-2 send encrypted, RC2\n") ; fprintf(stderr, "\t-4 send encrypted, RC4\n") ; fprintf(stderr, "\t-b <Message Body>\n") ; fprintf(stderr, "\t-e Enhanced Encryption\n") ; fprintf(stderr, "\t-l <Message Label>\n") ; fprintf(stderr, "\t-m <Name of destination machine>\n") ; fprintf(stderr, "\t-q <Queue name>\n") ; exit(1); }
BOOL getPublicKeyBlob( PBYTE* pbPbKeyxKey, DWORD* pdwPbKeyxKeyLen) /*++
Routine Description: This routine retrieves the public key of the remote machine. The key is retrieved using the MQGetMachineProperties() API which connects to the Ds to retrieve the specified properties . Usually when using Direct mode no DS connection is available. This routine comes only as a substitute to other means of obtaining the remote machine public key. (SSL protocol, via disk or file etc') .
Arguments:
pbPbKeyxKey - (OUT) pointer to the Key. pdwPbKeyxKeyLen - (OUT) pointer to the key length
Return Value:
TRUE - if the Key was retreived . FALSE - if the Key couldn't be reteived.
--*/ { if (fEnhEncrypted) { propidPK = PROPID_QM_ENCRYPTION_PK_ENHANCED ; }
QMPROPID aQmPropId[1] ; aQmPropId[0] = propidPK ; #define QMPROPS (sizeof(aQmPropId) / sizeof(*aQmPropId))
MQPROPVARIANT aQmPropVar[QMPROPS]; HRESULT aQmStatus[QMPROPS];
MQQMPROPS QmProps = {QMPROPS, aQmPropId, aQmPropVar, aQmStatus};
aQmPropVar[0].vt = VT_NULL;
HRESULT hr = MQGetMachineProperties(wszMachineName, NULL, &QmProps); if (FAILED(hr)) { printf( "ERROR: Could not retrieve public key of %S, hr- %lxh\n", wszMachineName, hr);
return FALSE; }
if (aQmPropVar[0].vt != (VT_UI1|VT_VECTOR)) { printf( "Wrong VT after MQGetMachineProperties(), vt- %lxh, QMPROPS- %lut, hr- %lxh\n", aQmPropVar[0].vt, QMPROPS, hr) ; return FALSE ; }
*pbPbKeyxKey = aQmPropVar[0].caub.pElems; *pdwPbKeyxKeyLen = aQmPropVar[0].caub.cElems;
return TRUE; }
int main(int argc, char *argv[]) { DWORD dwEncryptAlg = CALG_RC2 ; WCHAR wszQueueName[ 128 ] = {0} ; WCHAR wszMsgLabel[ 128 ] = {TEXT("MessageLabel")} ; WCHAR wszMsgBody[ 128 ] = {TEXT("MessageBody")} ; LPSTR lpszArg = NULL ; DWORD dwMsgSize = sizeof(WCHAR) * (1 + wcslen(wszMsgBody)) ; DWORD dwBufferSize = sizeof(wszMsgBody) ; LPWSTR pMsgBody = wszMsgBody ;
//
// allow the user to override settings with command line switches
//
for ( int i = 1; i < argc; i++) { if ((*argv[i] == '-') || (*argv[i] == '/')) { switch (*(argv[i]+1)) { case '2': dwEncryptAlg = CALG_RC2 ; break ;
case '4': dwEncryptAlg = CALG_RC4 ; break ;
case 'e': fEnhEncrypted = TRUE ; break ;
case 'b': lpszArg = argv[++i]; mbstowcs(wszMsgBody, lpszArg, 127) ; break;
case 'l': lpszArg = argv[++i]; mbstowcs(wszMsgLabel, lpszArg, 127) ; break;
case 'm': lpszArg = argv[++i]; mbstowcs(wszMachineName, lpszArg, 127) ; break;
case 'q': lpszArg = argv[++i]; mbstowcs(wszQueueName, lpszArg, 127) ; break;
case 'h': case '?': default: Usage(argv[0]); } } else { Usage(argv[0]); } }
dwMsgSize = sizeof(WCHAR) * (1 + wcslen(wszMsgBody)) ;
//
// Get the public key blob of the destination computer.
//
PBYTE pbPbKeyxKey = NULL; DWORD dwPbKeyxKeyLen = 0;
if (getPublicKeyBlob( &pbPbKeyxKey, &dwPbKeyxKeyLen)) { printf("Public key of %S retrieved successfully, len- %lut\n", wszMachineName, dwPbKeyxKeyLen) ;
} else { return -1 ; }
//
// Get a handle to the default CSP.
//
LPWSTR lpwszProviderName = MS_DEF_PROV ; if (fEnhEncrypted) { lpwszProviderName = MS_ENHANCED_PROV ; } HCRYPTPROV hProv = NULL;
BOOL bRet = CryptAcquireContext( &hProv, NULL, lpwszProviderName, PROV_RSA_FULL, 0 ) ; if (!bRet) { if (GetLastError() == NTE_BAD_KEYSET) { //
// The default key container does not exist yet, create it.
//
if (!CryptAcquireContext( &hProv, NULL, lpwszProviderName, PROV_RSA_FULL, CRYPT_NEWKEYSET )) { printf( "CryptAcquireContext(%s, CRYPT_NEWKEYSET) failed, error- %lxh\n", lpwszProviderName, GetLastError()); return -1; } printf("CryptAcquireContext(%s, CRYPT_NEWKEYSET) succeeded\n", lpwszProviderName) ; } else { printf( "CryptAcquireContext(%s) failed, error- %lxh\n", lpwszProviderName, GetLastError()); return -1; } } else { printf("CryptAcquireContext(%s) succeeded\n", lpwszProviderName) ; }
//
// Import the public key blob of the destination computer into the CSP.
//
HCRYPTKEY hPbKey = NULL;
if (!CryptImportKey( hProv, pbPbKeyxKey, dwPbKeyxKeyLen, NULL, 0, &hPbKey )) { printf("CryptImportKey() failed, error- %lxh\n", GetLastError()); return -1; } printf("CryptImportKey() succeeded\n") ;
//
// Free the public key blob of the destination computer.
//
MQFreeMemory(pbPbKeyxKey);
//
// Create a symmetric key.
//
HCRYPTKEY hSymmKey = NULL;
if (!CryptGenKey(hProv, dwEncryptAlg, CRYPT_EXPORTABLE, &hSymmKey)) { printf("CryptGenKey() failed, error- %lxh\n", GetLastError()); return -1; } printf("CryptGenKey(alg- %lut) successfully created symmetric key\n", dwEncryptAlg) ; //
// Get the encrypted symmetric key blob. This blob should
// be passed to MQSendMessage in PROPID_M_DEST_SYMM_KEY.
//
BYTE abSymmKey[ 512 ]; DWORD dwSymmKeyLen = sizeof(abSymmKey);
if (!CryptExportKey( hSymmKey, hPbKey, SIMPLEBLOB, 0, abSymmKey, &dwSymmKeyLen )) { printf("CryptExportKey() failed, error- %lxh\n", GetLastError()); return -1; } printf("CryptExportKey() succeeded\n") ;
//
// Get a handle to the destination queue.
//
WCHAR szQueueFormat[128];
swprintf(szQueueFormat, TEXT("DIRECT=OS:%s\\%s"), wszMachineName, wszQueueName);
QUEUEHANDLE hQueue = NULL;
HRESULT hr = MQOpenQueue(szQueueFormat, MQ_SEND_ACCESS, 0, &hQueue); if (FAILED(hr)) { printf("MQOpenQueue(%S) failed, error- %lxh\n", szQueueFormat, hr) ; return -1; } printf("MQOpenQueue(%S) succeeded\n", szQueueFormat) ;
//
// Prepare the message properties.
//
GUID guid ;
MSGPROPID aMsgPropId[] = {PROPID_M_BODY, PROPID_M_DEST_SYMM_KEY, PROPID_M_ENCRYPTION_ALG, PROPID_M_CONNECTOR_TYPE, PROPID_M_LABEL, PROPID_M_PRIV_LEVEL}; #define MSGPROPS (sizeof(aMsgPropId) / sizeof(*aMsgPropId))
MQPROPVARIANT aMsgPropVar[MSGPROPS]; HRESULT aMsgStatus[MSGPROPS];
MQMSGPROPS MsgProps = {MSGPROPS, aMsgPropId, aMsgPropVar, aMsgStatus};
aMsgPropVar[0].vt = VT_VECTOR | VT_UI1; aMsgPropVar[0].caub.pElems = (BYTE*) pMsgBody ;
aMsgPropVar[1].vt = VT_VECTOR | VT_UI1; aMsgPropVar[1].caub.cElems = dwSymmKeyLen; aMsgPropVar[1].caub.pElems = abSymmKey;
aMsgPropVar[2].vt = VT_UI4; aMsgPropVar[2].ulVal = dwEncryptAlg ;
aMsgPropVar[3].vt = VT_CLSID; aMsgPropVar[3].puuid = &guid;
aMsgPropVar[4].vt = VT_LPWSTR; aMsgPropVar[4].pwszVal = wszMsgLabel;
//
// The connector type (PROPID_M_CONNECTOR_TYPE) is not initialized
// because it is assumed that nobody will bother about it on the
// receiving side, otherwise it should be initialized.
//
//
// Encrypt the line.
//
if (!CryptEncrypt( hSymmKey, NULL, TRUE, 0, (BYTE*) pMsgBody, &dwMsgSize, dwBufferSize )) { printf("CryptEncrypt() failed, error- %lxh\n", GetLastError()); return -1; } printf("CryptEncrypt() succeeded\n") ;
//
// Update the length of the message according to the result of the
// encryption algorithm. RC4 may enlarge the message size. On the
// destination, the message will be received as clear text with the
// correct (original) message body size.
//
aMsgPropVar[0].caub.cElems = dwMsgSize ; aMsgPropVar[5].vt = VT_UI4; if(!fEnhEncrypted) { aMsgPropVar[5].ulVal= MQMSG_PRIV_LEVEL_NONE ; } else { aMsgPropVar[5].ulVal = MQMSG_PRIV_LEVEL_BODY_ENHANCED ; } MsgProps.cProp = MSGPROPS ;
//
// Send the mesasge.
//
hr = MQSendMessage(hQueue, &MsgProps, NULL); if (FAILED(hr)) { printf("MQSendMessage() failed, hr- %lxh\n", hr) ; return -1; } printf("MQSendMessage() succeeded\n") ;
//
// Free resources. This is actually not required here, it is just
// to show how it should be done, if neccessary.
//
MQCloseQueue(hQueue); CryptDestroyKey(hSymmKey); CryptDestroyKey(hPbKey); CryptReleaseContext(hProv, 0);
return 0; }
|