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.
 
 
 
 
 
 

1509 lines
40 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: rpccfg.cxx
//
//--------------------------------------------------------------------------
#include<nt.h>
#include<ntrtl.h>
#include<nturtl.h>
#include<stdio.h>
#include<string.h>
#include<memory.h>
#include<malloc.h>
#include<stdlib.h>
#include <windows.h>
#include <winsock2.h>
extern "C" {
#include <iphlpapi.h>
};
#include <selbinding.hxx>
#define IF_INFO_DESC_LENGTH 256
#define MAX_REG_BUFFER 1024
#define MAX_SUBNETS 256;
#define RPC_PORT_SETTINGS "Software\\Microsoft\\Rpc\\Internet"
typedef struct _IF_INFO
{
struct _IF_INFO *Next;
DWORD dwIndex;
CHAR szDesc[IF_INFO_DESC_LENGTH];
}IF_INFO,*PIF_INFO;
typedef struct _SUBNET_INFO
{
struct _SUBNET_INFO* Next;
DWORD dwSubnet;
DWORD dwIfCount;
PIF_INFO pIfList;
}SUBNET_INFO,*PSUBNET_INFO;
#define FREE(x) if(x!=NULL){free(x);x=NULL;}
VOID
DoHttpCommandA(
IN CHAR Command,
IN LPSTR Arguments[],
IN ULONG ArgCount
);
void
FreeSubnetList(
IN OUT PSUBNET_INFO *ppSubnetList
)
/*++
Routine Description:
Walks the linked list of adapters (and also each linked list of interfaces
within each adapter) and frees the memory. The input pointer is set too NULL
on return.
Arguments:
ppSubnetList - Pointer to the head pointer of the list which is to be deleted.
This will be set to NULL when the function returns.
Return Value:
--*/
{
if(*ppSubnetList==NULL)
{
return;
}
PSUBNET_INFO pCurr,pNext;
for(pCurr=*ppSubnetList; pCurr!=NULL; pCurr=pNext)
{
pNext=pCurr->Next;
PIF_INFO pIfCurr,pIfNext;
for(pIfCurr=pCurr->pIfList; pIfCurr!=NULL; pIfCurr=pIfNext)
{
pIfNext = pIfCurr->Next;
free(pIfCurr);
}
free(pCurr);
}
ppSubnetList = NULL;
}
BOOL
GetSubnetList(
OUT PSUBNET_INFO *ppSubnetList,
OUT PULONG pSubnetCount
)
/*++
Routine Description:
Creates a linked list of subnets for every individual subnet on the
machine. Each subnet contains a linked list of interfaces, one for each
interface listening on that subnet. The subnet count is also filled in.
Arguments:
ppSubnetList - This is filled in with a pointer to the head of the subnet
linked list.
pSubnetCount - The number of subnets, which means the number of nodes. Note that
the number of Interfaces does not necissarily equal the number of subnets.
Return Value:
--*/
{
// Get the IP Address table
PMIB_IPADDRTABLE pMib;
MIB_IFROW IfRow;
DWORD Size = 20*sizeof(MIB_IPADDRROW)+sizeof(DWORD);
unsigned int i;
DWORD Status,dwSubnet;
PSUBNET_INFO pTmpSubnetInfo;
PIF_INFO pTmpIfInfo;
for (i = 0; i < 2; i++)
{
pMib = (PMIB_IPADDRTABLE) malloc(Size);
if (pMib == 0)
{
goto cleanup;
}
memset(pMib, 0, Size);
Status = GetIpAddrTable(pMib, &Size, TRUE);
if (Status == 0)
{
break;
}
free(pMib);
}
*ppSubnetList = NULL;
*pSubnetCount = 0;
// Create the subnets, link them together
for(i=0; i < pMib->dwNumEntries; i++)
{
(*pSubnetCount)++;
//Allocate a new subnet, or link to the previous one
if(*ppSubnetList==NULL)
{
*ppSubnetList = (PSUBNET_INFO) malloc(sizeof(SUBNET_INFO));
pTmpSubnetInfo = *ppSubnetList;
if(!pTmpSubnetInfo)
{
goto cleanup;
}
}
else
{
pTmpSubnetInfo->Next = (PSUBNET_INFO) malloc(sizeof(SUBNET_INFO));
if(!pTmpSubnetInfo)
{
goto cleanup;
}
pTmpSubnetInfo = pTmpSubnetInfo->Next;
}
//Fill in the subnet
memset(pTmpSubnetInfo,0,sizeof(SUBNET_INFO));
pTmpSubnetInfo->dwSubnet = pMib->table[i].dwAddr & pMib->table[i].dwMask;
pTmpSubnetInfo->dwIfCount = 1;
pTmpSubnetInfo->pIfList = (PIF_INFO)malloc(sizeof(IF_INFO));
pTmpIfInfo = pTmpSubnetInfo->pIfList;
if(!pTmpIfInfo)
{
goto cleanup;
}
memset(pTmpIfInfo,0,sizeof(IF_INFO));
//Fill in the new interface
pTmpIfInfo->dwIndex = pMib->table[i].dwIndex;
//Get the description
memset(&IfRow,0,sizeof(MIB_IFROW));
IfRow.dwIndex = pMib->table[i].dwIndex;
GetIfEntry(&IfRow);
strcpy(pTmpIfInfo->szDesc,(char*)IfRow.bDescr);
//Add any additional interfaces to the subnet
for(i=i+1; i < pMib->dwNumEntries; i++)
{
dwSubnet = pMib->table[i].dwAddr & pMib->table[i].dwMask;
if(pTmpSubnetInfo->dwSubnet != dwSubnet)
{
break;
}
//Increment the interface count for this subnet
pTmpSubnetInfo->dwIfCount++;
//Create a new interface
pTmpIfInfo->Next = (PIF_INFO) malloc(sizeof(IF_INFO));
pTmpIfInfo = pTmpIfInfo->Next;
if(!pTmpIfInfo)
{
goto cleanup;
}
memset(pTmpIfInfo,0,sizeof(IF_INFO));
//Fill in the new interface
pTmpIfInfo->dwIndex = pMib->table[i].dwIndex;
//Get the description
memset(&IfRow,0,sizeof(MIB_IFROW));
IfRow.dwIndex = pMib->table[i].dwIndex;
GetIfEntry(&IfRow);
strcpy(pTmpIfInfo->szDesc,(char*)IfRow.bDescr);
}
i=i-1;
}
FREE(pMib);
return TRUE;
cleanup:
FREE(pMib);
FreeSubnetList(ppSubnetList);
return FALSE;
}
void
DisplaySubnet(
IN SUBNET_INFO Info,
int idx
)
/*++
Routine Description:
Prints out the subnet info and the info for each interface in that subnet.
Arguments:
Info - This is the Subnet_info structure which you want to display,
it is a node in the list formed from GetSubnetList
Return Value:
--*/
{
unsigned int rightcol = 55;
unsigned int leftcol = 24;
unsigned int linewidth = rightcol+leftcol;
char *linebuff = (char*)malloc(linewidth+2); //width + /n + /0
if (linebuff == NULL)
{
return;
}
memset(linebuff,' ',linewidth);
struct in_addr inaddr;
inaddr.S_un.S_addr = Info.dwSubnet;
char szSubnet[16];
sprintf(szSubnet,"%d.%d.%d.%d", inaddr.S_un.S_un_b.s_b1,
inaddr.S_un.S_un_b.s_b2,
inaddr.S_un.S_un_b.s_b3,
inaddr.S_un.S_un_b.s_b4);
sprintf(linebuff,"%-5d%-16s%-3d",idx,szSubnet,Info.dwIfCount);
PIF_INFO pCurrInfo;
for(pCurrInfo=Info.pIfList;pCurrInfo!=NULL;pCurrInfo = pCurrInfo->Next)
{
char *currstr = pCurrInfo->szDesc;
if(strlen(currstr)>=(rightcol))
{
memcpy(&linebuff[leftcol],currstr,(rightcol));
currstr+=(rightcol);
linebuff[linewidth]='\n';
linebuff[linewidth+1]=0;
}
else if(strlen(currstr)>0)
{
sprintf(&linebuff[leftcol],"%s\n",currstr);
currstr+=strlen(currstr);
}
printf("%s",linebuff);
memset(linebuff,' ',leftcol);
while(strlen(currstr)>0)
{
if(strlen(currstr)>=rightcol)
{
memcpy(&linebuff[leftcol],currstr,rightcol);
currstr+=rightcol;
linebuff[linewidth]='\n';
linebuff[linewidth+1]=0;
}
else if(strlen(currstr)>0)
{
sprintf(&linebuff[leftcol],"%s\n",currstr);
currstr+=strlen(currstr);
}
printf("%s",linebuff);
}
printf("\n");
}
}
void
GetSubnetArray(
IN PSUBNET_INFO pHead,
OUT PULONG Subnets
)
/*++
Routine Description:
Fills the array in with the subnet values in the subnet list. The array
pointed to must be long enough to hold all the values. The length can be taken
from the output parameter in GetSubnetList
Arguments:
pHead - Pointer to the head of the list of subnets which are to be written to the
array.
Subnets - pointer to an array which is long enough to hold all the subnets.
Return Value:
--*/
{
int i;
for(i=0;pHead!=NULL;pHead=pHead->Next,i++)
{
Subnets[i] = pHead->dwSubnet;
}
}
void
SetSubnets (
IN BOOL bAdmit,
IN LPDWORD lpIndexArray,
IN DWORD dwIndexCount
)
/*++
Routine Description:
Writes the input subnets to the registry.
FORMAT:
DWORD DWORD DWORD DWORD DWORD
'4vPI' Flag Subnet Count Subnet 1 Subnet 2 ...
Flag = 1 for admit list
0 for deny list
Subnets stored in host byte order.
Arguments:
bAdmit - TRUE for admit list FALSE for block list.
plSubnets - Array of indexes provided by the user into our array of subnets.
Count - Number of indexes in the array
Return Value:
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
PSUBNET_INFO pHead;
DWORD dwInSubnetCount;
DWORD dwInSubnetIdx = 0;
LPDWORD pInSubnetArray = NULL;
DWORD dwOutSubnetCount= 0;
LPDWORD pOutSubnetArray = NULL;
//Get the IPv4 address table, in assending order of IP address
GetSubnetList(&pHead,&dwInSubnetCount);
if (pHead == NULL)
{
return;
}
pInSubnetArray = new DWORD[dwInSubnetCount];
if (pInSubnetArray == NULL)
{
FreeSubnetList(&pHead);
return;
}
// The number of subnets we write out won't be larger than the number of
// indicies the user specifies
pOutSubnetArray = new DWORD[dwIndexCount];
if (pOutSubnetArray == NULL)
{
delete pInSubnetArray;
FreeSubnetList(&pHead);
return;
}
GetSubnetArray(pHead, pInSubnetArray);
for (dwInSubnetIdx = 0; dwInSubnetIdx < dwInSubnetCount; dwInSubnetIdx++)
{
DWORD dwIndexArrayIdx;
for (dwIndexArrayIdx = 0; dwIndexArrayIdx < dwIndexCount; dwIndexArrayIdx++)
{
if (lpIndexArray[dwIndexArrayIdx] == (dwInSubnetIdx + 1))
{
pOutSubnetArray[dwOutSubnetCount++] = pInSubnetArray[dwInSubnetIdx];
}
}
}
FreeSubnetList(&pHead);
if (dwOutSubnetCount != 0)
{
//Write the settings
(void ) SetSelectiveBindingSubnets(dwOutSubnetCount, pOutSubnetArray, bAdmit);
}
delete pOutSubnetArray;
}
void
DisplaySubnetList(
IN PSUBNET_INFO pHead
)
/*++
Routine Description:
Walks the subnet list and prints out info on each node using DisplaySubnet
Arguments:
pHead - Pointer to the head of the subnet list which is to be displayed.
Return Value:
--*/
{
if(pHead == NULL)
{
return;
}
int i=1;
for(; pHead!=NULL; pHead=pHead->Next,i++)
{
DisplaySubnet(*pHead,i);
}
}
void
FilterSubnetListSubnets(
IN OUT PSUBNET_INFO *ppSubnetList,
IN ULONG *Subnets,
IN ULONG SubnetCount
)
/*++
Routine Description:
After this function returns, the Subnetlist only contains entries for subnets which
are in the input array. No new entries are added to the list, but any entry in the list
which does not match one of the input subnets is removed.
Arguments:
ppSubnetList - This value may change if the head node is not a matching subnet. It
may be NULL if none of the subnets in the list are matching.
Subnets - An array of subnet values which will be used to match up with entries in the subnet list
SubnetCount - Contains the number of subnets in the subnet array.
Return Value:
--*/
{
PSUBNET_INFO pCurr,pPrev,pTmp;
pCurr=*ppSubnetList;
pPrev=NULL;
while(pCurr!=NULL)
{
//Check each subnet to see if it matches anyone
//on the subnet list
ULONG i;
BOOL bMatches = FALSE;
for(i=0; i<SubnetCount; i++)
{
if(pCurr->dwSubnet == Subnets[i])
{
bMatches = TRUE;
break;
}
}
if(!bMatches)
{
//Doesnt match any of the subnets so remove it
pTmp = pCurr;
pCurr = pCurr->Next;
if(pPrev == NULL)
{
*ppSubnetList = pCurr;
}
else
{
pPrev->Next = pCurr;
}
pTmp->Next = NULL;
FreeSubnetList(&pTmp);
}
else
{
pPrev = pCurr;
pCurr = pCurr->Next;
}
}
}
void
FilterSubnetListIndices(
IN OUT PSUBNET_INFO *ppSubnetList,
IN DWORD *IndexTable,
IN DWORD IndexCount
)
/*++
Routine Description:
This function steps through each subnet and each interface within each subnet and
eliminates any interface whose index is not a memeber of the input index array. If
all the interfaces of a particular subnet entry are removed, than the subnet is also removed.
Arguments:
ppSubnetList - This value may change if the head node does not contain a valid interface. It
may be NULL if all of the interfaces are removed.
IndexTable - An array of device index values which will be used to match up with interface entries.
IndexCount - Contains the number of indices in the index table.
Return Value:
--*/
{
PSUBNET_INFO pCurr,pPrev,pTmp;
pCurr=*ppSubnetList;
pPrev=NULL;
while(pCurr!=NULL)
{
//Go through and check each interface in this subnet
//against each device index
PIF_INFO pIfCurr,pIfPrev,pIfTmp;
pIfCurr=pCurr->pIfList;
pIfPrev=NULL;
while(pIfCurr!=NULL)
{
ULONG i;
BOOL bMatches = FALSE;
for(i=0;i<IndexCount;i++)
{
if(pIfCurr->dwIndex==IndexTable[i])
{
bMatches = TRUE;
break;
}
}
if(!bMatches)
{
//Doesn't match anyone in the device list
//so remove it
pIfTmp = pIfCurr;
pIfCurr=pIfCurr->Next;
if(pIfPrev==NULL)
{
pCurr->pIfList = pIfCurr;
}
else
{
pIfPrev=pIfCurr;
pIfCurr=pIfCurr->Next;
}
free(pIfTmp);
pCurr->dwIfCount--;
}
else
{
pIfPrev = pIfCurr;
pIfCurr = pIfCurr->Next;
}
}
//If all the interfaces for this subnet were removed
//than remove the subnet
if(pCurr->dwIfCount==0)
{
pTmp = pCurr;
pCurr = pCurr->Next;
if(pPrev == NULL)
{
*ppSubnetList = pCurr;
}
else
{
pPrev->Next = pCurr;
}
free(pTmp);
}
else
{
pPrev = pCurr;
pCurr = pCurr->Next;
}
}
}
BOOL
ListInterfaces()
/*++
Routine Description:
This lists all the interfaces, grouped by subnet, on the machine.
Arguments:
Return Value:
--*/
{
PSUBNET_INFO pInfo;
DWORD dwTmp;
int count = 1;
GetSubnetList(&pInfo,&dwTmp);
if(!pInfo)
{
return FALSE;
}
printf(" Subnet Description\n");
DisplaySubnetList(pInfo);
FreeSubnetList(&pInfo);
return TRUE;
}
void ResetState (
)
{
DWORD Status;
HKEY hKey;
//
// Reset interface state to default
//
Status = DeleteSelectiveBinding();
if (Status != ERROR_SUCCESS)
{
if (Status == ERROR_ACCESS_DENIED)
{
printf("RPCCFG: Access denied to HKLM\\%s\n",RPC_SELECTIVE_BINDING_KEY_PATH);
}
else
{
printf("RPCCFG: Error occured while removing selective binding settings :[0x%x]\n",Status);
}
}
//
// Reset Port state to default
//
Status =
RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Rpc",
0,
KEY_ALL_ACCESS,
&hKey);
if ((Status != ERROR_SUCCESS) && (Status != ERROR_FILE_NOT_FOUND))
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
}
else
{
Status = RegDeleteKeyA(hKey, "Internet");
if (!((Status == ERROR_FILE_NOT_FOUND) || (Status == ERROR_SUCCESS)))
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
}
}
RegCloseKey(hKey);
}
BOOL
ListCurrentInterfaces(
)
/*++
Routine Description:
Lists all interfaces, grouped by subnet, which are currently being either
admited or denyed. This function bases the display on the registry settings
and will output the same wheither the registry entry is in the old or new format.
Arguments:
Return Value:
--*/
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwSize = 0;
DWORD dwDummy = 0;
LPVOID lpSettings = NULL;
PSUBNET_INFO pSubnetList = NULL;
BOOL bAdmit = TRUE;
SB_VER sbVer = SB_VER_UNKNOWN;
dwStatus = GetSelectiveBindingSettings(&sbVer, &dwSize, &lpSettings);
if (dwStatus != ERROR_SUCCESS)
{
printf("RPCCFG: Error occured while retrieving selective binding settings :[0x%x]\n",dwStatus);
return FALSE;
}
if (sbVer == SB_VER_DEFAULT)
{
printf("RPCCFG: Using default selective binding settings\n");
return TRUE;
}
if (sbVer == SB_VER_UNKNOWN)
{
printf("RPCCFG: Corrupt selective binding settings\n");
return FALSE;
}
if (!GetSubnetList(&pSubnetList,&dwDummy))
{
delete lpSettings;
printf("RPCCFG: Unexpected error, cannot list the selective binding settings \n");
return FALSE;
}
//Filter the subnets appropriatly based on the type of settings we have,
if (sbVer == SB_VER_SUBNETS)
{
VER_SUBNETS_SETTINGS *pSubnetSettings = (VER_SUBNETS_SETTINGS*)lpSettings;
FilterSubnetListSubnets(&pSubnetList, pSubnetSettings->dwSubnets, pSubnetSettings->dwCount);
bAdmit = pSubnetSettings->bAdmit;
}
else if (sbVer == SB_VER_INDICES)
{
VER_INDICES_SETTINGS *pIndexSettings = (VER_INDICES_SETTINGS*)lpSettings;
FilterSubnetListIndices(&pSubnetList, pIndexSettings->dwIndices, pIndexSettings->dwCount);
}
else
{
printf("RPCCFG: Error, selective binding settings are corrupt, use 'rpccfg -r' to reset them\n");
delete lpSettings;
return FALSE;
}
delete lpSettings;
printf("%s\n",(bAdmit?"Admit List":"Deny List"));
printf(" Subnet Description\n");
//Display the list
DisplaySubnetList(pSubnetList);
//Free the SubnetList
FreeSubnetList(&pSubnetList);
return TRUE;
}
char *
NextPortRange(
char **Ptr
)
{
char *Port = *Ptr ;
if (*Port == 0)
{
return 0;
}
while (**Ptr) (*Ptr)++ ;
(*Ptr)++ ;
return Port ;
}
void
ListCurrentPortSettings (
)
{
HKEY hKey;
DWORD Size ;
DWORD Type;
char *Buffer;
DWORD Status;
Status =
RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
RPC_PORT_SETTINGS,
0,
KEY_READ,
&hKey);
if (Status == ERROR_FILE_NOT_FOUND)
{
printf("RPCCFG: Using default port settings\n");
return;
}
if (Status != ERROR_SUCCESS)
{
return;
}
Size = 2048;
Buffer = (char *) malloc(Size) ;
if (Buffer == 0)
{
RegCloseKey(hKey);
return;
}
while(TRUE)
{
Status =
RegQueryValueExA(
hKey,
"Ports",
0,
&Type,
(unsigned char *) Buffer,
&Size);
if (Status == ERROR_SUCCESS)
{
break;
}
if (Status == ERROR_MORE_DATA)
{
free(Buffer) ;
Buffer = (char *) malloc(Size) ;
if (Buffer == 0)
{
RegCloseKey(hKey);
printf("RPCCFG: Could not perform operation, out of memory\n");
return;
}
continue;
}
if (Status == ERROR_FILE_NOT_FOUND)
{
free(Buffer) ;
printf("RPCCFG: Using default port settings\n");
RegCloseKey(hKey);
return;
}
printf("RPCCFG: Could not perform operation\n");
free(Buffer) ;
RegCloseKey(hKey);
return;
}
if (*Buffer == 0)
{
printf("RPCCFG: Bad settings\n");
RegCloseKey(hKey);
ResetState();
return;
}
char *PortRange;
char Flags[32];
Size = 32;
Status =
RegQueryValueExA(
hKey,
"PortsInternetAvailable",
0,
&Type,
(unsigned char *) Flags,
&Size);
if (Status != ERROR_SUCCESS)
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
RegCloseKey(hKey);
return;
}
printf("The following ports/port ranges will be used for ");
if (Flags[0] == 'Y')
{
printf("Internet ports\n");
}
else
{
printf("Intranet ports\n");
}
while ((PortRange = NextPortRange(&Buffer)) != 0)
{
printf("\t%s\n", PortRange);
}
Size = 32;
Status =
RegQueryValueExA(
hKey,
"UseInternetPorts",
0,
&Type,
(unsigned char *) Flags,
&Size);
printf("\nDefault port allocation is from ");
if ((Status != ERROR_SUCCESS) || (Flags[0] != 'Y'))
{
printf("Intranet ports\n");
}
else
{
printf("Internet ports\n");
}
RegCloseKey(hKey);
}
void
SetPortRange(
char **PortRangeTable,
int NumEntries,
char *InternetAvailable
)
{
int i;
DWORD Status;
DWORD disposition;
HKEY hKey;
Status =
RegCreateKeyExA(
HKEY_LOCAL_MACHINE,
RPC_PORT_SETTINGS,
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&disposition);
if (Status != ERROR_SUCCESS)
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
return;
}
int cbPorts = 0;
char *lpPorts = (char *) malloc(257*NumEntries+1);
if (lpPorts == 0)
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
return;
}
char *current = lpPorts;
for (i = 0; i < NumEntries; i++)
{
strcpy(current, PortRangeTable[i]);
int length = strlen(current)+1;
current += length;
cbPorts += length;
}
*current = 0;
cbPorts++;
Status = RegSetValueExA(hKey,
"Ports",
0,
REG_MULTI_SZ,
(unsigned char *) lpPorts,
cbPorts);
free(lpPorts);
if (Status != ERROR_SUCCESS)
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
return;
}
Status = RegSetValueExA(hKey,
"PortsInternetAvailable",
0,
REG_SZ,
(unsigned char *) InternetAvailable,
strlen(InternetAvailable)+1);
if (Status != ERROR_SUCCESS)
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
return;
}
}
void
SetDefaultPortSetting (
char *PortSetting
)
{
int i;
HKEY hKey;
DWORD Status;
DWORD disposition;
Status =
RegCreateKeyExA(
HKEY_LOCAL_MACHINE,
RPC_PORT_SETTINGS,
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&disposition);
if (Status != ERROR_SUCCESS)
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
return;
}
if (PortSetting[0] == '0')
{
PortSetting = "Y";
}
else
{
PortSetting = "N";
}
Status = RegSetValueExA(hKey,
"UseInternetPorts",
0,
REG_SZ,
(unsigned char *) PortSetting,
strlen(PortSetting)+1);
if (Status != ERROR_SUCCESS)
{
printf("RPCCFG: Could not perform operation (%d)\n", Status);
return;
}
RegCloseKey(hKey);
}
BOOL
IsNewVersion()
/*++
Routine Description:
Determines what version and service pack this os is.
Arguments:
Return Value:
True if Windows server or WinXP SP1 or greater
--*/
{
OSVERSIONINFOEX osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO*)&osvi);
if(
(osvi.dwMajorVersion > 5) ||
((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >=2))
)
{
// Check if it is Windows Server 2003 or a DC
if(osvi.wProductType > VER_NT_WORKSTATION){
return TRUE;
}
}
return FALSE;
}
VOID
GetDeviceIndiciesFromSubnetIndicies(
IN ULONG *alIndex,
IN ULONG count,
OUT ULONG **ppIndex,
OUT ULONG *pIndexCount)
/*++
Routine Description:
This maps subnet indicies (the ones that the user supplies to the -a and -b options)
to a set of device indicies which are the device indicies for each interface in one
of the subnets specified by the subnet indicies.
Arguments:
alIndex - The array of subnet indicies (user supplied indicies).
count - The number of user supplied indices in alIndex
ppIndex - This is the output parameter which points to the allocated array which contains
the device indices generated by this function.
pIndexCount - Output parameter which holds the count of device indices. May be greater than
or equal to the input parameter 'count'.
NOTE: This function is not currently called by anyone, Originally it was written to map
user indices to device indices so that we could maintain backwards compatibility with the
old version of rpcrt4.dll. Instead, we now block users from creating admit lists using this
version of rpccfg if they are on a pre Win XP SP1 or pre Windows 2003 system
--*/
{
PSUBNET_INFO pSubnetList = NULL;
ULONG SubnetCount = 0;
GetSubnetList(&pSubnetList,&SubnetCount);
//figure out how many device indices we have
*pIndexCount = 0;
PSUBNET_INFO pSubnet;
for(UINT i=0;i<count;i++)
{
//Get the subnet entry for this index
//GetSubnetEntry(alIndex[i],&pSubnet);
pSubnet = pSubnetList;
for(UINT j=0 ; j<SubnetCount ;j++)
{
if(j+1 == alIndex[i])
{
break;
}
else
{
pSubnet = pSubnet->Next;
}
}
if(pSubnet!=NULL)
{
*pIndexCount += pSubnet->dwIfCount;
}
}
//allocate space for the device indicies
*ppIndex = NULL;
if(*pIndexCount!=0)
{
*ppIndex = (ULONG*)malloc(sizeof(ULONG)*(*pIndexCount));
if (*ppIndex == NULL)
{
return;
}
}
//step through the input indicies (i)
UINT idx = 0;
for(i = 0; (i < count) && (idx < *pIndexCount); i++)
{
//Get the subnet entry for this index
//GetSubnetEntry(alIndex[i],&pSubnet);
pSubnet = pSubnetList;
for(UINT j=0 ; j<SubnetCount ;j++)
{
if(j+1 == alIndex[i])
{
break;
}
else
{
pSubnet = pSubnet->Next;
}
}
if(pSubnet!=NULL)
{
//step through each interface in this subnet
PIF_INFO pIf;
pIf = pSubnet->pIfList;
while(pIf!=NULL)
{
(*ppIndex)[idx++] = pIf->dwIndex;
pIf = pIf->Next;
}
}
}
FreeSubnetList(&pSubnetList);
}
void
Help (
)
{
printf("usage: RPCCFG [/l] [/a ifindex1 [ifindex2 ...]] [/r] [/q] [/d 0|1] \n");
printf(" [/pi port|port-range ...] [/pe port|port-range ...] \n");
printf("\t/?: This help message\n");
printf("\t/l: List all the subnets and associated interfaces\n");
printf("\t/q: List the subnet admit or deny list and our port usage settings\n");
printf("\t/r: Reset the interface and port settings to default\n");
printf("\t/a: Admit the listed subnets (eg: /a 1 3 5)\n");
printf("\t this will cause RPC servers to listen on the listed subnets\n");
printf("\t by default.\n");
printf("\t/b: Block the listed subnets (eg: /b 1 3 5)\n");
printf("\t this will cause RPC servers to listen on all but the listed subnets\n");
printf("\t by default.\n");
printf("\t/pi:Specify the intranet available ports, the ports may be single\n");
printf("\t values or ranges (eg: /pi 555 600-700 900), this option may not be\n");
printf("\t used with the /pe option\n");
printf("\t/pe:Specify the internet available ports, the ports may be single\n");
printf("\t values or ranges this option may not be used with the /pi option\n");
printf("\t/d: Specify the default port usage\n");
printf("\t 0: Use internet available ports by default\n");
printf("\t 1: Use intranet available ports by default\n");
printf("\n");
printf("\tRPC HTTP Proxy \"Valid Ports\" configuration commands\n");
printf("\n");
printf("\t/ha: Sets port ranges for a given server\n");
printf("\t Usage: /ha [machine-name] [port-range ...]\n");
printf("\t ex /ha server1 2000\n");
printf("\t ex /ha server1 2000-3000\n");
printf("\t ex /ha server1 2000-3000 3050 4000-4050\n");
printf("\n");
printf("\t/hr: Removes all port range settings for a given server\n");
printf("\t Usage: /hr [machine-name]\n");
printf("\t ex /hr server1\n");
printf("\n");
printf("\t/hd: Display current port range settings\n");
printf("\t Usage: /hd\n");
printf("\n");
printf("\t/hs: Stores the current settings to the specified file\n");
printf("\t Usage: /hs [filename]\n");
printf("\t ex /hs settings.txt\n");
printf("\n");
printf("\t/hl: Loads port range settings from a file\n");
printf("\t Usage: /hl [filename]\n");
printf("\t ex /hl settings.txt\n");
}
void
__cdecl main (int argc, char *argv[])
{
int argscan;
ULONG alIndex[512];
char *PortRangeTable[512];
int i;
BOOL fPortChanged = 0;
BOOL fInterfaceChanged = 0;
BOOL bAdmit = 0;
if (argc == 1)
{
Help();
}
for (argscan = 1; argscan < argc;argscan++)
{
if ((strcmp(argv[argscan], "-l") == 0) || (strcmp(argv[argscan], "/l") == 0))
{
ListInterfaces();
}
else if ((strcmp(argv[argscan], "-?") == 0) || (strcmp(argv[argscan], "/?") == 0))
{
Help();
}
else if ((strcmp(argv[argscan], "-r") == 0) || (strcmp(argv[argscan], "/r") == 0))
{
ResetState();
}
else if ((strcmp(argv[argscan], "-q") == 0) || (strcmp(argv[argscan], "/q") == 0))
{
ListCurrentInterfaces();
printf("\n");
ListCurrentPortSettings();
}
else if ( (strcmp(argv[argscan], "-a") == 0) || (strcmp(argv[argscan], "-b") == 0) ||
(strcmp(argv[argscan], "/a") == 0) || (strcmp(argv[argscan], "/b") == 0) )
{
int count = 0;
if((strcmp(argv[argscan], "-a") == 0) || (strcmp(argv[argscan], "/a") == 0))
{
bAdmit = TRUE;
} else {
bAdmit = FALSE;
}
for (i = 0; i < 512; i++)
{
argscan++;
if (argscan == argc)
{
break;
}
if (argv[argscan][0] == '-')
{
argscan--;
break;
}
count++;
alIndex[i] = atol(argv[argscan]);
if (alIndex[i] == 0)
{
printf("RPCCFG: Bad interface index\n");
return;
}
}
if (i == 512)
{
printf("RPCCFG: Too many interfaces\n");
return;
}
if (count)
{
if (bAdmit == TRUE)
{
//If it is an old version of the rpc runtime, then
//we will use the old method of writing the indices
if(IsNewVersion())
{
//It is a new version, so write the subnets out instead
SetSubnets(TRUE, alIndex, (USHORT)count);
fInterfaceChanged = 1;
}
else
{
// Need to map the indices entered by the user into a set of device indicies.
// ULONG *pIndex;
// ULONG IndexCount;
// GetDeviceIndiciesFromSubnetIndicies(alIndex,count,&pIndex,&IndexCount);
// ListenOnInterfaces(pIndex,IndexCount);
// if(pIndex!=NULL) free(pIndex);
// fInterfaceChanged = 1;
/* Need to put this in untill the bug in TCP_ServerListenEx is fixed*/
printf("This version of Windows does not support accept lists\n");
return;
}
}
else
{
if(IsNewVersion())
{
SetSubnets(FALSE, alIndex, (USHORT)count);
fInterfaceChanged = 1;
}
else
{
printf("This version of Windows does not support deny lists\n");
return;
}
}
}
}
else if ((strncmp(argv[argscan], "-p", 2) == 0) || (strncmp(argv[argscan], "/p", 2) == 0))
{
int count = 0;
char *option = argv[argscan];
for (i = 0; i < 512; i++)
{
argscan++;
if (argscan == argc)
{
break;
}
if (argv[argscan][0] == '-')
{
argscan--;
break;
}
count++;
//Make sure there aren't any comma delimiters
if(strchr(argv[argscan],',')!=NULL)
{
printf("Comma separators not permited\n");
return;
}
PortRangeTable[i] = argv[argscan];
}
if (i == 512)
{
printf("Too many ports\n");
return;
}
if ((strcmp(option, "-pi") == 0) || (strcmp(option, "/pi") == 0))
{
SetPortRange(PortRangeTable, count, "N");
}
else
{
SetPortRange(PortRangeTable, count, "Y");
}
fPortChanged = 1;
}
else if ((strcmp(argv[argscan], "-d") == 0) || (strcmp(argv[argscan], "/d") == 0))
{
argscan++;
if (argscan == argc)
{
break;
}
SetDefaultPortSetting(argv[argscan]);
fPortChanged = 1;
}
else if ((strncmp(argv[argscan], "-h", 2) == 0) || (strncmp(argv[argscan], "/h", 2) == 0))
{
if(strlen(argv[argscan]) !=3)
{
printf("Error: The command was not recognized, please enter rpccfg /? for a list of valid commands.\n");
return;
}
char *Command = argv[argscan];
LPSTR *Arguments;
Command+=2;
argscan++;
if (argscan == argc){
Arguments = NULL;
}
else{
Arguments = &(argv[argscan]);
}
DoHttpCommandA(*Command, Arguments, argc - argscan);
return;
}
}
if (fInterfaceChanged)
{
ListCurrentInterfaces();
printf("\n");
}
if (fPortChanged)
{
ListCurrentPortSettings();
}
}