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.
 
 
 
 
 
 

698 lines
18 KiB

//***********************************************************
// Copyright (C) Microsoft Corporation, 1996 - 1998
//
// metasnap.cpp
//
// Description: Metabase Snapshot utility tool main
//
// History: 15-July-98 Tamas Nemeth (t-tamasn) Created.
//
//***********************************************************
#define INITGUID
#define E_UNKNOWN_ARG 0x10000
#define E_WRONG_NUMBER_ARGS 0x20000
#define E_NULL_PTR 0x30000
#define DEFAULT_MD_TIMEOUT 0x1000
#define DEFAULT_GETALL_BUFFER_SIZE 4096
//#define DBG_ASSERT(exp)
//# define DBG_ASSERT(exp) ((void)0) /* Do Nothing */
//#include "stdafx.h"
//#include "winsock.h"
//#undef dllexp
//#include "tcpdllp.hxx"
//#define _RDNS_STANDALONE
//#include "afx.h"
#include <objbase.h>
#include <coguid.h>
#include <stdio.h>
#include <stdlib.h>
#include <mbstring.h>
#include "iadmw.h"
#include "iiscnfg.h"
#include "uiutils.h"
//#include <pudebug.h>
//extern "C" DEBUG_PRINTS * g_pDebug = NULL;
//#undef dllexp
//#include "tcpdllp.hxx"
//#define _RDNS_STANDALONE
enum ERROR_PARAMETER
{
MACHINE_NAME,
START_KEY_NAME,
};
struct _CMD_PARAMS
{
LPWSTR szMachineName;
LPWSTR szStartKey;
BOOL bShowSecure; //
DWORD dwErrParameter; // to determine which parameter is incorrect
};
typedef struct _CMD_PARAMS CMD_PARAMS;
//typedef CString* pCString;
// Global variables:
//DWORD* dwSortArray;
PBYTE pbGetAllBuffer;
// Function prototypes:
HRESULT PrintKeyRecursively(IMSAdminBase *pcAdmCom, WCHAR *lpwstrFullPath, CMD_PARAMS* pcpCommandStructure);
HRESULT PrintAllPropertiesAtKey (IMSAdminBase *pcAdmCom, METADATA_HANDLE hmdHandle,
CMD_PARAMS* pcpCommandStructure);
VOID PrintProperty(METADATA_GETALL_RECORD & mdr, BOOL bShowSecure);
VOID PrintDataTypeAndValue(METADATA_GETALL_RECORD *pmdgr, BOOL bShowSecure);
DWORD ParseCommands (int argc, char *argv[], CMD_PARAMS *pcpCommandStructure);
VOID DisplayHelp();
// new stuff
DWORD
AddAccessEntries(
IN ADDRESS_CHECK & ac,
IN BOOL fName,
IN BOOL fGrant,
//OUT CObListPlus & oblAccessList,
OUT DWORD & cEntries
)
/*++
Routine Description:
Add specific kind of addresses from the list to the oblist of
access entries
Arguments:
ADDRESS_CHECK & ac : Address list input object
BOOL fName : TRUE for names, FALSE for ip
BOOL fGrant : TRUE for granted, FALSE for denied
CObListPlus & oblAccessList : ObList to add access entries to
int & cEntries : Returns the number of entries
Return Value:
Error code
Notes:
Sentinel entries (ip 0.0.0.0) are not added to the oblist, but
are reflected in the cEntries return value
--*/
{
DWORD i;
DWORD dwFlags;
if (fName)
{
//
// Domain names
//
LPSTR lpName;
cEntries = ac.GetNbName(fGrant);
//printf("Number of names: %ld.\n",cEntries);
for (i = 0L; i < cEntries; ++i)
{
if (ac.GetName(fGrant, i, &lpName, &dwFlags))
{
if (fGrant)
printf("\tGranted to %s.\n",lpName);
else
printf("\tDenied to %s.\n",lpName);
/*CString strDomain(lpName);
if (!(dwFlags & DNSLIST_FLAG_NOSUBDOMAIN))
{
strDomain = _T("*.") + strDomain;
}*/
//oblAccessList.AddTail(new CIPAccessDescriptor(fGrant, strDomain));
}
}
}
else
{
//
// IP Addresses
//
LPBYTE lpMask;
LPBYTE lpAddr;
cEntries = ac.GetNbAddr(fGrant);
//printf("Number of addresses: %ld.\n",cEntries);
for (i = 0L; i < cEntries; ++i)
{
if (ac.GetAddr(fGrant, i, &dwFlags, &lpMask, &lpAddr))
{
if (lpAddr[0] != 0 || lpAddr[1] != 0 || lpAddr[2] !=0 || lpAddr[3] !=0)
{
if (lpAddr[0] != 0 || lpAddr[1] != 0 || lpAddr[2] !=0 || lpAddr[3] !=0)
if (fGrant)
printf("\tGranted to %d",lpAddr[0]);
else
printf("\tDenied to %d",lpAddr[0]);
for (int j = 1; j<4; j++)
printf(".%d",lpAddr[j]);
if (lpMask[0] != 255 || lpMask[1] != 255 || lpMask[2] !=255 || lpMask[3] !=255)
{
printf(" (Mask: %d",lpMask[0]);
for (int j = 1; j<4; j++)
printf(".%d",lpMask[j]);
printf(")");
}
printf(".\n");
}
else
printf("\tDenied to everyone.\n");
}
}
}
return ERROR_SUCCESS;
}
DWORD
BuildIplOblistFromBlob(
IN METADATA_GETALL_RECORD & mdgr
//OUT CObListPlus & oblAccessList,
// OUT BOOL & fGrantByDefault
)
{
//oblAccessList.RemoveAll();
if (mdgr.dwMDDataLen == 0)
{
return ERROR_SUCCESS;
}
ADDRESS_CHECK ac;
ac.BindCheckList(mdgr.pbMDData, mdgr.dwMDDataLen);
DWORD cGrantAddr, cGrantName, cDenyAddr, cDenyName;
// Name/IP Granted/Deny
// ============================================================
AddAccessEntries(ac, TRUE, TRUE, cGrantName);
AddAccessEntries(ac, FALSE, TRUE, cGrantAddr);
AddAccessEntries(ac, TRUE, FALSE, cDenyName);
AddAccessEntries(ac, FALSE, FALSE, cDenyAddr);
ac.UnbindCheckList();
// fGrantByDefault = (cDenyAddr + cDenyName != 0L)
// || (cGrantAddr + cGrantName == 0L);
return ERROR_SUCCESS;
}
// end new
VOID __cdecl main (int argc, char *argv[])
{
if (argc == 1)
{
DisplayHelp();
return;
}
CMD_PARAMS pcpCommands;
DWORD dwRetVal = ParseCommands (argc, argv, &pcpCommands);
if (dwRetVal != ERROR_SUCCESS)
{
if (dwRetVal == E_OUTOFMEMORY)
fprintf (stderr, "ERROR: Out of memory.");
else if (dwRetVal == E_WRONG_NUMBER_ARGS)
fprintf (stderr, "ERROR: Invalid number of arguments.");
else if (dwRetVal == E_INVALIDARG)
{
fprintf (stderr, "ERROR: Invalid input value");
switch (pcpCommands.dwErrParameter)
{
case (MACHINE_NAME):
fputs (" for MachineName.", stderr);
break;
case (START_KEY_NAME):
fputs (" for StartKey.", stderr);
break;
default:
fputs (".", stderr);
break;
}
}
else
fprintf (stderr, "ERROR: Unknown error in processing arguments.");
fputs(" Enter \"metasnap\" without arguments to display help.\n", stderr);
return;
}
IMSAdminBase *pcAdmCom = NULL; //interface pointer
IClassFactory * pcsfFactory = NULL;
COSERVERINFO csiMachineName;
COSERVERINFO *pcsiParam = NULL;
// Fill the structure for CoGetClassObject:
csiMachineName.pAuthInfo = NULL;
csiMachineName.dwReserved1 = 0;
csiMachineName.dwReserved2 = 0;
pcsiParam = &csiMachineName;
csiMachineName.pwszName = pcpCommands.szMachineName;
// Initialize COM:
HRESULT hresError = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hresError))
{
fprintf (stderr, "ERROR: COM Initialization failed. Error: %d (%#x)\n", hresError, hresError);
return;
}
hresError = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, pcsiParam,
IID_IClassFactory, (void**) &pcsfFactory);
if (FAILED(hresError))
{
switch (hresError)
{
case HRESULT_FROM_WIN32(REGDB_E_CLASSNOTREG):
fprintf(stderr, "ERROR: IIS Metabase does not exist.\n");
break;
case HRESULT_FROM_WIN32(E_ACCESSDENIED):
fprintf(stderr, "ERROR: Access to Metabase denied.\n");
break;
case HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE):
fprintf(stderr, "ERROR: The specified host is unavailable.\n");
break;
default:
fprintf (stderr, "ERROR: Couldn't get Metabase Object. Error: %d (%#x)\n", hresError, hresError);
break;
}
return;
}
hresError = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &pcAdmCom);
if (FAILED(hresError))
{
switch (hresError)
{
case HRESULT_FROM_WIN32(RPC_S_SEC_PKG_ERROR):
fprintf (stderr, "ERROR: A security-related error occurred.\n");
break;
case HRESULT_FROM_WIN32(E_OUTOFMEMORY):
fprintf (stderr, "ERROR: There is not enough memory available.\n");
break;
default:
fprintf (stderr, "ERROR: Couldn't create Metabase Instance. Error: %d (%#x)\n", hresError, hresError);
break;
}
pcsfFactory->Release();
return;
}
pcsfFactory->Release();
METADATA_HANDLE hmdHandle;
hresError = pcAdmCom->OpenKey (
METADATA_MASTER_ROOT_HANDLE,
pcpCommands.szStartKey,
METADATA_PERMISSION_READ,
DEFAULT_MD_TIMEOUT,
&hmdHandle);
if (FAILED(hresError))
{
switch (hresError)
{
case HRESULT_FROM_WIN32(ERROR_PATH_BUSY):
fprintf (stderr, "ERROR: The specified key is already in use.\n");
break;
case HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND):
fprintf (stderr, "ERROR: The specified key is not found.\n");
break;
default:
fprintf (stderr, "ERROR: Couldn't open Metabase Key. Error: %d (%#x)\n", hresError, hresError);
break;
}
pcAdmCom->Release();
return;
}
// Recurse and dump children
printf("\nIP address and domain name access restrictions:\n");
hresError = PrintKeyRecursively(pcAdmCom, pcpCommands.szStartKey, &pcpCommands);
if (hresError != ERROR_SUCCESS)
{
switch (hresError)
{
case HRESULT_FROM_WIN32(ERROR_PATH_BUSY):
fprintf (stderr, "ERROR: Could not open a key because it is already in use.\n");
break;
case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
fprintf (stderr, "ERROR: There is not enough memory available.\n");
break;
default:
fprintf (stderr, "ERROR: Failed dumping metabase. Error: %u (%#x)\n", hresError, hresError);
break;
}
}
pcAdmCom->CloseKey (hmdHandle);
pcAdmCom->Release();
if (hresError == ERROR_SUCCESS)
fputs("Successfully printed IP Security information.\n", stderr);
}
DWORD ParseCommands (int argc, char *argv [], CMD_PARAMS *pcpCommandStructure)
{
if (pcpCommandStructure == NULL)
return E_NULL_PTR;
if ( argc > 3 )
return E_WRONG_NUMBER_ARGS;
// Set default values:
pcpCommandStructure->szMachineName = (LPWSTR) HeapAlloc (GetProcessHeap(),
HEAP_ZERO_MEMORY, (9 + 1) * sizeof (WCHAR) );
if (pcpCommandStructure->szMachineName == NULL)
return E_OUTOFMEMORY;
wcscpy(pcpCommandStructure->szMachineName,L"localhost");
pcpCommandStructure->bShowSecure = FALSE;
// Handle StartKey:
DWORD dwStartKeyLen = _mbstrlen(argv[1]) + 3;
pcpCommandStructure->szStartKey = (LPWSTR) HeapAlloc (GetProcessHeap(),
HEAP_ZERO_MEMORY, (dwStartKeyLen + 1) * sizeof (WCHAR));
LPWSTR lpwstrTemp = (LPWSTR) HeapAlloc (GetProcessHeap(),
HEAP_ZERO_MEMORY, (dwStartKeyLen + 1) * sizeof (WCHAR));
// _mbscpy(lpwstrTemp,"/LM");
// wcscat(lpwstrTemp, argv[1]);
// printf("%S\n",lpwstrTemp);
// wcscpy(pcpCommands.szStartKey, lpwstrTemp);
if (pcpCommandStructure->szStartKey == NULL)
return E_OUTOFMEMORY;
DWORD dwResult = MultiByteToWideChar(
CP_ACP,
0,
argv[1],
dwStartKeyLen + 1,
pcpCommandStructure->szStartKey,
dwStartKeyLen + 1);
if (dwResult == 0)
{
pcpCommandStructure->dwErrParameter = START_KEY_NAME;
return E_INVALIDARG;
}
// Add /lm to StartKey:
wcscpy(lpwstrTemp,L"/LM");
wcscat(lpwstrTemp, pcpCommandStructure->szStartKey);
wcscpy(pcpCommandStructure->szStartKey, lpwstrTemp);
// Chop off trailing slashes:
LPWSTR lpwchTemp = pcpCommandStructure->szStartKey;
for (DWORD i=0; i < dwStartKeyLen-1; i++)
lpwchTemp++;
if (!wcscmp(lpwchTemp, TEXT("/") ) || !wcscmp(lpwchTemp, TEXT("\\")) )
*(lpwchTemp) = (WCHAR)'\0';
// Look for MachineName:
if ( argc > 2 && strcmp("-s",argv[2]))
{
DWORD dwMachineNameLen = _mbstrlen(argv[2]);
pcpCommandStructure->szMachineName = (LPWSTR) HeapAlloc (GetProcessHeap(),
HEAP_ZERO_MEMORY, (dwMachineNameLen + 1) * sizeof (WCHAR) );
if (pcpCommandStructure->szMachineName == NULL)
return E_OUTOFMEMORY;
dwResult = MultiByteToWideChar(
CP_ACP,
0,
argv[2],
dwMachineNameLen + 1,
pcpCommandStructure->szMachineName,
dwMachineNameLen + 1);
if (dwResult == 0)
{
pcpCommandStructure->dwErrParameter = MACHINE_NAME;
return E_INVALIDARG;
}
// Check for "-s" flag:
if (argc == 4)
{
if ( !strcmp("-s",argv[3]) )
pcpCommandStructure->bShowSecure = TRUE;
else
return E_INVALIDARG;
}
}
else if (argc == 3 && !strcmp("-s",argv[2]))
pcpCommandStructure->bShowSecure = TRUE;
else if (argc > 2)
return E_INVALIDARG;
return ERROR_SUCCESS;
}
HRESULT PrintKeyRecursively(IMSAdminBase *pcAdmCom, WCHAR *lpwstrFullPath, CMD_PARAMS* pcpCommandStructure)
{
METADATA_HANDLE hmdHandle;
HRESULT hresError = pcAdmCom->OpenKey(
METADATA_MASTER_ROOT_HANDLE,
lpwstrFullPath,
METADATA_PERMISSION_READ,
DEFAULT_MD_TIMEOUT,
&hmdHandle);
if (hresError != ERROR_SUCCESS)
return hresError;
// Get all data into a buffer:
DWORD dwNumDataEntries ;
DWORD dwDataSetNumber;
DWORD dwRequestBufferSize = DEFAULT_GETALL_BUFFER_SIZE;
DWORD dwRequiredDataLen;
// Allocate a default buffer size
pbGetAllBuffer = (PBYTE)HeapAlloc
(GetProcessHeap(),
HEAP_ZERO_MEMORY,
DEFAULT_GETALL_BUFFER_SIZE);
if (pbGetAllBuffer == NULL)
return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
hresError = pcAdmCom -> GetAllData (
hmdHandle,
TEXT ("/"),
0,
0,
0,
&dwNumDataEntries,
&dwDataSetNumber,
dwRequestBufferSize,
pbGetAllBuffer,
&dwRequiredDataLen);
if (hresError == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
{
// retry the GetAllData with the new buffer size
dwRequestBufferSize = dwRequiredDataLen;
pbGetAllBuffer = (PBYTE)HeapReAlloc
(GetProcessHeap(),
0,
pbGetAllBuffer,
dwRequestBufferSize);
if (!pbGetAllBuffer)
return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
hresError = pcAdmCom -> GetAllData (
hmdHandle,
TEXT ("/"),
0,
0,
0,
&dwNumDataEntries,
&dwDataSetNumber,
dwRequestBufferSize,
pbGetAllBuffer,
&dwRequiredDataLen);
}
if (hresError != ERROR_SUCCESS)
{
HeapFree (GetProcessHeap(), 0, pbGetAllBuffer);
return hresError;
}
METADATA_GETALL_RECORD *pmdgr = NULL;
for (DWORD dwIndex = 0; dwIndex < dwNumDataEntries; dwIndex ++)
{
pmdgr = &(((METADATA_GETALL_RECORD *) pbGetAllBuffer)[dwIndex]);
pmdgr->pbMDData = pmdgr->dwMDDataOffset + pbGetAllBuffer;
if (pmdgr->dwMDIdentifier == 6019 && pmdgr->dwMDDataType == BINARY_METADATA &&
pmdgr->dwMDDataLen > 0)
{
printf(" [%S]\n",lpwstrFullPath);
// PrintProperty(*pmdgr, pcpCommandStructure->bShowSecure);
BuildIplOblistFromBlob( *pmdgr);
}
}
WCHAR *lpwstrTempPath = (WCHAR*) HeapAlloc
(GetProcessHeap(),
HEAP_ZERO_MEMORY,
METADATA_MAX_NAME_LEN * sizeof (WCHAR));
if (lpwstrTempPath == NULL)
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
// Find out number of the children:
DWORD dwChildCount = 0;
while (1)
{
hresError = pcAdmCom->EnumKeys (
hmdHandle,
TEXT("/"),
lpwstrTempPath,
dwChildCount);
if (hresError != ERROR_SUCCESS)
break;
dwChildCount++;
}
if (dwChildCount == 0)
return ERROR_SUCCESS;
// Dynamically allocate arrays:
LPWSTR * lpwstrChildPath = new LPWSTR[dwChildCount];
DWORD * dwSortedIndex = new DWORD[dwChildCount];
// Initialization:
for (dwIndex = 0; dwIndex < dwChildCount; dwIndex++)
{
dwSortedIndex[dwIndex] = dwIndex;
hresError = pcAdmCom->EnumKeys (
hmdHandle,
TEXT("/"),
lpwstrTempPath,
dwIndex);
lpwstrChildPath[dwIndex] = (WCHAR*) HeapAlloc
(GetProcessHeap(),
HEAP_ZERO_MEMORY,
(wcslen (lpwstrTempPath) + 1) * sizeof (WCHAR));
if (lpwstrChildPath[dwIndex] == NULL)
{
hresError = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
break;
}
else
wcscpy(lpwstrChildPath[dwIndex], lpwstrTempPath);
}
if (hresError == ERROR_SUCCESS)
{
// Sort children lexicographically (here we assume that dwChildCount is small)
if (dwChildCount > 1 )
{
DWORD dwTemp;
for (DWORD i = 1; i < dwChildCount; i++)
for (DWORD j=0; j < dwChildCount-i; j++)
{
if (wcscmp(lpwstrChildPath[dwSortedIndex[j]],lpwstrChildPath[dwSortedIndex[j+1]]) > 0)
{
dwTemp = dwSortedIndex[j+1];
dwSortedIndex[j+1] = dwSortedIndex[j];
dwSortedIndex[j] = dwTemp;
}
}
}
for (dwIndex = 0; dwIndex < dwChildCount; dwIndex++)
{
// create the full path name for the child:
wsprintf(lpwstrTempPath,TEXT("%s/%s"),lpwstrFullPath,lpwstrChildPath[dwSortedIndex[dwIndex]]);
HeapFree (GetProcessHeap(), 0, lpwstrChildPath[dwSortedIndex[dwIndex]]);
hresError = PrintKeyRecursively (pcAdmCom, lpwstrTempPath, pcpCommandStructure);
if (hresError != ERROR_SUCCESS)
break;
}
}
// Close keys, free memory and exit
pcAdmCom->CloseKey(hmdHandle);
delete lpwstrChildPath;
delete dwSortedIndex;
HeapFree (GetProcessHeap(), 0, lpwstrTempPath);
return hresError;
}
VOID DisplayHelp()
{
fprintf (stderr, "\n DESCRIPTION: Displays the IP address/domain name restictions.\n\n");
fprintf (stderr, " FORMAT: ipperm <StartKey> <MachineName>\n\n");
fprintf (stderr, " <StartKey> : metabase key to start at.\n");
fprintf (stderr, " <MachineName>: name of host (optional, default: localhost).\n\n");
fprintf (stderr, " EXAMPLES: ipperm /w3svc/1 t-tamasn2\n");
fprintf (stderr, " ipperm / > dump.txt (dump all to text)\n\n");
}