|
|
//depot/Lab03_DEV/Ds/security/cryptoapi/test/capi20/trpfx/rpfx.cpp#2 - edit change 21738 (text)
//--------------------------------------------------------------------
// rpfx - implementation
// Copyright (C) Microsoft Corporation, 2001
//
// Created by: Duncan Bryce (duncanb), 11-11-2001
//
// Core functionality of the rpfx tool
#include "pch.h"
HINSTANCE g_hThisModule = NULL;
//--------------------------------------------------------------------------
void __cdecl SeTransFunc(unsigned int u, EXCEPTION_POINTERS* pExp) { throw SeException(u); }
//--------------------------------------------------------------------------
void PrintHelp() { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_HELP); }
//--------------------------------------------------------------------------
extern "C" LPVOID MIDL_user_allocate(size_t cb) { return LocalAlloc(LPTR, cb); }
//--------------------------------------------------------------------------
extern "C" void MIDL_user_free(LPVOID pvBuffer) { LocalFree(pvBuffer); }
//--------------------------------------------------------------------------
HRESULT ParseServerFile(LPWSTR wszFileName, StringList & vServers) { FILE *pFile = NULL; HRESULT hr; WCHAR *wszCurrent = NULL; WCHAR wszServer[1024];
ZeroMemory(&wszServer, sizeof(wszServer)); pFile = _wfopen(wszFileName, L"r"); if(NULL == pFile) { _JumpLastError(hr, error, "_wfopen"); }
while (1 == fwscanf(pFile, L"%s", wszServer)) { if (L'\0' != *wszServer) { // Not worth bothering to do more than this for a simple command-line tool like this
_MyAssert(wcslen(wszServer) < ARRAYSIZE(wszServer)); wszCurrent = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(wcslen(wszServer)+1)); _JumpIfOutOfMemory(hr, error, wszCurrent); wcscpy(wszCurrent, wszServer);
_SafeStlCall(vServers.push_back(wszCurrent), hr, error, "vServers.push_back(wszServer)"); wszCurrent = NULL; }
fgetwc(pFile); }
hr = S_OK; error: if (NULL != pFile) { fclose(pFile); } if (NULL != wszCurrent) { LocalFree(wszCurrent); } // Caller is responsible for freeing strings in vServers.
return hr; }
//---------------------------------------------------------------------------------
HRESULT RemoteInstall(CmdArgs *pca) { bool bExportable = false; bool bFreeServerList = false; bool bImpersonated = false; DWORD dwResult; HANDLE hToken = NULL; HRESULT hr; KEYSVC_BLOB blobPFX; KEYSVC_UNICODE_STRING strPassword; KEYSVCC_HANDLE hKeySvcCli = NULL; LPSTR szMachineName = NULL; LPWSTR wszDomainName = NULL; // doesn't need to be freed
LPWSTR wszFileName = NULL; // doesn't need to be freed
LPWSTR wszPassword = NULL; // doesn't need to be freed
LPWSTR wszPFXPassword = NULL; // doesn't need to be freed
LPWSTR wszServerName = NULL; // doesn't need to be freed
LPWSTR wszServerFileName = NULL; // doesn't need to be freed
LPWSTR wszUserAndDomain = NULL; // doesn't need to be freed
LPWSTR wszUserName = NULL; // doesn't need to be freed
StringList vServers; ULONG ulPFXImportFlags; unsigned int nArgID;
ZeroMemory(&blobPFX, sizeof(blobPFX)); ZeroMemory(&strPassword, sizeof(strPassword));
// We're doing a remote PFX install. Attempt to parse the information
// we need from the command line. We need:
//
// a) The path to the PFX file to install
//
if (FindArg(pca, L"file", &wszFileName, &nArgID)) { MarkArgUsed(pca, nArgID); } else { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_PARAMETER_MISSING, L"pfxfile"); hr = E_INVALIDARG; _JumpError(hr, error, "RemoteInstall: pfxfile missing"); }
// b) Either a machine name to install the file on, or a file which contains
// a carriage-return delimted list of machines to install the file on
//
if (FindArg(pca, L"server", &wszServerName, &nArgID)) { MarkArgUsed(pca, nArgID); _SafeStlCall(vServers.push_back(wszServerName), hr, error, "vServers.push_back"); wszServerName = NULL; // we'll clean up all strings in vServers
} else { // No remote machine was specified. See if they specified a server file:
if (FindArg(pca, L"serverlist", &wszServerFileName, &nArgID)) { MarkArgUsed(pca, nArgID); bFreeServerList = true; hr = ParseServerFile(wszServerFileName, vServers); _JumpIfError(hr, error, "ParseServerFile"); } else { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_ONEOF_2_PARAMETERS_MISSING, L"server", L"serverfile"); hr = E_INVALIDARG; _JumpError(hr, error, "RemoteInstall: pfx destination missing"); } }
// c) The password to use when importing the pfx file:
//
if (FindArg(pca, L"pfxpwd", &wszPFXPassword, &nArgID)) { MarkArgUsed(pca, nArgID); InitKeysvcUnicodeString(&strPassword, wszPFXPassword); } else { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_PARAMETER_MISSING, L"pfxpassword"); hr = E_INVALIDARG; _JumpError(hr, error, "RemoteInstall: pfxpassword missing"); }
// d) Optionally, flags controlling key creation on the remote machine.
// Only CRYPT_EXPORTABLE may be currently specified
//
if (FindArg(pca, L"exportable", NULL, &nArgID)) { MarkArgUsed(pca, nArgID); bExportable = true; } // e) Optionally, a username & password combination to use when authenticating to the remote machines
//
if (FindArg(pca, L"user", &wszUserAndDomain, &nArgID)) { MarkArgUsed(pca, nArgID);
if (FindArg(pca, L"pwd", &wszPassword, &nArgID)) { MarkArgUsed(pca, nArgID); // Parse the username string to see if we have UPN or NT4 style.
WCHAR *wszSplit = wcschr(wszUserAndDomain, L'\\'); if (NULL != wszSplit) { wszDomainName = wszUserAndDomain; *wszSplit = L'\0'; wszUserName = wszSplit+1; } else { wszUserName = wszUserAndDomain; }
if (!LogonUser(wszUserName, wszDomainName, wszPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &hToken)) { _JumpLastError(hr, error, "LogonUser"); }
if (!ImpersonateLoggedOnUser(hToken)) { _JumpLastError(hr, error, "ImpersonateLoggedOnUser"); } bImpersonated = true;
} else { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_PARAMETER_MISSING, L"password"); hr = E_INVALIDARG; _JumpError(hr, error, "RemoteInstall: password missing"); } }
hr = VerifyAllArgsUsed(pca); _JumpIfError(hr, error, "VerifyAllArgsUsed");
// Calculate the import flags we're going to use based on the command line options:
//
ulPFXImportFlags = CRYPT_MACHINE_KEYSET; if (bExportable) { ulPFXImportFlags |= CRYPT_EXPORTABLE; } for (StringIter wszIter = vServers.begin(); wszIter != vServers.end(); wszIter++) { szMachineName = MBFromWide(*wszIter); if (NULL == szMachineName) { _JumpLastError(hr, error, "MBFromWide"); }
// Attempt to bind to the remote machine:
dwResult = RKeyOpenKeyService(szMachineName, KeySvcMachine, NULL, (void *)0 /*allow insecure connection*/, NULL, &hKeySvcCli); if (ERROR_SUCCESS != dwResult) { hKeySvcCli = NULL; // handle is invalid on error
hr = HRESULT_FROM_WIN32(dwResult); _JumpError(hr, NextServer, "RKeyOpenKeyService"); }
// If we haven't yet, map the PFX file:
if (NULL == blobPFX.pb) { hr = MyMapFile(wszFileName, &blobPFX.pb, &blobPFX.cb); _JumpIfError(hr, error, "MyMapFile"); } // Install the PFX file on the remote machine:
dwResult = RKeyPFXInstall(hKeySvcCli, &blobPFX, &strPassword, ulPFXImportFlags); if (ERROR_SUCCESS != dwResult) { hr = HRESULT_FROM_WIN32(dwResult); _JumpError(hr, NextServer, "RKeyPFXInstall"); }
NextServer: if (FAILED(hr)) { WCHAR * wszError; HRESULT hr2=GetSystemErrorString(hr, &wszError); if (FAILED(hr2)) { _IgnoreError(hr2, "GetSystemErrorString"); } else { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_REMOTE_INSTALL_ERROR, *wszIter, wszError); LocalFree(wszError); } } else { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_REMOTE_INSTALL_SUCCESS, *wszIter); }
if (NULL != hKeySvcCli) { RKeyCloseKeyService(hKeySvcCli, NULL); hKeySvcCli = NULL; } }
hr = S_OK; error: if (NULL != hToken) { CloseHandle(hToken); } if (bImpersonated) { RevertToSelf(); } if (NULL != blobPFX.pb) { MyUnmapFile(blobPFX.pb); } if (NULL != hKeySvcCli) { RKeyCloseKeyService(hKeySvcCli, NULL /*reserved*/); } if (NULL != szMachineName) { LocalFree(szMachineName); } if (bFreeServerList) { for (StringIter wszIter = vServers.begin(); wszIter != vServers.end(); wszIter++) { LocalFree(*wszIter); } } if (FAILED(hr) && E_INVALIDARG!=hr) { WCHAR * wszError; HRESULT hr2=GetSystemErrorString(hr, &wszError); if (FAILED(hr2)) { _IgnoreError(hr2, "GetSystemErrorString"); } else { DisplayMsg(FORMAT_MESSAGE_FROM_HMODULE, IDS_ERROR_GENERAL, wszError); LocalFree(wszError); } } return hr; }
//--------------------------------------------------------------------
extern "C" int WINAPI WinMain (HINSTANCE hinstExe, HINSTANCE hinstExePrev, LPSTR pszCommandLine, int nCommandShow) { g_hThisModule = hinstExe;
HRESULT hr; CmdArgs caArgs; int nArgs = 0; WCHAR **rgwszArgs = NULL;
hr = InitializeConsoleOutput(); _JumpIfError(hr, error, "InitializeConsoleOutput");
rgwszArgs = CommandLineToArgvW(GetCommandLineW(), &nArgs); if (nArgs < 0 || NULL == rgwszArgs) { _JumpError(HRESULT_FROM_WIN32(GetLastError()), error, "GetCommandLineW"); }
// analyze args
caArgs.nArgs=nArgs; caArgs.nNextArg=1; caArgs.rgwszArgs=rgwszArgs;
// check for help command
if (true==CheckNextArg(&caArgs, L"?", NULL) || caArgs.nNextArg==caArgs.nArgs) { PrintHelp();
// Default to the "install" command.
} else { hr = RemoteInstall(&caArgs); _JumpIfError(hr, error, "RemoteInstall"); }
hr=S_OK; error: return hr; }
|