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

//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;
}