Leaked source code of windows server 2003
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.

340 lines
11 KiB

  1. //depot/Lab03_DEV/Ds/security/cryptoapi/test/capi20/trpfx/rpfx.cpp#2 - edit change 21738 (text)
  2. //--------------------------------------------------------------------
  3. // rpfx - implementation
  4. // Copyright (C) Microsoft Corporation, 2001
  5. //
  6. // Created by: Duncan Bryce (duncanb), 11-11-2001
  7. //
  8. // Core functionality of the rpfx tool
  9. #include "pch.h"
  10. HINSTANCE g_hThisModule = NULL;
  11. //--------------------------------------------------------------------------
  12. void __cdecl SeTransFunc(unsigned int u, EXCEPTION_POINTERS* pExp) {
  13. throw SeException(u);
  14. }
  15. //--------------------------------------------------------------------------
  16. void PrintHelp() {
  17. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_HELP);
  18. }
  19. //--------------------------------------------------------------------------
  20. extern "C" LPVOID MIDL_user_allocate(size_t cb) {
  21. return LocalAlloc(LPTR, cb);
  22. }
  23. //--------------------------------------------------------------------------
  24. extern "C" void MIDL_user_free(LPVOID pvBuffer) {
  25. LocalFree(pvBuffer);
  26. }
  27. //--------------------------------------------------------------------------
  28. HRESULT ParseServerFile(LPWSTR wszFileName, StringList & vServers) {
  29. FILE *pFile = NULL;
  30. HRESULT hr;
  31. WCHAR *wszCurrent = NULL;
  32. WCHAR wszServer[1024];
  33. ZeroMemory(&wszServer, sizeof(wszServer));
  34. pFile = _wfopen(wszFileName, L"r");
  35. if(NULL == pFile) {
  36. _JumpLastError(hr, error, "_wfopen");
  37. }
  38. while (1 == fwscanf(pFile, L"%s", wszServer)) {
  39. if (L'\0' != *wszServer) {
  40. // Not worth bothering to do more than this for a simple command-line tool like this
  41. _MyAssert(wcslen(wszServer) < ARRAYSIZE(wszServer));
  42. wszCurrent = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(wcslen(wszServer)+1));
  43. _JumpIfOutOfMemory(hr, error, wszCurrent);
  44. wcscpy(wszCurrent, wszServer);
  45. _SafeStlCall(vServers.push_back(wszCurrent), hr, error, "vServers.push_back(wszServer)");
  46. wszCurrent = NULL;
  47. }
  48. fgetwc(pFile);
  49. }
  50. hr = S_OK;
  51. error:
  52. if (NULL != pFile) {
  53. fclose(pFile);
  54. }
  55. if (NULL != wszCurrent) {
  56. LocalFree(wszCurrent);
  57. }
  58. // Caller is responsible for freeing strings in vServers.
  59. return hr;
  60. }
  61. //---------------------------------------------------------------------------------
  62. HRESULT RemoteInstall(CmdArgs *pca) {
  63. bool bExportable = false;
  64. bool bFreeServerList = false;
  65. bool bImpersonated = false;
  66. DWORD dwResult;
  67. HANDLE hToken = NULL;
  68. HRESULT hr;
  69. KEYSVC_BLOB blobPFX;
  70. KEYSVC_UNICODE_STRING strPassword;
  71. KEYSVCC_HANDLE hKeySvcCli = NULL;
  72. LPSTR szMachineName = NULL;
  73. LPWSTR wszDomainName = NULL; // doesn't need to be freed
  74. LPWSTR wszFileName = NULL; // doesn't need to be freed
  75. LPWSTR wszPassword = NULL; // doesn't need to be freed
  76. LPWSTR wszPFXPassword = NULL; // doesn't need to be freed
  77. LPWSTR wszServerName = NULL; // doesn't need to be freed
  78. LPWSTR wszServerFileName = NULL; // doesn't need to be freed
  79. LPWSTR wszUserAndDomain = NULL; // doesn't need to be freed
  80. LPWSTR wszUserName = NULL; // doesn't need to be freed
  81. StringList vServers;
  82. ULONG ulPFXImportFlags;
  83. unsigned int nArgID;
  84. ZeroMemory(&blobPFX, sizeof(blobPFX));
  85. ZeroMemory(&strPassword, sizeof(strPassword));
  86. // We're doing a remote PFX install. Attempt to parse the information
  87. // we need from the command line. We need:
  88. //
  89. // a) The path to the PFX file to install
  90. //
  91. if (FindArg(pca, L"file", &wszFileName, &nArgID)) {
  92. MarkArgUsed(pca, nArgID);
  93. } else {
  94. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_PARAMETER_MISSING, L"pfxfile");
  95. hr = E_INVALIDARG;
  96. _JumpError(hr, error, "RemoteInstall: pfxfile missing");
  97. }
  98. // b) Either a machine name to install the file on, or a file which contains
  99. // a carriage-return delimted list of machines to install the file on
  100. //
  101. if (FindArg(pca, L"server", &wszServerName, &nArgID)) {
  102. MarkArgUsed(pca, nArgID);
  103. _SafeStlCall(vServers.push_back(wszServerName), hr, error, "vServers.push_back");
  104. wszServerName = NULL; // we'll clean up all strings in vServers
  105. } else {
  106. // No remote machine was specified. See if they specified a server file:
  107. if (FindArg(pca, L"serverlist", &wszServerFileName, &nArgID)) {
  108. MarkArgUsed(pca, nArgID);
  109. bFreeServerList = true;
  110. hr = ParseServerFile(wszServerFileName, vServers);
  111. _JumpIfError(hr, error, "ParseServerFile");
  112. } else {
  113. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_ONEOF_2_PARAMETERS_MISSING, L"server", L"serverfile");
  114. hr = E_INVALIDARG;
  115. _JumpError(hr, error, "RemoteInstall: pfx destination missing");
  116. }
  117. }
  118. // c) The password to use when importing the pfx file:
  119. //
  120. if (FindArg(pca, L"pfxpwd", &wszPFXPassword, &nArgID)) {
  121. MarkArgUsed(pca, nArgID);
  122. InitKeysvcUnicodeString(&strPassword, wszPFXPassword);
  123. } else {
  124. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_PARAMETER_MISSING, L"pfxpassword");
  125. hr = E_INVALIDARG;
  126. _JumpError(hr, error, "RemoteInstall: pfxpassword missing");
  127. }
  128. // d) Optionally, flags controlling key creation on the remote machine.
  129. // Only CRYPT_EXPORTABLE may be currently specified
  130. //
  131. if (FindArg(pca, L"exportable", NULL, &nArgID)) {
  132. MarkArgUsed(pca, nArgID);
  133. bExportable = true;
  134. }
  135. // e) Optionally, a username & password combination to use when authenticating to the remote machines
  136. //
  137. if (FindArg(pca, L"user", &wszUserAndDomain, &nArgID)) {
  138. MarkArgUsed(pca, nArgID);
  139. if (FindArg(pca, L"pwd", &wszPassword, &nArgID)) {
  140. MarkArgUsed(pca, nArgID);
  141. // Parse the username string to see if we have UPN or NT4 style.
  142. WCHAR *wszSplit = wcschr(wszUserAndDomain, L'\\');
  143. if (NULL != wszSplit) {
  144. wszDomainName = wszUserAndDomain;
  145. *wszSplit = L'\0';
  146. wszUserName = wszSplit+1;
  147. } else {
  148. wszUserName = wszUserAndDomain;
  149. }
  150. if (!LogonUser(wszUserName, wszDomainName, wszPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &hToken)) {
  151. _JumpLastError(hr, error, "LogonUser");
  152. }
  153. if (!ImpersonateLoggedOnUser(hToken)) {
  154. _JumpLastError(hr, error, "ImpersonateLoggedOnUser");
  155. }
  156. bImpersonated = true;
  157. } else {
  158. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_PARAMETER_MISSING, L"password");
  159. hr = E_INVALIDARG;
  160. _JumpError(hr, error, "RemoteInstall: password missing");
  161. }
  162. }
  163. hr = VerifyAllArgsUsed(pca);
  164. _JumpIfError(hr, error, "VerifyAllArgsUsed");
  165. // Calculate the import flags we're going to use based on the command line options:
  166. //
  167. ulPFXImportFlags = CRYPT_MACHINE_KEYSET;
  168. if (bExportable) {
  169. ulPFXImportFlags |= CRYPT_EXPORTABLE;
  170. }
  171. for (StringIter wszIter = vServers.begin(); wszIter != vServers.end(); wszIter++) {
  172. szMachineName = MBFromWide(*wszIter);
  173. if (NULL == szMachineName) {
  174. _JumpLastError(hr, error, "MBFromWide");
  175. }
  176. // Attempt to bind to the remote machine:
  177. dwResult = RKeyOpenKeyService(szMachineName, KeySvcMachine, NULL, (void *)0 /*allow insecure connection*/, NULL, &hKeySvcCli);
  178. if (ERROR_SUCCESS != dwResult) {
  179. hKeySvcCli = NULL; // handle is invalid on error
  180. hr = HRESULT_FROM_WIN32(dwResult);
  181. _JumpError(hr, NextServer, "RKeyOpenKeyService");
  182. }
  183. // If we haven't yet, map the PFX file:
  184. if (NULL == blobPFX.pb) {
  185. hr = MyMapFile(wszFileName, &blobPFX.pb, &blobPFX.cb);
  186. _JumpIfError(hr, error, "MyMapFile");
  187. }
  188. // Install the PFX file on the remote machine:
  189. dwResult = RKeyPFXInstall(hKeySvcCli, &blobPFX, &strPassword, ulPFXImportFlags);
  190. if (ERROR_SUCCESS != dwResult) {
  191. hr = HRESULT_FROM_WIN32(dwResult);
  192. _JumpError(hr, NextServer, "RKeyPFXInstall");
  193. }
  194. NextServer:
  195. if (FAILED(hr)) {
  196. WCHAR * wszError;
  197. HRESULT hr2=GetSystemErrorString(hr, &wszError);
  198. if (FAILED(hr2)) {
  199. _IgnoreError(hr2, "GetSystemErrorString");
  200. } else {
  201. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_REMOTE_INSTALL_ERROR, *wszIter, wszError);
  202. LocalFree(wszError);
  203. }
  204. } else {
  205. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_REMOTE_INSTALL_SUCCESS, *wszIter);
  206. }
  207. if (NULL != hKeySvcCli) {
  208. RKeyCloseKeyService(hKeySvcCli, NULL);
  209. hKeySvcCli = NULL;
  210. }
  211. }
  212. hr = S_OK;
  213. error:
  214. if (NULL != hToken) {
  215. CloseHandle(hToken);
  216. }
  217. if (bImpersonated) {
  218. RevertToSelf();
  219. }
  220. if (NULL != blobPFX.pb) {
  221. MyUnmapFile(blobPFX.pb);
  222. }
  223. if (NULL != hKeySvcCli) {
  224. RKeyCloseKeyService(hKeySvcCli, NULL /*reserved*/);
  225. }
  226. if (NULL != szMachineName) {
  227. LocalFree(szMachineName);
  228. }
  229. if (bFreeServerList) {
  230. for (StringIter wszIter = vServers.begin(); wszIter != vServers.end(); wszIter++) {
  231. LocalFree(*wszIter);
  232. }
  233. }
  234. if (FAILED(hr) && E_INVALIDARG!=hr) {
  235. WCHAR * wszError;
  236. HRESULT hr2=GetSystemErrorString(hr, &wszError);
  237. if (FAILED(hr2)) {
  238. _IgnoreError(hr2, "GetSystemErrorString");
  239. } else {
  240. DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_GENERAL, wszError);
  241. LocalFree(wszError);
  242. }
  243. }
  244. return hr;
  245. }
  246. //--------------------------------------------------------------------
  247. extern "C" int WINAPI WinMain
  248. (HINSTANCE hinstExe,
  249. HINSTANCE hinstExePrev,
  250. LPSTR pszCommandLine,
  251. int nCommandShow)
  252. {
  253. g_hThisModule = hinstExe;
  254. HRESULT hr;
  255. CmdArgs caArgs;
  256. int nArgs = 0;
  257. WCHAR **rgwszArgs = NULL;
  258. hr = InitializeConsoleOutput();
  259. _JumpIfError(hr, error, "InitializeConsoleOutput");
  260. rgwszArgs = CommandLineToArgvW(GetCommandLineW(), &nArgs);
  261. if (nArgs < 0 || NULL == rgwszArgs) {
  262. _JumpError(HRESULT_FROM_WIN32(GetLastError()), error, "GetCommandLineW");
  263. }
  264. // analyze args
  265. caArgs.nArgs=nArgs;
  266. caArgs.nNextArg=1;
  267. caArgs.rgwszArgs=rgwszArgs;
  268. // check for help command
  269. if (true==CheckNextArg(&caArgs, L"?", NULL) || caArgs.nNextArg==caArgs.nArgs) {
  270. PrintHelp();
  271. // Default to the "install" command.
  272. } else {
  273. hr = RemoteInstall(&caArgs);
  274. _JumpIfError(hr, error, "RemoteInstall");
  275. }
  276. hr=S_OK;
  277. error:
  278. return hr;
  279. }