Source code of Windows XP (NT5)
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.

415 lines
11 KiB

  1. //
  2. // file: drctencp.cpp
  3. //
  4. //
  5. //=--------------------------------------------------------------------------=
  6. // Copyright 1997-1999 Microsoft Corporation. All Rights Reserved.
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  9. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  10. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  11. // PARTICULAR PURPOSE.
  12. //=--------------------------------------------------------------------------=
  13. #include <windows.h>
  14. #include <wincrypt.h>
  15. #include <STDIO.H>
  16. #include <mq.h>
  17. //
  18. // Globals.
  19. //
  20. BOOL fEnhEncrypted = FALSE ;
  21. QMPROPID propidPK = PROPID_QM_ENCRYPTION_PK;
  22. WCHAR wszMachineName[ 128 ] = {0} ;
  23. void Usage(char * pszProgramName)
  24. {
  25. fprintf(stderr, "...Usage: %s\n", pszProgramName);
  26. fprintf(stderr, "\t-2 send encrypted, RC2\n") ;
  27. fprintf(stderr, "\t-4 send encrypted, RC4\n") ;
  28. fprintf(stderr, "\t-b <Message Body>\n") ;
  29. fprintf(stderr, "\t-e Enhanced Encryption\n") ;
  30. fprintf(stderr, "\t-l <Message Label>\n") ;
  31. fprintf(stderr, "\t-m <Name of destination machine>\n") ;
  32. fprintf(stderr, "\t-q <Queue name>\n") ;
  33. exit(1);
  34. }
  35. BOOL getPublicKeyBlob( PBYTE* pbPbKeyxKey, DWORD* pdwPbKeyxKeyLen)
  36. /*++
  37. Routine Description:
  38. This routine retrieves the public key of the remote machine.
  39. The key is retrieved using the MQGetMachineProperties() API which connects to the Ds to retrieve
  40. the specified properties .
  41. Usually when using Direct mode no DS connection is available.
  42. This routine comes only as a substitute to other means of obtaining the
  43. remote machine public key. (SSL protocol, via disk or file etc') .
  44. Arguments:
  45. pbPbKeyxKey - (OUT) pointer to the Key.
  46. pdwPbKeyxKeyLen - (OUT) pointer to the key length
  47. Return Value:
  48. TRUE - if the Key was retreived .
  49. FALSE - if the Key couldn't be reteived.
  50. --*/
  51. {
  52. if (fEnhEncrypted)
  53. {
  54. propidPK = PROPID_QM_ENCRYPTION_PK_ENHANCED ;
  55. }
  56. QMPROPID aQmPropId[1] ;
  57. aQmPropId[0] = propidPK ;
  58. #define QMPROPS (sizeof(aQmPropId) / sizeof(*aQmPropId))
  59. MQPROPVARIANT aQmPropVar[QMPROPS];
  60. HRESULT aQmStatus[QMPROPS];
  61. MQQMPROPS QmProps = {QMPROPS, aQmPropId, aQmPropVar, aQmStatus};
  62. aQmPropVar[0].vt = VT_NULL;
  63. HRESULT hr = MQGetMachineProperties(wszMachineName, NULL, &QmProps);
  64. if (FAILED(hr))
  65. {
  66. printf(
  67. "ERROR: Could not retrieve public key of %S, hr- %lxh\n",
  68. wszMachineName, hr);
  69. return FALSE;
  70. }
  71. if (aQmPropVar[0].vt != (VT_UI1|VT_VECTOR))
  72. {
  73. printf(
  74. "Wrong VT after MQGetMachineProperties(), vt- %lxh, QMPROPS- %lut, hr- %lxh\n",
  75. aQmPropVar[0].vt, QMPROPS, hr) ;
  76. return FALSE ;
  77. }
  78. *pbPbKeyxKey = aQmPropVar[0].caub.pElems;
  79. *pdwPbKeyxKeyLen = aQmPropVar[0].caub.cElems;
  80. return TRUE;
  81. }
  82. int main(int argc, char *argv[])
  83. {
  84. DWORD dwEncryptAlg = CALG_RC2 ;
  85. WCHAR wszQueueName[ 128 ] = {0} ;
  86. WCHAR wszMsgLabel[ 128 ] = {TEXT("MessageLabel")} ;
  87. WCHAR wszMsgBody[ 128 ] = {TEXT("MessageBody")} ;
  88. LPSTR lpszArg = NULL ;
  89. DWORD dwMsgSize = sizeof(WCHAR) * (1 + wcslen(wszMsgBody)) ;
  90. DWORD dwBufferSize = sizeof(wszMsgBody) ;
  91. LPWSTR pMsgBody = wszMsgBody ;
  92. //
  93. // allow the user to override settings with command line switches
  94. //
  95. for ( int i = 1; i < argc; i++)
  96. {
  97. if ((*argv[i] == '-') || (*argv[i] == '/'))
  98. {
  99. switch (*(argv[i]+1))
  100. {
  101. case '2':
  102. dwEncryptAlg = CALG_RC2 ;
  103. break ;
  104. case '4':
  105. dwEncryptAlg = CALG_RC4 ;
  106. break ;
  107. case 'e':
  108. fEnhEncrypted = TRUE ;
  109. break ;
  110. case 'b':
  111. lpszArg = argv[++i];
  112. mbstowcs(wszMsgBody, lpszArg, 127) ;
  113. break;
  114. case 'l':
  115. lpszArg = argv[++i];
  116. mbstowcs(wszMsgLabel, lpszArg, 127) ;
  117. break;
  118. case 'm':
  119. lpszArg = argv[++i];
  120. mbstowcs(wszMachineName, lpszArg, 127) ;
  121. break;
  122. case 'q':
  123. lpszArg = argv[++i];
  124. mbstowcs(wszQueueName, lpszArg, 127) ;
  125. break;
  126. case 'h':
  127. case '?':
  128. default:
  129. Usage(argv[0]);
  130. }
  131. }
  132. else
  133. {
  134. Usage(argv[0]);
  135. }
  136. }
  137. dwMsgSize = sizeof(WCHAR) * (1 + wcslen(wszMsgBody)) ;
  138. //
  139. // Get the public key blob of the destination computer.
  140. //
  141. PBYTE pbPbKeyxKey = NULL;
  142. DWORD dwPbKeyxKeyLen = 0;
  143. if (getPublicKeyBlob( &pbPbKeyxKey, &dwPbKeyxKeyLen))
  144. {
  145. printf("Public key of %S retrieved successfully, len- %lut\n",
  146. wszMachineName, dwPbKeyxKeyLen) ;
  147. }
  148. else
  149. {
  150. return -1 ;
  151. }
  152. //
  153. // Get a handle to the default CSP.
  154. //
  155. LPWSTR lpwszProviderName = MS_DEF_PROV ;
  156. if (fEnhEncrypted)
  157. {
  158. lpwszProviderName = MS_ENHANCED_PROV ;
  159. }
  160. HCRYPTPROV hProv = NULL;
  161. BOOL bRet = CryptAcquireContext( &hProv,
  162. NULL,
  163. lpwszProviderName,
  164. PROV_RSA_FULL,
  165. 0 ) ;
  166. if (!bRet)
  167. {
  168. if (GetLastError() == NTE_BAD_KEYSET)
  169. {
  170. //
  171. // The default key container does not exist yet, create it.
  172. //
  173. if (!CryptAcquireContext( &hProv,
  174. NULL,
  175. lpwszProviderName,
  176. PROV_RSA_FULL,
  177. CRYPT_NEWKEYSET ))
  178. {
  179. printf(
  180. "CryptAcquireContext(%s, CRYPT_NEWKEYSET) failed, error- %lxh\n",
  181. lpwszProviderName, GetLastError());
  182. return -1;
  183. }
  184. printf("CryptAcquireContext(%s, CRYPT_NEWKEYSET) succeeded\n",
  185. lpwszProviderName) ;
  186. }
  187. else
  188. {
  189. printf(
  190. "CryptAcquireContext(%s) failed, error- %lxh\n",
  191. lpwszProviderName, GetLastError());
  192. return -1;
  193. }
  194. }
  195. else
  196. {
  197. printf("CryptAcquireContext(%s) succeeded\n", lpwszProviderName) ;
  198. }
  199. //
  200. // Import the public key blob of the destination computer into the CSP.
  201. //
  202. HCRYPTKEY hPbKey = NULL;
  203. if (!CryptImportKey( hProv,
  204. pbPbKeyxKey,
  205. dwPbKeyxKeyLen,
  206. NULL,
  207. 0,
  208. &hPbKey ))
  209. {
  210. printf("CryptImportKey() failed, error- %lxh\n", GetLastError());
  211. return -1;
  212. }
  213. printf("CryptImportKey() succeeded\n") ;
  214. //
  215. // Free the public key blob of the destination computer.
  216. //
  217. MQFreeMemory(pbPbKeyxKey);
  218. //
  219. // Create a symmetric key.
  220. //
  221. HCRYPTKEY hSymmKey = NULL;
  222. if (!CryptGenKey(hProv, dwEncryptAlg, CRYPT_EXPORTABLE, &hSymmKey))
  223. {
  224. printf("CryptGenKey() failed, error- %lxh\n", GetLastError());
  225. return -1;
  226. }
  227. printf("CryptGenKey(alg- %lut) successfully created symmetric key\n",
  228. dwEncryptAlg) ;
  229. //
  230. // Get the encrypted symmetric key blob. This blob should
  231. // be passed to MQSendMessage in PROPID_M_DEST_SYMM_KEY.
  232. //
  233. BYTE abSymmKey[ 512 ];
  234. DWORD dwSymmKeyLen = sizeof(abSymmKey);
  235. if (!CryptExportKey( hSymmKey,
  236. hPbKey,
  237. SIMPLEBLOB,
  238. 0,
  239. abSymmKey,
  240. &dwSymmKeyLen ))
  241. {
  242. printf("CryptExportKey() failed, error- %lxh\n", GetLastError());
  243. return -1;
  244. }
  245. printf("CryptExportKey() succeeded\n") ;
  246. //
  247. // Get a handle to the destination queue.
  248. //
  249. WCHAR szQueueFormat[128];
  250. swprintf(szQueueFormat, TEXT("DIRECT=OS:%s\\%s"),
  251. wszMachineName, wszQueueName);
  252. QUEUEHANDLE hQueue = NULL;
  253. HRESULT hr = MQOpenQueue(szQueueFormat, MQ_SEND_ACCESS, 0, &hQueue);
  254. if (FAILED(hr))
  255. {
  256. printf("MQOpenQueue(%S) failed, error- %lxh\n", szQueueFormat, hr) ;
  257. return -1;
  258. }
  259. printf("MQOpenQueue(%S) succeeded\n", szQueueFormat) ;
  260. //
  261. // Prepare the message properties.
  262. //
  263. GUID guid ;
  264. MSGPROPID aMsgPropId[] = {PROPID_M_BODY,
  265. PROPID_M_DEST_SYMM_KEY,
  266. PROPID_M_ENCRYPTION_ALG,
  267. PROPID_M_CONNECTOR_TYPE,
  268. PROPID_M_LABEL,
  269. PROPID_M_PRIV_LEVEL};
  270. #define MSGPROPS (sizeof(aMsgPropId) / sizeof(*aMsgPropId))
  271. MQPROPVARIANT aMsgPropVar[MSGPROPS];
  272. HRESULT aMsgStatus[MSGPROPS];
  273. MQMSGPROPS MsgProps = {MSGPROPS, aMsgPropId, aMsgPropVar, aMsgStatus};
  274. aMsgPropVar[0].vt = VT_VECTOR | VT_UI1;
  275. aMsgPropVar[0].caub.pElems = (BYTE*) pMsgBody ;
  276. aMsgPropVar[1].vt = VT_VECTOR | VT_UI1;
  277. aMsgPropVar[1].caub.cElems = dwSymmKeyLen;
  278. aMsgPropVar[1].caub.pElems = abSymmKey;
  279. aMsgPropVar[2].vt = VT_UI4;
  280. aMsgPropVar[2].ulVal = dwEncryptAlg ;
  281. aMsgPropVar[3].vt = VT_CLSID;
  282. aMsgPropVar[3].puuid = &guid;
  283. aMsgPropVar[4].vt = VT_LPWSTR;
  284. aMsgPropVar[4].pwszVal = wszMsgLabel;
  285. //
  286. // The connector type (PROPID_M_CONNECTOR_TYPE) is not initialized
  287. // because it is assumed that nobody will bother about it on the
  288. // receiving side, otherwise it should be initialized.
  289. //
  290. //
  291. // Encrypt the line.
  292. //
  293. if (!CryptEncrypt( hSymmKey,
  294. NULL,
  295. TRUE,
  296. 0,
  297. (BYTE*) pMsgBody,
  298. &dwMsgSize,
  299. dwBufferSize ))
  300. {
  301. printf("CryptEncrypt() failed, error- %lxh\n", GetLastError());
  302. return -1;
  303. }
  304. printf("CryptEncrypt() succeeded\n") ;
  305. //
  306. // Update the length of the message according to the result of the
  307. // encryption algorithm. RC4 may enlarge the message size. On the
  308. // destination, the message will be received as clear text with the
  309. // correct (original) message body size.
  310. //
  311. aMsgPropVar[0].caub.cElems = dwMsgSize ;
  312. aMsgPropVar[5].vt = VT_UI4;
  313. if(!fEnhEncrypted)
  314. {
  315. aMsgPropVar[5].ulVal= MQMSG_PRIV_LEVEL_NONE ;
  316. }
  317. else
  318. {
  319. aMsgPropVar[5].ulVal = MQMSG_PRIV_LEVEL_BODY_ENHANCED ;
  320. }
  321. MsgProps.cProp = MSGPROPS ;
  322. //
  323. // Send the mesasge.
  324. //
  325. hr = MQSendMessage(hQueue, &MsgProps, NULL);
  326. if (FAILED(hr))
  327. {
  328. printf("MQSendMessage() failed, hr- %lxh\n", hr) ;
  329. return -1;
  330. }
  331. printf("MQSendMessage() succeeded\n") ;
  332. //
  333. // Free resources. This is actually not required here, it is just
  334. // to show how it should be done, if neccessary.
  335. //
  336. MQCloseQueue(hQueue);
  337. CryptDestroyKey(hSymmKey);
  338. CryptDestroyKey(hPbKey);
  339. CryptReleaseContext(hProv, 0);
  340. return 0;
  341. }