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
340 lines
11 KiB
//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;
|
|
}
|
|
|
|
|
|
|